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

ruby-changes:29125

From: akr <ko1@a...>
Date: Sat, 8 Jun 2013 21:06:10 +0900 (JST)
Subject: [ruby-changes:29125] akr:r41177 (trunk): * bignum.c (rb_absint_singlebit_p): New function.

akr	2013-06-08 21:05:57 +0900 (Sat, 08 Jun 2013)

  New Revision: 41177

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

  Log:
    * bignum.c (rb_absint_singlebit_p): New function.
    
    * internal.h (rb_absint_singlebit_p): Declared.
    
    * time.c (v2w_bignum): Use rb_absint_singlebit_p instead of
      rb_big_abs_find_minbit.
      (rb_big_abs_find_minbit): Removed.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c
    trunk/internal.h
    trunk/time.c

Index: time.c
===================================================================
--- time.c	(revision 41176)
+++ time.c	(revision 41177)
@@ -313,25 +313,6 @@ rb_big_abs_find_maxbit(VALUE big) https://github.com/ruby/ruby/blob/trunk/time.c#L313
     return res;
 }
 
-static VALUE
-rb_big_abs_find_minbit(VALUE big)
-{
-    BDIGIT *ds = RBIGNUM_DIGITS(big);
-    BDIGIT d;
-    long len = RBIGNUM_LEN(big);
-    long i;
-    VALUE res;
-    for (i = 0; i < len; i++)
-        if (ds[i])
-            break;
-    if (i == len)
-        return Qnil;
-    res = mul(LONG2NUM(i), INT2FIX(SIZEOF_BDIGITS * CHAR_BIT));
-    d = ds[i];
-    res = add(res, LONG2FIX(ffs(d)-1));
-    return res;
-}
-
 static wideval_t
 v2w_bignum(VALUE v)
 {
@@ -346,8 +327,7 @@ v2w_bignum(VALUE v) https://github.com/ruby/ruby/blob/trunk/time.c#L327
         return WINT2FIXWV(0);
     if (lt(maxbit, INT2FIX(sizeof(wideint_t) * CHAR_BIT - 2)) ||
         (eq(maxbit, INT2FIX(sizeof(wideint_t) * CHAR_BIT - 2)) &&
-         RBIGNUM_NEGATIVE_P(v) &&
-         eq(rb_big_abs_find_minbit(v), INT2FIX(sizeof(wideint_t) * CHAR_BIT - 2)))) {
+         RBIGNUM_NEGATIVE_P(v) && rb_absint_singlebit_p(v))) {
         wideint_t i;
         i = 0;
         while (len)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 41176)
+++ ChangeLog	(revision 41177)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Jun  8 21:03:40 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c (rb_absint_singlebit_p): New function.
+
+	* internal.h (rb_absint_singlebit_p): Declared.
+
+	* time.c (v2w_bignum): Use rb_absint_singlebit_p instead of
+	  rb_big_abs_find_minbit.
+	  (rb_big_abs_find_minbit): Removed.
+
 Sat Jun  8 20:24:23 2013  Tanaka Akira  <akr@f...>
 
 	* time.c (rb_big_abs_find_maxbit): Use rb_absint_size.
Index: internal.h
===================================================================
--- internal.h	(revision 41176)
+++ internal.h	(revision 41177)
@@ -121,6 +121,7 @@ VALUE rb_integer_float_cmp(VALUE x, VALU https://github.com/ruby/ruby/blob/trunk/internal.h#L121
 VALUE rb_integer_float_eq(VALUE x, VALUE y);
 size_t rb_absint_size(VALUE val, int *number_of_leading_zero_bits);
 size_t rb_absint_size_in_word(VALUE val, size_t word_numbits, size_t *number_of_leading_zero_bits);
+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 41176)
+++ bignum.c	(revision 41177)
@@ -537,6 +537,52 @@ rb_absint_size_in_word(VALUE val, size_t https://github.com/ruby/ruby/blob/trunk/bignum.c#L537
     return numwords;
 }
 
+int
+rb_absint_singlebit_p(VALUE val)
+{
+    BDIGIT *dp;
+    BDIGIT *de;
+    BDIGIT fixbuf[(sizeof(long) + SIZEOF_BDIGITS - 1) / SIZEOF_BDIGITS];
+    BDIGIT d;
+
+    val = rb_to_int(val);
+
+    if (FIXNUM_P(val)) {
+        long v = FIX2LONG(val);
+        if (v < 0) {
+            v = -v;
+        }
+#if SIZEOF_BDIGITS == SIZEOF_LONG
+        fixbuf[0] = v;
+#else
+        {
+            int i;
+            for (i = 0; i < numberof(fixbuf); i++) {
+                fixbuf[i] = (BDIGIT)(v & ((1L << (SIZEOF_BDIGITS * CHAR_BIT)) - 1));
+                v >>= SIZEOF_BDIGITS * CHAR_BIT;
+            }
+        }
+#endif
+        dp = fixbuf;
+        de = fixbuf + numberof(fixbuf);
+    }
+    else {
+        dp = BDIGITS(val);
+        de = dp + RBIGNUM_LEN(val);
+    }
+    while (dp < de && de[-1] == 0)
+        de--;
+    while (dp < de && dp[0] == 0)
+        dp++;
+    if (dp == de) /* no bit set. */
+        return 0;
+    if (dp != de-1) /* two non-zero words. two bits set, at least. */
+        return 0;
+    d = *dp;
+    d = d & (d - 1); /* Clear the least significant bit set */
+    return d == 0;
+}
+
 #define INTEGER_PACK_WORDORDER_MASK \
     (INTEGER_PACK_MSWORD_FIRST | \
      INTEGER_PACK_LSWORD_FIRST)

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

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