! Three-bit packed unsigned integers. ! Constant TEST_THREE; ! Returns the number of bytes needed to store count unsigned ! integers packed in three bits. [ ThreeNeed count three c8 r8; if (~~three) three = 3; c8 = count/8; r8 = count%8; ! (count*three+7)/8 == ! ((c8*8+r8)*three+7)/8 == ! c8*three + (r8*three+7)/8 return (r8*three+7)/8 + c8*three; ]; [ ThreeGet table ix three bytepos data cnt mask i8 r8; if (~~three) three = 3; i8 = ix/8; r8 = ix%8; ! (ix*three)/8 == (i8*8+r8)*three/8 == i8*three+r8*three/8 bytepos = i8*three + r8*three/8; ! (ix*three)%8 == (i8*8+r8)*three%8 == r8*three%8 ix = r8*three%8; data = 255 & (table->bytepos); if (8 < ix+three) data = data + (255 & table->(bytepos+1)) * 256; if (ix && data < 0) { data = data & $7FFF; } for (cnt = 0: cnt < ix: cnt++) data = data / 2; mask = -1; for (cnt = 0: cnt < three: cnt++) mask = mask * 2; return data & ~mask; ]; [ ThreePut table ix data three bytepos mask cnt orig i8 r8; if (~~three) three = 3; i8 = ix/8; r8 = ix%8; ! (ix*three)/8 == (i8*8+r8)*three/8 == i8*three+r8*three/8 bytepos = i8*three + r8*three/8; ! (ix*three)%8 == (i8*8+r8)*three%8 == r8*three%8 ix = r8*three%8; mask = -1; for (cnt = 0: cnt < three: cnt++) mask = mask + mask; for (cnt = 0: cnt < ix: cnt++) { mask = (mask + mask) | 1; data = data + data; } orig = 255 & (table->bytepos); if (8 < ix+three) orig = orig | ((255 & table->(bytepos+1)) * 256); data = (orig & mask) | data; table->bytepos = (data & 255); if (8 < ix+three) { ! ((data & $FF00) / 256) is to right shift 8 bits. ! simple (data/256) did not work correctly e.g. data = $8088. table->(bytepos+1) = ((data&$FF00)/256) & 255; } ]; #IFDEF TEST_THREE; Constant testsize $7FFF; Constant testarraysize (testsize/8*3+(testsize%8*3+7)/8); Array testthree -> testarraysize; Array tt -> testarraysize; [ Main i j k l bad q; @output_stream 2; print "Testsize is ", testsize, ", testarraysize is ", testarraysize; print ", threeneed is ", ThreeNeed(testsize), "^"; bad = k = 0; for (i = 0: i < 3: i++) { k = i; for (q = 0: q < testarraysize: q++) tt->q = testthree->q; k = (k + 1) % 3; for (j = 0: j < testsize: j++) { ThreePut(testthree, j, k); l = ThreeGet(testthree, j); if (l ~= k) { print "Putting ", k, " at ", j, " produced ", l, "^"; for (q = 0: q < testarraysize: q++) print " ", tt->q; new_line; for (q = 0: q < testarraysize: q++) print " ", testthree->q; new_line; bad++; } } } print "Bad:", bad, "^^"; ]; #ENDIF;