ruby-changes:29261
From: akr <ko1@a...>
Date: Sat, 15 Jun 2013 22:32:27 +0900 (JST)
Subject: [ruby-changes:29261] akr:r41313 (trunk): * bignum.c (bary_mul): New function.
akr 2013-06-15 22:32:16 +0900 (Sat, 15 Jun 2013) New Revision: 41313 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=41313 Log: * bignum.c (bary_mul): New function. (absint_numwords_generic): Use bary_mul. (bary_mul_single): Extracted from bigmul1_single. (bary_mul_normal): Extracted from bigmul1_normal. Modified files: trunk/ChangeLog trunk/bignum.c Index: ChangeLog =================================================================== --- ChangeLog (revision 41312) +++ ChangeLog (revision 41313) @@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sat Jun 15 22:05:30 2013 Tanaka Akira <akr@f...> + + * bignum.c (bary_mul): New function. + (absint_numwords_generic): Use bary_mul. + (bary_mul_single): Extracted from bigmul1_single. + (bary_mul_normal): Extracted from bigmul1_normal. + Sat Jun 15 20:13:46 2013 Tanaka Akira <akr@f...> * bignum.c (bary_unpack): Extracted from rb_integer_unpack_internal. Index: bignum.c =================================================================== --- bignum.c (revision 41312) +++ bignum.c (revision 41313) @@ -58,6 +58,7 @@ static int nlz(BDIGIT x); https://github.com/ruby/ruby/blob/trunk/bignum.c#L58 static BDIGIT bdigs_small_lshift(BDIGIT *zds, BDIGIT *xds, long n, int shift); static void bdigs_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); #define BIGNUM_DEBUG 0 #if BIGNUM_DEBUG @@ -595,8 +596,10 @@ absint_numwords_generic(size_t numbytes, https://github.com/ruby/ruby/blob/trunk/bignum.c#L596 size_t numwords; size_t nlz_bits; + BDIGIT numbytes_bary[bdigit_roomof(sizeof(numbytes))]; + BDIGIT char_bit[1] = { CHAR_BIT }; BDIGIT val_numbits_bary[bdigit_roomof(sizeof(numbytes) + 1)]; - VALUE expected; + VALUE v; /* * val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte @@ -605,15 +608,16 @@ absint_numwords_generic(size_t numbytes, https://github.com/ruby/ruby/blob/trunk/bignum.c#L608 * nlz_bits = mod == 0 ? 0 : word_numbits - mod */ - bary_unpack(BARY_ARGS(val_numbits_bary), &numbytes, 1, sizeof(numbytes), 0, + bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0, INTEGER_PACK_NATIVE_BYTE_ORDER); + bary_mul(BARY_ARGS(val_numbits_bary), BARY_ARGS(numbytes_bary), BARY_ARGS(char_bit)); - val_numbits = rb_integer_unpack(val_numbits_bary, numberof(val_numbits_bary), sizeof(BDIGIT), 0, + v = rb_integer_unpack(val_numbits_bary, numberof(val_numbits_bary), sizeof(BDIGIT), 0, INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER); - expected = SIZET2NUM(numbytes); - assert(rb_equal(val_numbits, expected)); + val_numbits = SIZET2NUM(numbytes); val_numbits = rb_funcall(val_numbits, '*', 1, LONG2FIX(CHAR_BIT)); + assert(rb_equal(val_numbits, v)); if (nlz_bits_in_msbyte) val_numbits = rb_funcall(val_numbits, '-', 1, LONG2FIX(nlz_bits_in_msbyte)); word_numbits_v = SIZET2NUM(word_numbits); @@ -1279,6 +1283,7 @@ bary_unpack(BDIGIT *bdigits, size_t num_ https://github.com/ruby/ruby/blob/trunk/bignum.c#L1283 } if (dd) *dp++ = (BDIGIT)dd; + assert(dp <= de); while (dp < de) *dp++ = 0; #undef PUSH_BITS @@ -3140,10 +3145,21 @@ big_real_len(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L3145 return i + 1; } +static void +bary_mul_single(BDIGIT *zds, size_t zl, BDIGIT x, BDIGIT y) +{ + BDIGIT_DBL n; + + assert(2 <= zl); + + n = (BDIGIT_DBL)x * y; + zds[0] = BIGLO(n); + zds[1] = (BDIGIT)BIGDN(n); +} + static VALUE bigmul1_single(VALUE x, VALUE y) { - BDIGIT_DBL n; VALUE z = bignew(2, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y)); BDIGIT *xds, *yds, *zds; @@ -3151,24 +3167,20 @@ bigmul1_single(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L3167 yds = BDIGITS(y); zds = BDIGITS(z); - n = (BDIGIT_DBL)xds[0] * yds[0]; - zds[0] = BIGLO(n); - zds[1] = (BDIGIT)BIGDN(n); + bary_mul_single(zds, 2, xds[0], yds[0]); return z; } -static VALUE -bigmul1_normal(VALUE x, VALUE y) +static void +bary_mul_normal(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl) { - long xl = RBIGNUM_LEN(x), yl = RBIGNUM_LEN(y), i, j = xl + yl; + size_t i; + size_t j = zl; BDIGIT_DBL n = 0; - VALUE z = bignew(j, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y)); - BDIGIT *xds, *yds, *zds; - xds = BDIGITS(x); - yds = BDIGITS(y); - zds = BDIGITS(z); + assert(xl + yl <= zl); + while (j--) zds[j] = 0; for (i = 0; i < xl; i++) { BDIGIT_DBL dd; @@ -3185,10 +3197,40 @@ bigmul1_normal(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L3197 zds[i + j] = (BDIGIT)n; } } +} + +static VALUE +bigmul1_normal(VALUE x, VALUE y) +{ + size_t xl = RBIGNUM_LEN(x), yl = RBIGNUM_LEN(y), zl = xl + yl; + VALUE z = bignew(zl, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y)); + BDIGIT *xds, *yds, *zds; + + xds = BDIGITS(x); + yds = BDIGITS(y); + zds = BDIGITS(z); + + bary_mul_normal(zds, zl, xds, xl, yds, yl); + rb_thread_check_ints(); return z; } +static void +bary_mul(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl) +{ + size_t l; + if (xl == 1 && yl == 1) { + l = 2; + bary_mul_single(zds, zl, xds[0], yds[1]); + } + else { + l = xl + yl; + bary_mul_normal(zds, zl, xds, xl, yds, yl); + } + MEMZERO(zds + l, BDIGIT, zl - l); +} + static VALUE bigmul0(VALUE x, VALUE y); /* balancing multiplication by slicing larger argument */ -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/