summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-07 14:01:40 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-07 14:01:40 +0000
commit29634bca310c32b8f8dacd6e9bd8304388b30d17 (patch)
treea302efcad36156493f8e4c51fcde940fe4c20db7 /bignum.c
parentd7c2f3f8a412b64880fa07b65faabe2b56543290 (diff)
* internal.h (rb_big_mul_normal): Declared.
(rb_big_mul_balance): Ditto. (rb_big_mul_karatsuba): Ditto. * bignum.c (rb_big_mul_normal): New function for tests. (rb_big_mul_balance): Ditto. (rb_big_mul_karatsuba): Ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41824 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/bignum.c b/bignum.c
index ea828ff859..31d35b2d78 100644
--- a/bignum.c
+++ b/bignum.c
@@ -1489,6 +1489,17 @@ bary_mul_normal(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, siz
}
}
+VALUE
+rb_big_mul_normal(VALUE x, VALUE y)
+{
+ size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;
+ VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
+ bary_mul_normal(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
+ RB_GC_GUARD(x);
+ RB_GC_GUARD(y);
+ return z;
+}
+
/* efficient squaring (2 times faster than normal multiplication)
* ref: Handbook of Applied Cryptography, Algorithm 14.16
* http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
@@ -1558,6 +1569,19 @@ bary_mul_balance(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, si
ALLOCV_END(work);
}
+VALUE
+rb_big_mul_balance(VALUE x, VALUE y)
+{
+ size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;
+ VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
+ if (!(2 * xn <= yn || 3 * xn <= 2*(yn+2)))
+ rb_raise(rb_eArgError, "invalid bignum length");
+ bary_mul_balance(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
+ RB_GC_GUARD(x);
+ RB_GC_GUARD(y);
+ return z;
+}
+
/* multiplication by karatsuba method */
static void
bary_mul_karatsuba(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl)
@@ -1720,6 +1744,19 @@ bary_mul_karatsuba(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds,
ALLOCV_END(work);
}
+VALUE
+rb_big_mul_karatsuba(VALUE x, VALUE y)
+{
+ size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;
+ VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
+ if (!(xn <= yn && yn < 2 * xn))
+ rb_raise(rb_eArgError, "invalid bignum length");
+ bary_mul_karatsuba(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
+ RB_GC_GUARD(x);
+ RB_GC_GUARD(y);
+ return z;
+}
+
static void
bary_mul1(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl)
{