-- IeeeIOB.mesa -- String munging for IO -- Last Modified By Paul Rovner On May 4, 1983 10:08 am -- Last Edited by: Levin, August 8, 1983 6:21 pm -- Last Edited by: MBrown, January 16, 1984 2:51 pm PST DIRECTORY Basics USING [LongNumber], ConvertReal USING [], -- EXPORTS only Ieee USING [BitOn, HiBit], Real USING [NumberType, RealToPair]; IeeeIOB: CEDAR PROGRAM IMPORTS Ieee, Real EXPORTS ConvertReal = BEGIN AppendReal: PUBLIC PROC [s: STRING, r: REAL, precision: CARDINAL, forceE: BOOL] = TRUSTED { exp: INTEGER; z: INT; ty: Real.NumberType; sign: BOOL; Zeros: PROC [n: CARDINAL] = TRUSTED { THROUGH [1..n] DO AppendChar[s, '0] ENDLOOP }; { sign ← Ieee.BitOn[LOOPHOLE[r, Basics.LongNumber].highbits, Ieee.HiBit]; [type: ty, fr: z, exp10: exp] ← Real.RealToPair[r, precision]; IF sign THEN z ← -z; SELECT ty FROM nan => AppendString[to: s, from: ".."]; infinity => AppendString[to: s, from: IF sign THEN "--" ELSE "++"]; zero => AppendString[to: s, from: IF sign THEN "-0.0" ELSE "0.0"]; ENDCASE => GOTO Ok; EXITS Ok => { lds: STRING ← [20]; rds: STRING ← [20]; i, digit, digits, ld, rd: CARDINAL; IF sign THEN AppendChar[s, '-]; IF z = 0 THEN { AppendChar[s, '0]; RETURN }; -- leading zeros digits ← precision ← MAX[1, MIN[precision, 9]]; WHILE (z MOD 10) = 0 DO -- strip trailing zeros z ← z/10; exp ← exp + 1; digits ← digits - 1; ENDLOOP; IF digits = 0 THEN ERROR; rd ← MAX[0, -exp]; rds.length ← MIN[digits, rd]; -- right digit string FOR i DECREASING IN [0..rds.length) DO digit ← LOOPHOLE[z MOD 10, Basics.LongNumber].lowbits; z ← z/10; rds[i] ← digit + '0; ENDLOOP; ld ← MAX[0, LOOPHOLE[digits, INTEGER] + exp]; lds.length ← MIN[digits, ld]; -- left digit string FOR i DECREASING IN [0..lds.length) DO digit ← LOOPHOLE[z MOD 10, Basics.LongNumber].lowbits; z ← z/10; lds[i] ← digit + '0; ENDLOOP; forceE ← forceE OR ld > 6 OR rd > 6; IF NOT forceE THEN SELECT TRUE FROM ld = 0 => { -- number entirely to right of decimal point AppendString[to: s, from: "0."]; Zeros[rd - rds.length]; AppendString[to: s, from: rds]; }; rd = 0 => { -- number entirely to left of decimal point AppendString[to: s, from: lds]; Zeros[ld - lds.length]; AppendString[to: s, from: ".0"]; }; ENDCASE => { -- some of each AppendString[to: s, from: lds]; AppendChar[s, '.]; AppendString[to: s, from: rds]; } ELSE { -- e format AppendString[to: lds, from: rds]; AppendChar[s, lds[0]]; lds.length ← lds.length; exp ← exp + lds.length - 1; SELECT TRUE FROM precision = 1 => AppendChar[s, '.]; lds.length = 1 => AppendString[to: s, from: ".0"]; ENDCASE => { AppendChar[s, '.]; FOR i IN [1..lds.length) DO AppendChar[s, lds[i]]; ENDLOOP; }; -- print exponent IF exp = 0 THEN RETURN; AppendChar[s, 'e]; AppendChar[s, IF exp < 0 THEN '- ELSE '+]; exp ← ABS[exp]; IF exp > 9 THEN AppendChar[s, '0 + (exp/10)]; AppendChar[s, '0 + (exp MOD 10)]; }; }; }; }; AppendChar: PROC [s: STRING, c: CHARACTER] = TRUSTED { IF s = NIL THEN RETURN; IF s.length >= s.maxlength THEN ERROR; s[s.length] ← c; s.length ← s.length + 1; }; AppendString: PROC [to: STRING, from: STRING] = TRUSTED { i, j, n: CARDINAL; IF to = NIL OR from = NIL THEN RETURN; IF from.length + to.length > to.maxlength THEN ERROR; n ← MIN[from.length, LOOPHOLE[to.maxlength - to.length, CARDINAL]]; i ← to.length; j ← 0; WHILE j < n DO to[i] ← from[j]; i ← i + 1; j ← j + 1; ENDLOOP; to.length ← i; }; END. L. Stewart, July 12, 1980 10:37 PM, Name changes L. Stewart, July 13, 1980 8:57 PM, delete WF procwedures (Moved to WFReal) August 24, 1980 8:42 PM, L. Stewart; formatting, fix ReadReal December 11, 1980 11:06 AM, L. Stewart; Use Ascii instead of IODefs June 5, 1982 5:58 pm, L. Stewart, removed STRING conversions August 27, 1982 1:05 pm, L. Stewart, CEDAR January 16, 1984 2:35 pm PST, MBrown, toss unused stuff.