[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]