<> <> <> <> <> 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: REF_NIL] = { 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_all] 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; <> 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: REF_NIL]; 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: BOOL _ TRUE; testAfter: BOOL _ TRUE; 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: BOOL _ FALSE; sig: SIGNAL = CODE; mustQuit: ERROR = CODE; balanceOForCheck: INT_0; balanceNForCheck: INT_0; 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: BOOL _ FALSE; nRunning: BOOL _ FALSE; 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.