summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2006-05-16 23:24:08 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2006-05-16 23:24:08 +0000
commit7b724e750f55227e455a618f044e057920b5f671 (patch)
tree5ca7774f0f6950d814a213e2dbe5fa373d43205b /util.c
parentc606447c00af509f26f4feec95332f832bcc4935 (diff)
* util.c (ruby_strtod): try to reduce errors using powersOf10
table. [ruby-dev:28644] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10160 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'util.c')
-rw-r--r--util.c52
1 files changed, 31 insertions, 21 deletions
diff --git a/util.c b/util.c
index 9424fa58e3..6d1c9bc496 100644
--- a/util.c
+++ b/util.c
@@ -684,6 +684,18 @@ ruby_getcwd()
#define MDMINEXPT DBL_MIN_EXP
#define MDMAXEXPT DBL_MAX_EXP
+static double powersOf10[] = { /* Table giving binary powers of 10. Entry */
+ 10.0, /* is 10^2^i. Used to convert decimal */
+ 100.0, /* exponents into floating-point numbers. */
+ 1.0e4,
+ 1.0e8,
+ 1.0e16,
+ 1.0e32,
+ 1.0e64,
+ 1.0e128,
+ 1.0e256
+};
+
/*
*----------------------------------------------------------------------
*
@@ -724,7 +736,7 @@ ruby_strtod(string, endPtr)
* address here. */
{
int sign, expSign = Qfalse;
- double fraction = 0.0, dblExp;
+ double fraction = 0.0, dblExp, *d;
register const char *p;
register int c;
int exp = 0; /* Exponent read from "EX" field. */
@@ -891,18 +903,17 @@ ruby_strtod(string, endPtr)
else {
expSign = Qfalse;
}
- dblExp = 10.0;
- while (exp) {
+ dblExp = 1.0;
+ for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
if (exp & 01) {
- if (expSign) {
- frac1 /= dblExp;
- }
- else {
- frac1 *= dblExp;
- }
+ dblExp *= *d;
}
- exp >>= 1;
- dblExp *= dblExp;
+ }
+ if (expSign) {
+ frac1 /= dblExp;
+ }
+ else {
+ frac1 *= dblExp;
}
exp = fracExp;
if (exp < 0) {
@@ -912,18 +923,17 @@ ruby_strtod(string, endPtr)
else {
expSign = Qfalse;
}
- dblExp = 10.0;
- while (exp) {
+ dblExp = 1.0;
+ for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
if (exp & 01) {
- if (expSign) {
- frac2 /= dblExp;
- }
- else {
- frac2 *= dblExp;
- }
+ dblExp *= *d;
}
- exp >>= 1;
- dblExp *= dblExp;
+ }
+ if (expSign) {
+ frac2 /= dblExp;
+ }
+ else {
+ frac2 *= dblExp;
}
fraction = frac1 + frac2;
}