<<>> <> <> <> <<>> DIRECTORY Basics, RasterOp USING [BitAddress, BitsPerSample]; RasterOpGreenbayImpl: PROGRAM IMPORTS Basics EXPORTS RasterOp ~ BEGIN OPEN RasterOp, Basics; bpw: CARDINAL ~ BITS[WORD]; Pack: PUBLIC PROC [dst: BitAddress, src: LONG POINTER TO RawWords, bitsPerSample: BitsPerSample, nSamples: CARDINAL] ~ UNCHECKED { p: LONG POINTER TO ARRAY [0..0] OF WORD ¬ LOOPHOLE[dst.word]; h: WORD ¬ BITSHIFT[p[0], dst.bit-bpw]; g: [0..bpw] ¬ dst.bit; -- number of good bits at least-sig end of h j: CARDINAL ¬ 0; count: CARDINAL ¬ nSamples; bps: [0..bpw) ~ bitsPerSample; m: WORD ~ BITLSHIFT[1, bps]-1; bitsPerSample2: CARDINAL ~ bitsPerSample+bitsPerSample; bitsPerSample4: CARDINAL ~ bitsPerSample2+bitsPerSample2; bitsPerSample8: CARDINAL ~ bitsPerSample4+bitsPerSample4; Combine: PROC [w: WORD, s: WORD] RETURNS [WORD] ~ INLINE { RETURN [BITOR[BITLSHIFT[w, bps], BITAND[s, m]]] }; WHILE count >= 8 DO SELECT CARDINAL[bpw-g] FROM >= bitsPerSample8 => { h ¬ Combine[h, src[j]]; h ¬ Combine[h, src[j+1]]; h ¬ Combine[h, src[j+2]]; h ¬ Combine[h, src[j+3]]; h ¬ Combine[h, src[j+4]]; h ¬ Combine[h, src[j+5]]; h ¬ Combine[h, src[j+6]]; h ¬ Combine[h, src[j+7]]; count ¬ count - 8; j ¬ j + 8; g ¬ g + bitsPerSample8; }; >= bitsPerSample4 => { h ¬ Combine[h, src[j]]; h ¬ Combine[h, src[j+1]]; h ¬ Combine[h, src[j+2]]; h ¬ Combine[h, src[j+3]]; count ¬ count - 4; j ¬ j + 4; g ¬ g + bitsPerSample4; }; >= bitsPerSample2 => { h ¬ Combine[h, src[j]]; h ¬ Combine[h, src[j+1]]; count ¬ count - 2; j ¬ j + 2; g ¬ g + bitsPerSample2; }; >= bps => { h ¬ Combine[h, src[j]]; count ¬ count - 1; j ¬ j + 1; g ¬ g + bps; }; ENDCASE => EXIT; -- Need to span a word, so drop through to the slower case below IF g = bpw THEN { p[0] ¬ h; p ¬ p + SIZE[WORD]; g ¬ 0; }; ENDLOOP; UNTIL j = nSamples DO SELECT bpw-g FROM >= bps => { <> h ¬ Combine[h, src[j]]; g ¬ g + bps; }; = 0 => { <> p[0] ¬ h; p ¬ p + SIZE[WORD]; h ¬ src[j]; g ¬ bps; }; ENDCASE => { <> k: WORD ~ BITAND[src[j], m]; p[0] ¬ BITLSHIFT[h, bpw-g] + BITRSHIFT[k, bps+g-bpw]; p ¬ p + SIZE[WORD]; h ¬ k; g ¬ g + bps - bpw; }; j ¬ j + 1; ENDLOOP; IF g # 0 THEN { p[0] ¬ BITLSHIFT[h, bpw-g]+BITAND[p[0], BITLSHIFT[1, bpw-g]-1]; }; }; Unpack: PUBLIC PROC [dst: LONG POINTER TO RawWords, src: BitAddress, bitsPerSample: BitsPerSample, nSamples: CARDINAL] ~ UNCHECKED { SELECT TRUE FROM (nSamples = 0) => NULL; (bitsPerSample = 1) => { wordPointer: LONG POINTER TO WORD ¬ @(dst[0]); srcp: LONG POINTER TO WORD ¬ src.word; bit: CARDINAL ¬ src.bit; word: WORD ¬ 0; count: CARDINAL ¬ nSamples; IF bit#0 THEN { word ¬ BITLSHIFT[srcp­, bit]; srcp ¬ srcp + SIZE[WORD]; WHILE count#0 AND bit#bpw DO <> wordPointer­ ¬ BITRSHIFT[word, bpw-1]; count ¬ count-1; bit ¬ bit+1; word ¬ 2*word; wordPointer ¬ wordPointer + SIZE[WORD]; ENDLOOP; }; bit ¬ bpw; WHILE count>=32 DO a: LONG POINTER TO ARRAY [0..32) OF WORD ~ LOOPHOLE[wordPointer]; lp: LONG POINTER TO PACKED ARRAY [0..32) OF [0..1] ~ LOOPHOLE[srcp]; b: PACKED ARRAY [0..32) OF [0..1] ~ lp­; a[0] ¬ b[0]; a[1] ¬ b[1]; a[2] ¬ b[2]; a[3] ¬ b[3]; a[4] ¬ b[4]; a[5] ¬ b[5]; a[6] ¬ b[6]; a[7] ¬ b[7]; a[8] ¬ b[8]; a[9] ¬ b[9]; a[10] ¬ b[10]; a[11] ¬ b[11]; a[12] ¬ b[12]; a[13] ¬ b[13]; a[14] ¬ b[14]; a[15] ¬ b[15]; a[16] ¬ b[16]; a[17] ¬ b[17]; a[18] ¬ b[18]; a[19] ¬ b[19]; a[20] ¬ b[20]; a[21] ¬ b[21]; a[22] ¬ b[22]; a[23] ¬ b[23]; a[24] ¬ b[24]; a[25] ¬ b[25]; a[26] ¬ b[26]; a[27] ¬ b[27]; a[28] ¬ b[28]; a[29] ¬ b[29]; a[30] ¬ b[30]; a[31] ¬ b[31]; wordPointer ¬ wordPointer + SIZE[ARRAY [0..32) OF WORD]; count ¬ count - 32; srcp ¬ srcp + SIZE[PACKED ARRAY [0..32) OF [0..1]]; ENDLOOP; WHILE count#0 DO <> IF bit = bpw THEN {bit ¬ 0; word ¬ srcp­; srcp ¬ srcp + SIZE[WORD]}; <> wordPointer­ ¬ BITRSHIFT[word, bpw-1]; count ¬ count-1; word ¬ 2*word; wordPointer ¬ wordPointer + SIZE[WORD]; bit ¬ bit+1; ENDLOOP; }; ((bitsPerSample = 8) AND ((src.bit MOD 8) = 0)) => { wordPointer: LONG POINTER TO WORD ¬ @(dst[0]); chunksize: CARDINAL ~ 8; -- to change this, also change assignments in the unrolled loop below. Must be a multiple of BYTES[WORD]. srcp: LONG POINTER TO PACKED ARRAY [0..chunksize) OF BYTE ¬ LOOPHOLE[src.word]; byte: CARDINAL ¬ src.bit/8; count: CARDINAL ¬ nSamples; IF byte#0 THEN { WHILE count#0 AND byte#chunksize DO wordPointer­ ¬ srcp[byte]; wordPointer ¬ wordPointer + SIZE[WORD]; byte ¬ byte + 1; count ¬ count-1; ENDLOOP; srcp ¬ srcp + SIZE[PACKED ARRAY [0..chunksize) OF BYTE]; byte ¬ 0; }; WHILE count>=chunksize DO a: LONG POINTER TO ARRAY [0..chunksize) OF WORD ~ LOOPHOLE[wordPointer]; b: PACKED ARRAY [0..chunksize) OF BYTE ~ srcp­; a[0] ¬ b[0]; a[1] ¬ b[1]; a[2] ¬ b[2]; a[3] ¬ b[3]; a[4] ¬ b[4]; a[5] ¬ b[5]; a[6] ¬ b[6]; a[7] ¬ b[7]; wordPointer ¬ wordPointer + SIZE[ARRAY [0..chunksize) OF WORD]; count ¬ count - chunksize; srcp ¬ srcp + SIZE[PACKED ARRAY [0..chunksize) OF BYTE]; ENDLOOP; WHILE count#0 DO wordPointer­ ¬ srcp[byte]; wordPointer ¬ wordPointer + SIZE[WORD]; byte ¬ byte + 1; count ¬ count-1; ENDLOOP; }; ENDCASE => { m: WORD ~ BITLSHIFT[1, bitsPerSample]-1; p: LONG POINTER TO ARRAY [0..1] OF WORD ¬ LOOPHOLE[src.word]; h: WORD ¬ p[0]; g: INTEGER ¬ bpw-src.bit; -- number of good bits at least-sig end of h FOR j: CARDINAL IN [0..nSamples) DO SELECT g FROM >= bitsPerSample => { <> dst[j] ¬ BITAND[m, BITRSHIFT[h, g-bitsPerSample]]; g ¬ g - bitsPerSample; }; 0 => { <> p ¬ p + SIZE[WORD]; h ¬ p[0]; dst[j] ¬ BITAND[m, BITRSHIFT[h, bpw-bitsPerSample]]; g ¬ bpw - bitsPerSample; }; ENDCASE => { <> k: WORD ~ p[1]; dst[j] ¬ BITAND[m, BITOR[BITLSHIFT[h, bitsPerSample-g], BITRSHIFT[k, g+bpw-bitsPerSample]]]; h ¬ k; p ¬ p + SIZE[WORD]; g ¬ g + bpw - bitsPerSample; }; ENDLOOP; }; }; END.