LichenIntBasics:
CEDAR
DEFINITIONS
IMPORTS SetBasics
= {OPEN Sets:AbSets;
LNAT: TYPE ~ INT--[0 .. INT.LAST], but we can't write that--;
ROPE: TYPE ~ Rope.ROPE;
Int2: TYPE ~ PACKED ARRAY Dim2 OF Int;
Dim2: TYPE ~ Dim3 [X .. Y];
Dim3: TYPE ~ {X, Y, Z};
Int: TYPE ~ INT16;
dullInt2: Int2 ~ [Int.FIRST, Int.LAST];
Range: TYPE = RECORD [min, maxPlusOne: Int];
Range2: TYPE = ARRAY Dim2 OF Range;
emptyRange2: Range2 ~ ALL[[Int.LAST, Int.FIRST]];
fullRange2: Range2 ~ ALL[[Int.FIRST, Int.LAST]];
Transform:
TYPE ~
RECORD [
transpose: BOOL ← FALSE,
mirror: PACKED ARRAY Dim2 OF BOOL ← ALL[FALSE]];
mirroring done after transpose.
int2s: SetBasics.Space;
OtherDim2: ARRAY Dim2 OF Dim2 ~ [X: Y, Y: X];
I2V:
PROC [x: Int2]
RETURNS [Sets.Value]
~ INLINE {RETURN [[ra: NIL, i: LOOPHOLE[x]]]};
VI2:
PROC [v: Sets.Value]
RETURNS [Int2]
~ INLINE {RETURN LOOPHOLE[v.i]};
ConsInt2:
PROC [d1: Dim2, x1, x2: Int]
RETURNS [x: Int2]
~ INLINE {x[d1] ← x1; x[OtherDim2[d1]] ← x2};
Neg:
PROC [a: Int2]
RETURNS [Int2]
~ INLINE {RETURN [[X: -a[X], Y: -a[Y]]]};
Add:
PROC [a, b: Int2]
RETURNS [Int2]
~ INLINE {RETURN [[X: INT[a[X]]+b[X], Y: INT[a[Y]]+b[Y]]]};
Sub:
PROC [a, b: Int2]
RETURNS [Int2]
~ INLINE {RETURN [[X: INT[a[X]]-b[X], Y: INT[a[Y]]-b[Y]]]};
InRange:
PROC [i: Int2, r: Range2]
RETURNS [
BOOL]
~ INLINE {RETURN [i[X] IN [r[X].min .. r[X].maxPlusOne) AND i[Y] IN [r[Y].min .. r[Y].maxPlusOne)]};
Tweak:
PROC [i: Int2, d: Dim2,
D: Int]
RETURNS [Int2]
~ INLINE {i[d] ← i[d] + D; RETURN [i]};
Mul:
PROC [i: Int2,
t,
f: Int2]
RETURNS [Int2]
~ INLINE {RETURN [[X: i[X]*t[X]+f[X], Y: i[Y]*t[Y]+f[Y]]]};
Scale:
PROC [a: Int2, b: Int]
RETURNS [Int2]
~ INLINE {RETURN [[X: a[X]*b, Y: a[Y]*b]]};
Scale2:
PROC [a, b: Int2]
RETURNS [Int2]
~ INLINE {RETURN [[X: a[X]*b[X], Y: a[Y]*b[Y]]]};
Dot:
PROC [a, b: Int2]
RETURNS [Int]
~ INLINE {RETURN [a[X]*b[X]+a[Y]*b[Y]]};
Cross:
PROC [a, b: Int2]
RETURNS [
INT]
~ INLINE {RETURN [INT[a[X]]*b[Y]-INT[a[Y]]*b[X]]};
Div:
PROC [a, b: Int2]
RETURNS [Int2]
Guaranteed only for a, b > 0.
~ INLINE {RETURN [[X: a[X]/b[X], Y: a[Y]/b[Y]]]};
Mod:
PROC [a, mod: Int2]
RETURNS [Int2]
mod > 0. Depends on new divide when a < 0.
~ INLINE {RETURN [[X: a[X] MOD mod[X], Y: a[Y] MOD mod[Y]]]};
QuotRem: TYPE ~ RECORD [q, r: Int2];
DivMod:
PROC [n, d: Int2]
RETURNS [QuotRem]
Guaranteed only for a, b > 0.
~
INLINE {
q: Int2 ~ Div[n, d];
RETURN [[q: q, r: [n[X]-q[X]*d[X], n[Y]-q[Y]*d[Y]] ]]};
AddMod:
PROC [a, b: Int2, mod: Int2]
RETURNS [Int2]
~
INLINE {
RETURN [[
X: (a[X]+b[X]+mod[X]) MOD mod[X],
Y: (a[Y]+b[Y]+mod[Y]) MOD mod[Y]]]};
SubMod:
PROC [a, b: Int2, mod: Int2]
RETURNS [Int2]
~
INLINE {
RETURN [[
X: (a[X]-b[X]+mod[X]) MOD mod[X],
Y: (a[Y]-b[Y]+mod[Y]) MOD mod[Y]]]};
Area:
PROC [x: Int2]
RETURNS [
LNAT]
~ INLINE {RETURN [x[X] * x[Y]]};
Int2Hash:
PROC [x: Int2]
RETURNS [
CARDINAL]
~ INLINE {RETURN [17*LOOPHOLE[x[X], CARDINAL] + 257*LOOPHOLE[x[Y], CARDINAL]]};
Int2Compare:
PROC [a, b: Int2]
RETURNS [SetBasics.TotalComparison]
~ INLINE {RETURN SetBasics.CompareIntI[LOOPHOLE[a], LOOPHOLE[b]]};
RangeOff:
PROC [r: Range,
D: Int]
RETURNS [Range]
~ INLINE {RETURN[[min: r.min+D, maxPlusOne: r.maxPlusOne+D]]};
RangeOffClip:
PROC [r: Range,
D: Int]
RETURNS [Range]
~ INLINE {RETURN[[min: MAX[r.min+D, 0], maxPlusOne: r.maxPlusOne+D]]};
ShaveRange2Top1:
PROC [r: Range2, d: Dim2]
RETURNS [Range2]
~ INLINE {r[d].min ← MIN[r[d].min, r[d].maxPlusOne ← r[d].maxPlusOne - 1]; RETURN [r]};
ConsRange2:
PROC [d1: Dim2, x1, x2: Range]
RETURNS [x: Range2]
~ INLINE {x[d1] ← x1; x[OtherDim2[d1]] ← x2};
TransposeRange2:
PROC [r: Range2]
RETURNS [Range2]
~ INLINE {RETURN [[X: r[Y], Y: r[X]]]};
Range2Empty:
PROC [r: Range2]
RETURNS [
BOOL]
~ INLINE {RETURN [r[X].maxPlusOne<=r[X].min OR r[Y].maxPlusOne<=r[Y].min]};
Range2IsSingleton:
PROC [r: Range2]
RETURNS [
BOOL]
~ INLINE {RETURN [r[X].maxPlusOne=r[X].min+1 AND r[Y].maxPlusOne=r[Y].min+1]};
Range2Min:
PROC [r2: Range2]
RETURNS [Int2]
~ INLINE {RETURN[[X: r2[X].min, Y: r2[Y].min]]};
Range2Mid:
PROC [r2: Range2]
RETURNS [Int2]
~ INLINE {RETURN[[X: (INT[r2[X].min] + r2[X].maxPlusOne)/2, Y: (INT[r2[Y].min] + r2[Y].maxPlusOne)/2]]};
Range2Max:
PROC [r2: Range2]
RETURNS [Int2]
~ INLINE {RETURN[[X: r2[X].maxPlusOne-1, Y: r2[Y].maxPlusOne-1]]};
Range2Off:
PROC [r: Range2,
D: Int2]
RETURNS [Range2]
~ INLINE {RETURN[[X: RangeOff[r[X], D[X]], Y: RangeOff[r[Y], D[Y]]]]};
Range2OffClip:
PROC [r: Range2,
D: Int2]
RETURNS [Range2]
~ INLINE {RETURN[[X: RangeOffClip[r[X], D[X]], Y: RangeOffClip[r[Y], D[Y]]]]};
Range2Included:
PROC [sub, in: Range2]
RETURNS [
BOOL]
~ INLINE {RETURN [RangeIncluded[sub[X], in[X]] AND RangeIncluded[sub[Y], in[Y]]]};
RangeIncluded:
PROC [sub, in: Range]
RETURNS [
BOOL]
~ INLINE {RETURN [sub.min>=in.min AND sub.maxPlusOne<=in.maxPlusOne]};
Range2Intersection:
PROC [a, b: Range2]
RETURNS [Range2]
~
INLINE {
RETURN [[
X: [
min: MAX[a[X].min, b[X].min],
maxPlusOne: MIN[a[X].maxPlusOne, b[X].maxPlusOne]],
Y: [
min: MAX[a[Y].min, b[Y].min],
maxPlusOne: MIN[a[Y].maxPlusOne, b[Y].maxPlusOne]]]]};
RangeLength:
PROC [r: Range]
RETURNS [
NATURAL]
~ INLINE {RETURN [r.maxPlusOne - r.min]};
RangeArea:
PROC [r: Range2]
RETURNS [area:
LNAT]
~ INLINE {area ← INT[RangeLength[r[X]]] * RangeLength[r[Y]]};
RangeShape:
PROC [r: Range2]
RETURNS [Int2]
~ INLINE {RETURN [[RangeLength[r[X]], RangeLength[r[Y]]]]};
SizeRange:
PROC [size: Int2]
RETURNS [Range2]
~ INLINE {RETURN [[[0, size[X]], [0, size[Y]]]]};
Int2sRange:
PROC [a, b: Int2]
RETURNS [r: Range2]
~
INLINE {
RETURN [[
X: [MIN[a[X], b[X]], MAX[a[X], b[X]]+1],
Y: [MIN[a[Y], b[Y]], MAX[a[Y], b[Y]]+1]]]};
Range2Mbb:
PROC [a, b: Range2]
RETURNS [Range2]
~ INLINE {RETURN [[X: RangeMbb[a[X], b[X]], Y: RangeMbb[a[Y], b[Y]]]]};
RangeMbb:
PROC [a, b: Range]
RETURNS [Range]
~ INLINE {RETURN [[min: MIN[a.min, b.min], maxPlusOne: MAX[a.maxPlusOne, b.maxPlusOne]]]};
Range2sIntersect:
PROC [r1, r2: Range2]
RETURNS [
BOOL]
= INLINE {RETURN [RangesIntersect[r1[X], r2[X]] AND RangesIntersect[r1[Y], r2[Y]]]};
RangesIntersect:
PROC [r1, r2: Range]
RETURNS [
BOOL]
=
INLINE {
RETURN [
(r1.min IN [r2.min .. r2.maxPlusOne) AND r1.maxPlusOne > r1.min) OR
(r2.min IN [r1.min .. r1.maxPlusOne) AND r2.maxPlusOne > r2.min)]};
Range2Div: PROC [r: Range2, t, f: Int2] RETURNS [Range2];
Range1Div:
PROC [r: Range,
t,
f:
NATURAL]
RETURNS [Range];
Gives the range of i such that i*t+f is in r.
Range2RoundA: PROC [r: Range2, t, f: Int2] RETURNS [Range2];
Range2MulA: PROC [r: Range2, t, f: Int2] RETURNS [Range2];
Range1MulA:
PROC [r: Range,
t,
f:
NATURAL]
RETURNS [Range];
.maxPlusOne-1 has given phase.
Range2RoundB: PROC [r: Range2, t, f: Int2] RETURNS [Range2];
Range2MulB: PROC [r: Range2, t, f: Int2] RETURNS [Range2];
Range1MulB:
PROC [r: Range,
t,
f:
NATURAL]
RETURNS [Range];
.maxPlusOne has given phase.
FmtRange: PROC [Range] RETURNS [ROPE];
FmtRange2: PROC [Range2] RETURNS [ROPE];
XfmV:
PROC [xfm: Transform]
RETURNS [SetBasics.Value]
~ INLINE {RETURN [[i: LOOPHOLE[xfm, CARDINAL]]]};
VXfm:
PROC [v: SetBasics.Value]
RETURNS [Transform]
~ INLINE {RETURN [LOOPHOLE[CARDINAL[v.i]]]};
xfmSpace: SetBasics.Space;
XfmFrom4: PROC [dxdx, dxdy, dydx, dydy: INT] RETURNS [Transform];
Compose: PROC [first, then: Transform] RETURNS [Transform];
Invert: PROC [xfm: Transform] RETURNS [Transform];
InvertXO: PROC [xfm: Transform, offset: Int2] RETURNS [Transform, Int2];
TransformDim: PROC [xfm: Transform, dim: Dim2] RETURNS [Dim2];
TransformSize: PROC [xfm: Transform, size: Int2] RETURNS [Int2];
TransformVector: PROC [xfm: Transform, vec: Int2] RETURNS [Int2];
TransformPos:
PROC [xfm: Transform, vec, size: Int2]
RETURNS [Int2];
size is `transformed' size.
TransOffPos: PROC [xfm: Transform, offset, pos: Int2] RETURNS [Int2];
TransOffRange2: PROC [xfm: Transform, offset: Int2, r: Range2] RETURNS [Range2];
TranspRange2:
PROC [xfm: Transform, r: Range2]
RETURNS [Range2]
~ INLINE {RETURN [IF xfm.transpose THEN TransposeRange2[r] ELSE r]};
FormatTransform: PROC [Transform] RETURNS [ROPE];
ParseTransform: PROC [ROPE] RETURNS [Transform];
Int2Mods: PROC [range: Range2, t: Int2 ← [1, 1], f: Int2 ← [0, 0]] RETURNS [Sets.Set];
}.