mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* bignum.c (big2dbl): more precise conversion at edge cases.
[ruby-dev:34195] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15881 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
05da1ec22d
commit
e31a69562e
2 changed files with 58 additions and 4 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
Tue Apr 1 16:40:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* bignum.c (big2dbl): more precise conversion at edge cases.
|
||||||
|
[ruby-dev:34195]
|
||||||
|
|
||||||
Tue Apr 1 14:43:38 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Tue Apr 1 14:43:38 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* configure.in: get rid of empty expansion.
|
* configure.in: get rid of empty expansion.
|
||||||
|
|
55
bignum.c
55
bignum.c
|
@ -1133,16 +1133,65 @@ rb_dbl2big(double d)
|
||||||
return bignorm(dbl2big(d));
|
return bignorm(dbl2big(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nlz(BDIGIT x)
|
||||||
|
{
|
||||||
|
BDIGIT y;
|
||||||
|
int n = BITSPERDIG;
|
||||||
|
#if BITSPERDIG > 64
|
||||||
|
y = x >> 64; if (y) {n -= 64; x = y;}
|
||||||
|
#endif
|
||||||
|
#if BITSPERDIG > 32
|
||||||
|
y = x >> 32; if (y) {n -= 32; x = y;}
|
||||||
|
#endif
|
||||||
|
#if BITSPERDIG > 16
|
||||||
|
y = x >> 16; if (y) {n -= 16; x = y;}
|
||||||
|
#endif
|
||||||
|
y = x >> 8; if (y) {n -= 8; x = y;}
|
||||||
|
y = x >> 4; if (y) {n -= 4; x = y;}
|
||||||
|
y = x >> 2; if (y) {n -= 2; x = y;}
|
||||||
|
y = x >> 1; if (y) {return n - 2;}
|
||||||
|
return n - x;
|
||||||
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
big2dbl(VALUE x)
|
big2dbl(VALUE x)
|
||||||
{
|
{
|
||||||
double d = 0.0;
|
double d = 0.0;
|
||||||
long i = RBIGNUM_LEN(x);
|
long i = RBIGNUM_LEN(x), lo = 0, bits;
|
||||||
BDIGIT *ds = BDIGITS(x);
|
BDIGIT *ds = BDIGITS(x), dl;
|
||||||
|
|
||||||
while (i--) {
|
if (i) {
|
||||||
|
bits = i * BITSPERDIG - nlz(ds[i-1]);
|
||||||
|
if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
|
||||||
|
d = HUGE_VAL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (bits > DBL_MANT_DIG+1)
|
||||||
|
lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
|
||||||
|
else
|
||||||
|
bits = 0;
|
||||||
|
while (--i > lo) {
|
||||||
d = ds[i] + BIGRAD*d;
|
d = ds[i] + BIGRAD*d;
|
||||||
}
|
}
|
||||||
|
dl = ds[i];
|
||||||
|
if (bits && (dl & (1UL << (bits %= BITSPERDIG)))) {
|
||||||
|
int carry = dl & ~(~0UL << bits);
|
||||||
|
if (!carry) {
|
||||||
|
while (i-- > 0) {
|
||||||
|
if ((carry = ds[i]) != 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (carry) {
|
||||||
|
dl &= ~0UL << bits;
|
||||||
|
dl += 1UL << bits;
|
||||||
|
if (!dl) d += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d = dl + BIGRAD*d;
|
||||||
|
if (lo) d = ldexp(d, lo * BITSPERDIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!RBIGNUM_SIGN(x)) d = -d;
|
if (!RBIGNUM_SIGN(x)) d = -d;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue