Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site seismo.CSS.GOV Posting-Version: version B 2.10.2 9/3/84; site panda.UUCP Path: seismo!harvard!talcott!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: IEEE Calculator (part 5 of 6) Message-ID: <864@panda.UUCP> Date: 4 Sep 85 02:12:50 GMT Sender: jpn@panda.UUCP Lines: 1609 Approved: jpn@panda.UUCP 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