IntStuffImpl.Mesa
Last tweaked by Mike Spreitzer on December 10, 1987 10:32:44 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: BOOLFALSE] RETURNS [useOld: BOOLFALSE] --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, commas: BOOLTRUE] RETURNS [rope: ROPE] ~ TRUSTED {
neg: BOOL ~ t.Negative;
tweak: BOOL ← neg;
phase: [0..3) ← 0;
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;
IF commas THEN {
IF phase#2 THEN phase ← phase.SUCC ELSE {
IF t#zero THEN rope ← Rope.Concat[",", rope];
phase ← 0};
};
}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, commas: BOOLTRUE] RETURNS [t: EINT] ~ TRUSTED {
rlen: INT ~ r.Length;
pos: BOOL ~ r.Fetch[0] # '-;
lim: EINT ~ TDivMod[firstEINT, base].quot;
cPhase: [0 .. 4) ~ rlen MOD 4;
i: INTIF pos THEN 0 ELSE 1;
t ← zero;
IF commas AND r.Find[","]=-1 THEN commas ← FALSE;
FOR i ← i, i+1 WHILE i < rlen DO
c: CHAR ~ r.Fetch[i];
IF commas AND (i MOD 4)=cPhase THEN {IF c=', THEN LOOP ELSE Convert.Error[syntax, 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: CARDCARD[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.