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 = 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] 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 _ 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: 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 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 _ 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: 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 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 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. "LichenArray2Impl.Mesa Last tweaked by Mike Spreitzer on April 30, 1987 1:47:09 pm PDT 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. Κ-Ύ˜™Icode™?—J˜KšΟk œWœX˜ΊK˜šΠbxœœ˜Kšœ”˜›Kšœ&˜-™ K™BK™8K™?—Kšœ˜—K˜Kšœœœ]˜lK˜KšΟnœœœ˜K˜šŸ œœœ Οgœ œœœ˜D˜Kšœ  œ œ˜Kšœ œ œ˜ —K˜—K˜š Ÿ œœœ  œ œœ˜G˜˜Kšœ œ œ˜ Kšœ œ œ˜/—˜Kšœ œ œ˜ Kšœ œ œ˜0——K˜—K˜šŸ œœœ  œ œœœ˜D˜Kš œ œ œ œ œ˜#Kšœ& œ œ˜1—K˜—K˜š Ÿ œœœ  œ œœ˜G˜˜Kš œ œ  œ  œ œ˜7Kšœ+ œ œ ˜@—˜Kš œ œ  œ  œ œ˜7Kšœ+ œ œ ˜A——K˜—K˜š Ÿ œœœ/œœ˜sšŸœœ œ˜,šœœ˜Kšœ-œ˜Kšœ.˜.Kšœ* œ˜,Kšœ˜!—Kšœœ˜0—K˜—KšœŸœ Ÿœ ˜&Kšœ˜Kšœ.˜.K˜—K˜š Ÿ œœœŸœœ6˜rK˜ Kšœ#˜#šœœ˜šœ œœ˜Kšœ3œ˜IKšœ,œ œœ˜gKšœ œ"˜9—Kšœ˜—šœΟdœœ˜Kšœ/‘œ˜7Kšœ‘œ ˜'šœ œ˜Kš œ+œ œœ‘œ ˜lKšœ œœ$œ˜ZKšœ/ œ˜2š Ÿœœ‘œŸœœœ˜-šœ˜Kšœœ‘œ‘œ˜8Kšœ œ‘œ!‘œ˜N—Kš œœœ‘œœœ˜AKšœœœ‘œœ ‘œ œœ˜gKšœœ‘œ˜KK˜—šŸœœœ˜KšŸœœœ‘œ!˜FK˜—K˜Kšœ˜—Kšœ˜—K˜—K˜š Ÿœœœœ"œ˜]šŸœœ œœ˜7šœœ˜Kšœ*œ˜Išœ+˜+Kšœ( œ˜*Kšœ˜"—šœ˜ Kš œœ,˜2KšœH œ˜KKšœ% œ˜BKšœ˜——K˜—K˜"Kšœ"˜"Kšœ˜K˜—K˜š Ÿœœœ Ÿœœ%˜Zšœœ˜šœ ‘œœœœœ ‘œœœ˜YKšœ ‘œ ‘œ˜Kšœ&˜&K˜Kšœœ˜—Kšœ˜—K˜—K˜š Ÿ œœœ Ÿœœœ&˜|šŸœœ$˜0Kšœœ˜ š œ‘œœœ#˜5š œ‘œœœ#˜5Kšœ‘œ‘œ˜Kšœ Οc œœ˜*šŸœœœœ˜Kšœ#œ˜0—K˜K˜Kšœ˜—Kšœ˜—Kšœœœ˜"K˜—Kšœ˜K˜—K˜š Ÿœœœ!Ÿœœœ1˜£šŸœœ;˜GKšœœ˜#Kšœ ’ œœ˜*šŸœœœœ˜Kšœ œ˜K˜ šœ˜ K˜K˜ Kšœœ˜—Kšœ+˜+K˜—K˜K˜K˜—K˜K˜K˜—K˜š Ÿœœœœœ˜LK˜Kšœ œ˜Kšœœœœ˜šœœ˜šœ œœ˜/Kšœ œ˜'Kšœœ;˜Dšœœœ ˜Kšœ ’ œœ˜*šŸœœœœ˜Kšœ œ˜Kšœœœœ˜/K˜—K˜Kšœ œœ˜Kšœ˜—Kšœ˜—Kšœ˜—K˜Kšœ˜—K˜š Ÿ œœœ@œœ˜lKšœœ˜(Kš œœœœœ˜ Kšœ$˜$Kšœ˜KšœB˜BKšœœ$˜.Kšœ ˜K˜—K˜šŸœœœœ˜Kšœœœœ˜-Kšœœœœ˜.K˜—Kšœ"˜"K˜K˜Kšœ&˜&K˜KšŸœœœ˜—K˜Kšœ œœ˜#šœœœ˜K˜ Kšœœ˜ K˜K˜—K˜šŸ œœœœœœ’ œ˜DKšœœ˜Kšœ*˜0K˜—K˜šŸ œœœœœœ’ œ˜JKšœœ˜Kšœœ˜Kšœ˜K˜—K˜šŸœœœ˜+Kšœ’ œ˜0Kšœ’œ/˜LšŸœœœœ˜Kšœœ˜K˜ K˜—šŸ œœœœ˜!Kšœ œ˜Kšœ˜K˜—šœ‘œœœ#œœ‘œœœ#˜qKšœ‘œ‘œ˜Kšœœ˜ Kšœœ˜*š Ÿ œœœœœœ˜HKšœ œ˜Kšœ œœ œ˜ Kš œœœœœ˜/Kšœœœ˜šœ œœ˜Kšœœœ ˜Kšœœ œœ˜1K˜—šœœ˜K˜K˜šŸœœœ0˜aKšœœœœ˜šœ œ˜Kšœ&˜&Kšœœœ˜!Kšœœœ˜šœœ œœ˜Kšœœ"˜3Kšœ#˜#Kš œ œ œœ œ˜XK˜—Kšœœ˜&K˜—K˜—K˜Kšœœœœ˜Kšœ,˜,Kšœ˜—Kšœ œœ˜Kš œœœœœœ˜4Kšœœ˜K˜—K˜!Kšœœ˜—K˜K˜"K˜—K˜šŸœœœ˜7Kšœœœœ˜*K˜K˜K˜K˜ K˜—K˜Kšœ œœœ ˜$Kšœ œœ˜#Kšœœœœ˜2Kšœœœœ˜K˜Kšœœœ˜3šœœœ˜'Kšœ ’œ˜Kšœœ˜K˜—K˜šŸ œœ˜ Kšœ‘œœœœœœœœ˜RKšœ œYœœ˜wK˜šœ ‘œœœœœ ‘œœœ˜YKšœ ‘œ ‘œ˜KšœB˜BKšœK˜KKšœ œœœJ˜fšŸœœ œœ˜.šœœœ˜Kšœ;˜;Kšœ1˜1Kšœ6œ˜Kšœ‘œœ˜,Kšœ‘œ’œ˜7Kšœ‘œ ‘œ’œ˜0K˜2šœœ œœ˜ Kšœ˜Kšœ)˜)Kšœœ˜-Kšœ)œ˜<—šŸœœœ’œ˜@šœ œ˜šœ œ ˜Kšœ œœ‘œ˜8Kšœ˜—Kšœ ‘œ˜—Kšœœ˜—šŸ œœœœœœœ˜_Kšœœ˜Kšœ*˜*K˜—Kšœ‘œ‘œ ‘œ˜%šœœœ˜+Kšœ‘œ‘œ˜BKšœ‘œ ‘œ˜ K˜—Kšœ‘œ ˜š œ‘œœ œœ˜;Kšœ‘œ)˜FKšœœ6˜>Kšœ‘œœ˜,šœœ˜Kš œ‘œ‘œ‘œ‘œ˜dKšœ‘œ ‘œ˜ K˜—Kšœ‘œ ‘œ˜,š œ‘œœ œœ˜;Kšœ‘œ)˜FKšœœ6˜>Kšœ‘œœ˜,Kš œ‘œ‘œ‘œ‘œ‘œ%˜vKšœ‘œ ‘œ˜ Kšœ˜—Kšœ‘œ ‘œ˜,š œ‘œœœ-˜>Kšœ‘œ6 œ ˜`Kšœœ6˜>Kšœ‘œœ˜,Kš œ‘œ‘œ‘œ‘œ‘œ%˜vKšœ‘œ ‘œ˜ Kšœ˜—Kšœ˜—Kšœ‘œ ˜š œ‘œœœ-˜>Kšœ‘œ6 œ ˜`Kšœœ6˜>Kšœ‘œœ˜,šœœ˜Kš œ‘œ‘œ‘œ‘œ˜dKšœ‘œ ‘œ˜ K˜—Kšœ‘œ ‘œ˜,š œ‘œœ œœ˜;Kšœ‘œ)˜FKšœœ6˜>Kšœ‘œœ˜,Kš œ‘œ‘œ‘œ‘œ‘œ˜qKšœ‘œ ‘œ˜ Kšœ˜—Kšœ‘œ ‘œ˜,š œ‘œœœ-˜>Kšœ‘œ6 œ ˜`Kšœœ6˜>Kšœ‘œœ˜,Kš œ‘œ‘œ‘œ‘œ‘œ˜qKšœ‘œ ‘œ˜ Kšœ˜—Kšœ˜—šœœ˜Kšœ‘œ ˜š œ‘œœ œœ˜;Kšœ‘œ)˜FKšœœ6˜>Kšœ‘œœ˜,Kš œ‘œ‘œ‘œ‘œ˜dKšœ‘œ ‘œ˜ Kšœ˜—K˜—šœœ˜Kšœ‘œ ˜š œ‘œœœ-˜>Kšœ‘œ6 œ ˜`Kšœœ6˜>Kšœ‘œœ˜,Kš œ‘œ‘œ‘œ‘œ˜dKšœ‘œ ‘œ˜ Kšœ˜—K˜—K˜Kšœœ˜—K˜Kšœ˜—K˜šŸ œœ ‘œ#’œ˜_šŸœœœœ˜ Kšœ œ˜Kšœœ5˜Sšœ'œ œ˜>šœœ˜*Kšœœ ‘œ˜6Kšœœ ‘œ#˜;—Kšœœ&œœ˜7Kšœ˜—Kšœœ"œœ˜3K˜—K˜Kšœ˜—K˜šŸ œœ)’œ˜SšŸœœœœ˜ Kšœœ˜&Kšœ œ˜+šŸ œœœœ˜$Kšœœ˜Kš œœœœœœ˜8Kšœ ˜ Kšœ œ˜Kšœœœœ˜,K˜—K˜%Kšœœœœ˜.K˜—K˜K˜K˜K˜—K˜š Ÿœœ’œœ ’œ˜nšŸœœœœ˜+Kšœœ˜$Kšœœ5˜RšŸœœœœ˜Kšœœ œœ˜1K˜—Kšœ˜Kšœœœœ˜.K˜—K˜Kšœ(˜(K˜ K˜—K˜šŸœœ ‘œ!’œ*Ÿ œœœœœœœ˜δKšœ!‘œ˜(šœ‘œœœ'œœ‘œœœ'˜qKšœ‘œ‘œ˜@K˜Kšœœ"˜+Kšœœ˜šŸœœœœ˜ Kšœœ˜&K˜K˜K˜—šŸ œœœœ˜!Kšœœ˜&šŸ œœœœ˜!Kšœœœ˜Kšœœ‘œ˜/šœ˜Kšœœ˜ K˜!šœ˜ K˜7Kšœœ˜=šœ œœ˜šœ œ˜(K˜K˜Kšœ˜—Kšœœœœ˜0Kšœœ!œœ˜2K˜—Kšœœ!œœ˜2Kšœœœœ˜.K˜——K˜—Kšœ"˜"K˜—šœ‘œ ‘œœ˜Kšœ ˜ Kšœ‘œ ‘œ˜Kš œœ‘œœ œ˜2—Kšœ˜Kšœ˜K˜Kšœœ˜—K˜—K˜šŸ œœ˜.Kšœ œYœœ˜wK˜šœ ‘œœœœœ ‘œœœœœ‘œœ˜oKšœ ‘œ ‘œ˜Kšœ‘œ ˜'Kšœ œœ˜Kšœ"˜"Kšœ+˜+Kšœ œœœJ˜fš Ÿœœ‘œœœ˜/šœœœ˜Kšœ ‘œ‘œ ˜2Kšœ‘œ˜2Kšœ‘œ‘œœ˜?Kšœ‘œ˜.K˜——Kšœ,˜,Kšœœ6˜>Kšœ‘œ’ œœ˜)Kšœ‘œ’œ˜7Kšœ‘œ ‘œ’œ˜0K˜2šœœ œœ˜ Kšœ˜Kšœ)˜)Kšœœ˜-Kšœ)œ˜<—šŸœœœ’œ˜@šœ œ˜šœ œ ˜Kšœ œœ‘œ˜8Kšœ˜—Kšœ ‘œ˜—Kšœœ˜—šŸ œœœœœœœ˜_Kšœœ˜!Kšœ œœ˜K˜ K˜—Kšœ‘œ‘œ ‘œ˜#šœœœ˜+Kšœ‘œ‘œ˜BKšœ‘œ‘œ˜/K˜—Kšœ‘œ ˜š œ‘œœ œœ˜;Kšœ‘œ ˜)šœœ˜Kš œ‘œ‘œ‘œ‘œ˜dKšœ‘œ‘œ˜/K˜—Kšœ‘œ ‘œ˜,š œ‘œœ œœ˜;Kšœ‘œ ˜)Kš œ‘œ‘œ‘œ‘œ‘œ%˜vKšœ‘œ‘œ˜/Kšœ˜—Kšœ‘œ ‘œ˜,š œ‘œœœ-˜>Kšœ‘œ œ ˜CKš œ‘œ‘œ‘œ‘œ‘œ%˜vKšœ‘œ‘œ˜/Kšœ˜—Kšœ˜—Kšœ‘œ ˜š œ‘œœœ-˜>Kšœ‘œ œ ˜Cšœœ˜Kš œ‘œ‘œ‘œ‘œ˜dKšœ‘œ‘œ˜/K˜—Kšœ‘œ ‘œ˜,š œ‘œœ œœ˜;Kšœ‘œ ˜)Kš œ‘œ‘œ‘œ‘œ‘œ˜qKšœ‘œ‘œ˜/Kšœ˜—Kšœ‘œ ‘œ˜,š œ‘œœœ-˜>Kšœ‘œ œ ˜CKš œ‘œ‘œ‘œ‘œ‘œ˜qKšœ‘œ‘œ˜/Kšœ˜—Kšœ˜—šœœ˜Kšœ‘œ ˜š œ‘œœ œœ˜;Kšœ‘œ ˜)Kš œ‘œ‘œ‘œ‘œ˜dKšœ‘œ‘œ˜/Kšœ˜—K˜—šœœ˜Kšœ‘œ ˜š œ‘œœœ-˜>Kšœ‘œ œ ˜CKš œ‘œ‘œ‘œ‘œ˜dKšœ‘œ‘œ˜/Kšœ˜—K˜—K˜Kšœœœœ˜—K˜Kšœ˜—K˜š Ÿ œœ ‘œ’ œ’œ˜ašŸœœœœ˜ Kšœ œ˜Kšœœ5˜Sšœ œ˜š œœœœ4œ œ˜hKšœœ ‘œ ˜GKšœœœœ˜Kšœœ"œœ˜3Kšœ˜—Kšœ˜—Kšœœœ˜&Kšœœ"œœ˜3K˜—K˜Kšœ˜—K˜Kšœœœœ ˜*Kšœ œœ˜)Kšœœœ˜7K˜Kšœœœœ ˜(Kšœœœ ˜#Kšœ œœœ˜%K˜šŸœœS’œ˜{K˜'Kšœœ6˜>K˜.Kšœ ’ œœ˜+Kšœ ’ œ˜'Kš œœœ ’£’œœœ˜dšŸœœœœ˜ Kšœœ˜&Kš œ œœ œœ˜,šŸ œœœœ˜$Kšœœ˜ Kšœ3˜3Kšœœ!œœ˜YK˜—K˜%š œœœœœ˜6Kšœ œF˜RKšœœœœ˜*šœ œ˜Kšœœ$œœ˜5Kšœ˜—K˜—K˜—Kšœœœ1˜EšŸœœœœ˜Kšœœ˜K˜2Kšœœ˜Kšœœ˜Kšœ˜Kšœ˜šœ œ˜K˜ K˜"š œœœœ*œ œ˜TK˜5Kšœ œœ˜,Kšœ,˜,Kš œ œœœœ˜:Kšœœœœ˜K˜Kšœ œœœ˜KKšœœœœ˜0Kš œ œœœ4œœ˜VKšœœ˜ —Kšœ˜—Kšœœ œ˜7šœ‘œœœ)œœ‘œœœ)˜wKšœ‘œ‘œ˜Kšœ'˜'Kšœœ‘œ‘œ˜#Kšœ œœ˜šœ$œœ˜9Kš œœœœ3œ5˜Kšœœ˜%Kšœœœ ˜AKšœ œœœ!œœœœœ˜dKšœœœœ˜KKšœœœœ˜OKšœ˜—KšœA˜AKšœC˜CKšœœ˜šŸœœœ œœœœœ’œ˜`Kšœœœ˜)Kšœ=˜=šŸœœ˜,Kšœ2˜2Kšœ2˜2Kšœ œ˜'K˜—šŸœœ˜*K˜Kš œœiœœœ˜€Kš œœkœœœ˜‚K˜—šœ œœ˜Kšœ)˜)Kšœ'˜'K˜—K˜K˜—Kšœ˜Kšœ˜Kšœœœ˜—K˜—K˜Kšœ œœœ˜2K˜K˜K˜—K˜šŸ œœœ˜%šœœ˜šœ ‘œœœœœ ‘œœœ˜YKšœ ‘œ ‘œ˜Kšœ&˜&šœœœ˜'Kšœ ’ œœ˜*šŸœœœœ˜ Kšœ œ˜Kšœœœœœœœ˜jK˜—K˜Kšœ˜—Kšœœ˜—Kšœ˜—šœœ˜šœœœ˜-Kšœœ˜4Kš œœœ’œ˜-Kš œ œœœœ œ˜IKšœ˜—Kšœ˜—K˜—K˜š Ÿœœœœ œ˜Nšœ œœ˜Kšœœ˜,Kšœœ˜,Kšœœ ˜"—K˜—K˜Kšœœ˜Kš œœœœœœ˜-K˜šŸ œœœœ œœœ˜GKšœœœ œ<˜|K˜—K˜Kšœ œ˜KšœD˜DKšœ'˜'Kšœœ˜K˜šŸœœœœœœ’œ˜GKšœœœ˜!K˜(K˜(K˜FKšœ˜K˜—K˜šŸœœ œœœœ’œ˜IKšœœœ˜"Kšœœœ˜"Kšœ˜—K˜š Ÿ œœœœœœ˜OKšœœœ˜/Kšœœ˜ Kšœœ˜ Kšœ"˜"Kšœ˜šœœ˜Kšœg˜gKšœ˜Kšœ˜—Kšœœ˜(K˜K˜—šŸœœ˜šœœœ˜&Kšœ=˜=Kšœ˜—K˜—K˜K˜K˜Kšœ˜—…—‡΅ΰ