LichenNewArrayImpl1.Mesa
Last tweaked by Mike Spreitzer on October 20, 1987 8:17:37 pm PDT
DIRECTORY Basics, Collections, Convert, LichenArrayStuff, LichenDataOps, LichenDataStructure, List, LRUCache, PairCollections, Rope;
LichenNewArrayImpl1: CEDAR PROGRAM
IMPORTS Collections, Convert, LichenDataOps, LichenDataStructure, List, LRUCache, PairCollections, Rope
EXPORTS LichenArrayStuff, LichenDataStructure
=
BEGIN OPEN LichenDataOps, LichenDataStructure, LichenArrayStuff, PairColls:PairCollections, Colls:Collections;
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: Colls.CreateHashSet[],
portEdge: [
FALSE: PairColls.CreateHashReln[functional: [FALSE, TRUE], mappable: [TRUE, FALSE]],
TRUE: PairColls.CreateHashReln[functional: [FALSE, TRUE], mappable: [TRUE, FALSE]]]
]];
RETURN};
flushSelves: BOOLTRUE;
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 ff: NAT IN [0 .. a.basePeriod[Foo]) DO FOR fb: NAT IN [0 .. a.basePeriod[Bar]) DO
fA: Nat2 ~ [ff, fb];
fB: Nat2 ~ Nat2AddMod[fA, delta, a.basePeriod];
svA: StatVertex ~ NEW [StatVertexPrivate ← [epA, fA]];
svB: StatVertex ~ NEW [StatVertexPrivate ← [epB, fB]];
IF NOT StatEdgeRedundant[a, [vs: [svA, svB], d: delta], NIL] THEN [] ← AddStatEdge[a.statrep, [vs: [FALSE: svA, TRUE: svB], d: delta]];
act ← act;
ENDLOOP ENDLOOP;
RETURN};
AddStatEdge: PUBLIC PROC [sr: StatRep, sep: StatEdgePrivate] RETURNS [se: StatEdge] ~ {
se ← NEW [StatEdgePrivate ← sep];
sr.portEdge[FALSE].AddNewPair[[sep.vs[FALSE].port, se]];
sr.portEdge[TRUE].AddNewPair[[sep.vs[TRUE].port, se]];
IF NOT sr.edges.AddElt[se] THEN ERROR;
RETURN};
StatEdgeRedundant: PUBLIC PROC [a: Array, sep: StatEdgePrivate, avoid: StatEdge ← NIL] RETURNS [redundant: BOOL] ~ {
seen: Set--of PortAtIndex-- ~ Colls.CreateHashSet[portsAtIndices];
frontier: Set--of PortAtIndex-- ~ Colls.CreateHashSet[portsAtIndices];
c1: Int2 ~ WidenNat2[sep.vs[FALSE].phase];
c2: Int2 ~ Int2Add[c1, sep.d];
bounds: Range2 ~ Int2sRange[c1, c2];
IF sep.vs[TRUE].phase # Nat2AddMod[sep.vs[FALSE].phase, sep.d, a.basePeriod] THEN ERROR;
IF NOT frontier.AddElt[NEW [PortAtIndexPrivate ← [sep.vs[FALSE].port, c1]]] THEN ERROR;
WHILE NOT frontier.Empty[] DO
pai: PortAtIndex ~ NARROW[frontier.Pop.val];
IF NOT seen.AddElt[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] ~ {
d: Int2 ~ IF ob THEN se.d ELSE Int2Neg[se.d];
oai: ArrayIndex ~ Int2Add[pai.ai, d];
IF se#avoid AND Int2InRange[oai, bounds] THEN [] ← frontier.AddElt[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.SpaceEqual[se.vs[ob], sep.vs[TRUE]] AND sep.d = (IF ob THEN se.d ELSE Int2Neg[se.d])]};
fse ← ScanStatEdgesFrom[sr, sep.vs[FALSE], TestEdge].se;
RETURN};
FinishedMakingArrayConnections: PUBLIC PROC [act: CellType] ~ {
a: Array ~ act.asArray;
dumrep: DumRep ~ NEW [DumRepPrivate ← [
topWires: Colls.CreateHashSet[],
epToTopWire: PairColls.CreateHashFn[invable: FALSE],
apToWire: PairColls.CreateHashFn[invable: TRUE]
]];
PerStatEdge: PROC [ra: REF ANY] ~ {
se: StatEdge ~ NARROW[ra];
DumbifyStatEdge[a, se];
RETURN};
IF a.buildPhase#buildingStatrep THEN ERROR;
a.buildPhase ← statrepFixed;
IF a.dumrep#NIL THEN ERROR;
a.dumrep ← dumrep;
a.statrep.edges.Enumerate[PerStatEdge];
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.d]]];
iRangeA: Range2 ~ Range2Div[fullRangeA, a.basePeriod, se.vs[FALSE].phase];
dwsA: RefSeq--cai b TopDumbWire-- ~ GetDumbWires[a, epA, TRUE];
dwsB: RefSeq--cai b TopDumbWire-- ~ GetDumbWires[a, epB, TRUE];
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.d, aiA];
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 ~ NEW [DumbWirePrivate[top] ← [
children: PairColls.CreateHashFn[invable: FALSE],
variant: top[eps: PairColls.CreateHashFn[invable: FALSE]]
]];
IF NOT a.dumrep.topWires.AddElt[dw] THEN ERROR;
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};
AddDumbElt: PROC [a: Array, dw: TopDumbWire, ep: Port, ai: ArrayIndex] ~ {
cai: CompositeArrayIndex ~ ComposeAI[a, ai];
dws: RefSeq--CompositeArrayIndex b TopDumbWire-- ~ GetDumbWires[a, ep, TRUE];
mems: BoolSeq--CompositeArrayIndex b member--NARROW[dw.eps.Apply[ep].DVal];
IF mems=NIL THEN dw.eps.AddNewPair[[ep, mems ← CreateBoolSeq[a.size, FALSE]]];
dws[cai] ← dw;
mems[cai] ← TRUE;
RETURN};
JoinDumbWires: PROC [a: Array, dwA, dwB: TopDumbWire] ~ {
MoveElt: PROC [pair: PairColls.Pair] ~ {
ep: Port ~ NARROW[pair[left]];
dws: RefSeq--CompositeArrayIndex b DumbWire-- ~ NARROW[a.dumrep.epToTopWire.Apply[ep].val];
memsB: BoolSeq ~ NARROW[pair[right]];
memsA: BoolSeq ~ NARROW[dwA.eps.Apply[ep].DVal];
IF memsA=NIL THEN {
dwA.eps.AddNewPair[[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: REF ANY] ~ {
ap: Port ~ NARROW[ra];
[] ← a.dumrep.apToWire.AddPair[[ap, dwA]];
RETURN};
IF NOT a.dumrep.topWires.RemoveElt[dwB] THEN ERROR;
dwB.eps.Enumerate[MoveElt];
a.dumrep.apToWire.Mapping[dwB, rightToLeft].Enumerate[MoveExport];
RETURN};
GetDumbWires: PROC [a: Array, ep: Port, mayAdd: BOOL] RETURNS [dws: RefSeq--cai b TopDumbWire--] ~ {
dws ← NARROW[a.dumrep.epToTopWire.Apply[ep].DVal];
IF dws=NIL AND mayAdd THEN a.dumrep.epToTopWire.AddNewPair[[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 b TopDumbWire-- ~ GetDumbWires[a, ep, FALSE];
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.Apply[port].DVal];
IF cdw#NIL THEN RETURN;
pdw.children.AddNewPair[[port, cdw ← NEW [DumbWirePrivate[child] ← [
children: PairColls.CreateHashFn[invable: FALSE],
variant: child[pdw, port] ]] ]];
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]] ~ {
seenPorts: Set--of elt Port-- ~ Colls.CreateHashSet[];
PerWire: PROC [dw: DumbWire] ~ {
[] ← ScanPortsInDumbWire[a, dw, PassPort];
RETURN};
PassPort: PROC [ep: Port] RETURNS [BOOL] ~ {
IF seenPorts.AddElt[ep] THEN Consume[ep];
RETURN [FALSE]};
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-- ~ Colls.CreateHashSet[];
Work: PROC [port: Port, Consume: PROC [DumbWire]] ~ {
dws: RefSeq--CompositeArrayIndex b TopDumbWire-- ~ NARROW[a.dumrep.epToTopWire.Apply[port].DVal];
IF dws#NIL THEN {
FOR cai: CompositeArrayIndex IN [0 .. a.size) DO
dw: TopDumbWire ~ NARROW[dws[cai]];
IF seenWires.AddElt[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: PairColls.Pair] RETURNS [pass: BOOLFALSE] ~ {
port: Port ~ NARROW[pair[left]];
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: BOOLFALSE] ~ {
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 b member-- ~ NARROW[tdw.eps.Apply[ep].val];
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: PairColls.Pair] RETURNS [pass: BOOL] ~ {
ep: Port ~ NARROW[pair[left]];
mems: BoolSeq--CompositeArrayIndex b member-- ~ NARROW[pair[right]];
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: BOOLFALSE, sv: StatVertex ← NIL] ~ {
seen: Set--of StatVertex-- ~ Colls.CreateHashSet[statVerts];
PerEdge: PROC [ra: REF ANY] ~ {
se: StatEdge ~ NARROW[ra];
IF seen.AddElt[se.vs[FALSE]] AND Test[se.vs[FALSE]] THEN {found ← TRUE; sv ← se.vs[FALSE]; RETURN};
IF seen.AddElt[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: BOOLFALSE, se: StatEdge ← NIL, ob: BOOLFALSE] ~ {
FOR ob IN BOOL DO
sb: BOOL ~ NOT ob;
TestEdge: PROC [ra: REF ANY] RETURNS [pass: BOOL] ~ {
se: StatEdge ~ NARROW[ra];
pass ← se.vs[sb].phase = from.phase AND Test[se, ob];
RETURN};
mp: PairColls.MaybePair ~ sr.portEdge[sb].ScanMapping[from.port, TestEdge];
IF mp.found THEN RETURN [TRUE, NARROW[mp.pair[right]], ob];
ENDLOOP;
RETURN};
GetArrayPortForPort: PUBLIC PROC [act: CellType, index: ArrayIndex, ep: Port, mayAdd: BOOL] RETURNS [arrayPort: Port] ~ {
a: Array ~ act.asArray;
dw: DumbWire ~ GetDumbWire[a, ep, index];
IF a.buildPhase#statrepFixed THEN ERROR;
IF dw=NIL THEN {IF mayAdd THEN ERROR--trying to export a composite wire that doesn't really exist-- ELSE RETURN [NIL]};
{ports: Set--of array Port-- ~ a.dumrep.apToWire.Mapping[dw, rightToLeft];
IF NOT ports.Empty THEN RETURN [NARROW[ports.First[].val]];
IF NOT mayAdd THEN RETURN [NIL];
{portName: SteppyName ~ List.Append[NameIndex[a, index], SteppyDescribe[ep, a.eltType.port]];
arrayPort ← FullyAddPort[[parent: act.port, names: CreateSteppyNames[LIST[portName]]]].port;
a.dumrep.apToWire.AddNewPair[[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] = {
SELECT TRUE FROM
a.size2[Foo]=1 => RETURN [LIST[NewInt[index[Bar]]]];
a.size2[Bar]=1 => RETURN [LIST[NewInt[index[Foo]]]];
ENDCASE => RETURN [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 ROPEALL[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};
statVerts: PUBLIC Colls.Space ~ NEW [Colls.SpacePrivate ← [
Equal: StatVertsEqual,
Hash: HashStatVert,
Compare: CompareStatVerts,
other: List.PutAssoc[$Name, "stat verts", NIL]
]];
StatVertsEqual: PROC [data, elt1, elt2: REF ANY] RETURNS [BOOL] ~ {
RETURN [CompareStatVerts[data, elt1, elt2]=equal]};
HashStatVert: PROC [data, elt: REF ANY] RETURNS [CARDINAL] ~ {
sv: StatVertex ~ NARROW[elt];
RETURN [Colls.HashRefI[sv.port] + Colls.HashIntI[sv.phase[Foo]]*137 + Colls.HashIntI[sv.phase[Bar]]]};
CompareStatVerts: PROC [data, elt1, elt2: REF ANY] RETURNS [c: Basics.Comparison] ~ {
sv1: StatVertex ~ NARROW[elt1];
sv2: StatVertex ~ NARROW[elt2];
IF (c ← Colls.CompareRefI[sv1.port, sv2.port]) = equal THEN IF (c ← Colls.CompareIntI[sv1.phase[Foo], sv2.phase[Foo]]) = equal THEN c ← Colls.CompareIntI[sv1.phase[Bar], sv2.phase[Bar]];
RETURN};
portsAtIndices: PUBLIC Colls.Space ~ NEW [Colls.SpacePrivate ← [
Equal: PortAtIndexEqual,
Hash: HashPortAtIndex,
Compare: ComparePortAtIndex,
other: List.PutAssoc[$Name, "ports at indices", NIL]
]];
PortAtIndexEqual: PROC [data, elt1, elt2: REF ANY] RETURNS [BOOL] ~ {
RETURN [ComparePortAtIndex[data, elt1, elt2]=equal]};
HashPortAtIndex: PROC [data, elt: REF ANY] RETURNS [CARDINAL] ~ {
pai: PortAtIndex ~ NARROW[elt];
RETURN [Colls.HashRefI[pai.port] + Colls.HashIntI[pai.ai[Foo]]*137 + Colls.HashIntI[pai.ai[Bar]]]};
ComparePortAtIndex: PROC [data, elt1, elt2: REF ANY] RETURNS [c: Basics.Comparison] ~ {
pai1: PortAtIndex ~ NARROW[elt1];
pai2: PortAtIndex ~ NARROW[elt2];
IF (c ← Colls.CompareRefI[pai1.port, pai2.port]) = equal THEN IF (c ← Colls.CompareIntI[pai1.ai[Foo], pai2.ai[Foo]]) = equal THEN c ← Colls.CompareIntI[pai1.ai[Bar], pai2.ai[Bar]];
RETURN};
Range2Div: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = {
rr ← [
Foo: [
min: CeilDiv[r[Foo].min-f[Foo], t[Foo]],
maxPlusOne: FloorDiv[r[Foo].maxPlusOne-1-f[Foo], t[Foo]] + 1],
Bar: [
min: CeilDiv[r[Bar].min-f[Bar], t[Bar]],
maxPlusOne: FloorDiv[r[Bar].maxPlusOne-1-f[Bar], t[Bar]] + 1]];
};
Range1Div: PUBLIC PROC [r: Range, t, f: NAT] RETURNS [rr: Range] = {
rr ← [
min: CeilDiv[r.min-f, t],
maxPlusOne: FloorDiv[r.maxPlusOne-1-f, t] + 1];
};
Range2MulA: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = {
rr ← [
Foo: [
min: r[Foo].min*t[Foo] + f[Foo],
maxPlusOne: (r[Foo].maxPlusOne-1)*t[Foo] + 1 + f[Foo]],
Bar: [
min: r[Bar].min*t[Bar] + f[Bar],
maxPlusOne: (r[Bar].maxPlusOne-1)*t[Bar] + 1 + f[Bar]]];
};
Range2MulB: 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]]];
};
Range1MulB: PUBLIC PROC [r: Range, t, f: NAT] RETURNS [rr: Range] = {
rr ← [
min: r.min*t + f,
maxPlusOne: r.maxPlusOne*t + f];
};
Start: PROC ~ {
FOR index: NATURAL IN [0 .. sublen) DO
subs[index] ← Convert.RopeFromInt[index].Concat["/"];
ENDLOOP;
RETURN};
Start[];
END.