aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-08 13:05:57 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-08 13:05:57 +0000
commit6fdad008a2bf2e28db5029104b51373b767021fd (patch)
tree068375d8277b90188bfbc623e62c2c3639b1d6f7
parent85855a22420bb6e2fd244f294c844106c992141a (diff)
downloadruby-6fdad008a2bf2e28db5029104b51373b767021fd.tar.gz
* bignum.c (rb_big_sq_fast): New function for testing.
(rb_big_mul_toom3): Ditto. * internal.h (rb_big_sq_fast): Declared. (rb_big_mul_toom3): Ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41832 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog8
-rw-r--r--bignum.c25
-rw-r--r--ext/-test-/bignum/mul.c14
-rw-r--r--internal.h2
-rw-r--r--test/-ext-/bignum/test_mul.rb22
5 files changed, 68 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 544df309c9..3443867365 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Mon Jul 8 22:03:30 2013 Tanaka Akira <akr@fsij.org>
+
+ * bignum.c (rb_big_sq_fast): New function for testing.
+ (rb_big_mul_toom3): Ditto.
+
+ * internal.h (rb_big_sq_fast): Declared.
+ (rb_big_mul_toom3): Ditto.
+
Mon Jul 8 21:59:34 2013 Tanaka Akira <akr@fsij.org>
* bignum.c (bary_mul_balance): Initialize a local variable to suppress
diff --git a/bignum.c b/bignum.c
index eed2181955..1e87b2e519 100644
--- a/bignum.c
+++ b/bignum.c
@@ -1515,7 +1515,8 @@ bary_sq_fast(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn)
MEMZERO(zds, BDIGIT, zn);
for (i = 0; i < xn; i++) {
v = (BDIGIT_DBL)xds[i];
- if (!v) continue;
+ if (!v)
+ continue;
c = (BDIGIT_DBL)zds[i + i] + v * v;
zds[i + i] = BIGLO(c);
c = BIGDN(c);
@@ -1525,18 +1526,30 @@ bary_sq_fast(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn)
c += (BDIGIT_DBL)zds[i + j] + BIGLO(v) * w;
zds[i + j] = BIGLO(c);
c = BIGDN(c);
- if (BIGDN(v)) c += w;
+ if (BIGDN(v))
+ c += w;
}
if (c) {
c += (BDIGIT_DBL)zds[i + xn];
zds[i + xn] = BIGLO(c);
c = BIGDN(c);
assert(c == 0 || i != xn-1);
- if (c && i != xn-1) zds[i + xn + 1] += (BDIGIT)c;
+ if (c && i != xn-1)
+ zds[i + xn + 1] += (BDIGIT)c;
}
}
}
+VALUE
+rb_big_sq_fast(VALUE x)
+{
+ size_t xn = RBIGNUM_LEN(x), zn = 2 * xn;
+ VALUE z = bignew(zn, 1);
+ bary_sq_fast(BDIGITS(z), zn, BDIGITS(x), xn);
+ RB_GC_GUARD(x);
+ return z;
+}
+
/* balancing multiplication by slicing larger argument */
static void
bary_mul_balance(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl)
@@ -4626,6 +4639,12 @@ bigmul1_toom3(VALUE x, VALUE y)
return bignorm(z);
}
+VALUE
+rb_big_mul_toom3(VALUE x, VALUE y)
+{
+ return bigmul1_toom3(x, y);
+}
+
static VALUE
bigmul0(VALUE x, VALUE y)
{
diff --git a/ext/-test-/bignum/mul.c b/ext/-test-/bignum/mul.c
index 18ab3f7633..ad416a9112 100644
--- a/ext/-test-/bignum/mul.c
+++ b/ext/-test-/bignum/mul.c
@@ -19,6 +19,12 @@ mul_normal(VALUE x, VALUE y)
}
static VALUE
+sq_fast(VALUE x)
+{
+ return rb_big_norm(rb_big_sq_fast(big(x)));
+}
+
+static VALUE
mul_balance(VALUE x, VALUE y)
{
return rb_big_norm(rb_big_mul_balance(big(x), big(y)));
@@ -30,12 +36,20 @@ mul_karatsuba(VALUE x, VALUE y)
return rb_big_norm(rb_big_mul_karatsuba(big(x), big(y)));
}
+static VALUE
+mul_toom3(VALUE x, VALUE y)
+{
+ return rb_big_norm(rb_big_mul_toom3(big(x), big(y)));
+}
+
void
Init_mul(VALUE klass)
{
rb_define_const(rb_cBignum, "SIZEOF_BDIGITS", INT2NUM(SIZEOF_BDIGITS));
rb_define_const(rb_cBignum, "BITSPERDIG", INT2NUM(SIZEOF_BDIGITS * CHAR_BIT));
rb_define_method(rb_cInteger, "big_mul_normal", mul_normal, 1);
+ rb_define_method(rb_cInteger, "big_sq_fast", sq_fast, 0);
rb_define_method(rb_cInteger, "big_mul_balance", mul_balance, 1);
rb_define_method(rb_cInteger, "big_mul_karatsuba", mul_karatsuba, 1);
+ rb_define_method(rb_cInteger, "big_mul_toom3", mul_toom3, 1);
}
diff --git a/internal.h b/internal.h
index 38e3701059..dd4d182a21 100644
--- a/internal.h
+++ b/internal.h
@@ -518,6 +518,8 @@ VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, siz
VALUE rb_big_mul_normal(VALUE x, VALUE y);
VALUE rb_big_mul_balance(VALUE x, VALUE y);
VALUE rb_big_mul_karatsuba(VALUE x, VALUE y);
+VALUE rb_big_mul_toom3(VALUE x, VALUE y);
+VALUE rb_big_sq_fast(VALUE x);
/* io.c */
void rb_maygvl_fd_fix_cloexec(int fd);
diff --git a/test/-ext-/bignum/test_mul.rb b/test/-ext-/bignum/test_mul.rb
index e125401664..e462506e9f 100644
--- a/test/-ext-/bignum/test_mul.rb
+++ b/test/-ext-/bignum/test_mul.rb
@@ -36,6 +36,22 @@ class TestBignum < Test::Unit::TestCase
assert_equal(z, x.big_mul_normal(y))
end
+ def test_sq_fast
+ x = (1 << BITSPERDIG) | 1
+ z = (1 << 2*BITSPERDIG) | (2 << BITSPERDIG) | 1
+ assert_equal(z, x.big_sq_fast)
+ end
+
+ def test_sq_fast_max2
+ x = (BDIGMAX << BITSPERDIG) | BDIGMAX
+ assert_equal(x.big_mul_normal(x), x.big_sq_fast)
+ end
+
+ def test_sq_fast_zero_in_middle
+ x = (BDIGMAX << 2*BITSPERDIG) | BDIGMAX
+ assert_equal(x.big_mul_normal(x), x.big_sq_fast)
+ end
+
def test_mul_balance
x = (1 << BITSPERDIG) | 1
y = (1 << BITSPERDIG) | 1
@@ -104,5 +120,11 @@ class TestBignum < Test::Unit::TestCase
assert_equal(x.big_mul_normal(y), x.big_mul_karatsuba(y))
end
+ def test_mul_toom3
+ x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ assert_equal(x.big_mul_normal(y), x.big_mul_toom3(y))
+ end
+
end
end