-- Real.mesa
-- Last Modified: L. Stewart, September 1, 1982 10:03 am
-- Last Modified: Paul Rovner, May 13, 1983 1:13 pm
-- Last Edited by: Levin, August 8, 1983 4:15 pm

DIRECTORY
Basics USING [Comparison],
PrincOps USING [zINC, zMISC, aFIX, aFIXI, aFIXC, aROUND, aROUNDI, aROUNDC, aFREM, aFSQRT, aFCOMP, aFADD, aFSUB, aFMUL, aFDIV, aFLOAT, aFSC];

Real: CEDAR DEFINITIONS =
BEGIN

-- See IEEE floating point standard for more information.

-- Extended is the internal form of a single precision
-- floating point number. If the type of a value is
-- infinity or zero, only the sign is interesting.
-- In these cases, exp and frac are undefined.
-- If spec = nan, then exp is undefined and frac
-- contains the nan significand. Some constant
-- nans are defined below. If spec is normal,
-- then sign, exp, and frac describe the value.
-- If sign is true, then the number is negative.
-- Exp is the binary exponent. Frac is the significand
-- (the binary point is between bits 0 and 1 -
-- normalized numbers are between 1 and 2).

NumberType: TYPE = MACHINE DEPENDENT{normal, zero, infinity, nan};

Extended: TYPE = RECORD [
type: NumberType, sign: BOOLEAN, exp: INTEGER, frac: LONG CARDINAL];

-- Constants

-- Useful REAL values.
PlusZero: REAL = LOOPHOLE[LONG[00000000000B]];
MinusZero: REAL = LOOPHOLE[20000000000B];
PlusInfinity: REAL = LOOPHOLE[17740000000B];
MinusInfinity: REAL = LOOPHOLE[37740000000B];
LargestNumber: REAL = LOOPHOLE[17737777777B]; -- almost infinity
SmallestNormalizedNumber: REAL = LOOPHOLE[00040000000B];

-- You may want to use TrappingNaN to initialize storage.

NonTrappingNaN: REAL = LOOPHOLE[17740000001B];
TrappingNaN: REAL = LOOPHOLE[17740000002B];

-- Values that may be encountered as vp.frac during an exception.

TrapNonTrappingNaN: LONG CARDINAL = LONG[1];
TrapTrappingNaN: LONG CARDINAL = LONG[2];
AddInfinityNaN: LONG CARDINAL = LONG[3];
MultiplyInfinityNaN: LONG CARDINAL = LONG[4];
DivideInfinityNaN: LONG CARDINAL = LONG[5];
SqRtNaN: LONG CARDINAL = LONG[6];

-- Exceptions
Flag: TYPE = BOOLEANFALSE;

Exception: TYPE = MACHINE DEPENDENT{
fixOverflow, inexactResult, invalidOperation, divisionByZero, overflow,
underflow};

ExceptionFlags: TYPE = PACKED ARRAY Exception OF Flag;

NoExceptions: ExceptionFlags = ALL[FALSE];
AllExceptions: ExceptionFlags = ALL[TRUE];
UsualExceptions: ExceptionFlags =
[fixOverflow: TRUE, invalidOperation: TRUE, divisionByZero: TRUE,
overflow: TRUE];

-- The six kinds of exceptions have independent
-- "sticky" flags that remember if the exception
-- has occurred since the last call to SetStickyFlags.
-- SetStickyFlags is provided so that procedures may
-- save and restore the state for others.

SetStickyFlags: PROC [new: ExceptionFlags ← NoExceptions]
RETURNS [old: ExceptionFlags];

GetStickyFlags: PROC RETURNS [ExceptionFlags];

