summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--bignum.c51
2 files changed, 42 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 197e7a360a..94f33d6e11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/bignum.c b/bignum.c
index 8324280f24..1377f55a6c 100644
--- a/bignum.c
+++ b/bignum.c
@@ -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;