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.