-- This signal is raised if any enabled exception occurs.
-- Flags reports all the exceptions which occurred during
-- the faulted operation (including those which are
-- disabled). On RESUME, if clientFixup is TRUE, the client is
-- expected to have fixed up the reference. If clientFixup is
-- FALSE the standard fixup will happen. Operations
-- in this interface only raise RealException on the
-- conditions mentioned in UsualExceptions, above.
-- Usually, RealException can be resumed, but certain
-- exceptions, such as invalidOperation raised as a
-- result of compare or one of the Fixes, cannot be
-- resumed. If a RESUME is done in such a case, the
-- ERROR RealError is raised.

RealException: SIGNAL [flags: ExceptionFlags, vp: REF Extended]
RETURNS [clientFixup: BOOLEANFALSE];

RealError: ERROR;

-- INITIALIZATION

-- The procedure InitReals must be called before any
-- floating point operations are called. Alternatively,
-- RealControl must be STARTed. It is ok to call
-- InitReals more than once.

InitReals: PROC;
RealControl: UNSAFE PROGRAM;

MaxSinglePrecision: CARDINAL = 9;
DefaultSinglePrecision: CARDINAL = 7;

-- The decimal to binary routines may cause exceptions
-- in the normal course of their work. In particular,
-- InexactResult, Overflow, and Underflow. They
-- always use rounding mode rn (round to nearest).

-- PairToReal converts the value fr*10**exp10 to real.

PairToReal: PROC [fr: INT, exp10: INTEGER] RETURNS [REAL];

-- The binary to decimal routines will not cause
-- exceptions. The decimal output is rounded to
-- precision significant digits in rounding mode rn.
-- ForceE ← TRUE forces output in scientific notation.

-- Real to Pair converts value r to fr*10**exp10.
-- fr will have precision significant digits.

RealToPair: PROC [r: REAL, precision: NAT ← DefaultSinglePrecision]
RETURNS [type: NumberType, fr: INT, exp10: INTEGER];

-- Operations

-- These three Fixes truncate (round to integer in mode rz).

Fix: PROC [REAL] RETURNS [INT] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFIX; };

FixI: PROC [REAL] RETURNS [INTEGER] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFIXI; };

FixC: PROC [REAL] RETURNS [CARDINAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFIXC; };

-- These three Fixes round.

RoundLI: PROC [REAL] RETURNS [INT] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aROUND; };

RoundI: PROC [REAL] RETURNS [INTEGER] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aROUNDI; };

RoundC: PROC [REAL] RETURNS [CARDINAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aROUNDC; };

-- Remainder of a/b.

FRem: PROC [a, b: REAL] RETURNS [REAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFREM; };

-- Square Root.

SqRt: PROC [REAL] RETURNS [REAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFSQRT; };

-- Basics.Comparison style compare

CompareREAL: PROC [a, b: REAL] RETURNS [Basics.Comparison] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFCOMP; PrincOps.zINC; };

-- These operations are normally generated by the compiler.

FAdd: PROC [a, b: REAL] RETURNS [REAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFADD; };

FSub: PROC [a, b: REAL] RETURNS [REAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFSUB; };

FMul: PROC [a, b: REAL] RETURNS [REAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFMUL; };

FDiv: PROC [a, b: REAL] RETURNS [REAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFDIV; };

FComp: PROC [a, b: REAL] RETURNS [INTEGER] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFCOMP; };

Float: PROC [INT] RETURNS [REAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFLOAT; };

FScale: PROC [a: REAL, scale: INTEGER] RETURNS [REAL] =
TRUSTED MACHINE CODE { PrincOps.zMISC, PrincOps.aFSC; };

Microcode: BOOLEAN = TRUE;
-- For use by the implementation

END.
4-Feb-81 18:42:11, L. Stewart, fixed TrappingNaN to be of type REAL
June 3, 1982 10:36 am, L. Stewart, added REF, SqRt, FScale, removed STRING
September 1, 1982 10:03 am, L. Stewart, CompareREAL, Cedar 3.4
May 13, 1983 1:13 pm, Paul Rovner, conversion to Cedar 5.0