ruby-changes:29492
From: akr <ko1@a...>
Date: Sat, 22 Jun 2013 02:22:25 +0900 (JST)
Subject: [ruby-changes:29492] akr:r41544 (trunk): * bignum.c (bary_pack): Specialized packers implemented.
akr 2013-06-22 02:22:14 +0900 (Sat, 22 Jun 2013) New Revision: 41544 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=41544 Log: * bignum.c (bary_pack): Specialized packers implemented. (HOST_BIGENDIAN_P): New macro. (ALIGNOF): New macro. (CLEAR_LOWBITS): New macro. (FILL_LOWBITS): New macro. (swap_bdigit): New macro. (bary_2comp): Returns an int. * internal.h (swap16): Moved from pack.c (swap32): Ditto. (swap64): Ditto. Modified files: trunk/ChangeLog trunk/bignum.c trunk/internal.h trunk/pack.c trunk/test/-ext-/bignum/test_pack.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 41543) +++ ChangeLog (revision 41544) @@ -1,3 +1,17 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sat Jun 22 02:18:07 2013 Tanaka Akira <akr@f...> + + * bignum.c (bary_pack): Specialized packers implemented. + (HOST_BIGENDIAN_P): New macro. + (ALIGNOF): New macro. + (CLEAR_LOWBITS): New macro. + (FILL_LOWBITS): New macro. + (swap_bdigit): New macro. + (bary_2comp): Returns an int. + + * internal.h (swap16): Moved from pack.c + (swap32): Ditto. + (swap64): Ditto. + Fri Jun 21 21:29:49 2013 Masaya Tarui <tarui@r...> * gc.c (typedef enum): Introduce flags of major gc reason. Index: pack.c =================================================================== --- pack.c (revision 41543) +++ pack.c (revision 41544) @@ -100,43 +100,6 @@ TOKEN_PASTE(swap,x)(xtype z) \ https://github.com/ruby/ruby/blob/trunk/pack.c#L100 return r; \ } -#ifndef swap32 -# if GCC_VERSION_SINCE(4,3,0) -# define swap32(x) __builtin_bswap32(x) -# endif -#endif - -#ifndef swap64 -# if GCC_VERSION_SINCE(4,3,0) -# define swap64(x) __builtin_bswap64(x) -# endif -#endif - -#ifndef swap16 -# define swap16(x) ((uint16_t)((((x)&0xFF)<<8) | (((x)>>8)&0xFF))) -#endif - -#ifndef swap32 -# define swap32(x) ((uint32_t)((((x)&0xFF)<<24) \ - |(((x)>>24)&0xFF) \ - |(((x)&0x0000FF00)<<8) \ - |(((x)&0x00FF0000)>>8) )) -#endif - -#ifndef swap64 -# ifdef HAVE_INT64_T -# define byte_in_64bit(n) ((uint64_t)0xff << (n)) -# define swap64(x) ((uint64_t)((((x)&byte_in_64bit(0))<<56) \ - |(((x)>>56)&0xFF) \ - |(((x)&byte_in_64bit(8))<<40) \ - |(((x)&byte_in_64bit(48))>>40) \ - |(((x)&byte_in_64bit(16))<<24) \ - |(((x)&byte_in_64bit(40))>>24) \ - |(((x)&byte_in_64bit(24))<<8) \ - |(((x)&byte_in_64bit(32))>>8))) -# endif -#endif - #if SIZEOF_SHORT == 2 # define swaps(x) swap16(x) #elif SIZEOF_SHORT == 4 Index: internal.h =================================================================== --- internal.h (revision 41543) +++ internal.h (revision 41544) @@ -73,6 +73,43 @@ extern "C" { https://github.com/ruby/ruby/blob/trunk/internal.h#L73 (INTEGER_PACK_MSWORD_FIRST | \ INTEGER_PACK_MSBYTE_FIRST) +#ifndef swap16 +# define swap16(x) ((uint16_t)((((x)&0xFF)<<8) | (((x)>>8)&0xFF))) +#endif + +#ifndef swap32 +# if GCC_VERSION_SINCE(4,3,0) +# define swap32(x) __builtin_bswap32(x) +# endif +#endif + +#ifndef swap32 +# define swap32(x) ((uint32_t)((((x)&0xFF)<<24) \ + |(((x)>>24)&0xFF) \ + |(((x)&0x0000FF00)<<8) \ + |(((x)&0x00FF0000)>>8) )) +#endif + +#ifndef swap64 +# if GCC_VERSION_SINCE(4,3,0) +# define swap64(x) __builtin_bswap64(x) +# endif +#endif + +#ifndef swap64 +# ifdef HAVE_INT64_T +# define byte_in_64bit(n) ((uint64_t)0xff << (n)) +# define swap64(x) ((uint64_t)((((x)&byte_in_64bit(0))<<56) \ + |(((x)>>56)&0xFF) \ + |(((x)&byte_in_64bit(8))<<40) \ + |(((x)&byte_in_64bit(48))>>40) \ + |(((x)&byte_in_64bit(16))<<24) \ + |(((x)&byte_in_64bit(40))>>24) \ + |(((x)&byte_in_64bit(24))<<8) \ + |(((x)&byte_in_64bit(32))>>8))) +# endif +#endif + struct rb_deprecated_classext_struct { char conflict[sizeof(VALUE) * 3]; }; Index: bignum.c =================================================================== --- bignum.c (revision 41543) +++ bignum.c (revision 41544) @@ -33,6 +33,15 @@ static VALUE big_three = Qnil; https://github.com/ruby/ruby/blob/trunk/bignum.c#L33 #define USHORT _USHORT #endif +#ifdef WORDS_BIGENDIAN +# define HOST_BIGENDIAN_P 1 +#else +# define HOST_BIGENDIAN_P 0 +#endif +#define ALIGNOF(type) ((int)offsetof(struct { char f1; type f2; }, f2)) +#define CLEAR_LOWBITS(d, numbits) (sizeof(d) * CHAR_BIT <= (numbits) ? 0 : ((d) >> (numbits)) << (numbits)) +#define FILL_LOWBITS(d, numbits) (sizeof(d) * CHAR_BIT <= (numbits) ? ~((d)*0) : (d) | ((((d)*0+1) << (numbits))-1)) + #define BDIGITS(x) (RBIGNUM_DIGITS(x)) #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT) #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG) @@ -48,6 +57,14 @@ static VALUE big_three = Qnil; https://github.com/ruby/ruby/blob/trunk/bignum.c#L57 #define BIGLO(x) ((BDIGIT)((x) & BDIGMAX)) #define BDIGMAX ((BDIGIT)(BIGRAD-1)) +#if SIZEOF_BDIGITS == 2 +# define swap_bdigit(x) swap16(x) +#elif SIZEOF_BDIGITS == 4 +# define swap_bdigit(x) swap32(x) +#elif SIZEOF_BDIGITS == 8 +# define swap_bdigit(x) swap64(x) +#endif + #define BIGZEROP(x) (RBIGNUM_LEN(x) == 0 || \ (BDIGITS(x)[0] == 0 && \ (RBIGNUM_LEN(x) == 1 || bigzero_p(x)))) @@ -76,7 +93,7 @@ static void bary_sub(BDIGIT *zds, size_t https://github.com/ruby/ruby/blob/trunk/bignum.c#L93 static void bary_divmod(BDIGIT *qds, size_t nq, BDIGIT *rds, size_t nr, BDIGIT *xds, size_t nx, BDIGIT *yds, size_t ny); static void bary_add(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn, BDIGIT *yds, size_t yn); static int bary_pack(int sign, BDIGIT *ds, size_t num_bdigits, void *words, size_t numwords, size_t wordsize, size_t nails, int flags); -static BDIGIT bary_2comp(BDIGIT *ds, size_t n); +static int bary_2comp(BDIGIT *ds, size_t n); #define BIGNUM_DEBUG 0 #if BIGNUM_DEBUG @@ -231,7 +248,7 @@ rb_big_clone(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L248 return z; } -static BDIGIT +static int bary_2comp(BDIGIT *ds, size_t n) { size_t i = n; @@ -244,7 +261,7 @@ bary_2comp(BDIGIT *ds, size_t n) https://github.com/ruby/ruby/blob/trunk/bignum.c#L261 ds[i++] = BIGLO(num); num = BIGDN(num); } while (i < n); - return (BDIGIT)num; + return num != 0; } /* modify a bignum by 2's complement */ @@ -901,6 +918,170 @@ bary_pack(int sign, BDIGIT *ds, size_t n https://github.com/ruby/ruby/blob/trunk/bignum.c#L918 sign = 0; } + if (nails == 0 && sign == 0) { + MEMZERO(words, unsigned char, numwords * wordsize); + return 0; + } + if (nails == 0 && numwords == 1) { + int need_swap = wordsize != 1 && + (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_NATIVE_BYTE_ORDER && + ((flags & INTEGER_PACK_MSBYTE_FIRST) ? !HOST_BIGENDIAN_P : HOST_BIGENDIAN_P); + if (0 < sign || !(flags & INTEGER_PACK_2COMP)) { + BDIGIT d; + if (wordsize == 1) { + *((unsigned char *)words) = (unsigned char)(d = dp[0]); + return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign; + } +#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGITS + if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) { + uint16_t u = (uint16_t)(d = dp[0]); + if (need_swap) u = swap16(u); + *((uint16_t *)words) = u; + return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign; + } +#endif +#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGITS + if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) { + uint32_t u = (uint32_t)(d = dp[0]); + if (need_swap) u = swap32(u); + *((uint32_t *)words) = u; + return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign; + } +#endif +#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGITS + if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) { + uint64_t u = (uint64_t)(d = dp[0]); + if (need_swap) u = swap64(u); + *((uint64_t *)words) = u; + return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign; + } +#endif + } + else { /* sign < 0 && (flags & INTEGER_PACK_2COMP) */ + BDIGIT_DBL_SIGNED d; + if (wordsize == 1) { + *((unsigned char *)words) = (unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]); + return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1; + } +#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGITS + if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) { + uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]); + if (need_swap) u = swap16(u); + *((uint16_t *)words) = u; + return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 : + (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1; + } +#endif +#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGITS + if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) { + uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]); + if (need_swap) u = swap32(u); + *((uint32_t *)words) = u; + return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 : + (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1; + } +#endif +#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGITS + if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) { + uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]); + if (need_swap) u = swap64(u); + *((uint64_t *)words) = u; + return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 : + (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1; + } +#endif + } + } +#if !defined(WORDS_BIGENDIAN) + if (nails == 0 && SIZEOF_BDIGITS == sizeof(BDIGIT) && + (flags & INTEGER_PACK_WORDORDER_MASK) == INTEGER_PACK_LSWORD_FIRST && + (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_MSBYTE_FIRST) { + size_t src_size = num_bdigits * SIZEOF_BDIGITS; + size_t dst_size = numwords * wordsize; + int overflow = 0; + while (0 < src_size && ((unsigned char *)ds)[src_size-1] == 0) + src_size--; + if (src_size <= dst_size) { + MEMCPY(words, dp, char, src_size); + MEMZERO((char*)words + src_size, char, dst_size - src_size); + } + else { + MEMCPY(words, dp, char, dst_size); + overflow = 1; + } + if (sign < 0 && (flags & INTEGER_PACK_2COMP)) { + unsigned char *p = words, *e = (unsigned char *)words + dst_size; + while (p < e && *p == 0) + p++; + if (p < e) { + *p = 1 + (unsigned char)~*p; + p++; + while (p < e) { + *p = (unsigned char)~*p; + p++; + } + } + else if (overflow) { + p = (unsigned char *)dp + dst_size; + e = (unsigned char *)dp + src_size; + if (p < e && *p++ == 1) { + while (p < e && *p == 0) + p++; + if (p == e) + overflow = 0; + } + } + } + if (overflow) + sign *= 2; + return sign; + } +#endif + if (nails == 0 && SIZEOF_BDIGITS == sizeof(BDIGIT) && + wordsize % SIZEOF_BDIGITS == 0 && (uintptr_t)words % ALIGNOF(BDIGIT) == 0) { + size_t buf_num_bdigits = numwords * wordsize / SIZEOF_BDIGITS; + int need_swap = + (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_NATIVE_BYTE_ORDER && + ((flags & INTEGER_PACK_MSBYTE_FIRST) ? !HOST_BIGENDIAN_P : HOST_BIGENDIAN_P); + size_t i; + int overflow = 0; + if (num_bdigits <= buf_num_bdigits) { + MEMCPY(words, dp, BDIGIT, num_bdigits); + MEMZERO((BDIGIT*)words + num_bdigits, BDIGIT, buf_num_bdigits - num_bdigits); + } + else { + MEMCPY(words, dp, BDIGIT, buf_num_bdigits); + overflow = 1; + } + if (sign < 0 && (flags & INTEGER_PACK_2COMP)) { + int zero_p = bary_2comp(words, buf_num_bdigits); + if (overflow && + buf_num_bdigits == num_bdigits-1 && + dp[buf_num_bdigits] == 1 && + zero_p) + overflow = 0; + } + if (need_swap) { + for (i = 0; i < buf_num_bdigits; i++) { + BDIGIT d = ((BDIGIT*)words)[i]; + ((BDIGIT*)words)[i] = swap_bdigit(d); + } + } + if (flags & INTEGER_PACK_MSWORD_FIRST) { + BDIGIT *p1 = words, *p2 = p1 + buf_num_bdigits - 1; + while (p1 < p2) { + BDIGIT tmp = *p1; + *p1 = *p2; + *p2 = tmp; + p1++; + p2--; + } + } + if (overflow) + sign *= 2; + return sign; + } + buf = words; bufend = buf + numwords * wordsize; Index: test/-ext-/bignum/test_pack.rb =================================================================== --- test/-ext-/bignum/test_pack.rb (revision 41543) +++ test/-ext-/bignum/test_pack.rb (revision 41544) @@ -69,6 +69,55 @@ class TestBignum < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/bignum/test_pack.rb#L69 assert_equal([1, "\x00\x12\x00\x34\x00\x56\x00\x78"], 0x12345678.test_pack(4, 2, 8, BIG_ENDIAN)) end + def test_pack_overflow + assert_equal([-2, "\x1"], (-0x11).test_pack(1, 1, 4, BIG_ENDIAN)) + assert_equal([-2, "\x0"], (-0x10).test_pack(1, 1, 4, BIG_ENDIAN)) + assert_equal([-1, "\xF"], (-0x0F).test_pack(1, 1, 4, BIG_ENDIAN)) + assert_equal([+1, "\xF"], (+0x0F).test_pack(1, 1, 4, BIG_ENDIAN)) + assert_equal([+2, "\x0"], (+0x10).test_pack(1, 1, 4, BIG_ENDIAN)) + assert_equal([+2, "\x1"], (+0x11).test_pack(1, 1, 4, BIG_ENDIAN)) + + assert_equal([-2, "\x01"], (-0x101).test_pack(1, 1, 0, BIG_ENDIAN)) + assert_equal([-2, "\x00"], (-0x100).test_pack(1, 1, 0, BIG_ENDIAN)) + assert_equal([-1, "\xFF"], (-0x0FF).test_pack(1, 1, 0, BIG_ENDIAN)) + assert_equal([+1, "\xFF"], (+0x0FF).test_pack(1, 1, 0, BIG_ENDIAN)) + assert_equal([+2, "\x00"], (+0x100).test_pack(1, 1, 0, BIG_ENDIAN)) + assert_equal([+2, "\x01"], (+0x101).test_pack(1, 1, 0, BIG_ENDIAN)) + + assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x01"], (-0x10000000000000001).test_pack(2, 4, 0, BIG_ENDIAN)) + assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x00"], (-0x10000000000000000).test_pack(2, 4, 0, BIG_ENDIAN)) + assert_equal([-1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], (-0x0FFFFFFFFFFFFFFFF).test_pack(2, 4, 0, BIG_ENDIAN)) + assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], (+0x0FFFFFFFFFFFFFFFF).test_pack(2, 4, 0, BIG_ENDIAN)) + assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], (+0x10000000000000000).test_pack(2, 4, 0, BIG_ENDIAN)) + assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], (+0x10000000000000001).test_pack(2, 4, 0, BIG_ENDIAN)) + + 1.upto(16) {|wordsize| + 1.upto(20) {|numwords| + w = numwords*wordsize + n = 256**w + assert_equal([-2, "\x00"*(w-1)+"\x01"], (-n-1).test_pack(numwords, wordsize, 0, BIG_ENDIAN)) + assert_equal([-2, "\x00"*w], (-n ).test_pack(numwords, wordsize, 0, BIG_ENDIAN)) + assert_equal([-1, "\xFF"*w], (-n+1).test_pack(numwords, wordsize, 0, BIG_ENDIAN)) + assert_equal([+1, "\xFF"*w], (+n-1).test_pack(numwords, wordsize, 0, BIG_ENDIAN)) + assert_equal([+2, "\x00"*w], (+n ).test_pack(numwords, wordsize, 0, BIG_ENDIAN)) + assert_equal([+2, "\x00"*(w-1)+"\x01"], (+n+1).test_pack(numwords, wordsize, 0, BIG_ENDIAN)) + } + } + + 1.upto(16) {|wordsize| + 1.upto(20) {|numwords| + w = numwords*wordsize + n = 256**w + assert_equal([-2, "\x01"+"\x00"*(w-1)], (-n-1).test_pack(numwords, wordsize, 0, LITTLE_ENDIAN)) + assert_equal([-2, "\x00"*w], (-n ).test_pack(numwords, wordsize, 0, LITTLE_ENDIAN)) + assert_equal([-1, "\xFF"*w], (-n+1).test_pack(numwords, wordsize, 0, LITTLE_ENDIAN)) + assert_equal([+1, "\xFF"*w], (+n-1).test_pack(numwords, wordsize, 0, LITTLE_ENDIAN)) + assert_equal([+2, "\x00"*w], (+n ).test_pack(numwords, wordsize, 0, LITTLE_ENDIAN)) + assert_equal([+2, "\x01"+"\x00"*(w-1)], (+n+1).test_pack(numwords, wordsize, 0, LITTLE_ENDIAN)) + } + } + end + def test_pack_sign assert_equal([-1, "\x01"], (-1).test_pack(1, 1, 0, BIG_ENDIAN)) assert_equal([-1, "\x80\x70\x60\x50\x40\x30\x20\x10"], (-0x8070605040302010).test_pack(8, 1, 0, BIG_ENDIAN)) @@ -116,6 +165,33 @@ class TestBignum < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/bignum/test_pack.rb#L165 assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], (+0x0FFFFFFFFFFFFFFFF).test_pack(2, 4, 0, TWOCOMP|BIG_ENDIAN)) assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], (+0x10000000000000000).test_pack(2, 4, 0, TWOCOMP|BIG_ENDIAN)) assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], (+0x10000000000000001).test_pack(2, 4, 0, TWOCOMP|BIG_ENDIAN)) + + 1.upto(16) {|wordsize| + 1.upto(20) {|numwords| + w = numwords*wordsize + n = 256**w + assert_equal([-2, "\xFF"*w ], (-n-1).test_pack(numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN)) + assert_equal([-1, "\x00"*w], (-n ).test_pack(numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN)) + assert_equal([-1, "\x00"*(w-1)+"\x01"], (-n+1).test_pack(numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN)) + assert_equal([+1, "\xFF"*w], (+n-1).test_pack(numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN)) + assert_equal([+2, "\x00"*w], (+n ).test_pack(numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN)) + assert_equal([+2, "\x00"*(w-1)+"\x01"], (+n+1).test_pack(numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN)) + } + } + + 1.upto(16) {|wordsize| + 1.upto(20) {|numwords| + w = numwords*wordsize + n = 256**w + assert_equal([-2, "\xFF"*w ], (-n-1).test_pack(numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN)) + assert_equal([-1, "\x00"*w], (-n ).test_pack(numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN)) + assert_equal([-1, "\x01"+"\x00"*(w-1)], (-n+1).test_pack(numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN)) + assert_equal([+1, "\xFF"*w], (+n-1).test_pack(numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN)) + assert_equal([+2, "\x00"*w], (+n ).test_pack(numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN)) + assert_equal([+2, "\x01"+"\x00"*(w-1)], (+n+1).test_pack(numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN)) + } + } + end def test_unpack_zero -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/