[mod.sources] IEEE Calculator

sources-request@panda.UUCP (09/04/85)

Mod.sources:  Volume 3, Issue 4
Submitted by: decvax!decwrl!sun!dgh!dgh (David Hough)

#! /bin/sh
: make a directory, cd to it, and run this through sh
echo If this kit is complete, "End of Kit" will echo at the end
echo Extracting calc.p
cat >calc.p <<'End-Of-File'
program calculator (input, output) ;

(* File calc.p, Version 9 October 1984.  *)
        
        (* calc is a calculator style program to demonstrate the proposed
        IEEE floating point arithmetic *)

#include 'sane.h'
#include 'oldfplib.h'
#include 'calctest.h'
#include 'calcsingle.h'
#include 'calcdouble.h'
#include 'global.i'
#include 'forward.i'
#include 'init.i'
#include 'divrem.i'
#include 'extra.i'
#include 'storage.i'
#include 'addsubpas.i'
#include 'utility.i'
#include 'function.i'
#include 'hex.i'
#include 'base.i'

procedure store (* var x : internal *) ;

        (* Rounds x to current storage mode, setting exceptions accordingly,
        then puts result back in internal format.  *)
        
var 
yx : cextended ;
yd : cdouble ;
ys : csingle ;
yi : cint64 ;

begin
case storagemode of 
i16, i32,  i64 : tointeger( storagemode, x, yi ) ;
flt32 : tosingle ( x, ys ) ;
f64 : todouble ( x, yd ) ;
ext80 : toextended ( x, yx ) ;
otherwise
end ;
end ;

procedure commandloop ;
var
c : char ;
s : strng ;
i,j : integer ;
found, exit : boolean ;
ps : pstack ;
badnan, x, y, z, r  : internal ; 
                (* Rule is: x gets the top of stack, y the next,
                        for use in DOTEST *)
error : boolean ;
cc : conditioncode ;
oldtop : internal ; (* Saves previous top of stack, so we can tell when it
        changes.  New tops of stack are displayed.  *)
heap : ^ integer ; (* Heap marker.  *)
yx : cextended ;
yd : cdouble ;
yi : cint64 ;
xs, ys, zs  : csingle ;
tx : real ;
es : integer ;
fpe : xcpn ;
buffer : strng ; (* Used to buffer multiple commands.  *)
semipos : integer ; (* Used to record end of command. *)
fulldisplay : boolean ; (* Flag set at the end of a calculator operation;
                        if true, the top of stack will be displayed;
                        if false, only traps, if any, will be displayed.  *)

procedure clear ;

        (* Clears stack and heap.  *)
        
begin
stack := nil ;
end ;

procedure docommand ( var found : boolean ) ;

var fpe : xcpn ;

procedure subc ;

var i : integer ;

begin
if sequal(s , 'COMPARE') then begin
found := true ;
popstack(x) ;
popstack(y) ;
compare( y, x,  cc) ;
write(' Compare result: ') ;
case cc of
lesser : writeln(' < ') ;
equal : writeln(' = ' ) ;
greater : writeln(' > ') ;
notord : writeln(' Unordered ') ;
end ;
for i := 0 to 6 do yi[i] := 0 ;
yi[7] := ord(cc) ;
unpackinteger(yi,z,i16) ;
pushstack(z) ;
end else
if sequal(s , 'CLEAR') then  begin (* CLEAR *) found := true ; 
clear end
else if sequal(s , 'CRUNCH') then begin (* Clear stack except for top two entries.  *)
found := true ;
popstack(x) ;
popstack(y) ;
clear ;
pushstack(y) ;
pushstack(x) ;
end
 ;
end ;

procedure subd ;

begin
if sequal(s , 'DUP') then begin (* Duplicate top of stack *)
popstack(x) ;
pushstack(x) ;
pushstack(x) ;
found := true ;
end 
else if sequal(s , 'DIV') then begin
found := true ;
popstack(x) ;
popstack(y) ;
divrem( y, x,  z, r ) ;
writeln(' REM: ') ;
display(r) ;
pushstack(z) ;
end else if sequal(s,  'DUMP') then begin (* DUMP STACK *)
found := true ;
ps := stack ;
while ps <> nil do begin
display(ps^.x ) ;
ps := ps^.next ;
end ;
end ;
end ;

procedure subRR ;

begin
if sequal(s, 'REV') then begin (* reverse top two entries on stack *)
found := true ;
popstack(x) ;
popstack(y) ;
pushstack(x) ;
pushstack(y) ;
end 
else if sequal(s, 'REM') then begin
found := true ;
popstack(x) ;
popstack(y) ;
divrem( y, x, z, r ) ;
writeln(' DIV: ') ;
display(z) ;
pushstack(r) ;
end else if sequal(s, 'RN') then begin
found := true ;
fpstatus.mode.round := rnear ;
end
else if sequal(s, 'RM') then begin
found := true ;
fpstatus.mode.round := rneg ;
end
else if sequal(s, 'RP') then begin
found := true ;
fpstatus.mode.round := rpos ;
end
else if sequal(s, 'RZ') then begin
found := true ;
fpstatus.mode.round := rzero ;
end else if sequal(s, 'R24') then begin
found := true ;
fpstatus.mode.precision := sprec ; (* Round cextended to 24 significant bits.  *)
end else if sequal(s, 'R53') then begin
found := true ;
fpstatus.mode.precision := dprec ; 
        (* Round cextended to 53 significant bits.  *)
end end ;

procedure subS ;

begin
{
if sequal(s, 'SOFT') then begin
found := true ;
ffloat_ ; ffunc_ ;
end else if sequal(s, 'SKY') then begin
found := true ;
sfloat_ ; sfunc_ ;
end else }
if sequal(s, 'SCALE') then begin
found := true ;
popstack(x) ;
popstack(y) ;
cscale( y, x,  z ) ;
pushstack( z ) ;
end else if sequal(s, 'SQRT') then begin
found := true ;
popstack(x) ;
csqrt( x, z) ;
pushstack(z) ;
end else if sequal(s, 'STOF32') then begin (* Set storage mode.  *)
found := true ;
storagemode := flt32 ;
end
else if sequal(s, 'STOF64') then begin
found := true ;
storagemode := f64 ;
end
else if sequal(s, 'STOX80') then begin
found := true ;
storagemode := ext80 ;
end
else if sequal(s, 'STOI16') then begin
found := true ;
storagemode := i16 ;
end else if sequal(s, 'STOI32') then begin
found := true ;
storagemode := i32 ;
end else if sequal(s, 'STOI64') then begin
found := true ;
storagemode := i64
end 
end ;

procedure subT ;

var yi : cint64 ;

begin
if sequal(s, 'TOF32') then begin (* Convert to csingle.  *)
found := true ;
popstack(x);z:=x ;
tosingle( z, ys) ;
pushstack(z) ;
end else if sequal(s, 'TOF32I') then begin (* Convert to csingle integral.  *)
found := true ;
popstack(x);z:=x ;
roundint( z, fpstatus.mode.round, sprec ) ;
tosingle( z, ys) ;
pushstack(z) ;
end else if sequal(s, 'TOF64') then begin (* Convert to cdouble.  *)
found := true ;
popstack(x);z:=x ;
todouble( z, yd) ;
pushstack(z) ;
end else if sequal(s, 'TOF64I') then begin (* Convert to cdouble integral.  *)
found := true ;
popstack(x);z:=x ;
roundint( z, fpstatus.mode.round, dprec ) ;
todouble( z, yd) ;
pushstack(z) ;
end else  if sequal(s, 'TOX80' )then begin (* Convert to cextended.  *)
found := true ;
popstack(x);z:=x ;
toextended( z, yx) ;
pushstack(z) ;
end else if sequal(s, 'TOX80I') then begin (* Convert to cextended integral.  *)
found := true ;
popstack(x);z:=x ;
roundint( z, fpstatus.mode.round, xprec ) ;
toextended( z, yx) ;
pushstack(z) ;
end else if sequal(s, 'TOI16') then begin (* Convert to 16 bit integer.  *)
found := true ;
popstack(x);z:=x ;
tointeger( i16, z, yi) ;
pushstack(z) ;
end else if sequal(s, 'TOI32') then begin (* Convert to 32 bit integer.  *)
found := true ;
popstack(x);z:=x ;
tointeger( i32, z, yi) ;
pushstack(z) ;
end else if sequal(s, 'TOI64' )then begin (* Convert to 64 bit integer.  *)
found := true ;
popstack(x);z:=x ;
tointeger(i64, z, yi) ;
pushstack(z) ;
end 
else if sequal(s, 'TEST') then begin (* Toggle test flag *)
found := true ;
testflag := not testflag ;
end ;
end ;


begin
found := false ;
if length(s) > 0 then case s[1] of

'+' : if length(s)=1 then begin
found := true ;
popstack(x) ;popstack(y) ; 
add( y, x,  z ) ;
pushstack(z) ;
end ;

'-' : if length(s)=1 then begin
found := true ;
popstack(x) ;popstack(y) ; 
r := x ; r.sign := not x.sign ;
add( y, r, z ) ;
pushstack(z) ;
end ;

'*' : if length(s)=1 then begin
found := true ;
popstack(x) ; popstack(y) ;
multiply ( y, x,  z) ;
pushstack(z) ;
end ;

'/' : if length(s)=1 then begin
found := true ;
popstack(x) ;popstack(y) ; 
divide ( y, x,  z) ;
pushstack(z) ;
end ;
'A' : if sequal(s, 'ABS') then begin
found := true ;
popstack(x) ;
z := x ;
z.sign := false ;
pushstack(z) ;
end
else if sequal(s, 'AFF') then begin
found := true ;
fpstatus.mode.clos := affine ;
end ;

'C' : subc ;

'D' : subd ;

'E' : if length(s)=1 then begin
found := true ;
pushstack(e) ;
end else if sequal(s, 'EXIT') then begin (* EXIT *) found := true ; exit := true end ;

'L' : if sequal(s, 'LOGB') then begin
found := true ;
popstack(x) ;
clogb( x,  z ) ;
pushstack( z ) ;
end ;

'N' : if sequal(s, 'NEG') then begin (* NEGATE top of stack *)
found := true ;
popstack(x) ;
z := x ;
z.sign := not z.sign ;
pushstack(z) ;
end 
else if sequal(s, 'NORM') then begin
found := true ;
fpstatus.mode.norm := normalizing ;
end else if sequal(s, 'NEXT') then begin (* Compute NEXTAFTER function.  *)
found := true ;
popstack(x) ;
popstack(y) ;
cnextafter( y, x,  z ) ;
pushstack ( z ) ;
end ;

'P' : if sequal(s, 'POP') then begin
found := true ;
if stack <> nil then stack := stack^.next ;
end
else if sequal(s, 'PI') then begin
found := true ;
pushstack(pi) ;
end else if sequal(s, 'PROJ') then begin 
found := true ;
fpstatus.mode.clos := proj ;
end ;

'R' : subRr ;
'S' : subS ;
'T' : subT ;

'U' : if sequal(s, 'UNROUNDED') then begin
found := true ;
storagemode := unrounded ;
fpstatus.mode.precision := xprec ;
end ;

'W' : if sequal(s, 'WARN') then begin 
found := true ;
fpstatus.mode.norm := warning ;
end ;

otherwise
end ;

if found then writeln( ' Did ',s) ;

if (length(s)=2) and not found then begin (* Is is a trap enable toggle?  *)
for fpe := invop to inexact do 
if (s[1]=xcpnname[fpe,1]) and (s[2]=xcpnname[fpe,2]) then begin
found := true ; (* Command was name of exception so toggle that trap enable. *)
if fpe in fpstatus.trap then 
fpstatus.trap := fpstatus.trap - [fpe] (* If on, turn off.  *)
else
fpstatus.trap := fpstatus.trap + [fpe] ; (* If off, turn on.  *)
end ;
end ;

if not found then begin (* check for decimal input *)
decbin(s, x, error ) ;
fpstatus.curexcep := fpstatus.curexcep - [invop] ;
badnan.sign := x.sign ; (* Set up BadNaN to compare correctly with x.  *)
if (not error) and (not equalinternal(x,badnan))  then begin
found := true ;
pushstack(x) ;
end
end ;
if not found then begin (* check for  hex input *)
hexbin(s, x, error ) ;
fpstatus.curexcep := fpstatus.curexcep - [invop] ;
if not error then begin
found := true ;
pushstack(x) ;
end
end ;
if  found then begin
if stack <> nil then store(stack^.x) ;
fpstatus.excep := fpstatus.excep + fpstatus.curexcep ; (* Add in current
        exceptions.  *)
fulldisplay := stack <> nil ; 
if fulldisplay then
fulldisplay := (fpstatus.curexcep <> []) or 
(not equalinternal( stack^.x, oldtop )) ;
if fulldisplay then  begin
displaystatus ;
trapmessage ;
fpstatus.curexcep := [] ;
display(stack^.x) ;
end
else trapmessage 
end
else  writeln(' Command not recognized: ',s) ;

end ;


begin
clear ;
makenan(nanascnan,badnan) ; (* Create a Bad-NaN Nan for use later.  *)
repeat

exit := false ;
fpstatus.excep := [] ; 
        (* Reset exception flag register for new command strng.  *)
writeln(' Command: ') ;
i := 1 ;
while not eoln do
	begin
	read(c) ;
	buffer[i] := c ;
	i := i + 1 ;
	end ;
buffer[0] := chr(i-1) ;
readln ;
concatchar( buffer, ';' ) ;

while (not exit) and (length(buffer) > 1) do begin (* Get next command.  *)
semipos := pos(';', buffer) ; (* Find boundary of next command.  *)
copy( buffer, 1, semipos - 1,s ) ; (* Extract next command.  *)
delete ( buffer, 1, semipos ) ;  (* Remove next command from buffer.  *)
if stack <> nil then oldtop := stack^.x ; (* Save old top of stack.  *)
fpstatus.curexcep := [] ; (* Reset exception flags for new operation.  *)
j := 0 ;
for i := 1 to length(s) do if s[i] <> ' ' then begin (* suppress blanks
and lower case *)
j := j + 1 ;
s[j] := upcase(s[i]) ;
end ;
copy(s,1,j,s) ;
for i := ord(s[0])+1 to maxfpstring do s[i] := ' ' ;
docommand ( found ) ;
if  found and testflag then dotest ( s, found, x, y  ) ;
end ;
until exit ;
end ;

procedure execute ;
begin
writeln(' Begin IEEE Calculator version 2 September 1985 ') ;
initialize ;
commandloop ;
end ;

#include 'dotest.i'

begin (* Outer block.  *)
execute ;
end .


End-Of-File
echo Extracting calcf32.p
cat >calcf32.p <<'End-Of-File'

(* File calcf32.p, Version 9 October 1984.  *)

(* This version of the calculator test unit tests 32 bit single precision
IEEE arithmetic accessed by the "shortreal" type.  *)

#include 'sane.h'
#include 'oldfplib.h'
#include 'calctest.h'
#include 'calcsingle.h'

type bite = -128..+127 ;

function getbite ( b : bite ) : byt  ;
begin
if b >= 0 then getbite := b else getbite := b + 256 ;
end   ;

function setbite ( b : byt ) : bite   ;
begin
if b < 128 then setbite := b else setbite := b - 256 ;
end   ;

procedure swapexcep (* var e : excepset *) ;

var t : excepset ;

begin
e := [] ;
end ;

procedure swaptrap (* var e : excepset *) ;

var t : excepset ;

begin
e := [] ;
end ;

procedure swapmode (* var e : fpmodetype *) ;

var t : fpmodetype ;

begin
t.round := rnear ;
t.clos := affine ;
t.norm := normalizing ;
t.precision := xprec ;
e := t ;
end ;

procedure toreal ( s : csingle ; var r : shortreal ) ;
        (* kluge to call a csingle a shortreal *)
type
klugetype = record
        case boolean of
        false : ( sk : packed array[0..3] of -128..+127  ) ;
        true : ( rk : shortreal ) ;
        end ;
var
kluge : klugetype ;
i : 0..3 ;

begin
for i := 0 to 3 do kluge.sk[i] := setbite(s[i]) ;
r := kluge.rk ;
end ;

procedure fromreal ( r : shortreal ; var s : csingle ) ;
        (* kluge to call a shortreal a csingle  *)
type
klugetype = record
        case boolean of
        false : ( sk : packed array[0..3] of -128..+127  ) ;
        true : ( rk : shortreal ) ;
        end ;
var
kluge : klugetype ;
i : 0..3 ;

begin
kluge.rk := r  ;
for i := 0 to 3 do s[i] := getbite(kluge.sk[i]) ;
end ;

procedure pretest (* var storemode : arithtype *) ;
begin
storemode := flt32 ;
end ;


procedure tstore (* var z : internal *) ;
begin end ;

procedure tabs(* x : internal ; var z : internal *) ;
var
xs : csingle ; xr : shortreal ;
begin
tosingle(x,xs) ; toreal (xs,xr) ;
xr := abs(xr) ;
fromreal(xr,xs) ; unpacksingle(xs,z) ;
end ;

procedure tsqrt(* x : internal ; var z : internal *) ;
var
xs : csingle ; xr : shortreal ;
begin
tosingle(x,xs) ; toreal (xs,xr) ;
fromreal(sqrt(xr),xs) ; unpacksingle(xs,z) ;
end ;

procedure tneg(* x : internal ; var z : internal *) ;
var
xs : csingle ; xr : shortreal ;
begin
tosingle(x,xs) ; toreal (xs,xr) ;
xr := -xr ;
fromreal(xr,xs) ; unpacksingle(xs,z) ;
end ;


