BigIntegersImpl.Mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
James Rauen, June 20, 1988 4:34:50 pm PDT
James Rauen, July 16, 1988 5:11:25 pm PDT
DIRECTORY
BigCardinals USING [BigAdd, BigCARD, BigCompare, BigDivMod, BigFromBinaryRope, BigFromDecimalRope, BigFromSmall, BigMultiply, BigSubtract, BigToDecimalRope, BigZero, Zero],
BigIntegers USING [Sign],
IO USING [int, PutFR],
Rope USING [Cat, Fetch, ROPE, Substr],
SaffronErrorHandling USING [InternalError];
BigIntegersImpl: CEDAR PROGRAM
IMPORTS BigCardinals, IO, Rope, SaffronErrorHandling
EXPORTS BigIntegers
= BEGIN
BigINT: TYPE = REF BigINTBody;
BigINTBody: PUBLIC TYPE = RECORD [
sign: Sign,
absoluteValue: BigCardinals.BigCARD
];
Sign: TYPE = BigIntegers.Sign;
BigFromRope: PUBLIC PROC [text: Rope.ROPE, base: [2..36] ← 10] RETURNS [BigINT] ~ BEGIN
sign: Sign ← plus;
absoluteValue: BigCardinals.BigCARD;
SELECT text.Fetch[0] FROM
'+   => {text ← text.Substr[1]};
'-   => {text ← text.Substr[1]; sign ← minus};
ENDCASE => NULL;
SELECT base FROM
2   => {absoluteValue ← BigCardinals.BigFromBinaryRope[text]};
10   => {absoluteValue ← BigCardinals.BigFromDecimalRope[text]};
ENDCASE => {
ERROR SaffronErrorHandling.InternalError[IO.PutFR["Can't parse base %g", IO.int[base]]] };
RETURN[NEW[BigINTBody ← [sign, absoluteValue]]];
END;
RopeFromBig: PUBLIC PROC [big: BigINT, base: [2..36] ← 10] RETURNS [Rope.ROPE] ~ BEGIN
RETURN[Rope.Cat[
IF big.sign = minus THEN "-" ELSE "",
SELECT base FROM
10   => BigCardinals.BigToDecimalRope[big.absoluteValue],
ENDCASE =>
ERROR SaffronErrorHandling.InternalError[IO.PutFR["Can't parse base %g", IO.int[base]]]
]];
END;
BigFromSmall: PUBLIC PROC [small: INT] RETURNS [BigINT] ~ BEGIN
RETURN[NEW[BigINTBody ← [
sign: IF small >= 0 THEN plus ELSE minus,
absoluteValue: BigCardinals.BigFromSmall[ABS[small]]
]]];
END;
SmallFromBig: PUBLIC PROC [big: BigINT] RETURNS [INT] ~ BEGIN
Add: PUBLIC PROC [big1, big2: BigINT] RETURNS [BigINT] ~ BEGIN
abs1: BigCardinals.BigCARD = big1.absoluteValue;
abs2: BigCardinals.BigCARD = big2.absoluteValue;
RETURN[NEW[BigINTBody ←
IF big1.sign = big2.sign
THEN [big1.sign, BigCardinals.BigAdd[abs1, abs2]]
ELSE SELECT BigCardinals.BigCompare[abs1, abs2] FROM
less  => [big2.sign, BigCardinals.BigSubtract[abs2, abs1]],
equal  => [plus, BigCardinals.Zero],
greater => [big1.sign, BigCardinals.BigSubtract[abs1, abs2]]
ENDCASE => ERROR
]];
END;
Sub: PUBLIC PROC [big1, big2: BigINT] RETURNS [BigINT] ~ BEGIN
abs1: BigCardinals.BigCARD = big1.absoluteValue;
abs2: BigCardinals.BigCARD = big2.absoluteValue;
RETURN[NEW[BigINTBody ←
IF big1.sign # big2.sign
THEN [big1.sign, BigCardinals.BigAdd[abs1, abs2]]
ELSE SELECT BigCardinals.BigCompare[abs1, abs2] FROM
less  => [FlipSign[big1.sign], BigCardinals.BigSubtract[abs2, abs1]],
equal  => [plus, BigCardinals.Zero],
greater => [big1.sign, BigCardinals.BigSubtract[abs1, abs2]]
ENDCASE => ERROR
]];
END;
Mul: PUBLIC PROC [big1, big2: BigINT] RETURNS [BigINT] ~ BEGIN
RETURN[NEW[BigINTBody ← [
sign: IF big1.sign = big2.sign THEN plus ELSE minus,
absoluteValue: BigCardinals.BigMultiply[big1.absoluteValue, big2.absoluteValue]
]]];
END;
Div: PUBLIC PROC [big1, big2: BigINT] RETURNS [BigINT] ~ BEGIN
RETURN[NEW[BigINTBody ← [
sign: IF big1.sign = big2.sign THEN plus ELSE minus,
absoluteValue: BigCardinals.BigDivMod[big1.absoluteValue, big2.absoluteValue].quo
]]];
END;
Mod: PUBLIC PROC [big1, big2: BigINT] RETURNS [BigINT] ~ BEGIN
RETURN[NEW[BigINTBody ← [
sign: IF big1.sign = big2.sign THEN plus ELSE minus,
absoluteValue: BigCardinals.BigDivMod[big1.absoluteValue, big2.absoluteValue].rem
]]];
END;
Neg: PUBLIC PROC [big1: BigINT] RETURNS [BigINT] ~ BEGIN
RETURN[IF BigCardinals.BigZero[big1.absoluteValue]
THEN big1
ELSE NEW[BigINTBody ← [
sign: FlipSign[big1.sign],
absoluteValue: big1.absoluteValue
]]];
END;
FlipSign: PROC [sign: Sign] RETURNS [Sign] = INLINE {
RETURN[IF sign = plus THEN minus ELSE plus]; };
MultiplySigns: PROC [sign1, sign2: Sign] RETURNS[Sign] = INLINE {
RETURN[IF sign1 = sign2 THEN plus ELSE minus]; };
Abs: PUBLIC PROC [big1: BigINT] RETURNS [BigCardinals.BigCARD] ~ BEGIN
RETURN [big1.absoluteValue];
END;
Sgn: PUBLIC PROC [big1: BigINT] RETURNS [Sign] ~ BEGIN
RETURN [big1.sign];
END;
BigFromBigCARD: PUBLIC PROC [bc: BigCardinals.BigCARD, sign: Sign] RETURNS [BigINT] ~ BEGIN
IF BigCardinals.BigZero[bc]
THEN RETURN [NEW[BigINTBody ← [plus, bc]]]
ELSE RETURN [NEW[BigINTBody ← [sign, bc]]];
END;
END.