From 80ad1473cfefea77b4964d285fcae8ff5a4cac4b Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 27 May 2009 16:16:57 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 11 ++++ bignum.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 146 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index eb831b1fb9..9a187b7e33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,17 @@ Wed May 27 23:00:38 2009 Nobuyoshi Nakada * parse.y (struct parser_params): lex_gets_ptr should be long. +Wed May 27 18:00:15 2009 Yukihiro Matsumoto + + * 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 * st.c (st_insert2): new function with processing new key, diff --git a/bignum.c b/bignum.c index ab7b5f7553..398d963aea 100644 --- a/bignum.c +++ b/bignum.c @@ -2530,7 +2530,7 @@ rb_big_pow(VALUE x, VALUE y) 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 @@ bit_coerce(VALUE x) 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 @@ rb_big_and(VALUE xx, VALUE yy) 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 @@ rb_big_and(VALUE xx, VALUE yy) 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 @@ rb_big_or(VALUE xx, VALUE yy) x = xx; y = bit_coerce(yy); - if (FIXNUM_P(y)) { - y = rb_int2big(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 (FIXNUM_P(y)) { + return bigor_int(x, FIX2LONG(y)); + } + if (!RBIGNUM_SIGN(y)) { + y = rb_big_clone(y); + get2comp(y); + } if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) { l1 = RBIGNUM_LEN(y); l2 = RBIGNUM_LEN(x); @@ -2650,10 +2730,44 @@ rb_big_or(VALUE xx, VALUE yy) 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 @@ rb_big_xor(VALUE xx, VALUE yy) x = xx; y = bit_coerce(yy); - if (FIXNUM_P(y)) { - y = rb_int2big(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 (FIXNUM_P(y)) { + return bigxor_int(x, FIX2LONG(y)); + } + if (!RBIGNUM_SIGN(y)) { + y = rb_big_clone(y); + get2comp(y); + } if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) { l1 = RBIGNUM_LEN(y); l2 = RBIGNUM_LEN(x);