1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
akr 2013-07-08 13:05:57 +00:00
parent 85855a2242
commit 6fdad008a2
5 changed files with 68 additions and 3 deletions

View file

@ -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> Mon Jul 8 21:59:34 2013 Tanaka Akira <akr@fsij.org>
* bignum.c (bary_mul_balance): Initialize a local variable to suppress * bignum.c (bary_mul_balance): Initialize a local variable to suppress

View file

@ -1515,7 +1515,8 @@ bary_sq_fast(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn)
MEMZERO(zds, BDIGIT, zn); MEMZERO(zds, BDIGIT, zn);
for (i = 0; i < xn; i++) { for (i = 0; i < xn; i++) {
v = (BDIGIT_DBL)xds[i]; v = (BDIGIT_DBL)xds[i];
if (!v) continue; if (!v)
continue;
c = (BDIGIT_DBL)zds[i + i] + v * v; c = (BDIGIT_DBL)zds[i + i] + v * v;
zds[i + i] = BIGLO(c); zds[i + i] = BIGLO(c);
c = BIGDN(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; c += (BDIGIT_DBL)zds[i + j] + BIGLO(v) * w;
zds[i + j] = BIGLO(c); zds[i + j] = BIGLO(c);
c = BIGDN(c); c = BIGDN(c);
if (BIGDN(v)) c += w; if (BIGDN(v))
c += w;
} }
if (c) { if (c) {
c += (BDIGIT_DBL)zds[i + xn]; c += (BDIGIT_DBL)zds[i + xn];
zds[i + xn] = BIGLO(c); zds[i + xn] = BIGLO(c);
c = BIGDN(c); c = BIGDN(c);
assert(c == 0 || i != xn-1); 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 */ /* balancing multiplication by slicing larger argument */
static void static void
bary_mul_balance(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl) 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); return bignorm(z);
} }
VALUE
rb_big_mul_toom3(VALUE x, VALUE y)
{
return bigmul1_toom3(x, y);
}
static VALUE static VALUE
bigmul0(VALUE x, VALUE y) bigmul0(VALUE x, VALUE y)
{ {

View file

@ -18,6 +18,12 @@ mul_normal(VALUE x, VALUE y)
return rb_big_norm(rb_big_mul_normal(big(x), big(y))); return rb_big_norm(rb_big_mul_normal(big(x), big(y)));
} }
static VALUE
sq_fast(VALUE x)
{
return rb_big_norm(rb_big_sq_fast(big(x)));
}
static VALUE static VALUE
mul_balance(VALUE x, VALUE y) mul_balance(VALUE x, VALUE y)
{ {
@ -30,12 +36,20 @@ mul_karatsuba(VALUE x, VALUE y)
return rb_big_norm(rb_big_mul_karatsuba(big(x), big(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 void
Init_mul(VALUE klass) Init_mul(VALUE klass)
{ {
rb_define_const(rb_cBignum, "SIZEOF_BDIGITS", INT2NUM(SIZEOF_BDIGITS)); rb_define_const(rb_cBignum, "SIZEOF_BDIGITS", INT2NUM(SIZEOF_BDIGITS));
rb_define_const(rb_cBignum, "BITSPERDIG", INT2NUM(SIZEOF_BDIGITS * CHAR_BIT)); 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_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_balance", mul_balance, 1);
rb_define_method(rb_cInteger, "big_mul_karatsuba", mul_karatsuba, 1); rb_define_method(rb_cInteger, "big_mul_karatsuba", mul_karatsuba, 1);
rb_define_method(rb_cInteger, "big_mul_toom3", mul_toom3, 1);
} }

View file

@ -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_normal(VALUE x, VALUE y);
VALUE rb_big_mul_balance(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_karatsuba(VALUE x, VALUE y);
VALUE rb_big_mul_toom3(VALUE x, VALUE y);
VALUE rb_big_sq_fast(VALUE x);
/* io.c */ /* io.c */
void rb_maygvl_fd_fix_cloexec(int fd); void rb_maygvl_fd_fix_cloexec(int fd);

View file

@ -36,6 +36,22 @@ class TestBignum < Test::Unit::TestCase
assert_equal(z, x.big_mul_normal(y)) assert_equal(z, x.big_mul_normal(y))
end 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 def test_mul_balance
x = (1 << BITSPERDIG) | 1 x = (1 << BITSPERDIG) | 1
y = (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)) assert_equal(x.big_mul_normal(y), x.big_mul_karatsuba(y))
end 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
end end