LichenArray2Impl.Mesa
Last tweaked by Mike Spreitzer on April 30, 1987 1:47:09 pm PDT
DIRECTORY Asserting, Basics, Convert, GList, IntChainedHashTable, InterpreterOps, IntHashTable, IO, LichenArrayStuff, LichenDataOps, LichenDataStructure, LichenSetTheory, LRUCache, Rope;
LichenArray2Impl: CEDAR MONITOR
IMPORTS Asserting, Convert, GList, IntChainedHashTable, IntHashTable, LichenArrayStuff, LichenDataOps, LichenDataStructure, LichenSetTheory, LRUCache, Rope
EXPORTS LichenArrayStuff, LichenDataStructure
INVARIANT
tie.completion is redundant with the information in the rpd.links.
tie.completion = NIL iff tie.completion.nIncomplete = 0.
a SidedPortData has links iff needed or array is being created.
=
BEGIN OPEN ICHT: IntChainedHashTable, LichenSetTheory, LichenDataStructure, LichenArrayStuff, 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];
};
EnumJgiOfGi: PUBLIC PROC [a: Array, gi2: Nat2, Consume: PROC [d: Dim, j: Joint, side: End, jgi2, phase: 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]] = {
mid: Range ~ [
min: MAX[jir[de].min, j.groupingParmses[de].middle.min],
maxPlusOne: MIN[jir[de].maxPlusOne, j.groupingParmses[de].middle.maxPlusOne]];
FOR jgi: INT IN [jir[de].min .. mid.min) DO Consume[jgi] ENDLOOP;
FOR jgi: INT IN [mid.maxPlusOne .. jir[de].maxPlusOne) DO Consume[jgi+j.groupingParmses[de].d] ENDLOOP;
IF mid.min < mid.maxPlusOne THEN Consume[j.groupingParmses[de].middle.min];
};
Med: PROC [jgif: NAT] = {
Inner: PROC [jgib: NAT] = {Consume[dj, j, side, [jgif, jgib], phase]};
Enum[Bar, Inner]};
Enum[Foo, Med];
ENDLOOP;
ENDLOOP;
};
Gi2ToAir: PUBLIC PROC [a: Array, gi2: Nat2] RETURNS [air: Range2, ngii2: Nat2, ngii: NAT] = {
Do1: PROC [d: Dim] RETURNS [air: Range, n: NATURAL] = {
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]];
};
};
[air[Foo], ngii2[Foo]] ← Do1[Foo];
[air[Bar], ngii2[Bar]] ← Do1[Bar];
ngii ← ngii2[Foo] * ngii2[Bar];
};
EnumerateJoints: PUBLIC PROC [a: Array, Consume: PROC [d: Dim, phase: Nat2, j: Joint]] ~ {
FOR d: Dim IN Dim DO
FOR ff: INT IN [0 .. a.jointsPeriod[Foo]) DO FOR fb: INT IN [0 .. a.jointsPeriod[Bar]) DO
phase: Nat2 ~ [ff, fb];
j: Joint ~ GetArrayJoint[a, d, phase];
Consume[d, phase, j];
ENDLOOP ENDLOOP;
ENDLOOP;
};
EnumerateTies: PUBLIC PROC [a: Array, Consume: PROC [d: Dim, phase: Nat2, jgi: NATURAL, jgi2: Nat2, j: Joint, tie: Tie]] ~ {
Refine: PROC [d: Dim, phase: Nat2, j: Joint] ~ {
jgi: NAT ← 0;
FOR jgif: NAT IN [0 .. j.groupingParmses[Foo].sum) DO
FOR jgib: NAT IN [0 .. j.groupingParmses[Bar].sum) DO
jgi2: Nat2 ~ [jgif, jgib];
ties: Set--of Tie-- ~ NARROW[j.ties[jgi]];
PassTie: PROC [ra: REF ANY]
~ {Consume[d, phase, jgi, jgi2, j, NARROW[ra]]};
ties.Enumerate[PassTie];
jgi ← jgi + 1;
ENDLOOP;
ENDLOOP;
IF jgi # j.ties.length THEN ERROR;
};
EnumerateJoints[a, Refine];
};
EnumerateTiesOfGroup: PUBLIC PROC [a: Array, gi2: Nat2, g: Group, Consume: PROC [d: Dim, phase: Nat2, jgi: NATURAL, jgi2: Nat2, j: Joint, tie: Tie, side: End]] ~ {
PerJgi: PROC [d: Dim, j: Joint, side: End, jgi2: Nat2, phase: Nat2] ~ {
jgi: NATURAL ~ ComposeJgi[j, jgi2];
ties: Set--of Tie-- ~ NARROW[j.ties[jgi]];
PassTie: PROC [ra: REF ANY] ~ {
tie: Tie ~ NARROW[ra];
side: End;
SELECT g FROM
tie.groups[low] => side ← low;
tie.groups[high] => side ← high;
ENDCASE => RETURN;
Consume[d, phase, jgi, jgi2, j, tie, side];
};
ties.Enumerate[PassTie];
a ← a;
};
EnumJgiOfGi[a, gi2, PerJgi];
a ← a;
};
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;
};
GroupInWireAt: PUBLIC PROC [a: Array, gi2: Nat2, g: Group, aw: ArrayWire, ai: ArrayIndex] RETURNS [BOOL] ~ {
bs: BoolSeq ~ NARROW[aw.members.Map[g]];
IF bs = NIL THEN RETURN [FALSE];
{air: Range2 ~ Gi2ToAir[a, gi2].air;
shape: Nat2 ~ RangeShape[air];
gii: Nat2 ~ Nat2Div[Int2SubN[ai, Range2Min[air]], a.jointsPeriod];
index: NAT ~ shape[Bar] * gii[Foo] + gii[Bar];
RETURN [bs[index]];
}};
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 = ComposeGI[a, gi2];
gs: Groupings = NARROW[a.groupingses[gi]];
PerGroup: PROC [ra: REF ANY] = {
g: Group = NARROW[ra];
PerJgi: PROC [d: Dim, j: Joint, side: End, jgi2, phase: Nat2] = {
jgi: NAT ~ ComposeJgi[j, jgi2];
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 [act: CellType, a: Array, index: ArrayIndex, ep: Port, mayAdd: BOOL] RETURNS [arrayPort: Port] = {
gi: NAT = ComputeGroupingsIndex[a, index].gi;
g: Group = PortToGroup[a, gi, ep];
IF g # NIL THEN {
arrayPort ← GetArrayPortForGroup[act, a, index, g, FALSE];
IF arrayPort # NIL THEN RETURN;
};
IF mayAdd THEN {
portName: ROPE ~ FmtIndex[a, index].Concat[Describe[ep, a.eltType.port]];
arrayPort ← FullyAddPort[[parent: act.port, other: Asserting.Assert[nameReln, LIST[portName], NIL]]].port;
SetArrayPortForPort[a, index, ep, arrayPort];
}
ELSE arrayPort ← NIL;
};
GetArrayPortForGroup: PUBLIC PROC [act: CellType, a: Array, index: ArrayIndex, g: Group, mayAdd: BOOL] RETURNS [arrayPort: Port] = {
gi: NAT = ComputeGroupingsIndex[a, index].gi;
aw: ArrayWire = ArrayWireForGroup[a, index, gi, g, mayAdd];
PerPort: PROC [ra: REF ANY] = {
IF (arrayPort ← NARROW[ra]) = NIL THEN ERROR;
};
arrayPort ← NIL;
IF aw # NIL THEN aw.ports.Enumerate[PerPort];
IF arrayPort=NIL AND mayAdd THEN {
ep: Port ~ g.ports.first;
portName: ROPE ~ FmtIndex[a, index].Concat[Describe[ep, a.eltType.port]];
arrayPort ← FullyAddPort[[parent: act.port, other: Asserting.Assert[nameReln, LIST[portName], NIL]]].port;
SetArrayPortForGroup[a, index, gi, g, arrayPort];
};
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;
};
FlushArrayWires: PUBLIC PROC [a: Array, doomedArrayPorts: Set--of port of a--] ~ {
portToAWE: Mapper--array port b REF ArrayWireElt-- ~ CreateHashMapper[];
RememberExPort: PROC [ra: REF ANY] ~ {
aw: ArrayWire ~ NARROW[ra];
awe: REF ArrayWireElt ← NIL;
IF aw.ports.Size[] # 0 THEN {
TryGroup: PROC [domain, range: REF ANY] ~ {
g: Group ~ NARROW[domain];
bs: BoolSeq ~ NARROW[range];
air: Range2;
gii, ngii: NATURAL ← 0;
IF g.ports=NIL THEN RETURN;
[air, , ngii] ← Gi2ToAir[a, g.gi2];
FOR foo: INT ← air[Foo].min, foo+a.jointsPeriod[Foo] WHILE foo < air[Foo].maxPlusOne DO FOR bar: INT ← air[Bar].min, bar+a.jointsPeriod[Bar] WHILE bar < air[Bar].maxPlusOne DO
IF bs[gii] THEN {
awe ← NEW [ArrayWireElt ← [g, [foo, bar]]];
ERROR GotIt;
};
gii ← gii+1;
ENDLOOP ENDLOOP;
IF gii # ngii THEN ERROR;
};
aw.members.EnumerateMap[TryGroup !GotIt => GOTO Gotit];
{NoteDoomedPort: PROC [ra: REF ANY] ~ {
IF NOT doomedArrayPorts.UnionSingleton[ra] THEN ERROR;
};
aw.ports.Enumerate[NoteDoomedPort];
};
EXITS
Gotit => {
NotePortAns: PROC [ra: REF ANY] ~ {
IF NOT portToAWE.PutMapping[ra, awe] THEN ERROR;
};
aw.ports.Enumerate[NotePortAns];
awe ← awe;
};
};
};
ExPortNewWire: PROC [domain, range: REF ANY] ~ {
ap: Port ~ NARROW[domain];
awe: REF ArrayWireElt ~ NARROW[range];
gi: NAT ~ ComputeGroupingsIndex[a, awe.ai].gi;
aw: ArrayWire ~ ArrayWireForGroup[a, awe.ai, gi, awe.g, TRUE];
IF NOT a.portWire.Replace[ap, aw] THEN ERROR;
IF NOT aw.ports.UnionSingleton[ap] THEN ERROR;
};
a.wires.Enumerate[RememberExPort];
a.toWire.Erase[];
a.wires.Erase[];
portToAWE.EnumerateMap[ExPortNewWire];
};
GotIt: ERROR = CODE;
TieSpec: TYPE = REF TieSpecPrivate;
TieSpecPrivate: TYPE = RECORD [
j: Joint,
jgi: NATURAL,
tie: Tie
];
HashTieSpec: PROC [key: REF ANY] RETURNS [CARDINAL] --HashProc-- ~ {
ts: TieSpec ~ NARROW[key];
RETURN [HashRefI[ts.j]+HashRefI[ts.tie]+ts.jgi];
};
EqualTieSpecs: PROC [key1, key2: REF ANY] RETURNS [BOOL] --EqualProc-- ~ {
ts1: TieSpec ~ NARROW[key1];
ts2: TieSpec ~ NARROW[key2];
RETURN [ts1^ = ts2^];
};
TrimEmptyGroups: PUBLIC PROC [a: Array] ~ {
doomedGroups: Set--of Group-- ~ CreateHashSet[];
doomedTies: Set--of TieSpec-- ~ CreateHashSet[[HashTieSpec, EqualTieSpecs]];
KillTie: PROC [ra: REF ANY] ~ {
ts: TieSpec ~ NARROW[ra];
DeleteTie[ts.j, ts.jgi, ts.tie];
};
KillGroup: PROC [ra: REF ANY] ~ {
g: Group ~ NARROW[ra];
DeleteGroup[a, g];
};
FOR gif: NATURAL IN [0 .. a.groupingParmses[Foo].sum) DO FOR gib: NATURAL IN [0 .. a.groupingParmses[Bar].sum) DO
gi2: Nat2 ~ [gif, gib];
gi: NATURAL ~ ComposeGI[a, gi2];
gs: Groupings ~ NARROW[a.groupingses[gi]];
ExploreFrom: PROC [ra: REF ANY] ~ {IF ~doomedGroups.HasMember[ra] THEN {
g: Group ~ NARROW[ra];
nonempties: LIST OF Group ← NIL;
stack: LIST OF RECORD [g: Group, t: Tie] ← NIL;
cyclic: BOOLFALSE;
IF g.ports=NIL THEN {
stack ← CONS[[g, NIL], stack];
IF NOT doomedGroups.UnionSingleton[g] THEN ERROR;
};
WHILE stack#NIL DO
h: Group ~ stack.first.g;
avoid: Tie ~ stack.first.t;
CrossTie: PROC [d: Dim, phase: Nat2, jgi: NATURAL, jgi2: Nat2, j: Joint, tie: Tie, side: End] ~ {
IF tie=NIL THEN ERROR;
IF tie#avoid THEN {
i: Group ~ tie.groups[OtherEnd[side]];
IF tie.groups[side]#h THEN ERROR;
IF i=NIL THEN NULL
ELSE IF i.ports=NIL THEN {
ts: TieSpec ~ NEW [TieSpecPrivate ← [j, jgi, tie]];
[] ← doomedTies.UnionSingleton[ts];
IF doomedGroups.UnionSingleton[i] THEN stack ← CONS[[i, tie], stack] ELSE cyclic ← TRUE;
}
ELSE nonempties ← CONS[i, nonempties];
};
};
stack ← stack.rest;
IF h=NIL THEN ERROR;
EnumerateTiesOfGroup[a, h.gi2, h, CrossTie];
ENDLOOP;
IF nonempties=NIL THEN NULL
ELSE IF nonempties.rest=NIL AND NOT cyclic THEN NULL
ELSE ERROR nyet;
}};
gs.groups.Enumerate[ExploreFrom];
ENDLOOP ENDLOOP;
doomedTies.Enumerate[KillTie];
doomedGroups.Enumerate[KillGroup];
};
RetractFalseHypotheses: PUBLIC PROC [act: CellType] = {
IF NOT IsIncompleteArray[act] THEN RETURN;
{a: Array = act.asArray;
SplitGroups[a];
RemakeTies[act, a];
act ← act;
}};
RPDPairList: TYPE = LIST OF RPDPair;
RPDPair: TYPE = REF RPDPairPrivate;
RPDPairPrivate: TYPE = ARRAY End OF SidedPortData;
undef: NAT = LAST[NAT];
RefinableSubset: TYPE = REF RefinableSubsetPrivate;
RefinableSubsetPrivate: TYPE = RECORD [
elts: Set--of RPDPair--,
oldKey, nextRoot: NAT ← undef
];
SplitGroups: PROC [a: Array] = {
dt: Dim = IF a.size[Foo] > 1 THEN Foo ELSE IF a.size[Bar] > 1 THEN Bar ELSE ERROR;
d1: Dim = IF RangeLength[a.groupingParmses[Foo].middle] < RangeLength[a.groupingParmses[Bar].middle] THEN Foo ELSE Bar;
d2: Dim = OtherDim[d1];
FOR ff: NAT IN [0 .. a.jointsPeriod[Foo]) DO FOR fb: NAT IN [0 .. a.jointsPeriod[Bar]) DO
phase: Nat2 = [ff, fb];
wir: Range2 = Range2Div[SizeRange[a.size], a.jointsPeriod, phase];
mcir: Range2 = Range2Div[GPMiddle[a.groupingParmses],a.jointsPeriod,phase];
hasMiddle: ARRAY Dim OF BOOL = [HasMiddle[a.groupingParmses[Foo]], HasMiddle[a.groupingParmses[Bar]]];
SelStart: PROC [d: Dim] RETURNS [mgi: NAT] = {
mgi ← SELECT TRUE FROM
hasMiddle[d] => a.groupingParmses[d].middle.min + phase[d],
a.groupingParmses[d].middle.maxPlusOne <= 0 => 0,
a.groupingParmses[d].middle.maxPlusOne < a.size[d] => ERROR,
ENDCASE => a.groupingParmses[d].middle.min-1;
};
mgi2: Nat2 = [SelStart[Foo], SelStart[Bar]];
mgi: NAT = a.groupingParmses[Bar].sum * mgi2[Foo] + mgi2[Bar];
gsm: Groupings = NARROW[a.groupingses[mgi]];
rfblSetsm: Set--of RefinableSubset-- = CreateHashSet[];
rfblSetse, rfblSetsc: Set--of RefinableSubset--;
toNew: IntHashTable.Table = IntHashTable.Create[];
need: ARRAY [1 .. 4] OF BOOL = [
wir[d1].min < mcir[d1].min,
mcir[d1].maxPlusOne < wir[d1].maxPlusOne,
wir[d2].min < mcir[d2].min AND hasMiddle[d1],
mcir[d2].maxPlusOne < wir[d2].maxPlusOne AND hasMiddle[d1]];
Prep: PROC [i: [1 .. 4]] RETURNS [Set--of RefinableSubset--] = {
IF need[i] THEN {
FOR j: [1 .. 4] IN (i .. 4] DO
IF need[j] THEN RETURN[CopyRefinableSubsets[rfblSetsm]];
ENDLOOP;
RETURN[rfblSetsm]};
RETURN [NIL]};
GetEltRoot: PROC [a: Array, d: Dim, elt: REF ANY, side: End, clai: NAT] RETURNS [root: NAT] = {
rpdPair: RPDPair = NARROW[elt];
root ← GetRoot[a, d, rpdPair[side], clai];
};
MakeGroupSets[a, dt, gsm, rfblSetsm];
IF hasMiddle[Foo] AND hasMiddle[Bar] THEN {
RefineOverRange[a, dt, phase, rfblSetsm, toNew, mcir, GetEltRoot];
SetGroups[mgi2, gsm, rfblSetsm];
};
rfblSetse ← Prep[1];
FOR ci1: INT DECREASING IN [wir[d1].min .. mcir[d1].min) DO
egi2: Nat2 = ConsNat2[d1, ci1*a.jointsPeriod[d1]+phase[d1], mgi2[d2]];
egi: NAT = a.groupingParmses[Bar].sum * egi2[Foo] + egi2[Bar];
gse: Groupings = NARROW[a.groupingses[egi]];
IF hasMiddle[d2] THEN {
RefineOverRange[a, dt, phase, rfblSetse, toNew, ConsRange2[d1, [ci1, ci1+1], mcir[d2]], GetEltRoot];
SetGroups[egi2, gse, rfblSetse];
};
rfblSetsc ← CopyRefinableSubsets[rfblSetse];
FOR ci2: INT DECREASING IN [wir[d2].min .. mcir[d2].min) DO
cgi2: Nat2 = ConsNat2[d2, ci2*a.jointsPeriod[d2]+phase[d2], egi2[d1]];
cgi: NAT = a.groupingParmses[Bar].sum * cgi2[Foo] + cgi2[Bar];
gsc: Groupings = NARROW[a.groupingses[cgi]];
RefineOverRange[a, dt, phase, rfblSetsc, toNew, ConsRange2[d2, [ci2, ci2+1], [ci1, mcir[d1].maxPlusOne]], GetEltRoot];
SetGroups[cgi2, gsc, rfblSetsc];
ENDLOOP;
rfblSetsc ← CopyRefinableSubsets[rfblSetse];
FOR ci2: INT IN [mcir[d2].maxPlusOne .. wir[d2].maxPlusOne) DO
cgi2: Nat2 = ConsNat2[d2, ci2*a.jointsPeriod[d2]+phase[d2] + a.groupingParmses[d2].d, egi2[d1]];
cgi: NAT = a.groupingParmses[Bar].sum * cgi2[Foo] + cgi2[Bar];
gsc: Groupings = NARROW[a.groupingses[cgi]];
RefineOverRange[a, dt, phase, rfblSetsc, toNew, ConsRange2[d2, [ci2, ci2+1], [ci1, mcir[d1].maxPlusOne]], GetEltRoot];
SetGroups[cgi2, gsc, rfblSetsc];
ENDLOOP;
ENDLOOP;
rfblSetse ← Prep[2];
FOR ci1: INT IN [mcir[d1].maxPlusOne .. wir[d1].maxPlusOne) DO
egi2: Nat2 = ConsNat2[d1, ci1*a.jointsPeriod[d1]+phase[d1] + a.groupingParmses[d1].d, mgi2[d2]];
egi: NAT = a.groupingParmses[Bar].sum * egi2[Foo] + egi2[Bar];
gse: Groupings = NARROW[a.groupingses[egi]];
IF hasMiddle[d2] THEN {
RefineOverRange[a, dt, phase, rfblSetse, toNew, ConsRange2[d1, [ci1, ci1+1], mcir[d2]], GetEltRoot];
SetGroups[egi2, gse, rfblSetse];
};
rfblSetsc ← CopyRefinableSubsets[rfblSetse];
FOR ci2: INT DECREASING IN [wir[d2].min .. mcir[d2].min) DO
cgi2: Nat2 = ConsNat2[d2, ci2*a.jointsPeriod[d2]+phase[d2], egi2[d1]];
cgi: NAT = a.groupingParmses[Bar].sum * cgi2[Foo] + cgi2[Bar];
gsc: Groupings = NARROW[a.groupingses[cgi]];
RefineOverRange[a, dt, phase, rfblSetsc, toNew, ConsRange2[d2, [ci2, ci2+1], [mcir[d1].min, ci1+1]], GetEltRoot];
SetGroups[cgi2, gsc, rfblSetsc];
ENDLOOP;
rfblSetsc ← CopyRefinableSubsets[rfblSetse];
FOR ci2: INT IN [mcir[d2].maxPlusOne .. wir[d2].maxPlusOne) DO
cgi2: Nat2 = ConsNat2[d2, ci2*a.jointsPeriod[d2]+phase[d2] + a.groupingParmses[d2].d, egi2[d1]];
cgi: NAT = a.groupingParmses[Bar].sum * cgi2[Foo] + cgi2[Bar];
gsc: Groupings = NARROW[a.groupingses[cgi]];
RefineOverRange[a, dt, phase, rfblSetsc, toNew, ConsRange2[d2, [ci2, ci2+1], [mcir[d1].min, ci1+1]], GetEltRoot];
SetGroups[cgi2, gsc, rfblSetsc];
ENDLOOP;
ENDLOOP;
IF hasMiddle[d1] THEN {
rfblSetse ← Prep[3];
FOR ci2: INT DECREASING IN [wir[d2].min .. mcir[d2].min) DO
egi2: Nat2 = ConsNat2[d2, ci2*a.jointsPeriod[d2]+phase[d2], mgi2[d1]];
egi: NAT = a.groupingParmses[Bar].sum * egi2[Foo] + egi2[Bar];
gse: Groupings = NARROW[a.groupingses[egi]];
RefineOverRange[a, dt, phase, rfblSetse, toNew, ConsRange2[d2, [ci2, ci2+1], mcir[d1]], GetEltRoot];
SetGroups[egi2, gse, rfblSetse];
ENDLOOP;
};
IF hasMiddle[d1] THEN {
rfblSetse ← Prep[4];
FOR ci2: INT IN [mcir[d2].maxPlusOne .. wir[d2].maxPlusOne) DO
egi2: Nat2 = ConsNat2[d2, ci2*a.jointsPeriod[d2]+phase[d2] + a.groupingParmses[d2].d, mgi2[d1]];
egi: NAT = a.groupingParmses[Bar].sum * egi2[Foo] + egi2[Bar];
gse: Groupings = NARROW[a.groupingses[egi]];
RefineOverRange[a, dt, phase, rfblSetse, toNew, ConsRange2[d2, [ci2, ci2+1], mcir[d1]], GetEltRoot];
SetGroups[egi2, gse, rfblSetse];
ENDLOOP;
};
a ← a;
ENDLOOP ENDLOOP;
a ← a;
};
MakeGroupSets: PROC [a: Array, dt: Dim, gs: Groupings, rfblSets: Set--of RefinableSubset--] = {
StartSet: PROC [ra: REF ANY] = {
g: Group = NARROW[ra];
rfblSet: RefinableSubset = NEW [RefinableSubsetPrivate ← [elts: CreateHashSet[] ]];
FOR ports: PortList ← g.ports, ports.rest WHILE ports # NIL DO
rpdPair: RPDPair = NEW [RPDPairPrivate ← [
low: NARROW[a.toRole[dt][low].Fetch[ports.first].val],
high: NARROW[a.toRole[dt][high].Fetch[ports.first].val] ]];
IF NOT rfblSet.elts.UnionSingleton[rpdPair] THEN ERROR;
ENDLOOP;
IF NOT rfblSets.UnionSingleton[rfblSet] THEN ERROR;
};
gs.groups.Enumerate[StartSet];
};
SetGroups: PROC [gi2: Nat2, gs: Groupings, rfblSets: Set--of RefinableSubset--] = {
Transfer: PROC [ra: REF ANY] = {
rfblSet: RefinableSubset = NARROW[ra];
g: Group = NEW [GroupPrivate ← [gi2: gi2]];
TransferPort: PROC [ra: REF ANY] = {
rpdPair: RPDPair = NARROW[ra];
IF rpdPair[low] = NIL OR rpdPair[high] = NIL THEN ERROR;
{port: Port = rpdPair[low].port;
g.ports ← CONS[port, g.ports];
IF NOT gs.toGroup.Store[port, g] THEN ERROR;
}};
rfblSet.elts.Enumerate[TransferPort];
IF NOT gs.groups.UnionSingleton[g] THEN ERROR;
};
gs.toGroup.Erase[];
gs.groups ← CreateHashSet[];
rfblSets.Enumerate[Transfer];
};
CopyRefinableSubsets: PROC [original: Set--of RefinableSubset--] RETURNS [copy: Set--of RefinableSubset--] = {
CopyRefinableSubset: PROC [ra: REF ANY] = {
urSet: RefinableSubset = NARROW[ra];
newSet: RefinableSubset = NEW [RefinableSubsetPrivate ← [elts: CreateHashSet[] ]];
MoveRPD: PROC [ra: REF ANY] = {
IF NOT newSet.elts.UnionSingleton[ra] THEN ERROR;
};
urSet.elts.Enumerate[MoveRPD];
IF NOT copy.UnionSingleton[newSet] THEN ERROR;
};
copy ← CreateHashSet[];
original.Enumerate[CopyRefinableSubset];
copy ← copy;
};
RefineOverRange: PROC [a: Array, dt: Dim, phase: Nat2, rfblSets: Set--of RefinableSubset--, toNew: IntHashTable.Table, cir: Range2, GetEltRoot: PROC [a: Array, d: Dim, elt: REF ANY, side: End, clai: NAT] RETURNS [root: NAT]] = {
jSize: Nat2 = Nat2Tweak[a.size, dt, -1];
FOR cif: INT IN [cir[Foo].min .. cir[Foo].maxPlusOne) DO FOR cib: INT IN [cir[Bar].min .. cir[Bar].maxPlusOne) DO
lai: Nat2 ← Nat2Add[Nat2Mul[[cif, cib], a.jointsPeriod], phase];
side: End ← low;
clai: NAT ← jSize[Bar]*lai[Foo] + lai[Bar];
oldKey: NAT ← 0;
ResetSet: PROC [ra: REF ANY] = {
rfblSet: RefinableSubset = NARROW[ra];
rfblSet.oldKey ← oldKey;
oldKey ← oldKey + 1;
rfblSet.nextRoot ← undef};
RefineSet: PROC [ra: REF ANY] = {
rfblSet: RefinableSubset = NARROW[ra];
RefineElt: PROC [ra: REF ANY] = {
elt: REF ANY = ra;
root: NAT = GetEltRoot[a, dt, elt, side, clai];
SELECT rfblSet.nextRoot FROM
root => NULL;
undef => rfblSet.nextRoot ← root;
ENDCASE => {
both: Basics.LongNumber = [pair[rfblSet.oldKey, root]];
newSet: RefinableSubset ← NARROW[toNew.Fetch[both.li].value];
IF newSet = NIL THEN {
newSet ← NEW [RefinableSubsetPrivate ← [
elts: CreateHashSet[],
oldKey: rfblSet.oldKey,
nextRoot: root]];
IF NOT toNew.Insert[both.li, newSet] THEN ERROR;
IF NOT rfblSets.UnionSingleton[newSet] THEN ERROR;
};
IF NOT newSet.elts.UnionSingleton[elt] THEN ERROR;
IF NOT rfblSet.elts.RemoveElt[elt] THEN ERROR;
};
};
rfblSet.elts.Enumerate[RefineElt];
};
IF lai[dt] = jSize[dt] THEN {
side ← high;
lai[dt] ← lai[dt] - 1;
clai ← clai - (IF dt=Foo THEN jSize[Bar] ELSE 1)};
rfblSets.Enumerate[ResetSet];
rfblSets.Enumerate[RefineSet];
toNew.Erase[];
ENDLOOP ENDLOOP;
};
RemakeTies: PROC [act: CellType, a: Array] = {
d1: Dim = IF RangeLength[a.groupingParmses[Foo].middle] < RangeLength[a.groupingParmses[Bar].middle] THEN Foo ELSE Bar;
d2: Dim = OtherDim[d1];
FOR ff: NAT IN [0 .. a.jointsPeriod[Foo]) DO FOR fb: NAT IN [0 .. a.jointsPeriod[Bar]) DO FOR dj: Dim IN Dim DO
phase: Nat2 = [ff, fb];
j: Joint = GetArrayJoint[a, dj, phase];
IF j.size = 0 THEN LOOP;
{wir: Range2 = SizeRange[j.size2];
mcir: Range2 = GPMiddle[j.groupingParmses];
hasMiddle: ARRAY Dim OF BOOL = [HasMiddle[a.groupingParmses[Foo]], HasMiddle[a.groupingParmses[Bar]]];
SelStart: PROC [di: Dim] RETURNS [mji: NAT] = {
mji ← SELECT TRUE FROM
hasMiddle[di] => j.groupingParmses[di].middle.min,
a.groupingParmses[di].middle.maxPlusOne <= 0 => 0,
a.groupingParmses[di].middle.maxPlusOne < j.size2[di] => ERROR,
ENDCASE => a.groupingParmses[di].middle.min-1;
};
mji2: Nat2 = [SelStart[Foo], SelStart[Bar]];
mji: NAT = j.groupingParmses[Bar].sum * mji2[Foo] + mji2[Bar];
tsm: Set--of Tie-- = NARROW[j.ties[mji]];
rfblSetsm: Set--of RefinableSubset-- = CreateHashSet[];
rfblSetse, rfblSetsc: Set--of RefinableSubset--;
toNew: IntHashTable.Table = IntHashTable.Create[];
need: ARRAY [1 .. 4] OF BOOL = [
wir[d1].min < mcir[d1].min,
mcir[d1].maxPlusOne < wir[d1].maxPlusOne,
wir[d2].min < mcir[d2].min AND hasMiddle[d1],
mcir[d2].maxPlusOne < wir[d2].maxPlusOne AND hasMiddle[d1]];
Prep: PROC [i: [1 .. 4]] RETURNS [Set--of RefinableSubset--] = {
IF need[i] THEN {
FOR j: [1 .. 4] IN (i .. 4] DO
IF need[j] THEN RETURN[CopyRefinableSubsets[rfblSetsm]];
ENDLOOP;
RETURN[rfblSetsm]};
RETURN [NIL]};
GetEltRoot: PROC [a: Array, d: Dim, elt: REF ANY, side: End, clai: NAT] RETURNS [root: NAT] = {
rpd: SidedPortData = NARROW[elt];
IF side # low THEN ERROR;
root ← GetRoot[a, d, rpd, clai];
};
MakeTieSets[a, dj, tsm, rfblSetsm];
IF hasMiddle[Foo] AND hasMiddle[Bar] THEN {
RefineOverRange[a, dj, phase, rfblSetsm, toNew, mcir, GetEltRoot];
SetTies[act, a, dj, phase, j, mji2, rfblSetsm];
};
rfblSetse ← Prep[1];
FOR ci1: INT DECREASING IN [wir[d1].min .. mcir[d1].min) DO
eji2: Nat2 = ConsNat2[d1, ci1, mji2[d2]];
IF hasMiddle[d2] THEN {
RefineOverRange[a, dj, phase, rfblSetse, toNew, ConsRange2[d1, [ci1, ci1+1], mcir[d2]], GetEltRoot];
SetTies[act, a, dj, phase, j, eji2, rfblSetse];
};
rfblSetsc ← CopyRefinableSubsets[rfblSetse];
FOR ci2: INT DECREASING IN [wir[d2].min .. mcir[d2].min) DO
cji2: Nat2 = ConsNat2[d2, ci2, eji2[d1]];
RefineOverRange[a, dj, phase, rfblSetsc, toNew, ConsRange2[d2, [ci2, ci2+1], [ci1, mcir[d1].maxPlusOne]], GetEltRoot];
SetTies[act, a, dj, phase, j, cji2, rfblSetsc];
ENDLOOP;
rfblSetsc ← CopyRefinableSubsets[rfblSetse];
FOR ci2: INT IN [mcir[d2].maxPlusOne .. wir[d2].maxPlusOne) DO
cji2: Nat2 = ConsNat2[d2, ci2 + j.groupingParmses[d2].d, eji2[d1]];
RefineOverRange[a, dj, phase, rfblSetsc, toNew, ConsRange2[d2, [ci2, ci2+1], [ci1, mcir[d1].maxPlusOne]], GetEltRoot];
SetTies[act, a, dj, phase, j, cji2, rfblSetsc];
ENDLOOP;
ENDLOOP;
rfblSetse ← Prep[2];
FOR ci1: INT IN [mcir[d1].maxPlusOne .. wir[d1].maxPlusOne) DO
eji2: Nat2 = ConsNat2[d1, ci1 + j.groupingParmses[d1].d, mji2[d2]];
IF hasMiddle[d2] THEN {
RefineOverRange[a, dj, phase, rfblSetse, toNew, ConsRange2[d1, [ci1, ci1+1], mcir[d2]], GetEltRoot];
SetTies[act, a, dj, phase, j, eji2, rfblSetse];
};
rfblSetsc ← CopyRefinableSubsets[rfblSetse];
FOR ci2: INT DECREASING IN [wir[d2].min .. mcir[d2].min) DO
cji2: Nat2 = ConsNat2[d2, ci2, eji2[d1]];
RefineOverRange[a, dj, phase, rfblSetsc, toNew, ConsRange2[d2, [ci2, ci2+1], [mcir[d1].min, ci1+1]], GetEltRoot];
SetTies[act, a, dj, phase, j, cji2, rfblSetsc];
ENDLOOP;
rfblSetsc ← CopyRefinableSubsets[rfblSetse];
FOR ci2: INT IN [mcir[d2].maxPlusOne .. wir[d2].maxPlusOne) DO
cji2: Nat2 = ConsNat2[d2, ci2 + j.groupingParmses[d2].d, eji2[d1]];
RefineOverRange[a, dj, phase, rfblSetsc, toNew, ConsRange2[d2, [ci2, ci2+1], [mcir[d1].min, ci1+1]], GetEltRoot];
SetTies[act, a, dj, phase, j, cji2, rfblSetsc];
ENDLOOP;
ENDLOOP;
IF hasMiddle[d1] THEN {
rfblSetse ← Prep[3];
FOR ci2: INT DECREASING IN [wir[d2].min .. mcir[d2].min) DO
eji2: Nat2 = ConsNat2[d2, ci2, mji2[d1]];
RefineOverRange[a, dj, phase, rfblSetse, toNew, ConsRange2[d2, [ci2, ci2+1], mcir[d1]], GetEltRoot];
SetTies[act, a, dj, phase, j, eji2, rfblSetse];
ENDLOOP;
};
IF hasMiddle[d1] THEN {
rfblSetse ← Prep[4];
FOR ci2: INT IN [mcir[d2].maxPlusOne .. wir[d2].maxPlusOne) DO
eji2: Nat2 = ConsNat2[d2, ci2 + j.groupingParmses[d2].d, mji2[d1]];
RefineOverRange[a, dj, phase, rfblSetse, toNew, ConsRange2[d2, [ci2, ci2+1], mcir[d1]], GetEltRoot];
SetTies[act, a, dj, phase, j, eji2, rfblSetse];
ENDLOOP;
};
a ← a;
}ENDLOOP ENDLOOP ENDLOOP;
a ← a;
};
MakeTieSets: PROC [a: Array, dj: Dim, ts: Set--of Tie--, rfblSets: Set--of RefinableSubset--] = {
StartSet: PROC [ra: REF ANY] = {
t: Tie = NARROW[ra];
rfblSet: RefinableSubset = NEW [RefinableSubsetPrivate ← [elts: CreateHashSet[] ]];
FOR side: End IN End DO
IF t.groups[side] # NIL THEN FOR ports: PortList ← t.groups[side].ports, ports.rest WHILE ports # NIL DO
rpd: SidedPortData = NARROW[a.toRole[dj][side].Fetch[ports.first].val];
IF rpd = NIL THEN ERROR;
IF NOT rfblSet.elts.UnionSingleton[rpd] THEN ERROR;
ENDLOOP;
ENDLOOP;
IF rfblSet.elts.Size[] = 0 THEN ERROR;
IF NOT rfblSets.UnionSingleton[rfblSet] THEN ERROR;
};
ts.Enumerate[StartSet];
};
RoledGroupList: TYPE = LIST OF RoledGroup;
RoledGroup: TYPE = REF RoledGroupPrivate;
RoledGroupPrivate: TYPE = RECORD [side: End, g: Group];
GroupPairList: TYPE = LIST OF GroupPair;
GroupPairRef: TYPE = REF GroupPair;
GroupPair: TYPE = ARRAY End OF Group;
SetTies: PROC [act: CellType, a: Array, d: Dim, phase: Nat2, j: Joint, jgi2: Nat2, rfblSets: Set--of RefinableSubset--] = {
jSize: Nat2 = Nat2Tweak[a.size, d, -1];
jgi: NAT = j.groupingParmses[Bar].sum * jgi2[Foo] + jgi2[Bar];
gip: GIPair = Jgi2ToGip[a, d, phase, j, jgi2];
oldTS: Set--of Tie-- = NARROW[j.ties[jgi]];
newTS: Set--of Tie-- = CreateHashSet[];
g2t: ARRAY End OF RefTable--Group b Tie-- = [NARROW[j.toTie[low][jgi]], NARROW[j.toTie[high][jgi]]];
Transfer: PROC [ra: REF ANY] = {
rfblSet: RefinableSubset = NARROW[ra];
groupses: ARRAY End OF GroupList ← ALL[NIL];
TransferPort: PROC [ra: REF ANY] = {
rpd: SidedPortData = NARROW[ra];
g: Group = PortToGroup[a, gip[rpd.side], rpd.port];
groupses[rpd.side] ← NARROW[GList.Union[groupses[rpd.side], NARROW[LIST[g], GroupList]]];
};
rfblSet.elts.Enumerate[TransferPort];
IF groupses[low] # NIL AND groupses[high] # NIL THEN {
t: Tie = NEW [TiePrivate ← [groups: [groupses[low].first, groupses[high].first]]];
IF NOT newTS.UnionSingleton[t] THEN ERROR;
FOR side: End IN End DO
IF NOT g2t[side].Store[t.groups[side], t] THEN ERROR;
ENDLOOP;
};
};
toPair: ARRAY End OF RefTable = [CreateRefTable[], CreateRefTable[]];
Patch: PROC [ra: REF ANY] = {
oldTie: Tie = NARROW[ra];
lair: Range2 = Jgi2ToLair[a, phase, j, jgi2].lair;
gpl: GroupPairList ← NIL;
size: NAT ← 0;
toPair[low].Erase[];
toPair[high].Erase[];
FOR side: End IN End DO
otherSide: End = OtherEnd[side];
oldG: Group = oldTie.groups[side];
IF oldG # NIL THEN FOR ports: PortList ← oldG.ports, ports.rest WHILE ports # NIL DO
newG: Group = PortToGroup[a, gip[side], ports.first];
IF toPair[side].Fetch[newG].found THEN LOOP;
{newTie: Tie = FetchTie[j, side, jgi, newG];
IF newTie # NIL AND newTie.groups[side] # newG THEN ERROR;
gpl ← CONS[[NIL, NIL], gpl];
size ← size + 1;
IF newTie # NIL THEN gpl.first ← newTie.groups ELSE gpl.first[side] ← newG;
IF NOT toPair[side].Store[newG, gpl] THEN ERROR;
IF newTie # NIL AND NOT toPair[otherSide].Store[gpl.first[otherSide], gpl] THEN ERROR;
}ENDLOOP;
ENDLOOP;
{rootToPairs: ICHT.Table = ICHT.Create[-1, size/4*6+5];
FOR laif: INT IN [lair[Foo].min .. lair[Foo].maxPlusOne) DO FOR laib: INT IN [lair[Bar].min .. lair[Bar].maxPlusOne) DO
lai: ArrayIndex = [laif, laib];
hai: ArrayIndex = Int2Tweak[lai, d, 1];
clai: NAT = jSize[Bar]*laif + laib;
gis, giis: ARRAY End OF Nat2;
FOR gps: GroupPairList ← gpl, gps.rest WHILE gps # NIL DO
rpd: SidedPortData = IF gps.first[low] # NIL THEN FetchRPD[a, d, [low, gps.first[low].ports.first]] ELSE FetchRPD[a, d, [high, gps.first[high].ports.first]];
root: NAT = GetRoot[a, d, rpd, clai];
pairs: REF GroupListPair ← NARROW[rootToPairs.Fetch[root].value];
IF pairs = NIL AND NOT rootToPairs.Store[root, pairs ← NEW [GroupListPair ← [NIL, NIL]]] THEN ERROR;
IF gps.first[low] # NIL THEN pairs[low] ← CONS[gps.first[low], pairs[low]];
IF gps.first[high] # NIL THEN pairs[high] ← CONS[gps.first[high], pairs[high]];
ENDLOOP;
[gi2: gis[low], gii2: giis[low]] ← ComputeGroupingsIndex[a, lai];
[gi2: gis[high], gii2: giis[high]] ← ComputeGroupingsIndex[a, hai];
{lastPort: Port ← NIL;
Export: PROC [key: INT, value: REF ANY] RETURNS [quit: BOOLFALSE] --ICHT.EachPairAction-- = {
pairs: REF GroupListPair = NARROW[value];
thisPort: Port = EnsurePortForGroups[act, gis, giis, pairs^];
ConnectInstance: PROC [ci: CellInstance] = {
w1: Wire = FindTransitiveConnection[ci, lastPort];
w2: Wire = FindTransitiveConnection[ci, thisPort];
IF w1 # w2 THEN [] ← MergeNets[w1, w2];
};
ConnectArrayElts: PROC [pct: CellType] = {
pa: Array = pct.asArray;
IF NOT MakeArrayConnection[pct, Foo, SizeRange[Nat2Tweak[pa.size, Foo, -1]], [low, lastPort], [low, thisPort], TRUE] THEN ERROR;
IF NOT MakeArrayConnection[pct, Foo, SizeRange[Nat2Tweak[pa.size, Foo, -1]], [high, lastPort], [high, thisPort], TRUE] THEN ERROR;
};
IF lastPort # NIL THEN {
EnumerateInstances[act, ConnectInstance];
EnumerateArrays[act, ConnectArrayElts];
};
lastPort ← thisPort;
};
[] ← rootToPairs.Pairs[Export];
rootToPairs.Erase[];
}ENDLOOP ENDLOOP;
}};
j.ties[jgi] ← newTS;
FOR side: End IN End DO g2t[side].Erase[] ENDLOOP;
rfblSets.Enumerate[Transfer];
oldTS.Enumerate[Patch];
};
TrimArray: PUBLIC PROC [a: Array] = {
FOR d: Dim IN Dim DO
FOR ff: NAT IN [0 .. a.jointsPeriod[Foo]) DO FOR fb: NAT IN [0 .. a.jointsPeriod[Bar]) DO
phase: Nat2 = [ff, fb];
j: Joint = GetArrayJoint[a, d, phase];
FOR jgi: NAT IN [0 .. j.ties.length) DO
ties: Set--of Tie-- = NARROW[j.ties[jgi]];
PruneTie: PROC [ra: REF ANY] = {
tie: Tie = NARROW[ra];
IF tie.completion = NIL AND (tie.groups[low] = NIL OR tie.groups[high] = NIL) THEN DeleteTie[j, jgi, tie];
};
ties.Enumerate[PruneTie];
ENDLOOP;
ENDLOOP ENDLOOP;
ENDLOOP;
FOR d: Dim IN Dim DO
FOR index: NAT IN [0 .. a.roles[d].length) DO
rpd: SidedPortData ~ NARROW[a.roles[d].refs[index]];
IF rpd=NIL THEN --it's a deleted index--LOOP;
IF rpd.links # NIL AND NOT RPDNeedsLinks[a, d, rpd] THEN rpd.links ← NIL;
ENDLOOP;
ENDLOOP;
};
FmtIndex: PUBLIC PROC [a: Array, index: ArrayIndex] RETURNS [asRope: ROPE] = {
asRope ← SELECT TRUE FROM
a.size[Foo]=1 => Subscript[NIL, index[Bar]],
a.size[Bar]=1 => Subscript[NIL, index[Foo]],
ENDCASE => Subscript2[NIL, index];
};
sublen: NATURAL ~ 64;
subs: ARRAY [0 .. sublen) OF ROPEALL[NIL];
Subscript: PUBLIC PROC [base: ROPE, index: INT] RETURNS [sub: ROPE] ~ {
sub ← IF index < sublen THEN sub ← base.Concat[subs[index]] ELSE sub ← Rope.Cat[base, "[", Convert.RopeFromInt[index], "]"];
};
sub2len: NATURAL ← 2000;
sub2Ps: LRUCache.Handle ← LRUCache.Create[sub2len, HashAI, EqualAI];
sub2Rs: RefSeq ← CreateRefSeq[sub2len];
s2probes, s2misses: CARD ← 0;
HashAI: PROC [ra: REF ANY] RETURNS [CARDINAL] --LRUCache.HashProc-- ~ {
rai: REF ArrayIndex ~ NARROW[ra];
lnF: Basics.LongNumber ~ [li[rai[Foo]]];
lnB: Basics.LongNumber ~ [li[rai[Bar]]];
ln: Basics.LongNumber ~ [lc[lnF.lo + lnF.hi*3 + lnB.lo*5 + lnB.hi*7]];
RETURN [ln.lo+ln.hi];
};
EqualAI: PROC [r1, r2: REF ANY] RETURNS [BOOL] --LRUCache.EqualProc-- ~ {
rai1: REF ArrayIndex ~ NARROW[r1];
rai2: REF ArrayIndex ~ NARROW[r2];
RETURN [rai1^ = rai2^]};
Subscript2: PUBLIC PROC [base: ROPE, index: ArrayIndex] RETURNS [sub: ROPE] ~ {
rai: REF ArrayIndex ~ NEW [ArrayIndex ← index];
p: NATURAL;
news: BOOL;
[p, news, ] ← sub2Ps.Include[rai];
s2probes ← s2probes+1;
IF news THEN {
sub2Rs[p] ← Rope.Cat["[", Convert.RopeFromInt[index[Foo]], ", ", Convert.RopeFromInt[index[Bar]], "]"];
s2misses ← s2misses+1;
};
RETURN [base.Concat[NARROW[sub2Rs[p]]]];
};
Start: PROC ~ {
FOR index: NATURAL IN [0 .. sublen) DO
subs[index] ← Rope.Cat["[", Convert.RopeFromInt[index], "]"];
ENDLOOP;
};
Start[];
END.