IEEE Calculator (part 6 of 6)

sources-request at panda.UUCP sources-request at panda.UUCP
Wed Sep 4 22:37:10 AEST 1985


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



More information about the Mod.sources mailing list