LongTest:
PROC [cmd: Commander.Handle ←
NIL, n:
INT ← 100, m:
INT ← 100,
seed: INT ← 31415, maxSize: NAT ← 2048] RETURNS[CountVec] ~ {
BEGIN ENABLE ABORTED => GOTO exit;
random: Random.RandomStream ← Random.Create[seed: seed];
SkewedRand:
PROC [max:
CARDINAL]
RETURNS [
CARDINAL] ~ {
RETURN [random.ChooseInt[0, max]*random.ChooseInt[0, max]/max+1]
};
doOpCountVec ← [0, 0, 0, 0, 0, 0, 0];
FOR i:
INT
IN [0..n)
DO
bitsPerSample: CARDINAL ← random.ChooseInt[1, 16];
aSize: CVEC ~ [SkewedRand[maxSize], SkewedRand[maxSize]];
bSize: CVEC ~ [SkewedRand[(maxSize+1)/2], SkewedRand[(maxSize+2)/3]];
a: SampleMap;
b: SampleMap;
t1, st1: SampleMap;
nWords: LONG CARDINAL;
IF cmd # NIL THEN cmd.out.PutChar[IF i MOD 10 = 0 THEN '! ELSE '~];
a ← SlowSampleMapOps.Create[sSize: aSize.s, fSize: aSize.f, bitsPerSample: bitsPerSample];
b ← SlowSampleMapOps.Create[sSize: bSize.s, fSize: bSize.f, bitsPerSample: bitsPerSample];
t1 ← SlowSampleMapOps.CreateZ[sSize: aSize.s, fSize: aSize.f, bitsPerSample: bitsPerSample];
st1 ← SlowSampleMapOps.CreateZ[sSize: aSize.s, fSize: aSize.f, bitsPerSample: bitsPerSample];
RunTest[a, b, seed, m];
a ← b ← NIL;
RunTest[a, b, t1, st1, seed, m, nWords];
a ← b ← t1 ← st1 ← NIL;
SafeStorage.ReclaimCollectibleObjects[suspendMe: FALSE];
ENDLOOP;
END;
RETURN[doOpCountVec];
};
RunTest:
PROC [a, b: SampleMap, seed:
INT ← 314159, n:
INT ← 1000] ~ {
a, b, t1, st1: SampleMap, seed: INT ← 314159, n: INT ← 1000, nWords: LONG CARDINAL] ~ {
random: Random.RandomStream ← Random.Create[seed: seed];
sa, sb: SampleMap;
num, first: LONG CARDINAL;
try a real simple things first
SlowSampleMapOps.DoubleCopy[to: t1, slowTo: st1, from: a, destStart: [0, 0]];
[first, num] ← TestEquality[t1, st1, nWords];
IF num # 0 THEN SIGNAL DoubleCopyFailed[first, num];
AddressInit[a, 1, Basics.DoubleShiftRight[LOOPHOLE[a.base.word], 8].lo];
AddressInit[b, -1, Basics.DoubleShiftRight[LOOPHOLE[b.base.word], 8].lo];
sa ← SlowSampleMapOps.Copy[[a]];
IF NOT Equal[[sa],[a]] THEN SIGNAL AnotEqSA[$first];
sb ← SlowSampleMapOps.Copy[[b]];
IF NOT Equal[[sb],[b]] THEN SIGNAL BnotEqSB[$first];
IF NOT Equal[[sa],[a]] THEN SIGNAL AnotEqSA[$afterSb];
FOR i:
INT
IN [0..n)
DO
rand: CARDINAL ← random.ChooseInt[0, CARDINAL.LAST];
function: Function;
op: LastOp;
IF simplePattern
THEN {
ax: WORD;
AddressInit[a, 1, ax ← Basics.DoubleShiftRight[LOOPHOLE[a.base.word], 8].lo];
AddressInit[sa, 1, ax];
AddressInit[b, -1, ax ← Basics.DoubleShiftRight[LOOPHOLE[b.base.word], 8].lo];
AddressInit[sb, -1, ax];
};
[function, op] ← DoOp[a, b, sa, sb, rand];
IF NOT Equal[[sa],[a]] THEN SIGNAL AnotEqSA[$afterDoOp];
IF NOT Equal[[sb],[b]] THEN SIGNAL BnotEqSB[$afterDoOp];
{t: SampleMap ← a; a ← b; b ← t};
{t: SampleMap ← sa; sa ← sb; sb ← t};
Process.CheckForAbort[];
ENDLOOP;
FreeCountedVM[a, b, sa, sb];
a ← b ← sa ← sb ← NIL;
};
SkewTest:
PROC [cmd: Commander.Handle ←
NIL, n:
INT ← 100, m:
INT ← 100,
seed: INT ← 31415, maxSize: NAT ← 2048] RETURNS[CountVec] ~ {
BEGIN ENABLE ABORTED => GOTO exit;
random: Random.RandomStream ← Random.Create[seed: seed];
SkewedRand:
PROC [max:
CARDINAL]
RETURNS [
CARDINAL] ~ {
RETURN [random.ChooseInt[0, max]*random.ChooseInt[0, max]/max+1]
};
doOpCountVec ← [0, 0, 0, 0, 0, 0, 0];
FOR i:
INT
IN [0..n)
DO
bitsPerSample: CARDINAL ← random.ChooseInt[1, 16];
aSize: CVEC ~ [SkewedRand[maxSize], SkewedRand[maxSize]];
bSize: CVEC ~ [SkewedRand[(maxSize+1)/2], SkewedRand[(maxSize+2)/3]];
a: SampleMap;
b: SampleMap;
IF cmd # NIL THEN cmd.out.PutChar[IF i MOD 10 = 0 THEN '! ELSE '~];
-- FunnyCreate makes odd sized SampleMaps
a ← FunnyCreate[sSize: aSize.s, fSize: aSize.f, bitsPerSample: bitsPerSample];
b ← FunnyCreate[sSize: bSize.s, fSize: bSize.f, bitsPerSample: bitsPerSample];
RunSkewTest[a, b, seed, m];
a ← b ← NIL;
SafeStorage.ReclaimCollectibleObjects[suspendMe: FALSE];
ENDLOOP;
END;
RETURN[doOpCountVec];
};
RunSkewTest:
PROC [a, b: SampleMap, seed:
INT ← 314159, n:
INT ← 1000] ~ {
random: Random.RandomStream ← Random.Create[seed: seed];
sa, sb: SampleMap;
AddressInit[a, 1, Basics.DoubleShiftRight[LOOPHOLE[a.base.word], 8].lo];
AddressInit[b, -1, Basics.DoubleShiftRight[LOOPHOLE[b.base.word], 8].lo];
sa ← SlowSampleMapOps.Copy[[a]];
IF NOT Equal[[sa],[a]] THEN SIGNAL AnotEqSA[$first];
sb ← SlowSampleMapOps.Copy[[b]];
IF NOT Equal[[sb],[b]] THEN SIGNAL BnotEqSB[$first];
IF NOT Equal[[sa],[a]] THEN SIGNAL AnotEqSA[$afterSb];
FOR i:
INT
IN [0..n)
DO
rand: CARDINAL ← random.ChooseInt[0, CARDINAL.LAST];
function: Function;
op: LastOp;
IF simplePattern
THEN {
ax: WORD;
AddressInit[a, 1, ax ← Basics.DoubleShiftRight[LOOPHOLE[a.base.word], 8].lo];
AddressInit[sa, 1, ax];
AddressInit[b, -1, ax ← Basics.DoubleShiftRight[LOOPHOLE[b.base.word], 8].lo];
AddressInit[sb, -1, ax];
};
[function, op] ← DoSkewOp[a, b, sa, sb, rand];
IF NOT Equal[[sa],[a]] THEN SIGNAL AnotEqSA[$afterDoOp];
IF NOT Equal[[sb],[b]] THEN SIGNAL BnotEqSB[$afterDoOp];
{t: SampleMap ← a; a ← b; b ← t};
{t: SampleMap ← sa; sa ← sb; sb ← t};
Process.CheckForAbort[];
ENDLOOP;
FreeCountedVM[a, b, sa, sb];
a ← b ← sa ← sb ← NIL;
};
FreeCountedVM:
PROC[a, b, c, d: SampleMap] =
TRUSTED {
WITH a.ref
SELECT
FROM
x: CountedVM.Handle => CountedVM.Free[x];
ENDCASE => NULL;
WITH b.ref
SELECT
FROM
x: CountedVM.Handle => CountedVM.Free[x];
ENDCASE => NULL;
WITH c.ref
SELECT
FROM
x: CountedVM.Handle => CountedVM.Free[x];
ENDCASE => NULL;
WITH d.ref
SELECT
FROM
x: CountedVM.Handle => CountedVM.Free[x];
ENDCASE => NULL;
a.ref ← b.ref ← c.ref ← d.ref ← NIL;
};
FunnyCreate:
PROC [sSize:
CARDINAL, fSize:
CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]]
RETURNS [SampleMap] ~ {
bitsPerLine: NAT ~ Basics.LongMult[fSize, bitsPerSample];
nWords: LONG CARDINAL ~ (Basics.LongMult[sSize, bitsPerLine]+15)/16;
vm: CountedVM.Handle ~ CountedVM.SimpleAllocate[words: nWords];
TRUSTED {
RETURN [UnsafeCreate[
sSize: sSize,
fSize: fSize,
bitsPerSample: bitsPerSample,
bitsPerLine: bitsPerLine,
base: [word: vm.pointer, bit: 0],
nWords: vm.words,
ref: vm
]]};
};
Rot:
PROC [a, b, sa, sb: SampleMap] ~ {
rowSize: NAT ~ MIN[a.sSize, b.fSize];
buf: Buffer ~ ObtainBuffer[rowSize];
IF rowSize > 0
THEN
FOR i:
NAT
IN [0..
MIN[a.fSize, b.sSize])
DO
Get[buffer: buf, sampleMap: b, s: i];
Flip[buf];
Put[buffer: buf, sampleMap: a, s: 0, f: i, ds: 1, df: 0];
Get[buffer: buf, sampleMap: sb, s: i];
Flip[buf];
SlowSampleMapOps.Put[buffer: buf, sampleMap: sa, s: 0, f: i, ds: 1, df: 0, goodDest: a];
ENDLOOP;
ReleaseBuffer[buf];
};
SkewRotate:
PROC [a, b, sa, sb: SampleMap] ~ {
rowSize: NAT ~ MIN[a.sSize, b.fSize];
buf: Buffer ~ ObtainBuffer[rowSize];
IF rowSize > 0
THEN
FOR i:
NAT
IN [0..
MIN[a.fSize, b.sSize])
DO
Get[buffer: buf, sampleMap: b, s: i];
Flip[buf];
Put[buffer: buf, sampleMap: a, s: 0, f: i, ds: 1, df: 0];
Get[buffer: buf, sampleMap: sb, s: i];
Flip[buf];
SlowSampleMapOps.Put[buffer: buf, sampleMap: sa, s: 0, f: i, ds: 1, df: 0, goodDest: NIL];
ENDLOOP;
ReleaseBuffer[buf];
};
DoOp:
PROC [a, b, sa, sb: SampleMap, seed:
CARDINAL]
RETURNS[function: Function, lop: LastOp] ~ {
Rand:
PROC [max:
CARDINAL]
RETURNS [
CARDINAL] ~ {
seed ← seed * 3141 + 3;
RETURN [Basics.HighHalf[Basics.LongMult[max+1, seed]]];
};
RandV: PROC [max: CVEC] RETURNS [CVEC] ~ {RETURN [[Rand[max.s], Rand[max.f]]]};
aMin: CVEC ~ [Rand[a.sSize], Rand[a.fSize]];
aSize: CVEC ~ [Rand[a.sSize-aMin.s], Rand[a.fSize-aMin.f]];
ad: CVEC ~ [Rand[a.sSize-aSize.s], Rand[a.fSize-aSize.f]];
bMin: CVEC ~ [Rand[b.sSize-1], Rand[b.fSize-1]];
bSize: CVEC ~ [Rand[b.sSize-bMin.s-1]+1, Rand[b.fSize-bMin.f-1]+1];
value: CARDINAL ← Rand[Basics.BITSHIFT[1, a.bitsPerSample]-1];
op: NAT = Rand[5];
function ← [VAL[Rand[3]], VAL[Rand[1]]];
SELECT op
FROM
0 =>
IF a.sSize > 0
AND a.fSize > 0
THEN {
randVec: CVEC = RandV[[a.sSize-1, a.fSize-1]];
PutSample[sampleMap: a, index: randVec, value: value, function: function];
SlowSampleMapOps.PutSample[sampleMap: sa, index: randVec, value: value, function: function, goodDest: a];
lastOp ← putSample;
} ELSE lastOp ← none;
1 => {
Move[sampleMap: a, destStart: aMin, sourceStart: ad, size: aSize, function: function];
SlowSampleMapOps.Move[sampleMap: sa, destStart: aMin, sourceStart: ad, size: aSize, function: function, goodDest: a];
lastOp ← move;
};
2 => {
Transfer[dest: a, destStart: aMin, source: [b, bMin, bSize], function: function];
SlowSampleMapOps.Transfer[dest: sa, destStart: aMin, source: [sb, bMin, bSize], function: function, goodDest: a];
lastOp ← transfer;
};
3 => {
IF value = 0 THEN value ← 123456B; -- don't want 0 gray fill
Fill[dest: [a, aMin, aSize], value: value, function: function];
SlowSampleMapOps.Fill[dest: [sa, aMin, aSize], value: value, function: function, goodDest: [a, aMin, aSize] ];
lastOp ← fill;
};
4 => {
s0: INTEGER ← INTEGER[Rand[100]]-50;
f0: INTEGER ← INTEGER[Rand[100]]-50;
phase: NAT ← Rand[bSize.f]*Rand[1];
tile: SampleMap ~ FromSubMap[[b, bMin, bSize]];
slowTile: SampleMap ~ FromSubMap[[sb, bMin, bSize]];
IF tile.sSize > 0
AND tile.fSize > 0
THEN {
lastOp ← tile;
TileBox[dest: a, start: aMin, size: aSize, source: tile, s0: s0, f0: f0, phase: phase, function: function];
SlowSampleMapOps.TileBox[dest: sa, start: aMin, size: aSize, source: slowTile, s0: s0, f0: f0, phase: phase, function: function, goodDest: a];
} ELSE lastOp ← none;
};
5 => {
Rot[FromSubMap[[a, aMin, aSize]], FromSubMap[[b, bMin, bSize]],
FromSubMap[[sa, aMin, aSize]], FromSubMap[[b, bMin, bSize]] ];
lastOp ← rotate;
};
ENDCASE => ERROR;
doOpCountVec[lastOp] ← doOpCountVec[lastOp] + 1;
RETURN[function, lastOp];
};
DoSkewOp:
PROC [a, b, sa, sb: SampleMap, seed:
CARDINAL]
RETURNS[function: Function, lop: LastOp] ~ {
Rand:
PROC [max:
CARDINAL]
RETURNS [
CARDINAL] ~ {
seed ← seed * 3141 + 3;
RETURN [Basics.HighHalf[Basics.LongMult[max+1, seed]]];
};
RandV: PROC [max: CVEC] RETURNS [CVEC] ~ {RETURN [[Rand[max.s], Rand[max.f]]]};
aMin: CVEC ~ [Rand[a.sSize], Rand[a.fSize]];
aSize: CVEC ~ [Rand[a.sSize-aMin.s], Rand[a.fSize-aMin.f]];
ad: CVEC ~ [Rand[a.sSize-aSize.s], Rand[a.fSize-aSize.f]];
bMin: CVEC ~ [Rand[b.sSize-1], Rand[b.fSize-1]];
bSize: CVEC ~ [Rand[b.sSize-bMin.s-1]+1, Rand[b.fSize-bMin.f-1]+1];
value: CARDINAL ← Rand[Basics.BITSHIFT[1, a.bitsPerSample]-1];
op: NAT = Rand[5];
function ← [VAL[Rand[3]], VAL[Rand[1]]];
SELECT op
FROM
0 =>
IF a.sSize > 0
AND a.fSize > 0
THEN {
randVec: CVEC = RandV[[a.sSize-1, a.fSize-1]];
PutSample[sampleMap: a, index: randVec, value: value, function: function];
SlowSampleMapOps.PutSample[sampleMap: sa, index: randVec, value: value, function: function, goodDest: NIL];
lastOp ← putSample;
} ELSE lastOp ← none;
1 => {
Move[sampleMap: a, destStart: aMin, sourceStart: ad, size: aSize, function: function];
SlowSampleMapOps.Move[sampleMap: sa, destStart: aMin, sourceStart: ad, size: aSize, function: function, goodDest: NIL];
lastOp ← move;
};
2 => {
Transfer[dest: a, destStart: aMin, source: [b, bMin, bSize], function: function];
SlowSampleMapOps.Transfer[dest: sa, destStart: aMin, source: [sb, bMin, bSize], function: function, goodDest: NIL];
lastOp ← transfer;
};
3 => {
IF value = 0 THEN value ← 123456B; -- don't want 0 gray fill
Fill[dest: [a, aMin, aSize], value: value, function: function];
SlowSampleMapOps.Fill[dest: [sa, aMin, aSize], value: value, function: function, goodDest: [NIL, [0, 0], [0, 0] ] ];
lastOp ← fill;
};
4 => {
s0: INTEGER ← INTEGER[Rand[100]]-50;
f0: INTEGER ← INTEGER[Rand[100]]-50;
phase: NAT ← Rand[bSize.f]*Rand[1];
tile: SampleMap ~ FromSubMap[[b, bMin, bSize]];
slowTile: SampleMap ~ FromSubMap[[sb, bMin, bSize]];
IF tile.sSize > 0
AND tile.fSize > 0
THEN {
lastOp ← tile;
TileBox[dest: a, start: aMin, size: aSize, source: tile, s0: s0, f0: f0, phase: phase, function: function];
SlowSampleMapOps.TileBox[dest: sa, start: aMin, size: aSize, source: slowTile, s0: s0, f0: f0, phase: phase, function: function, goodDest: NIL];
} ELSE lastOp ← none;
};
5 => {
SkewRotate[FromSubMap[[a, aMin, aSize]], FromSubMap[[b, bMin, bSize]],
FromSubMap[[sa, aMin, aSize]], FromSubMap[[b, bMin, bSize]] ];
lastOp ← rotate;
};
ENDCASE => ERROR;
doOpCountVec[lastOp] ← doOpCountVec[lastOp] + 1;
RETURN[function, lastOp];
};
AddressInit:
PROC[a: SampleMap, inc:
INTEGER, value:
WORD] =
TRUSTED {
sBase: LONG POINTER TO WORD ← LOOPHOLE[a.base.word];
wordsRemaining, nWords: LONG CARDINAL;
WITH a.ref
SELECT
FROM
x: CountedVM.Handle => nWords ← x.words;
ENDCASE => nWords ←
SampleMapOps.ComputeWords[sSize: a.sSize, fSize: a.fSize, bitsPerSample: a.bitsPerSample];
IF nWords < 256
THEN {
FOR j:
LONG
CARDINAL
IN [0..nWords)
DO
sBase^ ← value;
sBase ← sBase + 1;
value ← value + inc;
ENDLOOP;
RETURN
};
FOR i:
LONG
CARDINAL ← 0, i+wordsPerPage
UNTIL i >= nWords - 1
DO
this: WORD ← value;
IF nWords >= 511 THEN IF AllocatorOps.quantumMap[LOOPHOLE[value]] THEN ERROR;
IF wordsRemaining < wordsPerPage
THEN {
FOR j:
LONG
CARDINAL
IN [0..wordsRemaining)
DO
sBase^ ← this;
sBase ← sBase + 1;
this ← this + inc;
ENDLOOP
}
ELSE {
FOR j:
INTEGER
IN [0..wordsPerPage)
DO
sBase^ ← this;
sBase ← sBase + 1;
this ← this + inc;
ENDLOOP;
};
value ← value + 1;
wordsRemaining ← wordsRemaining - wordsPerPage;
ENDLOOP;
};
MakeAddressPattern:
PROC[a, sa: SampleMap, inc:
INTEGER] =
TRUSTED {
sBase: LONG POINTER TO WORD ← LOOPHOLE[a.base.word];
tBase: LONG POINTER TO WORD ← LOOPHOLE[sa.base.word];
value: WORD ← Basics.DoubleShiftRight[LOOPHOLE[a.base.word], 8].lo;
nWords:
LONG
CARDINAL =
SampleMapOps.ComputeWords[sSize: a.sSize, fSize: a.fSize, bitsPerSample: a.bitsPerSample];
wordsRemaining: LONG CARDINAL ← nWords;
IF nWords < 256
THEN {
FOR j:
LONG
CARDINAL
IN [0..nWords)
DO
sBase^ ← tBase^ ← value;
sBase ← sBase + 1;
tBase ← tBase + 1;
value ← value + inc;
ENDLOOP;
RETURN
};
FOR i:
LONG
CARDINAL ← 0, i+wordsPerPage
UNTIL i >= nWords - 1
DO
this: WORD ← value;
IF nWords >= 511 THEN IF AllocatorOps.quantumMap[LOOPHOLE[value]] THEN ERROR;
IF wordsRemaining < wordsPerPage
THEN {
FOR j:
LONG
CARDINAL
IN [0..wordsRemaining)
DO
sBase^ ← tBase^ ← this;
sBase ← sBase + 1;
tBase ← tBase + 1;
this ← this + inc;
ENDLOOP
}
ELSE {
FOR j:
INTEGER
IN [0..wordsPerPage)
DO
sBase^ ← tBase^ ← this;
sBase ← sBase + 1;
tBase ← tBase + 1;
this ← this + inc;
ENDLOOP;
};
wordsRemaining ← wordsRemaining - wordsPerPage;
value ← value + 1;
ENDLOOP;
};
MakeSimpleUpPattern:
PROC[a, sa: SampleMap] =
TRUSTED {
sBase: LONG POINTER TO WORD ← LOOPHOLE[a.base.word];
tBase: LONG POINTER TO WORD ← LOOPHOLE[sa.base.word];
nWords:
LONG
CARDINAL =
SampleMapOps.ComputeWords[sSize: a.sSize, fSize: a.fSize, bitsPerSample: a.bitsPerSample];
FOR i:
LONG
CARDINAL
IN [0.. nWords)
DO
sBase^ ← tBase^ ← LOOPHOLE[i, Basics.LongNumber].lo;
sBase ← sBase + 1;
tBase ← tBase + 1;
ENDLOOP;
};
MakeSimpleDownPattern:
PROC[a, sa: SampleMap] =
TRUSTED {
sBase: LONG POINTER TO WORD ← LOOPHOLE[a.base.word];
tBase: LONG POINTER TO WORD ← LOOPHOLE[sa.base.word];
nWords:
LONG
CARDINAL =
SampleMapOps.ComputeWords[sSize: a.sSize, fSize: a.fSize, bitsPerSample: a.bitsPerSample];
val: WORD ← 177777B;
FOR i:
LONG
CARDINAL
IN [0.. nWords)
DO
sBase^ ← tBase^ ← val;
sBase ← sBase + 1;
tBase ← tBase + 1;
val ← val - 1;
ENDLOOP;
};
MakePattern:
PROC[s, t: SampleMap, nWords:
LONG
CARDINAL, value:
WORD] =
TRUSTED {
sBase: LONG POINTER TO WORD ← LOOPHOLE[s.base.word];
tBase: LONG POINTER TO WORD ← LOOPHOLE[t.base.word];
alt: WORD ← IF value = 0 THEN 0 ELSE Basics.BITNOT[value];
alt2: WORD ← IF value = 0 THEN 0 ELSE Basics.BITSHIFT[value, -3];
temp: WORD ← alt2;
FOR i:
LONG
CARDINAL
IN [0..nWords/2)
DO
sBase^ ← value;
tBase^ ← value;
sBase ← sBase + 1;
tBase ← tBase + 1;
sBase^ ← alt;
tBase^ ← alt;
sBase ← sBase + 1;
tBase ← tBase + 1;
temp ← value;
value ← alt;
alt ← alt2;
alt2 ← temp;
ENDLOOP;
};
ReallyCopy:
PROC[from, to: SampleMap, nWords:
INT] =
TRUSTED {
fromBase: LONG POINTER TO WORD ← LOOPHOLE[from.base.word];
toBase: LONG POINTER TO WORD ← LOOPHOLE[to.base.word];
FOR i:
INT
IN [0..nWords)
DO
toBase^ ← fromBase^;
toBase ← toBase + 1;
fromBase ← fromBase + 1;
ENDLOOP;
};
TestEquality:
PROC[a, sa: SampleMap, nWords:
LONG
CARDINAL]
RETURNS[firstBad, num: LONG CARDINAL] = TRUSTED {
aBase: LONG POINTER TO WORD ← LOOPHOLE[a.base.word];
saBase: LONG POINTER TO WORD ← LOOPHOLE[sa.base.word];
firstBad ← num ← 0;
FOR i:
LONG
CARDINAL
IN [0..nWords)
DO
IF aBase^ # saBase^ THEN IF (num ← num + 1) = 1 THEN firstBad ← i;
aBase ← aBase + 1;
saBase ← saBase + 1;
ENDLOOP;
};
Srt: Commander.CommandProc = {
cv: CountVec;
m, n: INT ← 0;
[] ← CommandTool.Parse[cmd];
m ← IntFromCmd[cmd];
IF m = -1 THEN RETURN;
n ← IntFromCmd[cmd];
IF n = -1 THEN RETURN;
cv ← LongTest[cmd, m, n];
cmd.out.PutF["\nnone: %g, putSample: %g, move: %g, transfer: %g, ",
IO.int[cv[none]], IO.int[cv[putSample]], IO.int[cv[move]], IO.int[cv[transfer]] ];
cmd.out.PutF["fill: %g, tile: %g, rotate: %g\n",
IO.int[cv[fill]], IO.int[cv[tile]], IO.int[cv[rotate]] ];
};
Skew: Commander.CommandProc = {
cv: CountVec;
m, n: INT ← 0;
[] ← CommandTool.Parse[cmd];
m ← IntFromCmd[cmd];
IF m = -1 THEN RETURN;
n ← IntFromCmd[cmd];
IF n = -1 THEN RETURN;
cv ← SkewTest[cmd, m, n];
cmd.out.PutF["\nnone: %g, putSample: %g, move: %g, transfer: %g, ",
IO.int[cv[none]], IO.int[cv[putSample]], IO.int[cv[move]], IO.int[cv[transfer]] ];
cmd.out.PutF["fill: %g, tile: %g, rotate: %g\n",
IO.int[cv[fill]], IO.int[cv[tile]], IO.int[cv[rotate]] ];
};
IntFromCmd:
PROC[cmd: Commander.Handle]
RETURNS[n:
INT] = {
arg: Rope.ROPE = CommandTool.NextArgument[cmd];
n ← -1;
n ← Convert.IntFromRope[arg ! Convert.Error => CONTINUE ];
IF n = -1
THEN
cmd.out.PutF["\nCouldn't parse \"%g\" as a number - quitting\n", IO.rope[arg] ]
};
Commander.Register["srt", Srt, "Run tests of BitBltOpsImpl"];
Commander.Register["skew", Skew, "Run skew tests of BitBltOpsImpl"];
END.