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

ruby-changes:29150

From: akr <ko1@a...>
Date: Mon, 10 Jun 2013 12:12:55 +0900 (JST)
Subject: [ruby-changes:29150] akr:r41202 (trunk): * bignum.c (integer_unpack_num_bdigits_small: Extracted from

akr	2013-06-10 12:12:44 +0900 (Mon, 10 Jun 2013)

  New Revision: 41202

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=41202

  Log:
    * bignum.c (integer_unpack_num_bdigits_small: Extracted from
      rb_integer_unpack.
      (integer_unpack_num_bdigits_generic): Ditto.
      (integer_unpack_num_bdigits_bytes): New function.
      (rb_integer_unpack): Use above functions.
      Return a Bignum for INTEGER_PACK_FORCE_BIGNUM evenwhen the result
      is zero.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 41201)
+++ ChangeLog	(revision 41202)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Jun 10 12:10:06 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c (integer_unpack_num_bdigits_small: Extracted from
+	  rb_integer_unpack.
+	  (integer_unpack_num_bdigits_generic): Ditto.
+	  (integer_unpack_num_bdigits_bytes): New function.
+	  (rb_integer_unpack): Use above functions.
+	  Return a Bignum for INTEGER_PACK_FORCE_BIGNUM evenwhen the result
+	  is zero.
+
 Mon Jun 10 05:38:23 2013  Tanaka Akira  <akr@f...>
 
 	* bignum.c (absint_numwords_small): New function.
Index: bignum.c
===================================================================
--- bignum.c	(revision 41201)
+++ bignum.c	(revision 41202)
@@ -982,6 +982,59 @@ rb_integer_pack(VALUE val, int *signp, v https://github.com/ruby/ruby/blob/trunk/bignum.c#L982
 #undef TAKE_LOWBITS
 }
 
+static size_t
+integer_unpack_num_bdigits_small(size_t numwords, size_t wordsize, size_t nails)
+{
+    size_t num_bits;
+    num_bits = (wordsize * CHAR_BIT - nails) * numwords;
+    return (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT);
+}
+
+static size_t
+integer_unpack_num_bdigits_bytes(size_t numwords, size_t wordsize)
+{
+    /*
+     * num_bits = wordsize * CHAR_BIT * numwords
+     *
+     * num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
+     * = (wordsize * CHAR_BIT * numwords + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
+     * = ((wordsize * numwords + SIZEOF_BDIGITS)*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
+     *
+     * q, r = (wordsize * numwords).divmod(SIZEOF_BDIGITS)
+     * q * SIZEOF_BDIGITS + r = wordsize * numwords
+     *
+     * num_bdigits = ((q * SIZEOF_BDIGITS + r + SIZEOF_BDIGITS)*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
+     * = (q * SIZEOF_BDIGITS * CHAR_BIT + r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
+     * = q + (r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
+     */
+    size_t t, q, r;
+    t = wordsize * numwords;
+    q = t / SIZEOF_BDIGITS;
+    r = t % SIZEOF_BDIGITS;
+    return q + (r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT);
+}
+
+static size_t
+integer_unpack_num_bdigits_generic(size_t numwords, size_t wordsize, size_t nails)
+{
+    VALUE num_bits_v, num_bdigits_v;
+
+    /* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
+    num_bits_v = SIZET2NUM(wordsize);
+    num_bits_v = rb_funcall(num_bits_v, '*', 1, LONG2FIX(CHAR_BIT));
+    num_bits_v = rb_funcall(num_bits_v, '-', 1, SIZET2NUM(nails));
+    num_bits_v = rb_funcall(num_bits_v, '*', 1, SIZET2NUM(numwords));
+
+    if (num_bits_v == LONG2FIX(0))
+        return 0;
+
+    /* num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT) */
+    num_bdigits_v = rb_funcall(num_bits_v, '+', 1, LONG2FIX(SIZEOF_BDIGITS*CHAR_BIT-1));
+    num_bdigits_v = rb_funcall(num_bdigits_v, '/', 1, LONG2FIX(SIZEOF_BDIGITS*CHAR_BIT));
+
+    return NUM2SIZET(num_bdigits_v);
+}
+
 static inline void
 integer_unpack_push_bits(int data, int numbits, BDIGIT_DBL *ddp, int *numbits_in_dd_p, BDIGIT **dpp)
 {
@@ -1012,6 +1065,7 @@ rb_integer_unpack(int sign, const void * https://github.com/ruby/ruby/blob/trunk/bignum.c#L1065
 {
     VALUE result;
     const unsigned char *buf = words;
+    size_t num_bdigits;
 
     BDIGIT *dp;
     BDIGIT *de;
@@ -1035,33 +1089,44 @@ rb_integer_unpack(int sign, const void * https://github.com/ruby/ruby/blob/trunk/bignum.c#L1089
         rb_raise(rb_eArgError, "unexpected sign: %d", sign);
 
     if (numwords <= (SIZE_MAX - (SIZEOF_BDIGITS*CHAR_BIT-1)) / CHAR_BIT / wordsize) {
-        size_t num_bits, num_bdigits;
-        num_bits = (wordsize * CHAR_BIT - nails) * numwords;
-        if (num_bits == 0)
-            return LONG2FIX(0);
-        num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT);
-        if (LONG_MAX < num_bdigits)
-            rb_raise(rb_eArgError, "too big to unpack as an integer");
-        result = bignew((long)num_bdigits, 0 <= sign);
+        num_bdigits = integer_unpack_num_bdigits_small(numwords, wordsize, nails);
+#if 0
+        {
+            static int first = 1;
+            if (first)
+                first = 0;
+            else {
+                size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails);
+                assert(num_bdigits == num_bdigits1);
+            }
+        }
+#endif
+    }
+    else if (nails == 0) {
+        num_bdigits = integer_unpack_num_bdigits_bytes(numwords, wordsize);
+#if 0
+        {
+            static int first = 1;
+            if (first)
+                first = 0;
+            else {
+                size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails);
+                assert(num_bdigits == num_bdigits1);
+            }
+        }
+#endif
     }
     else {
-        VALUE num_bits, num_bdigits;
-
-        /* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
-        num_bits = SIZET2NUM(wordsize);
-        num_bits = rb_funcall(num_bits, '*', 1, LONG2FIX(CHAR_BIT));
-        num_bits = rb_funcall(num_bits, '-', 1, SIZET2NUM(nails));
-        num_bits = rb_funcall(num_bits, '*', 1, SIZET2NUM(numwords));
-
-        if (num_bits == LONG2FIX(0))
-            return LONG2FIX(0);
-
-        /* num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT) */
-        num_bdigits = rb_funcall(num_bits, '+', 1, LONG2FIX(SIZEOF_BDIGITS*CHAR_BIT-1));
-        num_bdigits = rb_funcall(num_bdigits, '/', 1, LONG2FIX(SIZEOF_BDIGITS*CHAR_BIT));
-
-        result = bignew(NUM2LONG(num_bdigits), 0 <= sign);
+        num_bdigits = integer_unpack_num_bdigits_generic(numwords, wordsize, nails);
+    }
+    if (num_bdigits == 0) {
+        if (flags & INTEGER_PACK_FORCE_BIGNUM)
+            return rb_int2big(0);
+        return LONG2FIX(0);
     }
+    if (LONG_MAX < num_bdigits)
+        rb_raise(rb_eArgError, "too big to unpack as an integer");
+    result = bignew((long)num_bdigits, 0 <= sign);
 
     dp = BDIGITS(result);
     de = dp + RBIGNUM_LEN(result);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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