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

ruby-changes:29628

From: akr <ko1@a...>
Date: Thu, 27 Jun 2013 22:54:13 +0900 (JST)
Subject: [ruby-changes:29628] akr:r41680 (trunk): * bignum.c (get2comp): Use bary_2comp.

akr	2013-06-27 22:54:02 +0900 (Thu, 27 Jun 2013)

  New Revision: 41680

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

  Log:
    * bignum.c (get2comp): Use bary_2comp.
      (abs2twocomp_bang): New function.
      (abs2twocomp): New function.
      (twocomp2abs_bang): New function.
      (rb_big_and): Use abs2twocomp and twocomp2abs_bang.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 41679)
+++ ChangeLog	(revision 41680)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Jun 27 22:52:19 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c (get2comp): Use bary_2comp.
+	  (abs2twocomp_bang): New function.
+	  (abs2twocomp): New function.
+	  (twocomp2abs_bang): New function.
+	  (rb_big_and): Use abs2twocomp and twocomp2abs_bang.
+
 Thu Jun 27 20:03:13 2013  CHIKANAGA Tomoyuki  <nagachika@r...>
 
 	* ext/openssl/lib/openssl/ssl.rb (verify_certificate_identity): fix
Index: bignum.c
===================================================================
--- bignum.c	(revision 41679)
+++ bignum.c	(revision 41680)
@@ -289,17 +289,8 @@ get2comp(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L289
 {
     long i = RBIGNUM_LEN(x);
     BDIGIT *ds = BDIGITS(x);
-    BDIGIT_DBL num;
 
-    if (!i) return;
-    while (i--) ds[i] = BIGLO(~ds[i]);
-    i = 0; num = 1;
-    do {
-	num += ds[i];
-	ds[i++] = BIGLO(num);
-	num = BIGDN(num);
-    } while (i < RBIGNUM_LEN(x));
-    if (num != 0) {
+    if (bary_2comp(ds, i)) {
 	rb_big_resize(x, RBIGNUM_LEN(x)+1);
 	ds = BDIGITS(x);
 	ds[RBIGNUM_LEN(x)-1] = 1;
@@ -312,6 +303,50 @@ rb_big_2comp(VALUE x)			/* get 2's compl https://github.com/ruby/ruby/blob/trunk/bignum.c#L303
     get2comp(x);
 }
 
+static BDIGIT
+abs2twocomp_bang(VALUE x)
+{
+    long numbdigits = RBIGNUM_LEN(x);
+    long n;
+    BDIGIT *ds = BDIGITS(x);
+    BDIGIT hibits;
+
+    n = numbdigits;
+
+    while (0 < n && ds[n-1] == 0)
+        n--;
+
+    if (n == 0 || RBIGNUM_POSITIVE_P(x))
+        hibits = 0;
+    else {
+        hibits = BDIGMAX;
+        bary_2comp(ds, numbdigits);
+    }
+
+    return hibits;
+}
+
+static BDIGIT
+abs2twocomp(VALUE *xp)
+{
+    VALUE x = *xp;
+    BDIGIT hibits = 0;
+    if (RBIGNUM_NEGATIVE_P(x)) {
+	*xp = x = rb_big_clone(x);
+        hibits = abs2twocomp_bang(x);
+    }
+    return hibits;
+}
+
+static void
+twocomp2abs_bang(VALUE x, int hibits)
+{
+    RBIGNUM_SET_SIGN(x, !hibits);
+    if (hibits) {
+        get2comp(x);
+    }
+}
+
 static inline VALUE
 bigtrunc(VALUE x)
 {
@@ -4691,55 +4726,48 @@ bigand_int(VALUE x, long y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L4726
  */
 
 VALUE
-rb_big_and(VALUE xx, VALUE yy)
+rb_big_and(VALUE x, VALUE y)
 {
-    volatile VALUE x, y, z;
+    VALUE z;
     BDIGIT *ds1, *ds2, *zds;
     long i, l1, l2;
-    char sign;
+    BDIGIT hibitsx, hibitsy;
+    BDIGIT hibits1, hibits2;
+    VALUE tmpv;
+    BDIGIT tmph;
 
-    if (!FIXNUM_P(yy) && !RB_TYPE_P(yy, T_BIGNUM)) {
-	return rb_num_coerce_bit(xx, yy, '&');
+    if (!FIXNUM_P(y) && !RB_TYPE_P(y, T_BIGNUM)) {
+	return rb_num_coerce_bit(x, y, '&');
     }
 
-    x = xx;
-    y = yy;
-
-    if (!RBIGNUM_SIGN(x)) {
-	x = rb_big_clone(x);
-	get2comp(x);
-    }
+    hibitsx = abs2twocomp(&x);
     if (FIXNUM_P(y)) {
 	return bigand_int(x, FIX2LONG(y));
     }
-    if (!RBIGNUM_SIGN(y)) {
-	y = rb_big_clone(y);
-	get2comp(y);
-    }
+    hibitsy = abs2twocomp(&y);
     if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
-	l1 = RBIGNUM_LEN(y);
-	l2 = RBIGNUM_LEN(x);
-	ds1 = BDIGITS(y);
-	ds2 = BDIGITS(x);
-	sign = RBIGNUM_SIGN(y);
-    }
-    else {
-	l1 = RBIGNUM_LEN(x);
-	l2 = RBIGNUM_LEN(y);
-	ds1 = BDIGITS(x);
-	ds2 = BDIGITS(y);
-	sign = RBIGNUM_SIGN(x);
+        tmpv = x; x = y; y = tmpv;
+        tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
     }
-    z = bignew(l2, RBIGNUM_SIGN(x) || RBIGNUM_SIGN(y));
+    l1 = RBIGNUM_LEN(x);
+    l2 = RBIGNUM_LEN(y);
+    ds1 = BDIGITS(x);
+    ds2 = BDIGITS(y);
+    hibits1 = hibitsx;
+    hibits2 = hibitsy;
+
+    z = bignew(l2, 0);
     zds = BDIGITS(z);
 
     for (i=0; i<l1; i++) {
 	zds[i] = ds1[i] & ds2[i];
     }
     for (; i<l2; i++) {
-	zds[i] = sign?0:ds2[i];
+	zds[i] = hibits1 & ds2[i];
     }
-    if (!RBIGNUM_SIGN(z)) get2comp(z);
+    twocomp2abs_bang(z, hibits1 && hibits2);
+    RB_GC_GUARD(x);
+    RB_GC_GUARD(y);
     return bignorm(z);
 }
 

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

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