<> <> DIRECTORY AbSets, Basics, BiRels, Convert, LichenArrayStuff, LichenDataOps, LichenDataStructure, LRUCache, Rope, SetBasics; LichenNewArrayImpl1: CEDAR PROGRAM IMPORTS AbSets, BiRels, Convert, LichenDataOps, LichenDataStructure, LRUCache, Rope, SetBasics EXPORTS LichenArrayStuff, LichenDataStructure = BEGIN OPEN LichenDataOps, LichenDataStructure, LichenArrayStuff, Sets:AbSets; Array: TYPE ~ LichenDataStructure.Array; CreateArrayRep: PUBLIC PROC [eltType: CellType, size2, basePeriod: Size2] RETURNS [Array] ~ { statrep: StatRep ~ CreateStatRep[]; a: Array = NEW [ArrayPrivate _ [ eltType: eltType, prevArray: NIL, nextArray: NIL, size2: size2, size: size2[Foo]*size2[Bar], basePeriod: basePeriod, dumrep: NIL, statrep: statrep ]]; RETURN [a]}; CreateStatRep: PUBLIC PROC RETURNS [sr: StatRep] ~ { sr _ NEW [StatRepPrivate _ [ edges: Sets.CreateHashSet[statEdges], portEdge: [ FALSE: BiRels.CreateHashReln[functional: [FALSE, TRUE], mappable: [TRUE, FALSE]], TRUE: BiRels.CreateHashReln[functional: [FALSE, TRUE], mappable: [TRUE, FALSE]]], apToPAI: BiRels.CreateHashFn[spaces: [SetBasics.refs, portsAtIndices], invable: FALSE] ]]; RETURN}; flushSelves: BOOL _ TRUE; MakeArrayNewConnection: PUBLIC PROC [act: CellType, rangeA: Range2, delta: Int2, epA, epB: Port] ~ { a: Array ~ act.asArray; fullRangeA: Range2 ~ Range2Intersection[SizeRange[a.size2], Range2Off[SizeRange[a.size2], Int2Neg[delta]]]; rangeB: Range2 ~ Range2Off[rangeA, delta]; IF a.buildPhase#buildingStatrep THEN ERROR; IF ABS[delta[Foo]]>1 OR ABS[delta[Bar]]>1 THEN ERROR; IF epA=epB AND delta=[0, 0] THEN --this self-connection is always implicitly present, let's not make it explicit-- IF flushSelves THEN RETURN; IF rangeA # fullRangeA THEN ERROR; FOR svA: StatVertex ~ NEW [StatVertexPrivate _ [epA, svB: StatVertex ~ NEW [StatVertexPrivate _ [epB, IF FindStatEdge[a.statrep, [vs: [svA, svB], delta]]; act _ act; ENDLOOP ENDLOOP; RETURN}; MakeStatEdge: PUBLIC PROC [sep: StatEdgePrivate] RETURNS [StatEdge] ~ { rev: BOOL ~ SELECT sep. <0 => TRUE, =0 => sep. >0 => FALSE, ENDCASE => ERROR; IF rev THEN sep _ [ vs: [FALSE: sep.vs[TRUE], TRUE: sep.vs[FALSE]], ]; RETURN [NEW [StatEdgePrivate _ sep]]}; AddStatEdge: PUBLIC PROC [sr: StatRep, sep: StatEdgePrivate] RETURNS [se: StatEdge] ~ { se _ MakeStatEdge[sep]; IF sr.edges.HasMemA[se] THEN ERROR; sr.portEdge[FALSE].AddNewAA[se.vs[FALSE].port, se]; sr.portEdge[TRUE].AddNewAA[se.vs[TRUE].port, se]; IF NOT sr.edges.AddA[se] THEN ERROR; RETURN}; RemStatEdge: PUBLIC PROC [sr: StatRep, se: StatEdge] ~ { IF NOT sr.edges.RemA[se] THEN ERROR; IF sr.portEdge[FALSE].RemAA[se.vs[FALSE].port, se].had[rightToLeft]#same THEN ERROR; IF sr.portEdge[TRUE].RemAA[se.vs[TRUE].port, se].had[rightToLeft]#same THEN ERROR; RETURN}; StatEdgeRedundant: PROC [a: Array, sep: StatEdgePrivate, avoid: StatEdge _ NIL] RETURNS [redundant: BOOL] ~ { seen: Set--of PortAtIndex-- ~ Sets.CreateHashSet[portsAtIndices]; frontier: Set--of PortAtIndex-- ~ Sets.CreateHashSet[portsAtIndices]; c1: Int2 ~ WidenNat2[sep.vs[FALSE].phase]; c2: Int2 ~ Int2Add[c1, sep. bounds: Range2 ~ Int2sRange[c1, c2]; IF sep.vs[TRUE].phase # Nat2AddMod[sep.vs[FALSE].phase, sep. IF NOT frontier.AddA[NEW [PortAtIndexPrivate _ [sep.vs[FALSE].port, c1]]] THEN ERROR; WHILE NOT frontier.Empty[] DO pai: PortAtIndex ~ NARROW[frontier.Pop.MA]; IF NOT seen.AddA[pai] THEN LOOP; IF pai.port = sep.vs[TRUE].port AND pai.ai = c2 THEN RETURN [TRUE]; {sv: StatVertex ~ NEW [StatVertexPrivate _ [pai.port, Int2Mod[pai.ai, a.basePeriod]]]; TestEdge: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL] ~ { oai: ArrayIndex ~ Int2Add[pai.ai, IF se#avoid AND Int2InRange[oai, bounds] THEN [] _ frontier.AddA[NEW [PortAtIndexPrivate _ [se.vs[ob].port, oai]]]; RETURN [FALSE]}; [] _ ScanStatEdgesFrom[a.statrep, sv, TestEdge]; }ENDLOOP; RETURN [FALSE]}; FindStatEdge: PUBLIC PROC [sr: StatRep, sep: StatEdgePrivate] RETURNS [fse: StatEdge] ~ { TestEdge: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL] ~ { RETURN [statVerts.SEqual[AV[se.vs[ob]], AV[sep.vs[TRUE]]] AND sep. fse _ ScanStatEdgesFrom[sr, sep.vs[FALSE], TestEdge].se; RETURN}; FinishedMakingArrayConnections: PUBLIC PROC [act: CellType] ~ { a: Array ~ act.asArray; dumrep: DumRep ~ NEW [DumRepPrivate _ [ topWires: Sets.CreateHashSet[], epToTopWire: BiRels.CreateHashFn[invable: FALSE], apToWire: BiRels.CreateHashFn[invable: TRUE] ]]; PerStatEdge: PROC [ra: REF ANY] ~ { DumbifyStatEdge[a, NARROW[ra]]; RETURN}; PerPort: PROC [rap, rpai: REF ANY] ~ { ap: Port ~ NARROW[rap]; pai: PortAtIndex ~ NARROW[rpai]; dw: DumbWire ~ GetDumbWireForPort[a, pai.port, pai.ai, TRUE]; IF dw=NIL THEN ERROR; dumrep.apToWire.AddNewAA[ap, dw]; RETURN}; IF a.buildPhase#buildingStatrep THEN ERROR; a.buildPhase _ statrepFixed; a.dumrep _ dumrep; a.statrep.edges.EnumA[PerStatEdge]; a.statrep.apToPAI.EnumAA[PerPort]; RETURN}; SetStatRep: PUBLIC PROC [act: CellType, statrep: StatRep, reset: BOOL] ~ { a: Array ~ act.asArray; IF a.buildPhase # (IF reset THEN statrepFixed ELSE buildingStatrep) THEN ERROR; a.buildPhase _ buildingStatrep; a.statrep _ statrep; FinishedMakingArrayConnections[act]; RETURN}; DumbifyStatEdge: PROC [a: Array, se: StatEdge] ~ { epA: Port ~ se.vs[FALSE].port; epB: Port ~ se.vs[TRUE].port; fullRangeA: Range2 ~ Range2Intersection[SizeRange[a.size2], Range2Off[SizeRange[a.size2], Int2Neg[se. iRangeA: Range2 ~ Range2Div[fullRangeA, a.basePeriod, se.vs[FALSE].phase]; dwsA: RefSeq--cai dwsB: RefSeq--cai FOR if: INT IN [iRangeA[Foo].min .. iRangeA[Foo].maxPlusOne) DO FOR ib: INT IN [iRangeA[Bar].min .. iRangeA[Bar].maxPlusOne) DO aiA: Int2 ~ [ if*a.basePeriod[Foo]+se.vs[FALSE].phase[Foo], ib*a.basePeriod[Bar]+se.vs[FALSE].phase[Bar]]; aiB: ArrayIndex ~ Int2Add[se. caiA: CompositeArrayIndex ~ ComposeAI[a, aiA]; caiB: CompositeArrayIndex ~ ComposeAI[a, aiB]; dwA: TopDumbWire ~ NARROW[dwsA[caiA]]; dwB: TopDumbWire ~ NARROW[dwsB[caiB]]; IF dwA=dwB THEN {IF dwA=NIL THEN { dw: TopDumbWire ~ CreateDumbTop[a]; AddDumbElt[a, dw, epA, aiA]; AddDumbElt[a, dw, epB, aiB]}} ELSE IF dwA=NIL THEN AddDumbElt[a, dwB, epA, aiA] ELSE IF dwB=NIL THEN AddDumbElt[a, dwA, epB, aiB] ELSE JoinDumbWires[a, dwA, dwB]; a _ a; ENDLOOP ENDLOOP; RETURN}; CreateDumbTop: PROC [a: Array] RETURNS [tdw: TopDumbWire] ~ { tdw _ NEW [DumbWirePrivate[top] _ [ children: BiRels.CreateHashFn[invable: FALSE], variant: top[eps: BiRels.CreateHashFn[invable: FALSE]] ]]; IF NOT a.dumrep.topWires.AddA[tdw] THEN ERROR; RETURN}; AddDumbElt: PROC [a: Array, dw: TopDumbWire, ep: Port, ai: ArrayIndex] ~ { cai: CompositeArrayIndex ~ ComposeAI[a, ai]; dws: RefSeq--CompositeArrayIndex mems: BoolSeq--CompositeArrayIndex IF mems=NIL THEN dw.eps.AddNewAA[ep, mems _ CreateBoolSeq[a.size, FALSE]]; dws[cai] _ dw; mems[cai] _ TRUE; RETURN}; JoinDumbWires: PROC [a: Array, dwA, dwB: TopDumbWire] ~ { MoveElt: PROC [pair: BiRels.Pair] ~ { ep: Port ~ NARROW[pair[left].VA]; dws: RefSeq--CompositeArrayIndex memsB: BoolSeq ~ NARROW[pair[right].VA]; memsA: BoolSeq ~ NARROW[dwA.eps.ApplyA[ep].MDA]; IF memsA=NIL THEN { dwA.eps.AddNewAA[ep, memsB]; FOR cai: CompositeArrayIndex IN [0 .. a.size) DO IF memsB[cai] THEN dws[cai] _ dwA; ENDLOOP; } ELSE { FOR cai: CompositeArrayIndex IN [0 .. a.size) DO IF memsB[cai] THEN { memsA[cai] _ TRUE; dws[cai] _ dwA}; ENDLOOP; }; RETURN}; MoveExport: PROC [ra: Sets.Value] ~ { ap: Port ~ NARROW[ra.VA]; [] _ a.dumrep.apToWire.AddAA[ap, dwA]; RETURN}; IF NOT a.dumrep.topWires.RemA[dwB] THEN ERROR; dwB.eps.Enumerate[MoveElt]; a.dumrep.apToWire.MappingA[dwB, rightToLeft].Enumerate[MoveExport]; RETURN}; GetDumbWires: PROC [a: Array, ep: Port, mayAdd: BOOL] RETURNS [dws: RefSeq--cai dws _ NARROW[a.dumrep.epToTopWire.ApplyA[ep].MDA]; IF dws=NIL AND mayAdd THEN a.dumrep.epToTopWire.AddNewAA[ep, dws _ CreateRefSeq[a.size]]; RETURN}; GetDumbWire: PUBLIC PROC [a: Array, ep: Port, ai: ArrayIndex] RETURNS [dw: DumbWire] ~ { cai: CompositeArrayIndex ~ ComposeAI[a, ai]; Work: PROC [ep: Port] RETURNS [dw: DumbWire] ~ { dws: RefSeq--cai IF dws#NIL THEN dw _ NARROW[dws[cai]]; IF dw#NIL THEN RETURN; IF ep.parent # a.eltType.port THEN { pdw: DumbWire ~ Work[NARROW[ep.parent]]; IF pdw#NIL THEN RETURN [GetDumbChild[pdw, ep]]; }; RETURN}; IF a.buildPhase#statrepFixed THEN ERROR; RETURN Work[ep]}; GetDumbChild: PROC [pdw: DumbWire, port: Port] RETURNS [cdw: ChildDumbWire] ~ { cdw _ NARROW[pdw.children.ApplyA[port].MDA]; IF cdw#NIL THEN RETURN; pdw.children.AddNewAA[port, cdw _ NEW [DumbWirePrivate[child] _ [ children: BiRels.CreateHashFn[invable: FALSE], variant: child[pdw, port] ]] ]; RETURN}; GetDumbWireForPort: PROC [a: Array, ep: Port, ai: ArrayIndex, mayAdd: BOOL] RETURNS [dw: DumbWire] ~ { dw _ GetDumbWire[a, ep, ai]; IF dw#NIL OR NOT mayAdd THEN RETURN; AddDumbSubtree[a, ai, ep]; dw _ GetDumbWire[a, ep, ai]; RETURN}; AddDumbSubtree: PROC [a: Array, index: ArrayIndex, ep: Port] ~ { Check: PROC [ep, done: Port] RETURNS [ok: BOOL _ TRUE] ~ { ok _ GetDumbWire[a, ep, index] = NIL; FOR cep: Port _ ep.FirstChildPort, cep.NextChildPort WHILE ok AND cep#NIL DO ok _ cep=done OR Check[cep, NIL]; ENDLOOP; RETURN}; IF NOT Check[ep, NIL] THEN RETURN; {WorkUp: PROC [ep: Port] ~ { WITH ep.parent SELECT FROM parent: Port => IF parent#a.eltType.port THEN { pdw: DumbWire ~ GetDumbWire[a, parent, index]; IF pdw#NIL THEN {WorkDown[pdw, parent]; RETURN}; IF Check[parent, ep] THEN {WorkUp[parent]; RETURN}; }; ENDCASE => NULL; {tdw: TopDumbWire ~ CreateDumbTop[a]; AddDumbElt[a, tdw, ep, index]; WorkDown[tdw, ep]; RETURN}}; WorkDown: PROC [dw: DumbWire, ep: Port] ~ { FOR cep: Port _ ep.FirstChildPort, cep.NextChildPort WHILE cep#NIL DO WorkDown[GetDumbChild[dw, cep], cep]; ENDLOOP; RETURN}; WorkUp[ep]; RETURN}}; ArrayEltPortsConnected: PUBLIC PROC [a: Array, ai1, ai2: ArrayIndex, ep1, ep2: Port] RETURNS [BOOL] ~ { dw1: DumbWire ~ GetDumbWire[a, ep1, ai1]; dw2: DumbWire ~ GetDumbWire[a, ep2, ai2]; IF a.buildPhase#statrepFixed THEN ERROR; RETURN [dw1=dw2 AND dw1#NIL]}; EnumerateConnectedEltPorts: PUBLIC PROC [a: Array, ep: Port, Consume: PROC [Port], mayDuplicate: BOOL] ~ { seenPorts: Set--of elt Port--; PerWire: PROC [dw: DumbWire] ~ { [] _ ScanPortsInDumbWire[a, dw, PassPort]; RETURN}; PassPort: PROC [ep: Port] RETURNS [BOOL] ~ { IF (mayDuplicate OR seenPorts.AddA[ep]) THEN Consume[ep]; RETURN [FALSE]}; IF NOT mayDuplicate THEN seenPorts _ Sets.CreateHashSet[]; IF a.buildPhase#statrepFixed THEN ERROR; EnumerateDumbWiresForPort[a, ep, PerWire]; RETURN}; EnumerateDumbWiresForPort: PUBLIC PROC [a: Array, ep: Port, Consume: PROC [DumbWire]] ~ { seenWires: Set--of TopDumbWire-- ~ Sets.CreateHashSet[]; Work: PROC [port: Port, Consume: PROC [DumbWire]] ~ { dws: RefSeq--CompositeArrayIndex IF dws#NIL THEN { FOR cai: CompositeArrayIndex IN [0 .. a.size) DO dw: TopDumbWire ~ NARROW[dws[cai]]; IF seenWires.AddA[dw] THEN Consume[dw]; ENDLOOP; }; WITH port.parent SELECT FROM parent: Port => { Pass: PROC [parent: DumbWire] ~ { child: ChildDumbWire ~ GetDumbChild[parent, port]; Consume[child]; RETURN}; Work[parent, Pass]; }; x: CellType => NULL; ENDCASE => ERROR; RETURN}; IF a.buildPhase#statrepFixed THEN ERROR; Work[ep, Consume]; RETURN}; ScanPortsInDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, Test: PROC [Port] RETURNS [BOOL]] RETURNS [found: BOOL, ep: Port] ~ { ScanWire: PROC [dw: DumbWire, Test: PROC [Port] RETURNS [BOOL]] RETURNS [found: BOOL, ep: Port] ~ { WITH dw SELECT FROM tdw: TopDumbWire => { TestPort: PROC [pair: BiRels.Pair] RETURNS [pass: BOOL _ FALSE] ~ { port: Port ~ NARROW[pair[left].VA]; IF (pass _ Test[port]) THEN ep _ port; RETURN}; found _ tdw.eps.Scan[TestPort].found; RETURN}; cdw: ChildDumbWire => { index: NATURAL ~ cdw.port.PortIndex; TestPort: PROC [parent: Port] RETURNS [pass: BOOL _ FALSE] ~ { child: Port ~ parent.SubPort[index]; IF (pass _ Test[child]) THEN ep _ child; RETURN}; found _ ScanWire[cdw.parent, TestPort].found; RETURN}; ENDCASE => ERROR; }; RETURN ScanWire[dw, Test]}; GetInstForPortInDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, ep: Port] RETURNS [ArrayIndex] ~ { WITH dw SELECT FROM tdw: TopDumbWire => { mems: BoolSeq--CompositeArrayIndex FOR cai: NATURAL IN [0 .. a.size) DO IF mems[cai] THEN RETURN DecomposeAI[a, cai]; ENDLOOP; RETURN [ALL[-1]]}; cdw: ChildDumbWire => RETURN GetInstForPortInDumbWire[a, cdw.parent, NARROW[ep.parent]]; ENDCASE => ERROR; }; ScanPortsAtIndicesForDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, Test: PROC [port: Port, ai: ArrayIndex] RETURNS [BOOL]] RETURNS [found: BOOL, pai: PortAtIndexPrivate] ~ { WITH dw SELECT FROM tdw: TopDumbWire => { PerPort: PROC [pair: BiRels.Pair] RETURNS [pass: BOOL] ~ { ep: Port ~ NARROW[pair[left].VA]; mems: BoolSeq--CompositeArrayIndex FOR f: INT IN [0 .. a.size2[Foo]) DO FOR b: INT IN [0 .. a.size2[Bar]) DO cai: CompositeArrayIndex ~ ComposeAI[a, [f, b]]; IF mems[cai] THEN IF (pass _ Test[ep, [f, b]]) THEN {pai _ [ep, [f, b]]; RETURN}; ENDLOOP ENDLOOP; RETURN [FALSE]}; found _ tdw.eps.Scan[PerPort].found; RETURN}; cdw: ChildDumbWire => { index: NATURAL ~ cdw.port.PortIndex; Pass: PROC [port: Port, ai: ArrayIndex] RETURNS [pass: BOOL] ~ { child: Port ~ port.SubPort[index]; IF (pass _ Test[child, ai]) THEN pai _ [child, ai]; RETURN}; found _ ScanPortsAtIndicesForDumbWire[a, cdw.parent, Pass].found; RETURN}; ENDCASE => ERROR; }; ScanStatVertices: PUBLIC PROC [a: Array, Test: PROC [StatVertex] RETURNS [BOOL]] RETURNS [found: BOOL _ FALSE, sv: StatVertex _ NIL] ~ { seen: Set--of StatVertex-- ~ Sets.CreateHashSet[statVerts]; PerEdge: PROC [ra: Sets.Value] ~ { se: StatEdge ~ NARROW[ra.VA]; IF seen.AddA[se.vs[FALSE]] AND Test[se.vs[FALSE]] THEN {found _ TRUE; sv _ se.vs[FALSE]; RETURN}; IF seen.AddA[se.vs[TRUE]] AND Test[se.vs[TRUE]] THEN {found _ TRUE; sv _ se.vs[TRUE]}; RETURN}; a.statrep.edges.Enumerate[PerEdge]; RETURN}; ScanStatEdgesFrom: PUBLIC PROC [sr: StatRep, from: StatVertex, Test: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL]] RETURNS [found: BOOL _ FALSE, se: StatEdge _ NIL, ob: BOOL _ FALSE] ~ { FOR ob IN BOOL DO sb: BOOL ~ NOT ob; TestEdge: PROC [ra: Sets.Value] RETURNS [pass: BOOL] ~ { se: StatEdge ~ NARROW[ra.VA]; pass _ se.vs[sb].phase = from.phase AND Test[se, ob]; RETURN}; mp: BiRels.MaybePair ~ sr.portEdge[sb].ScanMapping[AV[from.port], TestEdge]; IF mp.found THEN RETURN [TRUE, NARROW[mp.it[right].VA], ob]; ENDLOOP; RETURN}; GetArrayPortForPort: PUBLIC PROC [act: CellType, index: ArrayIndex, ep: Port, mayAdd: BOOL] RETURNS [arrayPort: Port] ~ { a: Array ~ act.asArray; IF a.buildPhase#statrepFixed THEN ERROR; {dw: DumbWire ~ GetDumbWireForPort[a, ep, index, mayAdd]; IF dw=NIL THEN {IF mayAdd THEN ERROR--trying to export a composite wire that doesn't really exist-- ELSE RETURN [NIL]}; {aPort: Port ~ NARROW[a.dumrep.apToWire.ScanHalfRestriction[set: Sets.CreateSingleton[AV[dw], SetBasics.refs], Test: BiRels.AcceptAny, side: right].KeepHalf[left].MDA]; IF aPort#NIL THEN RETURN [aPort]; IF NOT mayAdd THEN RETURN [NIL]; arrayPort _ FullyAddPort[[parent: act.port, names: CreateSteppyNames[IF act.inheritNames THEN LIST[SNCat[NameIndex[a, index], SteppyDescribe[ep, a.eltType.port]]] ELSE NIL]]].port; a.statrep.apToPAI.AddNewAA[arrayPort, NEW[PortAtIndexPrivate _ [ep, index]]]; a.dumrep.apToWire.AddNewAA[arrayPort, dw]; RETURN}}}; NoteNewEltPort: PUBLIC PROC [a: Array, ep: Port] ~ { RETURN}; IsIncompleteArray: PUBLIC PROC [act: CellType] RETURNS [BOOL] ~ {RETURN [FALSE]}; ComposeAI: PROC [a: Array, ai: ArrayIndex] RETURNS [CompositeArrayIndex] ~ INLINE {RETURN [a.size2[Bar]*ai[Foo]+ai[Bar]]}; DecomposeAI: PROC [a: Array, cai: CompositeArrayIndex] RETURNS [ArrayIndex] ~ { f: NATURAL ~ cai/a.size2[Bar]; RETURN [[f, cai - f*a.size2[Bar]]]}; NameIndex: PUBLIC PROC [a: Array, index: ArrayIndex] RETURNS [SteppyName] = { RETURN LSn[SELECT 1 FROM a.size2[Foo] => LIST[NewInt[index[Bar]]], a.size2[Bar] => LIST[NewInt[index[Foo]]], ENDCASE => LIST[NewInt[index[Foo]], NewInt[index[Bar]]]]; }; FmtIndex: PUBLIC PROC [a: Array, index: ArrayIndex] RETURNS [asRope: ROPE] = { asRope _ SELECT TRUE FROM a.size2[Foo]=1 => Subscript[NIL, index[Bar]], a.size2[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 _ subs[index] ELSE sub _ Convert.RopeFromInt[index].Concat["/"]; IF base.Length#0 THEN sub _ base.Cat["/", sub]; RETURN}; sub2len: NATURAL _ 2050; 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; }; sub _ NARROW[sub2Rs[p]]; IF base.Length#0 THEN sub _ base.Cat["/", sub]; RETURN}; statEdges: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate _ [ Contains: StatEdgesContains, Equal: StatEdgesEqual, Hash: HashStatEdge, Compare: CompareStatEdges, name: "stat edges" ]]; StatEdgesContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ { RETURN [WITH v.ra SELECT FROM x: StatEdge => TRUE, ENDCASE => FALSE]}; StatEdgesEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ { RETURN [CompareStatEdges[data, v1, v2]=equal]}; HashStatEdge: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ { se: StatEdge ~ NARROW[v.ra]; RETURN [statVerts.SHash[AV[se.vs[FALSE]]]*17 + statVerts.SHash[AV[se.vs[TRUE]]] + SetBasics.HashIntI[se. SetBasics.HashIntI[se. CompareStatEdges: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ { se1: StatEdge ~ NARROW[v1.ra]; se2: StatEdge ~ NARROW[v2.ra]; IF (c _ statVerts.SCompare[AV[se1.vs[FALSE]], AV[se2.vs[FALSE]]]) = equal THEN IF (c _ statVerts.SCompare[AV[se1.vs[TRUE]], AV[se2.vs[TRUE]]]) = equal THEN IF (c _ SetBasics.CompareIntI[se1. c _ SetBasics.CompareIntI[se1. RETURN}; statVerts: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate _ [ Contains: StatVertsContains, Equal: StatVertsEqual, Hash: HashStatVert, Compare: CompareStatVerts, name: "stat verts" ]]; StatVertsContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ { RETURN [WITH v.ra SELECT FROM x: StatVertex => TRUE, ENDCASE => FALSE]}; StatVertsEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ { RETURN [CompareStatVerts[data, v1, v2]=equal]}; HashStatVert: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ { sv: StatVertex ~ NARROW[v.VA]; RETURN [SetBasics.HashRefI[sv.port] + SetBasics.HashIntI[sv.phase[Foo]]*137 + SetBasics.HashIntI[sv.phase[Bar]]]}; CompareStatVerts: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ { sv1: StatVertex ~ NARROW[v1.VA]; sv2: StatVertex ~ NARROW[v2.VA]; IF (c _ SetBasics.CompareRefI[sv1.port, sv2.port]) = equal THEN IF (c _ SetBasics.CompareIntI[sv1.phase[Foo], sv2.phase[Foo]]) = equal THEN c _ SetBasics.CompareIntI[sv1.phase[Bar], sv2.phase[Bar]]; RETURN}; portsAtIndices: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate _ [ Contains: PortsAtIndicesContains, Equal: PortsAtIndicesEqual, Hash: PortsAtIndicesHash, Compare: PortsAtIndicesCompare, name: "ports at indices" ]]; PortsAtIndicesContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ { RETURN [WITH v.ra SELECT FROM x: PortAtIndex => TRUE, ENDCASE => FALSE]}; PortsAtIndicesEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ { RETURN [PortsAtIndicesCompare[data, v1, v2]=equal]}; PortsAtIndicesHash: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ { pai: PortAtIndex ~ NARROW[v.VA]; RETURN [SetBasics.HashRefI[pai.port] + SetBasics.HashIntI[pai.ai[Foo]]*137 + SetBasics.HashIntI[pai.ai[Bar]]]}; PortsAtIndicesCompare: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ { pai1: PortAtIndex ~ NARROW[v1.VA]; pai2: PortAtIndex ~ NARROW[v2.VA]; IF (c _ SetBasics.CompareRefI[pai1.port, pai2.port]) = equal THEN IF (c _ SetBasics.CompareIntI[pai1.ai[Foo], pai2.ai[Foo]]) = equal THEN c _ SetBasics.CompareIntI[pai1.ai[Bar], pai2.ai[Bar]]; RETURN}; Range2Div: PUBLIC PROC [r: Range2, rr _ [ Foo: [ min: CeilDiv[r[Foo].min- maxPlusOne: FloorDiv[r[Foo].maxPlusOne-1- Bar: [ min: CeilDiv[r[Bar].min- maxPlusOne: FloorDiv[r[Bar].maxPlusOne-1- }; Range1Div: PUBLIC PROC [r: Range, rr _ [ min: CeilDiv[r.min- maxPlusOne: FloorDiv[r.maxPlusOne-1- }; Range2MulA: PUBLIC PROC [r: Range2, rr _ [ Foo: [ min: r[Foo].min* maxPlusOne: (r[Foo].maxPlusOne-1)* Bar: [ min: r[Bar].min* maxPlusOne: (r[Bar].maxPlusOne-1)* }; Range2MulB: PUBLIC PROC [r: Range2, rr _ [ Foo: [ min: r[Foo].min* maxPlusOne: r[Foo].maxPlusOne* Bar: [ min: r[Bar].min* maxPlusOne: r[Bar].maxPlusOne* }; Range1MulB: PUBLIC PROC [r: Range, rr _ [ min: r.min* maxPlusOne: r.maxPlusOne* }; Start: PROC ~ { FOR index: NATURAL IN [0 .. sublen) DO subs[index] _ Convert.RopeFromInt[index].Concat["/"]; ENDLOOP; RETURN}; Start[]; END.