A BRIEF DESCRIPTION OF THE BUG AND MY FIX: The C function for converting a bitstring to an integer (P_Bitstring_To_Int) sometimes incorrectly tries to convert a bitstring into a fixnum when the bitstring will not fit (and should be converted into a bignum). My patch corrects this behavior. Here is the patch. It should be applied from within the elk-3.0 directory: -- CUT HERE -- *** lib/misc/bitstring.c.orig Tue Jun 3 21:20:12 1997 --- lib/misc/bitstring.c Tue Jun 3 21:20:21 1997 *************** *** 205,216 **** Check_Type(bs, T_Bitstring); b = BITSTRING(bs); ! ! for (i = bits_to_bytes(b->len) - 1; i >= 0; i--) { ! u = u << 8 | b->data[i]; ! if (!UFIXNUM_FITS(u)) ! return Bitstring_To_Bignum(bs); } return Make_Integer(u); } --- 205,229 ---- Check_Type(bs, T_Bitstring); b = BITSTRING(bs); ! ! /* If there are any 1 bits above the position which fits in an ! * integer, use a bignum */ ! ! if (b->len >= FIXBITS) ! { ! if (b->data[sizeof(int) - 1] & (1 << 7)) ! return Bitstring_To_Bignum(bs); ! ! for (i = sizeof(int); i < bits_to_bytes(b->len); i++) ! if (b->data[i] != 0) ! return Bitstring_To_Bignum(bs); } + + /* Otherwise, use an integer */ + + for (i = bits_to_bytes(b->len) - 1; i >= 0; i--) + u = u << 8 | b->data[i]; + return Make_Integer(u); } -- CUT HERE -- A DETAILED DESCRIPTION OF THE BUG AND MY FIX, WITH TEST CODE: The logic which tests when to unpack a bitstring into a fixnum and when to pack it into a bignum incorrectly uses the macro UFIXNUM_FITS to test the number as it is being unpacked. Since UFIXNUM_FITS simply tests the high bit of an integer, the function will fail to use bignums on many bitstrings which do not fit into a fixnum. The only bitstrings which it will correctly unpack into a bignum are those with a 1 in the high bit of one of its bytes past the integer boundary. The resulting behavior is erratic. Here is a short test routine to demonstrate the problem. It generates bitstrings of lengths 1 to 99 bits with a 1 in their high bit and zeros in all other bits. It then converts each of these back to an integer and prints the result. Note that after the bitstring passes 31 bits in length (the size of a fixnum on my SGI), only every eighth conversion works properly. > (let ((i 1)) (while (< i 100) (display (bitstring->unsigned-integer (unsigned-integer->bitstring i (expt 2 (- i 1))))) (display "\n") (set! i (+ i 1)))) 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 1073741824 2147483648 0 0 0 0 0 0 0 549755813888 0 0 0 0 0 0 0 140737488355328 0 0 0 0 0 0 0 36028797018963968 0 0 0 0 0 0 0 9223372036854775808 0 0 0 0 0 0 0 2361183241434822606848 0 0 0 0 0 0 0 604462909807314587353088 0 0 0 0 0 0 0 154742504910672534362390528 0 0 0 0 0 0 0 39614081257132168796771975168 0 0 0 #f -- My patch to bitstring.c correctly decides when to use a fixnum and when to use a bignum. If the length of the bitstring is greater than that which will fit in a fixnum, then it looks at the portion of the bitstring above the fixnum. If any of those bits are 1, then it unpacks the bitstring into a bignum. Otherwise (if all those bits are 0 or if the length of the bitstring is less than that of a fixnum) it unpacks into a fixnum. Note that this will often lead to long bitstrings with small negative numbers being unpacked into bignums temporarily (until the scheme code for bitstring->signed-integer does its magic to convert it to a negative number). This is the same thing that happened with the unpatched code. Here is the output of the test function with my patch in place: > (let ((i 1)) (while (< i 100) (display (bitstring->unsigned-integer (unsigned-integer->bitstring i (expt 2 (- i 1))))) (display "\n") (set! i (+ i 1)))) 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 1073741824 2147483648 4294967296 8589934592 17179869184 34359738368 68719476736 137438953472 274877906944 549755813888 1099511627776 2199023255552 4398046511104 8796093022208 17592186044416 35184372088832 70368744177664 140737488355328 281474976710656 562949953421312 1125899906842624 2251799813685248 4503599627370496 9007199254740992 18014398509481984 36028797018963968 72057594037927936 144115188075855872 288230376151711744 576460752303423488 1152921504606846976 2305843009213693952 4611686018427387904 9223372036854775808 18446744073709551616 36893488147419103232 73786976294838206464 147573952589676412928 295147905179352825856 590295810358705651712 1180591620717411303424 2361183241434822606848 4722366482869645213696 9444732965739290427392 18889465931478580854784 37778931862957161709568 75557863725914323419136 151115727451828646838272 302231454903657293676544 604462909807314587353088 1208925819614629174706176 2417851639229258349412352 4835703278458516698824704 9671406556917033397649408 19342813113834066795298816 38685626227668133590597632 77371252455336267181195264 154742504910672534362390528 309485009821345068724781056 618970019642690137449562112 1237940039285380274899124224 2475880078570760549798248448 4951760157141521099596496896 9903520314283042199192993792 19807040628566084398385987584 39614081257132168796771975168 79228162514264337593543950336 158456325028528675187087900672 316912650057057350374175801344 #f