From df1192edf575c50281ffba3ae1b9bac89c774cf7 Mon Sep 17 00:00:00 2001 From: akr Date: Mon, 1 Jul 2013 13:59:50 +0000 Subject: [PATCH] * bignum.c (bary_mul2): New function. (rb_cstr_to_inum): Use a better algorithm to compose the result if input length is very long. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41726 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 +++ bignum.c | 135 +++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 119 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd0ac0531b..0070e5d344 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Mon Jul 1 22:57:19 2013 Tanaka Akira + + * bignum.c (bary_mul2): New function. + (rb_cstr_to_inum): Use a better algorithm to compose the result + if input length is very long. + Mon Jul 1 20:22:00 2013 Kenta Murata * ext/bigdecimal/bigdecimal.h (RB_UNUSED_VAR, UNREACHABLE): diff --git a/bignum.c b/bignum.c index 9b3cf2745d..8324280f24 100644 --- a/bignum.c +++ b/bignum.c @@ -92,16 +92,24 @@ static VALUE big_three = Qnil; #define RBIGNUM_SET_NEGATIVE_SIGN(b) RBIGNUM_SET_SIGN(b, 0) #define RBIGNUM_SET_POSITIVE_SIGN(b) RBIGNUM_SET_SIGN(b, 1) +#define KARATSUBA_MUL_DIGITS 70 +#define TOOM3_MUL_DIGITS 150 + static BDIGIT bary_small_lshift(BDIGIT *zds, BDIGIT *xds, long n, int shift); static void bary_small_rshift(BDIGIT *zds, BDIGIT *xds, long n, int shift, int sign_bit); static void bary_unpack(BDIGIT *bdigits, size_t num_bdigits, const void *words, size_t numwords, size_t wordsize, size_t nails, int flags); static void bary_mul(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl); +static void bary_mul2(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl); static void bary_sub(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn, BDIGIT *yds, size_t yn); static void bary_divmod(BDIGIT *qds, size_t nq, BDIGIT *rds, size_t nr, BDIGIT *xds, size_t nx, BDIGIT *yds, size_t ny); static void bary_add(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn, BDIGIT *yds, size_t yn); static int bary_pack(int sign, BDIGIT *ds, size_t num_bdigits, void *words, size_t numwords, size_t wordsize, size_t nails, int flags); static int bary_2comp(BDIGIT *ds, size_t n); +static void calc_hbase(int base, BDIGIT *hbase_p, int *hbase_numdigits_p); +static VALUE bigsqr_fast(VALUE x); +static VALUE bigmul0(VALUE x, VALUE y); + #define BIGNUM_DEBUG 0 #if BIGNUM_DEBUG #define ON_DEBUG(x) do { x; } while (0) @@ -2039,27 +2047,94 @@ rb_cstr_to_inum(const char *str, int base, int badcheck) } else { len = (len/BITSPERDIG)+1; - z = bignew(len, sign); - zds = BDIGITS(z); - for (i=len;i--;) zds[i]=0; + if (len < KARATSUBA_MUL_DIGITS) { + z = bignew(len, sign); + zds = BDIGITS(z); + for (i=len;i--;) zds[i]=0; - size = p - buf; - for (p = buf; p < buf + size; p++) { - num = *p; - i = 0; - for (;;) { - while (i