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, Environment.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], -Environment.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, Environment.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 {Mopcodes.zSHIFT};
ShiftC: PRIVATE PROCEDURE [i: UNSPECIFIED, shiftAmt: INTEGER] RETURNS [CARDINAL] = TRUSTED MACHINE CODE {Mopcodes.zSHIFT};
BitAndI: PRIVATE PROCEDURE [i, j: UNSPECIFIED] RETURNS [INTEGER] = TRUSTED MACHINE CODE {Mopcodes.zAND};
END.