IntStuffImpl.Mesa
Last tweaked by Mike Spreitzer on November 17, 1987 7:23:07 pm PST
DIRECTORY AMBridge, AMTypes, Basics, Convert, IntStuff, IO, PrintTV, Rope, RuntimeError;
IntStuffImpl:
CEDAR
PROGRAM
IMPORTS AMBridge, AMTypes, Convert, IntStuff, IO, PrintTV, Rope, RuntimeError
EXPORTS IntStuff
=
BEGIN OPEN IntStuff;
ROPE: TYPE ~ Rope.ROPE;
TV: TYPE ~ AMTypes.TV;
Type: TYPE ~ AMTypes.Type;
PrintEINT:
PROC [tv:
TV, data:
REF
ANY, stream:
IO.
STREAM, depth:
INT ← 4, width:
INT ← 32, verbose:
BOOL ←
FALSE]
RETURNS [useOld:
BOOL ←
FALSE]
--PrintTV.TVPrintProc-- ~
TRUSTED {
refEINT: REF EINT ~ NEW [EINT];
refTV: TV ~ AMBridge.TVForReferent[refEINT];
AMTypes.Assign[lhs: refTV, rhs: tv];
stream.PutRope[ToRope[refEINT^]];
RETURN};
ToRope:
PUBLIC
PROC [t:
EINT, base: [2..36] ← 10]
RETURNS [rope:
ROPE] ~
TRUSTED {
neg: BOOL ~ t.Negative;
tweak: BOOL ← neg;
IF neg THEN t ← negOne.Sub[t];
rope ← NIL;
WHILE t#zero
DO
{quot: EINT;
rem: CARDINAL;
[quot, rem] ← TDivMod[t, base];
IF tweak
THEN {
rem ← rem+1;
IF rem=base THEN rem ← 0 ELSE tweak ← FALSE};
rope ← Rope.FromChar[IF rem<10 THEN '0 + rem ELSE 'A + (rem-10)].Concat[rope];
t ← quot;
}ENDLOOP;
IF tweak THEN rope ← Rope.Concat["1", rope] ELSE IF rope=NIL THEN rope ← "0";
IF neg THEN rope ← Rope.Concat["-", rope];
RETURN};
TDivMod:
PROC [num:
EINT, den:
CARDINAL]
RETURNS [quot:
EINT, rem:
CARDINAL] ~
TRUSTED {
h: DM ~ DivMod[num.hi, den];
n2: INT ~ INT[num.lo] + INT[b1]*h.rem;
l: DM ~ DivMod[n2, den];
quot ← IE[l.quot].Add[[loShort[lo: 0, hi: h.quot]]];
rem ← l.rem;
RETURN};
DM: TYPE ~ RECORD [quot: INT, rem: CARDINAL];
DivMod:
PROC [num:
INT, den:
CARDINAL]
RETURNS [dm:
DM] ~ {
dm.quot ← num/den;
num ← num - dm.quot*den;
IF num<0 THEN {num ← num + den; dm.quot ← dm.quot-1};
IF num NOT IN [0 .. den) THEN ERROR;
dm.rem ← num;
RETURN};
FromRope:
PUBLIC
PROC [r:
ROPE, base: [2..36] ← 10]
RETURNS [t:
EINT] ~
TRUSTED {
rlen: INT ~ r.Length;
pos: BOOL ~ r.Fetch[0] # '-;
lim: EINT ~ TDivMod[firstEINT, base].quot;
i: INT ← IF pos THEN 0 ELSE 1;
t ← zero;
FOR i ← i, i+1
WHILE i < rlen
DO
c: CHAR ~ r.Fetch[i];
d: CARDINAL;
IF c IN ['0 .. '9] THEN d ← c - '0
ELSE IF c IN ['A .. 'Z] THEN d ← (c-'A) + 10
ELSE IF c IN ['a .. 'z] THEN d ← (c-'a) + 10
ELSE d ← 37;
IF d >= base THEN Convert.Error[syntax, i];
IF t.Compare[lim] = less THEN Convert.Error[overflow, i];
t ← MulSC[t, base].SubI[d];
IF t.Positive THEN Convert.Error[overflow, i];
ENDLOOP;
IF pos THEN {IF t#firstEINT THEN t ← t.Neg ELSE Convert.Error[overflow, i-1]};
RETURN};
Mul:
PUBLIC
PROC [a, b:
EINT]
RETURNS [
DEINT] ~
TRUSTED {
Ans:
TYPE ~
RECORD [variant:
SELECT
OVERLAID *
FROM
unsigned => [cards: ARRAY [0 .. 5] OF CARDINAL],
pair => [d: DEINT],
ENDCASE];
ans: Ans ← [unsigned[ALL[0]]];
FOR i: [0 .. 2]
IN [0 .. 2]
DO
FOR j: [0 .. 2]
IN [0 .. 2]
DO
ij: [0 .. 5] ~ i+j;
sum: CARD ← CARD[a.cards[i]]*b.cards[j] + ans.cards[ij];
ans.cards[ij] ← Basics.LowHalf[sum];
FOR k: [0 .. 5]
IN (ij .. 5]
WHILE Basics.HighHalf[sum] # 0
DO
sum ← ans.cards[k] + CARD[Basics.HighHalf[sum]];
ans.cards[k] ← Basics.LowHalf[sum];
ENDLOOP;
ENDLOOP ENDLOOP;
IF a.Negative
THEN
IF b.Negative
THEN ans.d.hi ← ans.d.hi.Add[a.Add[b]]
ELSE ans.d.hi ← ans.d.hi.Sub[a]
ELSE
IF b.Negative
THEN ans.d.hi ← ans.d.hi.Sub[b]
ELSE NULL;
IF ans.d.lo.Negative THEN ans.d.hi ← ans.d.hi.Succ;
RETURN [ans.d]};
MulI:
PUBLIC
PROC [a:
EINT, b:
INT]
RETURNS [
EINT] ~ {
l: EINT ~ MulSC[a, Basics.LowHalf[b]];
h: EINT ~ MulSI[a, LOOPHOLE[Basics.HighHalf[b]]];
hi: INT ~ h.EI;
RETURN l.Add[[loShort[lo: 0, hi: hi]]]};
MulSI:
PROC [a:
EINT, b:
INTEGER]
RETURNS [c:
EINT] ~ {
m: INT ~ INT[a.lo]*INT[b];
RETURN [[loShort[lo: Basics.LowHalf[m], hi: HighInt[m] + a.hi*b]]]};
MulSC:
PROC [a:
EINT, b:
CARDINAL]
RETURNS [c:
EINT] ~ {
m: CARD ~ a.lo.LONG*b;
RETURN [[loShort[lo: Basics.LowHalf[m], hi: INT[Basics.HighHalf[m]] + a.hi*b]]]};
ShiftInterval:
PUBLIC
PROC [i: Interval,
d:
EINT]
RETURNS [o: Interval] ~ {
o.min ← d.AddI[i.min].EI;
o.max ← d.AddI[i.max].EI;
};
ClipShiftInterval:
PUBLIC
PROC [i: Interval,
d:
EINT]
RETURNS [o: Interval] ~ {
o.min ← d.AddI[i.min].ClipI;
o.max ← d.AddI[i.max].ClipI;
};
NCN: PROC [c: CARD] RETURNS [n: LNAT] ~ {n ← c};
NIE: PROC [i: INT] RETURNS [EINT] ~ {RETURN IE[i]};
NCE: PROC [c: CARD] RETURNS [EINT] ~ {RETURN CE[c]};
NEI: PROC [t: EINT] RETURNS [INT] ~ {RETURN t.EI};
NEC: PROC [t: EINT] RETURNS [CARD] ~ {RETURN t.EC};
NEN: PROC [t: EINT] RETURNS [LNAT] ~ {RETURN t.EN};
NIsInt: PROC [t: EINT] RETURNS [BOOL] ~ {RETURN t.IsInt};
NIsNat: PROC [t: EINT] RETURNS [BOOL] ~ {RETURN t.IsNat};
NClipI: PROC [t: EINT] RETURNS [INT] ~ {RETURN t.ClipI};
NAdd: PROC [a, b: EINT] RETURNS [EINT] ~ {RETURN a.Add[b]};
NCompare: PROC [a, b: EINT] RETURNS [c: Basics.Comparison] ~ {c ← a.Compare[b]};
NAddI: PROC [a: EINT, b: INT] RETURNS [EINT] ~ {RETURN a.AddI[b]};
NISub: PROC [a, b: INT] RETURNS [EINT] ~ {RETURN ISub[a, b]};
NSucc: PROC [t: EINT] RETURNS [EINT] ~ {RETURN t.Succ};
Start:
PROC ~ {
PrintTV.RegisterTVPrintProc[CODE[EINT], PrintEINT];
};
Start[];
END.