IntStuffImpl.Mesa
Last tweaked by Mike Spreitzer on July 8, 1987 10:42:50 am PDT
DIRECTORY Basics, Convert, IntStuff, Rope, RuntimeError;
IntStuffImpl: CEDAR PROGRAM
IMPORTS Convert, IntStuff, Rope, RuntimeError
EXPORTS IntStuff
=
BEGIN OPEN IntStuff;
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: INTIF 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};
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;
};
NClipI: PROC [t: EINT] RETURNS [INT] ~ {RETURN t.ClipI};
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};
END.