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) 48 static ID id_BigDecimal_exception_mode;
49 static ID id_BigDecimal_rounding_mode;
50 static ID id_BigDecimal_precision_limit;
54 static ID id_truncate;
57 static ID id_half_down;
58 static 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 74 #define BASE RMPD_BASE 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 108 rb_rational_num(
VALUE rat)
110 #ifdef HAVE_TYPE_STRUCT_RRATIONAL 118 #ifndef HAVE_RB_RATIONAL_DEN 120 rb_rational_den(
VALUE rat)
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) 142 BigDecimal_version(
VALUE self)
155 static unsigned short VpGetException(
void);
156 static void VpSetException(
unsigned short f);
157 static void VpInternalRound(
Real *c,
size_t ixDigit,
BDIGIT vPrev,
BDIGIT v);
158 static int VpLimitRound(
Real *c,
size_t ixDigit);
161 #ifdef BIGDECIMAL_ENABLE_VPRINT 162 static int VPrint(
FILE *fp,
const char *cntl_chr,
Real *a);
170 BigDecimal_delete(
void *pv)
176 BigDecimal_memsize(
const void *ptr)
178 const Real *pv = ptr;
184 { 0, BigDecimal_delete, BigDecimal_memsize, },
185 #ifdef RUBY_TYPED_FREE_IMMEDIATELY 191 is_kind_of_BigDecimal(
VALUE const v)
214 cannot_be_coerced_into_BigDecimal(
VALUE exc_class,
VALUE v)
218 if (rb_special_const_p(v)) {
232 GetVpValueWithPrec(
VALUE v,
long prec,
int must)
244 if (prec < 0)
goto unable_to_coerce_without_prec;
245 if (prec >
DBL_DIG+1)
goto SomeOneMayDoIt;
262 if (prec < 0)
goto unable_to_coerce_without_prec;
264 if (orig ==
Qundef ? (orig = v, 1) : orig != v) {
265 num = rb_rational_num(v);
266 pv = GetVpValueWithPrec(num, -1, must);
267 if (pv ==
NULL)
goto SomeOneMayDoIt;
269 v = BigDecimal_div2(ToValue(pv), rb_rational_den(v),
LONG2NUM(prec));
277 if (is_kind_of_BigDecimal(v)) {
290 #ifdef ENABLE_NUMERIC_STRING 313 unable_to_coerce_without_prec:
316 "%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
323 GetVpValue(
VALUE v,
int must)
325 return GetVpValueWithPrec(v, -1, must);
336 BigDecimal_double_fig(
VALUE self)
354 BigDecimal_prec(
VALUE self)
375 BigDecimal_hash(
VALUE self)
437 while((*pch) != (
unsigned char)
'\0' && (ch = *pch++) != (
unsigned char)
':') {
441 m = m*10 + (
unsigned long)(ch-
'0');
452 static unsigned short 453 check_rounding_mode_option(
VALUE const opts)
472 if (
NIL_P(str_mode))
goto invalid;
501 static unsigned short 502 check_rounding_mode(
VALUE const v)
511 if (
id == id_down ||
id == id_truncate)
513 if (
id == id_half_up ||
id == id_default)
515 if (
id == id_half_down)
517 if (
id == id_half_even ||
id == id_banker)
519 if (
id == id_ceiling ||
id ==
id_ceil)
582 f = (
unsigned long)
NUM2INT(which);
586 fo = VpGetException();
593 VpSetException((
unsigned short)((val ==
Qtrue) ? (fo | VP_EXCEPTION_INFINITY) :
594 (fo & (~VP_EXCEPTION_INFINITY))));
596 fo = VpGetException();
598 VpSetException((
unsigned short)((val ==
Qtrue) ? (fo | VP_EXCEPTION_NaN) :
599 (fo & (~VP_EXCEPTION_NaN))));
601 fo = VpGetException();
603 VpSetException((
unsigned short)((val ==
Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) :
604 (fo & (~VP_EXCEPTION_UNDERFLOW))));
606 fo = VpGetException();
608 VpSetException((
unsigned short)((val ==
Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) :
609 (fo & (~VP_EXCEPTION_ZERODIVIDE))));
611 fo = VpGetException();
619 sw = check_rounding_mode(val);
635 if (mx < b->Prec) mx = b->
Prec;
649 GetPositiveInt(
VALUE v)
675 #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT)) 676 #define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT)) 679 VpCopy(
Real *pv,
Real const*
const x)
696 BigDecimal_IsNaN(
VALUE self)
698 Real *p = GetVpValue(
self, 1);
707 BigDecimal_IsInfinite(
VALUE self)
709 Real *p = GetVpValue(
self, 1);
717 BigDecimal_IsFinite(
VALUE self)
719 Real *p = GetVpValue(
self, 1);
726 BigDecimal_check_num(
Real *p)
746 BigDecimal_to_i(
VALUE self)
753 BigDecimal_check_num(p);
762 VALUE a = BigDecimal_split(
self);
793 BigDecimal_to_f(
VALUE self)
803 if (
VpVtoD(&d, &e, p) != 1)
815 if (
errno == ERANGE) {
816 if (d == 0.0)
goto underflow;
817 if (fabs(d) >= HUGE_VAL)
goto overflow;
840 BigDecimal_to_r(
VALUE self)
843 ssize_t sign, power, denomi_power;
844 VALUE a, digits, numerator;
846 p = GetVpValue(
self, 1);
847 BigDecimal_check_num(p);
851 a = BigDecimal_split(
self);
859 if (denomi_power < 0) {
920 BigDecimal_uplus(
VALUE self)
951 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
957 b = GetVpValue(r, 0);
966 mx = GetAddSubPrec(a, b);
967 if (mx == (
size_t)-1L) {
1009 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1015 b = GetVpValue(r,0);
1024 mx = GetAddSubPrec(a,b);
1025 if (mx == (
size_t)-1L) {
1050 if (!is_kind_of_BigDecimal(r))
break;
1107 if (e == 0)
return Qtrue;
1111 if (e >= 0)
return Qtrue;
1115 if (e > 0)
return Qtrue;
1119 if (e <= 0)
return Qtrue;
1123 if (e < 0)
return Qtrue;
1130 rb_bug(
"Undefined operation in BigDecimalCmp()");
1137 BigDecimal_zero(
VALUE self)
1139 Real *a = GetVpValue(
self, 1);
1145 BigDecimal_nonzero(
VALUE self)
1147 Real *a = GetVpValue(
self, 1);
1157 return BigDecimalCmp(
self, r,
'*');
1173 return BigDecimalCmp(
self, r,
'=');
1186 return BigDecimalCmp(
self, r,
'<');
1199 return BigDecimalCmp(
self, r,
'L');
1212 return BigDecimalCmp(
self, r,
'>');
1225 return BigDecimalCmp(
self, r,
'G');
1238 BigDecimal_neg(
VALUE self)
1272 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1278 b = GetVpValue(r,0);
1300 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1306 b = GetVpValue(r, 0);
1338 r = BigDecimal_divide(&c, &res, &div,
self, r);
1339 if (!
NIL_P(r))
return r;
1366 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1372 b = GetVpValue(r, 0);
1450 if (BigDecimal_DoDivmod(
self, r, &div, &mod)) {
1452 return ToValue(mod);
1467 b = GetVpValueWithPrec(r,
DBL_DIG+1, 1);
1473 b = GetVpValue(r, 0);
1515 f = BigDecimal_divremain(
self, r, &d, &rv);
1548 if (BigDecimal_DoDivmod(
self, r, &div, &mod)) {
1567 if (BigDecimal_DoDivmod(
self, b, &div, &mod)) {
1568 return BigDecimal_to_i(ToValue(div));
1574 ix = GetPositiveInt(n);
1576 return BigDecimal_div(
self, b);
1587 mx = av->
Prec + bv->Prec + 2;
1588 if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
1635 return BigDecimal_div2(
self, b, n);
1644 if (mx == 0)
return BigDecimal_add(
self, b);
1647 VALUE c = BigDecimal_add(
self, b);
1674 if (mx == 0)
return BigDecimal_sub(
self, b);
1677 VALUE c = BigDecimal_sub(
self, b);
1692 if (mx == 0)
return BigDecimal_mult(
self, b);
1695 VALUE c = BigDecimal_mult(
self, b);
1714 BigDecimal_abs(
VALUE self)
1746 if (mx <= n) mx = n;
1755 BigDecimal_fix(
VALUE self)
1808 sw = check_rounding_mode_option(vLoc);
1817 sw = check_rounding_mode_option(vRound);
1820 sw = check_rounding_mode(vRound);
1834 return BigDecimal_to_i(ToValue(c));
1880 return BigDecimal_to_i(ToValue(c));
1888 BigDecimal_frac(
VALUE self)
1939 #ifdef BIGDECIMAL_DEBUG 1940 VPrint(stderr,
"floor: c=%\n", c);
1943 return BigDecimal_to_i(ToValue(c));
1986 return BigDecimal_to_i(ToValue(c));
2047 else if (*psz ==
'+') {
2051 while ((ch = *psz++) != 0) {
2056 if (ch ==
'F' || ch ==
'f') {
2061 mc = mc*10 + ch -
'0';
2065 mc = (size_t)GetPositiveInt(f);
2075 nc += (nc + mc - 1) / mc + 1;
2116 BigDecimal_split(
VALUE self)
2129 if(psz1[0] ==
'-') {
2136 if (psz1[0] ==
'N') s = 0;
2153 BigDecimal_exponent(
VALUE self)
2170 BigDecimal_inspect(
VALUE self)
2189 #define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n)) 2190 #define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n)) 2199 is_negative(
VALUE x)
2213 #define is_positive(x) (!is_negative(x)) 2228 num = rb_rational_num(x);
2251 num = rb_rational_num(x);
2252 den = rb_rational_den(x);
2285 rmpd_power_by_big_decimal(
Real const* x,
Real const* exp, ssize_t
const n)
2287 VALUE log_x, multiplied, y;
2295 multiplied = BigDecimal_mult2(exp->
obj, log_x,
SSIZET2NUM(n+1));
2336 switch (
TYPE(vexp)) {
2345 if (d ==
round(d)) {
2354 exp = GetVpValueWithPrec(vexp,
DBL_DIG+1, 1);
2358 if (is_zero(rb_rational_num(vexp))) {
2364 else if (is_one(rb_rational_den(vexp))) {
2365 vexp = rb_rational_num(vexp);
2368 exp = GetVpValueWithPrec(vexp, n, 1);
2372 if (is_kind_of_BigDecimal(vexp)) {
2374 VALUE rounded = BigDecimal_round(1, &zero, vexp);
2375 if (
RTEST(BigDecimal_eq(vexp, rounded))) {
2376 vexp = BigDecimal_to_i(vexp);
2385 "wrong argument type %"PRIsVALUE" (expected scalar Numeric)",
2390 if (is_negative(vexp)) {
2394 if (is_integer(vexp)) {
2395 if (is_even(vexp)) {
2415 else if (is_zero(vexp)) {
2423 if (is_zero(vexp)) {
2426 else if (is_one(vexp)) {
2431 if (is_negative(vexp)) {
2433 if (is_integer(vexp)) {
2434 if (is_even(vexp)) {
2455 if (is_integer(vexp)) {
2456 if (is_even(vexp)) {
2466 "a non-integral exponent for a negative base");
2477 return rmpd_power_by_big_decimal(x, exp, n);
2480 VALUE abs_value = BigDecimal_abs(
self);
2481 if (is_one(abs_value)) {
2485 if (is_negative(vexp)) {
2487 if (is_even(vexp)) {
2505 if (is_even(vexp)) {
2524 if (ma < 0) ma = -ma;
2525 if (ma == 0) ma = 1;
2551 return BigDecimal_power(1, &exp,
self);
2555 BigDecimal_s_allocate(
VALUE klass)
2618 BigDecimal_initialize_copy(
VALUE self,
VALUE other)
2623 if (
self != other) {
2641 mf = GetPositiveInt(nFig);
2644 switch (
TYPE(iniValue)) {
2646 if (is_kind_of_BigDecimal(iniValue)) {
2654 return GetVpValue(iniValue, 1);
2670 "can't omit precision for a %"PRIsVALUE".",
2673 return GetVpValueWithPrec(iniValue, mf, 1);
2694 if (ToValue(pv)) pv = VpCopy(
NULL, pv);
2696 return pv->
obj = obj;
2719 if (
NIL_P(nFig))
return nCur;
2746 BigDecimal_sign(
VALUE self)
2748 int s = GetVpValue(
self, 1)->
sign;
2771 BigDecimal_save_exception_mode(
VALUE self)
2773 unsigned short const exception_mode = VpGetException();
2776 VpSetException(exception_mode);
2796 BigDecimal_save_rounding_mode(
VALUE self)
2821 BigDecimal_save_limit(
VALUE self)
2861 if (!is_kind_of_BigDecimal(x))
break;
2871 vx = GetVpValue(x, 0);
2877 infinite =
isinf(flo);
2879 if (!infinite && !nan) {
2880 vx = GetVpValueWithPrec(x,
DBL_DIG+1, 0);
2885 vx = GetVpValueWithPrec(x, prec, 0);
2893 return ToValue(GetVpValueWithPrec(
INT2FIX(0), prec, 1));
2910 else if (vx ==
NULL) {
2915 n = prec + rmpd_double_figures();
2929 ssize_t m = n -
vabs(ey - ed);
2936 else if ((
size_t)m < rmpd_double_figures()) {
2937 m = rmpd_double_figures();
2940 d = BigDecimal_mult(d, x);
2942 y = BigDecimal_add(y, d);
2947 return BigDecimal_div2(one, y, vprec);
2951 return BigDecimal_round(1, &vprec, y);
2978 VALUE vn, one, two, w, x2, y, d;
2986 if (!is_integer(vprec)) {
2999 if (!is_kind_of_BigDecimal(x))
break;
3018 if (zero || negative)
break;
3019 vx = GetVpValue(x, 0);
3026 infinite =
isinf(flo);
3028 if (!zero && !negative && !infinite && !nan) {
3029 vx = GetVpValueWithPrec(x,
DBL_DIG+1, 1);
3036 if (zero || negative)
break;
3037 vx = GetVpValueWithPrec(x, prec, 1);
3042 "Complex argument for BigMath.log");
3047 if (infinite && !negative) {
3061 else if (zero || negative) {
3063 "Zero or negative argument for log");
3065 else if (vx ==
NULL) {
3073 n = prec + rmpd_double_figures();
3076 if (expo < 0 || expo >= 3) {
3084 w = BigDecimal_sub(x, one);
3085 x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
3093 ssize_t m = n -
vabs(ey - ed);
3097 else if ((
size_t)m < rmpd_double_figures()) {
3098 m = rmpd_double_figures();
3101 x = BigDecimal_mult2(x2, x, vn);
3104 y = BigDecimal_add(y, d);
3107 y = BigDecimal_mult(y, two);
3109 VALUE log10, vexpo, dy;
3110 log10 = BigMath_s_log(klass,
INT2FIX(10), vprec);
3111 vexpo = ToValue(GetVpValue(
SSIZET2NUM(expo), 1));
3112 dy = BigDecimal_mult(log10, vexpo);
3113 y = BigDecimal_add(y, dy);
3249 id_BigDecimal_exception_mode =
rb_intern_const(
"BigDecimal.exception_mode");
3250 id_BigDecimal_rounding_mode =
rb_intern_const(
"BigDecimal.rounding_mode");
3251 id_BigDecimal_precision_limit =
rb_intern_const(
"BigDecimal.precision_limit");
3472 #ifdef BIGDECIMAL_DEBUG 3473 static int gfDebug = 1;
3475 static int gfCheckVal = 1;
3479 static Real *VpConstOne;
3485 #define MemCmp(x,y,z) memcmp(x,y,z) 3486 #define StrCmp(x,y) strcmp(x,y) 3499 static 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);
3500 static int VpNmlz(
Real *a);
3501 static void VpFormatSt(
char *psz,
size_t fFmt);
3502 static int VpRdup(
Real *m,
size_t ind_m);
3504 #ifdef BIGDECIMAL_DEBUG 3505 static int gnAlloc = 0;
3516 #ifdef BIGDECIMAL_DEBUG 3537 #ifdef BIGDECIMAL_DEBUG 3540 printf(
" *************** All memories allocated freed ****************\n");
3544 printf(
" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
3555 #define rmpd_set_thread_local_exception_mode(mode) \ 3556 rb_thread_local_aset( \ 3557 rb_thread_current(), \ 3558 id_BigDecimal_exception_mode, \ 3559 INT2FIX((int)(mode)) \ 3562 static unsigned short 3563 VpGetException (
void)
3567 id_BigDecimal_exception_mode
3579 VpSetException(
unsigned short f)
3588 #define rmpd_set_thread_local_precision_limit(limit) \ 3589 rb_thread_local_aset( \ 3590 rb_thread_current(), \ 3591 id_BigDecimal_precision_limit, \ 3594 #define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0) 3602 id_BigDecimal_precision_limit
3605 if (
NIL_P(vlimit)) {
3625 #define rmpd_set_thread_local_rounding_mode(mode) \ 3626 rb_thread_local_aset( \ 3627 rb_thread_current(), \ 3628 id_BigDecimal_rounding_mode, \ 3629 INT2FIX((int)(mode)) \ 3637 id_BigDecimal_rounding_mode
3716 static double fNaN = 0.0;
3717 if (fNaN == 0.0) fNaN = Zero()/Zero();
3724 static double fInf = 0.0;
3725 if (fInf == 0.0) fInf = One()/Zero();
3732 static double fInf = 0.0;
3733 if (fInf == 0.0) fInf = -(One()/Zero());
3740 static double nzero = 1000.0;
3747 VpIsNegDoubleZero(
double v)
3750 return MemCmp(&v,&z,
sizeof(v))==0;
3757 unsigned short const exception_mode = VpGetException();
3761 if (always || (exception_mode & f)) {
3898 if ((
size_t)ex > vp->
Prec) {
3935 VpConstOne =
VpAlloc(1UL,
"1");
3938 #ifdef BIGDECIMAL_DEBUG 3942 #ifdef BIGDECIMAL_DEBUG 3944 printf(
"VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
3948 printf(
"\tBASE_FIG = %u\n",
BASE_FIG);
3949 printf(
"\tDBLE_FIG = %d\n",
DBLE_FIG);
3953 return rmpd_double_figures();
3976 if (eb - mb > 0)
goto overflow;
3985 if (mb - eb > 0)
goto underflow;
4016 const char *orig_szVal = szVal;
4017 size_t i, ni, ipn, ipf, nf, ipe,
ne, dot_seen, exp_seen, nalloc;
4028 while (
ISSPACE(*szVal)) szVal++;
4029 if (*szVal !=
'#') {
4058 while ((psz[i] = szVal[ipn]) != 0) {
4064 if (psz[i] ==
'_') {
4099 if (szVal[i] ==
'-') { sign=-1; ++i; }
4100 else if (szVal[i] ==
'+') ++i;
4103 while ((v = szVal[i]) != 0) {
4116 if (szVal[i] ==
'.') {
4120 while ((v = szVal[i]) != 0) {
4137 if ((v ==
'-') || (v ==
'+')) ++i;
4138 while ((v=szVal[i]) != 0) {
4148 if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
4155 if (mx == 0) mx = 1;
4156 nalloc =
Max(nalloc, mx);
4162 VpCtoV(vp, &szVal[ipn], ni, &szVal[ipf], nf, &szVal[ipe], ne);
4203 VpInternalRound(c, n, (n>0) ? a->
frac[n-1] : 0, a->
frac[n]);
4227 Real *a_ptr, *b_ptr;
4228 size_t n, na, nb, i;
4231 #ifdef BIGDECIMAL_DEBUG 4233 VPrint(stdout,
"VpAddSub(enter) a=% \n", a);
4234 VPrint(stdout,
" b=% \n", b);
4235 printf(
" operation=%d\n", operation);
4266 if (operation < 0) sw = -1;
4284 for (i=0; i < n; ++i) {
4290 else if (a->
frac[i] < b->
frac[i]) {
4326 mrv = VpAddAbs(a_ptr, b_ptr, c);
4331 mrv = VpSubAbs(a_ptr, b_ptr, c);
4339 VpInternalRound(c, 0, (c->
Prec > 0) ? c->
frac[c->
Prec-1] : 0, mrv);
4341 #ifdef BIGDECIMAL_DEBUG 4343 VPrint(stdout,
"VpAddSub(result) c=% \n", c);
4344 VPrint(stdout,
" a=% \n", a);
4345 VPrint(stdout,
" b=% \n", b);
4346 printf(
" operation=%d\n", operation);
4365 size_t b_pos, b_pos_with_word_shift;
4367 BDIGIT av, bv, carry, mrv;
4369 #ifdef BIGDECIMAL_DEBUG 4371 VPrint(stdout,
"VpAddAbs called: a = %\n", a);
4372 VPrint(stdout,
" b = %\n", b);
4376 word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
4381 if (word_shift == (
size_t)-1L)
return 0;
4382 if (b_pos == (
size_t)-1L)
goto Assign_a;
4389 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4390 c->
frac[--c_pos] = b->
frac[--b_pos];
4393 if (b_pos == 0 && word_shift > a_pos) {
4394 while (word_shift-- > a_pos) {
4395 c->
frac[--c_pos] = 0;
4401 b_pos_with_word_shift = b_pos + word_shift;
4402 while (a_pos > b_pos_with_word_shift) {
4403 c->
frac[--c_pos] = a->
frac[--a_pos];
4410 c->
frac[--c_pos] = a->
frac[--a_pos] + b->
frac[--b_pos] + carry;
4423 c->
frac[--c_pos] = a->
frac[--a_pos] + carry;
4432 if (c_pos) c->
frac[c_pos - 1] += carry;
4441 #ifdef BIGDECIMAL_DEBUG 4443 VPrint(stdout,
"VpAddAbs exit: c=% \n", c);
4460 size_t b_pos, b_pos_with_word_shift;
4462 BDIGIT av, bv, borrow, mrv;
4464 #ifdef BIGDECIMAL_DEBUG 4466 VPrint(stdout,
"VpSubAbs called: a = %\n", a);
4467 VPrint(stdout,
" b = %\n", b);
4471 word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
4475 if (word_shift == (
size_t)-1L)
return 0;
4476 if (b_pos == (
size_t)-1L)
goto Assign_a;
4490 if (b_pos + word_shift > a_pos) {
4491 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4496 while (word_shift > a_pos) {
4506 b_pos_with_word_shift = b_pos + word_shift;
4507 while (a_pos > b_pos_with_word_shift) {
4508 c->
frac[--c_pos] = a->
frac[--a_pos];
4515 if (a->
frac[--a_pos] < b->
frac[--b_pos] + borrow) {
4520 c->
frac[c_pos] = a->
frac[a_pos] - b->
frac[b_pos] - borrow;
4529 if (a->
frac[--a_pos] < borrow) {
4534 c->
frac[c_pos] = a->
frac[a_pos] - borrow;
4538 if (c_pos) c->
frac[c_pos - 1] -= borrow;
4546 #ifdef BIGDECIMAL_DEBUG 4548 VPrint(stdout,
"VpSubAbs exit: c=% \n", c);
4571 size_t left_word, right_word, word_shift;
4581 left_word = b->
Prec + word_shift;
4582 right_word =
Max(a->
Prec, left_word);
4588 if (right_word > left_word) {
4598 *c_pos = right_word = left_word + 1;
4607 if (*a_pos <= round_limit) {
4608 *av = a->
frac[*a_pos];
4626 if (c->
MaxPrec >= word_shift + 1) {
4627 *b_pos = c->
MaxPrec - word_shift - 1;
4628 if (*b_pos + word_shift <= round_limit) {
4629 *bv = b->
frac[*b_pos];
4655 *c_pos = right_word + 1;
4659 if (!AddExponent(c, 1))
return (
size_t)-1L;
4681 size_t MxIndA, MxIndB, MxIndAB, MxIndC;
4682 size_t ind_c, i, ii, nc;
4683 size_t ind_as, ind_ae, ind_bs;
4688 #ifdef BIGDECIMAL_DEBUG 4690 VPrint(stdout,
"VpMult(Enter): a=% \n", a);
4691 VPrint(stdout,
" b=% \n", b);
4695 if (!VpIsDefOP(c, a, b,
OP_SW_MULT))
return 0;
4718 MxIndA = a->
Prec - 1;
4719 MxIndB = b->
Prec - 1;
4723 if (MxIndC < MxIndAB) {
4732 if (!AddExponent(c, b->
exponent)) {
4738 nc = ind_c = MxIndAB;
4739 memset(c->
frac, 0, (nc + 1) *
sizeof(
BDIGIT));
4741 for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
4743 ind_as = MxIndA - nc;
4747 else if (nc <= MxIndA) {
4748 ind_as = MxIndA - nc;
4749 ind_ae = MxIndA - (nc - MxIndB);
4754 ind_ae = MxIndAB - nc - 1;
4755 ind_bs = MxIndB - (nc - MxIndA);
4758 for (i = ind_as; i <= ind_ae; ++i) {
4771 c->
frac[ii] += carry;
4794 #ifdef BIGDECIMAL_DEBUG 4796 VPrint(stdout,
"VpMult(c=a*b): c=% \n", c);
4797 VPrint(stdout,
" a=% \n", a);
4798 VPrint(stdout,
" b=% \n", b);
4810 size_t word_a, word_b, word_c, word_r;
4811 size_t i, n, ind_a, ind_b, ind_c, ind_r;
4814 BDIGIT borrow, borrow1, borrow2;
4817 #ifdef BIGDECIMAL_DEBUG 4819 VPrint(stdout,
" VpDivd(c=a/b) a=% \n", a);
4820 VPrint(stdout,
" b=% \n", b);
4825 if (!VpIsDefOP(c, a, b,
OP_SW_DIV))
goto Exit;
4855 if (word_a >= word_r)
goto space_error;
4858 while (ind_r <= word_a) {
4859 r->
frac[ind_r] = a->
frac[ind_r - 1];
4863 while (ind_r < word_r) r->
frac[ind_r++] = 0;
4864 while (ind_c < word_c) c->
frac[ind_c++] = 0;
4867 b1 = b1p1 = b->
frac[0];
4869 b1b2p1 = b1b2 = b1p1 *
BASE;
4873 b1b2p1 = b1b2 = b1 *
BASE + b->
frac[1];
4874 if (b->
Prec > 2) ++b1b2p1;
4880 nLoop =
Min(word_c,ind_c);
4882 while (ind_c < nLoop) {
4883 if (r->
frac[ind_c] == 0) {
4892 while (ind_b < word_b) {
4893 if (r->
frac[ind_a] < b->
frac[ind_b])
goto div_b1p1;
4894 if (r->
frac[ind_a] > b->
frac[ind_b])
break;
4902 ind_b = b->
Prec - 1;
4903 ind_r = ind_c + ind_b;
4904 if (ind_r >= word_r)
goto space_error;
4906 for (i = 0; i <= n; ++i) {
4907 if (r->
frac[ind_r] < b->
frac[ind_b] + borrow) {
4912 r->
frac[ind_r] = r->
frac[ind_r] - b->
frac[ind_b] - borrow;
4923 if (r1r2 >= b1b2p1) {
4926 ind_r = b->
Prec + ind_c - 1;
4931 if (ind_c + 1 >= word_c)
goto out_side;
4934 ind_r = b->
Prec + ind_c;
4937 borrow1 = borrow2 = 0;
4939 if (ind_r >= word_r)
goto space_error;
4941 for (i = 0; i <= n; ++i) {
4943 qb = q * b->
frac[ind_b];
4944 if (qb <
BASE) borrow1 = 0;
4949 if(r->
frac[ind_r] < qb) {
4951 borrow2 = borrow2 + borrow1 + 1;
4958 if(r->
frac[ind_r - 1] < borrow2) {
4959 r->
frac[ind_r - 1] += (
BASE - borrow2);
4963 r->
frac[ind_r - 1] -= borrow2;
4971 r->
frac[ind_r] -= borrow2;
4984 if (!AddExponent(c, 2))
return 0;
4985 if (!AddExponent(c, -(b->
exponent)))
return 0;
4991 if (!AddExponent(r, 1))
return 0;
4997 #ifdef BIGDECIMAL_DEBUG 4999 printf(
" word_a=%"PRIuSIZE"\n", word_a);
5000 printf(
" word_b=%"PRIuSIZE"\n", word_b);
5001 printf(
" word_c=%"PRIuSIZE"\n", word_c);
5002 printf(
" word_r=%"PRIuSIZE"\n", word_r);
5003 printf(
" ind_r =%"PRIuSIZE"\n", ind_r);
5006 rb_bug(
"ERROR(VpDivd): space for remainder too small.");
5009 #ifdef BIGDECIMAL_DEBUG 5011 VPrint(stdout,
" VpDivd(c=a/b), c=% \n", c);
5012 VPrint(stdout,
" r=% \n", r);
5032 if (a->
frac[ind_a]) {
5033 a->
Prec = ind_a + 1;
5035 while (a->
frac[i] == 0) ++i;
5072 if (e > 0)
return 1;
5073 else if (e < 0)
return -1;
5078 if (e > 0)
return 1;
5134 if (val > 1) val = 1;
5135 else if (val < -1) val = -1;
5137 #ifdef BIGDECIMAL_DEBUG 5139 VPrint(stdout,
" VpComp a=%\n", a);
5140 VPrint(stdout,
" b=%\n", b);
5141 printf(
" ans=%d\n", val);
5157 #ifdef BIGDECIMAL_ENABLE_VPRINT 5159 VPrint(
FILE *fp,
const char *cntl_chr,
Real *a)
5161 size_t i, j, nc, nd, ZeroSup, sep = 10;
5169 while (*(cntl_chr + j)) {
5170 if (*(cntl_chr + j) ==
'%' && *(cntl_chr + j + 1) !=
'%') {
5189 nc += fprintf(fp,
"0.");
5190 switch (*(cntl_chr + j + 1)) {
5200 for (i = 0; i < a->
Prec; ++i) {
5205 if (!ZeroSup || nn) {
5206 nc += fprintf(fp,
"%lu", (
unsigned long)nn);
5214 nc += fprintf(fp,
" ");
5224 nc += fprintf(fp,
"0.0");
5229 if (*(cntl_chr + j) ==
'\\') {
5230 switch (*(cntl_chr + j + 1)) {
5244 fprintf(fp,
"%c", *(cntl_chr + j));
5249 fprintf(fp,
"%c", *(cntl_chr + j));
5250 if (*(cntl_chr + j) ==
'%') ++j;
5261 VpFormatSt(
char *psz,
size_t fFmt)
5263 size_t ie, i, nf = 0;
5266 if (fFmt == 0)
return;
5269 for (i = 0; i < ie; ++i) {
5272 if (
ISSPACE(ch) || ch==
'-' || ch==
'+')
continue;
5273 if (ch ==
'.') { nf = 0;
continue; }
5274 if (ch ==
'E' || ch ==
'e')
break;
5277 memmove(psz + i + 1, psz + i, ie - i + 1);
5295 while ((a->
frac[0] / n) == 0) {
5305 size_t i, n, ZeroSup;
5325 for (i = 0; i < n; ++i) {
5330 if (!ZeroSup || nn) {
5331 sprintf(psz,
"%lu", (
unsigned long)nn);
5341 while (psz[-1] ==
'0') *(--psz) = 0;
5345 else sprintf(psz,
"-0");
5362 else if (fPlus == 2) {
5374 if (fPlus == 1) sprintf(psz,
" 0.0");
5375 else if (fPlus == 2) sprintf(psz,
"+0.0");
5376 else sprintf(psz,
"0.0");
5378 else sprintf(psz,
"-0.0");
5388 size_t i, n, ZeroSup;
5398 else if (fPlus == 1) *psz++ =
' ';
5399 else if (fPlus == 2) *psz++ =
'+';
5404 for (i = 0; i < n; ++i) {
5409 if (!ZeroSup || nn) {
5410 sprintf(psz,
"%lu", (
unsigned long)nn);
5421 while (a->
frac[0] / shift == 0) {
5425 while (psz[-1] ==
'0') {
5429 if (fFmt) VpFormatSt(pszSav, fFmt);
5444 else if (fPlus == 1) *psz++ =
' ';
5445 else if (fPlus == 2) *psz++ =
'+';
5450 *psz++ =
'0';*psz++ =
'.';
5452 for (i=0; i <
BASE_FIG; ++i) *psz++ =
'0';
5458 for (i = 0; i < n; ++i) {
5460 if (i == 0 && ex >= 0) {
5461 sprintf(psz,
"%lu", (
unsigned long)a->
frac[i]);
5469 *psz++ = (char)(nn +
'0');
5474 if (ex == 0) *psz++ =
'.';
5478 while (m /= 10) *psz++ =
'0';
5479 if (ex == 0) *psz++ =
'.';
5482 while (psz[-1] ==
'0') *(--psz) = 0;
5483 if (psz[-1] ==
'.') sprintf(psz,
"0");
5484 if (fFmt) VpFormatSt(pszSav, fFmt);
5499 VpCtoV(
Real *a,
const char *int_chr,
size_t ni,
const char *frac,
size_t nf,
const char *exp_chr,
size_t ne)
5501 size_t i, j, ind_a, ma, mi, me;
5503 int sign, signe, exponent_overflow;
5511 exponent_overflow = 0;
5515 if (exp_chr[0] ==
'-') {
5520 else if (exp_chr[0] ==
'+') {
5533 e = e * 10 + exp_chr[i] -
'0';
5538 exponent_overflow = 1;
5550 if (int_chr[0] ==
'-') {
5555 else if (int_chr[0] ==
'+') {
5564 if (e > 0) signe = 1;
5583 if (exponent_overflow) {
5585 for ( ; i < mi && zero; i++) zero = int_chr[i] ==
'0';
5586 for (i = 0; i < nf && zero; i++) zero = frac[i] ==
'0';
5587 if (!zero && signe > 0) {
5599 a->
frac[ind_a] = a->
frac[ind_a] * 10 + int_chr[i] -
'0';
5605 if (ind_a >= ma)
goto over_flow;
5615 a->
frac[ind_a] = a->
frac[ind_a] * 10 + frac[i] -
'0';
5621 if (ind_a >= ma)
goto over_flow;
5628 rb_warn(
"Conversion from String to BigDecimal overflow (last few digits discarded).");
5631 if (ind_a >= ma) ind_a = ma - 1;
5633 a->
frac[ind_a] = a->
frac[ind_a] * 10;
5636 a->
Prec = ind_a + 1;
5661 size_t ind_m, mm, fig;
5701 while (ind_m < mm) {
5702 div /= (double)
BASE;
5703 *d = *d + (double)m->
frac[ind_m++] * div;
5709 #ifdef BIGDECIMAL_DEBUG 5711 VPrint(stdout,
" VpVtoD: m=%\n", m);
5712 printf(
" d=%e * 10 **%ld\n", *d, *e);
5713 printf(
" DBLE_FIG = %d\n",
DBLE_FIG);
5744 val = (d > 0.) ? d : -d;
5747 while (val >= 1.0) {
5748 val /= (double)
BASE;
5753 val2 = 1.0 / (double)
BASE;
5754 while (val < val2) {
5755 val *= (double)
BASE;
5763 for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
5764 val *= (double)
BASE;
5769 if (ind_m >= mm) ind_m = mm - 1;
5771 m->
Prec = ind_m + 1;
5774 VpInternalRound(m, 0, (m->
Prec > 0) ? m->
frac[m->
Prec-1] : 0,
5778 #ifdef BIGDECIMAL_DEBUG 5780 printf(
"VpDtoV d=%30.30e\n", d);
5781 VPrint(stdout,
" m=%\n", m);
5795 size_t val, v1, v2, v;
5807 val =(size_t)(-ival);
5812 while (ind_m < mm) {
5821 while (v1 >=
BASE) {
5825 val = val - v2 * v1;
5835 m->
Prec = ind_m - 1;
5841 #ifdef BIGDECIMAL_DEBUG 5843 printf(
" VpItoV i=%d\n", ival);
5844 VPrint(stdout,
" m=%\n", m);
5899 prec = x->
exponent - (ssize_t)y_prec;
5908 if (e - n * 2 != 0) {
5931 #ifdef BIGDECIMAL_DEBUG 5933 printf(
"ERROR(VpSqrt): did not converge within %ld iterations.\n", nr);
5940 #ifdef BIGDECIMAL_DEBUG 5944 printf(
"VpSqrt: iterations = %"PRIdSIZE"\n", nr);
5945 VPrint(stdout,
" y =% \n", y);
5946 VPrint(stdout,
" x =% \n", x);
5947 VPrint(stdout,
" x-y*y = % \n", f);
5969 int fracf, fracf_1further;
5970 ssize_t n,i,ix,ioffset, exptoadd;
5987 if ((
size_t)ix >= y->
Prec)
return 0;
5990 ioffset = nf - ix*(ssize_t)
BASE_FIG;
5991 n = (ssize_t)
BASE_FIG - ioffset - 1;
5992 for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
6021 fracf = (v % (shifter * 10) > 0);
6022 fracf_1further = ((v % shifter) > 0);
6038 for (i = ix + 1; (size_t)i < y->Prec; i++) {
6040 fracf = fracf_1further = 1;
6051 memset(y->
frac + ix + 1, 0, (y->
Prec - (ix + 1)) *
sizeof(
BDIGIT));
6063 if (v > 5 || (v == 5 && fracf_1further)) ++
div;
6074 if (fracf_1further) {
6084 if (ix && (y->
frac[ix-1] % 2)) ++
div;
6093 for (i = 0; i <= n; ++i) div *= 10;
6114 for (i = 0; i < exptoadd; i++) {
6135 while ((v /= 10) != 0) nf--;
6144 if (
VpAsgn(y, x, 10) <= 1)
return 0;
6149 VpLimitRound(
Real *c,
size_t ixDigit)
6152 if (!VpNmlz(c))
return -1;
6154 if (!ixDigit) ixDigit = c->
Prec-1;
6168 if (VpLimitRound(c, ixDigit))
return;
6172 switch (rounding_mode) {
6197 else if (v == 5 && vPrev % 2) f = 1;
6210 VpRdup(
Real *m,
size_t ind_m)
6214 if (!ind_m) ind_m = m->
Prec;
6217 while (carry > 0 && ind_m--) {
6218 m->
frac[ind_m] += carry;
6223 if (!AddExponent(m, 1))
return 0;
6238 size_t my, ind_y, ind_x;
6263 while (ind_y < my) {
6271 #ifdef BIGDECIMAL_DEBUG 6273 VPrint(stdout,
"VpFrac y=%\n", y);
6274 VPrint(stdout,
" x=%\n", x);
6299 if (sign < 0) sign = (n % 2) ? -1 : 1;
6303 if (sign < 0) sign = (n % 2) ? -1 : 1;
6329 if ((n % 2) == 0)
goto Exit;
6334 if (n > 0) sign = 1;
6355 while (ss = s, (s += s) <= (
size_t)n) {
6364 VpDivd(w1, w2, VpConstOne, y);
6369 #ifdef BIGDECIMAL_DEBUG 6371 VPrint(stdout,
"VpPower y=%\n", y);
6372 VPrint(stdout,
"VpPower x=%\n", x);
6381 #ifdef BIGDECIMAL_DEBUG 6383 VpVarCheck(
Real * v)
6396 printf(
"ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
6401 printf(
"ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->
Prec);
6405 for (i = 0; i < v->
Prec; ++i) {
6407 printf(
"ERROR(VpVarCheck): Illegal fraction\n");
6411 printf(
" BASE =%"PRIuBDIGIT
"\n",
BASE);
VP_EXPORT size_t VpDivd(Real *c, Real *r, Real *a, Real *b)
VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
void rb_fatal(const char *fmt,...)
VP_EXPORT double VpGetDoublePosInf(void)
#define RMPD_EXCEPTION_MODE_DEFAULT
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
void rb_warn(const char *fmt,...)
void rb_bug(const char *fmt,...)
VP_EXPORT int VpException(unsigned short f, const char *str, int always)
#define RUBY_TYPED_FREE_IMMEDIATELY
size_t strlen(const char *)
VALUE rb_Rational(VALUE, VALUE)
#define BigMath_exp(x, n)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
VP_EXPORT int VpIsRoundMode(unsigned short n)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
#define VP_SIGN_POSITIVE_FINITE
void rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
#define VP_SIGN_NEGATIVE_ZERO
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define DECIMAL_SIZE_OF_BITS(n)
VALUE rb_ary_push(VALUE ary, VALUE item)
if(len<=MAX_WORD_LENGTH &&len >=MIN_WORD_LENGTH)
RUBY_EXTERN VALUE rb_eMathDomainError
st_index_t rb_memhash(const void *ptr, long len)
VP_EXPORT unsigned short VpGetRoundMode(void)
VP_EXPORT unsigned short VpSetRoundMode(unsigned short n)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
VP_EXPORT void VpDtoV(Real *m, double d)
VP_EXPORT void VpFrac(Real *y, Real *x)
#define VP_SIGN_POSITIVE_ZERO
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define VP_ROUND_HALF_DOWN
#define VP_SIGN_POSITIVE_INFINITE
#define VP_EXCEPTION_OVERFLOW
#define RRATIONAL_NEGATIVE_P(x)
VP_EXPORT Real * VpCreateRbObject(size_t mx, const char *str)
VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_str_tmp_new(long)
RUBY_EXTERN VALUE rb_eZeroDivError
#define DoSomeOne(x, y, f)
VP_EXPORT int VpComp(Real *a, Real *b)
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf)
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)
VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
RUBY_EXTERN void * memmove(void *, const void *, size_t)
#define VP_EXCEPTION_INFINITY
VALUE rb_thread_local_aref(VALUE, ID)
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
VP_EXPORT Real * VpNewRbClass(size_t mx, const char *str, VALUE klass)
#define VP_SIGN_NEGATIVE_FINITE
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
#define RB_TYPE_P(obj, type)
#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b)
VALUE rb_class_name(VALUE)
VALUE rb_dbl2big(double d)
#define RMPD_COMPONENT_FIGURES
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE))
#define VP_EXCEPTION_UNDERFLOW
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_big_cmp(VALUE x, VALUE y)
#define rmpd_set_thread_local_exception_mode(mode)
VALUE rb_thread_current(void)
VP_EXPORT double VpGetDoubleNaN(void)
VP_EXPORT size_t VpGetPrecLimit(void)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VP_EXPORT void * VpMemAlloc(size_t mb)
#define BDIGIT_DBL_SIGNED
void rb_define_const(VALUE, const char *, VALUE)
#define VpAllocReal(prec)
VP_EXPORT size_t VpMult(Real *c, Real *a, Real *b)
volatile const double gOne_ABCED9B4_CE73__00400511F31D
VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
#define MEMCPY(p1, p2, type, n)
RUBY_EXTERN int isinf(double)
VP_EXPORT Real * VpOne(void)
#define BIGDECIMAL_POSITIVE_P(bd)
VP_EXPORT void VpSzMantissa(Real *a, char *psz)
VALUE rb_big2str(VALUE x, int base)
VP_EXPORT void VpFree(Real *pv)
void Init_bigdecimal(void)
VALUE rb_str_resize(VALUE, long)
#define VP_EXCEPTION_ZERODIVIDE
volatile const double gZero_ABCED9B1_CE73__00400511F31D
#define VP_SIGN_NEGATIVE_INFINITE
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VP_EXPORT Real * VpAlloc(size_t mx, const char *szVal)
#define rmpd_set_thread_local_rounding_mode(mode)
unsigned char buf[MIME_BUF_SIZE]
VALUE rb_assoc_new(VALUE car, VALUE cdr)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
#define VP_EXCEPTION_MEMORY
#define BIGDECIMAL_NEGATIVE_P(bd)
VP_EXPORT size_t VpInit(BDIGIT BaseVal)
VALUE rb_num_coerce_relop(VALUE, VALUE, ID)
RUBY_EXTERN VALUE rb_cNumeric
VP_EXPORT double VpGetDoubleNegInf(void)
register unsigned int len
#define StringValueCStr(v)
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw)
BDIGIT frac[FLEXIBLE_ARRAY_SIZE]
#define RMPD_PRECISION_LIMIT_DEFAULT
#define rmpd_set_thread_local_precision_limit(limit)
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
#define VpChangeSign(a, s)
#define RARRAY_AREF(a, i)
RUBY_EXTERN double round(double)
#define RB_OBJ_CLASSNAME(obj)
VP_EXPORT int VpToSpecialString(Real *a, char *psz, int fPlus)
#define RMPD_ROUNDING_MODE_DEFAULT
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf)
VP_EXPORT size_t VpAddSub(Real *c, Real *a, Real *b, int operation)
VALUE rb_check_string_type(VALUE)
void rb_thread_check_ints(void)
void rb_check_safe_obj(VALUE)
VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n)
#define VP_ROUND_HALF_EVEN
VP_EXPORT size_t VpSetPrecLimit(size_t n)
RUBY_EXTERN VALUE rb_eFloatDomainError
#define RRATIONAL_ZERO_P(x)
#define BigMath_log(x, n)
#define RTYPEDDATA_DATA(v)
VP_EXPORT size_t VpNumOfChars(Real *vp, const char *pszFmt)
#define rb_intern_const(str)
VALUE rb_define_module(const char *name)
VP_EXPORT double VpGetDoubleNegZero(void)
#define VpReallocReal(ptr, prec)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VP_EXPORT void * VpMemRealloc(void *ptr, size_t mb)
VP_EXPORT ssize_t VpExponent10(Real *a)
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
VALUE rb_str_new(const char *, long)
VP_EXPORT int VpSqrt(Real *y, Real *x)