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

ruby-changes:29910

From: akr <ko1@a...>
Date: Sun, 14 Jul 2013 22:24:55 +0900 (JST)
Subject: [ruby-changes:29910] akr:r41962 (trunk): * bignum.c (bary_subb): Support xn < yn.

akr	2013-07-14 22:24:44 +0900 (Sun, 14 Jul 2013)

  New Revision: 41962

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

  Log:
    * bignum.c (bary_subb): Support xn < yn.
      (bigsub_core): Removed.
      (bigsub): Don't compare before subtraction.  Just subtract and
      get the two's complement if the subtraction causes a borrow.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 41961)
+++ ChangeLog	(revision 41962)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun Jul 14 22:21:11 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c (bary_subb): Support xn < yn.
+	  (bigsub_core): Removed.
+	  (bigsub): Don't compare before subtraction.  Just subtract and
+	  get the two's complement if the subtraction causes a borrow.
+
 Sun Jul 14 00:36:03 2013  Tanaka Akira  <akr@f...>
 
 	* bignum.c (DIGSPERLONG): Unused macro removed.
Index: bignum.c
===================================================================
--- bignum.c	(revision 41961)
+++ bignum.c	(revision 41962)
@@ -1353,21 +1353,33 @@ bary_subb(BDIGIT *zds, size_t zn, BDIGIT https://github.com/ruby/ruby/blob/trunk/bignum.c#L1353
 {
     BDIGIT_DBL_SIGNED num;
     size_t i;
+    size_t sn;
 
-    assert(yn <= xn);
     assert(xn <= zn);
+    assert(yn <= zn);
+
+    sn = xn < yn ? xn : yn;
 
     num = borrow ? -1 : 0;
-    for (i = 0; i < yn; i++) {
+    for (i = 0; i < sn; i++) {
 	num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
 	zds[i] = BIGLO(num);
 	num = BIGDN(num);
     }
-    for (; i < xn; i++) {
-        if (num == 0) goto num_is_zero;
-	num += xds[i];
-	zds[i] = BIGLO(num);
-	num = BIGDN(num);
+    if (yn <= xn) {
+        for (; i < xn; i++) {
+            if (num == 0) goto num_is_zero;
+            num += xds[i];
+            zds[i] = BIGLO(num);
+            num = BIGDN(num);
+        }
+    }
+    else {
+        for (; i < yn; i++) {
+            num -= yds[i];
+            zds[i] = BIGLO(num);
+            num = BIGDN(num);
+        }
     }
     if (num == 0) goto num_is_zero;
     for (; i < zn; i++) {
@@ -4237,42 +4249,27 @@ rb_big_neg(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L4249
     return bignorm(z);
 }
 
-static void
-bigsub_core(BDIGIT *xds, long xn, BDIGIT *yds, long yn, BDIGIT *zds, long zn)
-{
-    bary_sub(zds, zn, xds, xn, yds, yn);
-}
-
 static VALUE
 bigsub(VALUE x, VALUE y)
 {
-    VALUE z = 0;
-    long i = RBIGNUM_LEN(x);
-    BDIGIT *xds, *yds;
+    VALUE z;
+    BDIGIT *xds, *yds, *zds;
+    long xn, yn, zn;
 
-    /* if x is smaller than y, swap */
-    if (RBIGNUM_LEN(x) < RBIGNUM_LEN(y)) {
-	z = x; x = y; y = z;	/* swap x y */
-    }
-    else if (RBIGNUM_LEN(x) == RBIGNUM_LEN(y)) {
-	xds = BDIGITS(x);
-	yds = BDIGITS(y);
-	while (i > 0) {
-	    i--;
-	    if (xds[i] > yds[i]) {
-		break;
-	    }
-	    if (xds[i] < yds[i]) {
-		z = x; x = y; y = z;	/* swap x y */
-		break;
-	    }
-	}
-    }
+    xn = RBIGNUM_LEN(x);
+    yn = RBIGNUM_LEN(y);
+    zn = xn < yn ? yn : xn;
+
+    z = bignew(zn, 1);
 
-    z = bignew(RBIGNUM_LEN(x), z==0);
-    bigsub_core(BDIGITS(x), RBIGNUM_LEN(x),
-		BDIGITS(y), RBIGNUM_LEN(y),
-		BDIGITS(z), RBIGNUM_LEN(z));
+    xds = BDIGITS(x);
+    yds = BDIGITS(y);
+    zds = BDIGITS(z);
+
+    if (bary_sub(zds, zn, xds, xn, yds, yn)) {
+        bary_2comp(zds, zn);
+        RBIGNUM_SET_NEGATIVE_SIGN(z);
+    }
 
     return z;
 }

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

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