Scaled.mesa
Created February 4, 1983
Edited by Michael Plass, November 15, 1983 9:59 am
DIRECTORY Basics, PrincOps, Real;
Scaled: CEDAR DEFINITIONS IMPORTS Real = BEGIN
Value: TYPE = MACHINE DEPENDENT RECORD [fraction: CARDINAL ← 0, integerPart: INTEGER];
zero: Value = [0, 0];
one, unit: Value = [integerPart: 1];
epsilon: Value = [integerPart: 0, fraction: 1];
oneMinusEpsilon: Value = [integerPart: 0, fraction: LAST[CARDINAL]];
half: Value = [fraction: LAST[NAT]+1, integerPart: 0];
infinity: Value = LOOPHOLE[LAST[INT]];
negInfinity: Value = LOOPHOLE[FIRST[INT]];
FromInt: PROC [int: INTEGER] RETURNS [Value] = INLINE
{RETURN[[integerPart: int, fraction: 0]]};
FromReal: PROC [real: REAL] RETURNS [Value] = INLINE
{RETURN[ValRep[Real.RoundLI[Real.FScale[real, Basics.bitsPerWord]]]]};
PLUS: PROC [a, b: Value] RETURNS [Value] = INLINE
{RETURN[ValRep[IntRep[a] + IntRep[b]]]};
MINUS: PROC [a, b: Value] RETURNS [Value] = INLINE
{RETURN[ValRep[IntRep[a] - IntRep[b]]]};
UMINUS: PROC [a: Value] RETURNS [Value] = INLINE
{RETURN[ValRep[-IntRep[a]]]};
TIMES: PROC [a, b: Value] RETURNS [Value];
DIVIDE: PROC [a, b: Value] RETURNS [Value];
GREATER: PROC [a, b: Value] RETURNS [BOOLEAN] = INLINE
{RETURN[IntRep[a] > IntRep[b]]};
LESS: PROC [a, b: Value] RETURNS [BOOLEAN] = INLINE
{RETURN[IntRep[a] < IntRep[b]]};
Max: PROC [a, b: Value] RETURNS [Value] = INLINE
{RETURN[ValRep[MAX[IntRep[a], IntRep[b]]]]};
Min: PROC [a, b: Value] RETURNS [Value] = INLINE
{RETURN[ValRep[MIN[IntRep[a], IntRep[b]]]]};
Floor: PROC [a: Value] RETURNS [INTEGER] = INLINE
{RETURN[a.integerPart]};
Ceiling: PROC [a: Value] RETURNS [INTEGER] = INLINE
{RETURN[Floor[PLUS[a, oneMinusEpsilon]]]};
Round: PROC [a: Value] RETURNS [INTEGER] = INLINE
{RETURN[Floor[PLUS[a, half]]]};
Float: PROC [a: Value] RETURNS [REAL] = INLINE
{RETURN[Real.FScale[IntRep[a], -Basics.bitsPerWord]]};
Scale: PROC [a: Value, scale: INTEGER] RETURNS [Value];
Halve: PROC [a: Value] RETURNS [Value] = INLINE {
RETURN[[
integerPart: ShiftI[a.integerPart, -1] + BitAndI[a.integerPart, FIRST[INTEGER]],
fraction: ShiftC[a.integerPart, Basics.bitsPerWord-1] + ShiftC[a.fraction, -1]
]];
};
The following routines are to coax the inline expansion to do the right thing.
IntRep: PRIVATE PROCEDURE [v: Value] RETURNS [INT] = TRUSTED MACHINE CODE {};
ValRep: PRIVATE PROCEDURE [i: INT] RETURNS [Value] = TRUSTED MACHINE CODE {};
ShiftI: PRIVATE PROCEDURE [i: UNSPECIFIED, shiftAmt: INTEGER] RETURNS [INTEGER] = TRUSTED MACHINE CODE {PrincOps.zSHIFT};
ShiftC: PRIVATE PROCEDURE [i: UNSPECIFIED, shiftAmt: INTEGER] RETURNS [CARDINAL] = TRUSTED MACHINE CODE {PrincOps.zSHIFT};
BitAndI: PRIVATE PROCEDURE [i, j: UNSPECIFIED] RETURNS [INTEGER] = TRUSTED MACHINE CODE {PrincOps.zAND};
END.