summaryrefslogtreecommitdiff
path: root/ext/bigdecimal/bigdecimal.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/bigdecimal/bigdecimal.c')
-rw-r--r--ext/bigdecimal/bigdecimal.c294
1 files changed, 189 insertions, 105 deletions
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 7df56e3aa1..dd8f0f9d85 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -62,6 +62,7 @@ static ID id_ceil;
static ID id_floor;
static ID id_to_r;
static ID id_eq;
+static ID id_half;
/* MACRO's to guard objects from GC by keeping them in stack */
#define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
@@ -126,6 +127,9 @@ rb_rational_den(VALUE rat)
}
#endif
+#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
+#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
+
/*
* ================== Ruby Interface part ==========================
*/
@@ -240,9 +244,8 @@ again:
if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
d = RFLOAT_VALUE(v);
if (!isfinite(d)) {
- pv = VpCreateRbObject(prec, NULL);
- pv->sign = isnan(d) ? VP_SIGN_NaN :
- d > 0 ? VP_SIGN_POSITIVE_INFINITE : VP_SIGN_NEGATIVE_FINITE;
+ pv = VpCreateRbObject(1, NULL);
+ VpDtoV(pv, d);
return pv;
}
if (d != 0.0) {
@@ -385,9 +388,9 @@ BigDecimal_hash(VALUE self)
* Method used to provide marshalling support.
*
* inf = BigDecimal.new('Infinity')
- * #=> #<BigDecimal:1e16fa8,'Infinity',9(9)>
+ * #=> Infinity
* BigDecimal._load(inf._dump)
- * #=> #<BigDecimal:1df8dc8,'Infinity',9(9)>
+ * #=> Infinity
*
* See the Marshal module.
*/
@@ -441,6 +444,54 @@ BigDecimal_load(VALUE self, VALUE str)
}
static unsigned short
+check_rounding_mode_option(VALUE const opts)
+{
+ VALUE mode;
+ char const *s;
+ long l;
+
+ assert(RB_TYPE_P(opts, T_HASH));
+
+ if (NIL_P(opts))
+ goto noopt;
+
+ mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
+ if (mode == Qundef)
+ goto noopt;
+
+ if (SYMBOL_P(mode))
+ mode = rb_sym2str(mode);
+ else if (!RB_TYPE_P(mode, T_STRING)) {
+ VALUE str_mode = rb_check_string_type(mode);
+ if (NIL_P(str_mode)) goto invalid;
+ mode = str_mode;
+ }
+ s = RSTRING_PTR(mode);
+ l = RSTRING_LEN(mode);
+ switch (l) {
+ case 2:
+ if (strncasecmp(s, "up", 2) == 0)
+ return VP_ROUND_HALF_UP;
+ break;
+ case 4:
+ if (strncasecmp(s, "even", 4) == 0)
+ return VP_ROUND_HALF_EVEN;
+ else if (strncasecmp(s, "down", 4) == 0)
+ return VP_ROUND_HALF_DOWN;
+ default:
+ break;
+ }
+ invalid:
+ if (NIL_P(mode))
+ rb_raise(rb_eArgError, "invalid rounding mode: nil");
+ else
+ rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
+
+ noopt:
+ return VpGetRoundMode();
+}
+
+static unsigned short
check_rounding_mode(VALUE const v)
{
unsigned short sw;
@@ -562,7 +613,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
fo = VpSetRoundMode(sw);
return INT2FIX(fo);
}
- rb_raise(rb_eTypeError, "first argument for BigDecimal#mode invalid");
+ rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
return Qnil;
}
@@ -682,7 +733,7 @@ static VALUE BigDecimal_split(VALUE self);
/* Returns the value as an Integer.
*
- * If the BigNumber is infinity or NaN, raises FloatDomainError.
+ * If the BigDecimal is infinity or NaN, raises FloatDomainError.
*/
static VALUE
BigDecimal_to_i(VALUE self)
@@ -707,7 +758,7 @@ BigDecimal_to_i(VALUE self)
VALUE ret;
ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
- if (VpGetSign(p) < 0) {
+ if (BIGDECIMAL_NEGATIVE_P(p)) {
numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
}
if (dpower < 0) {
@@ -762,17 +813,17 @@ BigDecimal_to_f(VALUE self)
overflow:
VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
- if (p->sign >= 0)
- return rb_float_new(VpGetDoublePosInf());
- else
+ if (BIGDECIMAL_NEGATIVE_P(p))
return rb_float_new(VpGetDoubleNegInf());
+ else
+ return rb_float_new(VpGetDoublePosInf());
underflow:
VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
- if (p->sign >= 0)
- return rb_float_new(0.0);
- else
+ if (BIGDECIMAL_NEGATIVE_P(p))
return rb_float_new(-0.0);
+ else
+ return rb_float_new(0.0);
}
@@ -1720,11 +1771,21 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
iLoc = 0;
break;
case 1:
- iLoc = NUM2INT(vLoc);
+ if (RB_TYPE_P(vLoc, T_HASH)) {
+ sw = check_rounding_mode_option(vLoc);
+ }
+ else {
+ iLoc = NUM2INT(vLoc);
+ }
break;
case 2:
iLoc = NUM2INT(vLoc);
- sw = check_rounding_mode(vRound);
+ if (RB_TYPE_P(vRound, T_HASH)) {
+ sw = check_rounding_mode_option(vRound);
+ }
+ else {
+ sw = check_rounding_mode(vRound);
+ }
break;
default:
break;
@@ -2066,7 +2127,7 @@ BigDecimal_exponent(VALUE self)
* values in angle brackets with a leading #:
*
* BigDecimal.new("1234.5678").inspect
- * #=> "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
+ * #=> "0.12345678e4"
*
* The first part is the address, the second is the value as a string, and
* the final part ss(mm) is the current number of significant digits and the
@@ -2077,23 +2138,16 @@ BigDecimal_inspect(VALUE self)
{
ENTER(5);
Real *vp;
- volatile VALUE obj;
+ volatile VALUE str;
size_t nc;
- char *psz, *tmp;
GUARD_OBJ(vp, GetVpValue(self, 1));
nc = VpNumOfChars(vp, "E");
- nc += (nc + 9) / 10;
-
- obj = rb_str_new(0, nc+256);
- psz = RSTRING_PTR(obj);
- sprintf(psz, "#<BigDecimal:%"PRIxVALUE",'", self);
- tmp = psz + strlen(psz);
- VpToString(vp, tmp, 10, 0);
- tmp += strlen(tmp);
- sprintf(tmp, "',%"PRIuSIZE"(%"PRIuSIZE")>", VpPrec(vp)*VpBaseFig(), VpMaxPrec(vp)*VpBaseFig());
- rb_str_resize(obj, strlen(psz));
- return obj;
+
+ str = rb_str_new(0, nc);
+ VpToString(vp, RSTRING_PTR(str), 0, 0);
+ rb_str_resize(str, strlen(RSTRING_PTR(str)));
+ return str;
}
static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
@@ -2303,7 +2357,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
if (is_negative(vexp)) {
y = VpCreateRbObject(n, "#0");
RB_GC_GUARD(y->obj);
- if (VpGetSign(x) < 0) {
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
if (is_integer(vexp)) {
if (is_even(vexp)) {
/* (-0) ** (-even_integer) -> Infinity */
@@ -2342,7 +2396,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
if (VpIsInf(x)) {
if (is_negative(vexp)) {
- if (VpGetSign(x) < 0) {
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
if (is_integer(vexp)) {
if (is_even(vexp)) {
/* (-Infinity) ** (-even_integer) -> +0 */
@@ -2364,7 +2418,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
}
else {
y = VpCreateRbObject(n, "0#");
- if (VpGetSign(x) < 0) {
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
if (is_integer(vexp)) {
if (is_even(vexp)) {
VpSetPosInf(y);
@@ -2405,7 +2459,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
}
return ToValue(y);
}
- else if (VpGetSign(x) < 0 && is_even(vexp)) {
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
return ToValue(VpCreateRbObject(n, "-0"));
}
else {
@@ -2423,7 +2477,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
}
return ToValue(y);
}
- else if (VpGetSign(x) < 0 && is_even(vexp)) {
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
return ToValue(VpCreateRbObject(n, "-0"));
}
else {
@@ -2545,6 +2599,7 @@ BigDecimal_new(int argc, VALUE *argv)
size_t mf;
VALUE nFig;
VALUE iniValue;
+ double d;
if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
mf = 0;
@@ -2566,6 +2621,12 @@ BigDecimal_new(int argc, VALUE *argv)
return GetVpValue(iniValue, 1);
case T_FLOAT:
+ d = RFLOAT_VALUE(iniValue);
+ if (!isfinite(d)) {
+ Real *pv = VpCreateRbObject(1, NULL);
+ VpDtoV(pv, d);
+ return pv;
+ }
if (mf > DBL_DIG+1) {
rb_raise(rb_eArgError, "precision too large.");
}
@@ -2766,7 +2827,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
case T_DATA:
if (!is_kind_of_BigDecimal(x)) break;
vx = DATA_PTR(x);
- negative = VpGetSign(vx) < 0;
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
nan = VpIsNaN(vx);
break;
@@ -2819,7 +2880,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
x = vx->obj;
n = prec + rmpd_double_figures();
- negative = VpGetSign(vx) < 0;
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
if (negative) {
VpSetSign(vx, 1);
}
@@ -2905,7 +2966,7 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
if (!is_kind_of_BigDecimal(x)) break;
vx = DATA_PTR(x);
zero = VpIsZero(vx);
- negative = VpGetSign(vx) < 0;
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
nan = VpIsNaN(vx);
break;
@@ -3208,7 +3269,7 @@ Init_bigdecimal(void)
rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
/*
- * 0x01: Determines what happens when a division by zero is performed.
+ * 0x10: Determines what happens when a division by zero is performed.
* See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
@@ -3350,6 +3411,7 @@ Init_bigdecimal(void)
id_floor = rb_intern_const("floor");
id_to_r = rb_intern_const("to_r");
id_eq = rb_intern_const("==");
+ id_half = rb_intern_const("half");
}
/*
@@ -3377,7 +3439,14 @@ static Real *VpPt5; /* constant 0.5 */
#define MemCmp(x,y,z) memcmp(x,y,z)
#define StrCmp(x,y) strcmp(x,y)
-static int VpIsDefOP(Real *c,Real *a,Real *b,int sw);
+enum op_sw {
+ OP_SW_ADD = 1, /* + */
+ OP_SW_SUB, /* - */
+ OP_SW_MULT, /* * */
+ OP_SW_DIV /* / */
+};
+
+static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
static int AddExponent(Real *a, SIGNED_VALUE n);
static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
@@ -3404,7 +3473,7 @@ VpMemAlloc(size_t mb)
return p;
}
- VP_EXPORT void *
+VP_EXPORT void *
VpMemRealloc(void *ptr, size_t mb)
{
void *p = xrealloc(ptr, mb);
@@ -3664,7 +3733,7 @@ VpException(unsigned short f, const char *str,int always)
/* Throw exception or returns 0,when resulting c is Inf or NaN */
/* sw=1:+ 2:- 3:* 4:/ */
static int
-VpIsDefOP(Real *c,Real *a,Real *b,int sw)
+VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
{
if (VpIsNaN(a) || VpIsNaN(b)) {
/* at least a or b is NaN */
@@ -3675,7 +3744,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
if (VpIsInf(a)) {
if (VpIsInf(b)) {
switch(sw) {
- case 1: /* + */
+ case OP_SW_ADD: /* + */
if (VpGetSign(a) == VpGetSign(b)) {
VpSetInf(c, VpGetSign(a));
goto Inf;
@@ -3684,7 +3753,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
VpSetNaN(c);
goto NaN;
}
- case 2: /* - */
+ case OP_SW_SUB: /* - */
if (VpGetSign(a) != VpGetSign(b)) {
VpSetInf(c, VpGetSign(a));
goto Inf;
@@ -3693,12 +3762,10 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
VpSetNaN(c);
goto NaN;
}
- break;
- case 3: /* * */
+ case OP_SW_MULT: /* * */
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
goto Inf;
- break;
- case 4: /* / */
+ case OP_SW_DIV: /* / */
VpSetNaN(c);
goto NaN;
}
@@ -3707,18 +3774,18 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
}
/* Inf op Finite */
switch(sw) {
- case 1: /* + */
- case 2: /* - */
+ case OP_SW_ADD: /* + */
+ case OP_SW_SUB: /* - */
VpSetInf(c, VpGetSign(a));
break;
- case 3: /* * */
+ case OP_SW_MULT: /* * */
if (VpIsZero(b)) {
VpSetNaN(c);
goto NaN;
}
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
break;
- case 4: /* / */
+ case OP_SW_DIV: /* / */
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
}
goto Inf;
@@ -3726,20 +3793,20 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
if (VpIsInf(b)) {
switch(sw) {
- case 1: /* + */
+ case OP_SW_ADD: /* + */
VpSetInf(c, VpGetSign(b));
break;
- case 2: /* - */
+ case OP_SW_SUB: /* - */
VpSetInf(c, -VpGetSign(b));
break;
- case 3: /* * */
+ case OP_SW_MULT: /* * */
if (VpIsZero(a)) {
VpSetNaN(c);
goto NaN;
}
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
break;
- case 4: /* / */
+ case OP_SW_DIV: /* / */
VpSetZero(c, VpGetSign(a)*VpGetSign(b));
}
goto Inf;
@@ -3747,7 +3814,13 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
return 1; /* Results OK */
Inf:
- return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
+ if (VpIsPosInf(c)) {
+ return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
+ }
+ else {
+ return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
+ }
+
NaN:
return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
}
@@ -3894,7 +3967,8 @@ overflow:
VP_EXPORT Real *
VpAlloc(size_t mx, const char *szVal)
{
- size_t i, ni, ipn, ipf, nf, ipe, ne, nalloc;
+ const char *orig_szVal = szVal;
+ size_t i, ni, ipn, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
char v, *psz;
int sign=1;
Real *vp = NULL;
@@ -3929,6 +4003,26 @@ VpAlloc(size_t mx, const char *szVal)
return vp;
}
+ /* Check on Inf & NaN */
+ if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
+ vp = VpAllocReal(1);
+ vp->MaxPrec = 1; /* set max precision */
+ VpSetPosInf(vp);
+ return vp;
+ }
+ if (StrCmp(szVal, SZ_NINF) == 0) {
+ vp = VpAllocReal(1);
+ vp->MaxPrec = 1; /* set max precision */
+ VpSetNegInf(vp);
+ return vp;
+ }
+ if (StrCmp(szVal, SZ_NaN) == 0) {
+ vp = VpAllocReal(1);
+ vp->MaxPrec = 1; /* set max precision */
+ VpSetNaN(vp);
+ return vp;
+ }
+
/* Skip all '_' after digit: 2006-6-30 */
ni = 0;
buf = rb_str_tmp_new(strlen(szVal) + 1);
@@ -3954,26 +4048,6 @@ VpAlloc(size_t mx, const char *szVal)
}
szVal = psz;
- /* Check on Inf & NaN */
- if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
- vp = VpAllocReal(1);
- vp->MaxPrec = 1; /* set max precision */
- VpSetPosInf(vp);
- return vp;
- }
- if (StrCmp(szVal, SZ_NINF) == 0) {
- vp = VpAllocReal(1);
- vp->MaxPrec = 1; /* set max precision */
- VpSetNegInf(vp);
- return vp;
- }
- if (StrCmp(szVal, SZ_NaN) == 0) {
- vp = VpAllocReal(1);
- vp->MaxPrec = 1; /* set max precision */
- VpSetNaN(vp);
- return vp;
- }
-
/* check on number szVal[] */
ipn = i = 0;
if (szVal[i] == '-') { sign=-1; ++i; }
@@ -3989,9 +4063,12 @@ VpAlloc(size_t mx, const char *szVal)
ipf = 0;
ipe = 0;
ne = 0;
+ dot_seen = 0;
+ exp_seen = 0;
if (v) {
/* other than digit nor \0 */
if (szVal[i] == '.') { /* xxx. */
+ dot_seen = 1;
++i;
ipf = i;
while ((v = szVal[i]) != 0) { /* get fraction part. */
@@ -4007,6 +4084,7 @@ VpAlloc(size_t mx, const char *szVal)
break;
case 'e': case 'E':
case 'd': case 'D':
+ exp_seen = 1;
++i;
ipe = i;
v = szVal[i];
@@ -4021,6 +4099,11 @@ VpAlloc(size_t mx, const char *szVal)
break;
}
}
+ if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
+ VALUE str = rb_str_new2(orig_szVal);
+ rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
+ }
+
nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
/* units for szVal[] */
if (mx == 0) mx = 1;
@@ -4107,7 +4190,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
}
#endif /* BIGDECIMAL_DEBUG */
- if (!VpIsDefOP(c, a, b, (operation > 0) ? 1 : 2)) return 0; /* No significant digits */
+ if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
/* check if a or b is zero */
if (VpIsZero(a)) {
@@ -4563,7 +4646,7 @@ VpMult(Real *c, Real *a, Real *b)
}
#endif /* BIGDECIMAL_DEBUG */
- if (!VpIsDefOP(c, a, b, 3)) return 0; /* No significant digit */
+ if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */
if (VpIsZero(a) || VpIsZero(b)) {
/* at least a or b is zero */
@@ -4675,7 +4758,7 @@ Exit:
/*
* c = a / b, remainder = r
*/
- VP_EXPORT size_t
+VP_EXPORT size_t
VpDivd(Real *c, Real *r, Real *a, Real *b)
{
size_t word_a, word_b, word_c, word_r;
@@ -4693,14 +4776,14 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
#endif /*BIGDECIMAL_DEBUG */
VpSetNaN(r);
- if (!VpIsDefOP(c, a, b, 4)) goto Exit;
+ if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit;
if (VpIsZero(a) && VpIsZero(b)) {
VpSetNaN(c);
- return VpException(VP_EXCEPTION_NaN, "(VpDivd) 0/0 not defined(NaN)", 0);
+ return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
}
if (VpIsZero(b)) {
VpSetInf(c, VpGetSign(a) * VpGetSign(b));
- return VpException(VP_EXCEPTION_ZERODIVIDE, "(VpDivd) Divide by zero", 0);
+ return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0);
}
if (VpIsZero(a)) {
/* numerator a is zero */
@@ -5053,7 +5136,7 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
nc += 9;
}
else if (!VpIsZero(a)) {
- if (VpGetSign(a) < 0) {
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
fprintf(fp, "-");
++nc;
}
@@ -5142,7 +5225,7 @@ VpFormatSt(char *psz, size_t fFmt)
if (!ch) break;
if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
if (ch == '.') { nf = 0; continue; }
- if (ch == 'E') break;
+ if (ch == 'E' || ch == 'e') break;
if (++nf > fFmt) {
memmove(psz + i + 1, psz + i, ie - i + 1);
@@ -5191,7 +5274,7 @@ VpSzMantissa(Real *a,char *psz)
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
if (!VpIsZero(a)) {
- if (VpGetSign(a) < 0) *psz++ = '-';
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
n = a->Prec;
for (i = 0; i < n; ++i) {
m = BASE1;
@@ -5265,7 +5348,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
- if (VpGetSign(a) < 0) *psz++ = '-';
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
else if (fPlus == 1) *psz++ = ' ';
else if (fPlus == 2) *psz++ = '+';
@@ -5296,7 +5379,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
while (psz[-1] == '0') {
*(--psz) = 0;
}
- sprintf(psz, "E%"PRIdSIZE, ex);
+ sprintf(psz, "e%"PRIdSIZE, ex);
if (fFmt) VpFormatSt(pszSav, fFmt);
}
@@ -5311,7 +5394,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
if (VpToSpecialString(a, psz, fPlus)) return;
- if (VpGetSign(a) < 0) *psz++ = '-';
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
else if (fPlus == 1) *psz++ = ' ';
else if (fPlus == 2) *psz++ = '+';
@@ -5733,21 +5816,22 @@ VpSqrt(Real *y, Real *x)
ssize_t nr;
double val;
- /* Zero, NaN or Infinity ? */
- if (!VpHasVal(x)) {
- if (VpIsZero(x) || VpGetSign(x) > 0) {
- VpAsgn(y,x,1);
- goto Exit;
- }
- VpSetNaN(y);
- return VpException(VP_EXCEPTION_OP, "(VpSqrt) SQRT(NaN or negative value)", 0);
+ /* Zero or +Infinity ? */
+ if (VpIsZero(x) || VpIsPosInf(x)) {
+ VpAsgn(y,x,1);
goto Exit;
}
/* Negative ? */
- if (VpGetSign(x) < 0) {
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
+ VpSetNaN(y);
+ return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0);
+ }
+
+ /* NaN ? */
+ if (VpIsNaN(x)) {
VpSetNaN(y);
- return VpException(VP_EXCEPTION_OP, "(VpSqrt) SQRT(negative value)", 0);
+ return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0);
}
/* One ? */
@@ -5938,10 +6022,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
if (v > 5 || (v == 5 && fracf_1further)) ++div;
break;
case VP_ROUND_CEIL:
- if (fracf && (VpGetSign(y) > 0)) ++div;
+ if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
break;
case VP_ROUND_FLOOR:
- if (fracf && (VpGetSign(y) < 0)) ++div;
+ if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div;
break;
case VP_ROUND_HALF_EVEN: /* Banker's rounding */
if (v > 5) ++div;
@@ -6060,10 +6144,10 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
if (v >= 6) f = 1;
break;
case VP_ROUND_CEIL:
- if (v && (VpGetSign(c) > 0)) f = 1;
+ if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
break;
case VP_ROUND_FLOOR:
- if (v && (VpGetSign(c) < 0)) f = 1;
+ if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1;
break;
case VP_ROUND_HALF_EVEN: /* Banker's rounding */
/* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
@@ -6200,7 +6284,7 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
/* abs(x) = 1 */
VpSetOne(y);
- if (VpGetSign(x) > 0) goto Exit;
+ if (BIGDECIMAL_POSITIVE_P(x)) goto Exit;
if ((n % 2) == 0) goto Exit;
VpSetSign(y, -1);
goto Exit;