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

* util.c (ruby_strtod): should not cut off 18 digits for no

reason.  [ruby-core:07796]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10115 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2006-04-28 01:58:01 +00:00
parent f2fb05ffd6
commit 15a5fba74f
2 changed files with 58 additions and 64 deletions

View file

@ -1,3 +1,8 @@
Fri Apr 28 10:53:16 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
Thu Apr 27 01:38:10 2006 Yukihiro Matsumoto <matz@ruby-lang.org> Thu Apr 27 01:38:10 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* array.c (rb_ary_fill): internalize local variable "beg" to * array.c (rb_ary_fill): internalize local variable "beg" to

95
util.c
View file

@ -15,6 +15,7 @@
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <math.h>
#ifdef _WIN32 #ifdef _WIN32
#include "missing/file.h" #include "missing/file.h"
@ -679,22 +680,8 @@ ruby_getcwd()
* *
*/ */
#define TRUE 1
#define FALSE 0
static int MDMINEXPT = -323; static int MDMINEXPT = -323;
static int MDMAXEXPT = 309; static int MDMAXEXPT = 309;
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
};
/* /*
*---------------------------------------------------------------------- *----------------------------------------------------------------------
@ -735,8 +722,8 @@ ruby_strtod(string, endPtr)
char **endPtr; /* If non-NULL, store terminating character's char **endPtr; /* If non-NULL, store terminating character's
* address here. */ * address here. */
{ {
int sign, expSign = FALSE; int sign, expSign = Qfalse;
double fraction, dblExp, *d; double fraction = 0.0, dblExp;
register const char *p; register const char *p;
register int c; register int c;
int exp = 0; /* Exponent read from "EX" field. */ int exp = 0; /* Exponent read from "EX" field. */
@ -750,8 +737,8 @@ ruby_strtod(string, endPtr)
* case, fracExp is incremented one for each * case, fracExp is incremented one for each
* dropped digit. */ * dropped digit. */
int mantSize = 0; /* Number of digits in mantissa. */ int mantSize = 0; /* Number of digits in mantissa. */
int hasPoint = FALSE; /* Decimal point exists. */ int hasPoint = Qfalse; /* Decimal point exists. */
int hasDigit = FALSE; /* I or F exists. */ int hasDigit = Qfalse; /* I or F exists. */
const char *pMant; /* Temporarily holds location of mantissa const char *pMant; /* Temporarily holds location of mantissa
* in string. */ * in string. */
const char *pExp; /* Temporarily holds location of exponent const char *pExp; /* Temporarily holds location of exponent
@ -767,14 +754,14 @@ ruby_strtod(string, endPtr)
p += 1; p += 1;
} }
if (*p == '-') { if (*p == '-') {
sign = TRUE; sign = Qtrue;
p += 1; p += 1;
} }
else { else {
if (*p == '+') { if (*p == '+') {
p += 1; p += 1;
} }
sign = FALSE; sign = Qfalse;
} }
/* /*
@ -787,7 +774,7 @@ ruby_strtod(string, endPtr)
if (c != '.' || hasPoint) { if (c != '.' || hasPoint) {
break; break;
} }
hasPoint = TRUE; hasPoint = Qtrue;
} }
else { else {
if (hasPoint) { /* already in fractional part */ if (hasPoint) { /* already in fractional part */
@ -800,7 +787,7 @@ ruby_strtod(string, endPtr)
mantSize += 1; mantSize += 1;
pMant = p; pMant = p;
} }
hasDigit = TRUE; hasDigit = Qtrue;
} }
} }
@ -824,7 +811,7 @@ ruby_strtod(string, endPtr)
p = string; p = string;
} }
else { else {
int frac1, frac2; double frac1, frac2;
frac1 = 0; frac1 = 0;
for ( ; mantSize > 9; mantSize -= 1) { for ( ; mantSize > 9; mantSize -= 1) {
c = *p; c = *p;
@ -854,14 +841,14 @@ ruby_strtod(string, endPtr)
if ((*p == 'E') || (*p == 'e')) { if ((*p == 'E') || (*p == 'e')) {
p += 1; p += 1;
if (*p == '-') { if (*p == '-') {
expSign = TRUE; expSign = Qtrue;
p += 1; p += 1;
} }
else { else {
if (*p == '+') { if (*p == '+') {
p += 1; p += 1;
} }
expSign = FALSE; expSign = Qfalse;
} }
if (ISDIGIT(*p)) { if (ISDIGIT(*p)) {
do { do {
@ -888,55 +875,57 @@ ruby_strtod(string, endPtr)
* fraction. * fraction.
*/ */
if (exp >= MDMAXEXPT - 18) { if (exp >= MDMAXEXPT) {
exp = MDMAXEXPT;
errno = ERANGE; errno = ERANGE;
return HUGE_VAL * (sign ? -1.0 : 1.0);
} }
else if (exp < MDMINEXPT + 18) { else if (exp < MDMINEXPT) {
exp = MDMINEXPT;
errno = ERANGE; errno = ERANGE;
return 0.0 * (sign ? -1.0 : 1.0);
} }
if (frac1 > 0) {
fracExp = exp; fracExp = exp;
exp += 9; exp += 9;
if (exp < 0) { if (exp < 0) {
expSign = TRUE; expSign = Qtrue;
exp = -exp; exp = -exp;
} }
else { else {
expSign = FALSE; expSign = Qfalse;
} }
dblExp = 1.0; dblExp = 10.0;
for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { while (exp) {
if (exp & 01) { if (exp & 1) {
dblExp *= *d; if (expSign)
frac1 /= dblExp;
else
frac1 *= dblExp;
} }
exp >>= 1;
dblExp *= dblExp;
} }
if (expSign) { fraction = frac1;
fraction = frac1 / dblExp;
} }
else {
fraction = frac1 * dblExp;
}
exp = fracExp;
if (exp < 0) { if (exp < 0) {
expSign = TRUE; expSign = Qtrue;
exp = -exp; exp = -exp;
} }
else { else {
expSign = FALSE; expSign = Qfalse;
} }
dblExp = 1.0; dblExp = 10.0;
for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { while (exp)
if (exp & 01) { {
dblExp *= *d; if (exp & 1) {
if (expSign)
frac2 /= dblExp;
else
frac2 *= dblExp;
} }
exp >>= 1;
dblExp *= dblExp;
} }
if (expSign) { fraction += frac2;
fraction += frac2 / dblExp;
}
else {
fraction += frac2 * dblExp;
}
} }
if (endPtr != NULL) { if (endPtr != NULL) {