* 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/trunk@15415 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0e66903fca
commit
a424741c8e
@ -1,3 +1,12 @@
|
|||||||
|
Sat Feb 9 17:51:24 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]
|
||||||
|
|
||||||
Sat Feb 9 12:06:45 2008 Tanaka Akira <akr@fsij.org>
|
Sat Feb 9 12:06:45 2008 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* missing/tgamma.c (tgamma): add error check.
|
* missing/tgamma.c (tgamma): add error check.
|
||||||
|
@ -585,19 +585,22 @@ BigDecimal_to_f(VALUE self)
|
|||||||
{
|
{
|
||||||
ENTER(1);
|
ENTER(1);
|
||||||
Real *p;
|
Real *p;
|
||||||
double d, d2;
|
double d;
|
||||||
S_LONG e;
|
S_LONG e;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
GUARD_OBJ(p,GetVpValue(self,1));
|
GUARD_OBJ(p,GetVpValue(self,1));
|
||||||
if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d);
|
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;
|
errno = 0;
|
||||||
d2 = pow(10.0,(double)e);
|
d = strtod(buf, 0);
|
||||||
if((errno == ERANGE && e>0) || (d2>1.0 && (fabs(d) > (DBL_MAX / d2)))) {
|
if(errno == ERANGE) {
|
||||||
VpException(VP_EXCEPTION_OVERFLOW,"BigDecimal to Float conversion",0);
|
VpException(VP_EXCEPTION_OVERFLOW,"BigDecimal to Float conversion",0);
|
||||||
if(d>0.0) return rb_float_new(DBL_MAX);
|
if(d>0.0) return rb_float_new(DBL_MAX);
|
||||||
else 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
|
/* The coerce method provides support for Ruby type coercion. It is not
|
||||||
@ -1050,7 +1053,7 @@ static VALUE
|
|||||||
BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
|
BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
|
||||||
{
|
{
|
||||||
VALUE f;
|
VALUE f;
|
||||||
Real *d,*rv;
|
Real *d,*rv=0;
|
||||||
f = BigDecimal_divremain(self,r,&d,&rv);
|
f = BigDecimal_divremain(self,r,&d,&rv);
|
||||||
if(f!=(VALUE)0) return f;
|
if(f!=(VALUE)0) return f;
|
||||||
return ToValue(rv);
|
return ToValue(rv);
|
||||||
@ -1504,7 +1507,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
|
|||||||
} else if(*psz=='+') {
|
} else if(*psz=='+') {
|
||||||
fPlus = 2; psz++;
|
fPlus = 2; psz++;
|
||||||
}
|
}
|
||||||
while(ch=*psz++) {
|
while((ch=*psz++)!=0) {
|
||||||
if(ISSPACE(ch)) continue;
|
if(ISSPACE(ch)) continue;
|
||||||
if(!ISDIGIT(ch)) {
|
if(!ISDIGIT(ch)) {
|
||||||
if(ch=='F' || ch=='f') fmt = 1; /* F format */
|
if(ch=='F' || ch=='f') fmt = 1; /* F format */
|
||||||
@ -1961,17 +1964,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 gnPrecLimit = 0; /* Global upper limit of the precision newly allocated */
|
||||||
static U_LONG gfRoundMode = VP_ROUND_HALF_UP; /* Mode for general rounding operation */
|
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_FIG = 4; /* =log10(BASE) */
|
||||||
static U_LONG BASE = 10000L; /* Base value(value must be 10**BASE_FIG) */
|
static U_LONG BASE = 10000L; /* Base value(value must be 10**BASE_FIG) */
|
||||||
/* The value of BASE**2 + BASE must be represented */
|
/* The value of BASE**2 + BASE must be represented */
|
||||||
/* within one U_LONG. */
|
/* within one U_LONG. */
|
||||||
static U_LONG HALF_BASE = 5000L;/* =BASE/2 */
|
static U_LONG HALF_BASE = 5000L;/* =BASE/2 */
|
||||||
static S_LONG DBLE_FIG = 8; /* figure of double */
|
|
||||||
static U_LONG BASE1 = 1000L; /* =BASE/10 */
|
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 *VpConstOne; /* constant 1.0 */
|
||||||
static Real *VpPt5; /* constant 0.5 */
|
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() */
|
/* used in VpSqrt() */
|
||||||
|
|
||||||
/* ETC */
|
/* ETC */
|
||||||
@ -2088,8 +2101,8 @@ VpSetRoundMode(unsigned long n)
|
|||||||
* (to let the compiler know they may be changed in outside
|
* (to let the compiler know they may be changed in outside
|
||||||
* (... but not actually..)).
|
* (... but not actually..)).
|
||||||
*/
|
*/
|
||||||
volatile double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
|
volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
|
||||||
volatile double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
|
volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
|
||||||
static double
|
static double
|
||||||
Zero(void)
|
Zero(void)
|
||||||
{
|
{
|
||||||
@ -2361,16 +2374,15 @@ VpNumOfChars(Real *vp,const char *pszFmt)
|
|||||||
VP_EXPORT U_LONG
|
VP_EXPORT U_LONG
|
||||||
VpInit(U_LONG BaseVal)
|
VpInit(U_LONG BaseVal)
|
||||||
{
|
{
|
||||||
U_LONG w;
|
|
||||||
double v;
|
|
||||||
|
|
||||||
/* Setup +/- Inf NaN -0 */
|
/* Setup +/- Inf NaN -0 */
|
||||||
VpGetDoubleNaN();
|
VpGetDoubleNaN();
|
||||||
VpGetDoublePosInf();
|
VpGetDoublePosInf();
|
||||||
VpGetDoubleNegInf();
|
VpGetDoubleNegInf();
|
||||||
VpGetDoubleNegZero();
|
VpGetDoubleNegZero();
|
||||||
|
|
||||||
|
#ifndef BASE_FIG
|
||||||
if(BaseVal <= 0) {
|
if(BaseVal <= 0) {
|
||||||
|
U_LONG w;
|
||||||
/* Base <= 0, then determine Base by calcuration. */
|
/* Base <= 0, then determine Base by calcuration. */
|
||||||
BASE = 1;
|
BASE = 1;
|
||||||
while(
|
while(
|
||||||
@ -2387,6 +2399,8 @@ VpInit(U_LONG BaseVal)
|
|||||||
BASE1 = BASE / 10;
|
BASE1 = BASE / 10;
|
||||||
BASE_FIG = 0;
|
BASE_FIG = 0;
|
||||||
while(BaseVal /= 10) ++BASE_FIG;
|
while(BaseVal /= 10) ++BASE_FIG;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Allocates Vp constants. */
|
/* Allocates Vp constants. */
|
||||||
VpConstOne = VpAlloc((U_LONG)1, "1");
|
VpConstOne = VpAlloc((U_LONG)1, "1");
|
||||||
VpPt5 = VpAlloc((U_LONG)1, ".5");
|
VpPt5 = VpAlloc((U_LONG)1, ".5");
|
||||||
@ -2395,15 +2409,6 @@ VpInit(U_LONG BaseVal)
|
|||||||
gnAlloc = 0;
|
gnAlloc = 0;
|
||||||
#endif /* _DEBUG */
|
#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
|
#ifdef _DEBUG
|
||||||
if(gfDebug) {
|
if(gfDebug) {
|
||||||
printf("VpInit: BaseVal = %lu\n", BaseVal);
|
printf("VpInit: BaseVal = %lu\n", BaseVal);
|
||||||
@ -2506,7 +2511,7 @@ VpAlloc(U_LONG mx, const char *szVal)
|
|||||||
psz = ALLOCA_N(char,strlen(szVal)+1);
|
psz = ALLOCA_N(char,strlen(szVal)+1);
|
||||||
i = 0;
|
i = 0;
|
||||||
ipn = 0;
|
ipn = 0;
|
||||||
while(psz[i]=szVal[ipn]) {
|
while((psz[i]=szVal[ipn])!=0) {
|
||||||
if(ISDIGIT(psz[i])) ++ni;
|
if(ISDIGIT(psz[i])) ++ni;
|
||||||
if(psz[i]=='_') {
|
if(psz[i]=='_') {
|
||||||
if(ni>0) {ipn++;continue;}
|
if(ni>0) {ipn++;continue;}
|
||||||
@ -2549,7 +2554,7 @@ VpAlloc(U_LONG mx, const char *szVal)
|
|||||||
else if(szVal[i] == '+') ++i;
|
else if(szVal[i] == '+') ++i;
|
||||||
/* Skip digits */
|
/* Skip digits */
|
||||||
ni = 0; /* digits in mantissa */
|
ni = 0; /* digits in mantissa */
|
||||||
while(v = szVal[i]) {
|
while((v = szVal[i]) != 0) {
|
||||||
if(!ISDIGIT(v)) break;
|
if(!ISDIGIT(v)) break;
|
||||||
++i;
|
++i;
|
||||||
++ni;
|
++ni;
|
||||||
@ -2563,7 +2568,7 @@ VpAlloc(U_LONG mx, const char *szVal)
|
|||||||
if(szVal[i] == '.') { /* xxx. */
|
if(szVal[i] == '.') { /* xxx. */
|
||||||
++i;
|
++i;
|
||||||
ipf = i;
|
ipf = i;
|
||||||
while(v = szVal[i]) { /* get fraction part. */
|
while((v = szVal[i]) != 0) { /* get fraction part. */
|
||||||
if(!ISDIGIT(v)) break;
|
if(!ISDIGIT(v)) break;
|
||||||
++i;
|
++i;
|
||||||
++nf;
|
++nf;
|
||||||
@ -2581,7 +2586,7 @@ VpAlloc(U_LONG mx, const char *szVal)
|
|||||||
ipe = i;
|
ipe = i;
|
||||||
v = szVal[i];
|
v = szVal[i];
|
||||||
if((v == '-') ||(v == '+')) ++i;
|
if((v == '-') ||(v == '+')) ++i;
|
||||||
while(v=szVal[i]) {
|
while((v=szVal[i])!=0) {
|
||||||
if(!ISDIGIT(v)) break;
|
if(!ISDIGIT(v)) break;
|
||||||
++i;
|
++i;
|
||||||
++ne;
|
++ne;
|
||||||
@ -4439,7 +4444,7 @@ VpLeftRound(Real *y, int f, int nf)
|
|||||||
if(!VpHasVal(y)) return 0; /* Unable to round */
|
if(!VpHasVal(y)) return 0; /* Unable to round */
|
||||||
v = y->frac[0];
|
v = y->frac[0];
|
||||||
nf -= VpExponent(y)*BASE_FIG;
|
nf -= VpExponent(y)*BASE_FIG;
|
||||||
while(v=v/10) nf--;
|
while((v /= 10) != 0) nf--;
|
||||||
nf += (BASE_FIG-1);
|
nf += (BASE_FIG-1);
|
||||||
return VpMidRound(y,f,nf);
|
return VpMidRound(y,f,nf);
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,12 @@
|
|||||||
require 'mkmf'
|
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')
|
create_makefile('bigdecimal')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user