1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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]



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42208 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2013-07-28 02:14:58 +00:00
parent 56150eba92
commit e5ff9d58ef
6 changed files with 111 additions and 3 deletions

View file

@ -1,3 +1,11 @@
Sun Jul 28 11:12:07 2013 Tanaka Akira <akr@fsij.org>
* 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@ruby-lang.org>
* win32/win32.c (rb_w32_pipe): fix pipe name formatting. as "%x" may

View file

@ -3275,6 +3275,34 @@ rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
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)
{

View file

@ -45,6 +45,26 @@ rb_integer_unpack_m(VALUE klass, VALUE buf, VALUE numwords, VALUE wordsize, VALU
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)
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);
}

View file

@ -157,6 +157,9 @@ VALUE rb_big_rshift(VALUE, VALUE);
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);

View file

@ -141,9 +141,6 @@ VALUE rb_big_fdiv(VALUE x, VALUE y);
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);

View file

@ -322,4 +322,53 @@ class TestBignum < Test::Unit::TestCase
}
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