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

* bignum.c (rb_cstr_to_inum): Use BDIGIT_DBL to collect adjacent digits.

(BDIGIT_DBL_MAX): New macro.
  (maxpow_in_bdigit_dbl): New function.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2013-07-02 11:52:13 +00:00
parent 9487404c62
commit 2ade221827
2 changed files with 42 additions and 15 deletions

View file

@ -1,3 +1,9 @@
Tue Jul 2 20:25:04 2013 Tanaka Akira <akr@fsij.org>
* bignum.c (rb_cstr_to_inum): Use BDIGIT_DBL to collect adjacent digits.
(BDIGIT_DBL_MAX): New macro.
(maxpow_in_bdigit_dbl): New function.
Tue Jul 2 17:23:33 2013 Shugo Maeda <shugo@ruby-lang.org>
* doc/syntax/refinements.rdoc: add description of Module#using and

View file

@ -61,6 +61,7 @@ static VALUE big_three = Qnil;
#define BIGDN(x) RSHIFT((x),BITSPERDIG)
#define BIGLO(x) ((BDIGIT)((x) & BDIGMAX))
#define BDIGMAX ((BDIGIT)(BIGRAD-1))
#define BDIGIT_DBL_MAX (~(BDIGIT_DBL)0)
#if SIZEOF_BDIGITS == 2
# define swap_bdigit(x) swap16(x)
@ -220,6 +221,23 @@ static int nlz(BDIGIT x) { return nlz128((uint128_t)x); }
32 - nlz32(x))
#endif
static BDIGIT_DBL
maxpow_in_bdigit_dbl(int base, int *exp_ret)
{
BDIGIT_DBL maxpow;
int exponent;
maxpow = base;
exponent = 1;
while (maxpow <= BDIGIT_DBL_MAX / base) {
maxpow *= base;
exponent++;
}
*exp_ret = exponent;
return maxpow;
}
static int
bary_zero_p(BDIGIT *xds, size_t nx)
{
@ -2071,31 +2089,33 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
}
}
else {
BDIGIT hbase;
VALUE hbasev;
int hbase_numdigits;
int digits_per_bdigits_dbl;
BDIGIT_DBL power;
VALUE powerv;
int j;
size_t num_bdigits;
size_t unit;
VALUE tmpu = 0, tmpv = 0;
BDIGIT *uds, *vds, *tds;
calc_hbase(base, &hbase, &hbase_numdigits);
power = maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
size = p - buf;
num_bdigits = roomof(size, hbase_numdigits);
num_bdigits = roomof(size, digits_per_bdigits_dbl)*2;
uds = ALLOCV_N(BDIGIT, tmpu, num_bdigits);
vds = ALLOCV_N(BDIGIT, tmpv, num_bdigits);
hbasev = bignew(1, 1);
BDIGITS(hbasev)[0] = hbase;
powerv = bignew(2, 1);
BDIGITS(powerv)[0] = BIGLO(power);
BDIGITS(powerv)[1] = BIGDN(power);
i = 0;
while (buf < p) {
int m;
BDIGIT d = 0;
if (hbase_numdigits <= p - buf) {
m = hbase_numdigits;
BDIGIT_DBL d = 0;
if (digits_per_bdigits_dbl <= p - buf) {
m = digits_per_bdigits_dbl;
}
else {
m = (int)(p - buf);
@ -2104,23 +2124,24 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
for (j = 0; j < m; j++) {
d = d * base + p[j];
}
uds[i++] = d;
uds[i++] = BIGLO(d);
uds[i++] = BIGDN(d);
}
for (unit = 1; unit < num_bdigits; unit *= 2) {
for (unit = 2; unit < num_bdigits; unit *= 2) {
for (i = 0; i < num_bdigits; i += unit*2) {
if (2*unit <= num_bdigits - i) {
bary_mul2(vds+i, unit*2, BDIGITS(hbasev), RBIGNUM_LEN(hbasev), uds+i+unit, unit);
bary_mul2(vds+i, unit*2, BDIGITS(powerv), RBIGNUM_LEN(powerv), uds+i+unit, unit);
bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
}
else if (unit <= num_bdigits - i) {
bary_mul2(vds+i, num_bdigits-i, BDIGITS(hbasev), RBIGNUM_LEN(hbasev), uds+i+unit, num_bdigits-(i+unit));
bary_mul2(vds+i, num_bdigits-i, BDIGITS(powerv), RBIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
}
else {
MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
}
}
hbasev = bigtrunc(bigmul0(hbasev, hbasev));
powerv = bigtrunc(bigmul0(powerv, powerv));
tds = vds;
vds = uds;
uds = tds;