DIRECTORY Basics: TYPE USING [LongMult, LongNumber], PrincOpsUtils: TYPE USING [BITAND, BITOR, BITSHIFT, BITXOR], Real: FROM "IeeeFloat" USING [ Exception, ExceptionFlags, Extended, MinusInfinity, MinusZero, Mode, NoExceptions, NumberType, PlusInfinity, PlusZero, TrapNonTrappingNaN, TrapTrappingNaN]; IeeePack: PROGRAM IMPORTS Basics, PrincOpsUtils EXPORTS Real = { OPEN Basics, PrincOpsUtils, Real; RealException: PUBLIC SIGNAL [flags: ExceptionFlags] = CODE; Details: TYPE = MACHINE DEPENDENT RECORD [ sign: BOOL, sticky: BOOL, blank: [0..7777b], type: Real.NumberType]; Ext: TYPE = RECORD [ det: Details, exp: INTEGER, frac: LongNumber]; HiBit: CARDINAL = 100000b; ExponentBias: INTEGER = 127; ExponentMask: INTEGER = 077600b; ExponentShift: INTEGER = 7; HiFractionMask: INTEGER = 177b; FractionShift: INTEGER = 8; LeastSignificandBit: INTEGER = 0400b; HiddenBit: CARDINAL = 100000b; StickyBits: CARDINAL = 77b; HalfLC: LONG CARDINAL = 20000000000b; SignBit: CARDINAL = 100000b; ExpSingleMax: INTEGER = 127; ExpSingleMin: INTEGER = -126; DenormalizedExponent: INTEGER = -127; NaNExponent: INTEGER = 128; BiasAdjust: INTEGER = 192; fpmode: Mode = [nm: warning, round: rn]; enableFlags: ExceptionFlags = [invalidOperation: TRUE, divisionByZero: TRUE, overflow: TRUE]; thisTimeExceptions: ExceptionFlags; LN: PROC [r: LONG UNSPECIFIED] RETURNS [LongNumber] = INLINE { RETURN[LOOPHOLE[r, LongNumber]]}; BitOn: PROC [a, b: UNSPECIFIED] RETURNS [BOOL] = INLINE { RETURN[BITAND[a, b]#0]}; Normalized: PROC [g: INTEGER] RETURNS [BOOL] = INLINE { RETURN [BITAND[g, HiddenBit]#0]}; ADC3: PROC [a, b, c: CARDINAL] RETURNS [CARDINAL, CARDINAL] = INLINE { s: LongNumber; s.lc _ LONG[a]+LONG[b]+LONG[c]; RETURN[s.highbits, s.lowbits]}; PowTen: TYPE = RECORD [ f: LONG CARDINAL, e: INTEGER]; TenTable: TYPE = RECORD [ tens: ARRAY [0..13] OF PowTen, t26, t39: PowTen]; posTable: TenTable = [ tens: [ [ 20000000000b, 0], [ 24000000000b, 3], [ 31000000000b, 6], [ 37200000000b, 9], [ 23420000000b, 13], [ 30324000000b, 16], [ 36411000000b, 19], [ 23045500000b, 23], [ 27657020000b, 26], [ 35632624000b, 29], [ 22500574400b, 33], [ 27220733500b, 36], [ 35065122420b, 39], [ 22141163452b, 43]], t26: [24533722672b, 86], t39: [27405037645b, 129]]; negTable: TenTable = [ tens: [ [ 20000000000b, 0], [ 31463146315b, -4], [ 24365605075b, -7], [ 20304467230b, -10], [ 32155613531b, -14], [ 24761326107b, -17], [ 20615736406b, -20], [ 32657712326b, -24], [ 25363073422b, -27], [ 21134057501b, -30], [ 33371577317b, -34], [ 25772777414b, -37], [ 21457146011b, -40], [ 34113411502b, -44]], t26: [30604403045b, -87], t39: [25616276613b, -130]]; MulExtended: PROC [x, y: Ext] RETURNS [z: Ext] = { hi, lo: LongNumber; z.exp _ x.exp+y.exp+1; z.det.sign _ x.det.sign#y.det.sign; z.det.type _ normal; z.det.sticky _ x.det.sticky OR y.det.sticky; [hi, lo] _ Mul32[x.frac, y.frac]; WHILE NOT BitOn[hi.highbits, HiBit] DO hi.lc _ hi.lc+hi.lc; IF BitOn[lo.highbits, HiBit] THEN hi.lowbits _ BITOR[hi.lowbits, 1]; lo.lc _ lo.lc+lo.lc; z.exp _ z.exp-1; ENDLOOP; z.frac _ hi; IF lo.lc>HalfLC OR (lo.lc=HalfLC AND BitOn[z.frac.lowbits, 1]) THEN { z.frac.lc _ z.frac.lc+1; IF z.frac.lc mul _ table.tens[exp10]; IN (13..26) => { x _ MulExtended[x, CVExt[table.tens[13]]]; mul _ table.tens[exp10-13]}; =26 => mul _ table.t26; IN (26..39) => { x _ MulExtended[x, CVExt[table.t26]]; mul _ table.tens[exp10-26]}; =39 => mul _ table.t39; IN (39..52] => { x _ MulExtended[x, CVExt[table.t39]]; mul _ table.tens[exp10-39]}; ENDCASE => { WHILE exp10>52 DO x _ MulExtended[x, CVExt[table.t39]]; exp10 _ exp10-39; ENDLOOP; RETURN[Scale[x, IF big THEN -exp10 ELSE exp10]]}; y _ CVExt[mul]; y _ MulExtended[x, y]}; CVExt: PROC [t: PowTen] RETURNS [y: Ext] = { y.det.sticky _ y.det.sign _ FALSE; y.det.type _ normal; y.frac.lc _ t.f; y.exp _ t.e}; PairToReal: PUBLIC PROC [fr: LONG INTEGER, exp10: INTEGER] RETURNS [REAL] = { y: Ext; thisTimeExceptions _ NoExceptions; IF fr=0 THEN RETURN[PlusZero]; y.exp _ 31; y.det.sign _ fr<0; y.det.sticky _ FALSE; y.det.type _ normal; y.frac.li _ IF y.det.sign THEN -fr ELSE fr; PostNormalize[@y]; y _ Scale[y, exp10]; StepTwo[@y]; RETURN[Pack[@y]]}; RealToExtended: PUBLIC PROC [a: REAL] RETURNS [Real.Extended] = { ext: Ext = Unpack[a]; RETURN [[type: ext.det.type, sign: ext.det.sign, exp: ext.exp, frac: ext.frac.lc]]}; ExtendedToReal: PUBLIC PROC [e: Real.Extended] RETURNS [REAL] = { ext: Ext _ [ det: [sign: e.sign, sticky: FALSE, blank: 0, type: e.type], exp: e.exp, frac: [lc[e.frac]]]; RETURN [Pack[@ext]]}; Negate: PUBLIC PROC [a: REAL] RETURNS [REAL] = { IF LN[a] = LN[PlusZero] THEN RETURN [PlusZero]; LOOPHOLE[a, LongNumber].highbits _ BITXOR[LN[a].highbits, SignBit]; RETURN [a]}; Abs: PUBLIC PROC [a: REAL] RETURNS [REAL] = { RETURN [IF BitOn[LN[a].highbits, SignBit] THEN Negate[a] ELSE a]}; SetInexactResult: PROC = { thisTimeExceptions[inexactResult] _ TRUE}; SetInvalidOperation: PROC = { thisTimeExceptions[invalidOperation] _ TRUE}; SetUnderflow: PROC [z: POINTER TO Ext] = { thisTimeExceptions[underflow] _ TRUE}; SetOverflow: PROC [z: POINTER TO Ext] = { thisTimeExceptions[overflow] _ TRUE}; Unpack: PUBLIC PROC [r: REAL] RETURNS [z: Ext] = { z.det.sticky _ FALSE; z.det.sign _ BitOn[LN[r].highbits, HiBit]; -- first r.j. the exponent z.exp _ PrincOpsUtils.BITSHIFT[ PrincOpsUtils.BITAND[LN[r].highbits, ExponentMask], -ExponentShift]; z.exp _ z.exp - ExponentBias; z.det.type _ normal; z.frac.li _ LN[r].li; z.frac.highbits _ PrincOpsUtils.BITAND[HiFractionMask, z.frac.highbits]; SELECT z.exp FROM = DenormalizedExponent => { IF z.frac.li = 0 THEN z.det.type _ zero ELSE { z.exp _ ExpSingleMin; z.frac.li _ LongShift[z.frac.li, FractionShift]; IF fpmode.nm = normalizing THEN PostNormalize[@z]}; }; = NaNExponent => { IF z.frac.li = 0 THEN z.det.type _ infinity ELSE { z.det.type _ nan; IF z.frac.lc = Real.TrapTrappingNaN THEN SetInvalidOperation[]}; }; ENDCASE => { z.frac.li _ LongShift[z.frac.li, FractionShift]; z.frac.highbits _ PrincOpsUtils.BITOR[HiddenBit, z.frac.highbits]}; }; Pack: PROC [z: POINTER TO Ext] RETURNS [r: REAL] = { trap: BOOL _ FALSE; i: Exception; IF thisTimeExceptions#NoExceptions THEN { IF thisTimeExceptions[invalidOperation] THEN { z.det.type _ nan; IF z.frac.lc=0 THEN z.frac.lc _ TrapNonTrappingNaN}; FOR i IN Exception DO trap _ trap OR (enableFlags[i] AND thisTimeExceptions[i]); ENDLOOP ; IF trap THEN SIGNAL RealException[flags: thisTimeExceptions]; FixupProcedure[z]}; RETURN[UsualPack[z^]]}; UsualPack: PROC [z: Ext] RETURNS [REAL] = { SELECT z.det.type FROM zero => RETURN [IF z.det.sign THEN MinusZero ELSE PlusZero]; infinity => RETURN [IF z.det.sign THEN MinusInfinity ELSE PlusInfinity]; nan => z.exp _ NaNExponent; ENDCASE => z.frac.li _ LongShift[z.frac.li, -FractionShift]; z.frac.highbits _ BITAND[z.frac.highbits, HiFractionMask]; IF z.exp NOT IN [-127..128] THEN ERROR; z.exp _ BITSHIFT[z.exp+ExponentBias, ExponentShift]; z.frac.highbits _ BITOR[z.frac.highbits, z.exp]; IF z.det.sign THEN z.frac.highbits _ BITOR[z.frac.highbits, SignBit]; RETURN [LOOPHOLE[z.frac.li, REAL]]}; FixupProcedure: PROC [vp: POINTER TO Ext] = { IF thisTimeExceptions[underflow] THEN { DeNormalize[vp, vp.exp-ExpSingleMin]; vp.exp _ DenormalizedExponent}; IF thisTimeExceptions[overflow] THEN vp.det.type _ infinity; }; Round: PROC [z: POINTER TO Ext] = { temp: LONG CARDINAL; GRS: PROC [g: INTEGER] RETURNS [INTEGER] = { s: BOOL _ BitOn[g, StickyBits] OR z.det.sticky; g _ BITSHIFT[BITAND[g, 300b], -5]; IF s THEN g _ g+1; RETURN[g]}; grs: INTEGER _ GRS[z.frac.lowbits]; IF grs=0 THEN RETURN; SetInexactResult[]; BEGIN SELECT fpmode.round FROM rn => { IF z.det.sign THEN grs _ 8-grs; IF grs>4 OR (grs=4 AND BitOn[z.frac.lowbits, LeastSignificandBit]) THEN GOTO Plus1; }; rz => NULL; rm => IF z.det.sign THEN GOTO Plus1; rp => IF NOT z.det.sign THEN GOTO Plus1; ENDCASE => ERROR; EXITS Plus1 => { temp _ z.frac.lc; z.frac.lc _ z.frac.lc+LeastSignificandBit; IF z.frac.lc<=temp THEN { -- better overflow detect! z.frac.li _ RShift1in1[z.frac.li]; z.exp _ z.exp+1}; }; END}; RShift1in1: PROC [z: LONG UNSPECIFIED] RETURNS [LONG UNSPECIFIED] = { vl: LongNumber; vl.lc _ z; vl.lowbits _ BITSHIFT[vl.lowbits, -1]; IF BitOn[vl.highbits, 1] THEN vl.lowbits _ BITOR[vl.lowbits, HiBit]; vl.highbits _ BITOR[HiddenBit, BITSHIFT[vl.highbits, -1]]; RETURN [vl.lc]}; LShift: PROC [z: LONG UNSPECIFIED] RETURNS [LONG UNSPECIFIED] = { vl: LongNumber; vl.lc _ z; vl.highbits _ BITSHIFT[vl.highbits, 1]; IF BitOn[vl.lowbits, HiBit] THEN vl.highbits _ BITOR[vl.highbits, 1]; vl.lowbits _ BITSHIFT[vl.lowbits, 1]; RETURN [vl.lc]}; StepTwo: PROC [z: POINTER TO Ext] = { IF z.det.type#normal THEN RETURN; IF z.exp<=ExpSingleMin THEN { IF z.expExpSingleMax THEN SetOverflow[z]}; Mul32: PROC [x, y: LongNumber] RETURNS [LongNumber, LongNumber] = { hi, lo, t1, t2: LongNumber; cy: CARDINAL; lo.lc _ LongMult[x.lowbits, y.lowbits]; hi.lc _ LongMult[x.highbits, y.highbits]; t1.lc _ LongMult[x.highbits, y.lowbits]; t2.lc _ LongMult[x.lowbits, y.highbits]; [cy, lo.highbits] _ ADC3[lo.highbits, t1.lowbits, t2.lowbits]; hi.lc _ hi.lc+t1.highbits+t2.highbits+cy; RETURN [hi, lo]}; PostNormalize: PROC [z: POINTER TO Ext] = { IF z.frac.lc=0 THEN ERROR; WHILE BITAND[z.frac.highbits, HiddenBit]=0 DO z.frac.lc _ LShift[z.frac.lc]; z.exp _ z.exp-1; ENDLOOP; }; LongShift: PROC [z: LONG UNSPECIFIED, count: INTEGER] RETURNS [LONG UNSPECIFIED] = { xl, vl: LongNumber; vl.lc _ z; SELECT count FROM NOT IN (-32..32) => RETURN [0]; 0 => RETURN [vl.lc]; IN [16..32) => { xl.highbits _ BITSHIFT[vl.lowbits,count-16]; xl.lowbits _ 0}; IN (0..16) => { xl.highbits _ BITSHIFT[vl.highbits, count] + BITSHIFT[vl.lowbits,count-16]; xl.lowbits _ BITSHIFT[vl.lowbits, count]}; IN (-16..0) => { xl.highbits _ BITSHIFT[vl.highbits, count]; xl.lowbits _ BITSHIFT[vl.lowbits, count] + BITSHIFT[vl.highbits,count+16]}; IN (-32..-16] => { xl.highbits _ 0; xl.lowbits _ BITSHIFT[vl.highbits,count+16]}; ENDCASE => ERROR; RETURN[xl.lc]}; DeNormalize: PROC [z: POINTER TO Ext, count: INTEGER] = { sMask: ARRAY [1..16) OF CARDINAL = [ 1b, 3b, 7b, 17b, 37b, 77b, 177b, 377b, 777b, 1777b, 3777b, 7777b, 17777b, 37777b, 77777b]; IF count>0 THEN ERROR; IF count=0 THEN RETURN; count _ -count; z.det.sticky _ SELECT count FROM =16 => z.frac.lowbits#0, IN [1..16) => BitOn[z.frac.lowbits, sMask[count]], IN (16..32) => z.frac.lowbits#0 OR BitOn[z.frac.highbits, sMask[count-16]], ENDCASE => z.frac.lc#0; z.frac.lc _ LongShift[z.frac.lc, -count]}; }. òIeeePack.mesa Ieee Floating Point Package for compiler (Ieee + IeeeIOA + IeeeUtil) Last Modified by Satterthwaite, May 31, 1982 12:04 pm Last Edited by: Maxwell, August 11, 1983 8:36 am from Ieee.Mesa constants global variables Add with Carry from IeeeIOA normalize 64 Round to 32 bits. Overflow or: RoundingMode _ fpmode.round; fpmode.round _ rn; fpmode.round _ or; from IeeeFloatA (adapted) Negate a from IEEEUtil Separate the packed REAL into its component elements denormalized or zero infinity or nan Stuff the components back into the packed REAL. Possible typo in standard here!!! clear hidden bit A 32 bit extended is considered to have its hidden bit as bit 0, significand as the next 29 bits, then G, then R, then S as a separate boolean. GRS computs the 3 bit number formed by the concatenation of G, R, and IF S THEN 1 ELSE 0. StickyBits are the set used for rounding to 24 bits Should flush these constants The fraction should be normalized here! Post Normalize. S does not participate positive count is left shift, negative is right shift DeNormalize is much like LongShift, except that it maintains the sticky bits on the right. And it only shifts right. Mask off everything but the bits contributing to S, then set or clear S in the result. Ê ˜Jšœ ™ JšœD™DJšœ5™5J™0J˜šÏk ˜ Jšœœœ˜*Jš œœœœœœœ˜<šœœ œ˜J˜RJ˜IJ˜——šœ ˜Jšœ˜Jšœ ˜—Jšœ˜!J˜Jšœœœœ˜Jšœœ˜!J˜—š Ïnœœ œœœœ˜9Jšœœ ˜J˜—š ž œœœœœœ˜7Jšœœ˜!J˜—Jšœ™J˜šžœœ œœœœœ˜FJ˜Jšœœœœ˜Jšœ˜J˜—Jšœ ™ J˜šœœœ˜Jšœœœ˜Jšœœ˜ —šœ œœ˜Jšœœ œ˜J˜—˜˜J˜)J˜)J˜)J˜)J˜)J˜)J˜*—J˜J˜—˜˜J˜+J˜+J˜+J˜+J˜+J˜+J˜,—J˜J˜J˜—šž œœ œ ˜2J˜J˜J˜#J˜Jšœœ˜,J˜!Jšœ ™ šœœ˜&J˜Jšœœœ˜DJ˜J˜Jšœ˜—J˜ Jšœ™šœœœœ˜EJšœ™J˜šœœ˜J˜"J˜—J˜—Jšœ œœ˜%J˜—šžœœœœ ˜9J˜J˜ Jšœœ˜ Jšœ œœ˜J˜Jšœœœ œ ˜+Jšœœ˜šœ˜Jšœ$˜&šœ˜J˜*J˜—J˜šœ˜J˜%J˜—J˜šœ˜J˜%J˜—šœ˜ šœ ˜J˜%J˜Jšœ˜—Jšœ œœœ ˜1——J˜J˜J˜—šžœœ œ ˜,Jšœœ˜"J˜J˜J˜ J˜—šž œœœœœ œœœ˜MJ˜Jšœ ™ Jšœ™J˜"Jšœœœ ˜J˜ J˜Jšœœ˜J˜Jšœ œ œœ˜+J˜J˜J˜ Jšœ™Jšœ ˜J˜—Jšœ™J˜š žœœœœœ˜AJ˜JšœN˜TJ˜—š žœœœœœ˜A˜ Jšœœ˜;J˜ —Jšœ˜J˜J˜—š žœœœœœœ˜0Jš œœœ œœ ˜/Jšœ™Jšœœœ˜CJšœ˜ J˜—š žœœœœœœ˜-Jš œœœœ œ˜BJ˜—Jšœ ™ J˜šžœœ˜Jšœ$œ˜*J˜—šžœœ˜Jšœ'œ˜-J˜—šž œœœœ ˜*Jšœ œ˜&J˜—šž œœœœ ˜)Jšœœ˜%J˜—Jšœ4™4J˜š žœœœœœ ˜2Jšœœ˜JšœœÏc˜Ešœœ˜Jšœœœ-˜D—J˜J˜Jšœ œ˜Jšœ œ"˜Hšœ˜˜Jšœ™Jšœœ˜'šœ˜J˜J˜0Jšœœ˜3—J˜—˜Jšœ™Jšœœ˜+šœ˜J˜Jšœ"œ˜@—J˜—šœ˜ J˜0Jšœ œ˜C——J˜J˜—Jšœ/™/J˜š žœœœœœœ˜5Jšœœœ˜J˜ šœ!œ˜)Jšœ!™!šœ&œ˜.J˜Jšœ œ!˜4—šœœ ˜Jšœ œœ˜:Jšœ˜ —šœ˜ Jšœ*˜0—J˜—Jšœ˜J˜—šž œœ œœ˜+šœ ˜Jš œœœ œ œ ˜J˜)Jšœ ˜J˜—Jšœ'™'J˜šž œœœœ ˜+Jšœ œœ˜šœœ˜-J˜J˜Jšœ˜—J˜J˜—Jšœ5™5J˜šž œœœ œ œœœ œ˜TJ˜J˜ šœ˜Jšœœœ˜Jšœœ ˜šœ˜Jšœœ˜,J˜—šœ ˜Jšœœœ˜KJšœ œ˜*—šœ˜Jšœœ˜+Jšœ œœ˜K—šœ˜J˜Jšœ œ˜-—Jšœœ˜—Jšœ ˜J˜—Jšœt™tJ˜š ž œœœœ œ˜9šœœ œœ˜$J˜Z—JšœV™VJšœ œœ˜Jšœ œœ˜J˜šœœ˜ J˜Jšœ0˜2Jšœœ)˜KJšœ˜—J˜*J˜—J˜J˜—…—+F?D