10#ifdef BIGDECIMAL_DEBUG
11# define BIGDECIMAL_ENABLE_VPRINT 1
16#ifndef BIGDECIMAL_DEBUG
35#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
37 (a) == -1 ? (b) < -(max) : \
39 ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
40 ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
41#define SIGNED_VALUE_MAX INTPTR_MAX
42#define SIGNED_VALUE_MIN INTPTR_MIN
43#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
48static ID id_BigDecimal_exception_mode;
49static ID id_BigDecimal_rounding_mode;
50static ID id_BigDecimal_precision_limit;
57static ID id_half_down;
58static ID id_half_even;
68#define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
69#define PUSH(x) (vStack[iStack++] = (VALUE)(x))
70#define SAVE(p) PUSH((p)->obj)
71#define GUARD_OBJ(p,y) ((p)=(y), SAVE(p))
73#define BASE_FIG RMPD_COMPONENT_FIGURES
76#define HALF_BASE (BASE/2)
77#define BASE1 (BASE/10)
80#define DBLE_FIG (DBL_DIG+1)
83#ifndef RRATIONAL_ZERO_P
84# define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \
85 FIX2LONG(rb_rational_num(x)) == 0)
88#ifndef RRATIONAL_NEGATIVE_P
89# define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0)))
92#ifndef DECIMAL_SIZE_OF_BITS
93#define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999)
98# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
99# define RB_OBJ_STRING(obj) (obj)
101# define PRIsVALUE "s"
102# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
103# define RB_OBJ_STRING(obj) StringValueCStr(obj)
106#ifndef HAVE_RB_RATIONAL_NUM
110#ifdef HAVE_TYPE_STRUCT_RRATIONAL
118#ifndef HAVE_RB_RATIONAL_DEN
122#ifdef HAVE_TYPE_STRUCT_RRATIONAL
130#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
131#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
136#define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
141static unsigned short VpGetException(
void);
142static void VpSetException(
unsigned short f);
144static int VpLimitRound(
Real *c,
size_t ixDigit);
147#ifdef BIGDECIMAL_ENABLE_VPRINT
148static int VPrint(
FILE *fp,
const char *cntl_chr,
Real *a);
156BigDecimal_delete(
void *pv)
162BigDecimal_memsize(
const void *
ptr)
170 { 0, BigDecimal_delete, BigDecimal_memsize, },
171#ifdef RUBY_TYPED_FREE_IMMEDIATELY
177is_kind_of_BigDecimal(
VALUE const v)
200cannot_be_coerced_into_BigDecimal(
VALUE exc_class,
VALUE v)
218GetVpValueWithPrec(
VALUE v,
long prec,
int must)
230 if (prec < 0)
goto unable_to_coerce_without_prec;
231 if (prec >
DBL_DIG+1)
goto SomeOneMayDoIt;
248 if (prec < 0)
goto unable_to_coerce_without_prec;
250 if (orig ==
Qundef ? (orig =
v, 1) : orig !=
v) {
252 pv = GetVpValueWithPrec(num, -1, must);
253 if (pv ==
NULL)
goto SomeOneMayDoIt;
263 if (is_kind_of_BigDecimal(
v)) {
276#ifdef ENABLE_NUMERIC_STRING
298unable_to_coerce_without_prec:
301 "%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
308GetVpValue(
VALUE v,
int must)
310 return GetVpValueWithPrec(
v, -1, must);
321BigDecimal_double_fig(
VALUE self)
339BigDecimal_prec(
VALUE self)
360BigDecimal_hash(
VALUE self)
421 while((*pch) != (
unsigned char)
'\0' && (ch = *pch++) != (
unsigned char)
':') {
425 m = m*10 + (
unsigned long)(ch-
'0');
437check_rounding_mode_option(
VALUE const opts)
456 if (
NIL_P(str_mode))
goto invalid;
486check_rounding_mode(
VALUE const v)
495 if (
id == id_down ||
id == id_truncate)
497 if (
id == id_half_up ||
id == id_default)
499 if (
id == id_half_down)
501 if (
id == id_half_even ||
id == id_banker)
503 if (
id == id_ceiling ||
id ==
id_ceil)
570 fo = VpGetException();
580 fo = VpGetException();
585 fo = VpGetException();
590 fo = VpGetException();
595 fo = VpGetException();
603 sw = check_rounding_mode(val);
619 if (mx < b->Prec) mx = b->
Prec;
660#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
661#define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
664VpCopy(
Real *pv,
Real const*
const x)
681BigDecimal_IsNaN(
VALUE self)
683 Real *p = GetVpValue(
self, 1);
692BigDecimal_IsInfinite(
VALUE self)
694 Real *p = GetVpValue(
self, 1);
702BigDecimal_IsFinite(
VALUE self)
704 Real *p = GetVpValue(
self, 1);
711BigDecimal_check_num(
Real *p)
731BigDecimal_to_i(
VALUE self)
738 BigDecimal_check_num(p);
747 VALUE a = BigDecimal_split(
self);
778BigDecimal_to_f(
VALUE self)
788 if (
VpVtoD(&d, &e, p) != 1)
801 if (d == 0.0)
goto underflow;
825BigDecimal_to_r(
VALUE self)
828 ssize_t sign, power, denomi_power;
829 VALUE a, digits, numerator;
831 p = GetVpValue(
self, 1);
832 BigDecimal_check_num(p);
836 a = BigDecimal_split(
self);
844 if (denomi_power < 0) {
905BigDecimal_uplus(
VALUE self)
936 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
942 b = GetVpValue(r, 0);
951 mx = GetAddSubPrec(a, b);
952 if (mx == (
size_t)-1L) {
994 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1000 b = GetVpValue(r,0);
1009 mx = GetAddSubPrec(a,b);
1010 if (mx == (
size_t)-1L) {
1035 if (!is_kind_of_BigDecimal(r))
break;
1092 if (e == 0)
return Qtrue;
1096 if (e >= 0)
return Qtrue;
1100 if (e > 0)
return Qtrue;
1104 if (e <= 0)
return Qtrue;
1108 if (e < 0)
return Qtrue;
1115 rb_bug(
"Undefined operation in BigDecimalCmp()");
1122BigDecimal_zero(
VALUE self)
1124 Real *a = GetVpValue(
self, 1);
1130BigDecimal_nonzero(
VALUE self)
1132 Real *a = GetVpValue(
self, 1);
1142 return BigDecimalCmp(
self, r,
'*');
1158 return BigDecimalCmp(
self, r,
'=');
1171 return BigDecimalCmp(
self, r,
'<');
1184 return BigDecimalCmp(
self, r,
'L');
1197 return BigDecimalCmp(
self, r,
'>');
1210 return BigDecimalCmp(
self, r,
'G');
1223BigDecimal_neg(
VALUE self)
1257 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1263 b = GetVpValue(r,0);
1285 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1291 b = GetVpValue(r, 0);
1323 r = BigDecimal_divide(&c, &res, &
div,
self, r);
1324 if (!
NIL_P(r))
return r;
1351 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1357 b = GetVpValue(r, 0);
1435 if (BigDecimal_DoDivmod(
self, r, &
div, &
mod)) {
1437 return ToValue(
mod);
1452 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1458 b = GetVpValue(r, 0);
1500 f = BigDecimal_divremain(
self, r, &d, &rv);
1533 if (BigDecimal_DoDivmod(
self, r, &
div, &
mod)) {
1552 if (BigDecimal_DoDivmod(
self, b, &
div, &
mod)) {
1553 return BigDecimal_to_i(ToValue(
div));
1559 ix = GetPrecisionInt(
n);
1561 return BigDecimal_div(
self, b);
1572 mx = av->
Prec + bv->Prec + 2;
1573 if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
1620 return BigDecimal_div2(
self, b,
n);
1629 if (mx == 0)
return BigDecimal_add(
self, b);
1632 VALUE c = BigDecimal_add(
self, b);
1659 if (mx == 0)
return BigDecimal_sub(
self, b);
1662 VALUE c = BigDecimal_sub(
self, b);
1677 if (mx == 0)
return BigDecimal_mult(
self, b);
1680 VALUE c = BigDecimal_mult(
self, b);
1699BigDecimal_abs(
VALUE self)
1731 if (mx <=
n) mx =
n;
1740BigDecimal_fix(
VALUE self)
1796 sw = check_rounding_mode_option(vLoc);
1805 sw = check_rounding_mode_option(vRound);
1808 sw = check_rounding_mode(vRound);
1822 return BigDecimal_to_i(ToValue(c));
1868 return BigDecimal_to_i(ToValue(c));
1876BigDecimal_frac(
VALUE self)
1927#ifdef BIGDECIMAL_DEBUG
1928 VPrint(
stderr,
"floor: c=%\n", c);
1931 return BigDecimal_to_i(ToValue(c));
1974 return BigDecimal_to_i(ToValue(c));
2035 else if (*psz ==
'+') {
2039 while ((ch = *psz++) != 0) {
2044 if (ch ==
'F' || ch ==
'f') {
2049 mc = mc*10 + ch -
'0';
2067 nc += (nc + mc - 1) / mc + 1;
2108BigDecimal_split(
VALUE self)
2121 if(psz1[0] ==
'-') {
2128 if (psz1[0] ==
'N') s = 0;
2145BigDecimal_exponent(
VALUE self)
2157BigDecimal_inspect(
VALUE self)
2176#define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n))
2177#define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n))
2200#define is_positive(x) (!is_negative(x))
2274 VALUE log_x, multiplied, y;
2323 switch (
TYPE(vexp)) {
2332 if (d ==
round(d)) {
2341 exp = GetVpValueWithPrec(vexp,
DBL_DIG+1, 1);
2355 exp = GetVpValueWithPrec(vexp,
n, 1);
2359 if (is_kind_of_BigDecimal(vexp)) {
2361 VALUE rounded = BigDecimal_round(1, &zero, vexp);
2362 if (
RTEST(BigDecimal_eq(vexp, rounded))) {
2363 vexp = BigDecimal_to_i(vexp);
2372 "wrong argument type %"PRIsVALUE" (expected scalar Numeric)",
2377 if (is_negative(vexp)) {
2381 if (is_integer(vexp)) {
2382 if (is_even(vexp)) {
2402 else if (is_zero(vexp)) {
2410 if (is_zero(vexp)) {
2413 else if (is_one(vexp)) {
2418 if (is_negative(vexp)) {
2420 if (is_integer(vexp)) {
2421 if (is_even(vexp)) {
2442 if (is_integer(vexp)) {
2443 if (is_even(vexp)) {
2453 "a non-integral exponent for a negative base");
2464 return rmpd_power_by_big_decimal(x,
exp,
n);
2467 VALUE abs_value = BigDecimal_abs(
self);
2468 if (is_one(abs_value)) {
2472 if (is_negative(vexp)) {
2474 if (is_even(vexp)) {
2492 if (is_even(vexp)) {
2511 if (ma < 0) ma = -ma;
2512 if (ma == 0) ma = 1;
2538 return BigDecimal_power(1, &
exp,
self);
2546BigDecimal_initialize_copy(
VALUE self,
VALUE other)
2551 if (
self != other) {
2558BigDecimal_clone(
VALUE self)
2563#ifdef HAVE_RB_OPTS_EXCEPTION_P
2565#define opts_exception_p(opts) rb_opts_exception_p((opts), 1)
2576 switch (exception) {
2583 return exception !=
Qfalse;
2631 switch (
TYPE(iniValue)) {
2633 if (is_kind_of_BigDecimal(iniValue)) {
2641 return GetVpValue(iniValue, 1);
2663 "can't omit precision for a %"PRIsVALUE".",
2666 return GetVpValueWithPrec(iniValue, mf, 1);
2732 if (ToValue(pv)) pv = VpCopy(
NULL, pv);
2772 if (
NIL_P(nFig))
return nCur;
2799BigDecimal_sign(
VALUE self)
2801 int s = GetVpValue(
self, 1)->
sign;
2824BigDecimal_save_exception_mode(
VALUE self)
2826 unsigned short const exception_mode = VpGetException();
2829 VpSetException(exception_mode);
2849BigDecimal_save_rounding_mode(
VALUE self)
2874BigDecimal_save_limit(
VALUE self)
2914 if (!is_kind_of_BigDecimal(x))
break;
2924 vx = GetVpValue(x, 0);
2930 infinite =
isinf(flo);
2932 if (!infinite && !
nan) {
2933 vx = GetVpValueWithPrec(x,
DBL_DIG+1, 0);
2938 vx = GetVpValueWithPrec(x, prec, 0);
2946 return ToValue(GetVpValueWithPrec(
INT2FIX(0), prec, 1));
2963 else if (vx ==
NULL) {
2968 n = prec + rmpd_double_figures();
2972 VALUE x_copy = f_BigDecimal(1, &x_zero,
klass);
2973 x = BigDecimal_initialize_copy(x_copy, x);
2993 else if ((
size_t)m < rmpd_double_figures()) {
2994 m = rmpd_double_figures();
2997 d = BigDecimal_mult(d, x);
2999 y = BigDecimal_add(y, d);
3004 return BigDecimal_div2(one, y, vprec);
3008 return BigDecimal_round(1, &vprec, y);
3035 VALUE vn, one, two, w, x2, y, d;
3043 if (!is_integer(vprec)) {
3056 if (!is_kind_of_BigDecimal(x))
break;
3075 if (zero || negative)
break;
3076 vx = GetVpValue(x, 0);
3083 infinite =
isinf(flo);
3085 if (!zero && !negative && !infinite && !
nan) {
3086 vx = GetVpValueWithPrec(x,
DBL_DIG+1, 1);
3093 if (zero || negative)
break;
3094 vx = GetVpValueWithPrec(x, prec, 1);
3099 "Complex argument for BigMath.log");
3104 if (infinite && !negative) {
3118 else if (zero || negative) {
3120 "Zero or negative argument for log");
3122 else if (vx ==
NULL) {
3130 n = prec + rmpd_double_figures();
3133 if (expo < 0 || expo >= 3) {
3141 w = BigDecimal_sub(x, one);
3142 x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
3154 else if ((
size_t)m < rmpd_double_figures()) {
3155 m = rmpd_double_figures();
3158 x = BigDecimal_mult2(x2, x, vn);
3161 y = BigDecimal_add(y, d);
3164 y = BigDecimal_mult(y, two);
3168 vexpo = ToValue(GetVpValue(
SSIZET2NUM(expo), 1));
3169 dy = BigDecimal_mult(
log10, vexpo);
3170 y = BigDecimal_add(y, dy);
3306 id_BigDecimal_exception_mode =
rb_intern_const(
"BigDecimal.exception_mode");
3307 id_BigDecimal_rounding_mode =
rb_intern_const(
"BigDecimal.rounding_mode");
3308 id_BigDecimal_precision_limit =
rb_intern_const(
"BigDecimal.precision_limit");
3334#ifndef RUBY_BIGDECIMAL_VERSION
3335# error RUBY_BIGDECIMAL_VERSION is not defined
3538#ifdef BIGDECIMAL_DEBUG
3539static int gfDebug = 1;
3541static int gfCheckVal = 1;
3545static Real *VpConstOne;
3551#define MemCmp(x,y,z) memcmp(x,y,z)
3552#define StrCmp(x,y) strcmp(x,y)
3565static size_t VpSetPTR(
Real *a,
Real *b,
Real *c,
size_t *a_pos,
size_t *b_pos,
size_t *c_pos,
BDIGIT *av,
BDIGIT *bv);
3566static int VpNmlz(
Real *a);
3567static void VpFormatSt(
char *psz,
size_t fFmt);
3568static int VpRdup(
Real *m,
size_t ind_m);
3570#ifdef BIGDECIMAL_DEBUG
3571static int gnAlloc = 0;
3582#ifdef BIGDECIMAL_DEBUG
3603#ifdef BIGDECIMAL_DEBUG
3606 printf(
" *************** All memories allocated freed ****************\n");
3610 printf(
" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
3621#define rmpd_set_thread_local_exception_mode(mode) \
3622 rb_thread_local_aset( \
3623 rb_thread_current(), \
3624 id_BigDecimal_exception_mode, \
3625 INT2FIX((int)(mode)) \
3628static unsigned short
3629VpGetException (
void)
3633 id_BigDecimal_exception_mode
3645VpSetException(
unsigned short f)
3654#define rmpd_set_thread_local_precision_limit(limit) \
3655 rb_thread_local_aset( \
3656 rb_thread_current(), \
3657 id_BigDecimal_precision_limit, \
3660#define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0)
3668 id_BigDecimal_precision_limit
3671 if (
NIL_P(vlimit)) {
3691#define rmpd_set_thread_local_rounding_mode(mode) \
3692 rb_thread_local_aset( \
3693 rb_thread_current(), \
3694 id_BigDecimal_rounding_mode, \
3695 INT2FIX((int)(mode)) \
3703 id_BigDecimal_rounding_mode
3794 static double nzero = 1000.0;
3801VpIsNegDoubleZero(
double v)
3811 unsigned short const exception_mode = VpGetException();
3815 if (always || (exception_mode &
f)) {
3952 if ((
size_t)ex > vp->
Prec) {
3986 VpConstOne =
VpAlloc(1UL,
"1", 1, 1);
3987 VpPt5 =
VpAlloc(1UL,
".5", 1, 1);
3989#ifdef BIGDECIMAL_DEBUG
3993#ifdef BIGDECIMAL_DEBUG
4004 return rmpd_double_figures();
4027 if (eb - mb > 0)
goto overflow;
4036 if (mb - eb > 0)
goto underflow;
4054 static const struct {
4064 static const size_t table_length =
sizeof(table) /
sizeof(table[0]);
4067 for (
i = 0;
i < table_length; ++
i) {
4073 p =
str + table[
i].len;
4074 while (*p &&
ISSPACE(*p)) ++p;
4078 switch (table[
i].sign) {
4113 const char *orig_szVal = szVal;
4114 size_t i, j, ni, ipf, nf, ipe,
ne, dot_seen, exp_seen, nalloc;
4126 while (
ISSPACE(*szVal)) szVal++;
4129 if (*szVal !=
'#') {
4168 v = psz[
i] = szVal[j];
4169 if ((
v ==
'-') || (
v ==
'+')) {
4177 while ((
v = psz[
i] = szVal[j]) !=
'\0') {
4214 if ((psz[
i] = szVal[j]) ==
'.') {
4219 while ((
v = psz[
i] = szVal[j]) !=
'\0') {
4225 if (nf > 0 &&
ISDIGIT(szVal[j+1])) {
4247 switch ((psz[
i] = szVal[j])) {
4256 v = psz[
i] = szVal[j];
4257 if ((
v ==
'-') || (
v ==
'+')) {
4261 while ((
v = psz[
i] = szVal[j]) !=
'\0') {
4293 while (
ISSPACE(szVal[j])) ++j;
4296 if (szVal[j] && strict_p) {
4304 if (strict_p && (((ni == 0 || dot_seen) && nf == 0) || (exp_seen &&
ne == 0))) {
4319 if (mx == 0) mx = 1;
4320 nalloc =
Max(nalloc, mx);
4326 VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe,
ne);
4367 VpInternalRound(c,
n, (
n>0) ? a->
frac[
n-1] : 0, a->
frac[
n]);
4391 Real *a_ptr, *b_ptr;
4392 size_t n, na, nb,
i;
4395#ifdef BIGDECIMAL_DEBUG
4397 VPrint(
stdout,
"VpAddSub(enter) a=% \n", a);
4398 VPrint(
stdout,
" b=% \n", b);
4399 printf(
" operation=%d\n", operation);
4430 if (operation < 0) sw = -1;
4448 for (
i=0;
i <
n; ++
i) {
4490 mrv = VpAddAbs(a_ptr, b_ptr, c);
4495 mrv = VpSubAbs(a_ptr, b_ptr, c);
4503 VpInternalRound(c, 0, (c->
Prec > 0) ? c->
frac[c->
Prec-1] : 0, mrv);
4505#ifdef BIGDECIMAL_DEBUG
4507 VPrint(
stdout,
"VpAddSub(result) c=% \n", c);
4508 VPrint(
stdout,
" a=% \n", a);
4509 VPrint(
stdout,
" b=% \n", b);
4510 printf(
" operation=%d\n", operation);
4529 size_t b_pos, b_pos_with_word_shift;
4531 BDIGIT av, bv, carry, mrv;
4533#ifdef BIGDECIMAL_DEBUG
4535 VPrint(
stdout,
"VpAddAbs called: a = %\n", a);
4536 VPrint(
stdout,
" b = %\n", b);
4540 word_shift = VpSetPTR(a, b, c, &ap, &
bp, &cp, &av, &bv);
4545 if (word_shift == (
size_t)-1L)
return 0;
4546 if (b_pos == (
size_t)-1L)
goto Assign_a;
4553 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4554 c->
frac[--c_pos] = b->
frac[--b_pos];
4557 if (b_pos == 0 && word_shift > a_pos) {
4558 while (word_shift-- > a_pos) {
4559 c->
frac[--c_pos] = 0;
4565 b_pos_with_word_shift = b_pos + word_shift;
4566 while (a_pos > b_pos_with_word_shift) {
4567 c->
frac[--c_pos] = a->
frac[--a_pos];
4574 c->
frac[--c_pos] = a->
frac[--a_pos] + b->
frac[--b_pos] + carry;
4587 c->
frac[--c_pos] = a->
frac[--a_pos] + carry;
4596 if (c_pos) c->
frac[c_pos - 1] += carry;
4605#ifdef BIGDECIMAL_DEBUG
4607 VPrint(
stdout,
"VpAddAbs exit: c=% \n", c);
4624 size_t b_pos, b_pos_with_word_shift;
4626 BDIGIT av, bv, borrow, mrv;
4628#ifdef BIGDECIMAL_DEBUG
4630 VPrint(
stdout,
"VpSubAbs called: a = %\n", a);
4631 VPrint(
stdout,
" b = %\n", b);
4635 word_shift = VpSetPTR(a, b, c, &ap, &
bp, &cp, &av, &bv);
4639 if (word_shift == (
size_t)-1L)
return 0;
4640 if (b_pos == (
size_t)-1L)
goto Assign_a;
4654 if (b_pos + word_shift > a_pos) {
4655 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4660 while (word_shift > a_pos) {
4670 b_pos_with_word_shift = b_pos + word_shift;
4671 while (a_pos > b_pos_with_word_shift) {
4672 c->
frac[--c_pos] = a->
frac[--a_pos];
4679 if (a->
frac[--a_pos] < b->
frac[--b_pos] + borrow) {
4684 c->
frac[c_pos] = a->
frac[a_pos] - b->
frac[b_pos] - borrow;
4693 if (a->
frac[--a_pos] < borrow) {
4698 c->
frac[c_pos] = a->
frac[a_pos] - borrow;
4702 if (c_pos) c->
frac[c_pos - 1] -= borrow;
4710#ifdef BIGDECIMAL_DEBUG
4712 VPrint(
stdout,
"VpSubAbs exit: c=% \n", c);
4735 size_t left_word, right_word, word_shift;
4745 left_word = b->
Prec + word_shift;
4746 right_word =
Max(a->
Prec, left_word);
4752 if (right_word > left_word) {
4762 *c_pos = right_word = left_word + 1;
4771 if (*a_pos <= round_limit) {
4772 *av = a->
frac[*a_pos];
4790 if (c->
MaxPrec >= word_shift + 1) {
4791 *b_pos = c->
MaxPrec - word_shift - 1;
4792 if (*b_pos + word_shift <= round_limit) {
4793 *bv = b->
frac[*b_pos];
4819 *c_pos = right_word + 1;
4823 if (!AddExponent(c, 1))
return (
size_t)-1L;
4845 size_t MxIndA, MxIndB, MxIndAB, MxIndC;
4846 size_t ind_c,
i, ii, nc;
4847 size_t ind_as, ind_ae, ind_bs;
4852#ifdef BIGDECIMAL_DEBUG
4854 VPrint(
stdout,
"VpMult(Enter): a=% \n", a);
4855 VPrint(
stdout,
" b=% \n", b);
4859 if (!VpIsDefOP(c, a, b,
OP_SW_MULT))
return 0;
4882 MxIndA = a->
Prec - 1;
4883 MxIndB = b->
Prec - 1;
4887 if (MxIndC < MxIndAB) {
4896 if (!AddExponent(c, b->
exponent)) {
4902 nc = ind_c = MxIndAB;
4905 for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
4907 ind_as = MxIndA - nc;
4911 else if (nc <= MxIndA) {
4912 ind_as = MxIndA - nc;
4913 ind_ae = MxIndA - (nc - MxIndB);
4918 ind_ae = MxIndAB - nc - 1;
4919 ind_bs = MxIndB - (nc - MxIndA);
4922 for (
i = ind_as;
i <= ind_ae; ++
i) {
4935 c->
frac[ii] += carry;
4958#ifdef BIGDECIMAL_DEBUG
4960 VPrint(
stdout,
"VpMult(c=a*b): c=% \n", c);
4961 VPrint(
stdout,
" a=% \n", a);
4962 VPrint(
stdout,
" b=% \n", b);
4974 size_t word_a, word_b, word_c, word_r;
4975 size_t i,
n, ind_a, ind_b, ind_c, ind_r;
4978 BDIGIT borrow, borrow1, borrow2;
4981#ifdef BIGDECIMAL_DEBUG
4983 VPrint(
stdout,
" VpDivd(c=a/b) a=% \n", a);
4984 VPrint(
stdout,
" b=% \n", b);
4989 if (!VpIsDefOP(c, a, b,
OP_SW_DIV))
goto Exit;
5019 if (word_a >= word_r)
goto space_error;
5022 while (ind_r <= word_a) {
5023 r->
frac[ind_r] = a->
frac[ind_r - 1];
5027 while (ind_r < word_r) r->
frac[ind_r++] = 0;
5028 while (ind_c < word_c) c->
frac[ind_c++] = 0;
5031 b1 = b1p1 = b->
frac[0];
5033 b1b2p1 = b1b2 = b1p1 *
BASE;
5037 b1b2p1 = b1b2 = b1 *
BASE + b->
frac[1];
5038 if (b->
Prec > 2) ++b1b2p1;
5044 nLoop =
Min(word_c,ind_c);
5046 while (ind_c < nLoop) {
5047 if (r->
frac[ind_c] == 0) {
5056 while (ind_b < word_b) {
5057 if (r->
frac[ind_a] < b->
frac[ind_b])
goto div_b1p1;
5058 if (r->
frac[ind_a] > b->
frac[ind_b])
break;
5066 ind_b = b->
Prec - 1;
5067 ind_r = ind_c + ind_b;
5068 if (ind_r >= word_r)
goto space_error;
5070 for (
i = 0;
i <=
n; ++
i) {
5071 if (r->
frac[ind_r] < b->
frac[ind_b] + borrow) {
5076 r->
frac[ind_r] = r->
frac[ind_r] - b->
frac[ind_b] - borrow;
5087 if (r1r2 >= b1b2p1) {
5090 ind_r = b->
Prec + ind_c - 1;
5095 if (ind_c + 1 >= word_c)
goto out_side;
5098 ind_r = b->
Prec + ind_c;
5101 borrow1 = borrow2 = 0;
5103 if (ind_r >= word_r)
goto space_error;
5105 for (
i = 0;
i <=
n; ++
i) {
5107 qb = q * b->
frac[ind_b];
5108 if (qb <
BASE) borrow1 = 0;
5113 if(r->
frac[ind_r] < qb) {
5115 borrow2 = borrow2 + borrow1 + 1;
5122 if(r->
frac[ind_r - 1] < borrow2) {
5123 r->
frac[ind_r - 1] += (
BASE - borrow2);
5127 r->
frac[ind_r - 1] -= borrow2;
5135 r->
frac[ind_r] -= borrow2;
5148 if (!AddExponent(c, 2))
return 0;
5149 if (!AddExponent(c, -(b->
exponent)))
return 0;
5155 if (!AddExponent(r, 1))
return 0;
5161#ifdef BIGDECIMAL_DEBUG
5170 rb_bug(
"ERROR(VpDivd): space for remainder too small.");
5173#ifdef BIGDECIMAL_DEBUG
5175 VPrint(
stdout,
" VpDivd(c=a/b), c=% \n", c);
5176 VPrint(
stdout,
" r=% \n", r);
5196 if (a->
frac[ind_a]) {
5197 a->
Prec = ind_a + 1;
5199 while (a->
frac[
i] == 0) ++
i;
5236 if (e > 0)
return 1;
5237 else if (e < 0)
return -1;
5242 if (e > 0)
return 1;
5298 if (val > 1) val = 1;
5299 else if (val < -1) val = -1;
5301#ifdef BIGDECIMAL_DEBUG
5303 VPrint(
stdout,
" VpComp a=%\n", a);
5304 VPrint(
stdout,
" b=%\n", b);
5305 printf(
" ans=%d\n", val);
5321#ifdef BIGDECIMAL_ENABLE_VPRINT
5323VPrint(
FILE *fp,
const char *cntl_chr,
Real *a)
5325 size_t i, j, nc, nd, ZeroSup, sep = 10;
5333 while (*(cntl_chr + j)) {
5334 if (*(cntl_chr + j) ==
'%' && *(cntl_chr + j + 1) !=
'%') {
5354 switch (*(cntl_chr + j + 1)) {
5364 for (
i = 0;
i < a->
Prec; ++
i) {
5369 if (!ZeroSup || nn) {
5370 nc +=
fprintf(fp,
"%lu", (
unsigned long)nn);
5393 if (*(cntl_chr + j) ==
'\\') {
5394 switch (*(cntl_chr + j + 1)) {
5408 fprintf(fp,
"%c", *(cntl_chr + j));
5413 fprintf(fp,
"%c", *(cntl_chr + j));
5414 if (*(cntl_chr + j) ==
'%') ++j;
5425VpFormatSt(
char *psz,
size_t fFmt)
5427 size_t ie,
i, nf = 0;
5430 if (fFmt == 0)
return;
5433 for (
i = 0;
i < ie; ++
i) {
5436 if (
ISSPACE(ch) || ch==
'-' || ch==
'+')
continue;
5437 if (ch ==
'.') { nf = 0;
continue; }
5438 if (ch ==
'E' || ch ==
'e')
break;
5459 while ((a->
frac[0] /
n) == 0) {
5469 size_t i,
n, ZeroSup;
5489 for (
i = 0;
i <
n; ++
i) {
5494 if (!ZeroSup || nn) {
5495 sprintf(psz,
"%lu", (
unsigned long)nn);
5505 while (psz[-1] ==
'0') *(--psz) = 0;
5526 else if (fPlus == 2) {
5538 if (fPlus == 1)
sprintf(psz,
" 0.0");
5539 else if (fPlus == 2)
sprintf(psz,
"+0.0");
5552 size_t i,
n, ZeroSup;
5562 else if (fPlus == 1) *psz++ =
' ';
5563 else if (fPlus == 2) *psz++ =
'+';
5568 for (
i = 0;
i <
n; ++
i) {
5573 if (!ZeroSup || nn) {
5574 sprintf(psz,
"%lu", (
unsigned long)nn);
5585 while (a->
frac[0] / shift == 0) {
5589 while (psz[-1] ==
'0') {
5593 if (fFmt) VpFormatSt(pszSav, fFmt);
5608 else if (fPlus == 1) *psz++ =
' ';
5609 else if (fPlus == 2) *psz++ =
'+';
5614 *psz++ =
'0';*psz++ =
'.';
5622 for (
i = 0;
i <
n; ++
i) {
5624 if (
i == 0 && ex >= 0) {
5633 *psz++ = (
char)(nn +
'0');
5638 if (ex == 0) *psz++ =
'.';
5642 while (m /= 10) *psz++ =
'0';
5643 if (ex == 0) *psz++ =
'.';
5646 while (psz[-1] ==
'0') *(--psz) = 0;
5647 if (psz[-1] ==
'.')
sprintf(psz,
"0");
5648 if (fFmt) VpFormatSt(pszSav, fFmt);
5663VpCtoV(
Real *a,
const char *int_chr,
size_t ni,
const char *frac,
size_t nf,
const char *exp_chr,
size_t ne)
5665 size_t i, j, ind_a, ma, mi,
me;
5667 int sign, signe, exponent_overflow;
5675 exponent_overflow = 0;
5679 if (exp_chr[0] ==
'-') {
5684 else if (exp_chr[0] ==
'+') {
5697 e = e * 10 + exp_chr[
i] -
'0';
5702 exponent_overflow = 1;
5714 if (int_chr[0] ==
'-') {
5719 else if (int_chr[0] ==
'+') {
5728 if (e > 0) signe = 1;
5747 if (exponent_overflow) {
5749 for ( ;
i < mi && zero;
i++) zero = int_chr[
i] ==
'0';
5750 for (
i = 0;
i < nf && zero;
i++) zero = frac[
i] ==
'0';
5751 if (!zero && signe > 0) {
5763 a->
frac[ind_a] = a->
frac[ind_a] * 10 + int_chr[
i] -
'0';
5769 if (ind_a >= ma)
goto over_flow;
5779 a->
frac[ind_a] = a->
frac[ind_a] * 10 + frac[
i] -
'0';
5785 if (ind_a >= ma)
goto over_flow;
5792 rb_warn(
"Conversion from String to BigDecimal overflow (last few digits discarded).");
5795 if (ind_a >= ma) ind_a = ma - 1;
5797 a->
frac[ind_a] = a->
frac[ind_a] * 10;
5800 a->
Prec = ind_a + 1;
5825 size_t ind_m, mm, fig;
5865 while (ind_m < mm) {
5873#ifdef BIGDECIMAL_DEBUG
5875 VPrint(
stdout,
" VpVtoD: m=%\n", m);
5876 printf(
" d=%e * 10 **%ld\n", *d, *e);
5908 val = (d > 0.) ? d : -d;
5911 while (val >= 1.0) {
5918 while (val < val2) {
5927 for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
5933 if (ind_m >= mm) ind_m = mm - 1;
5935 m->
Prec = ind_m + 1;
5938 VpInternalRound(m, 0, (m->
Prec > 0) ? m->
frac[m->
Prec-1] : 0,
5942#ifdef BIGDECIMAL_DEBUG
5944 printf(
"VpDtoV d=%30.30e\n", d);
5945 VPrint(
stdout,
" m=%\n", m);
5959 size_t val, v1, v2,
v;
5976 while (ind_m < mm) {
5985 while (v1 >=
BASE) {
5989 val = val - v2 * v1;
5999 m->
Prec = ind_m - 1;
6005#ifdef BIGDECIMAL_DEBUG
6007 printf(
" VpItoV i=%d\n", ival);
6008 VPrint(
stdout,
" m=%\n", m);
6072 if (e -
n * 2 != 0) {
6095#ifdef BIGDECIMAL_DEBUG
6097 printf(
"ERROR(VpSqrt): did not converge within %ld iterations.\n", nr);
6104#ifdef BIGDECIMAL_DEBUG
6109 VPrint(
stdout,
" y =% \n", y);
6110 VPrint(
stdout,
" x =% \n", x);
6111 VPrint(
stdout,
" x-y*y = % \n",
f);
6133 int fracf, fracf_1further;
6151 if ((
size_t)ix >= y->
Prec)
return 0;
6156 for (shifter = 1,
i = 0;
i <
n; ++
i) shifter *= 10;
6185 fracf = (
v % (shifter * 10) > 0);
6186 fracf_1further = ((
v % shifter) > 0);
6202 for (
i = ix + 1; (
size_t)i < y->Prec;
i++) {
6204 fracf = fracf_1further = 1;
6227 if (
v > 5 || (
v == 5 && fracf_1further)) ++
div;
6238 if (fracf_1further) {
6248 if (ix && (y->
frac[ix-1] % 2)) ++
div;
6257 for (
i = 0;
i <=
n; ++
i)
div *= 10;
6278 for (
i = 0;
i < exptoadd;
i++) {
6299 while ((
v /= 10) != 0) nf--;
6308 if (
VpAsgn(y, x, 10) <= 1)
return 0;
6313VpLimitRound(
Real *c,
size_t ixDigit)
6316 if (!VpNmlz(c))
return -1;
6318 if (!ixDigit) ixDigit = c->
Prec-1;
6332 if (VpLimitRound(c, ixDigit))
return;
6336 switch (rounding_mode) {
6361 else if (
v == 5 && vPrev % 2)
f = 1;
6374VpRdup(
Real *m,
size_t ind_m)
6378 if (!ind_m) ind_m = m->
Prec;
6381 while (carry > 0 && ind_m--) {
6382 m->
frac[ind_m] += carry;
6387 if (!AddExponent(m, 1))
return 0;
6402 size_t my, ind_y, ind_x;
6427 while (ind_y < my) {
6435#ifdef BIGDECIMAL_DEBUG
6437 VPrint(
stdout,
"VpFrac y=%\n", y);
6438 VPrint(
stdout,
" x=%\n", x);
6463 if (sign < 0) sign = (
n % 2) ? -1 : 1;
6467 if (sign < 0) sign = (
n % 2) ? -1 : 1;
6493 if ((
n % 2) == 0)
goto Exit;
6498 if (
n > 0) sign = 1;
6519 while (ss = s, (s += s) <= (
size_t)
n) {
6528 VpDivd(w1, w2, VpConstOne, y);
6533#ifdef BIGDECIMAL_DEBUG
6535 VPrint(
stdout,
"VpPower y=%\n", y);
6536 VPrint(
stdout,
"VpPower x=%\n", x);
6545#ifdef BIGDECIMAL_DEBUG
6559 if (
v->MaxPrec == 0) {
6560 printf(
"ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
6564 if (
v->Prec == 0 ||
v->Prec >
v->MaxPrec) {
6565 printf(
"ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n",
v->Prec);
6569 for (
i = 0;
i <
v->Prec; ++
i) {
6570 if (
v->frac[
i] >=
BASE) {
6571 printf(
"ERROR(VpVarCheck): Illegal fraction\n");
VP_EXPORT double VpGetDoubleNegZero(void)
VP_EXPORT size_t VpDivd(Real *c, Real *r, Real *a, Real *b)
VP_EXPORT Real * VpCreateRbObject(size_t mx, const char *str)
#define RB_OBJ_CLASSNAME(obj)
#define BigMath_exp(x, n)
VP_EXPORT int VpIsRoundMode(unsigned short n)
VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
VP_EXPORT size_t VpInit(BDIGIT BaseVal)
#define rmpd_set_thread_local_rounding_mode(mode)
VP_EXPORT double VpGetDoubleNaN(void)
VP_EXPORT double VpGetDoubleNegInf(void)
#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b)
VP_EXPORT unsigned short VpGetRoundMode(void)
VP_EXPORT void VpDtoV(Real *m, double d)
VP_EXPORT size_t VpMult(Real *c, Real *a, Real *b)
VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
#define RMPD_PRECISION_LIMIT_DEFAULT
#define VpAllocReal(prec)
#define BIGDECIMAL_NEGATIVE_P(bd)
VP_EXPORT void VpFrac(Real *y, Real *x)
void Init_bigdecimal(void)
VP_EXPORT ssize_t VpExponent10(Real *a)
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf)
VP_EXPORT Real * VpOne(void)
VP_EXPORT size_t VpAddSub(Real *c, Real *a, Real *b, int operation)
VP_EXPORT size_t VpGetPrecLimit(void)
VP_EXPORT unsigned short VpSetRoundMode(unsigned short n)
VP_EXPORT size_t VpSetPrecLimit(size_t n)
VP_EXPORT Real * VpNewRbClass(size_t mx, const char *str, VALUE klass)
VP_EXPORT void VpSzMantissa(Real *a, char *psz)
VP_EXPORT size_t VpNumOfChars(Real *vp, const char *pszFmt)
VP_EXPORT int VpSqrt(Real *y, Real *x)
volatile const double gOne_ABCED9B4_CE73__00400511F31D
#define RRATIONAL_NEGATIVE_P(x)
VP_EXPORT Real * VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
Real * rmpd_parse_special_string(const char *str)
#define BIGDECIMAL_POSITIVE_P(bd)
VP_EXPORT void * VpMemAlloc(size_t mb)
VP_EXPORT int VpComp(Real *a, Real *b)
#define DoSomeOne(x, y, f)
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf)
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE))
#define BigMath_log(x, n)
#define rmpd_set_thread_local_precision_limit(limit)
#define RRATIONAL_ZERO_P(x)
VP_EXPORT int VpException(unsigned short f, const char *str, int always)
VP_EXPORT void * VpMemRealloc(void *ptr, size_t mb)
VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n)
VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
#define rmpd_set_thread_local_exception_mode(mode)
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw)
VP_EXPORT int VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne)
#define VpReallocReal(ptr, prec)
VP_EXPORT void VpFree(Real *pv)
VP_EXPORT int VpToSpecialString(Real *a, char *psz, int fPlus)
VP_EXPORT double VpGetDoublePosInf(void)
#define VP_EXCEPTION_ZERODIVIDE
#define VP_SIGN_NEGATIVE_INFINITE
#define VP_SIGN_POSITIVE_ZERO
#define VP_ROUND_HALF_EVEN
#define VpChangeSign(a, s)
#define VP_EXCEPTION_UNDERFLOW
#define VP_ROUND_HALF_DOWN
#define RMPD_ROUNDING_MODE_DEFAULT
#define VP_SIGN_NEGATIVE_FINITE
#define RMPD_EXCEPTION_MODE_DEFAULT
#define VP_SIGN_NEGATIVE_ZERO
#define VP_SIGN_POSITIVE_INFINITE
#define VP_EXCEPTION_OVERFLOW
#define VP_SIGN_POSITIVE_FINITE
#define VP_EXCEPTION_MEMORY
#define VP_EXCEPTION_INFINITY
#define RMPD_COMPONENT_FIGURES
char str[HTML_ESCAPE_MAX_LEN+1]
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
VALUE rb_define_module(const char *)
void rb_undef_method(VALUE, const char *)
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *)
VALUE rb_eFloatDomainError
VALUE rb_eMathDomainError
void rb_raise(VALUE exc, const char *fmt,...)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
void rb_bug(const char *fmt,...)
void rb_fatal(const char *fmt,...)
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
void rb_warn(const char *fmt,...)
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
#define opts_exception_p(opts)
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Tries to convert an object into another type.
int rb_opts_exception_p(VALUE opts, int default_value)
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
BDIGIT frac[FLEXIBLE_ARRAY_SIZE]
#define DECIMAL_SIZE_OF_BITS(n)