procedure tadd (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : csingle ;
xr,yr,zr : shortreal ;
begin
tosingle(x,xs) ; toreal(xs,xr) ; tosingle(y,ys) ; toreal(ys,yr) ;
zr := xr + yr ;
fromreal(zr,zs) ;
unpacksingle(zs,z) ;
end ;

procedure tsub (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : csingle ;
xr,yr,zr : shortreal ;
begin
tosingle(x,xs) ; toreal(xs,xr) ; tosingle(y,ys) ; toreal(ys,yr) ;
zr := xr - yr ;
fromreal(zr,zs) ;
unpacksingle(zs,z) ;
end ;

procedure tmul (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : csingle ;
xr,yr,zr : shortreal ;
begin
tosingle(x,xs) ; toreal(xs,xr) ; tosingle(y,ys) ; toreal(ys,yr) ;
zr := xr * yr ;
fromreal(zr,zs) ;
unpacksingle(zs,z) ;
end ;

procedure tdiv (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : csingle ;
xr,yr,zr : shortreal ;
begin
tosingle(x,xs) ; toreal(xs,xr) ; tosingle(y,ys) ; toreal(ys,yr) ;
zr := xr / yr ;
fromreal(zr,zs) ;
unpacksingle(zs,z) ;
end ;

procedure trem (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : csingle ;
xr,yr,zr : shortreal ;
begin
tosingle(x,xs) ; toreal(xs,xr) ; tosingle(y,ys) ; toreal(ys,yr) ;
fromreal(xr - yr * round(xr/yr),zs) ;
unpacksingle(zs,z) ;
end ;

procedure tcompare (* x, y : internal ; var cc : conditioncode *) ;
var
xs,ys,zs : csingle ;
xr,yr,zr : shortreal ;
begin
tosingle(x,xs) ; toreal(xs,xr) ; tosingle(y,ys) ; toreal(ys,yr) ;
write ( ' Tests affirm these predicates: ') ;
if xr=yr then write(' EQ ') ;
IF XR<>YR THEN write(' NE ') ;
IF XR<YR THEN write(' LT ') ;
IF XR<=YR THEN write(' LE ') ;
IF XR>YR THEN write(' GT ') ;
IF XR>=YR THEN write(' GE ') ;
writeln ;
IF xr=yr then cc := equal else
if xr>yr then cc := greater else
if xr<yr then cc := lesser else
cc := notord ;
end ;

procedure tconvert(* x : internal ; var z : internal ; a : arithtype *) ;
var yx : cextended ; yd : cdouble ; ys : csingle ; 
yi64 : cint64 ; yi16 : integer ;
xs : csingle ; xr : shortreal ; xl : longint ;
begin
If a=i32 then begin
tosingle(x,xs) ; toreal(xs,xr) ;
xl := round(xr) ;
yi16 := xl ;
writeln(' Intermediate i16 ',yi16) ;
xr := xl ;
fromreal(xr,xs) ; unpacksingle(xs,z) ;
end 
else begin
z := x ;
end
end ;

procedure tintconvert(* x : internal ; var z : internal ; a : arithtype *) ;
var yx : cextended ; yd : cdouble ; ys : csingle ; 
yi64 : cint64 ; yi16 : integer ;
xs : csingle ; xr : shortreal ; xl : longint ;
begin
If a=i32 then begin
tosingle(x,xs) ; toreal(xs,xr) ;
xl := trunc(xr) ;
yi16 := xl ;
writeln(' Intermediate i16 ',yi16) ;
xr := xl ;
fromreal(xr,xs) ; unpacksingle(xs,z) ;
end 
else begin
z := x ;
end
end ;

procedure tdisplay(* x : internal *) ;

var
xs : csingle ; xr : shortreal ;
s : fpstring ; i,j : integer ; error : boolean ;

begin
tosingle(x,xs) ; toreal(xs,xr) ;
{write  (' Free ') ;
for i := 1 to 4 do begin
f32_ascii(xr,5*i- 1,0,0,fp_free,s,error ) ;
for j := length(s)+1 to 5*i-1 do write(' ') ;
write(' ',s) ;
end ;
writeln ;
write  (' Lisa ') ;
for i := 1 to 4 do begin
f32_ascii(xr,5*i-1,0,0,fp_lisa,s,error ) ;
for j := length(s)+1 to 5*i-1 do write(' ') ;
write(' ',s) ;
end ;
writeln ;
}
writeln(' Efmt ',xr:5, xr:10, xr : 15, xr : 20 ) ;
writeln(' Ffmt ', xr : 5 : 0, xr : 10 : 5, xr : 15 : 7, xr : 20 : 10 ) ;
end ;

procedure tdecbin 
        (* s : fpstring ; var xout : internal  ; var error : boolean *) ;
(* converts decimal fpstring s to internal format *)
(* error is set true if bad format *)


var
r : shortreal ;
xs : csingle ;
next : integer ;
f : text ;
i : integer ;

begin
rewrite(f) ;
for i := 1 to ord(s[0]) do write(f,s[i]) ;
writeln(f) ;
reset(f) ;
readln(f,r) ;
fromreal(r,xs) ; unpacksingle(xs,x) ;
end ;
End-Of-File
echo Extracting calcf64.p
cat >calcf64.p <<'End-Of-File'

(* File calcf64.p, Version 8 October 1984.  *)

(* This version of the calculator test unit tests 64 bit double precision
IEEE arithmetic accessed by the "real" type.  *)

#include 'sane.h'
#include 'oldfplib.h'
#include 'calctest.h'
#include 'calcdouble.h'

type bite = -128..+127 ;

function getbite ( b : bite ) : byt  ;
begin
if b >= 0 then getbite := b else getbite := b + 256 ;
end   ;

function setbite ( b : byt ) : bite   ;
begin
if b < 128 then setbite := b else setbite := b - 256 ;
end   ;

procedure swapexcep (* var e : excepset *) ;

var t : excepset ;

begin
e := [] ;
end ;

procedure swaptrap (* var e : excepset *) ;

var t : excepset ;

begin
e := [] ;
end ;

procedure swapmode (* var e : fpmodetype *) ;

var t : fpmodetype ;

begin
t.round := rnear ;
t.clos := affine ;
t.norm := normalizing ;
t.precision := xprec ;
e := t ;
end ;

procedure toreal ( s : cdouble ; var r : real ) ;
        (* kluge to call a cdouble a real *)
type
klugetype = record
        case boolean of
        false : ( sk : packed array[0..7] of -128..+127  ) ;
        true : ( rk : real ) ;
        end ;
var
kluge : klugetype ;
i : 0..7 ;

begin
for i := 0 to 7 do kluge.sk[i] := setbite(s[i]) ;
r := kluge.rk ;
end ;

procedure fromreal ( r : real ; var s : cdouble ) ;
        (* kluge to call a real a cdouble  *)
type
klugetype = record
        case boolean of
        false : ( sk : packed array[0..7] of -128..+127  ) ;
        true : ( rk : real ) ;
        end ;
var
kluge : klugetype ;
i : 0..7 ;

begin
kluge.rk := r  ;
for i := 0 to 7 do s[i] := getbite(kluge.sk[i]) ;
end ;

procedure pretest (* var storemode : arithtype *) ;
begin
storemode := f64 ;
end ;


procedure tstore (* var z : internal *) ;
begin end ;

procedure tabs(* x : internal ; var z : internal *) ;
var
xs : cdouble ; xr : real ;
begin
todouble(x,xs) ; toreal (xs,xr) ;
xr := abs(xr) ;
fromreal(xr,xs) ; unpackdouble(xs,z) ;
end ;

procedure tsqrt(* x : internal ; var z : internal *) ;
var
xs : cdouble ; xr : real ;
begin
todouble(x,xs) ; toreal (xs,xr) ;
fromreal(sqrt(xr),xs) ; unpackdouble(xs,z) ;
end ;

procedure tneg(* x : internal ; var z : internal *) ;
var
xs : cdouble ; xr : real ;
begin
todouble(x,xs) ; toreal (xs,xr) ;
xr := -xr ;
fromreal(xr,xs) ; unpackdouble(xs,z) ;
end ;


procedure tadd (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : cdouble ;
xr,yr,zr : real ;
begin
todouble(x,xs) ; toreal(xs,xr) ; todouble(y,ys) ; toreal(ys,yr) ;
zr := xr + yr ;
fromreal(zr,zs) ;
unpackdouble(zs,z) ;
end ;

procedure tsub (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : cdouble ;
xr,yr,zr : real ;
begin
todouble(x,xs) ; toreal(xs,xr) ; todouble(y,ys) ; toreal(ys,yr) ;
zr := xr - yr ;
fromreal(zr,zs) ;
unpackdouble(zs,z) ;
end ;

procedure tmul (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : cdouble ;
xr,yr,zr : real ;
begin
todouble(x,xs) ; toreal(xs,xr) ; todouble(y,ys) ; toreal(ys,yr) ;
zr := xr * yr ;
fromreal(zr,zs) ;
unpackdouble(zs,z) ;
end ;

procedure tdiv (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : cdouble ;
xr,yr,zr : real ;
begin
todouble(x,xs) ; toreal(xs,xr) ; todouble(y,ys) ; toreal(ys,yr) ;
zr := xr / yr ;
fromreal(zr,zs) ;
unpackdouble(zs,z) ;
end ;

procedure trem (* x, y : internal ; var z : internal *) ; 
var
xs,ys,zs : cdouble ;
xr,yr,zr : real ;
begin
todouble(x,xs) ; toreal(xs,xr) ; todouble(y,ys) ; toreal(ys,yr) ;
fromreal(xr - yr * round(xr/yr),zs) ;
unpackdouble(zs,z) ;
end ;

procedure tcompare (* x, y : internal ; var cc : conditioncode *) ;
var
xs,ys,zs : cdouble ;
xr,yr,zr : real ;
begin
todouble(x,xs) ; toreal(xs,xr) ; todouble(y,ys) ; toreal(ys,yr) ;
write ( ' Tests affirm these predicates: ') ;
if xr=yr then write(' EQ ') ;
IF XR<>YR THEN write(' NE ') ;
IF XR<YR THEN write(' LT ') ;
IF XR<=YR THEN write(' LE ') ;
IF XR>YR THEN write(' GT ') ;
IF XR>=YR THEN write(' GE ') ;
writeln ;
IF xr=yr then cc := equal else
if xr>yr then cc := greater else
if xr<yr then cc := lesser else
cc := notord ;
end ;

procedure tconvert(* x : internal ; var z : internal ; a : arithtype *) ;
var yx : cextended ; yd : cdouble ; ys : csingle ; 
yi64 : cint64 ; yi16 : integer ;
xs : cdouble ; xr : real ; xl : longint ;
begin
If a=i32 then begin
todouble(x,xs) ; toreal(xs,xr) ;
xl := round(xr) ;
yi16 := xl ;
writeln(' Intermediate i16 ',yi16) ;
xr := xl ;
fromreal(xr,xs) ; unpackdouble(xs,z) ;
end 
else begin
z := x ;
end
end ;

procedure tintconvert(* x : internal ; var z : internal ; a : arithtype *) ;
var yx : cextended ; yd : cdouble ; ys : csingle ; 
yi64 : cint64 ; yi16 : integer ;
xs : cdouble ; xr : real ; xl : longint ;
begin
If a=i32 then begin
todouble(x,xs) ; toreal(xs,xr) ;
xl := trunc(xr) ;
yi16 := xl ;
writeln(' Intermediate i16 ',yi16) ;
xr := xl ;
fromreal(xr,xs) ; unpackdouble(xs,z) ;
end 
else begin
z := x ;
end
end ;

procedure tdisplay(* x : internal *) ;

var
xs : cdouble ; xr : real ;
s : fpstring ; i,j : integer ; error : boolean ;

begin
todouble(x,xs) ; toreal(xs,xr) ;
{write  (' Free ') ;
for i := 1 to 4 do begin
f32_ascii(xr,5*i- 1,0,0,fp_free,s,error ) ;
for j := length(s)+1 to 5*i-1 do write(' ') ;
write(' ',s) ;
end ;
writeln ;
write  (' Lisa ') ;
for i := 1 to 4 do begin
f32_ascii(xr,5*i-1,0,0,fp_lisa,s,error ) ;
for j := length(s)+1 to 5*i-1 do write(' ') ;
write(' ',s) ;
end ;
writeln ;
}
writeln(' Efmt ',xr:5, xr:10, xr : 15, xr : 20 ) ;
writeln(' Ffmt ', xr : 5 : 0, xr : 10 : 5, xr : 15 : 7, xr : 20 : 10 ) ;
end ;

procedure tdecbin 
        (* s : fpstring ; var xout : internal  ; var error : boolean *) ;
(* converts decimal fpstring s to internal format *)
(* error is set true if bad format *)


var
r : real ;
xs : cdouble ;
next : integer ;
f : text ;
i : integer ;

begin
rewrite(f) ;
for i := 1 to ord(s[0]) do write(f,s[i]) ;
writeln(f) ;
reset(f) ;
readln(f,r) ;
fromreal(r,xs) ; unpackdouble(xs,x) ;
end ;
End-Of-File
echo Extracting calctest.p
cat >calctest.p <<'End-Of-File'

(* File calctest.p, Version 5 October 1984. *)

#include 'sane.h'
#include 'oldfplib.h'
#include 'calctest.h'

procedure pretest (* var storemode : arithtype *)  ;
begin
end ;

procedure tstore (* var z : internal *) ;
begin
end ;

procedure tadd (* x, y : internal ; var z : internal *) ; 
begin 
end ;

procedure tsub (* x, y : internal ; var z : internal *) ; 
begin 
end ;

procedure tmul  (*  x, y : internal ; var z : internal  *) ;  
begin 
end ;

procedure tdiv  (*  x, y : internal ; var z : internal  *) ;  
begin 
end ;

procedure trem  (*  x, y : internal ; var z : internal  *) ;  
begin 
end ;

procedure tcompare  (*  x, y : internal ; var cc : conditioncode  *) ; 
begin 
end ;

procedure tconvert (*  x : internal ; var z : internal ; a : arithtype  *) ; 
begin
end ;

procedure tintconvert 
        (*  x : internal ; var z : internal ; a : arithtype  *) ; 
begin
end ;

procedure tabs (*  x : internal ; var z : internal  *) ; 
begin
end ;

procedure tsqrt (*  x : internal ; var z : internal  *) ; 
begin
end ;

procedure tneg (*  x : internal ; var z : internal  *) ; 
begin
end ;

procedure tdisplay (*  x : internal  *) ; 

begin
end ;

procedure tdecbin
  (*  s : fpstring ; var x : internal ; var error : boolean  *) ; 
begin
end ;

procedure swapexcep  (*  var e : excepset  *) ; 
begin
end ;

procedure swaptrap  (*  var e : excepset  *) ; 
begin
end ;

procedure swapmode  (*  var e : fpmodetype  *) ; 
begin
end ;
End-Of-File
echo ""
echo "End of Kit"
exit

sources-request@panda.UUCP (09/04/85)

Mod.sources:  Volume 3, Issue 5
Submitted by: decvax!decwrl!sun!dgh!dgh (David Hough)

#! /bin/sh
: make a directory, cd to it, and run this through sh
echo If this kit is complete, "End of Kit" will echo at the end
echo Extracting calcdouble.h
cat >calcdouble.h <<'End-Of-File'
procedure todouble ( var x : internal ; var y : cdouble ) ; external ;
procedure unpackdouble ( y : cdouble ; var x : internal ) ; external ;
 
End-Of-File
echo Extracting calcsingle.h
cat >calcsingle.h <<'End-Of-File'
procedure tosingle ( var x : internal ; var y : csingle ) ; external ;
procedure unpacksingle ( y : csingle ; var x : internal ) ; external ;
End-Of-File
echo Extracting calctest.h
cat >calctest.h <<'End-Of-File'

(* File calctest.h, Version 5 October 1984. *)

(* This version of the calculator test unit is a dummy to provide
constant and type declarations only.  *)

(* Global constant, type, and variable declarations for  Calc. *)

const
stickybit = 66 ; (* position of sticky bit in internal representation *)

type

arithtype = ( i16, i32, i64, flt32, f64, ext80, unrounded  ) ; 
        (* types of arithmetic operands *)

fpmodetype = record (* floating point mode record *)
round : rmode (* roundmodetype *) ;
precision : extprec ;
clos : closure(*type*) ;
norm : denorm ;
end ;

fpstype  = record (* complete status of floating point unit *)
mode : fpmodetype ;
curexcep : excepset ; (* Set of exceptions generated by current op.  *)
excep : excepset ;
trap : excepset end ;

internal = record (* internal extended format *)
(* unlike external extended, most significant bit represents 0.5,
not 1.0 *)
sign : boolean ;
exponent : integer ; (* range is -2**15 to 2**15-1 *)
significand :   array [0..stickybit] of boolean ; 
        (* bit stickybit-2 is guard ;
bit (stickybit-1) is round ; bit stickybit is sticky *)
end ;
        
        (* Following are temporary calculator internal types which use 
        logical bytes, which may not be the same as the physical bytes
        specified in x80modes.  *)
csingle = array [0..3] of byt ;
cdouble = array [0..7] of byt ;
cextended = array [0..9] of byt ;
cint64 = array [0..7] of byt ;

procedure pretest ( var storemode : arithtype )  ;  external ;
procedure swapmode ( var e : fpmodetype ) ;  external ;
procedure swaptrap ( var e : excepset ) ;  external ;
procedure swapexcep ( var e : excepset ) ;  external ;

procedure tneg ( x : internal ; var z : internal ) ;  external ;
procedure tabs ( x : internal ; var z : internal ) ;  external ;
procedure tsqrt ( x : internal ; var z : internal ) ;  external ;

procedure tadd ( x, y : internal ; var z : internal ) ;  external ;
procedure tsub ( x, y : internal ; var z : internal ) ;  external ;
procedure tmul ( x, y : internal ; var z : internal ) ;  external ;
procedure tdiv ( x, y : internal ; var z : internal ) ;  external ;
procedure trem ( x, y : internal ; var z : internal ) ;  external ;

procedure tcompare ( x, y : internal ; var cc : conditioncode ) ;  external ;
procedure tstore ( storagemode : arithtype ; var z : internal ) ;  external ;
procedure tconvert ( x : internal ; var z : internal ; a : arithtype ) ;  external ;

procedure tintconvert ( x : internal ; var z : internal ; a : arithtype ) ;  external ;

procedure tdisplay ( x : internal ) ;   external ;
procedure tdecbin ( s : fpstring ; var x : internal ; var error : boolean ) ;  external ;

procedure ffloat_ ; external ;
procedure ffunc_  ; external ;
procedure sfloat_ ; external ;
procedure sfunc_  ; external ;

End-Of-File
echo Extracting oldfplib.h
cat >oldfplib.h <<'End-Of-File'
	const

	maxfpstring = 80 ;

	invop = invalid;
	overfl = overflow;
	underfl = underflow;
	div0 = divbyzero;
	inxact = inexact;
	cvtovfl = invalid ;

	type

	byt = 0..255 ;

	fpstring = packed array [0..maxfpstring] of char ;

	roundtype = ( rnear, rzero, rpos, rneg, rout ) ;
	rmode = rnear .. rneg ;
	closure = (proj, affine) ;
	denorm = ( warning, normalizing ) ;
	extprec = ( xprec, sprec, dprec ) ;
	
	xcpn = exception ;
	excepset = set of exception ;

	fp_cc = ( equal, lesser, greater, notord ) ;
	conditioncode = fp_cc ;

End-Of-File
echo Extracting sane.h
cat >sane.h <<'End-Of-File'
type

longint = integer ;
integer = -32768..32767 ;
single = array [0..1] of integer ;
double = array [0..3] of integer ;
comp = array [0..3] of integer ;
extended = array [0..4] of integer ;

environ = integer ;
rounddir = ( tonearest, upward, downward, towardzero ) ;
relop = ( gt, lt, gl, eq, ge, le, gel, unord ) ;
exception = ( invalid, underflow, overflow, divbyzero, inexact ) ;
numclass = ( snan, qnan, infinite, zero, normal, denormal ) ;

roundprecision = ( extprecision, dblprecision, realprecision ) ;

procedure SetRnd ( r : rounddir ) ; external ;
function GetRnd : rounddir ; external ;
procedure SetXcp ( x : exception; onoff : boolean ); external ;
function TestXcp ( x : exception ) : boolean   ; external ;

End-Of-File
echo ""
echo "End of Kit"
exit

sources-request@panda.UUCP (09/04/85)

Mod.sources:  Volume 3, Issue 6
Submitted by: decvax!decwrl!sun!dgh!dgh (David Hough)

#! /bin/sh
: make a directory, cd to it, and run this through sh
echo If this kit is complete, "End of Kit" will echo at the end
echo Extracting base.i
cat >base.i <<'End-Of-File'
(* File base.i, Version 8 October 1984.  *)

procedure mpyten ( var x : internal ; n : integer  ) ;

        (* Multiplies x by 10**n, using table of powers of ten.  *)
        
var
n1, n2 : integer ;

begin
n1 := abs(n) div 32 ;
n2 := abs(n) mod 32 ;
if n1 < 32 then begin
if n > 0 then begin
if n2 > 0 then multiply( x, tensmall[n2], x ) ;
if n1 > 0 then multiply( x, tenbig[n1], x) ;
end
else if n < 0 then begin
if n2 > 0 then divide ( x, tensmall[n2], x ) ;
if n1 > 0 then divide ( x, tenbig[n1], x ) ;
end ;
end
else begin (* n is too big.  *)
if n > 0 then begin
makeinf(x) ;
setex ( overfl ) ;
end
else begin
makezero(x) ;
setex ( underfl ) ;
end ;
end ;
end ;


procedure xtodec ( x : internal ; r : roundtype ;
                var s : strng ) ;
                
                (* Converts abs(x) to an integral value, then that
                value is converted to a strng of ASCII digits.  *)
                

var
tf : excepset ;
acc : -20..+20  ; (* divide accumulator *)
i, j : integer ;
carry : boolean ;
nib : nibarray ;
last : integer ;

begin
roundint ( x, r, xprec ) ;
fpstatus.curexcep := fpstatus.curexcep - [inxact] ; 
        (* Don't care about inxact.  *)
if kind(x) = zerokind then makeucsdstring('0 ',s) else begin
s[0] := chr(0) ;
last := x.exponent - 1 ; (* Last is the last active bit of the accumulator.  *)

repeat (* Get one digit per cycle until there's nothing left.  *)

(* For each digit, do a NON RESTORING divide by TEN.  *)

acc := - 10 ;

for j := 0 to last do begin 
        (* Do one divide minicycle for each bit of dividend, plus one extra.  *)
acc := acc + acc ; (* Double remainder.  *)
if x.significand[j] then acc := acc + 1 ; (* Shift in next bit of dividend.  *)

if acc < 0 then begin (* Do add-ten cycle.  *)
acc := acc + 10 ;
end
else begin (* Do subtract-ten cycle.    *)
acc := acc - 10 ;
end ;
x.significand[j] := acc >= 0  ; (* Sign of this step determines quotient bit
                        and whether add or subtract next time.  *)
(* End around complement rotate for quotient bit.  *)
end (* Divide mini-cycle.  *) ;

if acc < 0  then begin 
        (* Remainder is negative so add 10.  *)
acc := acc + 10 ;
end ;

precatchar(' ',s) ;
s[1] := chr(ord('0') + acc ) ;

j := firstbit ( x, 0, last ) ;
if j <= last then 
        begin
        left(x, j) ;
        end ;
last := last - j ;
until last < 0 ;
        (* Keep doing divide cycles until the quotient is zero.  *)

end ;

end ;

procedure subdec (* x : internal ; p1, p2 : integer ; var s: strng *) ;
        (* s receives a strng of decimal digits representing the integer in
        x.significand[p1]..x.significand[p2], right justified.  *)
        
var
j, i : integer ;
nib : nibarray ;

begin

if p2 = stickybit then begin (* Avoid trying to donormalize sticky bit.  *)
for i := p1 to p2 do
x.significand[i-1] := x.significand[i] ;
p1 := p1 - 1 ;
p2 := p2 - 1 ;
end ;

for i := 0 to (p1-1) do 
x.significand[i] := false ; (* Clear bits outside field.  *)
for i := (p2+1) to stickybit do
x.significand[i] := false ;

x.exponent := p2 + 1 ;
donormalize(x) ;
xtodec( x, rnear, s) ;
end ;


procedure findbinten ( x : internal ; n : integer ;
                var s : strng ; var p : integer  ) ;
                
        (* Converts x into s and p, s a strng of exactly n significant
        digits, so
                x .=. s * 10^p *)

var
e1, e2, dp : integer ;
tf : excepset ;
t : internal ;
cc : conditioncode ;
i : integer ;
norm : boolean ;
et, dt : integer ;
fraction : integer ;
spill : boolean ;

begin
        (* First ESTIMATE p.
                We want a p such that
                10^(n-1) <= int(abs(x)*10^p) < 10^n
                
                For a first guess, use
                n - log10( 2**e * 1+f ) 
                which we approximate by
                n - ((77+(1/16))/256) * (e + f )
                
                
                e is broken into two pieces to get benefit of 
                22 bit product.  *)
                
norm := x.significand[0] ; (* If x is not normalized then we don't force
        n significant digits in E format.  *)
e2 := (x.exponent-1) div 256 ; (* e = e1 + 256*e2 *)
e1 := (x.exponent-1) - 256 * e2 ;
fraction := xbyte(x,1,8) ;
e1 := 77 * e1 + 16 * e2 ; (* First order contribution from e1 and second
        order from e2. *)
if norm then e1 := e1 + ( 77 * fraction ) div 256 ;
        (* If normalized add in a contribution for the fraction.
        If not normalized, assume significand of 1.00000...  *)
et := e1 div 256 ; dt := e1 - et * 256 ;
        (* We are never sure how Pascal div and mod work on negative
        numbers.  *)
if dt > 0  then et := et + 1 ;
        (* but we try to get et as close as possible anyway to
        the ceiling of e1/256.  *)
e2 := 77 * e2 ;
p := n  - (et + e2) ;

        (* Now remedy flaws in approximation by altering p as necessary.  *)

tf := fpstatus.curexcep  ; (* Save exceptions.  *)
dp := 0 ; (* Assume no correction required.  *)
repeat
fpstatus.curexcep  := tf ; 
(* Restore exception status.  Don't want inexact flag set
                for inappropriate p.  *)
p := p + dp ; (* Correct p.  *)
dp := 0 ; (* Assume no correction required.  *)
t := x ;
mpyten(t, p) ; (* Multiply t by appropriate power.  *)
roundint( t, fpstatus.mode.round, xprec ) ;

t.sign := false ; (* Use absolute values for comparison.  *)
compare ( t, tensmall[n], cc ) ;  (* t must not exceed n sig digits.  *)
case cc of
otherwise ;
greater : dp := -1 ; (* If too big, correct and repeat.  *)
equal : begin
        if norm or (n=1) then begin (* We want only n digits.  *)
        p := p - 1 ; (* If almost, avoid full repeat of process.  *)
        t := tensmall[n-1] ;
        end 
        else begin (* If not normalized we want n-1 digits.  *)
        p := p - 2 ;
        t := tensmall[n-2] ;
        end ;
        end ;
lesser : begin
        compare(t,tensmall[n-1],cc) ;
         if norm then begin (* If normalized, insure enough sig digits. *)
        if cc = lesser then dp :=  + 1 ; (* If not enough digits, correct *)
        end  (* Need exactly n digits.  *)
        else begin (* If unnormalized, want no more than n-1 digits.  *)
        if cc <> lesser then dp := -1 ; (* Try again for less than n.  *)
        end ;
        end ;
end ;
t.sign := x.sign ;
{
if dp <> 0 then writeln(' Power of ten correction: ',dp) ;
}
spill := ([underfl, overfl] * fpstatus.curexcep ) <> [] ;
until (dp = 0) or (kind(t)=zerokind) or spill ;
        (* Repeat until no correction necessary or over/underfl occurs.  *)
        (* or the number rounds to normalized zero.  *)
if spill then
        begin
        (* String of asterisks if overfl.  *)
        s[0] := chr(0) ;
        while length(s) < n do concatchar(s,'*') ;
        end 
else 
        begin
        xtodec(*2*) ( t, fpstatus.mode.round, s(*, n*) ) ; (* Get strng.  *)
        end ;
while length(s) < n do precatchar( '0', s ) ;
        (* Add unnormalizing digits.  *)
p := - p ;
end ;

procedure decint ( s : strng ; var x : internal ; var e : integer ) ;

        (* DECINT converts a strng s of decimal digits into x and e
        such that
                s = x * 10^e
        If s >= 2^(leastsigbit+1) then the sticky bit may be set. *)

const
last = 69 ; (* last bit of decint accumulator *)
var
i,j : integer ;
acc : array[0..last] of boolean ; (* Accumulator long enough to hold 20
        significant digits and a sticky bit *)
carry, zero : boolean ;
n : nibarray ;

procedure tenmult ; (* multiplies acc by 10 *)
var
i : integer ;
carry : boolean ;

begin
for i := 0 to (last-3) do acc[i] := acc[i+3] ; (* multiply acc by 8 *)
for i := (last-2) to last do acc[i] := false ;
carry := false ;
for i := (last-1) downto 2 do
adder( acc[i], acc[i-2], acc[i], carry) ;
for i := 1 downto 0 do
adder( acc[i], false, acc[i], carry) ;
end ;

begin (* decint *)
for i := 0 to last do acc[i] := false ;
e := 0 ;
zero := true ;
for j := 1 to length(s) do begin
if s[j] = '0' then begin
if not zero then e := e + 1 ;
end 
else begin
if not zero then begin
e := e + 1 ;
while (e>0) and (not acc[0]) and (not acc[1]) and (not acc[2]) and 
(not acc[3]) do begin (* multiply by ten *)
tenmult ;
e := e - 1 ;
end ;
end ;
zero := false ;
if e > 0 then acc[last] := true (* set sticky bit on *)
else begin (* add digit *)
hexnibble( s[j], n) ;
carry := false ;
for i := (last-1) downto (last-4) do
adder( acc[i], n[i+4-last], acc[i], carry) ;
for i := (last-5) downto 0 do
adder( acc[i], false, acc[i], carry) ;
end ;
end ;
end ;

if zero then makezero(x) else begin
        (* Now acc[0..(last-1)] represents an integer value,
        acc[last] a sticky bit, to be multiplied by 10^e *)
        
        i := 0 ;
        while ( i < last ) and not acc[i] do i := i + 1 ;
                (* search for first nonzero bit *)
        x.exponent := last - i ; (* Set exponent of result *)
        for j := 0 to (last-i-1) do acc[j] := acc[j+i] ;
                (* normalize *)
        for j := (last-i) to (last-1) do acc[j] := false  ; 
        for i := 0 to (stickybit-1) do x.significand[i] := acc[i] ;
        x.significand[stickybit] := acc[last] ;
        for i := stickybit to (last-1) do
        x.significand[stickybit] := x.significand[stickybit] or acc[i] ;
        end ;
end ;

procedure putdec (* s : strng ; p1, p2 : integer ; 
                var x : internal ; var error : boolean *) ;
                
                (* Interprets s as a decimal integer, puts value in bits
                p1..p2 of x.significand.
                Sets Error if any significant bits don't fit in field.  *)

var
i, j : integer ;
y : internal ;
e : integer ;
f : excepset ;

begin
decint( s, y, e ) ;
f := fpstatus.curexcep ;
mpyten ( y, e ) ;
fpstatus.curexcep := f ; (* Ignore exceptions that may arise.  *)
e := y.exponent ;
error := (e > (leastsigbit+1)) ;
        (* Bad news if s too big to fit in 64 bits.  *)
if not error then begin
if kind(y) = zerokind then begin
for i := p1 to p2 do
x.significand[i] := false ; (* Set up zero field.  *)
end
else begin
if (p2-p1+1) >= e then begin (* y fits in field.  *)
for i := p2 downto (p2+1-e) do
x.significand[i] := y.significand[i+e-1-p2] ;
for i := (p2-e) downto p1 do
x.significand[i] := false ;
end
else begin
for i := p2 downto p1 do
x.significand[i] := y.significand[i+e-1-p2] ;
for i := (p1-p2+e-2) downto 0 do
error := error or y.significand[i] ; (* Check for lost significant bits.  *)
end end end
end ;

procedure todecint ( x : internal ; var s : strng ) ;

(* if x is an integer less than 2**15,
then s receives the decimal digits representing x.
Otherwise s is set to empty. *)

var
i, k : integer ;

begin
s[0] := chr(0) ;
if kind(x) = zerokind then makeucsdstring('0 ',s) else
if (abs(kind(x)) = normkind) and (x.exponent <= 15) and (x.exponent >= 1)
then begin
if zerofield ( x, x.exponent, stickybit ) then begin (* it's all integer *)
k := 0 ;
for i := 0 to (x.exponent-1) do begin (* Accumulate k.  *)
k := k + k ;
if x.significand[i] then k := k + 1 ;
end ;
while k > 0 do begin
precatchar( chr(ord('0') + (k mod 10)), s) ;
k := k div 10 ;
end ;
if x.sign then precatchar( '-', s )  ;
end end
end ;

procedure bindec (* x : internal ; var s  : strng *)  ;
(* converts x to decimal format *)

var
e, i, j, k : integer ;
nib : nibarray ;
t : strng ;
tf : excepset ;
ns : integer ;

begin
case abs(kind(x)) of
zerokind : if x.sign 
	then makeucsdstring('-0',s) else  makeucsdstring('0 ',s) ;

unnormkind, normkind : begin
todecint ( x, s ) ;
if length(s) < 1 then begin (* Can't represent as integer; too bad.  *)
ns := 19 ;
case storagemode of (* Set number of significant digits output.  *)
flt32 : ns := 9 ;
f64 : ns := 17 ;
otherwise ;
end ;
findbinten( x, ns, s, e ) ;
tf := fpstatus.curexcep ;
fpstatus.curexcep := [] ;
if not (overfl in tf) then begin
if e <> 0 then begin (* x not an integer so write it in E format.  *)
e := e + ns-1 ;
for i := length(s) downto 2 do s[i+1] := s[i] ;
s[2] := '.' ;
s[0] := chr(length(s)+1) ;
if e <> 0 then begin
concatchar(s, 'E') ;
if e > 0 then concatchar(s, '+') ;
intdec(e, t) ;
s := concat(s,t) ;
end ;
end ;
end ;
if x.sign then precatchar('-',s) ;
end ;
end ;

infkind, nankind : nanascii ( x, false, s ) ;

otherwise
end ;
end ;



procedure decbin (* s : strng ; var x : internal ; var error : boolean *) ;
(* converts decimal strng s to internal format *)
(* error is set true if bad format *)

type
stringclass = (nonnumeric, truezero, nonzero) ; (* types of strng *)

var
class : stringclass ;
i, k,  min : integer ;
e1, e2 : integer ;
sub : strng ;
t : strng ;
esign : boolean ;
nib : nibarray ;
ee, ie : integer ;


procedure checkadd ( x, y : integer ; var z : integer ; var error : boolean ) ;
        (* Computes z := x + y except if z overflows error is set to true
                and z is set to maxexp-1 or minexp+1 *)
begin
error := false ;
z := x + y ;
if (x>0) and (y>0) and (z<=0) then begin
z := maxexp - 1 ;
error := true ;
end
else if (x<0) and (y<0) and (z>=0) then begin
z := minexp + 1 ;
error := true ;
end ;
end ;

procedure bump ; (* removes first character from strng t *)
begin
delete (t,1,1) 
end ;


begin
class := nonnumeric ;
error := false ;
esign := false ;
x.sign := false ;
x.exponent := 0 ;
ee := 0 ; ie := 0 ;
for i := 0 to stickybit do x.significand[i] := false ;
sub[0] := chr(0) ; (* substring for accumulating significant digits *)
t[0] := chr(0) ;
for i := 1 to length(s) do if s[i] <> ' ' then concatchar(t,upcase(s[i])) ;
concatchar(t,'!') ; (* this marks the end of the input strng *)

if t[1] = '+' then bump else if t[1] = '-' then begin (* handle negative *)
x.sign := true ;
bump
end ;
while t[1] = '0' do begin
class := truezero ;
bump ; (* delete leading zeros *)
end ;
while t[1] in digitset do begin (* digits before point *)
class := nonzero ;
concatchar(sub, t[1]) ;
bump
end ;
if t[1] = '.' then begin (* check for point *)
bump ;
while t[1] in digitset do begin (* process digits after point *)
if (t[1] <> '0') or (class = nonzero) then class := nonzero 
else class := truezero ;
concatchar( sub, t[1]) ;
ie := ie - 1 ;
bump ; 
end ;  
end ;
ee := 0 ;
if t[1] = 'E' then bump ; (* handle E for exponent *)
if t[1] = '+' then bump else if t[1]='-' then begin (* exponent sign *)
esign := true ;
bump
end ;
while t[1] in digitset do begin (* exponent digits *)
if ee > ((maxexp - (ord(t[1])-ord('0'))) div 10 ) then begin
error := true ;
ee := maxexp - 1 ;
end else
begin
ee := 10 * ee + ord(t[1]) - ord('0') ;
end ;  bump  end ;
if class = truezero then x.exponent := minexp  else begin
if esign then ee := -ee ;
checkadd(ee,ie,ee,error) ; (* ee := ee + ie *)
if not error then begin 
                (* Minimize ee if possible by adding zeros to sub *)
ie := 19 - length(sub) ; (* Maximum number of zeros to add.  *)
if (ee>0) and (ie>0) then begin (* Go ahead and add.  *)
if ee < ie then ie := ee ; (* Only add enough to reduce ee to 0.  *)
ee := ee - ie ;
for i := 1 to ie do concatchar( sub, '0') ;
end ;
decint ( sub, x, ie ) ; (* Convert substring to x and ie *)
checkadd( ee, ie, ee, error ) ; (* Add in ie to exponent.  *)
end ;
if not error then 
mpyten ( x, ee ) ; (* Adjust x by appropriate power of ten.  *)
end ;
if class = nonnumeric  then 
        (* the following code checks for INFs and NANs *)
begin
NANer ( s, false, x, error ) 
end 
else
if length(t) > 1 then error := true ;
if error  then 
        begin
        makenan(nanascbin,x) ;
        end ;
end ;

procedure display (* x : internal *) ;
(* displays x in decimal and binary *)

begin
write(' Hex: ') ; displayhex(x) ;
write(' Dec: ') ; displaydec(x) ;
end ;
End-Of-File
echo Extracting utility.i
cat >utility.i <<'End-Of-File'
(* File utility.i, Version 8 October 1984. *)

function length ( var x : strng ) : integer ;

begin (* concat *)
length := ord(x[0]) ;
end   (* concat *) ;

procedure displayhex ( x : internal ) ;

var s : strng ;
i : integer ;

begin
binhex(x,s) ;
for i := 1 to length(s) do write(s[i]) ;
writeln ;
end ;

procedure displaydec ( x : internal ) ;

var s : strng ;
i : integer ;

begin
bindec(x,s) ;
for i := 1 to length(s) do write(s[i]) ;
writeln ;
end ;

procedure concatchar ( var s : strng ; c : char ) ;
(* concatenates the character c onto the end of s *)
var
ls : integer ;
begin
ls := ord(s[0]) + 1 ;
s[ls] := c ;
s[0] := chr(ls) ;
end ;

function upcase ( c : char ) : char ;
begin
if ('a' <= c) and (c <= 'z') then upcase := chr(ord(c)-32) else upcase := c
end  ;

function stackspace : integer ;

        (* Computes number of stack entries left.
        As this number approaches zero, operation becomes dangerous.  *)

var space : integer ;

begin
stackspace := 10000 ;
end ;

procedure hexnibble ( h : char ; var n : nibarray ) ;
(* Converts ASCII hexit h into a nibarray *)
var
i, w : integer ;
begin
if h in digitset then w := ord(h)-ord('0') else w := ord(h) - ord('A') + 10 ;
for i := 3 downto 0 do begin
n[i] := odd(w) ;
w := w div 2 ;
end ;
end ;

function nibblehex (* n : nibarray ) : char *)  ;
(* converts a nibarray into a hexit ASCII character *)
var
i, w : integer ;
c : char ;

begin
w := 0 ;
for i := 0 to 3 do begin
w := w + w ;
if n[i] then w := w + 1 ;
end ;
if w < 10 then c := chr(ord('0') + w) else c := chr(ord('A') + w - 10 ) ;
nibblehex := c ;
end ;

procedure displayexcep ( es : excepset ) ;
        (* Displays exception names that are enabled.  *)
var i : xcpn ;
begin
for i := invop to inexact do
if i in es then write(' ',xcpnname[i],' ') ;
end ;

procedure displaystatus ;
        (* Displays current mode, trap, exception flags.  *)

begin
write(' Modes: ') ;
case fpstatus.mode.round of
rneg : write(' RM ') ;
rpos : write(' RP ') ;
rzero : write(' RZ ') ;
otherwise
end ;
case fpstatus.mode.precision of
sprec: write(' R24 ') ;
dprec: write(' R53 ') ;
otherwise
end ;
if fpstatus.mode.clos = proj then write(' PROJ ') ;
if fpstatus.mode.norm = warning then write(' WARN ') ;
case storagemode of
i16 : write(' I16 ') ;
i32 : write(' I32 ') ;
i64 : write(' I64 ') ;
flt32 : write(' F32 ') ;
f64 : write(' F64 ') ;
ext80 : write(' X80 ') ;
otherwise
end ;
writeln ;
if fpstatus.trap <> [] then begin (* Write out trap line.  *)
write(' Traps: ') ;
displayexcep( fpstatus.trap ) ;
writeln ;
end ;
if fpstatus.excep <> [] then begin (* Write out exceptions.  *)
write(' Exceptions: ') ;
displayexcep( fpstatus.excep ) ;
writeln ;
end ;
end ;

procedure trapmessage ;

        (* Announces name of trap that would occur now.  *)
        
var
tset : excepset ;
f : xcpn ;

begin
tset := fpstatus.trap * fpstatus.curexcep ;
if tset <> [] then begin
f := invop ; (* Start with highest priority exception.  *)
while (f <> cvtovfl) and not (f in tset) do f := succ(f) ;
if f in tset then writeln( xcpnname[f],' TRAP occurs.  ') ;
end ;
end ;

procedure setex (* e : xcpn *) ;
        (* Turns on exception flag in curexcep.  *)
begin
fpstatus.curexcep := fpstatus.curexcep  + [e] ;
end ;

function zerofield (* x : internal ; p1, p2 : integer ) : boolean *) ;

        (* Returns true if x.significand[p1..p2] is all zeros.  *)
        
var i : integer ;

begin
i := p1 ;
while ( i < p2 ) and not x.significand[i] do i := i + 1 ;
zerofield := ( i >= p2 ) and not x.significand[p2]  ;
        (* Can't test bit p2 in main loop ; would cause range error if
        p2 were stickybit, on subsequent test.  *)
end ;

function firstbit (* x : internal ; p1, p2 : integer ) : integer *)  ;

        (* Returns index of leftmost onebit in field
        x.significand[p1..p2].
        If field is zero, returns p2+1.  *)
        
var i : integer ;

begin
i := p1 ;
while ( i < p2 ) and not x.significand[i] do i := i + 1 ;
if ( i >= p2 ) and not x.significand[p2] then i := p2+1   ;
        (* Can't test bit p2 in main loop ; would cause range error if
        p2 were stickybit, on subsequent test.  *)
firstbit := i ;
end ;

function lastbit (* x : internal ; p1, p2 : integer ) : integer *)  ;

        (* Returns index of rightmost nonzero bit in field
        x.significand[p1..p2].
        If field is zero, returns p1-1.  *)
        
var i : integer ;

begin
i := p2 ;
while ( i > p1 ) and not x.significand[i] do i := i - 1 ;
if ( i <= p1 ) and not x.significand[p1] then i := p1 - 1  ;
        (* Can't test bit p1 in main loop ; would cause range error if
        p1 were zero, on subsequent test.  *)
lastbit := i ;
end ;

function kind (* x : internal ) : integer *)  ;
(* returns kind(x) but all NANs have kind=4 in order to fit int16 *)
var
i, tkind : integer ;
begin
if x.exponent = maxexp then begin (* inf or nan *)
if zerofield ( x, 1, stickybit )  then tkind := ord(infkind) 
else tkind := ord(nankind) ;
end
else 
if (x.exponent <= minexp) and zerofield(x, 0, stickybit)
then tkind := ord(zerokind)
else if x.significand[0] = true then tkind := ord(normkind)
else tkind := ord(unnormkind) ;
if x.sign then tkind := -tkind ;
kind := tkind ;
end ;

procedure makezero (* var x : internal *) ;

        (* makes x into a zero.  Does not change sign of x *)

var i : integer ;

begin
x.exponent := minexp ;
for i := 0 to stickybit do x.significand[i] := false ;
end ;


procedure makeinf (* var x : internal *) ;

        (* makes x into a infinity.  Does not change sign of x *)

var i : integer ;

begin
x.exponent := maxexp ;
for i := 0 to stickybit do x.significand[i] := false ;
end ;

procedure makenan (* n : integer ; var x : internal  *) ;

        (* makes x a NAN and inserts n in its more significant field.
        Sets NV Operand flag in curexcep. *)

var
i : integer ;

begin
x.exponent := maxexp ;
for i := 0 to stickybit do x.significand[i] := false ;
i := 15 ;
while n <> 0 do begin
x.significand[i] := odd(n) ;
n := n div 2 ;
i := i - 1 ;
end ;
setex( invop ) ;
end ;

function unzero (* x : internal ) : boolean *)  ;

        (* returns TRUE if x is an unnormalized zero,
        FALSE otherwise *)


begin
unzero := zerofield( x, 0, stickybit ) and (x.exponent > minexp)  ;
end ;

procedure pushstack (* x : internal *) ;
(* pushes x on stack *)
        (* In case of NV exception and trapping NAN, makes the NAN
        non-trapping.  *)

var
p : pstack  ;

begin
if stackspace >= 3 then begin
new(p) ;
if (invop in fpstatus.curexcep) and (abs(kind(x))=nankind) then
x.significand[1] := false ; (* By convention bit 1 determines trapping/
                                non-trapping.  *)
p^.x := x ;
p^.next := stack ;
stack := p ;
end else 
writeln(' ERROR: not enough space for push! ') ;
end ;

procedure popstack (* var x : internal *) ;
        (* pops stack to x, or sets x to 0 if stack is empty *)
begin
if stack=nil then begin
x.sign := false ;
makezero(x) ;
end
else begin
x := stack^.x ;
stack := stack^.next ;
if (abs(kind(x))=nankind) and x.significand[1] then (* It's a Trapping NAN. *)
setex( invop ) ;
end
end ;

procedure donormalize (* var x : internal *) ;
        (* normalizes x *)
        (* Unnormalized zeros are set to normalized zeros.
a           INFs and NANs are not changed *)

var
i, j : integer ;

begin
if x.exponent < maxexp then begin
i := firstbit( x, 0, stickybit )  ;
if i > stickybit then x.exponent := minexp (* zero *) else
if i > 0 then begin
x.exponent := x.exponent - i ;
for j := i to stickybit do 
x.significand[j-i] := x.significand[j] ;
for j := ((stickybit+1)-i) to (stickybit-1) do
x.significand[j] := x.significand[stickybit] ;
{
if (x.significand[stickybit]) and (i>1)  then 
writeln(i,' ERROR: Normalizing Sticky Bit ') ;
        (* It's OK to shift sticky bit into next to last position because
        during rounding the last two positions are stuck together.
        It is definitely not OK to shift a sticky bit any further left.  *)
}
end ;
end ;
end ;

procedure right (* var x : internal ; n : integer *) ;
        (* does sticky right shift of internal x *)
        
var
i : integer ;

begin
{
if (0 > n) or (n > stickybit) then
writeln(' Funny Right ',n) ;
}
if n > stickybit then n := stickybit ; (* It's all the same for large n.  *)
x.significand[stickybit] := not zerofield( x, (stickybit-n), stickybit) ;
for i := (stickybit-1) downto n do
x.significand[i] := x.significand[i-n] ;
for i := (n-1) downto 0 do
x.significand[i] := false ;
end ;

procedure left (* var x : internal ; n : integer *) ;

        (* Lefts shifts significand of x, n times *)
        
var i : integer ;

begin
{
if (0 > n) or ( n > stickybit) then
writeln(' Funny left ',n) ;
}
if n > stickybit then n := stickybit ;  (* All the same for large n.  *)
for i := 0 to (stickybit-1-n) do
x.significand[i] := x.significand[i+n] ;
{
if x.significand[stickybit] and (n>1)  then
writeln(n,' Error: LEFT shift of STICKY bit ') ;
}
for i := (stickybit-n) to (stickybit-1) do
x.significand[i] := x.significand[stickybit] ;
end ;

procedure roundkcs (* var x : internal ; r : roundtype ;
        p : precisetype  *) ;
        
        (* Rounds x according to rounding mode and rounding precision.
        Sets Inexact flag in curexcep if appropriate. *)
        
var i : integer ;
akx : integer ;

procedure dorn ; (* round to nearest *)

var
i : integer ;
carry : boolean ;

begin
carry := true ;
i := (leastsigbit+1) ;
while (i>=0) and carry do begin
adder(x.significand[i], false, x.significand[i], carry) ;
i := i-1 ;
end ;
if carry then begin (* carry out of most significant bit occurred. *)
x.significand[0] := true ;
x.exponent := x.exponent + 1 ;
end
else begin (* Check for ambiguous case *)
if zerofield( x, leastsigbit+1, stickybit )  
then (* It is the ambiguous case. *)
x.significand[leastsigbit] := false ; (* force round to even. *)
end ;
end ;

procedure doro ; (* Round away from zero (Outward Round) *)

var
i : integer ;
carry : boolean ;

begin
carry := false ;
for i := (leastsigbit+1) to stickybit do carry := carry or x.significand[i] ;
if carry then begin (* propagate a carry *)
i := leastsigbit ;
while (i >= 0) and carry do begin
adder(x.significand[i], false, x.significand[i], carry) ;
i := i - 1 ;
end ;
if carry then begin (* Carry out occurred, so renormalize. *)
x.significand[0] := true ;
x.exponent := x.exponent + 1 ;
end ;
end ;
end ;

begin (* round *)
akx := abs(kind(x)) ;
if akx in [unnormkind, normkind] then begin
case p of 
sprec: begin
right(x, 40) ;
x.exponent := x.exponent + 40 ;
end ;

dprec : begin
right(x, 11) ;
x.exponent := x.exponent + 11 ;
end ;

otherwise
end ;
for i := (leastsigbit+1) to stickybit do if x.significand[i] then 
begin
setex( inxact ) ;
end ;
case r of
rnear : begin 
dorn ;
end ;
rneg : if x.sign then doro  ;
rpos : if not x.sign then doro ;
otherwise
end ;

for i := (leastsigbit+1) to stickybit do x.significand[i] := false ;
        (* Eliminate G, R, and S bits. *)
case p of
 sprec: begin
left(x,39) ;
x.exponent := x.exponent - 39 ; 
if not  x.significand[0] then 
begin
left( x, 1) ;
x.exponent := x.exponent - 1 ;
end ;
end ;

dprec: begin
left(x,10) ;
x.exponent := x.exponent - 10 ; 
if not  x.significand[0] then 
begin
left(x,1) ;
x.exponent := x.exponent - 1 ;
end ;
end ;

otherwise
end ;
end ;
end ;

procedure roundint (* var x : internal ; r : roundtype ; p : precisetype *) ;
        
        (* Rounds x to an integral value in accordance with modes.  *)

var
akx, i, count : integer ;

begin
akx := abs(kind(x)) ;
if akx in [unnormkind, normkind]  then begin
if (x.exponent >= (leastsigbit+1)) then count := 0
else if x.exponent <= (leastsigbit+1-stickybit) then count := stickybit
else count := (leastsigbit+1) - x.exponent ; 
        (* Compute shift count of bits to get rid of.  *)
case p of (* But allow for rounding to shorter precisions, too.  *)
 sprec: if count < 40 then count := 40 ;
 dprec: if count < 11 then count := 11 ;
otherwise
end ;
if count > 0 then right ( x, count) ;
roundkcs( x, r, xprec) ; (* Do rounding.  *)
if count > leastsigbit then begin (* Limit left shifts
        for 0 < x < 1 which must be rounded either to 0 or 1.  *)
        count := leastsigbit ;
        x.exponent := 1 ;
        end ;
if count > 0 then begin
left(x, count-1 ) ;
if x.significand[0] then x.exponent := x.exponent + 1 (* Rounding carry out.  *)
else left(x, 1) ;
end ;
if zerofield ( x, 0, stickybit ) then x.exponent := minexp ;
        (* No significant bits left so make it a true zero.  *)
end end ;


procedure picknan (* x, y : internal ; var z : internal *) ;

        (* Sets z to whichever of x or y is a NAN.
        If both are NANs, sets z to the one with the 
        greatest significand.  *)
        
var i : integer ;

begin
if abs(kind(x)) = nankind then 
if abs(kind(y)) = nankind then begin
i := 0 ;
while (i <= leastsigbit) and (x.significand[i] = y.significand[i]) do 
        i := i + 1 ;
if x.significand[i] then z := x else z := y ;
end 
else z := x else z := y
end ;

function equalinternal ( x1, x2 : internal ) : boolean ;
        (* Returns true if x1 = x2 *)
var
t : boolean ;
i : integer ;

begin
t := (x1.sign=x2.sign) and (x1.exponent=x2.exponent) ;
if t then for i := 0 to stickybit do
t := t and (x1.significand[i]=x2.significand[i]) ;
equalinternal := t ;
end ;

function concat ( x, y : strng ) : strng ;

var t : strng ;
i, lx, ly : integer ;

begin (* concat *)
t := x ;
lx := ord(x[0]) ; ly := ord(y[0]) ;
for i := 1 to ly do t[lx+i] := y[i] ;
t[0] := chr(lx+ly) ;
concat := t ;
end   (* concat *) ;

procedure precatchar ( c : char ; var x : strng ) ;

var i, ls : integer ;

begin (* precatchar *)
ls := ord(x[0]) ;
for i := ls downto 1 do x[i+1] := x[i] ;
x[1] := c ;
x[0] := chr(ls+1) ;
end   (* precatchar *) ;

procedure delete ( var x : strng ; index, count : integer ) ;

var i : integer ;

begin (* delete *)
for i := index+count to length(x) do
	x[i-count] := x[i] ;
x[0] := chr(length(x)-count) ;
end   (* delete *) ;

procedure makeucsdstring( x : strng; var t : strng );
	(* Converts a constant string to UCSD form. *)
var i, l : integer ;
begin
l := 0 ;
while (33 <= ord(x[l])) and (ord(x[l]) <= 126) do l := l + 1 ;
for i := l downto 1 do t[i] := x[i-1] ;
t[0] := chr(l) ;
end ;

procedure copy ( s : strng; index, count : integer ; var t : strng ) ;

var i : integer ; l : integer ;

begin (* copy *)
t[0] := chr(count) ;
for i := 1 to count do t[i] := s[index+i-1] ;
end   (* copy *) ;

procedure insert( s : strng ; var d : strng ; index : integer ) ;

var i,ld,ls : integer ;

begin (* insert *)
ls := ord(s[0]) ; ld := ord(d[0]) ;
for i := ld downto index do d[i+ls] := d[i] ;
for i := ls downto 1 do d[index+i-1] := s[i] ;
d[0] := chr(ls+ld) ;
end   (* insert *) ;

function pos ( c : char ; s : strng ) : integer ;

var i, l : integer ;

begin (* pos *)
l := ord(s[0]) ;
i := 1 ;
while (i <= l) and (s[i] <> c) do i := i + 1 ;
if i <= l then pos := i else pos := 0 ;
end   (* pos *) ;

function sequal ( s, c : strng ) : boolean ;
      (* Compares UCSD string s to C string c and returns true if equal. *)
var
i, ls, lc : integer ;

begin (* sequal *)
lc := 0;
ls := ord(s[0]) ;
while (33 <= ord(c[lc])) and (ord(c[lc]) <= 126) do lc := lc + 1 ;
if lc <> ls then 
	begin
	sequal := false ;
	end
 else
	begin
	i := 1 ;
	while (i <= ls) and (s[i] = c[i-1]) do i := i + 1 ;
	sequal := i > ls ;
	end ;
end   (* sequal *) ;


End-Of-File
echo Extracting init.i
cat >init.i <<'End-Of-File'

(* File init.i, Version 4 February 1985. *)


PROCEDURE initialize ;

        (* does all the initializing of tables and variables.  *)

var error : boolean ;

procedure inittensmall ;

        (* procedure to initialize the table of small  powers of ten *)
        
var
i : integer ;
j : integer ;
x : internal ;
carry : boolean ;
last : integer ;
error : boolean ;

begin
(* Make 10^0=1 *)
for i := 1 to stickybit do x.significand[i] := false ;
x.sign := false ;
x.exponent := 1 ;
x.significand[0] := true ;
tensmall[0] := x ;

(* Make other exact powers of ten.  *)
last := 0 ; (* Last non-zero bit. *)
for j := 1 to 28 do begin
x.exponent := x.exponent + 3 ; (* Multiply by 8 first.  *)
last := last + 2 ; (* At least 2 more significant bits.  *)
carry := false ;
for i := last downto 2 do
adder(x.significand[i-2], x.significand[i],x.significand[i],carry) ;
for i := 1 downto 0 do
adder(false, x.significand[i],x.significand[i],carry) ;
if carry then begin (* Overflowed slightly.  *)
x.exponent := x.exponent + 1 ;
last := last + 1 ;
for i := last downto 1 do
x.significand[i] := x.significand[i-1] ;
x.significand[0] := true ;
end ;
tensmall[j] := x ;
end ;

hexbin(' .a18f 07d7 36b9 0be5 4 h  97', tensmall[29], error ) ;
hexbin(' .c9f2 c9cd 0467 4ede c h 100', tensmall[30], error ) ;
hexbin(' .fc6f 7c40 4581 2296 4 h 103', tensmall[31], error ) ;
end ;

procedure inittenbig ;

        (* procedure to initalize the table of large powers of ten *)
        
var
error : boolean ;

begin
tenbig[0] := tensmall[0] ;
hexbin(' .9dc5 ada8 2b70 b59d c h 107',tenbig[1], error ) ;
hexbin(' .c278 1f49 ffcf a6d5 4 h 213',tenbig[2], error ) ;
hexbin(' .efb3 ab16 c59b 14a2 c h 319',tenbig[3], error ) ;
hexbin(' .93ba 47c9 80e9 8cdf c h 426',tenbig[4], error ) ;
hexbin(' .b616 a12b 7fe6 17aa 4 h 532',tenbig[5], error ) ;
hexbin(' .e070 f78d 3927 556a c h 638',tenbig[6], error ) ;
hexbin(' .8a52 96ff e33c c92f c h 745',tenbig[7], error ) ;
hexbin(' .aa7e ebfb 9df9 de8d c h 851',tenbig[8], error ) ;
hexbin(' .d226 fc19 5c6a 2f8c 4 h 957',tenbig[9], error ) ;
hexbin(' .8184 2f29 f2cc e375 c h 1064',tenbig[10], error ) ;
hexbin(' .9fa4 2700 db90 0ad2 4 h 1170',tenbig[11], error ) ;
hexbin(' .c4c5 e310 aef8 aa17 4 h 1276',tenbig[12], error ) ;
hexbin(' .f28a 9c07 e9b0 9c58 c h 1382',tenbig[13], error ) ;
hexbin(' .957a 4ae1 ebf7 f3d3 c h 1489',tenbig[14],error) ;
hexbin(' .b83e d8dc 0795 a262 4 h 1595',tenbig[15], error) ;
end ;
 
procedure inittenhuge ;

var
error : boolean ;

begin
hexbin(' .e319 a0ae a60e 91c6 c h 1701',tenbig[16], error) ;
hexbin(' .8bf6 1451 432d 7bc2 c h 1808', tenbig[17], error) ;
hexbin(' .ac83 fb89 6b67 95fc c h 1914', tenbig[18], error) ;
hexbin(' .d4a4 4fb4 b8fa 79af c h 2020', tenbig[19], error) ;
hexbin(' .830c f791 e54a 9d1c c h 2127', tenbig[20], error) ;
hexbin(' .a188 4b69 ade2 4964 4 h 2233', tenbig[21], error) ;
hexbin(' .c71a a36a 1f8f 01cb c h 2339', tenbig[22], error) ;
hexbin(' .f56a 298f 4370 28f3 4 h 2445', tenbig[23], error) ;
hexbin(' .973f 9ca8 cd00 a68c 4 h 2552', tenbig[24], error) ;
hexbin(' .ba6d 9b40 d7cc 9ecc c h 2658', tenbig[25], error) ;
hexbin(' .e5ca 5a0b 8d73 7f0e 4 h 2764', tenbig[26], error) ;
hexbin(' .8d9e 89d1 1346 bda5 4 h 2871', tenbig[27], error) ;
hexbin(' .ae8f 2b2c e3d5 dbe9 c h 2977', tenbig[28], error) ;
hexbin(' .d729 3020 5a0c 1b2f c h 3083', tenbig[29], error) ;
hexbin(' .849a 672a 0d2e cfd1 c h 3190', tenbig[30], error) ;
hexbin(' .a372 2c13 41fa 93de 4 h 3296', tenbig[31], error) ;
end ;



begin
digitset := [ '0' .. '9' ] ;
hexset := digitset + [ 'A' .. 'F' ] ;
stack := nil ;
storagemode := unrounded ;
testflag := false ;
fpstatus.mode.round := rnear ;
fpstatus.mode.precision := xprec ;
fpstatus.mode.clos := affine ;
fpstatus.mode.norm := normalizing ;
fpstatus.curexcep := [] ;
fpstatus.excep := [] ;
fpstatus.trap := [] ;
leftnan[1] := 0 ;
leftnan[2] := 24 ;
leftnan[3] := 53 ;
leftnan[4] := leastsigbit + 1 ;
rightnan[1] := leftnan[2] - 1 ;
rightnan[2] := leftnan[3] - 1 ;
rightnan[3] := leftnan[4] - 1 ;
 rightnan[4] := stickybit ;
xcpnname[cvtovfl] := 'IV' ;
xcpnname[overfl] := 'OV' ;
xcpnname[underfl] := 'UN' ;
xcpnname[div0] := 'D0' ;
xcpnname[invop] := 'NO' ;
xcpnname[inxact] := 'NX' ;
inittensmall ;
inittenbig ;
inittenhuge ;
(*
decbin ( ' 3.1415926535 89793 23846 26433', pi, error ) ;
decbin ( ' 2.7182818284 59045 23536 02874', e, error ) ;
*)
hexbin ( ' .c90fdaa22168c234c h 2', pi, error ) ;
decbin ( ' 2.7182818284 59045 23536 02874', e, error ) ;
end ;


End-Of-File
echo ""
echo "End of Kit"
exit

sources-request@panda.UUCP (09/04/85)

Mod.sources:  Volume 3, Issue 7
Submitted by: decvax!decwrl!sun!dgh!dgh (David Hough)

#! /bin/sh
: make a directory, cd to it, and run this through sh
echo If this kit is complete, "End of Kit" will echo at the end
echo Extracting extra.i
cat >extra.i <<'End-Of-File'

(* File extra.i, version 9 October 1984 *)

procedure csqrt ( x : internal ; var z : internal  ) ;

        (* Computes z := sqrt(x).  *)
        
procedure dosqrt ;

        (* Does SQRT for normalized positive x.  *)

var
i, j : integer ;
r : internal ;
carry : boolean ;
sbit, vbit, orbit : boolean ;

begin
roundkcs ( x, fpstatus.mode.round, xprec ) ; (* Pre-round.  *)
r := x ; (* R will be the remainder for the nonrestoring binary square root  *)
z.sign := false ; (* Result is never negative since x is positive donormalize  *)
if odd(r.exponent) then begin
r.exponent := r.exponent + 1 ; (* Make exponent even.  *)
right( r, 1 ) ; (* And make fraction 0.25 <= r <= 0.5  *)
end ;
z.exponent := r.exponent div 2 ;
sbit := false ; (* Sign bit of remainder, initially positive.  *)
carry := false  ;
                (* Subtract 0.25 to start the fun.  *)
suber(r.significand[1], true, r.significand[1], carry) ;
suber(r.significand[0], false, r.significand[0], carry) ;

                (* Now do main loop.
                Ri fits in i+1 bits.
                Zi fits in i-1 bits.  *)

for i := 1 to (leastsigbit+2) do
if sbit then begin (* R is negative so add: 
                        Zi+1 := 2 Zi
                        Ri+1 := 4 Ri + 4 Zi+1 + 3    *)
z.significand[i-1] := false ; (* Set result bit.  *)
vbit := r.significand[0] ;  (* Catch overfl.  *)
left(r,1) ; (* Multiply R by 2.  *)
carry := false ;
adder( r.significand[i+1], true, r.significand[i+1], carry) ; 
(* Add 3*2**-i-2 *)
adder(r.significand[i], true, r.significand[i], carry) ;
for j := (i-1) downto 0 do (* Add Zi+1.  *)
adder(r.significand[j], z.significand[j], r.significand[j], carry ) ;
adder( vbit, false, vbit, carry ) ;
adder ( sbit, false, sbit, carry ) ; (* Sets sign of r.  *)
end

else begin (* R is >= 0 so subtract:
                        Zi+1 := 2 Zi + 1 
                        Ri+1 := 4 Ri - 4 Zi+1 - 1   *)
z.significand[i-1] := true ; (* Set result bit.  *)
vbit := r.significand[0] ;
left(r,1) ;
carry := false ;
suber( r.significand[i+1], true, r.significand[i+1], carry ) ;
        (* Subtract 1 *)
suber(r.significand[i], false, r.significand[i], carry ) ;
for j := (i-1) downto 0 do (* Subtract Zi+1 *)
suber( r.significand[j], z.significand[j], r.significand[j], carry ) ;
suber( vbit, false, vbit, carry ) ;
suber( sbit, false, sbit, carry ) ;
end ;

z.significand[stickybit-1] := false ; (* This bit isn't used.  *)

        (* Determine sticky bit.  Z is exact iff
        Rn + 4 Zn + 1 <= 0   *)
        
carry := false ; orbit := false ;
adder( r.significand[leastsigbit+3], true, vbit, carry ) ; (* Add 1.  *)
orbit := orbit or vbit ;
adder( r.significand[leastsigbit+2], false, vbit, carry ) ;
orbit := orbit or vbit ;
for j := (leastsigbit+1) downto 0 do begin
adder( r.significand[j], z.significand[j], vbit, carry ) ;
orbit := orbit or vbit ;
end ;
adder(sbit, false, vbit, carry ) ;
orbit := orbit or vbit ;
adder( sbit, false, sbit, carry ) ;
z.significand[stickybit] := orbit and (not sbit) ;
                (* Inexact if result of test is positive.  *)
end ;


begin (* csqrt*)

case kind(x) of 
negnan, nankind : z := x ;
neginf, negnorm, negunnorm, unnormkind : makenan(nansqrt, z) ;
zerokind : z := x ;
normkind : dosqrt ;
infkind : if fpstatus.mode.clos = affine then z := x else
makenan(nansqrt, z ) ;
otherwise
end ;

end ;

procedure clogb ( x : internal ; var z : internal ) ;

        (* Sets y to the unbiased exponent of x.  *)
        
var
yi : cint64 ;
i, k : integer ;

begin 
case abs(kind(x)) of

zerokind : begin
makeinf(z) ;
z.sign := true ;
end ;

unnormkind, normkind : begin
for i := 0 to 5 do yi[i] := 0 ;
k := x.exponent - 1 ; (* -1 because binary point is to left of bit 0.  *)
yi[6] := abs(k) div 256 ;
yi[7] := abs(k) mod 256 ;
unpackinteger ( yi, z, i16 ) ;
z.sign := k < 0 ;
end ;

infkind : begin
makeinf(z) ;
z.sign := false ;
end ;

nankind : z := x ;
otherwise
end ;
end ;

procedure cnextafter ( x, y : internal ; var z : internal  ) ;

        (* Sets z to the next machine number after x in the direction of
        y.  *)

var
cc : conditioncode ;
i : integer ;
rnd : roundtype ;
moveright : boolean ;
t : internal ;

begin
roundkcs(x, fpstatus.mode.round, xprec ) ; (* Preround.  *)
roundkcs(y, fpstatus.mode.round, xprec ) ;
z := x ; (* Default result.  *)
compare( x, y, cc ) ;
if cc in [lesser,greater] then
        begin (* x <> y *)
        moveright := cc = lesser ; (* If x < y then move x to right (+INF) *)
        rnd := fpstatus.mode.round ;
        if moveright then fpstatus.mode.round := rpos else
                fpstatus.mode.round := rneg ;
        case abs(kind(x)) of
        zerokind : begin (* zero *)
                   z.significand[leastsigbit] := true ;
                   z.sign := not moveright ;
                   end   (* zero *) ;
        infkind :  begin (* inf *)
                   z.exponent := maxexp - 1 ;
                   for i := 0 to leastsigbit do z.significand[i] := true ;
                   z.sign := moveright ;
                   end   (* inf *) ;
        unnormkind, normkind :
                if unzero(x) then z.exponent := x.exponent - 1
        else
                begin (* Do add *)
                makezero(t) ;
                t.significand[leastsigbit] := true ;
                t.sign := not moveright ;
                add(x, t, z) ;
                end   (* Do add *) ;
        otherwise
	end (* case *) ;
        roundkcs( z, fpstatus.mode.round, fpstatus.mode.precision ) ;
        store(z) ;
     fpstatus.mode.round := rnd ; (* Force special rounding mode on store.  *)
        end   (* x <> y *) ;
fpstatus.curexcep := fpstatus.curexcep - [inxact] ; (* Don't want inxact
        on a NEXT operation.  *)
end ;


procedure complement ( var x : internal ; var v : boolean ) ;

        (* Complements x.significand, treating it as a 64 bit integer.
        v is a carry out bit.  *)

var 
carry : boolean ;
i : integer ;

begin
carry := false ;
for i := leastsigbit downto 0 do 
suber( false, x.significand[i], x.significand[i], carry ) ;
v := carry ;
end ;

procedure cscale ( x, y : internal ; var z : internal  ) ;

        (* Sets z to x * 2 **int(y).  *)
        
var
rx, ry : roundtype ;

procedure doscale ; 

        (* Carries out scaling for proper x and y.  *)
        
var
xe : internal ;
i, k : integer ;
v, v2, carry : boolean ;
s : strng ;
irs : integer ;

begin
z := x ; (* Now all we have to do is set the exponent.  *)
xe.sign := x.exponent < 0 ; (* xe will contain exponent of x expanded.  *)
k := abs(x.exponent) ;
for i := leastsigbit downto 0 do begin
xe.significand[i] := odd(k) ;
k := k div 2   ;
end ;

if xe.sign then complement( xe, v2 ) ;

if y.exponent > 64 then begin (* Substitute for huge y.  *)
y.exponent := 64 ;
y.significand[0] := true ;
end ;
if y.exponent < (64-stickybit) then irs := stickybit 
        (* Look out for 16 bit integer overfl.  *)
else irs := 64 - y.exponent ; (* Set up count for right shift.  *)
right( y, irs  ) ; (* Align significand of y as an integer.  *)
if y.sign then complement(y, v) ;
carry := false ;
for i := stickybit downto 0 do 
adder( xe.significand[i], y.significand[i], xe.significand[i], carry ) ;
adder( v, v2, xe.sign, carry ) ;

if xe.sign then complement( xe, v ) ;

v := not zerofield( xe, 0, 48 ) ; (* v is now an overfl flag.  *)
k := 0 ;
for i := 49 to leastsigbit do begin
k := k + k ;
if xe.significand[i] then k := k + 1 ;
end ;
if xe.sign then k := -k ; (* Set up correct negative exponent.  *)
v := v or (k=maxexp) or (k=minexp) ;
if v then begin (* Exponent overfl.  *)
if xe.sign then begin (* Floating underfl.  *)
makezero(z) ;
setex ( underfl ) ;
end 
else begin (* Floating overfl.  *)
makeinf(z) ;
setex ( overfl ) ;
end
end
else z.exponent := k ;
end ;

begin (* Scale.  *)
if (abs(kind(x))=nankind) or (abs(kind(x))=nankind) then 
picknan(x, y, z ) else begin
rx := fpstatus.mode.round ; (* Default.  *)
ry := rx ;
case rx of
rneg : if x.sign then ry := rpos ;
rpos : if x.sign then ry := rneg ;
rzero : ry := rneg ;
otherwise
end ;

roundkcs(x, rx, xprec) ;
roundint(y, ry, xprec) ;
donormalize(y) ;

case abs(kind(x)) of

zerokind : case abs(kind(y)) of

zerokind, normkind : z := x ;
infkind : if (fpstatus.mode.clos = affine) and
(kind(y) = neginf) then z := x else
makenan( nanmul, z) ; (* 2 **INF = NAN,  2**+INF = +INF, 2**-INF = 0 *)
end ;

unnormkind, normkind : case abs(kind(y)) of
zerokind, normkind : doscale ;
infkind : if fpstatus.mode.clos = proj then makenan(nanmul, z)
else if x.sign then makezero(z)
else makeinf(z) ;
end ;

infkind : case abs(kind(y)) of
zerokind, normkind : z := x ;
infkind : if (fpstatus.mode.clos=proj) or (kind(x)=neginf) then
makenan(nanmul, z)
else z := x ;
end ;

otherwise
end ;
z.sign := x.sign ;
end ;
end ;


End-Of-File
echo Extracting storage.i
cat >storage.i <<'End-Of-File'
(* File storage.i, Version 9 October 1984.  *)

function xbyte ( x : internal ; p1, p2 : integer ) : BYT ;

        (* Converts bits
        x.significand[p1..p2] 
        into a BYT value.  *)
        
var
b : BYT ;
i : integer ;

begin
b := 0 ;
for i := p1 to p2 do 
if x.significand[i] then b := b + b + 1 else b := b + b ;
xbyte := b ;
end ;

procedure ibytes ( k : integer ; var b1, b2 : BYT ) ;

        (* Converts 16 bit integer into two BYT values.  *)
        
var 
neg : boolean ;

begin
neg := k < 0 ;
if neg then k := ( k + 16384 ) + 16384  ; (* Remove most significant bit.  *)
b1 := k div 256 ;
b2 := k mod 256 ;
if neg then b1 := b1 + 128 ; (* Restore most significant bit.  *)
end ;

procedure bytehex ( b : BYT  ; var s  : strng )  ;

        (* Converts BYT to two hex digits.  *)
        
var
nib : nibarray ;
i,j : integer ;
w : BYT ;

begin
s[0] := chr(2) ;
w := b ;
for j := 2 downto 1 do begin
for i := 3 downto 0 do begin
nib[i] := odd(w) ;
w := w div 2 ;
end ;
s[j] := nibblehex(nib) ;
end ;
end ;

procedure bytex ( b : BYT ; var x : internal ; p1, p2 : integer ) ;

        (* Inserts BYT b into
        x.significand[p1..p2] *)
        
var i : integer ;

begin
for i := p2 downto p1 do begin
x.significand[i] := odd(ord(b)) ;
b := b div 2 ;
end ;
end ;

procedure unpackextended ( y : cextended ; var x : internal ) ;

        (* Unpacks cextended into internal.  *)
        
var
zero : boolean ;
i : integer ;

begin
x.sign := (y[0] >= 128) ;
if x.sign then y[0] := y[0] - 128 ; (* Remove sign bit.  *)
x.exponent := (256*y[0] + y[1]) - biasex ;
for i := 2 to 9 do bytex( y[i], x, (8*i-16), (8*i-9) ) ;
for i := (leastsigbit+1) to stickybit do 
x.significand[i] := false ;

if x.exponent >= maxex then x.exponent := maxexp ; (* INF/NAN *)
if x.exponent <= minex then begin
zero := y[2]=0 ;
for i := 3 to 9 do 
zero := zero and (y[i]=0) ;
if zero then x.exponent := minexp else begin
x.exponent := minex + 1 ;
        (* Add offset for cextended denormalized.  *)
if (fpstatus.mode.norm = normalizing)  then begin
donormalize(x) ;
end
        (* Normalize denormalized operand in normalizing mode.  *)
end
end ;

end ;

procedure toextended ( var x : internal ; var y : cextended  ) ;
        
        (* Converts x to cextended y.  *)
        
var i : integer ;
s : strng ;
special : boolean ;
y0,y1 : BYT ;

begin
case abs(kind(x)) of
otherwise ;
zerokind : x.exponent := minex ;

unnormkind, normkind : begin
if x.exponent <= minex then begin (* Underflow.  *)
if underfl in fpstatus.trap then begin (* Trap enabled.  *)
setex ( underfl ) ;
x.exponent := x.exponent + 24576 ;
if x.exponent <= minex then begin (* Severe underfl - give invalid result. *)
makenan(nanresult,x) ;
end ;
end
else begin (* Trap disabled.  *)
right( x, minex + 1   - x.exponent ) ;
x.exponent := minex ;
roundkcs( x, fpstatus.mode.round, fpstatus.mode.precision ) ;
if inxact in fpstatus.curexcep  then
        setex ( underfl ) ; (* Signal.  *)
end ;
end ;

roundkcs( x, fpstatus.mode.round, fpstatus.mode.precision ) ;
if (x.exponent >= maxex)  then begin (* Overflow.  *)
if overfl in fpstatus.trap then begin (* Trap enabled.  *)
setex ( overfl ) ;
x.exponent := x.exponent - 24576 ;
if x.exponent >= maxex then (* Severe overfl - give invalid result.  *)
begin
makenan(nanresult,x) ;
end ;
end

else begin (* Trap disabled.  *)
setex ( inxact ) ;
setex( overfl ) ;
case fpstatus.mode.round of
rneg : special := not x.sign ;
rpos : special := x.sign ;
rnear : special := false ;
rzero : special := true ;
otherwise 
end ;
if special then begin (* Special case roundings.  *)
x.exponent := maxex - 1 ; 
        (* Round normalized to largest normalized number.
        Round unnormalized to largest exponent, same significand.  *)
if x.significand[0] then 
for i := 0 to leastsigbit do x.significand[i] := true ;
end
else begin (* Normal case - set INF.  *)
x.exponent := maxex ;
for i := 0 to leastsigbit do x.significand[i] := false ;
end ;
end
end ;
if abs(kind(x)) = nankind then begin
setex(invop) ;
fpstatus.curexcep := fpstatus.curexcep - [inxact] ;
x.exponent := maxex ;
end end ;

infkind, nankind : x.exponent := maxex ;
end ;

for i := 2 to 9 do (* Pack significand.  *)
y[i] := xbyte ( x, (8*i-16), (8*i-9) ) ;
ibytes ( x.exponent + biasex, y0, y1 ) ; (* Pack exponent.  *)
y[0] := y0 ; y[1] := y1 ;
if x.sign then y[0] := y[0] + 128 ; (* Pack sign bit.  *)

write(' Extended format: ') ;
for i := 0 to 9 do begin 
bytehex( y[i], s ) ;
write(s[1],s[2], ' ') ;
end ;
writeln ;

unpackextended ( y, x) ;

end ;

procedure unpackdouble (* y : cdouble ; var x : internal *) ;

        (* Unpacks cdouble into internal.  *)
        
var
i : integer ;
zero : boolean ;

begin
x.sign := y[0] >= 128 ;
if x.sign then y[0] := y[0] - 128 ;
x.exponent := (16*y[0] + (y[1] div 16)) - biased ;
bytex ( y[1] mod 16, x, 1, 4 ) ;
for i := 2 to 7 do bytex ( y[i], x, (8*i-11), (8*i-4) ) ;
for i := 53 to stickybit do x.significand[i] := false ;

if x.exponent >= maxed then begin
x.exponent := maxexp ;
x.significand[0] := false ;
end
else if x.exponent <= mined then  begin
x.significand[0] := false ;
if zerofield( x, 1, 52 ) then x.exponent := minexp (* Normal Zero.  *)
else x.exponent := x.exponent + 1 ; (* Offset for denormalized numbers.  *)
if (fpstatus.mode.norm = normalizing)  then donormalize(x) 
        (* Normalize denormalized operand in normalizing mode.  *)
end 
else x.significand[0] := true ; (* Insert leading bit. *)
end ;

procedure todouble (* var x : internal ; var y : cdouble  *) ;

        (* Converts x to cdouble y.  *)
        
var
i : integer ;
s : strng ;
special : boolean ;
y0,y1 : BYT ;

begin
case abs(kind(x)) of
otherwise ;
zerokind : x.exponent := mined ;

unnormkind, normkind : begin
if x.exponent <= mined then begin (* Underflow.  *)
if underfl in fpstatus.trap then begin (* Trap enabled.  *)
setex ( underfl ) ;
x.exponent := x.exponent + 1536 ;
if( x.exponent <= mined) or not x.significand[0]  then begin (* Severe underfl.  *)
makenan(nanresult,x)
end ;
end
else begin (* Trap disabled.  *)
right( x, mined + 1 - x.exponent ) ;
x.exponent := mined+1 ;
roundkcs( x, fpstatus.mode.round, dprec ) ;
if inxact in fpstatus.curexcep  then setex ( underfl ) ; (* Signal.  *)
end ;
end ;

roundkcs( x, fpstatus.mode.round, dprec ) ;
if (x.exponent >= maxed) and x.significand[0] then begin (* Overflow.  *)
if overfl in fpstatus.trap then begin (* Trap enabled.  *)
setex ( overfl ) ;
x.exponent := x.exponent - 1536 ;
if x.exponent >= maxed then begin (* Severe overfl.  *)
makenan(nanresult,x)
end ;
end

else begin (* Trap disabled.  *)
setex ( inxact ) ;
setex( overfl ) ;
case fpstatus.mode.round of
rneg : special := not x.sign ;
rpos : special := x.sign ;
rnear : special := false ;
rzero : special := true ;
otherwise
end ;
if special then begin (* Special case roundings.  *)
x.exponent := maxed - 1 ; (* Round to largest normalized number.  *)
for i := 0 to leastsigbit do x.significand[i] := true ;
end
else begin (* Normal case - set INF.  *)
x.exponent := maxed ;
for i := 0 to leastsigbit do x.significand[i] := false ;
end ;
end
end ;

if (x.exponent=(mined+1)) and (not x.significand[0]) then
        x.exponent := mined ; (* Look for  denormalized number,
         which may have resulted from an underfl, but might not have.  *)

if (abs(kind(x))=nankind) or (  (x.exponent > mined) and (x.exponent < maxed) 
and not x.significand[0]) then begin 
(* Invalid Result.  *)
makenan( nanresult, x ) ;
setex ( invop ) ;
fpstatus.curexcep := fpstatus.curexcep - [  inxact ] ;
x.exponent := maxed ;
end ;
end ;

infkind, nankind : 
        begin (* inf/nan *)
        x.exponent := maxed ;
        for i := 53 to leastsigbit do
                if x.significand[i] then x.significand[52] := true ;
                (* OR together least significant bits of NAN *)
        end   (* inf/nan *) ;
end (* case *);

ibytes (( x.exponent + biased) * 16, y0, y1 ) ;
        (* Pack exponent *)
y[0] := y0 ; y[1] := y1 ;
if x.sign then y[0] := y[0] + 128 ; (* Pack sign.  *)
y[1] := y[1] + xbyte( x, 1, 4 ) ;
for i := 2 to 7 do 
y[i] := xbyte ( x, 8 * i - 11, 8 * i - 4 ) ; (* Pack significand.  *)

write(' Double format: ') ;
for i := 0 to 7 do begin
bytehex( y[i], s ) ;
write(s[1],s[2], ' ') ;
end ;
writeln ;

unpackdouble( y, x ) ;
end ;

procedure unpacksingle (* y : csingle ; var x : internal *) ;

        (* Unpacks csingle into internal.  *)
        
var
i : integer ;
zero : boolean ;

begin
x.sign := y[0] >= 128 ;
if x.sign then y[0] := y[0] - 128 ;
x.exponent := (2*y[0] + (y[1] div 128)) - biases ;
bytex ( y[1] mod 128, x, 1, 7 ) ;
for i := 2 to 3 do bytex ( y[i], x, (8*i-8), (8*i-1) ) ;
for i := 24 to stickybit do x.significand[i] := false ;

if x.exponent >= maxes then begin
x.exponent := maxexp ;
x.significand[0] := false ;
end
else if x.exponent <= mines then  begin
x.significand[0] := false ;
if zerofield( x, 1, 23 ) then x.exponent := minexp (* Normal Zero.  *)
else x.exponent := x.exponent + 1 ; (* Offset for denormalized numbers.  *)
if (fpstatus.mode.norm = normalizing)   then donormalize(x) 
        (* Normalize denormalized operand in normalizing mode.  *)
end 
else x.significand[0] := true ; (* Insert leading bit. *)
end ;

procedure tosingle (* var x : internal ; var y : csingle  *) ;

        (* Converts x to csingle y.  *)
        
var
i : integer ;
s : strng ;
special : boolean ;
y0,y1 : BYT ;

begin
case abs(kind(x)) of
otherwise ;
zerokind : x.exponent := mines ;

unnormkind, normkind : begin
if x.exponent <= mines then begin (* Underflow.  *)
if underfl in fpstatus.trap then begin (* Trap enabled.  *)
setex ( underfl ) ;
x.exponent := x.exponent + 192 ;
if (  x.exponent <= mines) or (not x.significand[0])
then begin (* Severe underfl.  *)
makenan(nanresult,x) ;
end ;
end
else begin (* Trap disabled.  *)
right( x, mines + 1 - x.exponent ) ;
x.exponent := mines+1 ;
roundkcs( x, fpstatus.mode.round, sprec ) ;
if inxact in fpstatus.curexcep  then setex ( underfl ) ; (* Signal.  *)
end ;
end ;

roundkcs( x, fpstatus.mode.round, sprec ) ;
if (x.exponent >= maxes) and x.significand[0] then begin (* Overflow.  *)
if overfl in fpstatus.trap then begin (* Trap enabled.  *)
setex ( overfl ) ;
x.exponent := x.exponent - 192 ;
if x.exponent >= maxes then begin (* Severe overfl.  *)
makenan(nanresult,x) ;
end ;
end

else begin (* Trap disabled.  *)
setex ( inxact ) ;
setex( overfl ) ;
case fpstatus.mode.round of
rneg : special := not x.sign ;
rpos : special := x.sign ;
rnear : special := false ;
rzero : special := true ;
otherwise 
end ;
if special then begin (* Special case roundings.  *)
x.exponent := maxes - 1 ; (* Round to largest normalized number.  *)
for i := 0 to leastsigbit do x.significand[i] := true ;
end
else begin (* Normal case - set INF.  *)
x.exponent := maxes ;
for i := 0 to leastsigbit do x.significand[i] := false ;
end ;
end
end ;
if  ( (x.exponent=(mines+1)) and (not x.significand[0]))
then
        x.exponent := mines ; (* Look for  denormalized number.  *)

if (abs(kind(x))=nankind) or (  (x.exponent > mines) and (x.exponent < maxes) 
and not x.significand[0] )  then begin 
        (* Invalid Result.  *)
        makenan( nanresult, x ) ;
        setex ( invop ) ;
        fpstatus.curexcep := fpstatus.curexcep - [inxact] ;
        x.exponent := maxes ;
        end ;
        end ;

infkind, nankind : 
        begin (* inf/nan *)
        x.exponent := maxes ;
        for i := 24 to leastsigbit do
                if x.significand[i] then x.significand[23] := true ;
                (* OR together least significant bits of NAN *)
        end   (* inf/nan *) ;
end (* case *);

ibytes (( x.exponent + biases) * 128, y0, y1 ) ;
        (* Pack exponent *)
y[0] := y0 ; y[1] := y1 ;
if x.sign then y[0] := y[0] + 128 ; (* Pack sign.  *)
y[1] := y[1] + xbyte( x, 1, 7 ) ;
for i := 2 to 3 do 
y[i] := xbyte ( x, 8 * i - 8 , 8 * i - 1 ) ; (* Pack significand.  *)

write(' Single format: ') ;
for i := 0 to 3 do begin
bytehex( y[i], s ) ;
write(s[1],s[2], ' ') ;
end ;
writeln ;

unpacksingle( y, x ) ;
end ;

procedure unpackinteger (* y : cint64 ; var x : internal ; itype : inttype *) ;
        
        (* Unpacks integer in y according to itype.
        The significant bytes are presumed to be on the right.  *)
        
var i, msy : integer ;
carry : boolean ;
es : excepset ;

begin
case itype of 
i16 : msy := 6 ;
i32 : msy := 4 ;
i64 : msy := 0 ;
otherwise
end ;
x.sign := y[msy] >= 128 ;
if x.sign then (* Expand negative.  *)
for i := 0 to (msy-1) do y[i] := 255 
else
for i := 0 to (msy-1) do y[i] := 0 ;
for i := 0 to 7 do bytex( y[i], x, 8*i, 8*i+7) ;
if x.sign then begin
carry := false ;
for i:= leastsigbit downto 0 do 
suber( false, x.significand[i], x.significand[i], carry ) ;
end ;
for i := (leastsigbit+1) to stickybit do x.significand[i] := false ;
x.exponent := 64 ;
donormalize(x) ;
if (itype = i64) and (x.exponent = 64) then
        begin (* It was really a NAN *)
        es := fpstatus.curexcep ;
        makenan(naninteger, x) ;
        x.sign := false ; (* Default is a positive NAN.  *)
        fpstatus.curexcep := es ; (* Don't let makenan set NV.  *)
        end   (* It was really a NAN *) ;
end ;

procedure tointeger ( itype : inttype  ; var x : internal ;
var y : cint64  ) ;

        (* Converts x into integer value of type i-type.  *)
        
var
i, imax : integer ;
s : strng ;
carry : boolean ;

procedure i64nan ;
        (* Creates an int64 nan *)
var i : integer ;
begin (* i64nan *)
x.significand[0] := true ;
for i := 1 to stickybit do x.significand[i] := false ;
end   (* i64nan *) ;

begin
case itype of
i16 : imax := 16 ;
i32 : imax := 32 ;
i64 : imax := 64 ;
otherwise
end ;

case abs(kind(x)) of
otherwise ;
unnormkind, normkind : begin
roundint( x, fpstatus.mode.round, xprec) ;
donormalize(x) ;
if kind(x) <> zerokind then begin
if x.exponent < 64 then right( x, 64 - x.exponent ) ;
if x.exponent > 64 then 
        begin
        left ( x, x.exponent - 64 ) ;
        end ;
if (x.exponent >= imax) and (* Exclude case of max negative integer.  *)
((x.exponent <> imax) or (not x.sign) or 
(lastbit(x,leastsigbit-imax+1,leastsigbit) > (leastsigbit-imax+1)))
then begin
x.significand[leastsigbit+1-imax] := false ; (* Turn off bit to allow room
        for sign bit.  *)
setex ( cvtovfl ) ;
end ;
if (itype=i64) and (x.exponent >= imax) then
        begin (* overflowed to nan *)
        i64nan ;
        setex(cvtovfl) ; (* Might not have been set for -2^63.  *)
        end   (* overflowed to nan *) ;
end 
end
 ;

infkind : begin
setex ( cvtovfl  ) ;
if itype = i64 then i64nan else
        begin (* not i64 *)
        for i := leastsigbit downto (leastsigbit - imax + 2 ) 
        do x.significand[i] := true ;
        x.significand[leastsigbit-imax+1] := false ;
        end   (* not i64 *) ;
end ;
nankind : begin
if itype = i64 then i64nan else
        begin (* not i64 *)
        setex ( invop ) ;
        for i := leastsigbit downto (leastsigbit - imax + 2  ) 
        do x.significand[i] := false ;
        x.significand[leastsigbit-imax+1] := true ;
        end   (* not i64 *) ;
end ;

end ;

if x.sign then begin (* Complement.  *)
carry := false ;
for i := leastsigbit downto (leastsigbit - imax + 1) do
suber( false, x.significand[i], x.significand[i], carry ) ;
end ;

for i := 0 to 7 - (imax div 8) do y[i] := 0 ;
for i := (8 - (imax div 8)) to 7 do
y[i] := xbyte( x, leastsigbit - 63 + 8*i, leastsigbit - 56 + 8*i ) ;

write(' Integer format: ') ;
for i := (8 - (imax div 8)) to 7 do  begin
bytehex(y[i],s) ;
write(s[1],s[2],' ') ;
end ;
writeln ;

unpackinteger( y, x, itype ) ;

end ;


End-Of-File
echo Extracting dotest.i
cat >dotest.i <<'End-Of-File'

procedure dotest (* s : strng ; var found : boolean ; x, y : internal  *) ;

var
ztrue, z, r : internal ;
cc : conditioncode ;
ps : pstack ;
error : boolean ;
i, k: integer ;
yi : cint64 ;
ms : fpmodetype ; es, ts : excepset ;

procedure subRR ;

begin
if sequal(s , 'REM') then begin
found := true ;
trem( y, x,  z ) ;
end 
end ;

procedure subS ;

var
xr,yr,zr :real ;

begin
if sequal(s , 'SCALE') then begin
found := true ;


cscale( y, x,  z ) ;

end else if sequal(s , 'SQRT') then begin
found := true ;

tsqrt( x, z) ;

end 
end ;

procedure subT ;

var yi : cint64 ;

begin
if sequal(s , 'TEST') then begin
found := true ;
pretest( storagemode )  ;
end 
else if sequal(s , 'TOF32') then begin (* Convert to single.  *)
found := true ;
tconvert(x,z,flt32) ;
end else if sequal(s , 'TOF32I') then begin (* Convert to single integral.  *)
found := true ;
tintconvert(x,z,flt32) ;
end else if sequal(s , 'TOF64') then begin (* Convert to double.  *)
found := true ;
tconvert(x,z,f64) ;
end else if sequal(s , 'TOF64I') then begin (* Convert to double integral.  *)
found := true ;
tintconvert(x,z,f64) ;
end else  if sequal(s , 'TOX80') then begin (* Convert to extended.  *)
found := true ;
tconvert(x,z,ext80) ;
end else if sequal(s , 'TOX80I') then begin (* Convert to extended integral.  *)
found := true ;
tintconvert(x,z,ext80) ;
end else if sequal(s , 'TOI16') then begin (* Convert to 16 bit integer.  *)
found := true ;
tconvert(x,z,i16) ;
end else if sequal(s , 'TOI32') then begin (* Convert to 32 bit integer.  *)
found := true ;
tconvert(x,z,i32) ;
end else if sequal(s , 'TOI64') then begin (* Convert to 64 bit integer.  *)
found := true ;
tconvert(x,z,i64) ;
end  ;
end ;


begin
writeln(' BEGIN TEST ') ;
makezero(z) ; (* Define default "computed result" for those operations
        that don't return any.  *)
if stack = nil then makezero(ztrue) else ztrue := stack^.x ;
if not sequal(s,'TEST') then begin (* Not ready to do these mode switches until
initialization has been accomplished.  *)

ms := fpstatus.mode ;
swapmode(ms) ;
ts := fpstatus.trap ;
swaptrap(ts) ;
es := fpstatus.excep ;
swapexcep(es) ;
end ;
found := false ;
if length(s) > 0 then case s[1] of

'+' : if length(s)=1 then begin
found := true ;
 
tadd( y, x,  z ) ;

end ;

'-' : if length(s)=1 then begin
found := true ;
 
tsub( y, x,  z ) ;

end ;

'*' : if length(s)=1 then begin
found := true ;
tmul (y, x, z) ;

end ;

'/' : if length(s) = 1 then begin
found := true ;
tdiv ( y, x,  z) ;

end ;
'A' : if sequal(s , 'ABS') then begin
found := true ;
tabs(x,z) ;
end
 ;

'C' : if sequal(s , 'COMPARE') then begin
found := true ;
tcompare( y, x,  cc) ;
write(' Compare result: ') ;
case cc of
lesser : writeln(' < ') ;
equal : writeln(' = ' ) ;
greater : writeln(' > ') ;
notord : writeln(' Unordered ') ;
end ;
for i := 0 to 6 do yi[i] := 0 ;
yi[7] := ord(cc) ;
unpackinteger(yi, z, i16);
end ;

'L' : if sequal(s , 'LOGB') then begin
found := true ;
clogb( x,  z ) ;
end ;

'N' : if sequal(s , 'NEG') then begin (* NEGATE top of stack *)
found := true ;
tneg(x,z) ;
end 
else if sequal(s , 'NEXT') then begin (* Compute NEXTAFTER function.  *)
found := true ;
cnextafter( y, x,  z ) ;

end ;

'R' : subRr ;
'S' : subS ;
'T' : subT ;

otherwise

end ;

if found then writeln( ' Did ',s) ;

if not found then begin (* check for decimal input *)
tdecbin(s, z, error ) ;
if not error then begin
found := true ;

end
end ;
if sequal(s,'TEST') then writeln(' Begin TEST Mode ')
else begin
if  found then begin
tstore(storagemode,z) ;
swapexcep(es) ;
if (es=fpstatus.excep) and (equalinternal(z,ztrue)) then
writeln(' OK! ') 
else 
begin
if es <> fpstatus.excep then
        begin
        write(chr(ordbell),' DIFFERENT FLAGS: ') ;
        displayexcep(es) ;
        writeln ;
        end ;
if not equalinternal( z, ztrue ) then
        begin
        writeln(chr(ordbell),' DIFFERENT RESULT: ') ;
        display(z) ;
        end ;
end ;
tdisplay(z) ;
writeln(' END TEST  ') ;
end
else  writeln(' Command not tested: ',s) ;
end ;
end ;



End-Of-File
echo Extracting hex.i
cat >hex.i <<'End-Of-File'
(* File hex.i, Version 8 October 1984 *)

procedure puthex ( s : strng ; p1, p2 : integer ; 
                var x : internal ; var error : boolean ) ;
                
                (* Interprets s as a hex integer, puts value in bits
                p1..p2 of x.significand.
                Sets Error if any significant bits don't fit in field.  *)

var
i, j : integer ;
nib : nibarray ;

begin
error := false ;
for i := p1 to p2 do x.significand[i] := false ; (* Clear field.  *)
i := p2 + 1 - 4 * length(s) ;
while i < p2 do begin
hexnibble( s[1], nib ) ;
delete ( s, 1, 1 ) ;
for j := 0 to 3 do if nib[j] then begin
if (i+j) < p1 then error := true else x.significand[i+j] := true ;
end ;
i := i + 4 ;
end ;
end ;

procedure intdec ( i : integer ; var s : strng ) ;
        (* converts 16 bit integer to decimal strng *)
var
sign : boolean ;
t : strng ;

begin
if i = 0 then 
	begin
	s[0] := chr(1) ;
	s[1] := '0' ;
	end
	else begin
t[0] := chr(1) ;
s[0] := chr(0) ;
sign := false ;
if i < 0 then if i < -32767 then begin
makeucsdstring(' -32768',s) ; i := 0 end
else begin
sign := true ; i := -i end ;
while i <> 0 do begin
t[1] := chr( ord('0') + i mod 10 ) ;
s := concat ( t, s ) ;
i := i div 10 ;
end ; 
if sign then 
	begin
	t[1] := '-' ;
	s := concat( t, s ) ;
	end ;
end
end ;

procedure subhex ( x : internal ; p1, p2 : integer ; var s: strng ) ;
        (* s receives a strng of hex digits representing the integer in
        x.significand[p1]..x.significand[p2], right justified.  *)
var
j, i : integer ;
nib : nibarray ;

begin
i := p1 ;
while ( i < p2 ) and not x.significand[i] do i := i + 1 ;
        (* Find most significant non-zero bit in field.  *)
if ( i >= p2 ) and not x.significand[p2] then 
	begin
	s[0] := chr(1) ;
	s[1] := '0' ;
	end
	else begin
s[0] := chr(0) ;
i := p2 - 3 - 4 * (( p2 - i ) div 4 ) ;
        (* Start at left end of nibarray containing most significant bit.  *)
while i < p2 do begin
for j := 0 to 3 do 
if (i+j) < p1 then nib[j] := false else nib[j] := x.significand[i+j] ;
concatchar( s, nibblehex(nib)) ;
i := i + 4 ;
end ;
end ;
end ;

procedure tohexint ( x : internal ; var s : strng ) ;

(* if x is an integer less than 2**16,
then s receives the hex digits representing x.
Otherwise s is set to empty. *)

var
i, npoint : integer ;
nib : nibarray ;
integral : boolean ;
t : strng ;

begin
s[0] := chr(0) ;
if kind(x) = zerokind then 
	begin
	s[0] := chr(1) ; s[1] := '0' ;
	end
	else
if (abs(kind(x)) = normkind) and (x.exponent <= 16) and (x.exponent >= 1)
then begin
if zerofield ( x, x.exponent, stickybit ) then begin (* it's all integer *)
subhex ( x, 0, x.exponent - 1, s ) ;
if x.sign then 
	begin
	t[0] := chr(1) ;
	t[1] := '-' ;
	s := concat( t, s ) ;
	end ;
end end
end ;

procedure nanascii ( x : internal ; ishex : boolean ; var s : strng ) ;

        (* Converts an INF or NAN into strng s, using hex for numeric
        field values if ishex is true, and decimal if ishex is false.  *)
        
var t,t1 : strng ;
k : integer ;

begin
case kind(x) of
neginf : makeucsdstring('--',s) ;
infkind : makeucsdstring('++',s) ;
negnan, nankind : begin
makeucsdstring('NaN''',s) ;
if x.sign then 
	begin
	t[1] := '-' ;
	s := concat( t, s ) ;
	end ;
if ishex then 
        begin (* ishex nan *)
        subhex ( x, 1, 15, t ) ;
        if not zerofield(x,16,leastsigbit) then
                begin (* Extra stuff *)
                concatchar(t,':') ; (* Colon delimits extra stuff.  *)
                for k := 4 to 15 do
                        begin (* Add hexit.  *)
                        subhex(x,4*k,4*k+3,t1) ;
                        t := concat(t,t1) ;
                        end   (* Add hexit.  *) ;
                while t[length(t)] = '0' do
                        delete (t,length(t),1) ; (* Clear trailing zeros. *)
                end   (* Extra stuff *) ;
        end   (* ishex nan *)
else
        if zerofield( x, 1, 15 ) then makeucsdstring('0.',t) else
                begin (* Decimal Nan, non zero *)
                subdec ( x, 1, 15, t ) ;
                concatchar(t,'.') ; (* . Distinguishes decimal NAN from hex *)
                end   (* Decimal Nan, non zero *) ;
s := concat ( s, t) ;
concatchar(s, '''') ;
end ;
otherwise
end ;
end ;

procedure binhex (* x : internal ; var s  : strng *)(* forward *)  ;
(* converts x to hex format *)

var
i, j, k : integer ;
nib : nibarray ;
t : strng ;

begin
case abs(kind(x)) of
zerokind : if x.sign then 
	begin
	s[0] := chr(1) ; s[1] := '0' ;
	end 
	else 
	begin
	s[0] := chr(2) ; s[1] := '-' ; s[2] := '0' ;
	end ;

unnormkind, normkind : begin
tohexint(x, s) ;
if length(s) > 0 then 
	begin
	makeucsdstring('H ',t) ; s := concat(s, t) ;
	end
	else 
	begin
s[0] := chr(1) ;
s[1] := '.' ;
for i := 0 to 3 do begin
for j := 0 to 3 do begin
for k := 0 to 3 do
nib[k] := x.significand[k+4*j+16*i] ;
concatchar(s, nibblehex(nib)) ;
end ;
concatchar( s, ' ' ) ;
end ;
nib[0] := x.significand[64] ;
nib[1] := x.significand[65] or x.significand[66] ;
nib[2] := false ;
nib[3] := false ;
concatchar(s, nibblehex(nib)) ;

while( (s[length(s)] = ' ') or( s[length(s)] = '0')) and
(length(s) > 2) do delete(s,length(s),1) ; (* delete trailing 0 and blank *)
makeucsdstring('H ',t) ;
s := concat(s,t) ; 
if x.exponent <> 0 then begin
if x.exponent > 0 then concatchar(s, '+') ;
intdec(x.exponent, t) ;
s := concat(s,t) ;
end ;
if x.sign then 
	begin
	makeucsdstring('- ',t) ;
	s := concat(t,s) ;
	end ;
end end ;

infkind, nankind : nanascii ( x, true, s ) ;

otherwise
end ;
end ;

procedure NANer ( s : strng ; ishex : boolean ;
        var x : internal ; var error : boolean ) ;
        (* Checks for strng in proper INF or NAN format.
        If ishex is true, interprets numeric constants in hex;
        If ishex is false, interprets them in decimal.  *)
var
i, k : integer ;
t, snan : strng ;
nminus, ndot, nplus : integer ;
dset : set of char ;
err : boolean ;

procedure bump ; (* removes first character from strng t *)
begin
delete (t,1,1) 
end ;

begin
error := false ;
t[0] := chr(0) ;
for i := 1 to length(s) do if s[i] <> ' ' then concatchar(t,upcase(s[i])) ;
concatchar(t,'z') ;

nminus := 0 ;  nplus := 0 ;  
for i := 1 to length(t) do case t[i] of
'-' : nminus := nminus + 1 ;
'+' : nplus := nplus + 1 ;
otherwise 
end ;
if (nplus >= 2) and (nplus>=( length(t)-1)) then begin (* plus infinity *)
x.exponent := maxexp ;
makeucsdstring('z ',t) ;
end ;
if (nminus >= 2) and (nminus=( length(t)-1) ) then begin (* minus inf *)
x.exponent := maxexp ;
makeucsdstring('-z',t) ;
end ;
x.sign := t[1]='-' ; (* Check sign *)
if x.sign then bump else if t[1]='+' then bump ;
if (length(t) >= 3) 
 then (* check for NAN *)
if (t[1]='N') and (t[2]='A') and (t[3]='N')  then 
        begin (* Nan processing *)
        bump ; bump ; bump ;
        x.exponent := maxexp ;
        if t[1]='''' then 
                begin (* Process significand string *)
                bump ; (* Remove ' *)
                if ishex then dset := hexset else dset := digitset ;
                snan[0] := chr(0) ;
                while t[1] = '0' do bump ;
                while t[1] in dset do begin (* Accumulate field value. *)
                concatchar( snan, t[1] ) ;
                bump ;
                end ;
                if ishex then 
                puthex( snan, 1, 15, x, error ) 
                else
                putdec( snan, 1, 15, x, error ) ;
                if ishex then 
                        begin (* Extra Hex Processing.  *)
                        if t[1] = ':' then
                                begin (* Extra hex stuff *)
                                bump ;
                                k := 16 ;
                                snan[0] := chr(1) ;
                                snan[1] := ' ' ;
                                while (k <= (leastsigbit-3)) and 
                                                (t[1] in dset) do
                                        begin
                                        snan[1] := t[1] ;
                                        puthex(snan,k,k+3,x,err) ;
                                        k := k + 4 ;
                                        bump ;
                                        end ;
                                end   (* Extra hex stuff *) ;
                        if t[1]='''' then bump ; (* Absorb final delimiter.  *)
                        end   (* Extra Hex Processing.  *) 
                else
                        begin (* Extra Dec Processing *)
                        if t[1]='.' then 
                                begin (* Decimal Point Found *)
                                bump ; (* Absorb decimal point.  *)
                                if t[1]='''' then bump ; 
                                        (* Absorb final delimiter.  *)
                                end   (* Decimal Point Found *) ;
                        end   (* Extra Dec Processing *) ;
                if length(t) > 1 then
                        begin (* Extra characters *)
                        error := true ;
                        while (length(t)>1) and (t[1]<>'''') do bump ;
                        if t[1]='''' then bump ;
                        end   (* Extra characters *) ;
                end   (* Process significand string *) ;
        
        if error or zerofield( x, 1, leastsigbit ) then
                begin
                error := false ;
                makenan(nanascnan,x) ;
                (* NAN  format without significand is invalid. *)
                end ;
        end   (* Nan Processing *);
if length(t) > 1 then 
        begin
        error := true ;
        end ;
end  (* NANer *) ;

procedure hexbin (* s : strng ; var x : internal ; var error : boolean *) ;
(* converts hex strng s to internal format *)
(* error is set true if bad format *)

type
stringclass = (nonnumeric, truezero, nonzero) ; (* types of strng *)

var
class : stringclass ;
i, k,  min : integer ;
sigpoint : integer ;
t, snan : strng ;
esign : boolean ;
nib : nibarray ;
ee : integer ;

procedure bump ; (* removes first character from strng t *)
begin
delete (t,1,1) 
end ;


begin
class := nonnumeric ;
error := false ;
esign := false ;
x.sign := false ;
x.exponent := 0 ;
ee := 0 ;
for i := 0 to stickybit do x.significand[i] := false ;
sigpoint := 0 ;
t[0] := chr(0) ;
for i := 1 to length(s) do if s[i] <> ' ' then concatchar(t,upcase(s[i])) ;
concatchar(t,'!') ; (* this marks the end of the input strng *)

if t[1] = '+' then bump else if t[1] = '-' then begin (* handle negative *)
x.sign := true ;
bump
end ;
while t[1] = '0' do begin
class := truezero ;
bump ; (* delete leading zeros *)
end ;
while t[1] in hexset do begin (* digits before point *)
class := nonzero ;
hexnibble(t[1], nib) ;
if sigpoint <= (stickybit-4) then min := 3 else min := (stickybit-1)-sigpoint ;
for i := 0 to min do x.significand[sigpoint+i] := nib[i] ;
for i := (stickybit-sigpoint) to 3 do x.significand[stickybit] := x.significand[stickybit] or nib[i] ;
x.exponent := x.exponent + 4 ;
if x.significand[0] then begin
if sigpoint <= (stickybit-4) then sigpoint := sigpoint + 4 else sigpoint := stickybit
end else begin (* donormalize *)
donormalize(x) ;
sigpoint := x.exponent ;
end ;
bump
end ;
if t[1] = '.' then begin (* check for point *)
bump ;
while t[1] in hexset do begin (* process digits after point *)
if (t[1] <> '0') or (class = nonzero) then class := nonzero 
else class := truezero ;
hexnibble(t[1], nib) ;
if sigpoint <= (stickybit-4) then min := 3 else min := (stickybit-1)-sigpoint ;
for i := 0 to min do x.significand[sigpoint+i] := nib[i] ;
for i := (stickybit-sigpoint) to 3 do 
x.significand[stickybit] := x.significand[stickybit] or nib[i] ;
if x.significand[0] then begin
if sigpoint <= (stickybit-4) then sigpoint := sigpoint + 4 else 
sigpoint := stickybit
end else if t[1] = '0' then x.exponent := x.exponent - 4 else  
begin (* donormalize *)
sigpoint := x.exponent ;
donormalize(x) ;
sigpoint := 4 + x.exponent - sigpoint ;
end ;
bump ; 
end ;  
end ;
if t[1] = 'H' then bump ; (* handle H for Hex *)
if t[1] = '+' then bump else if t[1]='-' then begin (* exponent sign *)
esign := true ;
bump
end ;
while t[1] in digitset do begin (* exponent digits *)
if ee > ((maxexp - (ord(t[1])-ord('0'))) div 10 ) then begin
error := true ;
ee := maxexp - 1 ;
end else
begin
ee := 10 * ee + ord(t[1]) - ord('0') ;
end ; bump  end ;
if class = truezero then x.exponent := minexp  else begin
if esign then ee := -ee ;
if (x.exponent >= 0 ) and (ee > 0 ) then if x.exponent >= (maxexp - ee)
then begin
error := true ;
x.exponent := maxexp - 1 ;
end ;
if (x.exponent < 0) and ( ee < 0 ) then if x.exponent <= (minexp - ee) 
then begin
error := true ;
x.exponent := minexp + 1 ;
end ;
if not error then x.exponent := x.exponent + ee ;
end ;
if class = nonnumeric  then 
        (* the following code checks for INFs and NANs *)
NANer ( s, true, x, error ) 
else
if ( length(t) > 1) then error := true  ;
if error then 
        begin (* Erroneous input *)
        makenan(nanascbin,x) ;
        end
end ;



End-Of-File
echo ""
echo "End of Kit"
exit

sources-request@panda.UUCP (09/04/85)

Mod.sources:  Volume 3, Issue 8
Submitted by: decvax!decwrl!sun!dgh!dgh (David Hough)

#! /bin/sh
: make a directory, cd to it, and run this through sh
echo If this kit is complete, "End of Kit" will echo at the end
echo Extracting forward.i
cat >forward.i <<'End-Of-File'
(* File forward.i, Version 8 October 1984.  *)

                        (* FORWARDs for CALC   *)
                        
procedure adder ( x, y : boolean ; var z : boolean ; var carry : boolean ) ;
forward ;
procedure suber ( x, y : boolean ; var z : boolean ; var carry : boolean ) ;
forward ;

procedure bindec ( x : internal ; var s : strng ) ;
forward ;

procedure binhex ( x : internal ; var s : strng ) ;
forward ;

procedure compare ( x, y : internal ; var cc : conditioncode ) ;
forward ;

procedure add ( x, y : internal ; var z : internal ) ; forward ;

procedure decbin ( s : strng ; var x : internal ; var error : boolean ) ;
forward ;

procedure hexbin ( s : strng ; var x : internal ; var error : boolean ) ;
forward ;

procedure putdec ( s : strng ; p1, p2 : integer ; var x : internal ;
                        var error : boolean ) ;
forward ;

procedure subdec ( x : internal ; p1, p2 : integer ; var s : strng ) ;
forward ;

function nibblehex ( n : nibarray ) : char ;
forward ;

procedure setex ( e : xcpn ) ; forward ;

function zerofield ( x : internal ; p1, p2 : integer ) : boolean ;
forward ;

function firstbit ( x : internal ; p1, p2 : integer ) : integer ;
forward ;

function lastbit ( x : internal ; p1, p2 : integer ) : integer ;
forward ;

function kind ( x : internal ) : integer ;
forward ;

procedure makezero ( var x : internal ) ;
forward ;

procedure makeinf ( var x : internal ) ;
forward ;

procedure makenan ( n : integer ; var x : internal ) ;
forward ;

function unzero ( x : internal ) : boolean ;
forward ;

procedure donormalize ( var x : internal ) ;
forward ;

procedure right ( var x: internal ; n : integer ) ;
forward ;

procedure left ( var x : internal ; n : integer ) ;
forward ;

procedure roundkcs ( var x: internal ; r : roundtype ; p : extprec ) ;
forward ;

procedure picknan ( x, y : internal ; var z : internal ) ;
forward ;

procedure roundint ( var x : internal ; r : roundtype ; p : extprec ) ;
forward ;

procedure unpackinteger ( y : cint64 ; var x : internal ; itype : inttype ) ;
forward ;

procedure store ( var x : internal ) ;
forward ;

procedure display ( x : internal ) ; forward ;

procedure popstack ( var x : internal ) ; forward ;

procedure pushstack ( x : internal ) ; forward ;

procedure dotest ( s : strng ; var found : boolean ; x, y : internal ) ;
forward ;


End-Of-File
echo Extracting function.i
cat >function.i <<'End-Of-File'
(* File Calc:Function, Version 24 May 1984.    *)

procedure compare (* x, y : internal ; var cc : conditioncode *) ;

        (* computes X comp Y and returns result cc *)


procedure docomp ;
        (* does bitwise X comp Y and returns result in cc *)
        (* Works like -INF < -NORM < -0 < +0 < +NORM < +INF
        so don't use to compare two zeros or to compare with INF
        in proj mode *)
        
var i : integer ;

begin
cc := equal ;
if x.sign <> y.sign then
if x.sign then cc := lesser else cc := greater 
else begin (* same signs *)
if x.exponent < y.exponent then cc := lesser 
else if x.exponent > y.exponent then cc := greater
else begin (* same sign and same exponent *)
i := 0 ;
while ( i < stickybit) and (x.significand[i]=y.significand[i]) do i := i + 1 ;
if i <> stickybit then 
if x.significand[i] then cc := greater else cc := lesser ;
end ;
if x.sign then case cc of (* if negative numbers, reverse conclusion *)
lesser : cc := greater ;
greater : cc := lesser ;
end ;
end ;
end ;

begin (* compare *)
roundkcs ( x, fpstatus.mode.round, xprec ) ; (* Preround; ignore inxact. *)
donormalize(x) ;
roundkcs (y, fpstatus.mode.round, xprec ) ; (* Preround; ignore inxact. *)
donormalize(y) ;
fpstatus.curexcep := fpstatus.curexcep - [inxact] ; (* Ignore.  *)
case abs(kind(x)) of

zerokind: case abs(kind(y)) of
zerokind : cc := equal ;
normkind : docomp ;
infkind : if fpstatus.mode.clos = proj then cc := notord
else docomp ;
nankind : cc := notord ;
end ;

normkind : case abs(kind(y)) of
zerokind , normkind : docomp ;
infkind : if fpstatus.mode.clos = proj then cc := notord
else docomp ;
nankind : cc := notord ;
end ;

infkind : case abs(kind(y)) of
zerokind, normkind : if fpstatus.mode.clos = proj then
        cc := notord else docomp ;
infkind : if fpstatus.mode.clos = proj then cc := equal
else docomp ;
nankind : cc := notord ;
end ;

nankind : cc := notord ;
end ;

end ;

procedure add (* x, y : internal ; var z : internal  *) ;

        (* Does z := x + y  *)
        
procedure doadd ;

        (* Does true add z := x + y
        Neither x nor y should be INF or NAN
        x and y should not both be true zero.  *)
        
var
carry : boolean ;
i : integer ;
shiftcount : integer ;

begin
roundkcs( x, fpstatus.mode.round, xprec) ; (* Pre-round.  *)
roundkcs( y, fpstatus.mode.round, xprec) ;

z.sign := x.sign ;

if x.exponent >= y.exponent then begin (* Align smaller operand.  *)
z.exponent := x.exponent ;
shiftcount := x.exponent - y.exponent ;
if shiftcount < 0 then shiftcount := maxexp ;
right( y, shiftcount ) ;
end
else begin
z.exponent := y.exponent ;
shiftcount := y.exponent - x.exponent ;
if shiftcount < 0 then shiftcount := maxexp ;
right( x, shiftcount ) ;
end ;

carry := false ;
for i := stickybit downto 0 do
adder( x.significand[i], y.significand[i], z.significand[i], carry ) ;

if carry then begin (* Renormalize for carry out.  *)
right( z, 1 ) ;
z.significand[0] := true ;
z.exponent := z.exponent + 1 ;
end ;

end ;

procedure dosub ; 

        (* Does true subtract z := x - y,
        neither of which should be INF or NAN,
        only one of which should be true zero.  *)
        
var
carry : boolean ;
shiftcount, i : integer ;
postnorm : boolean ;
rnd : roundtype ;
redo : boolean ;
xur, yur : internal ; (* Save x and y unrounded operands.  *)

begin
        (* Proper preround is ambiguous in the case when the indicated
        rounding mode is RZ and a true subtract is required.
        x and y should be rounded RM if the result is positive,
        RP if the result is negative.
        Occasionally the result comes out reversed and the operands
        have to be re-pre-rounded.
        All this makes a good argument for not having pre-rounding or at
        least fudging this one annoying case.  *)
        
y.sign := not y.sign ; (* Reverse sign of y so x and y have same signs.  *)
xur := x ; yur := y ; (* Save unrounded operands.  *)
redo := false ; (* Set true if we go through loop twice.  *)

repeat
x := xur ; y := yur ; (* Restore unrounded state.  *)
rnd := fpstatus.mode.round ; (* This is almost always appropriate.  *)

if x.exponent >= y.exponent then begin
z.sign := x.sign ;
z.exponent := x.exponent ;
if rnd = rzero then begin
if x.sign <> redo then rnd := rpos else rnd := rneg end  ;
roundkcs ( x, rnd, xprec ) ;
roundkcs ( y, rnd, xprec ) ;
shiftcount := x.exponent - y.exponent ;
if shiftcount < 0 then shiftcount := maxexp ;
right ( y, shiftcount ) ;
end
else begin
z.sign := not y.sign ;
z.exponent := y.exponent ;
if rnd = rzero then begin  (*  Bad case.  *)
if y.sign <> redo then rnd := rpos else rnd := rneg end  ;
roundkcs( x, rnd, xprec ) ;
roundkcs( y, rnd, xprec ) ;
shiftcount := y.exponent - x.exponent ;
if shiftcount < 0 then shiftcount := maxexp ;
right ( x, shiftcount ) ;
end ;

postnorm := x.significand[0] or y.significand[0] ;
        (* Post normalization occurs if larger operand is normalized.  *)

carry := false ;
if z.sign = x.sign then for i := stickybit downto 0 do
suber( x.significand[i], y.significand[i], z.significand[i], carry ) 
else for i := stickybit downto 0 do 
suber( y.significand[i], x.significand[i], z.significand[i], carry ) ;

if carry then begin (* Sign reversal.  *)
z.sign := not z.sign ;
carry := true ; (* For end-around carry.  *)
for i := stickybit downto 0 do
adder( not z.significand[i], false, z.significand[i], carry ) ; 
(* Complement.  *)
redo := fpstatus.mode.round = rzero ; (* Pre-round was inappropriate.  *)
if redo then writeln(' RE-PRE-ROUND required for SUBTRACT.  ') ;
end ;

until not redo ;

if postnorm then donormalize(z) ; (* Do renormalization.  *)

store(z) ; (* Force round to storage mode to determine if the result will
                be zero; if so, special sign rules apply.  *)
if zerofield( z, 0, leastsigbit )  then (* Correct sign for zero result.  *)
z.sign := fpstatus.mode.round = rneg ;  (* Which is +0 except in RM mode.  *)

end ;

begin (* add *)
if (abs(kind(x))=nankind) or (abs(kind(y))=nankind) then
picknan( x, y, z) else

case abs(kind(x)) of

zerokind : case abs(kind(y)) of

zerokind : begin (* +-0 + +-0 *)
z := x ;
if x.sign <> y.sign then z.sign := fpstatus.mode.round = rneg ;
        (* +0 + -0 usually has sign +0 except in RM mode.  *)
end ;
unnormkind, normkind : if x.sign = y.sign then doadd else dosub ;
infkind : z := y ;
end ;

unnormkind, normkind : if abs(kind(y)) = infkind then z := y else
if x.sign = y.sign then doadd else dosub ;

infkind : if abs(kind(y)) <> infkind then z := x else (* INF +- INF *)
if (fpstatus.mode.clos = proj) or (x.sign <> y.sign) 
then makenan ( nanadd, z )
else z := x ;

end ;

end ;

procedure multiply (x , y : internal ; var z : internal  ) ;
        
        (* routine to multiply two internal numbers and return z := x*y
        with curexcep  containing flags set. *)
        
var dorout : boolean ;

procedure domult ; 

        (* does the multiply of z := abs(x) * abs(y) *)
        
var
i, j, j0, n0, n1  : integer ;
carry : boolean ;
r : roundtype ;
xlast, ylast : integer ;
xfirst, yfirst : integer ;

                (* The following subprocedures do various cases of
                multiply substeps.  Based on Booth algorithm ideas.  *)

procedure don0 ;

        (* Multiplies z by n0 zeros, i. e. right shifts n0 times,
        and resets n0.  *)
        
var i : integer ;

begin
z.significand[stickybit] := not zerofield ( z, stickybit-n0, stickybit ) ;
                (* Shift bits into stickybit.  *)
for i := (stickybit-1) downto n0 do
z.significand[i] := z.significand[i-n0] ; (* Really shift bits.  *)
for i := (n0-1) downto 0 do
z.significand[i] := false ; (* Shift in zeros at left.  *)
n0 := 0 ;
end ;

procedure do11 ;

        (* Does add y and shift to z.  *)
        
var
j : integer ;
carry : boolean ;

begin
if z.significand[stickybit-1] then z.significand[stickybit] := true ;
for j := (stickybit-1) downto (ylast+2) do  (* These bits only shift.  *)
z.significand[j] := z.significand[j-1] ;
carry := false ;
for j := (ylast+1) downto (yfirst+1) do
adder( z.significand[j-1], y.significand[j-1], z.significand[j], carry ) ;
z.significand[yfirst] := carry ;
end ;

procedure do21 ;

        (* Does twice:  add y and shift z.  *)
        
begin
do11 ; do11 ;
end ;

procedure don1 ;

        (* Does n1 times: add y and shift z, by
        1) subtract y
        2) shift z n1 times
        3) add 2*y
                                        *)
                                        
var
j, j0 : integer ;
carry : boolean ;

begin
if n1=1 then do11 else if n1=2 then do21 else begin
                        (* Do subtract.  *)
carry := false ;
for j := (ylast) downto (yfirst) do
suber( z.significand[j], y.significand[j], z.significand[j], carry ) ;
for j := (yfirst-1) downto 0 do (* Ripple carry.  *)
z.significand[j] := true ;
                        (* Do shift.  *)
z.significand[stickybit] := not zerofield( z, stickybit-n1, stickybit ) ;
for j := (stickybit-1) downto n1 do
z.significand[j] := z.significand[j-n1] ;
for j := (n1-1) downto 0 do 
z.significand[j] := true  ;
                        (* Do add 2*y.  *)
carry := false ;
for j := ylast downto yfirst do
adder( z.significand[j], y.significand[j], z.significand[j], carry ) ;
end ;
for j := (yfirst-1) downto 0 do
z.significand[j] := false ;
n1 := 0 ;
end ;

begin
        (* Preround. *)
dorout := false ;
case fpstatus.mode.round of
rnear, rzero : r := fpstatus.mode.round ;
rneg : if x.sign = y.sign then r := rzero else dorout := true ;
rpos : if x.sign = y.sign then dorout := true   else r := rzero ;
end ;
if dorout then
        begin (* round out *)
        if x.sign then roundkcs( x, rneg, xprec ) else roundkcs( x, rpos, xprec ) ;
        if y.sign then roundkcs( y, rneg, xprec ) else roundkcs( y, rpos, xprec ) ;
        end   (* round out *) 
        else
        begin 
        roundkcs( x, r, xprec ) ;
        roundkcs( y, r, xprec ) ;
        end ;

xfirst := firstbit( x, 0, leastsigbit) ;
yfirst := firstbit( y, 0, leastsigbit ) ;
if xfirst <= leastsigbit then
xlast := lastbit( x, xfirst, leastsigbit) else xlast := -1 ;
if yfirst <= leastsigbit then
ylast := lastbit( y, yfirst, leastsigbit) else ylast := -1 ;

if (xfirst > xlast) or (yfirst > ylast)  then begin 
(* z is unnormalized zero.  *)
makezero(z) ;
z.exponent := x.exponent + y.exponent - 1 ;
end

else begin (* Both operands are non-zero.  *)

z.exponent := x.exponent + y.exponent ;
for i := 0 to stickybit do z.significand[i] := false ;
n1 := 0 ; n0 := 0 ;
for i := xlast downto xfirst do  (* for each bit of x *)
if x.significand[i] then 
begin
        (* Encounter One.  *)
if n0 > 0 then begin
don0 ;
n1 := 1 ;
end 
else n1 := n1 + 1
end

else begin
        (* Encounter Zero.  *)
if n1 > 0 then begin
don1 ;
n0 := 1 ;
end
else n0 := n0 + 1
end ;

if n1 > 0 then don1 ; (* Tidy up at end.  *)
n0 := n0 + xfirst ; 
(* Additional right shifts necessary if x not normalized.  *)
if n0 > 0 then don0 ;

if not z.significand[0] then begin (* Do one donormalize cycle *)
z.exponent := z.exponent - 1 ;
left(z, 1 ) ;
end ;
end ;
if (x.exponent < 0) and (y.exponent < 0) and (z.exponent > 0) then begin
        (* Gross underfl has caused integer overfl leading to large
        positive exponent.  *)
right(z,stickybit) ;
z.exponent := minexp ;
setex(underfl) ;
end ;
end ;

begin
if (abs(kind(x))=nankind) or (abs(kind(y))=nankind) then picknan(x,y,z) else
case abs(kind(x)) of
zerokind : case abs(kind(y)) of
zerokind, unnormkind,  normkind : z := x ;
infkind : makenan(nanmul, z) ;
end ;

unnormkind : case abs(kind(y)) of
zerokind: z := y ;
unnormkind, normkind : domult ;
infkind : if unzero(y) then makenan( nanmul, z) else z := y ;
end ;

normkind : case abs(kind(y)) of
zerokind : z := y ;
unnormkind, normkind : domult ;
infkind : z := y ;
end ;

infkind : case abs(kind(y)) of
zerokind : makenan( nanmul, z ) ;
unnormkind : if unzero(y) then makenan(nanmul, z) else z := x ;
normkind , infkind : z := x ;
end ;
end ;

z.sign := (x.sign <> y.sign) ; (* exclusive OR signs *)

end ;

procedure divide ( x, y : internal ; var z : internal  ) ;

        (* Does extended internal divide z := x/y *)
        

procedure divbyzero ; (* for invalid divide exception *)
begin
makezero(z) ;
z.exponent := maxexp ; (* Make Infinity result *)
setex( div0 ) ;
end ;

procedure dodiv ; 

        (* carries out divide of x by normalized y *)
        (* x should be nonzero and finite *)
        (* signs are ignored *)
        
var
i,j : integer ;
carry, sbit, tbit : boolean ;
r : internal ;
rx, ry : roundtype ;
rlast, ylast  : integer ;
xrout, yrout : boolean ;

begin
        (* Preround. *)
xrout := false ; yrout := false ;
case fpstatus.mode.round of
rnear : begin
rx := rnear ;
ry := rnear ;
end ;
rzero : begin
rx := rzero ;
yrout := true ;
end ;
rneg : if x.sign = y.sign then begin
rx := rzero ;
yrout := true ;
end
else begin
xrout := true ;
ry := rzero ;
end ;
rpos: if x.sign = y.sign then begin
xrout := true ;
ry := rzero ;
end
else begin
rx := rzero ;
yrout := true ;
end ;
end ;
if xrout then 
        begin
        if x.sign then roundkcs( x, rneg, xprec ) else roundkcs ( x, rpos, xprec )
        end
        else roundkcs( x, rx, xprec) ;
if yrout then begin
        if y.sign then roundkcs( y, rneg, xprec ) else roundkcs ( y, rpos, xprec )
        end
else roundkcs( y, ry, xprec) ;

ylast := lastbit ( y, 0, leastsigbit ) ;
rlast := lastbit ( x, 0, leastsigbit ) + 1 ;
if rlast < (ylast+1) then rlast := ylast + 1  ;

for i := 0 to (rlast-1) do 
r.significand[i+1] := x.significand[i] ; (* remainder R := X/2 *)
r.significand[0] := false ;
z.exponent := x.exponent - y.exponent + 1 ;
sbit := false ; (* Sbit contains the sign of the remainder between steps *)

for i := 0 to (stickybit-1) do begin (* for each bit of result *)
tbit := sbit ; (* T bit holds test to decide + or -.  *)
sbit := r.significand[ylast+1] ;
for j := (ylast+1) to (rlast-1) do
r.significand[j] := r.significand[j+1] ;
carry := false ;

if tbit then begin (* If R < 0 then R := 2 * (R+Y) *)
for j := ylast downto 0 do begin
adder(sbit, y.significand[j], tbit, carry) ;
sbit := r.significand[j] ;
r.significand[j] := tbit ;
end ;
adder( sbit, false, sbit, carry) ; (* Sbit now has the sign of R *)
end
else begin (* If R >= 0 then R := 2 * (R-Y) *)
for j := ylast  downto 0 do begin
suber(sbit, y.significand[j], tbit, carry) ;
sbit := r.significand[j] ;
r.significand[j] := tbit ;
end ;
suber(sbit, false, sbit, carry) ; (* Sbit now has the sign of R *)
end ;
r.significand[rlast] := false ; (* result of left shift *)
z.significand[i] := not sbit ; (* Result bit for this step *)
end ;

(* Next check for sticky bit.  Result Z is exact iff
        R = 0 or R <= -2Y  *)
        
z.significand[stickybit] := true ; (* Result is almost always inexact *)
if sbit then begin (* R < 0 so compute R + 2Y *)
carry := false ;
for j := rlast downto 0 do
adder(r.significand[j], y.significand[j], r.significand[j], carry) ;
z.significand[stickybit] :=  carry ; (* If no carry then R+2Y < 0 *)
end ;
if z.significand[stickybit] then begin (* check if R >=0 or R+2Y >= 0 *)
(* R >= 0 ; Is R = 0 ? *)
z.significand[stickybit] := not zerofield ( r, 0, rlast )  ;
end ;


if not z.significand[0] then begin (* normalize once *)
z.exponent := z.exponent - 1 ;
for i := 1 to stickybit do z.significand[i-1] := z.significand[i] ;
end ;

if (x.exponent < 0) and (y.exponent < 0) and (z.exponent > 0) then begin
        (* Gross underfl has caused integer overfl leading to large
        positive exponent.  *)
right(z,stickybit) ;
z.exponent := minexp ;
setex(underfl) ;
end ;
end ;



begin (* divide *)
case abs(kind(x)) of

zerokind: case abs(kind(y)) of
zerokind: makenan( nandiv, z) ;
unnormkind: if unzero(y) then makenan(nandiv, z) else z := x ;
normkind, infkind : z := x ;
nankind : z := y ;
end ;

unnormkind : case abs(kind(y)) of
zerokind : if unzero(x) then makenan(nandiv, z) else divbyzero ;
unnormkind : makenan( nandiv, z) ;
normkind :  dodiv ;
infkind : makezero(z) ;
nankind : z := y ;
end ;

normkind : case abs(kind(y)) of
zerokind : divbyzero ;
unnormkind : makenan(nandiv,z) ;
normkind : dodiv ;
infkind : makezero(z) ;
nankind : z := y ;
end ;

infkind : case abs(kind(y)) of
zerokind, unnormkind, normkind : z := x ;
infkind : makenan(nandiv,z) ;
nankind : z := y ;
end ;

nankind : picknan( x, y, z) ;
end ;

z.sign := x.sign <> y.sign ; (* Do Exclusive Or *)
end ;


End-Of-File
echo Extracting global.i
cat >global.i <<'End-Of-File'
(* File Calc:Global, Version 24 May 1984.     *)

(* global constant, type, and variable declarations for  calc *)

const
leastsigbit = 63 ; 
(* Position of least significant bit in external extended.  *)

maxexp  = 32767 ; (* 2**15-1, maximum internal exponent *)
(* used for INF and NAN *)
minexp  = -maxexp ;
(* -2**15+1, minimum internal exponent, used for zero *)

biasex = 16383 ; (* Extended exponent bias.  *)
maxex = 16384 ; (* Extended maximum unbiased exponent.  *)
minex = -16383 ; (* Extended minimum unbiased exponent.  *)

biased = 1022 ; (* Double exponent bias.  *)
maxed = 1025 ; (* Double maximum unbiased exponent.  *)
mined = -1022 ; (* Double minimum unbiased exponent.  *)

biases = 126 ; (* Single exponent bias.  *)
maxes = 129 ; (* Single maximum unbiased exponent.  *)
mines = -126 ; (* Single minimum unbiased exponent.  *)

zerokind = 0 ; (* KIND of zero *)
unnormkind = 1 ; (* KIND of denormalized or unnormalized *)
normkind = 2 ; (* KIND of normalized number *)
infkind = 3 ; (* KIND of infinity *)
nankind = 4 ; (* KIND of NAN *)
negunnorm = -1 ; 
negnorm = -2 ;
neginf = -3 ;
negnan = -4 ;

ordbell = 7 ; (* ASCII code for Bell.  *)

nanfields = 4 ; (* Number of fields in NAN significand.  *)
{
notord = unord ;
}
nansqrt = 1 ;
nanadd = 2 ;
nanint = 3 ;
nandiv = 4 ;
nantrap = 5 ;
nanunord = 6 ;
nanproj = 7 ;
nanmul = 8 ;
nanrem = 9 ;
nanresult = 12 ;
nanascbin = 17 ;
nanascnan = 18 ;
naninteger = 20 ;
nanzero = 21 ;

type

strng = fpstring ; (* Standard string type.  *)

inttype = i16 .. i64 ; (* Types of integer operands.  *)

sxinternal = record (* Special signless single extended internal format.  *)
        exponent : integer ;
        significand : array[0..1] of integer ;
        end ;

pstack = ^ stacktype ;

stacktype = record (* item on stack *)
x : internal ;
next : pstack ;
end ;

nibarray = array[0..3] of boolean ;

var
fpstatus : fpstype ; (* current status *)
storagemode : arithtype ; (* current storage mode *)
        (* Each operand is rounded to this mode after operation.  *)
testflag : boolean ; (* True if DOTEST is to be called.  *)
stack : pstack  ;
digitset, hexset : set of char ;

tensmall : array [ 0 .. 31 ] of internal ; (* Table of small powers of ten *)
tenbig : array [ 0 .. 31 ] of internal ; (* Table of big powers of ten *)
pi, e : internal ; (* Familiar constants.  *)

leftnan, rightnan : array [ 1 .. nanfields ] of 0 .. stickybit ; 
        (* Indexes of bitfield boundaries for NAN significands.  *)

xcpnname : array [ exception                               ] of
        packed array [1..2] of char ;
        (* Two character codes for exceptions.  *)


End-Of-File
echo Extracting addsubpas.i
cat >addsubpas.i <<'End-Of-File'
procedure adder (* x, y : boolean ; var z : boolean ; var carry : boolean *);

        (* computes boolean z := x + y with carry in and out *)
        
        
begin
z := carry ;
carry := z and x ;
z := ( z <> x ) ;
if carry then z := y else begin
carry := (z and y) ;
z := (z <> y) ;
end ;
end ;

procedure suber (* x, y : boolean ; var z : boolean ; var carry : boolean *) ;


        (* computes boolean z := x - y with carry in and out *)

begin
z := y <> carry ;
carry := carry and y ;
if carry then z := x else begin
carry := (z and (not x)) ;
z := (z <> x) ;
end ;
end ;
End-Of-File
echo Extracting divrem.i
cat >divrem.i <<'End-Of-File'
(* File Calc:Divrem, Version 19 February 1982.  *)

procedure divrem ( x, y : internal ; var q, r : internal  ) ;

        (* Computes q := x DIV y and r := x REM y.  *)

procedure dodivrem ;

        (* Computes DIV and REM for normalized y and normalized or
        unnormalized x.  *)
        
var
i,j : integer ;
carry, sbit, tbit, zbit : boolean ;
rlast, ylast  : integer ;
nc : integer ;
roundup : boolean ;

begin
        (* Preround. *)
roundkcs( x, fpstatus.mode.round, xprec) ;
roundkcs( y, fpstatus.mode.round, xprec) ;
makezero(q) ; (* Starting assumption.  *)
r := x ; (* Starting assumption.  *)
nc := x.exponent - y.exponent + 1 ; (* Number of cycles to produce result. *)
if nc >= 0 then begin
ylast := lastbit ( y, 0, leastsigbit ) ;
rlast := lastbit ( x, 0, leastsigbit ) + 1 ;
if rlast < (ylast+1) then rlast := ylast + 1  ;

for i := 0 to (rlast-1) do 
r.significand[i+1] := x.significand[i] ; (* remainder R := X/2 *)
r.significand[0] := false ;
sbit := false ; (* Sbit contains the sign of the remainder between steps *)

for i := 1 to nc do begin (* for each bit of result *)
tbit := sbit ; (* T bit holds test to decide + or -.  *)
sbit := r.significand[ylast+1] ;
for j := (ylast+1) to (rlast-1) do
r.significand[j] := r.significand[j+1] ;
carry := false ;

if tbit then begin (* If R < 0 then R := 2R+Y *)
for j := ylast downto 0 do begin
adder(sbit, y.significand[j], tbit, carry) ;
sbit := r.significand[j] ;
r.significand[j] := tbit ;
end ;
adder( sbit, false, sbit, carry) ; (* Sbit now has the sign of R *)
end
else begin (* If R >= 0 then R := 2R-Y *)
for j := ylast  downto 0 do begin
suber(sbit, y.significand[j], tbit, carry) ;
sbit := r.significand[j] ;
r.significand[j] := tbit ;
end ;
suber(sbit, false, sbit, carry) ; (* Sbit now has the sign of R *)
end ;
r.significand[rlast] := false ; (* result of left shift *)
if (leastsigbit-nc+i) >= 0 then 
q.significand[leastsigbit-nc+i] := not sbit ;
end ;

r.exponent := r.exponent - nc + 1  ; 
for i := 0 to (leastsigbit-nc) do 
q.significand[i] := false ;  (* Fill in bits.  *)
carry := false ;
if sbit then (* R < 0 so set R := R + Y.  *)
for j := rlast downto 0 do
adder(r.significand[j], y.significand[j], r.significand[j], carry ) ;
if  zerofield( r, 0, rlast) then
        (* R=0 so q is exact and r is zero.  *)
        makezero(r) 
        else begin (* At this point
        2R < Y implies q is ok
        2R = Y implies round q to even and set r to +- .5 Y
        Y < 2R < 2Y implies round q upward, set r to r-y.  *)
roundup := false ; (* Roundup controls rounding of q, and thus r.  *)
carry := false ;
zbit := false ;
for j := rlast downto 1 do begin (* Compute sign of 2R - Y .*)
suber(r.significand[j], y.significand[j-1], tbit, carry ) ;
zbit := zbit or tbit ;
end ;
suber(r.significand[0], false, tbit, carry ) ;
zbit := zbit or tbit ; (* zbit is false if 2R = Y.  *)
if not carry then begin (* 2R >= Y.  *)
roundup := zbit (* 2R>Y *) or q.significand[leastsigbit] (* 2R=Y *) ;
end ;
if roundup then begin (* Increment q; reverse r.  *)
carry := true ;
for j := leastsigbit downto 0 do
adder(q.significand[j], false, q.significand[j], carry) ;
carry := false ;
for j := (leastsigbit+1) downto 0 do
suber( y.significand[j], r.significand[j], r.significand[j], carry ) ;
        (* R := Y - R.  *)
r.sign := not r.sign ;
end end ;
donormalize(r) ;
q.exponent := 64 ;
donormalize(q) ;
end ;
end ;

begin (* divrem *)

if (abs(kind(x))=nankind) or (abs(kind(y))=nankind) then begin
picknan( x, y, q ) ;
r := q ;
end 
else 
        begin (* no nan *)
        donormalize(x) ; (* Rem always normalizes x. *)
        case abs(kind(y)) of

zerokind, unnormkind : begin
makenan( nanrem, q ) ;
r := q ;
end ;

normkind : case abs(kind(x)) of
zerokind : begin
makezero(q) ;
r := x ;
end ;
unnormkind, normkind : dodivrem ;
infkind : begin
q := x ;
makenan( nanrem, r) ;
end ;
end ;

infkind : case abs(kind(x)) of
;zerokind, normkind : begin
makezero(q) ;
r := x ;
end ;
infkind : begin
q := x ;
makenan( nanrem, r) ;
end end end ;
        end   (* not nan *) ;
q.sign := x.sign <> y.sign ; (* EXOR. *)
end ;


End-Of-File
echo ""
echo "End of Kit"
exit