ruby-changes:11933
From: matz <ko1@a...>
Date: Thu, 28 May 2009 01:17:12 +0900 (JST)
Subject: [ruby-changes:11933] Ruby:r23596 (trunk): * bignum.c (bigand_int): new function to calculate bignum and
matz 2009-05-28 01:16:57 +0900 (Thu, 28 May 2009) New Revision: 23596 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=23596 Log: * bignum.c (bigand_int): new function to calculate bignum and fixnum without allocating internal bignum. * bignum.c (bigor_int): ditto. * bignum.c (bigxor_int): ditto. * bignum.c (bigand_int): even less object allocation. Modified files: trunk/ChangeLog trunk/bignum.c Index: ChangeLog =================================================================== --- ChangeLog (revision 23595) +++ ChangeLog (revision 23596) @@ -2,6 +2,17 @@ * parse.y (struct parser_params): lex_gets_ptr should be long. +Wed May 27 18:00:15 2009 Yukihiro Matsumoto <matz@r...> + + * bignum.c (bigand_int): new function to calculate bignum and + fixnum without allocating internal bignum. + + * bignum.c (bigor_int): ditto. + + * bignum.c (bigxor_int): ditto. + + * bignum.c (bigand_int): even less object allocation. + Wed May 27 14:08:39 2009 Yukihiro Matsumoto <matz@r...> * st.c (st_insert2): new function with processing new key, Index: bignum.c =================================================================== --- bignum.c (revision 23595) +++ bignum.c (revision 23596) @@ -2530,7 +2530,7 @@ return DBL2NUM(pow(rb_big2dbl(x), d)); } -static VALUE +static inline VALUE bit_coerce(VALUE x) { while (!FIXNUM_P(x) && TYPE(x) != T_BIGNUM) { @@ -2542,6 +2542,50 @@ return x; } +static VALUE +bigand_int(VALUE x, long y) +{ + VALUE z; + BDIGIT *xds, *zds; + long xn, zn; + long i; + char sign; + + if (y == 0) return INT2FIX(0); + sign = (y > 0); + xds = BDIGITS(x); + zn = xn = RBIGNUM_LEN(x); +#if SIZEOF_BDIGITS == SIZEOF_LONG + if (sign) { + y &= xds[0]; + return LONG2NUM(y); + } +#endif + + z = bignew(zn, RBIGNUM_SIGN(x) || sign); + zds = BDIGITS(z); + +#if SIZEOF_BDIGITS == SIZEOF_LONG + i = 1; + zds[0] = xds[0] & y; +#else + { + BDIGIT_DBL num = y; + + for (i=0; i<(int)(sizeof(y)/sizeof(BDIGIT)); i++) { + zds[i] = xds[i] & BIGLO(num); + num = BIGDN(num); + } + } +#endif + while (i < xn) { + zds[i] = sign?0:xds[i]; + i++; + } + if (!RBIGNUM_SIGN(z)) get2comp(z); + return bignorm(z); +} + /* * call-seq: * big & numeric => integer @@ -2559,17 +2603,17 @@ x = xx; y = bit_coerce(yy); + if (!RBIGNUM_SIGN(x)) { + x = rb_big_clone(x); + get2comp(x); + } if (FIXNUM_P(y)) { - y = rb_int2big(FIX2LONG(y)); + return bigand_int(x, FIX2LONG(y)); } if (!RBIGNUM_SIGN(y)) { y = rb_big_clone(y); get2comp(y); } - if (!RBIGNUM_SIGN(x)) { - x = rb_big_clone(x); - get2comp(x); - } if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) { l1 = RBIGNUM_LEN(y); l2 = RBIGNUM_LEN(x); @@ -2597,6 +2641,42 @@ return bignorm(z); } +static VALUE +bigor_int(VALUE x, long y) +{ + VALUE z; + BDIGIT *xds, *zds; + long xn, zn; + long i; + char sign; + + sign = (y >= 0); + xds = BDIGITS(x); + zn = xn = RBIGNUM_LEN(x); + z = bignew(zn, RBIGNUM_SIGN(x) && sign); + zds = BDIGITS(z); + +#if SIZEOF_BDIGITS == SIZEOF_LONG + i = 1; + zds[0] = xds[0] | y; +#else + { + BDIGIT_DBL num = y; + + for (i=0; i<(int)(sizeof(y)/sizeof(BDIGIT)); i++) { + zds[i] = xds[i] | BIGLO(num); + num = BIGDN(num); + } + } +#endif + while (i < xn) { + zds[i] = sign?xds[i]:(BDIGIT)(BIGRAD-1); + i++; + } + if (!RBIGNUM_SIGN(z)) get2comp(z); + return bignorm(z); +} + /* * call-seq: * big | numeric => integer @@ -2614,18 +2694,18 @@ x = xx; y = bit_coerce(yy); + + if (!RBIGNUM_SIGN(x)) { + x = rb_big_clone(x); + get2comp(x); + } if (FIXNUM_P(y)) { - y = rb_int2big(FIX2LONG(y)); + return bigor_int(x, FIX2LONG(y)); } - if (!RBIGNUM_SIGN(y)) { y = rb_big_clone(y); get2comp(y); } - if (!RBIGNUM_SIGN(x)) { - x = rb_big_clone(x); - get2comp(x); - } if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) { l1 = RBIGNUM_LEN(y); l2 = RBIGNUM_LEN(x); @@ -2650,10 +2730,44 @@ zds[i] = sign?ds2[i]:(BDIGIT)(BIGRAD-1); } if (!RBIGNUM_SIGN(z)) get2comp(z); + return bignorm(z); +} +static VALUE +bigxor_int(VALUE x, long y) +{ + VALUE z; + BDIGIT *xds, *zds; + long xn, zn; + long i; + char sign; + + sign = (y >= 0) ? 1 : 0; + xds = BDIGITS(x); + zn = xn = RBIGNUM_LEN(x); + z = bignew(zn, !(RBIGNUM_SIGN(x) ^ sign)); + zds = BDIGITS(z); + +#if SIZEOF_BDIGITS == SIZEOF_LONG + i = 1; + zds[0] = xds[0] ^ y; +#else + { + BDIGIT_DBL num = y; + + for (i=0; i<(int)(sizeof(y)/sizeof(BDIGIT)); i++) { + zds[i] = xds[i] ^ BIGLO(num); + num = BIGDN(num); + } + } +#endif + while (i < xn) { + zds[i] = sign?xds[i]:~xds[i]; + i++; + } + if (!RBIGNUM_SIGN(z)) get2comp(z); return bignorm(z); } - /* * call-seq: * big ^ numeric => integer @@ -2672,18 +2786,18 @@ x = xx; y = bit_coerce(yy); + + if (!RBIGNUM_SIGN(x)) { + x = rb_big_clone(x); + get2comp(x); + } if (FIXNUM_P(y)) { - y = rb_int2big(FIX2LONG(y)); + return bigxor_int(x, FIX2LONG(y)); } - if (!RBIGNUM_SIGN(y)) { y = rb_big_clone(y); get2comp(y); } - if (!RBIGNUM_SIGN(x)) { - x = rb_big_clone(x); - get2comp(x); - } if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) { l1 = RBIGNUM_LEN(y); l2 = RBIGNUM_LEN(x); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/