1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* bignum.c (bary_cmp): Extracted from rb_big_cmp.

(power_cache_get_power): Change n1 argument (number of digits) to
  power_level which is just passed to power_cache_get_power0.
  (big2str_karatsuba): Ditto.
  (rb_big2str1): Calculate the initial power_level.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42285 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2013-07-31 13:42:22 +00:00
parent 806dd30fe2
commit 621d2b3d6c
2 changed files with 68 additions and 35 deletions

View file

@ -1,3 +1,11 @@
Wed Jul 31 22:36:21 2013 Tanaka Akira <akr@fsij.org>
* bignum.c (bary_cmp): Extracted from rb_big_cmp.
(power_cache_get_power): Change n1 argument (number of digits) to
power_level which is just passed to power_cache_get_power0.
(big2str_karatsuba): Ditto.
(rb_big2str1): Calculate the initial power_level.
Wed Jul 31 22:04:36 2013 Kouhei Sutou <kou@cozmixng.org> Wed Jul 31 22:04:36 2013 Kouhei Sutou <kou@cozmixng.org>
* test/rexml/test_notationdecl_parsetest.rb: Fix a typo. * test/rexml/test_notationdecl_parsetest.rb: Fix a typo.

View file

@ -481,6 +481,26 @@ maxpow_in_bdigit(int base, int *exp_ret)
return maxpow; return maxpow;
} }
static int
bary_cmp(const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
while (0 < xn && xds[xn-1] == 0)
xn--;
while (0 < yn && yds[yn-1] == 0)
yn--;
if (xn < yn)
return -1;
if (xn > yn)
return 1;
while (xn-- && xds[xn] == yds[xn])
;
if (xn == (size_t)-1)
return 0;
return xds[xn] < yds[xn] ? -1 : 1;
}
static BDIGIT static BDIGIT
bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift) bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift)
{ {
@ -4125,19 +4145,13 @@ power_cache_get_power0(int base, int i)
} }
static VALUE static VALUE
power_cache_get_power(int base, long n1, long* m1) power_cache_get_power(int base, int power_level, long *numdigits_ret)
{ {
int i, m; VALUE power;
VALUE t; power = power_cache_get_power0(base, power_level);
if (numdigits_ret)
if (n1 <= KARATSUBA_BIG2STR_DIGITS) *numdigits_ret = KARATSUBA_BIG2STR_DIGITS * (1 << power_level);
rb_bug("n1 > KARATSUBA_BIG2STR_DIGITS"); return power;
m = bitsize(n1-1); /* ceil(log2(n1)) */
if (m1) *m1 = 1 << m; /* smallest x which n1 <= x and x is a power of 2. */
i = m - LOG2_KARATSUBA_BIG2STR_DIGITS;
t = power_cache_get_power0(base, i);
return t;
} }
/* big2str_muraken_find_n1 /* big2str_muraken_find_n1
@ -4232,7 +4246,7 @@ big2str_orig(struct big2str_struct *b2s, VALUE x, char* ptr, long len, int trim)
static long static long
big2str_karatsuba(struct big2str_struct *b2s, VALUE x, char* ptr, big2str_karatsuba(struct big2str_struct *b2s, VALUE x, char* ptr,
long n1, long len, int trim) int power_level, long len, int trim)
{ {
long lh, ll, m1; long lh, ll, m1;
VALUE b, q, r; VALUE b, q, r;
@ -4245,18 +4259,18 @@ big2str_karatsuba(struct big2str_struct *b2s, VALUE x, char* ptr,
} }
} }
if (n1 <= KARATSUBA_BIG2STR_DIGITS) { if (power_level == 0) {
return big2str_orig(b2s, x, ptr, len, trim); return big2str_orig(b2s, x, ptr, len, trim);
} }
b = power_cache_get_power(b2s->base, n1, &m1); b = power_cache_get_power(b2s->base, power_level, &m1);
bigdivmod(x, b, &q, &r); bigdivmod(x, b, &q, &r);
rb_obj_hide(q); rb_obj_hide(q);
rb_obj_hide(r); rb_obj_hide(r);
lh = big2str_karatsuba(b2s, q, ptr, (len - m1)/2, lh = big2str_karatsuba(b2s, q, ptr, power_level-1,
len - m1, trim); len - m1, trim);
rb_big_resize(q, 0); rb_big_resize(q, 0);
ll = big2str_karatsuba(b2s, r, ptr + lh, m1/2, ll = big2str_karatsuba(b2s, r, ptr + lh, power_level-1,
m1, !lh && trim); m1, !lh && trim);
rb_big_resize(r, 0); rb_big_resize(r, 0);
@ -4299,9 +4313,11 @@ rb_big2str1(VALUE x, int base, int trim)
{ {
int off; int off;
VALUE ss, xx; VALUE ss, xx;
long n1, n2, len; long n2, len;
char* ptr; char* ptr;
struct big2str_struct b2s_data; struct big2str_struct b2s_data;
int power_level;
VALUE power;
if (FIXNUM_P(x)) { if (FIXNUM_P(x)) {
return rb_fix2str(x, base); return rb_fix2str(x, base);
@ -4320,21 +4336,38 @@ rb_big2str1(VALUE x, int base, int trim)
return big2str_base_powerof2(x, (size_t)n2, base, trim); return big2str_base_powerof2(x, (size_t)n2, base, trim);
} }
n1 = (n2 + 1) / 2;
ss = rb_usascii_str_new(0, n2 + 1); /* plus one for sign */ ss = rb_usascii_str_new(0, n2 + 1); /* plus one for sign */
ptr = RSTRING_PTR(ss); ptr = RSTRING_PTR(ss);
ptr[0] = RBIGNUM_SIGN(x) ? '+' : '-'; ptr[0] = RBIGNUM_SIGN(x) ? '+' : '-';
power_level = 0;
power = power_cache_get_power0(base, power_level);
while (power_level < MAX_BIG2STR_TABLE_ENTRIES &&
RBIGNUM_LEN(power) <= (RBIGNUM_LEN(x)+1)/2) {
power_level++;
power = power_cache_get_power0(base, power_level);
}
assert(power_level != MAX_BIG2STR_TABLE_ENTRIES);
if (FIX2LONG(bary_cmp(BDIGITS(x), RBIGNUM_LEN(x), BDIGITS(power), RBIGNUM_LEN(power))) < 0) {
power_level--;
#ifndef NDEBUG
if (0 <= power_level) {
VALUE power0 = power_cache_get_power0(base, power_level);
assert(FIX2LONG(bary_cmp(BDIGITS(x), RBIGNUM_LEN(x), BDIGITS(power0), RBIGNUM_LEN(power0))) >= 0);
}
#endif
}
b2s_data.base = base; b2s_data.base = base;
b2s_data.hbase = maxpow_in_bdigit(base, &b2s_data.hbase_numdigits); b2s_data.hbase = maxpow_in_bdigit(base, &b2s_data.hbase_numdigits);
off = !(trim && RBIGNUM_SIGN(x)); /* erase plus sign if trim */ off = !(trim && RBIGNUM_SIGN(x)); /* erase plus sign if trim */
xx = rb_big_clone(x); xx = rb_big_clone(x);
RBIGNUM_SET_SIGN(xx, 1); RBIGNUM_SET_SIGN(xx, 1);
if (n1 <= KARATSUBA_BIG2STR_DIGITS) { if (power_level < 0) {
len = off + big2str_orig(&b2s_data, xx, ptr + off, n2, trim); len = off + big2str_orig(&b2s_data, xx, ptr + off, n2, trim);
} }
else { else {
len = off + big2str_karatsuba(&b2s_data, xx, ptr + off, n1, len = off + big2str_karatsuba(&b2s_data, xx, ptr + off, power_level,
n2, trim); n2, trim);
} }
rb_big_resize(xx, 0); rb_big_resize(xx, 0);
@ -4733,8 +4766,7 @@ rb_integer_float_eq(VALUE x, VALUE y)
VALUE VALUE
rb_big_cmp(VALUE x, VALUE y) rb_big_cmp(VALUE x, VALUE y)
{ {
long xlen = RBIGNUM_LEN(x); int cmp;
BDIGIT *xds, *yds;
switch (TYPE(y)) { switch (TYPE(y)) {
case T_FIXNUM: case T_FIXNUM:
@ -4753,19 +4785,12 @@ rb_big_cmp(VALUE x, VALUE y)
if (RBIGNUM_SIGN(x) > RBIGNUM_SIGN(y)) return INT2FIX(1); if (RBIGNUM_SIGN(x) > RBIGNUM_SIGN(y)) return INT2FIX(1);
if (RBIGNUM_SIGN(x) < RBIGNUM_SIGN(y)) return INT2FIX(-1); if (RBIGNUM_SIGN(x) < RBIGNUM_SIGN(y)) return INT2FIX(-1);
if (xlen < RBIGNUM_LEN(y))
return (RBIGNUM_SIGN(x)) ? INT2FIX(-1) : INT2FIX(1);
if (xlen > RBIGNUM_LEN(y))
return (RBIGNUM_SIGN(x)) ? INT2FIX(1) : INT2FIX(-1);
xds = BDIGITS(x); cmp = bary_cmp(BDIGITS(x), RBIGNUM_LEN(x), BDIGITS(y), RBIGNUM_LEN(y));
yds = BDIGITS(y); if (RBIGNUM_SIGN(x))
return INT2FIX(cmp);
while (xlen-- && (xds[xlen]==yds[xlen])); else
if (-1 == xlen) return INT2FIX(0); return INT2FIX(-cmp);
return (xds[xlen] > yds[xlen]) ?
(RBIGNUM_SIGN(x) ? INT2FIX(1) : INT2FIX(-1)) :
(RBIGNUM_SIGN(x) ? INT2FIX(-1) : INT2FIX(1));
} }
enum big_op_t { enum big_op_t {