summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-21 12:13:47 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-21 12:13:47 +0000
commit5cf931d65e0fbee89b50a09e65b30207ac767884 (patch)
tree55fde40c7d78d29a463d65344032f0d496d33727
parenta2116ef2cd946302f08f70bb192bfd0b74f4837f (diff)
* bignum.c (bary_mul): Use simple multiplication if yl is small.
(rb_cstr_to_inum): Invoke bigsq instead of bigmul0. (bigsq): Re-implemented. (bigmul0): Invoke bigsq if two arguments are identical. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42096 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--bignum.c37
2 files changed, 36 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index de61cc5a57..126ffba954 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sun Jul 21 21:08:59 2013 Tanaka Akira <akr@fsij.org>
+
+ * bignum.c (bary_mul): Use simple multiplication if yl is small.
+ (rb_cstr_to_inum): Invoke bigsq instead of bigmul0.
+ (bigsq): Re-implemented.
+ (bigmul0): Invoke bigsq if two arguments are identical.
+
Sun Jul 21 09:58:19 2013 Tanaka Akira <akr@fsij.org>
* bignum.c (bary_mul_toom3): New function based on bigmul1_toom3.
diff --git a/bignum.c b/bignum.c
index 88688acd7f..16186f6c85 100644
--- a/bignum.c
+++ b/bignum.c
@@ -2496,7 +2496,7 @@ bary_mul_toom3_start(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds
static void
bary_mul(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl)
{
- if (xl < KARATSUBA_MUL_DIGITS) {
+ if (xl < KARATSUBA_MUL_DIGITS || yl < KARATSUBA_MUL_DIGITS) {
if (xds == yds && xl == yl)
bary_sq_fast(zds, zl, xds, xl);
else
@@ -3586,7 +3586,7 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
}
}
- powerv = bigtrunc(bigmul0(powerv, powerv));
+ powerv = bigtrunc(bigsq(powerv));
tds = vds;
vds = uds;
uds = tds;
@@ -5013,12 +5013,39 @@ rb_big_minus(VALUE x, VALUE y)
static VALUE bigdivrem(VALUE, VALUE, volatile VALUE*, volatile VALUE*);
static VALUE
+bigsq(VALUE x)
+{
+ long xn, zn;
+ VALUE z;
+ BDIGIT *xds, *zds;
+
+ xn = RBIGNUM_LEN(x);
+ zn = 2 * xn;
+
+ z = bignew(zn, 1);
+
+ xds = BDIGITS(x);
+ zds = BDIGITS(z);
+
+ if (xn < KARATSUBA_MUL_DIGITS)
+ bary_sq_fast(zds, zn, xds, xn);
+ else
+ bary_mul(zds, zn, xds, xn, xds, xn);
+
+ RB_GC_GUARD(x);
+ return z;
+}
+
+static VALUE
bigmul0(VALUE x, VALUE y)
{
long xn, yn, zn;
VALUE z;
BDIGIT *xds, *yds, *zds;
+ if (x == y)
+ return bigsq(x);
+
xn = RBIGNUM_LEN(x);
yn = RBIGNUM_LEN(y);
zn = xn + yn;
@@ -5590,12 +5617,6 @@ rb_big_fdiv(VALUE x, VALUE y)
return DBL2NUM(dx / dy);
}
-static VALUE
-bigsq(VALUE x)
-{
- return bigtrunc(bigmul0(x, x));
-}
-
/*
* call-seq:
* big ** exponent -> numeric