ruby-changes:30156
From: akr <ko1@a...>
Date: Sun, 28 Jul 2013 11:15:42 +0900 (JST)
Subject: [ruby-changes:30156] akr:r42208 (trunk): * include/ruby/intern.h (rb_absint_size): Declaration moved from
akr 2013-07-28 11:14:58 +0900 (Sun, 28 Jul 2013) New Revision: 42208 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42208 Log: * include/ruby/intern.h (rb_absint_size): Declaration moved from internal.h to calculate required buffer size to pack integers. (rb_absint_numwords): Ditto. (rb_absint_singlebit_p): Ditto. [ruby-core:42813] [Feature #6065] Modified files: trunk/ChangeLog trunk/bignum.c trunk/ext/-test-/bignum/intpack.c trunk/include/ruby/intern.h trunk/internal.h trunk/test/-ext-/bignum/test_pack.rb Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 42207) +++ include/ruby/intern.h (revision 42208) @@ -157,6 +157,9 @@ VALUE rb_big_rshift(VALUE, VALUE); https://github.com/ruby/ruby/blob/trunk/include/ruby/intern.h#L157 INTEGER_PACK_MSBYTE_FIRST) int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags); VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags); +size_t rb_absint_size(VALUE val, int *nlz_bits_ret); +size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret); +int rb_absint_singlebit_p(VALUE val); /* rational.c */ VALUE rb_rational_raw(VALUE, VALUE); Index: ChangeLog =================================================================== --- ChangeLog (revision 42207) +++ ChangeLog (revision 42208) @@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun Jul 28 11:12:07 2013 Tanaka Akira <akr@f...> + + * include/ruby/intern.h (rb_absint_size): Declaration moved from + internal.h to calculate required buffer size to pack integers. + (rb_absint_numwords): Ditto. + (rb_absint_singlebit_p): Ditto. + [ruby-core:42813] [Feature #6065] + Sun Jul 28 10:54:26 2013 Nobuyoshi Nakada <nobu@r...> * win32/win32.c (rb_w32_pipe): fix pipe name formatting. as "%x" may Index: ext/-test-/bignum/intpack.c =================================================================== --- ext/-test-/bignum/intpack.c (revision 42207) +++ ext/-test-/bignum/intpack.c (revision 42208) @@ -45,6 +45,26 @@ rb_integer_unpack_m(VALUE klass, VALUE b https://github.com/ruby/ruby/blob/trunk/ext/-test-/bignum/intpack.c#L45 NUM2SIZET(nails), NUM2INT(flags)); } +static VALUE +rb_integer_test_numbits_2comp_without_sign(VALUE val) +{ + size_t size; + int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : RBIGNUM_NEGATIVE_P(val); + size = rb_absint_numwords(val, 1, NULL) - (neg && rb_absint_singlebit_p(val)); + return SIZET2NUM(size); +} + +static VALUE +rb_integer_test_numbytes_2comp_with_sign(VALUE val) +{ + int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : RBIGNUM_NEGATIVE_P(val); + int nlz_bits; + size_t size = rb_absint_size(val, &nlz_bits); + if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val))) + size++; + return SIZET2NUM(size); +} + void Init_intpack(VALUE klass) { @@ -62,4 +82,7 @@ Init_intpack(VALUE klass) https://github.com/ruby/ruby/blob/trunk/ext/-test-/bignum/intpack.c#L82 rb_define_const(rb_cInteger, "INTEGER_PACK_FORCE_BIGNUM", INT2NUM(INTEGER_PACK_FORCE_BIGNUM)); rb_define_const(rb_cInteger, "INTEGER_PACK_NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE)); rb_define_const(rb_cInteger, "INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION", INT2NUM(INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)); + + rb_define_method(rb_cInteger, "test_numbits_2comp_without_sign", rb_integer_test_numbits_2comp_without_sign, 0); + rb_define_method(rb_cInteger, "test_numbytes_2comp_with_sign", rb_integer_test_numbytes_2comp_with_sign, 0); } Index: internal.h =================================================================== --- internal.h (revision 42207) +++ internal.h (revision 42208) @@ -141,9 +141,6 @@ VALUE rb_big_fdiv(VALUE x, VALUE y); https://github.com/ruby/ruby/blob/trunk/internal.h#L141 VALUE rb_big_uminus(VALUE x); VALUE rb_integer_float_cmp(VALUE x, VALUE y); VALUE rb_integer_float_eq(VALUE x, VALUE y); -size_t rb_absint_size(VALUE val, int *nlz_bits_ret); -size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret); -int rb_absint_singlebit_p(VALUE val); /* class.c */ VALUE rb_obj_methods(int argc, VALUE *argv, VALUE obj); Index: bignum.c =================================================================== --- bignum.c (revision 42207) +++ bignum.c (revision 42208) @@ -3275,6 +3275,34 @@ rb_absint_numwords(VALUE val, size_t wor https://github.com/ruby/ruby/blob/trunk/bignum.c#L3275 return numwords; } +/* Test abs(val) consists only a bit or not. + * + * Returns 1 if abs(val) == 1 << n for some n >= 0. + * Returns 0 otherwise. + * + * rb_absint_singlebit_p can be used to determine required buffer size + * for rb_integer_pack used with INTEGER_PACK_2COMP (two's complement). + * + * Following example calculates number of bits required to + * represent val in two's complement number, without sign bit. + * + * size_t size; + * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : RBIGNUM_NEGATIVE_P(val); + * size = rb_absint_numwords(val, 1, NULL) + * if (size == (size_t)-1) ...overflow... + * if (neg && rb_absint_singlebit_p(val)) + * size--; + * + * Following example calculates number of bytes required to + * represent val in two's complement number, with sign bit. + * + * size_t size; + * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : RBIGNUM_NEGATIVE_P(val); + * int nlz_bits; + * size = rb_absint_size(val, &nlz_bits); + * if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val))) + * size++; + */ int rb_absint_singlebit_p(VALUE val) { Index: test/-ext-/bignum/test_pack.rb =================================================================== --- test/-ext-/bignum/test_pack.rb (revision 42207) +++ test/-ext-/bignum/test_pack.rb (revision 42208) @@ -322,4 +322,53 @@ class TestBignum < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/bignum/test_pack.rb#L322 } end end + + def test_numbits_2comp + assert_equal(4, -9.test_numbits_2comp_without_sign) + assert_equal(3, -8.test_numbits_2comp_without_sign) + assert_equal(3, -7.test_numbits_2comp_without_sign) + assert_equal(3, -6.test_numbits_2comp_without_sign) + assert_equal(3, -5.test_numbits_2comp_without_sign) + assert_equal(2, -4.test_numbits_2comp_without_sign) + assert_equal(2, -3.test_numbits_2comp_without_sign) + assert_equal(1, -2.test_numbits_2comp_without_sign) + assert_equal(0, -1.test_numbits_2comp_without_sign) + assert_equal(0, 0.test_numbits_2comp_without_sign) + assert_equal(1, 1.test_numbits_2comp_without_sign) + assert_equal(2, 2.test_numbits_2comp_without_sign) + assert_equal(2, 3.test_numbits_2comp_without_sign) + assert_equal(3, 4.test_numbits_2comp_without_sign) + assert_equal(3, 5.test_numbits_2comp_without_sign) + assert_equal(3, 6.test_numbits_2comp_without_sign) + assert_equal(3, 7.test_numbits_2comp_without_sign) + assert_equal(4, 8.test_numbits_2comp_without_sign) + assert_equal(4, 9.test_numbits_2comp_without_sign) + end + + def test_numbytes_2comp + assert_equal(6, -0x8000000001.test_numbytes_2comp_with_sign) + assert_equal(5, -0x8000000000.test_numbytes_2comp_with_sign) + assert_equal(5, -0x80000001.test_numbytes_2comp_with_sign) + assert_equal(4, -0x80000000.test_numbytes_2comp_with_sign) + assert_equal(4, -0x800001.test_numbytes_2comp_with_sign) + assert_equal(3, -0x800000.test_numbytes_2comp_with_sign) + assert_equal(3, -0x8001.test_numbytes_2comp_with_sign) + assert_equal(2, -0x8000.test_numbytes_2comp_with_sign) + assert_equal(2, -0x81.test_numbytes_2comp_with_sign) + assert_equal(1, -0x80.test_numbytes_2comp_with_sign) + assert_equal(1, -1.test_numbytes_2comp_with_sign) + assert_equal(1, 0.test_numbytes_2comp_with_sign) + assert_equal(1, 1.test_numbytes_2comp_with_sign) + assert_equal(1, 0x7f.test_numbytes_2comp_with_sign) + assert_equal(2, 0x80.test_numbytes_2comp_with_sign) + assert_equal(2, 0x7fff.test_numbytes_2comp_with_sign) + assert_equal(3, 0x8000.test_numbytes_2comp_with_sign) + assert_equal(3, 0x7fffff.test_numbytes_2comp_with_sign) + assert_equal(4, 0x800000.test_numbytes_2comp_with_sign) + assert_equal(4, 0x7fffffff.test_numbytes_2comp_with_sign) + assert_equal(5, 0x80000000.test_numbytes_2comp_with_sign) + assert_equal(5, 0x7fffffffff.test_numbytes_2comp_with_sign) + assert_equal(6, 0x8000000000.test_numbytes_2comp_with_sign) + end + end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/