(* Copyright (C) 1991, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Fri Feb 28 21:43:41 PST 1992 by stolfi *) (* modified on Thu Feb 20 23:07:42 PST 1992 by muller *) (* modified on Wed Sep 25 00:48:42 1991 by kalsow *) UNSAFE MODULE LongFloat; IMPORT Math, FPU, Word; PROCEDURE Scalb(x: T; n: INTEGER): T = BEGIN RETURN FPU.BinaryPower (x, n); END Scalb; PROCEDURE Logb(x: T): T = BEGIN CASE Class (x) OF | IEEEClass.SignalingNaN, IEEEClass.QuietNaN => RETURN x; | IEEEClass.Infinity => RETURN ABS (x); | IEEEClass.Zero => RETURN LOOPHOLE (FPU.LongRealRep {sign := 1, exponent := 16_7FF, significand0 := 16_0, significand1 := 16_0}, LONGREAL); | IEEEClass.Normal => RETURN FLOAT (LOOPHOLE (x, FPU.LongRealRep).exponent - 1023, LONGREAL); | IEEEClass.Denormal => RETURN -1022.0d0; END; END Logb; PROCEDURE ILogb(x: T): INTEGER = VAR xx := LOOPHOLE (x, FPU.LongRealRep); BEGIN CASE Class (x) OF | IEEEClass.SignalingNaN, IEEEClass.QuietNaN => (* RETURN 0; *) <* ASSERT FALSE*> | IEEEClass.Infinity => RETURN (LAST (INTEGER)); | IEEEClass.Zero => RETURN (FIRST (INTEGER)); | IEEEClass.Normal => RETURN xx.exponent - 1023; | IEEEClass.Denormal => VAR v : Word.T; n : INTEGER; BEGIN IF xx.significand0 = 16_0 THEN v := 16_80000000; n := - 1043; WHILE Word.And (v, xx.significand1) = 0 DO v := Word.RightShift (v, 1); DEC (n); END; ELSE v := 16_00080000; n := - 1023; WHILE Word.And (v, xx.significand0) = 0 DO v := Word.RightShift (v, 1); DEC (n); END; END; RETURN n; END; END; END ILogb; PROCEDURE NextAfter(x, y: T): T = VAR xx: FPU.LongRealRep; BEGIN IF x = y THEN RETURN x; END; IF IsNaN (x) OR NOT Finite (x) THEN RETURN x; END; IF IsNaN (y) THEN RETURN y; END; IF x = 0.0d0 THEN RETURN LOOPHOLE (FPU.LongRealRep {sign := Sign (y), exponent := 16_0, significand0 := 16_0, significand1 := 16_1}, LONGREAL); END; xx := LOOPHOLE (x, FPU.LongRealRep); IF (x > 0.0d0 AND x > y) OR (x < 0.0d0 AND x < y) THEN IF xx.significand0 = 16_0 AND xx.significand1 = 16_0 THEN xx.significand0 := 16_FFFFF; xx.significand1 := 16_FFFFFFFF; DEC (xx.exponent); IF xx.exponent = 16_0 THEN RETURN (2.0d0 * x) / 2.0d0; (* generate underflow *) END; ELSE IF xx.significand1 = 16_0 THEN xx.significand1 := 16_FFFFFFFF; DEC (xx.significand0); ELSE DEC (xx.significand1); END; END; ELSE IF xx.significand0 = 16_FFFFF AND xx.significand1 = 16_FFFFFFFF THEN xx.significand0 := 16_0; xx.significand1 := 16_0; INC (xx.exponent); IF xx.exponent = 16_7FF THEN RETURN (x + x); (* generate overflow *) END; ELSE IF xx.significand1 = 16_FFFFFFFF THEN xx.significand1 := 16_0; INC (xx.significand0); ELSE INC (xx.significand1); END; END; END; RETURN LOOPHOLE (xx, T); END NextAfter; PROCEDURE CopySign(x, y: T): T = BEGIN RETURN FPU.CopySign (x, y); END CopySign; PROCEDURE Finite(x: T): BOOLEAN = BEGIN RETURN FPU.IsFinite (x) # 0; END Finite; PROCEDURE IsNaN(x: T): BOOLEAN = BEGIN RETURN FPU.IsNaN (x) # 0; END IsNaN; PROCEDURE Sign(x: T): [0..1] = BEGIN RETURN LOOPHOLE (x, FPU.LongRealRep).sign; END Sign; PROCEDURE Differs(x, y: T): BOOLEAN = BEGIN RETURN (x < y) OR (y < x); END Differs; PROCEDURE Unordered(x, y: T): BOOLEAN = BEGIN RETURN NOT (x <= y OR y <= x); END Unordered; PROCEDURE Sqrt(x: T): T = BEGIN RETURN Math.sqrt (x); END Sqrt; PROCEDURE Class(x: T): IEEEClass = VAR xx := LOOPHOLE (x, FPU.LongRealRep); BEGIN IF xx.exponent = 16_0 THEN IF xx.significand0 = 16_0 AND xx.significand1 = 16_0 THEN RETURN IEEEClass.Zero; ELSE RETURN IEEEClass.Denormal; END; ELSIF xx.exponent = 16_7FF THEN IF xx.significand0 = 16_0 AND xx.significand1 = 16_0 THEN RETURN IEEEClass.Infinity; ELSIF Word.And (16_00080000, xx.significand0) = 0 THEN RETURN IEEEClass.QuietNaN; ELSE RETURN IEEEClass.SignalingNaN; END; ELSE RETURN IEEEClass.Normal; END; END Class; BEGIN END LongFloat.