ruby-changes:29976
From: akr <ko1@a...>
Date: Wed, 17 Jul 2013 22:53:35 +0900 (JST)
Subject: [ruby-changes:29976] akr:r42028 (trunk): * bignum.c: An static assertion for relation of SIZEOF_LONG and
akr 2013-07-17 22:53:24 +0900 (Wed, 17 Jul 2013) New Revision: 42028 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42028 Log: * bignum.c: An static assertion for relation of SIZEOF_LONG and SIZEOF_BDIGITS is added. (bary_mul_precheck): Reduce comparisons. (bary_mul): Invoke bary_sq_fast or bary_mul1 if the bignum size is small. (bigfixize): Resize the argument bignum here. (bignorm): Don't call bigtrunc after bigfixize. Modified files: trunk/ChangeLog trunk/bignum.c Index: ChangeLog =================================================================== --- ChangeLog (revision 42027) +++ ChangeLog (revision 42028) @@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed Jul 17 22:34:47 2013 Tanaka Akira <akr@f...> + + * bignum.c: An static assertion for relation of SIZEOF_LONG and + SIZEOF_BDIGITS is added. + (bary_mul_precheck): Reduce comparisons. + (bary_mul): Invoke bary_sq_fast or bary_mul1 if the bignum size is + small. + (bigfixize): Resize the argument bignum here. + (bignorm): Don't call bigtrunc after bigfixize. + Wed Jul 17 22:13:26 2013 Masaki Matsushita <glass.saga@g...> * hash.c (rb_hash_replace): performance improvement by using Index: bignum.c =================================================================== --- bignum.c (revision 42027) +++ bignum.c (revision 42028) @@ -47,6 +47,12 @@ STATIC_ASSERT(bdigit_dbl_signedness, 0 < https://github.com/ruby/ruby/blob/trunk/bignum.c#L47 STATIC_ASSERT(bdigit_dbl_signed_signedness, 0 > (BDIGIT_DBL_SIGNED)-1); STATIC_ASSERT(rbignum_embed_len_max, RBIGNUM_EMBED_LEN_MAX <= (RBIGNUM_EMBED_LEN_MASK >> RBIGNUM_EMBED_LEN_SHIFT)); +#if SIZEOF_BDIGITS < SIZEOF_LONG +STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGITS == 0); +#else +STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGITS % SIZEOF_LONG == 0); +#endif + #ifdef WORDS_BIGENDIAN # define HOST_BIGENDIAN_P 1 #else @@ -1911,22 +1917,40 @@ bary_mul_precheck(BDIGIT **zdsp, size_t https://github.com/ruby/ruby/blob/trunk/bignum.c#L1917 assert(xl + yl <= zl); - while (0 < xl && xds[xl-1] == 0) - xl--; - while (0 < yl && yds[yl-1] == 0) - yl--; - nlsz = 0; - while (0 < xl && xds[0] == 0) { - xds++; - xl--; - nlsz++; + + while (0 < xl) { + if (xds[xl-1] == 0) { + xl--; + } + else { + do { + if (xds[0] != 0) + break; + xds++; + xl--; + nlsz++; + } while (0 < xl); + break; + } } - while (0 < yl && yds[0] == 0) { - yds++; - yl--; - nlsz++; + + while (0 < yl) { + if (yds[yl-1] == 0) { + yl--; + } + else { + do { + if (xds[0] != 0) + break; + yds++; + yl--; + nlsz++; + } while (0 < yl); + break; + } } + if (nlsz) { MEMZERO(zds, BDIGIT, nlsz); zds += nlsz; @@ -1942,12 +1966,12 @@ bary_mul_precheck(BDIGIT **zdsp, size_t https://github.com/ruby/ruby/blob/trunk/bignum.c#L1966 } assert(xl <= yl); - if (xl == 0) { - MEMZERO(zds, BDIGIT, zl); - return 1; - } + if (xl <= 1) { + if (xl == 0) { + MEMZERO(zds, BDIGIT, zl); + return 1; + } - if (xl == 1) { if (xds[0] == 1) { MEMCPY(zds, yds, BDIGIT, yl); MEMZERO(zds+yl, BDIGIT, zl-yl); @@ -2059,6 +2083,14 @@ bary_mul_toom3_start(BDIGIT *zds, size_t https://github.com/ruby/ruby/blob/trunk/bignum.c#L2083 static void bary_mul(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl) { + if (xl < KARATSUBA_MUL_DIGITS) { + if (xds == yds && xl == yl) + bary_sq_fast(zds, zl, xds, xl); + else + bary_mul1(zds, zl, xds, xl, yds, yl); + return; + } + bary_mul_toom3_start(zds, zl, xds, xl, yds, yl, NULL, 0); } @@ -2275,28 +2307,45 @@ bigtrunc(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L2307 static inline VALUE bigfixize(VALUE x) { - long len = RBIGNUM_LEN(x); + size_t len = RBIGNUM_LEN(x); BDIGIT *ds = BDIGITS(x); +#if SIZEOF_BDIGITS < SIZEOF_LONG + unsigned long u; +#else + BDIGIT u; +#endif + + while (0 < len && ds[len-1] == 0) + len--; if (len == 0) return INT2FIX(0); - if (BIGSIZE(x) <= sizeof(long)) { - long num = 0; -#if SIZEOF_BDIGITS >= SIZEOF_LONG - num = (long)ds[0]; -#else - while (len--) { - num = (long)(BIGUP(num) + ds[len]); - } + +#if SIZEOF_BDIGITS < SIZEOF_LONG + if (sizeof(long)/SIZEOF_BDIGITS < len) + goto return_big; + else { + int i = (int)len; + u = 0; + while (i--) { + u = (long)(BIGUP(u) + ds[i]); + } + } +#else /* SIZEOF_BDIGITS >= SIZEOF_LONG */ + if (1 < len || LONG_MAX < ds[0]) + goto return_big; + else + u = ds[0]; #endif - if (num >= 0) { - if (RBIGNUM_SIGN(x)) { - if (POSFIXABLE(num)) return LONG2FIX(num); - } - else { - if (NEGFIXABLE(-num)) return LONG2FIX(-num); - } - } + + if (RBIGNUM_POSITIVE_P(x)) { + if (POSFIXABLE(u)) return LONG2FIX((long)u); } + else { + if (u <= -FIXNUM_MIN) return LONG2FIX(-(long)u); + } + + return_big: + rb_big_resize(x, len); return x; } @@ -2305,8 +2354,6 @@ bignorm(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L2354 { if (RB_TYPE_P(x, T_BIGNUM)) { x = bigfixize(x); - if (!FIXNUM_P(x)) - bigtrunc(x); } return x; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/