BiRelVectors.Mesa
Last tweaked by Mike Spreitzer on December 14, 1987 1:13:40 pm PST
DIRECTORY AbSets, BiRelBasics, BiRels, IntStuff, SetBasics;
BiRelVectors:
CEDAR
PROGRAM
IMPORTS AbSets, BiRelBasics, BiRels, IntStuff, SetBasics
EXPORTS BiRels
=
BEGIN OPEN IntStuff, SetBasics, Sets:AbSets, Sets, BiRelBasics, BiRels;
Simple: TYPE ~ REF SimplePrivate;
SimplePrivate:
TYPE ~
RECORD [
right: Space,
bounds: IntInterval,
leftDense, domFixed: BOOL,
d: INT,
vals: SimpleElts,
size, freezeCount: INT ← 0];
elt i is stored in vals[i-d]. Thus, there is storage for elts [d .. d+vals.size). Storage cells not corresponding to domain elts have noValue in them.
SimpleElts: TYPE ~ REF SimpleEltsPrivate;
SimpleEltsPrivate: TYPE ~ RECORD [vals: SEQUENCE size: NATURAL OF Value];
CreateSimpleCopy:
PUBLIC
PROC [of: IntFn, bounds: IntInterval ← [], oneToOne, dense, domainFixed: RelBool ←
SAME, rightSpace: Space ←
NIL]
RETURNS [IntFn] ~ {
realBounds: IntInterval ~ of.GetIntDom.Intersect[bounds];
realOneToOne: BOOL ~ oneToOne.RelativizeBool[of.Functional[][rightToLeft]];
realDense: BOOL ~ dense.RelativizeBool[of.IsDense[always, left]];
realDomainFixed: BOOL ~ domainFixed.RelativizeBool[of.SideFixed[left]];
realSpace: Space ~ IF rightSpace#NIL THEN rightSpace ELSE of.Spaces[][right];
vals: SimpleElts ~ NEW [SimpleEltsPrivate[realBounds.Length.EN]];
simple: Simple ~ NEW [SimplePrivate ← [realSpace, realBounds, realDense, realDomainFixed, realBounds.min, vals, of.Size[].EN]];
FOR i:
INT
IN [realBounds.min .. realBounds.max]
DO
TRUSTED {
mv: MaybeValue ~ of.ApplyI[i];
vals[i-simple.d] ← mv.it;
}ENDLOOP;
RETURN [[simpleClasses[realOneToOne][realDense][realDomainFixed][variable], simple]]};
CreateSimple:
PUBLIC
PROC [bounds: IntInterval ← [0, -1], val: Value ← noValue, oneToOne, dense, domainFixed:
BOOL ←
FALSE, rightSpace: Space ← basic]
RETURNS [IntFn] ~ {
vals: SimpleElts ~ NEW [SimpleEltsPrivate[bounds.Length.EN]];
simple: Simple ~ NEW [SimplePrivate ← [rightSpace, bounds, dense, domainFixed, bounds.min, vals, bounds.Length.EN]];
FOR i: NATURAL IN [0 .. vals.size) DO TRUSTED {vals[i] ← val} ENDLOOP;
IF val=noValue
THEN {
simple.bounds ← simple.bounds.ClipTop[simple.bounds.min];
simple.size ← 0};
RETURN [[simpleClasses[oneToOne][dense][domainFixed][variable], simple]]};
SimpleClasses: TYPE ~ ARRAY --oneToOne--BOOL OF ARRAY --leftDense--BOOL OF ARRAY --domainFixed--BOOL OF ARRAY Mutability OF BiRelClass;
simpleClasses: REF SimpleClasses ~ NEW [SimpleClasses];
SimplePrimitive:
PROC [br: BiRel, op:
ATOM, arg1, arg2:
REF
ANY]
RETURNS [PrimitiveAnswer] ~ {
simple: Simple ~ NARROW[br.data];
SELECT op
FROM
$Apply => {dir: Direction ~ ToDir[arg1];
RETURN [IF dir=leftToRight THEN yes ELSE no]};
$ScanRestriction, $GetBounds => {ro: RelOrder ~ ToRO[arg2];
RETURN [IF ro.first#left AND ro.sub[ro.first]#no THEN no ELSE yes]};
$RestrictionSize => {sets: RefSetPair ~ ToSets[arg1];
RETURN [IF sets^=ALL[nilSet] THEN yes ELSE no]};
ENDCASE => RETURN [pass]};
SimpleApply:
PROC [br: BiRel, v: Value, dir: Direction]
RETURNS [MaybeValue] ~ {
simple: Simple ~ NARROW[br.data];
IF br.MutabilityOf=constant AND simple.freezeCount=0 THEN Complain[br, unfrozen];
IF dir=rightToLeft THEN RETURN DefaultApply[br, v, dir];
{i: INT ~ v.VI;
w: Value ~ IF simple.bounds.Contains[i] THEN simple.vals[i-simple.d] ELSE noValue;
RETURN [[w#noValue, w]]}};
SimpleScanRestriction:
PROC [br: BiRel, sets: SetPair,
Test: Tester, ro: RelOrder]
RETURNS [MaybePair] ~ {
simple: Simple ~ NARROW[br.data];
IF br.MutabilityOf=constant AND simple.freezeCount=0 THEN Complain[br, unfrozen];
IF ro.first#left AND ro.sub[ro.first]#no THEN RETURN DefaultScanRestriction[br, sets, Test, ro];
{vals: SimpleElts ~ simple.vals;
lb: MaybeIntInterval ~ IF sets[left]#nilSet THEN sets[left].QuaIntInterval ELSE [TRUE, []];
scanBounds: IntInterval ~ simple.bounds.Intersect[IF lb.found THEN lb.it ELSE []];
left: Set ~ sets[left];
right: Set ~ sets[right];
rn: BOOL ~ right=nilSet;
ld: BOOL ~ lb.found;
IF ro.sub[left]=bwd
THEN
FOR i:
INT
DECREASING
IN [scanBounds.min .. scanBounds.max]
DO
pair: Pair ~ [[i[i]], simple.vals[i-simple.d]];
IF pair[right]#noValue AND (ld OR left.HasMember[[i[i]]]) AND (rn OR right.HasMember[pair[right]]) AND Test[pair] THEN RETURN [[TRUE, pair]];
ENDLOOP
ELSE
FOR i:
INT
IN [scanBounds.min .. scanBounds.max]
DO
pair: Pair ~ [[i[i]], simple.vals[i-simple.d]];
IF pair[right]#noValue AND (ld OR left.HasMember[[i[i]]]) AND (rn OR right.HasMember[pair[right]]) AND Test[pair] THEN RETURN [[TRUE, pair]];
ENDLOOP;
RETURN [noMaybePair]}};
SimpleRestrictionSize:
PROC [br: BiRel, sets: SetPair, limit:
EINT]
RETURNS [
EINT] ~ {
simple: Simple ~ NARROW[br.data];
IF sets # ALL[nilSet] THEN RETURN DefaultRestrictionSize[br, sets, limit];
RETURN [IE[simple.size]]};
SimpleGetBounds:
PROC [br: BiRel, want: EndBools, ro: RelOrder]
RETURNS [MaybePairInterval] ~ {
simple: Simple ~ NARROW[br.data];
IF br.MutabilityOf=constant AND simple.freezeCount=0 THEN Complain[br, unfrozen];
IF ro.first#left AND ro.sub[left]#no THEN RETURN DefaultGetBounds[br, want, ro];
IF simple.bounds.Empty
THEN
RETURN [[
FALSE, [
min: [[i[simple.bounds.min]], noValue],
max: [[i[simple.bounds.max]], noValue]] ]];
{pi: PairInterval ~ [min: [[i[simple.bounds.min]], simple.vals[simple.bounds.min-simple.d]], max: [[i[simple.bounds.max]], simple.vals[simple.bounds.max-simple.d]]];
RETURN [[TRUE, IF ro.sub[left]#bwd THEN pi ELSE RevPI[pi] ]]}};
SimpleCopy:
PROC [br: BiRel]
RETURNS [VarBiRel] ~ {
simple: Simple ~ NARROW[br.data];
v1: SimpleElts ~ simple.vals;
IF br.MutabilityOf=constant AND simple.freezeCount=0 THEN Complain[br, unfrozen];
{v2: SimpleElts ~ NEW [SimpleEltsPrivate[v1.size]];
s2: Simple ~ NEW [SimplePrivate ← simple^];
s2.vals ← v2;
s2.freezeCount ← 0;
FOR i: NATURAL IN [0 .. v2.size) DO TRUSTED {v2[i] ← v1[i]} ENDLOOP;
RETURN AsVar[[simpleClasses [br.Functional[][rightToLeft]] [simple.leftDense] [simple.domFixed] [variable], s2]]}};
SimpleFreeze:
PROC [br: BiRel]
RETURNS [ConstBiRel] ~ {
simple: Simple ~ NARROW[br.data];
IF br.MutabilityOf#variable THEN Complain[br, notVariable];
simple.freezeCount ← simple.freezeCount + 1;
RETURN AsConst[[
simpleClasses [br.IsOneToOne] [simple.leftDense] [br.SideFixed[left]] [constant],
simple]];
};
SimpleThaw:
PROC [br: BiRel] ~ {
simple: Simple ~ NARROW[br.data];
IF br.MutabilityOf#variable THEN Complain[br, notVariable];
IF simple.freezeCount<=0 THEN Complain[br, "too many thaws"];
simple.freezeCount ← simple.freezeCount-1;
RETURN};
SimpleAddSet:
PROC [br, other: BiRel, if: IfHadPair]
RETURNS [some: HadSetPair] ~ {
simple: Simple ~ NARROW[br.data];
right: Space ~ simple.right;
invSearch: BOOL ~ br.Functional[][rightToLeft];
urSize: INT ~ simple.size;
bounds: IntInterval;
d: INT;
vals: SimpleElts;
expansionCount: NATURAL ← 0;
Per:
PROC [pair: Pair]
RETURNS [
BOOL] ~ {
i: INT ~ pair[left].VI;
news: Had ← different;
IF invSearch
THEN
FOR j:
INT
IN [bounds.min-d .. bounds.max-d]
DO
IF vals[j]#noValue
AND right.SEqual[vals[j], pair[right]]
THEN
{some[rightToLeft][IF i=j THEN same ELSE different] ← TRUE; EXIT};
REPEAT FINISHED => some[rightToLeft][none] ← TRUE;
ENDLOOP;
IF bounds.Contains[i]
THEN {
old: Value ~ vals[i-d];
IF old=noValue
THEN {
news ← none;
simple.size ← simple.size+1;
}
ELSE IF right.SEqual[pair[right], old] THEN news ← same
}
ELSE IF simple.domFixed THEN br.Complain[fixedSide, LIST[[a[$left]]]]
ELSE {
de: NATURAL ~ EnsureContains[simple, [i, i]];
IF de=0 THEN ERROR;
expansionCount ← expansionCount + de;
simple.size ← simple.size+1;
bounds ← simple.bounds; d ← simple.d; vals ← simple.vals; news ← none};
TRUSTED {vals[i-d] ← pair[right]};
some[leftToRight][news] ← TRUE;
RETURN [FALSE]};
IF br.MutabilityOf # variable THEN br.Complain[notVariable];
IF simple.freezeCount#0 THEN br.Complain[frozen];
some ← ALL[ALL[FALSE]];
IF other.QualityOf[$GetIntDom] >= goodDefault THEN expansionCount ← EnsureContains[simple, other.GetIntDom[]];
bounds ← simple.bounds; d ← simple.d; vals ← simple.vals;
[] ← other.Scan[Per];
{newCount: NATURAL ~ simple.size - urSize;
IF newCount>expansionCount THEN ERROR;
IF simple.leftDense AND newCount<expansionCount THEN br.Complain[denseSide, LIST[[a[$left]]]];
IF newCount#0 THEN some[leftToRight][none] ← TRUE;
RETURN}};
EnsureContains:
PROC [simple: Simple, bounds: IntInterval]
RETURNS [expansionCount:
NATURAL] ~ {
IF bounds.min >= simple.bounds.min AND bounds.max <= simple.bounds.max THEN RETURN [0];
{oldVals: SimpleElts ~ simple.vals;
oldSize: NATURAL ~ oldVals.size;
oldBounds: IntInterval ~ simple.bounds;
newBounds: IntInterval ~ simple.bounds.MBI[bounds];
newLen: NATURAL ~ newBounds.Length.EN;
oldD: INT ~ simple.d;
expansionCount ← newLen - oldBounds.Length.EN;
simple.bounds ← newBounds;
IF newBounds.min >= oldD AND newBounds.max <= oldD+(oldSize-1) THEN RETURN;
IF newLen <= oldSize
THEN {
newPad: INT ~ (oldSize - newLen)/2;
newD: INT ~ ISub[newBounds.min, newPad].ClipI;
IF new
D > old
D
THEN {
FOR i:
INT
IN [oldBounds.min .. oldBounds.max]
DO
TRUSTED {oldVals[i-newD] ← oldVals[i-oldD]};
ENDLOOP;
IF
NOT oldBounds.Empty
THEN
FOR i:
INT
IN (oldBounds.max-new
D .. oldBounds.max-old
D]
DO
TRUSTED {oldVals[i] ← noValue};
ENDLOOP;
};
IF new
D < old
D
THEN {
FOR i:
INT
DECREASING
IN [oldBounds.min .. oldBounds.max]
DO
TRUSTED {oldVals[i-newD] ← oldVals[i-oldD]};
ENDLOOP;
IF
NOT oldBounds.Empty
THEN
FOR i:
INT
IN [oldBounds.min-old
D .. oldBounds.min-new
D)
DO
TRUSTED {oldVals[i] ← noValue};
ENDLOOP;
};
simple.d ← newD;
RETURN};
{newSize: NATURAL ~ MIN[INT[NATURAL.LAST], MAX[newLen, INT[oldSize]*2]];
newVals: SimpleElts ~ NEW [SimpleEltsPrivate[newSize]];
newPad: INT ~ (newSize - newLen)/2;
newD: INT ~ newBounds.min - newPad;
IF oldBounds.Empty
THEN
TRUSTED {
FOR i: INT IN [0 .. newSize) DO newVals[i] ← noValue ENDLOOP;
}
ELSE
TRUSTED {
FOR i: INT IN [0 .. oldBounds.min-newD) DO newVals[i] ← noValue ENDLOOP;
FOR i: INT IN [oldBounds.min .. oldBounds.max] DO newVals[i-newD] ← oldVals[i-oldD] ENDLOOP;
FOR i: INT IN (oldBounds.max-newD .. newSize) DO newVals[i] ← noValue ENDLOOP;
};
simple.d ← newD;
simple.vals ← newVals;
RETURN}}};
SimpleDenseRemSet:
PROC [br, other: BiRel]
RETURNS [some: HadSetPair ← []] ~ {
simple: Simple ~ NARROW[br.data];
vals: SimpleElts ~ simple.vals;
right: Space ~ simple.right;
urSize: INT ~ simple.size;
oldBounds: IntInterval ~ simple.bounds;
otherBounds: IntInterval ~ other.GetIntDom[];
scanBounds: IntInterval ~ oldBounds.Intersect[otherBounds];
mustKeep: IntInterval ← anEmptyInterval;
may: IntInterval ← oldBounds;
Per:
PROC [pair: Pair]
RETURNS [
BOOL] ~ {
i: INT ~ pair[left].VI;
w: Value ~ vals[i-simple.d];
hadIt: BOOL ~ right.SEqual[pair[right], w];
IF hadIt
THEN {
IF simple.domFixed THEN br.Complain[fixedSide, LIST[[a[$left]]]]
ELSE IF mustKeep.Contains[i] THEN br.Complain[denseSide, LIST[[a[$left]]]]
ELSE
IF may.Contains[i]
THEN {
SELECT i
FROM
< mustKeep.min => may.min ← i+1;
> mustKeep.max => may.max ← i-1;
ENDCASE => ERROR;
};
TRUSTED {vals[i-simple.d] ← noValue};
some[leftToRight][same] ← TRUE; simple.size ← simple.size - 1}
ELSE {
IF NOT may.Contains[i] THEN br.Complain[denseSide, LIST[[a[$left]]]]
ELSE IF NOT mustKeep.Contains[i] THEN mustKeep ← [min: MIN[mustKeep.min, i], max: MAX[mustKeep.max, i]];
some[leftToRight][different] ← TRUE};
RETURN [FALSE]};
IF br.MutabilityOf # variable THEN br.Complain[notVariable];
IF simple.freezeCount#0 THEN br.Complain[frozen];
some[leftToRight][none] ← scanBounds#otherBounds;
IF br.Functional[][rightToLeft] THEN some[rightToLeft] ← Has[br, other, [FALSE, TRUE]][rightToLeft];
[] ← other.ScanHalfRestriction[IIAsSet[scanBounds], Per];
simple.bounds ← may;
simple.d ← simple.d - oldBounds.min + simple.bounds.min;
IF may.Length.AddI[urSize-simple.size] # oldBounds.Length THEN br.Complain[denseSide, LIST[[a[$left]]]];
RETURN};
SimpleSparseRemSet:
PROC [br, other: BiRel]
RETURNS [some: HadSetPair ← []] ~ {
simple: Simple ~ NARROW[br.data];
vals: SimpleElts ~ simple.vals;
right: Space ~ simple.right;
oldBounds: IntInterval ~ simple.bounds;
otherBounds: IntInterval ~ other.GetIntDom[];
scanBounds: IntInterval ~ otherBounds.Intersect[oldBounds];
rebound: BOOL ← FALSE;
Per:
PROC [pair: Pair]
RETURNS [pass:
BOOL ←
FALSE] ~ {
i: INT ~ pair[left].VI;
w: Value ~ vals[i-simple.d];
notno: BOOL ~ w#noValue;
hadIt: BOOL ~ notno AND right.SEqual[pair[right], w];
IF hadIt
THEN {
IF simple.domFixed THEN br.Complain[fixedSide, LIST[[a[$left]]]];
IF i=oldBounds.min OR i=oldBounds.max THEN rebound ← TRUE;
TRUSTED {vals[i-simple.d] ← noValue};
simple.size ← simple.size - 1;
some[leftToRight][same] ← TRUE}
ELSE some[leftToRight][IF notno THEN different ELSE none] ← TRUE;
};
IF br.MutabilityOf # variable THEN br.Complain[notVariable];
IF simple.freezeCount#0 THEN br.Complain[frozen];
some[leftToRight][none] ← scanBounds#otherBounds;
IF br.Functional[][rightToLeft] THEN some[rightToLeft] ← Has[br, other, [FALSE, TRUE]][rightToLeft];
[] ← other.ScanHalfRestriction[IIAsSet[scanBounds], Per];
IF rebound THEN FixBounds[br, simple];
RETURN};
FixBounds:
PROC [br: BiRel, simple: Simple] ~ {
vals: SimpleElts ~ simple.vals;
d: INT ~ simple.d;
oldBounds: IntInterval ~ simple.bounds;
newBounds: IntInterval ← oldBounds;
WHILE newBounds.min<=newBounds.max AND vals[newBounds.min-d]=noValue DO newBounds ← newBounds.ClipBot[newBounds.min] ENDLOOP;
WHILE newBounds.min<=newBounds.max AND vals[newBounds.max-d]=noValue DO newBounds ← newBounds.ClipTop[newBounds.max] ENDLOOP;
simple.bounds ← newBounds;
IF NOT (oldBounds.Empty OR newBounds.Empty) THEN simple.d ← simple.d - simple.bounds.min + newBounds.min;
RETURN};
LeftDelete:
PROC [simple: Simple, where: IntInterval] ~ {
in: IntInterval ~ where.Intersect[simple.bounds];
IF in.Empty THEN RETURN;
FOR i:
INT
IN [in.min-simple.
d .. in.max-simple.
d]
DO
IF simple.vals[i]#noValue
THEN
TRUSTED {
simple.vals[i] ← noValue;
simple.size ← simple.size-1};
ENDLOOP;
IF where.min > simple.bounds.min
THEN
IF where.max < simple.bounds.max
THEN NULL
ELSE simple.bounds.max ← where.min-1
ELSE
IF where.max < simple.bounds.max
THEN simple.bounds.min ← where.max+1
ELSE simple.bounds ← anEmptyInterval;
RETURN};
SimpleReplaceMe:
PROC [br, with: BiRel, where: IntInterval] ~ {
simple: Simple ~ NARROW[br.data];
clip: IntInterval ~ with.GetIntDom[];
clipLen: EINT ~ clip.Length;
whereLen: EINT ~ where.Length;
tailShift: EINT ~ clipLen.Sub[whereLen];
insertShift: EINT ~ ISub[where.min, clip.min];
oldBounds: IntInterval ~ simple.bounds;
insertBoundsEst: IntInterval ~ clip.ClipShiftInterval[insertShift];
beforeTail: INT ~ IF where.Empty THEN where.min-1 ELSE where.max;
bounds: IntInterval ← anEmptyInterval;
newBoundsEst, headNeed, tailNeed: IntInterval;
AddStuff: PROC [new: IntInterval] ~ {bounds ← bounds.MBI[new]};
AddPair:
PROC [pair: Pair]
RETURNS [
BOOL] ~ {
i: INT ~ insertShift.AddI[pair[left].VI].EI;
[] ← EnsureContains[simple, [i, i]];
AddStuff[[i, i]]; simple.size ← simple.size + 1;
TRUSTED {simple.vals[i-simple.d] ← pair[right]};
RETURN [FALSE]};
IF br.MutabilityOf # variable THEN br.Complain[notVariable];
IF simple.freezeCount#0 THEN br.Complain[frozen];
SELECT
TRUE
FROM
oldBounds.max < where.min => {headNeed ← newBoundsEst ← oldBounds; tailNeed ← anEmptyInterval};
oldBounds.min > beforeTail => {tailNeed ← newBoundsEst ← oldBounds.ShiftInterval[tailShift]; headNeed ← anEmptyInterval};
ENDCASE => {
newBoundsEst ← [
min: MIN[oldBounds.min, where.min],
max: tailShift.AddI[MAX[oldBounds.max, where.max]].ClipI];
headNeed ← newBoundsEst.ClipTop[where.min];
tailNeed ← newBoundsEst.ClipBot[tailShift.AddI[beforeTail].ClipI]};
[] ← EnsureContains[simple, tailNeed];
AddStuff[headNeed];
AddStuff[tailNeed];
IF
NOT tailNeed.Empty
THEN
SELECT tailShift.Sgn[]
FROM
<0 => {
FOR i:
INT
IN [tailNeed.min-simple.
d .. tailNeed.max-simple.
d]
DO
j: INT ~ tailShift.SubFromI[i].EI;
IF simple.vals[i]=noValue THEN simple.size ← simple.size-1;
TRUSTED {simple.vals[i] ← simple.vals[j]; simple.vals[j] ← noValue};
ENDLOOP;
};
>0 => {
olds: IntInterval ~ oldBounds.ClipBot[insertBoundsEst.max].ClipTop[tailNeed.min];
FOR i:
INT
DECREASING
IN [tailNeed.min .. tailNeed.max]
DO
j: INT ~ tailShift.SubFromI[i].EI;
TRUSTED {simple.vals[i-simple.d] ← simple.vals[j-simple.d]};
ENDLOOP;
FOR i:
INT
IN [olds.min .. olds.max]
DO
TRUSTED {simple.vals[i-simple.d] ← noValue};
ENDLOOP;
};
=0 => NULL;
ENDCASE => ERROR;
LeftDelete[simple, insertBoundsEst];
{midSize: INT ~ simple.size;
[] ← with.Scan[AddPair];
IF simple.leftDense AND headNeed.Length.Add[tailNeed.Length].AddI[simple.size-midSize] # bounds.Length THEN br.Complain[denseSide, LIST[[a[$left]]]];
IF simple.domFixed AND bounds#oldBounds THEN br.Complain[fixedSide, LIST[[a[$left]]]];
simple.bounds ← bounds;
IF NOT (bounds.Empty OR oldBounds.Empty) THEN simple.d ← simple.d-oldBounds.min+simple.bounds.min;
RETURN}};
SimpleShiftAndClipMe:
PROC [br: BiRel, shift:
EINT, clip: IntInterval] ~ {
simple: Simple ~ NARROW[br.data];
unshifted: IntInterval ~ simple.bounds.Intersect[clip];
newBounds: IntInterval ~ unshifted.ClipShiftInterval[shift];
IF br.MutabilityOf#variable THEN br.Complain[notVariable];
IF simple.freezeCount#0 THEN br.Complain[frozen];
IF simple.domFixed AND newBounds#simple.bounds THEN br.Complain[fixedSide, LIST[[a[$left]]]];
TRUSTED {
FOR i:
INT
IN [simple.bounds.min-simple.
d .. unshifted.min-simple.
d)
DO
IF simple.vals[i]#noValue THEN {simple.vals[i] ← noValue; simple.size ← simple.size-1};
ENDLOOP;
FOR i:
INT
IN (unshifted.max-simple.
d .. simple.bounds.max-simple.
d]
DO
IF simple.vals[i]#noValue THEN {simple.vals[i] ← noValue; simple.size ← simple.size-1};
ENDLOOP;
};
simple.d ← shift.AddI[simple.d].EI;
simple.bounds ← newBounds;
RETURN};
SimpleSpaces:
PROC [br: BiRel]
RETURNS [SpacePair] ~ {
simple: Simple ~ NARROW[br.data];
RETURN [[ints, simple.right]]};
SimpleIsDense:
PROC [br: BiRel, when: When, side: Side]
RETURNS [
BOOL] ~ {
simple: Simple ~ NARROW[br.data];
RETURN [side=left AND simple.leftDense]};
SimpleSideFixed:
PROC [br: BiRel, side: Side]
RETURNS [
BOOL] ~ {
simple: Simple ~ NARROW[br.data];
RETURN [br.MutabilityOf=constant OR (side=left AND simple.domFixed)]};
Start:
PROC ~ {
FOR isOneToOne:
BOOL
IN
BOOL
DO
FOR dense:
BOOL
IN
BOOL
DO
FOR domainFixed:
BOOL
IN
BOOL
DO
FOR mutability: Mutability
IN Mutability
DO
simpleClasses[isOneToOne][dense][domainFixed][mutability] ← CreateClass[
cp: [
Primitive: SimplePrimitive,
Apply: SimpleApply,
ScanRestriction: SimpleScanRestriction,
RestrictionSize: SimpleRestrictionSize,
GetBounds: SimpleGetBounds,
Copy: SimpleCopy,
Freeze: SimpleFreeze,
Thaw: SimpleThaw,
AddSet: SimpleAddSet,
RemSet: IF dense THEN SimpleDenseRemSet ELSE SimpleSparseRemSet,
ReplaceMe: SimpleReplaceMe,
ShiftAndClipMe: SimpleShiftAndClipMe,
Spaces: SimpleSpaces,
IsDense: SimpleIsDense,
SideFixed: SimpleSideFixed,
functional: [TRUE, isOneToOne],
mutability: mutability
],
dirable: [TRUE, TRUE]
];
ENDLOOP ENDLOOP ENDLOOP ENDLOOP;
};
Start[];
END.