summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-13 03:05:38 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-13 03:05:38 +0000
commitae0134eeadfa885245668af5f61597922b83df3f (patch)
tree907ac5a4d90374c9aa73c15d6595ae80f0a6048d
parent74c4a0719c08347e8ca703a2565609100c705750 (diff)
merge revision(s) 15415:
* ext/bigdecimal/bigdecimal.c (BigDecimal_to_f): use strtod() for more precision. [ruby-talk:290296] * ext/bigdecimal/bigdecimal.c (BASE_FIG): made constant. * ext/bigdecimal/extconf.rb: ditto. [ruby-dev:33658] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_5@17129 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog9
-rw-r--r--ext/bigdecimal/bigdecimal.c59
-rw-r--r--ext/bigdecimal/extconf.rb10
-rw-r--r--version.h2
4 files changed, 52 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 8af94bf..28928a1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Jun 13 12:03:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_to_f): use strtod() for more
+ precision. [ruby-talk:290296]
+
+ * ext/bigdecimal/bigdecimal.c (BASE_FIG): made constant.
+
+ * ext/bigdecimal/extconf.rb: ditto. [ruby-dev:33658]
+
Fri Jun 13 11:58:34 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/irb.rb (IRB::Irb::eval_input): rescues Interrupt and other than
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index fd0cd65..6f215af 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -586,19 +586,22 @@ BigDecimal_to_f(VALUE self)
{
ENTER(1);
Real *p;
- double d, d2;
+ double d;
S_LONG e;
+ char *buf;
GUARD_OBJ(p,GetVpValue(self,1));
if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d);
+ buf = ALLOCA_N(char,(unsigned int)VpNumOfChars(p,"E"));
+ VpToString(p, buf, 0, 0);
errno = 0;
- d2 = pow(10.0,(double)e);
- if((errno == ERANGE && e>0) || (d2>1.0 && (fabs(d) > (DBL_MAX / d2)))) {
+ d = strtod(buf, 0);
+ if(errno == ERANGE) {
VpException(VP_EXCEPTION_OVERFLOW,"BigDecimal to Float conversion",0);
if(d>0.0) return rb_float_new(DBL_MAX);
else return rb_float_new(-DBL_MAX);
}
- return rb_float_new(d*d2);
+ return rb_float_new(d);
}
/* The coerce method provides support for Ruby type coercion. It is not
@@ -1062,7 +1065,7 @@ static VALUE
BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
{
VALUE f;
- Real *d,*rv;
+ Real *d,*rv=0;
f = BigDecimal_divremain(self,r,&d,&rv);
if(f!=(VALUE)0) return f;
return ToValue(rv);
@@ -1516,7 +1519,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
} else if(*psz=='+') {
fPlus = 2; psz++;
}
- while(ch=*psz++) {
+ while((ch=*psz++)!=0) {
if(ISSPACE(ch)) continue;
if(!ISDIGIT(ch)) {
if(ch=='F' || ch=='f') fmt = 1; /* F format */
@@ -1956,17 +1959,27 @@ static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
static U_LONG gnPrecLimit = 0; /* Global upper limit of the precision newly allocated */
static U_LONG gfRoundMode = VP_ROUND_HALF_UP; /* Mode for general rounding operation */
+#ifndef BASE_FIG
static U_LONG BASE_FIG = 4; /* =log10(BASE) */
static U_LONG BASE = 10000L; /* Base value(value must be 10**BASE_FIG) */
/* The value of BASE**2 + BASE must be represented */
/* within one U_LONG. */
static U_LONG HALF_BASE = 5000L;/* =BASE/2 */
-static S_LONG DBLE_FIG = 8; /* figure of double */
static U_LONG BASE1 = 1000L; /* =BASE/10 */
+#else
+#ifndef BASE
+#error BASE_FIG is defined but BASE is not
+#endif
+#define HALF_BASE (BASE/2)
+#define BASE1 (BASE/10)
+#endif
+#ifndef DBLE_FIG
+#define DBLE_FIG (DBL_DIG+1) /* figure of double */
+#endif
static Real *VpConstOne; /* constant 1.0 */
static Real *VpPt5; /* constant 0.5 */
-static U_LONG maxnr = 100; /* Maximum iterations for calcurating sqrt. */
+#define maxnr 100UL /* Maximum iterations for calcurating sqrt. */
/* used in VpSqrt() */
/* ETC */
@@ -2083,8 +2096,8 @@ VpSetRoundMode(unsigned long n)
* (to let the compiler know they may be changed in outside
* (... but not actually..)).
*/
-volatile double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
-volatile double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
+volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
+volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
static double
Zero(void)
{
@@ -2356,16 +2369,15 @@ VpNumOfChars(Real *vp,char *pszFmt)
VP_EXPORT U_LONG
VpInit(U_LONG BaseVal)
{
- U_LONG w;
- double v;
-
/* Setup +/- Inf NaN -0 */
VpGetDoubleNaN();
VpGetDoublePosInf();
VpGetDoubleNegInf();
VpGetDoubleNegZero();
+#ifndef BASE_FIG
if(BaseVal <= 0) {
+ U_LONG w;
/* Base <= 0, then determine Base by calcuration. */
BASE = 1;
while(
@@ -2382,6 +2394,8 @@ VpInit(U_LONG BaseVal)
BASE1 = BASE / 10;
BASE_FIG = 0;
while(BaseVal /= 10) ++BASE_FIG;
+#endif
+
/* Allocates Vp constants. */
VpConstOne = VpAlloc((U_LONG)1, "1");
VpPt5 = VpAlloc((U_LONG)1, ".5");
@@ -2390,15 +2404,6 @@ VpInit(U_LONG BaseVal)
gnAlloc = 0;
#endif /* _DEBUG */
- /* Determine # of digits available in one 'double'. */
-
- v = 1.0;
- DBLE_FIG = 0;
- while(v + 1.0 > 1.0) {
- ++DBLE_FIG;
- v /= 10;
- }
-
#ifdef _DEBUG
if(gfDebug) {
printf("VpInit: BaseVal = %lu\n", BaseVal);
@@ -2501,7 +2506,7 @@ VpAlloc(U_LONG mx, char *szVal)
psz = ALLOCA_N(char,strlen(szVal)+1);
i = 0;
ipn = 0;
- while(psz[i]=szVal[ipn]) {
+ while((psz[i]=szVal[ipn])!=0) {
if(ISDIGIT(psz[i])) ++ni;
if(psz[i]=='_') {
if(ni>0) {ipn++;continue;}
@@ -2544,7 +2549,7 @@ VpAlloc(U_LONG mx, char *szVal)
else if(szVal[i] == '+') ++i;
/* Skip digits */
ni = 0; /* digits in mantissa */
- while(v = szVal[i]) {
+ while((v = szVal[i]) != 0) {
if(!ISDIGIT(v)) break;
++i;
++ni;
@@ -2558,7 +2563,7 @@ VpAlloc(U_LONG mx, char *szVal)
if(szVal[i] == '.') { /* xxx. */
++i;
ipf = i;
- while(v = szVal[i]) { /* get fraction part. */
+ while((v = szVal[i]) != 0) { /* get fraction part. */
if(!ISDIGIT(v)) break;
++i;
++nf;
@@ -2576,7 +2581,7 @@ VpAlloc(U_LONG mx, char *szVal)
ipe = i;
v = szVal[i];
if((v == '-') ||(v == '+')) ++i;
- while(v=szVal[i]) {
+ while((v=szVal[i])!=0) {
if(!ISDIGIT(v)) break;
++i;
++ne;
@@ -4428,7 +4433,7 @@ VpLeftRound(Real *y, int f, int nf)
if(!VpHasVal(y)) return 0; /* Unable to round */
v = y->frac[0];
nf -= VpExponent(y)*BASE_FIG;
- while(v=v/10) nf--;
+ while((v /= 10) != 0) nf--;
nf += (BASE_FIG-1);
return VpMidRound(y,f,nf);
}
diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb
index a68a656..864aaad 100644
--- a/ext/bigdecimal/extconf.rb
+++ b/ext/bigdecimal/extconf.rb
@@ -1,2 +1,12 @@
require 'mkmf'
+
+base_fig = 0
+src = ("(BASE > 0) && "
+ "(BASE * (BASE+1)) > BASE && "
+ "(BASE * (BASE+1)) / BASE == (BASE+1)")
+while try_static_assert(src, nil, "-DBASE=10#{'0'*base_fig}UL")
+ base_fig += 1
+end
+$defs << "-DBASE=1#{'0'*base_fig}UL" << "-DBASE_FIG=#{base_fig}"
+
create_makefile('bigdecimal')
diff --git a/version.h b/version.h
index 30e7f31..87c8eef 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@
#define RUBY_RELEASE_DATE "2008-06-13"
#define RUBY_VERSION_CODE 185
#define RUBY_RELEASE_CODE 20080613
-#define RUBY_PATCHLEVEL 171
+#define RUBY_PATCHLEVEL 172
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8