diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-06-11 06:06:01 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-06-11 06:06:01 +0000 |
commit | 1e7898d76a90befec85074f9d580531cf64ee9be (patch) | |
tree | 9f2bf529de22a6ef97bc0720acc9e0f9cc80bff5 /ext/bigdecimal/bigdecimal.c | |
parent | 3bb5d07486b3d06224481b459be5e814fe082b7a (diff) |
* ext/bigdecimal/bigdecimal.c (VpCtoV): big number should result
to infinite. backported from 1.9.
* ext/bigdecimal/bigdecimal.c (VpIsRoundMode): rounding mode
condition check updated. backported from 1.9.
* ext/bigdecimal/bigdecimal.c (VpPower): should handle NaN and
Inf. backported from 1.9.
* ext/bigdecimal/bigdecimal.c (BigDecimal_DoDivmod): divmod should
raise ZeroDivisionError. backported from 1.9.
* ext/bigdecimal/bigdecimal.c (BigDecimal_mode): should check
exception for VP_EXCEPTION_UNDERFLOW and VP_EXCEPTION_ZERODIVIDE.
backported from 1.9.
* ext/bigdecimal/bigdecimal.c (VpException): ditto.
* ext/bigdecimal/bigdecimal.h (VP_EXCEPTION_ZERODIVIDE): new error
code. backported from 1.9.
* ext/bigdecimal/bigdecimal.c (BigDecimal_div2, BigDecimal_round,
BigDecimal_truncate, BigDecimal_floor, BigDecimal_ceil): eagerly convert
bigdecimal to integer. backported from 1.9.
* ext/bigdecimal/bigdecimal.c (VpMult): free internal Real.
backported from 1.9.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@23664 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/bigdecimal/bigdecimal.c')
-rw-r--r-- | ext/bigdecimal/bigdecimal.c | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 60751a84b7..0257ca50a7 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -22,7 +22,10 @@ #include <float.h> #include <math.h> #include "math.h" -#include "version.h" + +#ifdef HAVE_IEEEFP_H +#include <ieeefp.h> +#endif /* #define ENABLE_NUMERIC_STRING */ @@ -411,11 +414,22 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self) VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_INFINITY): (fo&(~VP_EXCEPTION_INFINITY)))); } + fo = VpGetException(); if(f&VP_EXCEPTION_NaN) { VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_NaN): (fo&(~VP_EXCEPTION_NaN)))); } fo = VpGetException(); + if(f&VP_EXCEPTION_UNDERFLOW) { + VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_UNDERFLOW): + (fo&(~VP_EXCEPTION_UNDERFLOW)))); + } + fo = VpGetException(); + if(f&VP_EXCEPTION_ZERODIVIDE) { + VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_ZERODIVIDE): + (fo&(~VP_EXCEPTION_ZERODIVIDE)))); + } + fo = VpGetException(); return INT2FIX(fo); } if(VP_ROUND_MODE==f) { @@ -956,7 +970,9 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) if(VpIsNaN(a) || VpIsNaN(b)) goto NaN; if(VpIsInf(a) || VpIsInf(b)) goto NaN; - if(VpIsZero(b)) goto NaN; + if(VpIsZero(b)) { + rb_raise(rb_eZeroDivError, "divided by 0"); + } if(VpIsZero(a)) { GUARD_OBJ(c,VpCreateRbObject(1, "0")); GUARD_OBJ(d,VpCreateRbObject(1, "0")); @@ -1113,7 +1129,7 @@ BigDecimal_div2(int argc, VALUE *argv, VALUE self) Real *mod; obj = BigDecimal_DoDivmod(self,b,&div,&mod); if(obj!=(VALUE)0) return obj; - return ToValue(div); + return BigDecimal_to_i(ToValue(div)); } else { /* div in BigDecimal sense */ U_LONG ix = (U_LONG)GetPositiveInt(n); if(ix==0) return BigDecimal_div(self,b); @@ -1311,6 +1327,9 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSetPrecLimit(pl); VpActiveRound(c,a,sw,iLoc); + if (argc == 0) { + return BigDecimal_to_i(ToValue(c)); + } return ToValue(c); } @@ -1355,6 +1374,9 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self) GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSetPrecLimit(pl); VpActiveRound(c,a,VP_ROUND_DOWN,iLoc); /* 0: truncate */ + if (argc == 0) { + return BigDecimal_to_i(ToValue(c)); + } return ToValue(c); } @@ -1415,6 +1437,9 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self) GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSetPrecLimit(pl); VpActiveRound(c,a,VP_ROUND_FLOOR,iLoc); + if (argc == 0) { + return BigDecimal_to_i(ToValue(c)); + } return ToValue(c); } @@ -1459,6 +1484,9 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self) GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSetPrecLimit(pl); VpActiveRound(c,a,VP_ROUND_CEIL,iLoc); + if (argc == 0) { + return BigDecimal_to_i(ToValue(c)); + } return ToValue(c); } @@ -1741,7 +1769,7 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self) * * A limit of 0, the default, means no upper limit. * - * The limit specified by this method takes priority over any limit + * The limit specified by this method takes less priority over any limit * specified to instance methods such as ceil, floor, truncate, or round. */ static VALUE @@ -1846,7 +1874,7 @@ Init_bigdecimal(void) /* * 0x01: Determines what happens when the result of a computation is an - * underflow (a result too large to be represented). See BigDecimal.mode. + * overflow (a result too large to be represented). See BigDecimal.mode. */ rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW)); @@ -2097,9 +2125,9 @@ VpGetRoundMode(void) VP_EXPORT int VpIsRoundMode(unsigned long n) { - if(n==VP_ROUND_UP || n!=VP_ROUND_DOWN || - n==VP_ROUND_HALF_UP || n!=VP_ROUND_HALF_DOWN || - n==VP_ROUND_CEIL || n!=VP_ROUND_FLOOR || + if(n==VP_ROUND_UP || n==VP_ROUND_DOWN || + n==VP_ROUND_HALF_UP || n==VP_ROUND_HALF_DOWN || + n==VP_ROUND_CEIL || n==VP_ROUND_FLOOR || n==VP_ROUND_HALF_EVEN ) return 1; return 0; @@ -2219,18 +2247,12 @@ VpException(unsigned short f, const char *str,int always) switch(f) { /* - case VP_EXCEPTION_ZERODIVIDE: case VP_EXCEPTION_OVERFLOW: */ + case VP_EXCEPTION_ZERODIVIDE: case VP_EXCEPTION_INFINITY: - exc = rb_eFloatDomainError; - goto raise; case VP_EXCEPTION_NaN: - exc = rb_eFloatDomainError; - goto raise; case VP_EXCEPTION_UNDERFLOW: - exc = rb_eFloatDomainError; - goto raise; case VP_EXCEPTION_OP: exc = rb_eFloatDomainError; goto raise; @@ -3168,7 +3190,10 @@ VpMult(Real *c, Real *a, Real *b) /* set LHSV c info */ c->exponent = a->exponent; /* set exponent */ - if(!AddExponent(c,b->exponent)) return 0; + if(!AddExponent(c,b->exponent)) { + if(w) VpFree(c); + return 0; + } VpSetSign(c,VpGetSign(a)*VpGetSign(b)); /* set sign */ Carry = 0; nc = ind_c = MxIndAB; @@ -3939,7 +3964,12 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con es = e*((S_INT)BASE_FIG); e = e * 10 + exp_chr[i] - '0'; if(es>e*((S_INT)BASE_FIG)) { - return VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0); + VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0); + sign = 1; + if(int_chr[0] == '-') sign = -1; + if(signe > 0) VpSetInf(a, sign); + else VpSetZero(a, sign); + return 1; } ++i; } @@ -4627,8 +4657,20 @@ VpPower(Real *y, Real *x, S_INT n) } goto Exit; } - if(!VpIsDef(x)) { - VpSetNaN(y); /* Not sure !!! */ + if(VpIsNaN(x)) { + VpSetNaN(y); + goto Exit; + } + if(VpIsInf(x)) { + if(n==0) { + VpSetOne(y); + goto Exit; + } + if(n>0) { + VpSetInf(y, (n%2==0 || VpIsPosInf(x)) ? 1 : -1); + goto Exit; + } + VpSetZero(y, (n%2==0 || VpIsPosInf(x)) ? 1 : -1); goto Exit; } |