<> <> <> <> DIRECTORY Basics, ImagerSample, ImagerTransformation, PrincOps, PrincOpsUtils, Process, Real; ImagerSampleImpl: CEDAR MONITOR IMPORTS Basics, ImagerSample, ImagerTransformation, PrincOpsUtils, Process, Real EXPORTS ImagerSample ~ BEGIN OPEN ImagerSample; assertSampleSizeMatchesWordSize: BOOL[TRUE..TRUE] ~ SIZE[Sample]=SIZE[WORD]; bitsPerWord: NAT ~ Basics.bitsPerWord; lgBitsPerWord: NAT ~ Basics.logBitsPerWord; NewBuffer: PUBLIC PROC [iSize, jSize: NAT, scratch: SampleBuffer _ NIL] RETURNS [SampleBuffer] ~ { size: NAT ~ Basics.LongMult[iSize, jSize]; new: SampleBuffer _ scratch; IF new=NIL OR new.size> nScratchSlots: NAT ~ 2; nScratchAvail: NAT _ 0; scratch: ARRAY [0..nScratchSlots) OF SampleBuffer _ ALL[NIL]; rover: NAT _ 0; ObtainScratchBuffer: PUBLIC ENTRY PROC [iSize, jSize: NAT] RETURNS [buffer: SampleBuffer _ NIL] ~ { ENABLE UNWIND => NULL; size: NAT ~ Basics.LongMult[iSize, jSize]; FOR i: NAT DECREASING IN [0..nScratchAvail) DO IF scratch[i].size >= size THEN { buffer _ scratch[i]; IF i # nScratchAvail-1 THEN scratch[i] _ scratch[nScratchAvail-1]; nScratchAvail _ nScratchAvail - 1; scratch[nScratchAvail] _ NIL; EXIT; }; ENDLOOP; buffer _ NewBuffer[iSize: iSize, jSize: jSize, scratch: buffer]; }; ReleaseScratchBuffer: PUBLIC ENTRY PROC [buffer: SampleBuffer] ~ { IF nScratchAvail < nScratchSlots THEN { scratch[nScratchAvail] _ buffer; nScratchAvail _ nScratchAvail + 1; } ELSE { scratch[rover] _ buffer; rover _ (rover + 1) MOD nScratchSlots; }; }; <<>> DoWithScratchBuffer: PUBLIC PROC [iSize, jSize: NAT, action: PROC [SampleBuffer]] ~ { buffer: SampleBuffer ~ ObtainScratchBuffer[iSize, jSize]; action[buffer ! UNWIND => ReleaseScratchBuffer[buffer]]; ReleaseScratchBuffer[buffer]; }; <<>> GetSample: PUBLIC PROC [buffer: SampleBuffer, i, j: NAT] RETURNS [Sample] ~ { k: NAT ~ Basics.BoundsCheck[i, buffer.iSize]*buffer.jSize+Basics.BoundsCheck[j, buffer.jSize]; RETURN[buffer[k]]; }; PutSample: PUBLIC PROC [buffer: SampleBuffer, i, j: NAT, sample: Sample] ~ { k: NAT ~ Basics.BoundsCheck[i, buffer.iSize]*buffer.jSize+Basics.BoundsCheck[j, buffer.jSize]; buffer[k] _ sample; }; GetPointer: PUBLIC PROC [buffer: SampleBuffer, i, j, count: NAT] RETURNS [UnsafeSamples] ~ { k: NAT ~ Basics.BoundsCheck[i, buffer.iSize]*buffer.jSize+Basics.BoundsCheck[j, buffer.jSize]; IF count#0 THEN [] _ Basics.BoundsCheck[j+count-1, buffer.jSize]; TRUSTED { RETURN[LOOPHOLE[@buffer[k]]] }; }; UnsafeAdd: PUBLIC UNSAFE PROC [src1, src2, dst: UnsafeSamples, count: NAT] ~ UNCHECKED { THROUGH [0..count/8) DO dst[0] _ src1[0]+src2[0]; dst[1] _ src1[1]+src2[1]; dst[2] _ src1[2]+src2[2]; dst[3] _ src1[3]+src2[3]; dst[4] _ src1[4]+src2[4]; dst[5] _ src1[5]+src2[5]; dst[6] _ src1[6]+src2[6]; dst[7] _ src1[7]+src2[7]; src1 _ src1+8; src2 _ src2+8; dst _ dst+8; ENDLOOP; FOR k: NAT IN[0..count MOD 8) DO dst[k] _ src1[k]+src2[k] ENDLOOP; }; <<>> UnsafeSub: PUBLIC UNSAFE PROC [src1, src2, dst: UnsafeSamples, count: NAT] ~ UNCHECKED { THROUGH [0..count/8) DO dst[0] _ src1[0]-src2[0]; dst[1] _ src1[1]-src2[1]; dst[2] _ src1[2]-src2[2]; dst[3] _ src1[3]-src2[3]; dst[4] _ src1[4]-src2[4]; dst[5] _ src1[5]-src2[5]; dst[6] _ src1[6]-src2[6]; dst[7] _ src1[7]-src2[7]; src1 _ src1+8; src2 _ src2+8; dst _ dst+8; ENDLOOP; FOR k: NAT IN[0..count MOD 8) DO dst[k] _ src1[k]-src2[k] ENDLOOP; }; <<>> UnsafeLookup: PUBLIC UNSAFE PROC [tbl, src, dst: UnsafeSamples, count: NAT] ~ UNCHECKED { THROUGH [0..count/8) DO dst[0] _ tbl[src[0]]; dst[1] _ tbl[src[1]]; dst[2] _ tbl[src[2]]; dst[3] _ tbl[src[3]]; dst[4] _ tbl[src[4]]; dst[5] _ tbl[src[5]]; dst[6] _ tbl[src[6]]; dst[7] _ tbl[src[7]]; src _ src+8; dst _ dst+8; ENDLOOP; FOR k: NAT IN[0..count) DO dst[k] _ tbl[src[k]] ENDLOOP; }; <<>> AddSamples: PUBLIC PROC [samples: SampleBuffer, si, sj: NAT _ 0, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ { src: UnsafeSamples ~ GetPointer[samples, si, sj, count]; dst: UnsafeSamples ~ GetPointer[buffer, bi, bj, count]; TRUSTED { UnsafeAdd[src1: dst, src2: src, dst: dst, count: count] }; }; <<>> SubSamples: PUBLIC PROC [samples: SampleBuffer, si, sj: NAT _ 0, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ { src: UnsafeSamples ~ GetPointer[samples, si, sj, count]; dst: UnsafeSamples ~ GetPointer[buffer, bi, bj, count]; TRUSTED { UnsafeSub[src1: dst, src2: src, dst: dst, count: count] }; }; <<>> LookupSamples: PUBLIC PROC [table: SampleBuffer, samples: SampleBuffer, si, sj: NAT _ 0, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ { tbl: UnsafeSamples ~ GetPointer[table, 0, 0, 0]; src: UnsafeSamples ~ GetPointer[samples, si, sj, count]; dst: UnsafeSamples ~ GetPointer[buffer, bi, bj, count]; TRUSTED { FOR k: NAT IN[0..count) DO dst[k] _ table[src[k]] ENDLOOP }; }; <<>> LookupPixels: PUBLIC PROC [tables: SampleBuffer, pixels: SampleBuffer, pj: NAT _ 0, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ { dst: UnsafeSamples ~ GetPointer[buffer, bi, bj, count]; SELECT tables.iSize FROM 0 => NULL; 1 => { tbl0: UnsafeSamples ~ GetPointer[tables, 0, 0, 0]; src0: UnsafeSamples ~ GetPointer[pixels, 0, pj, count]; TRUSTED { FOR k: NAT IN[0..count) DO dst[k] _ tbl0[src0[k]] ENDLOOP }; }; 2 => { tbl0: UnsafeSamples ~ GetPointer[tables, 0, 0, 0]; tbl1: UnsafeSamples ~ GetPointer[tables, 1, 0, 0]; src0: UnsafeSamples ~ GetPointer[pixels, 0, pj, count]; src1: UnsafeSamples ~ GetPointer[pixels, 1, pj, count]; TRUSTED { FOR k: NAT IN[0..count) DO dst[k] _ tbl0[src0[k]]+tbl1[src1[k]] ENDLOOP }; }; 3 => { tbl0: UnsafeSamples ~ GetPointer[tables, 0, 0, 0]; tbl1: UnsafeSamples ~ GetPointer[tables, 1, 0, 0]; tbl2: UnsafeSamples ~ GetPointer[tables, 2, 0, 0]; src0: UnsafeSamples ~ GetPointer[pixels, 0, pj, count]; src1: UnsafeSamples ~ GetPointer[pixels, 1, pj, count]; src2: UnsafeSamples ~ GetPointer[pixels, 2, pj, count]; TRUSTED { FOR k: NAT IN[0..count) DO dst[k] _ tbl0[src0[k]]+tbl1[src1[k]]+tbl2[src2[k]] ENDLOOP }; }; ENDCASE => FOR k: NAT IN[0..count) DO sum: Sample _ 0; FOR i: NAT IN[0..tables.iSize) DO sum _ sum+tables.GetSample[i, pixels.GetSample[i, pj+k]]; ENDLOOP; buffer.PutSample[bi, bj+k, sum]; ENDLOOP; }; <<>> LgEntry: TYPE ~ RECORD[powerOfTwo: BOOL, lg: NAT _ 0]; LgArray: TYPE ~ ARRAY BitsPerSample OF LgEntry; lgArray: REF LgArray ~ InitLgArray[]; InitLgArray: PROC RETURNS [REF LgArray] ~ { lgArray: REF LgArray ~ NEW[LgArray _ ALL[[powerOfTwo: FALSE]]]; FOR lg: NAT IN[0..lgBitsPerWord] DO lgArray[Basics.BITSHIFT[1, lg]] _ [powerOfTwo: TRUE, lg: lg]; ENDLOOP; RETURN[lgArray]; }; nullBitBltTable: PrincOps.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [] ]; UnsafeGetF: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: BitsPerSample] ~ UNCHECKED { lgEntry: LgEntry ~ lgArray[bitsPerSample]; line: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE]; PrincOpsUtils.LongZero[where: samples, nwords: count]; IF lgEntry.powerOfTwo THEN { lgBitsPerItem: NAT ~ lgEntry.lg; bitsPerItem: NAT ~ Basics.BITSHIFT[1, lgBitsPerItem]; lgItemsPerWord: NAT ~ lgBitsPerWord-lgBitsPerItem; itemsPerWord: NAT ~ Basics.BITSHIFT[1, lgItemsPerWord]; bb.dst.bit _ bitsPerWord-bitsPerItem; bb.dstBpl _ Basics.BITSHIFT[bitsPerWord, lgItemsPerWord]; bb.srcDesc.srcBpl _ bitsPerWord; bb.width _ bitsPerItem; FOR k: NAT IN [0..MIN[itemsPerWord, count]) DO x: CARDINAL ~ f+k; bb.dst.word _ @samples[k]; bb.src.word _ line+Basics.BITSHIFT[x, -lgItemsPerWord]; bb.src.bit _ Basics.BITSHIFT[Basics.BITAND[x, itemsPerWord-1], lgBitsPerItem]; bb.height _ Basics.BITSHIFT[(count-k)+(itemsPerWord-1), -lgItemsPerWord]; <> <> <> PrincOpsUtils.BITBLT[bb]; ENDLOOP; } ELSE { bit: LONG CARDINAL ~ Basics.LongMult[f, bitsPerSample]; bb.dst.word _ samples; bb.dst.bit _ bitsPerWord-bitsPerSample; bb.dstBpl _ bitsPerWord; bb.src.word _ line+bit/bitsPerWord; bb.src.bit _ bit MOD bitsPerWord; bb.srcDesc.srcBpl _ bitsPerSample; bb.width _ bitsPerSample; bb.height _ count; PrincOpsUtils.BITBLT[bb]; }; }; <<>> UnsafePutF: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: BitsPerSample, srcFunc: PrincOps.SrcFunc _ null, dstFunc: PrincOps.DstFunc _ null] ~ UNCHECKED { lgEntry: LgEntry ~ lgArray[bitsPerSample]; line: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE, srcFunc: srcFunc, dstFunc: dstFunc]; IF lgEntry.powerOfTwo THEN { lgBitsPerItem: NAT ~ lgEntry.lg; bitsPerItem: NAT ~ Basics.BITSHIFT[1, lgBitsPerItem]; lgItemsPerWord: NAT ~ lgBitsPerWord-lgBitsPerItem; itemsPerWord: NAT ~ Basics.BITSHIFT[1, lgItemsPerWord]; bb.src.bit _ bitsPerWord-bitsPerItem; bb.srcDesc.srcBpl _ Basics.BITSHIFT[bitsPerWord, lgItemsPerWord]; bb.dstBpl _ bitsPerWord; bb.width _ bitsPerItem; FOR k: NAT IN [0..MIN[itemsPerWord, count]) DO x: CARDINAL ~ f+k; bb.src.word _ @samples[k]; bb.dst.word _ line+Basics.BITSHIFT[x, -lgItemsPerWord]; bb.dst.bit _ Basics.BITSHIFT[Basics.BITAND[x, itemsPerWord-1], lgBitsPerItem]; bb.height _ Basics.BITSHIFT[(count-k)+(itemsPerWord-1), -lgItemsPerWord]; <> <> <> PrincOpsUtils.BITBLT[bb]; ENDLOOP; } ELSE { bit: LONG CARDINAL ~ Basics.LongMult[f, bitsPerSample]; bb.src.word _ samples; bb.src.bit _ bitsPerWord-bitsPerSample; bb.srcDesc.srcBpl _ bitsPerWord; bb.dst.word _ line+bit/bitsPerWord; bb.dst.bit _ bit MOD bitsPerWord; bb.dstBpl _ bitsPerSample; bb.width _ bitsPerSample; bb.height _ count; PrincOpsUtils.BITBLT[bb]; }; }; UnsafePutFSign: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT] ~ UNCHECKED { line: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE]; bb.srcDesc.srcBpl _ bitsPerWord*bitsPerWord; bb.dstBpl _ bitsPerWord; bb.width _ 1; FOR k: NAT IN [0..MIN[bitsPerWord, count]) DO x: CARDINAL ~ f+k; bb.src.word _ @samples[k]; bb.dst.word _ line+x/bitsPerWord; bb.dst.bit _ x MOD bitsPerWord; bb.height _ (CARDINAL[count-k]+bitsPerWord-1)/bitsPerWord; PrincOpsUtils.BITBLT[bb]; ENDLOOP; }; UnsafeGetS: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: BitsPerSample] ~ UNCHECKED { lgEntry: LgEntry ~ lgArray[bitsPerSample]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE]; PrincOpsUtils.LongZero[where: samples, nwords: count]; bb.dst.word _ samples; bb.dst.bit _ bitsPerWord-bitsPerSample; bb.dstBpl _ bitsPerWord; bb.srcDesc.srcBpl _ wordsPerLine*bitsPerWord; bb.width _ bitsPerSample; bb.height _ count; IF lgEntry.powerOfTwo THEN { lgBitsPerItem: NAT ~ lgEntry.lg; lgItemsPerWord: NAT ~ lgBitsPerWord-lgBitsPerItem; itemsPerWord: NAT ~ Basics.BITSHIFT[1, lgItemsPerWord]; bb.src.word _ base+Basics.LongMult[s, wordsPerLine]+Basics.BITSHIFT[f, -lgItemsPerWord]; bb.src.bit _ Basics.BITSHIFT[Basics.BITAND[f, itemsPerWord-1], lgBitsPerItem]; <> <> PrincOpsUtils.BITBLT[bb]; } ELSE { x: LONG CARDINAL ~ Basics.LongMult[bitsPerSample, f]; bb.src.word _ base+Basics.LongMult[wordsPerLine, s]+x/bitsPerWord; bb.src.bit _ x MOD bitsPerWord; PrincOpsUtils.BITBLT[bb]; }; }; UnsafePutS: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: BitsPerSample, srcFunc: PrincOps.SrcFunc _ null, dstFunc: PrincOps.DstFunc _ null] ~ UNCHECKED { lgEntry: LgEntry ~ lgArray[bitsPerSample]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE, srcFunc: srcFunc, dstFunc: dstFunc]; bb.dstBpl _ wordsPerLine*bitsPerWord; bb.src.word _ samples; bb.src.bit _ bitsPerWord-bitsPerSample; bb.srcDesc.srcBpl _ bitsPerWord; bb.width _ bitsPerSample; bb.height _ count; IF lgEntry.powerOfTwo THEN { lgBitsPerItem: NAT ~ lgEntry.lg; lgItemsPerWord: NAT ~ lgBitsPerWord-lgBitsPerItem; itemsPerWord: NAT ~ Basics.BITSHIFT[1, lgItemsPerWord]; bb.dst.word _ base+Basics.LongMult[s, wordsPerLine]+Basics.BITSHIFT[f, -lgItemsPerWord]; bb.dst.bit _ Basics.BITSHIFT[Basics.BITAND[f, itemsPerWord-1], lgBitsPerItem]; <> <> PrincOpsUtils.BITBLT[bb]; } ELSE { x: LONG CARDINAL ~ Basics.LongMult[bitsPerSample, f]; bb.dst.word _ base+Basics.LongMult[wordsPerLine, s]+x/bitsPerWord; bb.dst.bit _ x MOD bitsPerWord; PrincOpsUtils.BITBLT[bb]; }; }; realLastInt: REAL _ REAL[LAST[INT]]; Floor: PROC[a: REAL] RETURNS[c: REAL] ~ { IF ABS[a] >= realLastInt THEN RETURN [a]; c _ REAL[Real.Fix[a]]; IF c>a THEN RETURN[c-1] ELSE RETURN[c] }; ScaledFromRealMod: PROC [d: REAL, m: CARDINAL] RETURNS [INT] ~ { s: Basics.LongNumber _ [li[0]]; IF m # 0 THEN { modulus: REAL ~ m; residue: REAL _ IF d IN [0..modulus) THEN d ELSE (d-modulus*Floor[d/modulus]); s.li _ Real.Round[Real.FScale[residue, Basics.bitsPerWord]]; <> IF s.li < 0 THEN {s.hi _ s.hi + m}; IF s.hi >= m THEN {s.hi _ s.hi - m}; IF s.hi >= m THEN ERROR; }; RETURN [s.li]; }; SetSamplerIncrements: PUBLIC PROC [sampler: Sampler, m: Transformation] ~ { sSize: NAT ~ sampler.sSize; fSize: NAT ~ sampler.fSize; s, f: REAL _ 0.0; [[s, f]] _ m.InverseTransformVec[[0, 1] ! Real.RealException => CONTINUE]; <> sampler.sfDelta.li _ ScaledFromRealMod[s, sSize]; sampler.ffDelta.li _ ScaledFromRealMod[f, fSize]; s _ f _ 0.0; [[s, f]] _ m.InverseTransformVec[[1, 0] ! Real.RealException => CONTINUE]; sampler.ssDelta.li _ ScaledFromRealMod[s, sSize]; sampler.fsDelta.li _ ScaledFromRealMod[f, fSize]; }; SetSamplerPosition: PUBLIC PROC [sampler: Sampler, m: Transformation, s, f: CARDINAL] ~ { sSource, fSource: REAL _ 0.0; sSize: NAT ~ sampler.sSize; fSize: NAT ~ sampler.fSize; [[sSource, fSource]] _ m.InverseTransform[[s+0.5, f+0.5] ! Real.RealException => CONTINUE]; sampler.sSource.li _ ScaledFromRealMod[sSource, sSize]; sampler.fSource.li _ ScaledFromRealMod[fSource, fSize]; sampler.sDest _ s; sampler.fDest _ f; }; Sample0: TYPE ~ CARDINAL[0..000001B]; -- 1 bit Sample1: TYPE ~ CARDINAL[0..000003B]; -- 2 bits Sample2: TYPE ~ CARDINAL[0..000017B]; -- 4 bits Sample3: TYPE ~ CARDINAL[0..000377B]; -- 8 bits Sample4: TYPE ~ CARDINAL[0..177777B]; -- 16 bits Sequence0: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample0]; Sequence1: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample1]; Sequence2: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample2]; Sequence3: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample3]; Sequence4: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample4]; Pointer0: TYPE ~ LONG POINTER TO Sequence0; Pointer1: TYPE ~ LONG POINTER TO Sequence1; Pointer2: TYPE ~ LONG POINTER TO Sequence2; Pointer3: TYPE ~ LONG POINTER TO Sequence3; Pointer4: TYPE ~ LONG POINTER TO Sequence4; GetPointSamples: PUBLIC PROC [sampler: Sampler, s, f: CARDINAL, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ TRUSTED { lgEntry: LgEntry ~ lgArray[sampler.bitsPerSample]; samples: UnsafeSamples ~ buffer.GetPointer[bi, bj, count]; base: LONG POINTER ~ sampler.base; wordsPerLine: CARDINAL ~ sampler.wordsPerLine; line: LONG POINTER _ base; sLine: CARDINAL _ 0; sSize: CARDINAL ~ sampler.sSize; fSize: CARDINAL ~ sampler.fSize; sMin: CARDINAL ~ sampler.sMin; fMin: CARDINAL ~ sampler.fMin; sMax: CARDINAL ~ sMin+sSize; fMax: CARDINAL ~ fMin+fSize; ssDelta: Basics.LongNumber ~ sampler.ssDelta; fsDelta: Basics.LongNumber ~ sampler.fsDelta; sfDelta: Basics.LongNumber ~ sampler.sfDelta; ffDelta: Basics.LongNumber ~ sampler.ffDelta; sSource: Basics.LongNumber _ sampler.sSource; fSource: Basics.LongNumber _ sampler.fSource; sDest: CARDINAL _ sampler.sDest; fDest: CARDINAL _ sampler.fDest; Process.CheckForAbort[]; WHILE sDest FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer0][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer1][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer2][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer3][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer4][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi ERROR ELSE ERROR; }; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<}>> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <<};>> <> <> <<};>> <> <> <<};>> <> <> <> <> <> <> <