LichenArrayImpl.Mesa
Mike Spreitzer January 14, 1987 10:41:05 pm PST
DIRECTORY Basics, Convert, GList, HashTable, IntChainedHashTable, InterpreterOps, IntHashTable, IO, LichenDataOps, LichenDataStructure, LichenSetTheory, Rope;
LichenArray2Impl: CEDAR MONITOR
IMPORTS HashTable, LichenDataStructure, LichenDataOps, LichenSetTheory
EXPORTS LichenDataStructure, LichenDataOps
INVARIANT
tie.completion is redundant with the information in the rpd.links.
tie.completion = NIL iff tie.completion.nIncomplete = 0.
a RoledPortData has links iff needed or array is being created.
=
BEGIN OPEN ICHT: IntChainedHashTable, LichenSetTheory, LichenDataStructure, LichenDataOps;
Abort: ERROR = CODE;
Range1Mul: PUBLIC PROC [r: Range, t, f: NAT] RETURNS [rr: Range] = {
rr ← [
min: r.min*t + f,
maxPlusOne: r.maxPlusOne*t + f];
};
Range2Mul: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = {
rr ← [
Foo: [
min: r[Foo].min*t[Foo] + f[Foo],
maxPlusOne: r[Foo].maxPlusOne*t[Foo] + f[Foo]],
Bar: [
min: r[Bar].min*t[Bar] + f[Bar],
maxPlusOne: r[Bar].maxPlusOne*t[Bar] + f[Bar]]];
};
Range1Div: PUBLIC PROC [r: Range, t, f: NAT] RETURNS [rr: Range] = {
rr ← [
min: CeilDiv[MAX[r.min, f] - f, t],
maxPlusOne: FloorDiv[r.maxPlusOne-1 - f, t] + 1];
};
Range2Div: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = {
rr ← [
Foo: [
min: CeilDiv[MAX[r[Foo].min, f[Foo]] - f[Foo], t[Foo]],
maxPlusOne: FloorDiv[r[Foo].maxPlusOne-1 - f[Foo], t[Foo]] + 1],
Bar: [
min: CeilDiv[MAX[r[Bar].min, f[Bar]] - f[Bar], t[Bar]],
maxPlusOne: FloorDiv[r[Bar].maxPlusOne-1 - f[Bar], t[Bar]] + 1]];
};
Jgi2ToLair: PUBLIC PROC [a: Array, phase: Nat2, j: Joint, jgi2: Nat2] RETURNS [lair, jiir: Range2, jCount: NAT] = {
Do1: PROC [d: Dim] RETURNS [jiir: Range] = {
SELECT TRUE FROM
jgi2[d] < j.groupingParmses[d].middle.min => RETURN [[jgi2[d], jgi2[d]+1]];
jgi2[d] >= j.groupingParmses[d].firstHigh => {
jiir.min ← jgi2[d] - j.groupingParmses[d].d;
RETURN [[jiir.min, jiir.min+1]]};
ENDCASE => RETURN [j.groupingParmses[d].middle];
};
jiir ← [Foo: Do1[Foo], Bar: Do1[Bar]];
jCount ← RangeArea[jiir];
lair ← Range2Mul[jiir, a.jointsPeriod, phase];
};
ConsInt2: PROC [d1: Dim, x1, x2: INT] RETURNS [x: Int2]
= INLINE {x[d1] ← x1; x[OtherDim[d1]] ← x2};
Range2Intersection: PROC [a, b: Range2] RETURNS [c: Range2]
= INLINE {c ← [
Foo: [
min: MAX[a[Foo].min, b[Foo].min],
maxPlusOne: MIN[a[Foo].maxPlusOne, b[Foo].maxPlusOne]],
Bar: [
min: MAX[a[Bar].min, b[Bar].min],
maxPlusOne: MIN[a[Bar].maxPlusOne, b[Bar].maxPlusOne]]]};
EnumJgiOfGi: PROC [a: Array, gi2: Nat2, Consume: PROC [d: Dim, j: Joint, side: End, jgi2: Nat2]] = {
phase: Nat2;
air: Range2 = Gi2ToAir[a, gi2].air;
FOR d: Dim IN Dim DO
phase[d] ← SELECT TRUE FROM
gi2[d] < a.groupingParmses[d].middle.min => gi2[d] MOD a.jointsPeriod[d],
gi2[d] >= a.groupingParmses[d].firstHigh => NAT[(gi2[d]-a.groupingParmses[d].d) MOD a.jointsPeriod[d]],
ENDCASE => gi2[d] - NAT[a.groupingParmses[d].middle.min];
ENDLOOP;
FOR dj: Dim IN Dim DO
lairMax: Range2 = SizeRange[Nat2Tweak[a.size, dj, -1]];
j: Joint = GetArrayJoint[a, dj, phase];
FOR side: End IN End DO
lair: Range2 = Range2Intersection[lairMax, IF side = low THEN air ELSE Range2Off[air, ConsInt2[dj, -1, 0]]];
lf: Nat2 = [lair[Foo].min MOD a.jointsPeriod[Foo], lair[Bar].min MOD a.jointsPeriod[Bar]];
jir: Range2 = Range2Div[lair, a.jointsPeriod, lf];
Enum: PROC [de: Dim, Consume: PROC [NAT]] = {
IF jir[de].min >= jir[de].maxPlusOne OR j.groupingParmses[de].middle.min >= j.groupingParmses[de].middle.maxPlusOne THEN RETURN;
FOR jgi: INT IN [jir[de].min .. j.groupingParmses[de].middle.min) DO Consume[jgi] ENDLOOP;
FOR jgi: INT IN [j.groupingParmses[de].middle.maxPlusOne .. jir[de].maxPlusOne) DO Consume[jgi] ENDLOOP;
IF jir[de].min < j.groupingParmses[de].middle.maxPlusOne OR jir[de].maxPlusOne > j.groupingParmses[de].middle.min THEN Consume[j.groupingParmses[de].middle.min];
};
Med: PROC [jgif: NAT] = {
Inner: PROC [jgib: NAT] = {Consume[dj, j, side, [jgif, jgib]]};
Enum[Bar, Inner]};
Enum[Foo, Med];
ENDLOOP;
ENDLOOP;
};
Gi2ToAir: PROC [a: Array, gi2: Nat2] RETURNS [air: Range2, ngii: NAT] = {
Do1: PROC [d: Dim] RETURNS [air: Range, n: INT] = {
SELECT TRUE FROM
gi2[d]<a.groupingParmses[d].middle.min => RETURN [[gi2[d], gi2[d]+1], 1];
gi2[d]>=a.groupingParmses[d].firstHigh => {
air.min ← gi2[d] - a.groupingParmses[d].d;
RETURN [[air.min, air.min+1], 1]};
ENDCASE => {
f: NAT = gi2[d] - a.groupingParmses[d].middle.min;
jiir: Range = Range1Div[a.groupingParmses[d].middle, a.jointsPeriod[d], f];
RETURN [Range1Mul[jiir, a.jointsPeriod[d], f], RangeLength[jiir]];
};
};
count2: ARRAY Dim OF INT;
[air[Foo], count2[Foo]] ← Do1[Foo];
[air[Bar], count2[Bar]] ← Do1[Foo];
ngii ← count2[Foo] * count2[Bar];
};
IsIncompleteArray: PUBLIC PROC [ct: CellType] RETURNS [incomplete: BOOL] = {
a: Array = ct.asArray;
incomplete ← FALSE;
IF a = NIL THEN RETURN;
FOR d: Dim IN Dim DO
FOR cphase: INT IN [0 .. a.joints[d].length) DO
j: Joint = NARROW[a.joints[d][cphase]];
njgi: NAT = j.groupingParmses[Foo].sum * j.groupingParmses[Bar].sum;
FOR jgi: NAT IN [0 .. njgi) DO
ties: Set--of Tie-- = NARROW[j.ties[jgi]];
TestTie: PROC [ra: REF ANY] = {
tie: Tie = NARROW[ra];
IF tie.completion # NIL THEN incomplete ← TRUE;
};
ties.Enumerate[TestTie];
IF incomplete THEN RETURN;
ENDLOOP;
ENDLOOP;
ENDLOOP;
incomplete ← incomplete;
};
HasUnusedGroups: PROC [ct: CellType] RETURNS [has: BOOL] = {
ENABLE Abort => {has ← TRUE; CONTINUE};
a: Array = ct.asArray;
has ← FALSE;
IF a = NIL THEN RETURN;
FOR gif: NAT IN [0 .. a.groupingParmses[Foo].sum) DO FOR gib: NAT IN [0 .. a.groupingParmses[Bar].sum) DO
gi2: Nat2 = [gif, gib];
gi: NAT = a.groupingParmses[Bar].sum * gif + gib;
gs: Groupings = NARROW[a.groupingses[gi]];
PerGroup: PROC [ra: REF ANY] = {
g: Group = NARROW[ra];
PerJgi: PROC [d: Dim, j: Joint, side: End, jgi2: Nat2] = {
jgi: NAT = j.groupingParmses[Bar].sum * jgi2[Foo] + jgi2[Bar];
IF FetchTie[j, side, jgi, g] # NIL THEN ERROR Abort[];
};
EnumJgiOfGi[a, gi2, PerJgi !Abort => GOTO Used];
ERROR Abort[];
EXITS Used => ra ← ra;
};
gs.groups.Enumerate[PerGroup];
IF has THEN RETURN;
ENDLOOP ENDLOOP;
has ← FALSE;
};
GetArrayPortForPort: PUBLIC PROC [a: Array, index: ArrayIndex, ep: Port] RETURNS [arrayPort: Port] = {
gi: NAT = ComputeGroupingsIndex[a, index].gi;
g: Group = PortToGroup[a, gi, ep];
IF g = NIL THEN RETURN [NIL];
arrayPort ← GetArrayPortForGroup[a, index, g];
};
GetArrayPortForGroup: PUBLIC PROC [a: Array, index: ArrayIndex, g: Group] RETURNS [arrayPort: Port] = {
gi: NAT = ComputeGroupingsIndex[a, index].gi;
aw: ArrayWire = ArrayWireForGroup[a, index, gi, g, FALSE];
PerPort: PROC [ra: REF ANY] = {
IF (arrayPort ← NARROW[ra]) = NIL THEN ERROR;
};
arrayPort ← NIL;
IF aw # NIL THEN aw.ports.Enumerate[PerPort];
arrayPort ← arrayPort;
};
SetArrayPortForPort: PUBLIC PROC [a: Array, index: ArrayIndex, ep, ap: Port] = {
gi: NAT = ComputeGroupingsIndex[a, index].gi;
g: Group = GetGroup[a, gi, ep, TRUE];
SetArrayPortForGroup[a, index, gi, g, ap];
};
SetArrayPortForGroup: PUBLIC PROC [a: Array, index: ArrayIndex, gi: NAT, g: Group, ap: Port] = {
aw: ArrayWire = ArrayWireForGroup[a, index, gi, g, TRUE];
IF NOT aw.ports.UnionSingleton[ap] THEN ERROR;
IF NOT a.portWire.Insert[ap, aw] THEN ERROR;
};
END.