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 d
j: 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 [d
e: 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
f
f:
INT
IN [0 .. a.jointsPeriod[Foo])
DO
FOR
f
b:
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 jgi
f:
NAT
IN [0 .. j.groupingParmses[Foo].sum)
DO
FOR jgi
b:
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 gi
f:
NATURAL
IN [0 .. a.groupingParmses[Foo].sum)
DO
FOR gi
b:
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: BOOL ← FALSE;
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
f
f:
NAT
IN [0 .. a.jointsPeriod[Foo])
DO
FOR
f
b:
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 ci
1:
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 ci
2:
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 ci
2:
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 ci
1:
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 ci
2:
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 ci
2:
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 ci
2:
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 ci
2:
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, d
t: 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, d
t: 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 ci
f:
INT
IN [cir[Foo].min .. cir[Foo].maxPlusOne)
DO
FOR ci
b:
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[d
t] = jSize[d
t]
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
f
f:
NAT
IN [0 .. a.jointsPeriod[Foo])
DO
FOR
f
b:
NAT
IN [0 .. a.jointsPeriod[Bar])
DO
FOR d
j: 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 [d
i: 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 ci
1:
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 ci
2:
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 ci
2:
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 ci
1:
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 ci
2:
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 ci
2:
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 ci
2:
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 ci
2:
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, d
j: 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 lai
f:
INT
IN [lair[Foo].min .. lair[Foo].maxPlusOne)
DO
FOR lai
b:
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:
BOOL ←
FALSE]
--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
f
f:
NAT
IN [0 .. a.jointsPeriod[Foo])
DO
FOR
f
b:
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 ROPE ← ALL[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.