LichenIntBasicsImpl.Mesa
Last tweaked by Mike Spreitzer on August 5, 1988 11:22:12 am PDT
DIRECTORY AbSets, IO, LichenIntBasics, SetBasics;
LichenIntBasicsImpl:
CEDAR
PROGRAM
IMPORTS IO, LichenIntBasics, SetBasics
EXPORTS LichenIntBasics
=
BEGIN OPEN Sets:AbSets, LichenIntBasics;
Range2Div:
PUBLIC
PROC [r: Range2,
t,
f: Int2]
RETURNS [rr: Range2] = {
rr ← [
X: [
min: CeilDiv[r[X].min-f[X], t[X]],
maxPlusOne: FloorDiv[r[X].maxPlusOne-1-f[X], t[X]] + 1],
Y: [
min: CeilDiv[r[Y].min-f[Y], t[Y]],
maxPlusOne: FloorDiv[r[Y].maxPlusOne-1-f[Y], t[Y]] + 1]];
};
Range1Div:
PUBLIC
PROC [r: Range,
t,
f:
NATURAL]
RETURNS [rr: Range] = {
rr ← [
min: CeilDiv[r.min-f, t],
maxPlusOne: FloorDiv[r.maxPlusOne-1-f, t] + 1];
};
Range2MulA:
PUBLIC
PROC [r: Range2,
t,
f: Int2]
RETURNS [rr: Range2] = {
rr ← [
X: [
min: r[X].min*t[X] + f[X],
maxPlusOne: (r[X].maxPlusOne-1)*t[X] + 1 + f[X]],
Y: [
min: r[Y].min*t[Y] + f[Y],
maxPlusOne: (r[Y].maxPlusOne-1)*t[Y] + 1 + f[Y]]];
};
Range2MulB:
PUBLIC
PROC [r: Range2,
t,
f: Int2]
RETURNS [rr: Range2] = {
rr ← [
X: [
min: r[X].min*t[X] + f[X],
maxPlusOne: r[X].maxPlusOne*t[X] + f[X]],
Y: [
min: r[Y].min*t[Y] + f[Y],
maxPlusOne: r[Y].maxPlusOne*t[Y] + f[Y]]];
};
Range1MulB:
PUBLIC
PROC [r: Range,
t,
f:
NATURAL]
RETURNS [rr: Range] = {
rr ← [
min: r.min*t + f,
maxPlusOne: r.maxPlusOne*t + f];
};
int2s:
PUBLIC SetBasics.Space ←
NEW [SetBasics.SpacePrivate ← [
Contains: SetBasics.ints.Contains,
Equal: SetBasics.ints.Equal,
Print: Int2sPrint,
AHash: SetBasics.ints.AHash,
ACompare: Int2sCompare,
name: "int2s"]];
Int2sPrint:
PROC [data:
REF
ANY, v: Sets.Value, to:
IO.
STREAM, depth, length:
INT, verbose:
BOOL] ~ {
i: Int2 ~ VI2[v];
to.PutF["<%g,%g>", [integer[i[X]]], [integer[i[Y]]]];
RETURN};
Int2sCompare:
PROC [data:
REF
ANY, v1, v2: Sets.Value]
RETURNS [c: SetBasics.TotalComparison] ~ {
i1: Int2 ~ VI2[v1];
i2: Int2 ~ VI2[v2];
IF (c ← SetBasics.CompareIntI[MIN[i1[X], i1[Y]], MIN[i2[X], i2[Y]]])#equal THEN RETURN;
c ← SetBasics.CompareIntI[MAX[i1[X], i1[Y]], MAX[i2[X], i2[Y]]];
RETURN};
xfmSpace:
PUBLIC SetBasics.Space ←
NEW [SetBasics.SpacePrivate ← [
Contains: XfmsContains,
Equal: XfmsEqual,
Print: XfmsPrint,
AHash: SetBasics.ints.AHash,
ACompare: SetBasics.ints.ACompare,
name: "xfms"]];
XfmsContains:
PROC [data:
REF
ANY, v: Sets.Value]
RETURNS [
BOOL] ~ {
IF v.ra#NIL THEN RETURN [FALSE];
IF v.i<0 THEN RETURN [FALSE];
IF v.i > XfmV[[TRUE, ALL[TRUE]]].i THEN RETURN [FALSE];
RETURN [TRUE]};
XfmsEqual:
PROC [data:
REF
ANY, v1, v2: Sets.Value]
RETURNS [
BOOL] ~ {
x1: Transform ~ VXfm[v1];
x2: Transform ~ VXfm[v2];
RETURN [x1=x2]};
XfmsPrint:
PROC [data:
REF
ANY, v: Sets.Value, to:
IO.
STREAM, depth, length:
INT, verbose:
BOOL] ~ {
x: Transform ~ VXfm[v];
to.PutRope[FormatTransform[x]];
RETURN};
XfmName: TYPE ~ ARRAY --transpose--BOOL OF ARRAY --mx--BOOL OF ARRAY --my--BOOL OF ROPE;
xfmName:
REF XfmName ←
NEW [XfmName ← [
FALSE: [
FALSE: ["Id", "MirrorY"],
TRUE: ["MirrorX", "Rot180"]],
TRUE: [
FALSE: ["Transpose", "RotRight"],
TRUE: ["RotLeft", "Posetrans"]] ]];
FormatTransform:
PUBLIC
PROC [x: Transform]
RETURNS [
ROPE] ~ {
RETURN [xfmName[x.transpose][x.mirror[X]][x.mirror[Y]]]};
XfmFrom4:
PUBLIC
PROC [dxdx, dxdy, dydx, dydy:
INT]
RETURNS [Transform] ~ {
IF dxdy=0
AND dydx=0
THEN
IF dxdx=1
THEN
IF dydy=1 THEN RETURN [[FALSE, [FALSE, FALSE]]]
ELSE IF dydy=-1 THEN RETURN [[FALSE, [FALSE, TRUE]]]
ELSE ERROR
ELSE
IF dxdx=-1
THEN
IF dydy=1 THEN RETURN [[FALSE, [TRUE, FALSE]]]
ELSE IF dydy=-1 THEN RETURN [[FALSE, [TRUE, TRUE]]]
ELSE ERROR
ELSE ERROR
ELSE
IF dxdx=0
AND dydy=0
THEN
IF dxdy=1
THEN
IF dydx=1 THEN RETURN [[TRUE, [FALSE, FALSE]]]
ELSE IF dydx=-1 THEN RETURN [[TRUE, [FALSE, TRUE]]]
ELSE ERROR
ELSE
IF dxdy=-1
THEN
IF dydx=1 THEN RETURN [[TRUE, [TRUE, FALSE]]]
ELSE IF dydx=-1 THEN RETURN [[TRUE, [TRUE, TRUE]]]
ELSE ERROR
ELSE ERROR
ELSE ERROR};
Compose:
PUBLIC
PROC [first, then: Transform]
RETURNS [Transform] ~ {
mid: Transform ~ Invert[[then.transpose, first.mirror]];
RETURN [[mid.transpose#first.transpose, [mid.mirror[X]#then.mirror[X], mid.mirror[Y]#then.mirror[Y]] ]]};
Invert:
PUBLIC
PROC [xfm: Transform]
RETURNS [Transform] ~ {
IF xfm.transpose THEN RETURN [[TRUE, [xfm.mirror[Y], xfm.mirror[X]] ]];
RETURN [xfm]};
InvertXO:
PUBLIC
PROC [xfm: Transform, offset: Int2]
RETURNS [Transform, Int2] ~ {
xfm ← Invert[xfm];
offset ← Neg[TransformVector[xfm, offset]];
RETURN [xfm, offset]};
TransformSize:
PUBLIC
PROC [xfm: Transform, size: Int2]
RETURNS [Int2] ~ {
RETURN [IF xfm.transpose THEN [size[Y], size[X]] ELSE size]};
TransformVector:
PUBLIC
PROC [xfm: Transform, vec: Int2]
RETURNS [Int2] ~ {
ans: Int2 ← IF xfm.transpose THEN [vec[Y], vec[X]] ELSE vec;
IF xfm.mirror[X] THEN ans[X] ← -ans[X];
IF xfm.mirror[Y] THEN ans[Y] ← -ans[Y];
RETURN [ans]};
TransformPos:
PUBLIC
PROC [xfm: Transform, vec, size: Int2]
RETURNS [Int2] ~ {
ans: Int2 ← IF xfm.transpose THEN [vec[Y], vec[X]] ELSE vec;
IF xfm.mirror[X] THEN ans[X] ← size[X]-1 - ans[X];
IF xfm.mirror[Y] THEN ans[Y] ← size[Y]-1 - ans[Y];
RETURN [ans]};
TransOffPos:
PUBLIC
PROC [xfm: Transform, offset, pos: Int2]
RETURNS [Int2]
~ {RETURN Add[offset, TransformVector[xfm, pos]]};
TransOffRange2:
PUBLIC
PROC [xfm: Transform, offset: Int2, r: Range2]
RETURNS [Range2] ~ {
p1: Int2 ~ TransOffPos[xfm, offset, Range2Min[r]];
p2: Int2 ~ TransOffPos[xfm, offset, [r[X].maxPlusOne, r[Y].maxPlusOne]];
RETURN [[
X: [MIN[p1[X], p2[X]], MAX[p1[X], p2[X]]],
Y: [MIN[p1[Y], p2[Y]], MAX[p1[Y], p2[Y]]] ]]};
FloorDiv:
PROC [num, den:
INT]
RETURNS [
INT]
~ INLINE {RETURN [num/den]};
CeilDiv:
PROC [num, den:
INT]
RETURNS [
INT]
~ INLINE {RETURN [-((-num)/den)]};
END.