CSTestImpl.mesa
Debugging aid for CornerStitching.
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Jacobi, January 22, 1986 6:30:03 pm PST
Last Edited by: Jacobi, January 27, 1986 4:39:14 pm PST
DIRECTORY
BasicTime, CS, CornerStitching, D2Basic, IO, Process, Random, TerminalIO;
CSTestImpl: CEDAR MONITOR
IMPORTS BasicTime, CS, CornerStitching, IO, Process, Random, TerminalIO =
BEGIN
all: D2Basic.Rect = [FIRST[INT], FIRST[INT], LAST[INT], LAST[INT]];
randO: Random.RandomStream;
randN: Random.RandomStream;
planeN: CS.Tesselation;
planeO: REF CornerStitching.Tesselation;
RRect: PROC [r: D2Basic.Rect, s: Random.RandomStream] RETURNS [nr: D2Basic.Rect] = {
nr.x1 ← Random.ChooseInt[s, r.x1, r.x2];
nr.y1 ← Random.ChooseInt[s, r.y1, r.y2];
nr.x2 ← Random.ChooseInt[s, nr.x1, r.x2];
nr.y2 ← Random.ChooseInt[s, nr.y1, r.y2];
};
RVal: PROC [s: Random.RandomStream] RETURNS [v: REFNIL] = {
SELECT Random.ChooseInt[s, 0, 7] FROM
0 => v ← $A;
1 => v ← $B;
2 => v ← $C;
3 => v ← $D;
4 => v ← val;
ENDCASE => v ← NIL;
};
--counters for c-hange
cCallsO, cCallsN: INT ← 0;
cChangesO, cChangesN: INT ← 0;
cLoopO, cLoopN: INT;
cRegO, cRegN: LIST OF CS.Region;
cRangeO, cRangeN: CS.Region;
splitLimit: INT ← 6;
ll: INT ← 1;
ChangeO: PROC [range: D2Basic.Rect, val: REF←$x] = {
IF val=$x THEN val ← RVal[randO];
cRangeO ← [range, val];
cRegO ← NIL;
cCallsO ← cCallsO+1;
FOR i: INT IN [ll..cLoopO←Random.ChooseInt[randO, 0, splitLimit]] DO
r: D2Basic.Rect ← RRect[range, randO];
IF r.x1>=r.x2 OR r.y1>=r.y2 THEN LOOP;
cChangesO ← cChangesO+1;
cRegO ← CONS[[r, val], cRegO];
planeO.ChangeRect[r, val];
ENDLOOP;
};
ChangeN: PROC [range: D2Basic.Rect, val: REF←$x] = {
IF val=$x THEN val ← RVal[randN];
cRangeN ← [range, val];
cRegN ← NIL;
cCallsN ← cCallsN+1;
FOR i: INT IN [ll..cLoopN←Random.ChooseInt[randN, 0, splitLimit]] DO
r: D2Basic.Rect ← RRect[range, randN];
IF r.x1>=r.x2 OR r.y1>=r.y2 THEN LOOP;
cChangesN ← cChangesN+1;
cRegN ← CONS[[r, val], cRegN];
planeN.ChangeRect[r, val];
ENDLOOP;
};
ChangeB: PROC [range: D2Basic.Rect←[-100, -100, 100, 100], val: REF←$x] = {
ChangeN[range, val];
ChangeO[range, val];
};
AreaEqual: PROC [r: D2Basic.Rect𡤊ll] RETURNS [BOOL] = {
orl: LIST OF REF CornerStitching.Region ← planeO.ListArea[r, NEW[INT]];
nrl: LIST OF REF CS.Region ← planeN.ListArea[r, NEW[INT]];
DO
IF orl=NIL OR nrl=NIL THEN EXIT;
IF orl.first.rect#nrl.first.rect THEN EXIT;
IF orl.first.value#nrl.first.value THEN EXIT;
orl ← orl.rest;
nrl ← nrl.rest;
ENDLOOP;
RETURN [orl=NIL AND nrl=NIL]
};
lcnt, lstop: INT ← 0;
LongTest: PROC [r: D2Basic.Rect← [-500, -500, 500, 500]] = {
IF ~AreaEqual[r] THEN sig;
DO
ro: D2Basic.Rect ← RRect[r, randO];
rn: D2Basic.Rect ← RRect[r, randN];
IF rn#ro THEN sig;
ChangeB[rn];
IF ~AreaEqual[r] THEN sig;
ForkEnum[rn];
Enum[rn];
IF ~AreaEqual[r] THEN sig;
lcnt ← lcnt+1;
IF lcnt=lstop THEN EXIT;
ENDLOOP
};
--**UN forked**********************
Reg: TYPE = RECORD [r: D2Basic.Rect, val: REFNIL];
nlist: LIST OF Reg ← NIL;
olist: LIST OF Reg ← NIL;
ListEqual: PROC [] RETURNS [BOOL] = {
DO
IF nlist=NIL OR olist=NIL THEN EXIT;
IF nlist.first#olist.first THEN EXIT;
nlist ← nlist.rest;
olist ← olist.rest;
ENDLOOP;
RETURN [nlist=olist]
};
NEnum: CS.RectProc = {
nlist ← CONS[[rect, val], nlist];
ChangeN[rect, val];
};
OEnum: CornerStitching.PerTileChangeProc = {
olist ← CONS[[rect, val], olist];
ChangeO[rect, val];
};
EnumN: PROC [r: D2Basic.Rect] = {
planeN.ChangeEnumerateArea[r, NEnum, NIL, NEW[INT]];
};
EnumO: PROC [r: D2Basic.Rect] = {
planeO.FuncChangeRect[r, OEnum, NIL];
};
t1, t2, t3: BasicTime.Pulses;
timing: RECORD[old, new: LONG CARDINAL];
Enum: PROC [r: D2Basic.Rect] = {
t1 ← BasicTime.GetClockPulses[];
EnumN[r];
t2 ← BasicTime.GetClockPulses[];
EnumO[r];
t3 ← BasicTime.GetClockPulses[];
timing.new ← t2-t1;
timing.old ← t3-t2;
TerminalIO.WriteF["old: %g, new: %g \n", IO.card[timing.old], IO.card[timing.new]];
};
--** Forked **********************
val: REF ← $x;
testBefore: BOOLTRUE;
testAfter: BOOLTRUE;
FNEnum: CS.RectProc = {
IF testBefore THEN NPass[rect, val];
ChangeN[rect, val];
IF testAfter THEN NPass[rect, val];
};
FOEnum: CornerStitching.PerTileChangeProc = {
IF testBefore THEN OPass[rect, val];
ChangeO[rect, val];
IF testAfter THEN OPass[rect, val];
};
FOldEnumerate: PROC [r: D2Basic.Rect] = {
ENABLE UNWIND => oRunning ← FALSE;
planeO.FuncChangeRect[r, FOEnum, NIL ! mustQuit => CONTINUE];
oRunning ← FALSE;
};
FNewEnumerate: PROC [r: D2Basic.Rect] = {
ENABLE UNWIND => nRunning ← FALSE;
planeN.ChangeEnumerateArea[r, FNEnum, NIL, NEW[INT] ! mustQuit => CONTINUE];
nRunning ← FALSE;
};
ForkEnum: PROC [r: D2Basic.Rect] = TRUSTED {
Finish[];
quit ← newFinishedCompare ← oldReady ← interruptO ← FALSE;
cCallsO ← cCallsN ← cChangesO ← cChangesN ← cLoopO ← cLoopN ← 0;
balanceOForCheck ← balanceNForCheck ← 0;
oRunning ← TRUE;
nRunning ← TRUE;
Process.Detach[FORK FNewEnumerate[r]];
Process.Detach[FORK FOldEnumerate[r]];
WHILE oRunning OR nRunning DO Process.Pause[1] ENDLOOP;
};
check: CONDITION;
newFinishedCompare: BOOL;
oldReady: BOOL;
quit: BOOL;
oReg: Reg;
interruptO: BOOLFALSE;
sig: SIGNAL = CODE;
mustQuit: ERROR = CODE;
balanceOForCheck: INT𡤀
balanceNForCheck: INT𡤀
stopAtBalance: INT ← -1;
Quit: INTERNAL PROC [] = {quit ← TRUE; BROADCAST check};
NwaitForOready: ENTRY PROC [rect: D2Basic.Rect, val: REF] = {
ENABLE UNWIND => NULL;
InterruptO: INTERNAL PROC [] = {interruptO ← TRUE; BROADCAST check};
Compares: INTERNAL PROC [] = {
IF balanceNForCheck#balanceOForCheck THEN sig;
IF rect#oReg.r THEN sig;
IF val#oReg.val THEN sig;
IF cCallsO#cCallsN THEN sig;
IF cChangesO#cChangesN THEN sig;
IF cLoopO#cLoopN THEN sig;
IF ~AreaEqual[rect] THEN sig;
};
balanceNForCheck ← balanceNForCheck+1;
WHILE ~oldReady DO
IF quit THEN ERROR mustQuit;
WAIT check;
ENDLOOP;
IF ~quit THEN Compares[];
oldReady ← FALSE;
newFinishedCompare ← TRUE;
BROADCAST check;
};
NPass: PROC [rect: D2Basic.Rect, val: REF] = {
NwaitForOready[rect, val];
IF balanceNForCheck=stopAtBalance THEN sig;
};
InterruptO: ENTRY PROC [] = {
ENABLE UNWIND => NULL;
interruptO ← TRUE;
BROADCAST check;
};
OwaitForNready: ENTRY PROC [rect: D2Basic.Rect, val: REF] = {
ENABLE UNWIND => NULL;
oReg ← [rect, val];
balanceOForCheck ← balanceOForCheck+1;
oldReady ← TRUE;
BROADCAST check;
WHILE ~newFinishedCompare DO
IF quit THEN ERROR mustQuit;
IF interruptO THEN {interruptO ← FALSE; sig};
WAIT check;
ENDLOOP;
IF interruptO THEN {interruptO ← FALSE; sig};
newFinishedCompare ← FALSE;
};
OPass: PROC [rect: D2Basic.Rect, val: REF] = {
OwaitForNready[rect, val];
IF balanceOForCheck=stopAtBalance THEN sig;
};
oRunning: BOOLFALSE;
nRunning: BOOLFALSE;
Finish: ENTRY PROC [] = {
ENABLE UNWIND => NULL;
quit ← TRUE;
BROADCAST check;
WHILE oRunning OR nRunning DO
Process.Pause[1];
BROADCAST check;
ENDLOOP;
};
--** debug help **************
EN: PROC [tile: CS.Tile] RETURNS [CS.Tile] = {
RETURN [tile.eN]
};
NE: PROC [tile: CS.Tile] RETURNS [CS.Tile] = {
TRUSTED { RETURN [LOOPHOLE[tile.nE]] }
};
WS: PROC [tile: CS.Tile] RETURNS [CS.Tile] = {
TRUSTED { RETURN [LOOPHOLE[tile.wS]] }
};
SW: PROC [tile: CS.Tile] RETURNS [CS.Tile] = {
RETURN [tile.sW]
};
R: PROC [t: CS.Tile] RETURNS [CS.Rect] = TRUSTED {
--rect of tile; (upper and right border exclusive)
RETURN [[x1: t.pos.x, y1: t.pos.y, x2: t.nE.pos.x, y2: t.eN.pos.y]]
};
N: PROC [t: CS.Tile] RETURNS [CS.Number] = {RETURN [t.eN.pos.y]};
E: PROC [t: CS.Tile] RETURNS [CS.Number] = TRUSTED {RETURN [t.nE.pos.x]};
S: PROC [t: CS.Tile] RETURNS [CS.Number] = {RETURN [t.pos.y]};
W: PROC [t: CS.Tile] RETURNS [CS.Number] = {RETURN [t.pos.x]};
--** initializatins **************
seed: INT ← 17313;
ResetSeed: PROC [] = {
randO ← Random.Create[0, seed];
randN ← Random.Create[0, seed];
};
Reset: PROC [] = {
Finish[];
ResetSeed[];
planeN.ChangeRect[all, NIL];
planeO.ChangeRect[all, NIL];
nlist ← NIL;
olist ← NIL;
cCallsO ← cCallsN ← cChangesO ← cChangesN ← cLoopO ← cLoopN ← 0;
};
Init: PROC [] = {
planeN ← CS.NewTesselation[];
planeO ← CornerStitching.NewTesselation[];
Reset[];
};
Init[];
END.