<<>> <> <> <> <> DIRECTORY Basics, ConstArith; ConstArithImpl: PROGRAM IMPORTS Basics EXPORTS ConstArith = BEGIN OPEN ConstArith; <> <> <> <> <<>> <> <<>> <> <<>> divisionMethod: DivisionMethod ¬ princOps; DivisionMethod: TYPE = {princOps, absMod, floor}; <> <<[q, r] = DivMod[x, y] AND y # 0>> <<=> x = q*y+r AND ABS[r] >> <>> <> <>> <> <>> <> <<(r # 0 => SIGN[r] = SIGN[y])>> <> <<>> Overflow: PUBLIC ERROR = CODE; DivByZero: PUBLIC ERROR = CODE; <> <<>> one: Const = [sign: positive, low: 1, high: 0]; <> <<>> FromCard: PUBLIC PROC [card: CARD] RETURNS [Const] = { c: Const ¬ [sign: IF card = 0 THEN zero ELSE positive, low: card, high: 0]; RETURN [c]; }; FromInt: PUBLIC PROC [int: INT] RETURNS [Const] = { c: Const ¬ [sign: positive, low: 0, high: 0]; SELECT int FROM = FIRST[INT] => {c.low ¬ LOOPHOLE[int]; c.sign ¬ negative}; < 0 => {c.low ¬ -int; c.sign ¬ negative}; = 0 => c.sign ¬ zero; ENDCASE => c.low ¬ int; RETURN [c]; }; ToCard: PUBLIC PROC [const: Const] RETURNS [CARD] = { IF const.sign = negative OR const.high # 0 THEN ERROR Overflow; RETURN [const.low]; }; ToInt: PUBLIC PROC [const: Const] RETURNS [INT] = { low: CARD ¬ const.low; IF const.high # 0 THEN ERROR Overflow; SELECT const.sign FROM negative => { IF low <= CARD[LAST[INT]] THEN RETURN [-INT[low]]; IF low = LOOPHOLE[FIRST[INT], CARD] THEN RETURN [FIRST[INT]]; ERROR Overflow; }; positive => { IF low <= CARD[LAST[INT]] THEN RETURN [low]; IF low = LOOPHOLE[FIRST[INT], CARD] THEN RETURN [FIRST[INT]]; ERROR Overflow; }; ENDCASE => RETURN [0]; }; <> <<>> Add: PUBLIC PROC [x,y: Const] RETURNS [Const] = { IF x.sign = zero THEN RETURN [y]; IF y.sign = zero THEN RETURN [x]; IF x.sign # y.sign THEN { <> SELECT UnsignedComparison[x, y] FROM less => { highDiff: CARD ¬ y.high - x.high; -- requires no overflow checking! lowDiff: CARD ¬ y.low - x.low; -- requires no overflow checking! IF x.low > y.low THEN highDiff ¬ highDiff - 1; IF lowDiff = 0 AND highDiff = 0 THEN GO TO zeroExit; RETURN [ [y.sign, lowDiff, highDiff] ]; }; greater => { highDiff: CARD ¬ x.high - y.high; -- requires no overflow checking! lowDiff: CARD ¬ x.low - y.low; -- requires no overflow checking! IF y.low > x.low THEN highDiff ¬ highDiff - 1; IF lowDiff = 0 AND highDiff = 0 THEN GO TO zeroExit; RETURN [ [x.sign, lowDiff, highDiff] ]; }; ENDCASE => GO TO zeroExit; EXITS zeroExit => RETURN [ [zero, 0, 0] ]; } ELSE { <> lowSum: CARD ¬ x.low + y.low; -- requires no overflow checking! highSum: CARD ¬ x.high + y.high; -- requires no overflow checking! IF lowSum < x.low OR lowSum < y.low THEN <> highSum ¬ highSum + 1; IF highSum < x.high OR highSum < y.high THEN <> ERROR Overflow; RETURN [ [x.sign, lowSum, highSum] ]; }; }; Sub: PUBLIC PROC [x,y: Const] RETURNS [Const] = { SELECT y.sign FROM negative => y.sign ¬ positive; positive => y.sign ¬ negative; ENDCASE => RETURN [x]; RETURN [Add[x, y]]; }; Div: PUBLIC PROC [x,y: Const] RETURNS [Const] = { q,r: Const; [q, r] ¬ DivMod[x, y]; RETURN [q]; }; Mod: PUBLIC PROC [x,y: Const] RETURNS [Const] = { q,r: Const; [q, r] ¬ DivMod[x, y]; RETURN [r]; }; DivMod: PUBLIC PROC [x,y: Const] RETURNS [q, r: Const ¬ [zero, 0, 0]] = { <> <> <