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 rmpd_double_figures()
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
108rb_rational_num(
VALUE rat)
110#ifdef HAVE_TYPE_STRUCT_RRATIONAL
118#ifndef HAVE_RB_RATIONAL_DEN
120rb_rational_den(
VALUE rat)
122#ifdef HAVE_TYPE_STRUCT_RRATIONAL
130#ifndef HAVE_RB_COMPLEX_REAL
134#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
142#ifndef HAVE_RB_COMPLEX_IMAG
146#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
154#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
155#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
160#define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
165static unsigned short VpGetException(
void);
166static void VpSetException(
unsigned short f);
167static void VpInternalRound(
Real *c,
size_t ixDigit,
BDIGIT vPrev,
BDIGIT v);
168static int VpLimitRound(
Real *c,
size_t ixDigit);
171#ifdef BIGDECIMAL_ENABLE_VPRINT
172static int VPrint(
FILE *fp,
const char *cntl_chr,
Real *a);
180BigDecimal_delete(
void *pv)
186BigDecimal_memsize(
const void *
ptr)
192#ifndef HAVE_RB_EXT_RACTOR_SAFE
193# undef RUBY_TYPED_FROZEN_SHAREABLE
194# define RUBY_TYPED_FROZEN_SHAREABLE 0
199 { 0, BigDecimal_delete, BigDecimal_memsize, },
200#ifdef RUBY_TYPED_FREE_IMMEDIATELY
206is_kind_of_BigDecimal(
VALUE const v)
229cannot_be_coerced_into_BigDecimal(
VALUE exc_class,
VALUE v)
233 if (rb_special_const_p(v)) {
247GetVpValueWithPrec(
VALUE v,
long prec,
int must)
259 if (prec < 0)
goto unable_to_coerce_without_prec;
260 if (prec > (
long)
DBLE_FIG)
goto SomeOneMayDoIt;
277 if (prec < 0)
goto unable_to_coerce_without_prec;
279 if (orig ==
Qundef ? (orig = v, 1) : orig != v) {
280 num = rb_rational_num(v);
281 pv = GetVpValueWithPrec(
num, -1, must);
282 if (pv ==
NULL)
goto SomeOneMayDoIt;
284 v = BigDecimal_div2(ToValue(pv), rb_rational_den(v),
LONG2NUM(prec));
292 if (is_kind_of_BigDecimal(v)) {
305#ifdef ENABLE_NUMERIC_STRING
327unable_to_coerce_without_prec:
330 "%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
337GetVpValue(
VALUE v,
int must)
339 return GetVpValueWithPrec(v, -1, must);
350BigDecimal_double_fig(
VALUE self)
370BigDecimal_prec(
VALUE self)
377 "BigDecimal#precs is deprecated and will be removed in the future; "
378 "use BigDecimal#precision instead.");
403BigDecimal_precision(
VALUE self)
421 ssize_t precision = 0;
426 else if (p->
Prec > 0) {
428 for (precision = 0; x > 0; x /= 10) {
433 if (ex > (ssize_t)p->
Prec) {
436 else if (p->
Prec > 0) {
437 ssize_t n = (ssize_t)p->
Prec - 1;
438 while (n > 0 && p->
frac[n] == 0) --n;
442 if (ex < (ssize_t)p->
Prec) {
444 for (; x > 0 && x % 10 == 0; x /= 10) {
454BigDecimal_n_significant_digits(
VALUE self)
462 while (n > 0 && p->
frac[n-1] == 0) --n;
470 for (nlz =
BASE_FIG; x > 0; x /= 10) --nlz;
473 for (ntz = 0; x > 0 && x % 10 == 0; x /= 10) ++ntz;
475 ssize_t n_digits =
BASE_FIG * n - nlz - ntz;
488BigDecimal_hash(
VALUE self)
549 while((*pch) != (
unsigned char)
'\0' && (ch = *pch++) != (
unsigned char)
':') {
553 m = m*10 + (
unsigned long)(ch-
'0');
565check_rounding_mode_option(
VALUE const opts)
584 if (
NIL_P(str_mode))
goto invalid;
614check_rounding_mode(
VALUE const v)
623 if (
id == id_down ||
id == id_truncate)
625 if (
id == id_half_up ||
id == id_default)
627 if (
id == id_half_down)
629 if (
id == id_half_even ||
id == id_banker)
631 if (
id == id_ceiling ||
id == id_ceil)
698 fo = VpGetException();
708 fo = VpGetException();
713 fo = VpGetException();
718 fo = VpGetException();
723 fo = VpGetException();
731 sw = check_rounding_mode(val);
747 if (mx < b->Prec) mx = b->
Prec;
761GetPrecisionInt(
VALUE v)
788#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
789#define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
792VpCopy(
Real *pv,
Real const*
const x)
809BigDecimal_IsNaN(
VALUE self)
811 Real *p = GetVpValue(self, 1);
820BigDecimal_IsInfinite(
VALUE self)
822 Real *p = GetVpValue(self, 1);
830BigDecimal_IsFinite(
VALUE self)
832 Real *p = GetVpValue(self, 1);
839BigDecimal_check_num(
Real *p)
859BigDecimal_to_i(
VALUE self)
866 BigDecimal_check_num(p);
875 VALUE a = BigDecimal_split(self);
906BigDecimal_to_f(
VALUE self)
916 if (
VpVtoD(&d, &e, p) != 1)
928 if (errno == ERANGE) {
929 if (d == 0.0)
goto underflow;
930 if (fabs(d) >=
HUGE_VAL)
goto overflow;
953BigDecimal_to_r(
VALUE self)
956 ssize_t sign, power, denomi_power;
957 VALUE a, digits, numerator;
959 p = GetVpValue(self, 1);
960 BigDecimal_check_num(p);
964 a = BigDecimal_split(self);
972 if (denomi_power < 0) {
1005 if (RB_TYPE_P(other,
T_FLOAT)) {
1033BigDecimal_uplus(
VALUE self)
1064 b = GetVpValueWithPrec(r,
DBLE_FIG, 1);
1070 b = GetVpValue(r, 0);
1079 mx = GetAddSubPrec(a, b);
1080 if (mx == (
size_t)-1L) {
1122 b = GetVpValueWithPrec(r,
DBLE_FIG, 1);
1128 b = GetVpValue(r,0);
1137 mx = GetAddSubPrec(a,b);
1138 if (mx == (
size_t)-1L) {
1163 if (!is_kind_of_BigDecimal(r))
break;
1220 if (e == 0)
return Qtrue;
1224 if (e >= 0)
return Qtrue;
1228 if (e > 0)
return Qtrue;
1232 if (e <= 0)
return Qtrue;
1236 if (e < 0)
return Qtrue;
1243 rb_bug(
"Undefined operation in BigDecimalCmp()");
1250BigDecimal_zero(
VALUE self)
1252 Real *a = GetVpValue(self, 1);
1258BigDecimal_nonzero(
VALUE self)
1260 Real *a = GetVpValue(self, 1);
1270 return BigDecimalCmp(self, r,
'*');
1286 return BigDecimalCmp(self, r,
'=');
1299 return BigDecimalCmp(self, r,
'<');
1312 return BigDecimalCmp(self, r,
'L');
1325 return BigDecimalCmp(self, r,
'>');
1338 return BigDecimalCmp(self, r,
'G');
1351BigDecimal_neg(
VALUE self)
1385 b = GetVpValueWithPrec(r,
DBLE_FIG, 1);
1391 b = GetVpValue(r,0);
1413 b = GetVpValueWithPrec(r,
DBLE_FIG, 1);
1419 b = GetVpValue(r, 0);
1451 r = BigDecimal_divide(&c, &res, &
div, self, r);
1452 if (!
NIL_P(r))
return r;
1479 b = GetVpValueWithPrec(r,
DBLE_FIG, 1);
1485 b = GetVpValue(r, 0);
1563 if (BigDecimal_DoDivmod(self, r, &
div, &
mod)) {
1565 return ToValue(
mod);
1580 b = GetVpValueWithPrec(r,
DBLE_FIG, 1);
1586 b = GetVpValue(r, 0);
1628 f = BigDecimal_divremain(self, r, &d, &rv);
1661 if (BigDecimal_DoDivmod(self, r, &
div, &
mod)) {
1680 if (BigDecimal_DoDivmod(self, b, &
div, &
mod)) {
1681 return BigDecimal_to_i(ToValue(
div));
1687 ix = GetPrecisionInt(n);
1689 return BigDecimal_div(self, b);
1700 mx = av->
Prec + bv->Prec + 2;
1701 if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
1748 return BigDecimal_div2(self, b, n);
1757 if (mx == 0)
return BigDecimal_add(self, b);
1760 VALUE c = BigDecimal_add(self, b);
1787 if (mx == 0)
return BigDecimal_sub(self, b);
1790 VALUE c = BigDecimal_sub(self, b);
1805 if (mx == 0)
return BigDecimal_mult(self, b);
1808 VALUE c = BigDecimal_mult(self, b);
1827BigDecimal_abs(
VALUE self)
1859 if (mx <= n) mx = n;
1868BigDecimal_fix(
VALUE self)
1914 int round_to_int = 0;
1925 if (RB_TYPE_P(vLoc,
T_HASH)) {
1926 sw = check_rounding_mode_option(vLoc);
1930 if (iLoc < 1) round_to_int = 1;
1935 if (RB_TYPE_P(vRound,
T_HASH)) {
1936 sw = check_rounding_mode_option(vRound);
1939 sw = check_rounding_mode(vRound);
1953 return BigDecimal_to_i(ToValue(c));
1999 return BigDecimal_to_i(ToValue(c));
2007BigDecimal_frac(
VALUE self)
2058#ifdef BIGDECIMAL_DEBUG
2059 VPrint(stderr,
"floor: c=%\n", c);
2062 return BigDecimal_to_i(ToValue(c));
2105 return BigDecimal_to_i(ToValue(c));
2166 else if (*psz ==
'+') {
2170 while ((ch = *psz++) != 0) {
2175 if (ch ==
'F' || ch ==
'f') {
2180 mc = mc*10 + ch -
'0';
2198 nc += (nc + mc - 1) / mc + 1;
2239BigDecimal_split(
VALUE self)
2252 if(psz1[0] ==
'-') {
2259 if (psz1[0] ==
'N') s = 0;
2276BigDecimal_exponent(
VALUE self)
2288BigDecimal_inspect(
VALUE self)
2307#define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n))
2308#define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n))
2325 else if (RB_TYPE_P(x,
T_FLOAT)) {
2331#define is_positive(x) (!is_negative(x))
2346 num = rb_rational_num(x);
2369 num = rb_rational_num(x);
2370 den = rb_rational_den(x);
2403rmpd_power_by_big_decimal(
Real const* x,
Real const* exp, ssize_t
const n)
2405 VALUE log_x, multiplied, y;
2413 multiplied = BigDecimal_mult2(exp->
obj, log_x,
SSIZET2NUM(n+1));
2454 switch (
TYPE(vexp)) {
2463 if (d ==
round(d)) {
2475 exp = GetVpValueWithPrec(vexp,
DBLE_FIG, 1);
2479 if (is_zero(rb_rational_num(vexp))) {
2485 else if (is_one(rb_rational_den(vexp))) {
2486 vexp = rb_rational_num(vexp);
2489 exp = GetVpValueWithPrec(vexp, n, 1);
2496 if (is_kind_of_BigDecimal(vexp)) {
2498 VALUE rounded = BigDecimal_round(1, &zero, vexp);
2499 if (
RTEST(BigDecimal_eq(vexp, rounded))) {
2500 vexp = BigDecimal_to_i(vexp);
2513 "wrong argument type %"PRIsVALUE" (expected scalar Numeric)",
2518 if (is_negative(vexp)) {
2522 if (is_integer(vexp)) {
2523 if (is_even(vexp)) {
2543 else if (is_zero(vexp)) {
2551 if (is_zero(vexp)) {
2554 else if (is_one(vexp)) {
2559 if (is_negative(vexp)) {
2561 if (is_integer(vexp)) {
2562 if (is_even(vexp)) {
2583 if (is_integer(vexp)) {
2584 if (is_even(vexp)) {
2594 "a non-integral exponent for a negative base");
2605 return rmpd_power_by_big_decimal(x, exp, n);
2607 else if (RB_TYPE_P(vexp,
T_BIGNUM)) {
2608 VALUE abs_value = BigDecimal_abs(self);
2609 if (is_one(abs_value)) {
2613 if (is_negative(vexp)) {
2615 if (is_even(vexp)) {
2633 if (is_even(vexp)) {
2652 if (ma < 0) ma = -ma;
2653 if (ma == 0) ma = 1;
2679 return BigDecimal_power(1, &exp, self);
2687BigDecimal_initialize_copy(
VALUE self,
VALUE other)
2692 if (self != other) {
2699BigDecimal_clone(
VALUE self)
2704#ifdef HAVE_RB_OPTS_EXCEPTION_P
2706#define opts_exception_p(opts) rb_opts_exception_p((opts), 1)
2714 kwds[0] = rb_intern_const(
"exception");
2717 switch (exception) {
2724 return exception !=
Qfalse;
2759 if (!exc)
return NULL;
2762 if (!exc)
return NULL;
2765 if (!exc)
return NULL;
2773 switch (
TYPE(iniValue)) {
2775 if (is_kind_of_BigDecimal(iniValue)) {
2783 return GetVpValue(iniValue, 1);
2805 "can't omit precision for a %"PRIsVALUE".",
2808 return GetVpValueWithPrec(iniValue, mf, 1);
2816 "Unable to make a BigDecimal from non-zero imaginary number");
2886 if (ToValue(pv)) pv = VpCopy(
NULL, pv);
2889 return pv->
obj = obj;
2926 if (
NIL_P(nFig))
return nCur;
2953BigDecimal_sign(
VALUE self)
2955 int s = GetVpValue(self, 1)->
sign;
2978BigDecimal_save_exception_mode(
VALUE self)
2980 unsigned short const exception_mode = VpGetException();
2983 VpSetException(exception_mode);
3003BigDecimal_save_rounding_mode(
VALUE self)
3028BigDecimal_save_limit(
VALUE self)
3068 if (!is_kind_of_BigDecimal(x))
break;
3078 vx = GetVpValue(x, 0);
3084 infinite =
isinf(flo);
3086 if (!infinite && !
nan) {
3087 vx = GetVpValueWithPrec(x,
DBLE_FIG, 0);
3092 vx = GetVpValueWithPrec(x, prec, 0);
3100 return ToValue(GetVpValueWithPrec(
INT2FIX(0), prec, 1));
3117 else if (vx ==
NULL) {
3122 n = prec + rmpd_double_figures();
3126 VALUE x_copy = f_BigDecimal(1, &x_zero, klass);
3127 x = BigDecimal_initialize_copy(x_copy, x);
3140 ssize_t m = n -
vabs(ey - ed);
3147 else if ((
size_t)m < rmpd_double_figures()) {
3148 m = rmpd_double_figures();
3151 d = BigDecimal_mult(d, x);
3153 y = BigDecimal_add(y, d);
3158 return BigDecimal_div2(one, y, vprec);
3162 return BigDecimal_round(1, &vprec, y);
3189 VALUE vn, one, two, w, x2, y, d;
3197 if (!is_integer(vprec)) {
3210 if (!is_kind_of_BigDecimal(x))
break;
3229 if (zero || negative)
break;
3230 vx = GetVpValue(x, 0);
3237 infinite =
isinf(flo);
3239 if (!zero && !negative && !infinite && !
nan) {
3240 vx = GetVpValueWithPrec(x,
DBLE_FIG, 1);
3247 if (zero || negative)
break;
3248 vx = GetVpValueWithPrec(x, prec, 1);
3253 "Complex argument for BigMath.log");
3258 if (infinite && !negative) {
3272 else if (zero || negative) {
3274 "Zero or negative argument for log");
3276 else if (vx ==
NULL) {
3284 n = prec + rmpd_double_figures();
3287 if (expo < 0 || expo >= 3) {
3295 w = BigDecimal_sub(x, one);
3296 x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
3304 ssize_t m = n -
vabs(ey - ed);
3308 else if ((
size_t)m < rmpd_double_figures()) {
3309 m = rmpd_double_figures();
3312 x = BigDecimal_mult2(x2, x, vn);
3315 y = BigDecimal_add(y, d);
3318 y = BigDecimal_mult(y, two);
3320 VALUE log10, vexpo, dy;
3321 log10 = BigMath_s_log(klass,
INT2FIX(10), vprec);
3322 vexpo = ToValue(GetVpValue(
SSIZET2NUM(expo), 1));
3323 dy = BigDecimal_mult(log10, vexpo);
3324 y = BigDecimal_add(y, dy);
3458#ifdef HAVE_RB_EXT_RACTOR_SAFE
3463 id_BigDecimal_exception_mode = rb_intern_const(
"BigDecimal.exception_mode");
3464 id_BigDecimal_rounding_mode = rb_intern_const(
"BigDecimal.rounding_mode");
3465 id_BigDecimal_precision_limit = rb_intern_const(
"BigDecimal.precision_limit");
3491#ifndef RUBY_BIGDECIMAL_VERSION
3492# error RUBY_BIGDECIMAL_VERSION is not defined
3671 id_up = rb_intern_const(
"up");
3672 id_down = rb_intern_const(
"down");
3673 id_truncate = rb_intern_const(
"truncate");
3674 id_half_up = rb_intern_const(
"half_up");
3675 id_default = rb_intern_const(
"default");
3676 id_half_down = rb_intern_const(
"half_down");
3677 id_half_even = rb_intern_const(
"half_even");
3678 id_banker = rb_intern_const(
"banker");
3679 id_ceiling = rb_intern_const(
"ceiling");
3680 id_ceil = rb_intern_const(
"ceil");
3681 id_floor = rb_intern_const(
"floor");
3682 id_to_r = rb_intern_const(
"to_r");
3683 id_eq = rb_intern_const(
"==");
3684 id_half = rb_intern_const(
"half");
3696#ifdef BIGDECIMAL_DEBUG
3697static int gfDebug = 1;
3699static int gfCheckVal = 1;
3703static Real *VpConstOne;
3709#define MemCmp(x,y,z) memcmp(x,y,z)
3710#define StrCmp(x,y) strcmp(x,y)
3723static 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);
3724static int VpNmlz(
Real *a);
3725static void VpFormatSt(
char *psz,
size_t fFmt);
3726static int VpRdup(
Real *m,
size_t ind_m);
3728#ifdef BIGDECIMAL_DEBUG
3729# ifdef HAVE_RB_EXT_RACTOR_SAFE
3730# error Need to make rewiting gnAlloc atomic
3732static int gnAlloc = 0;
3743#ifdef BIGDECIMAL_DEBUG
3764#ifdef BIGDECIMAL_DEBUG
3767 printf(
" *************** All memories allocated freed ****************\n");
3771 printf(
" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
3782#define rmpd_set_thread_local_exception_mode(mode) \
3783 rb_thread_local_aset( \
3784 rb_thread_current(), \
3785 id_BigDecimal_exception_mode, \
3786 INT2FIX((int)(mode)) \
3789static unsigned short
3790VpGetException (
void)
3794 id_BigDecimal_exception_mode
3806VpSetException(
unsigned short f)
3815#define rmpd_set_thread_local_precision_limit(limit) \
3816 rb_thread_local_aset( \
3817 rb_thread_current(), \
3818 id_BigDecimal_precision_limit, \
3821#define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0)
3829 id_BigDecimal_precision_limit
3832 if (
NIL_P(vlimit)) {
3852#define rmpd_set_thread_local_rounding_mode(mode) \
3853 rb_thread_local_aset( \
3854 rb_thread_current(), \
3855 id_BigDecimal_rounding_mode, \
3856 INT2FIX((int)(mode)) \
3864 id_BigDecimal_rounding_mode
3955 static double nzero = 1000.0;
3962VpIsNegDoubleZero(
double v)
3965 return MemCmp(&v,&z,
sizeof(v))==0;
3972 unsigned short const exception_mode = VpGetException();
3976 if (always || (exception_mode &
f)) {
4113 if ((
size_t)ex > vp->
Prec) {
4147 VpConstOne =
VpAlloc(1UL,
"1", 1, 1);
4148 VpPt5 =
VpAlloc(1UL,
".5", 1, 1);
4150#ifdef BIGDECIMAL_DEBUG
4154#ifdef BIGDECIMAL_DEBUG
4156 printf(
"VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
4160 printf(
"\tBASE_FIG = %u\n",
BASE_FIG);
4161 printf(
"\tDBLE_FIG = %d\n",
DBLE_FIG);
4165 return rmpd_double_figures();
4188 if (eb - mb > 0)
goto overflow;
4197 if (mb - eb > 0)
goto underflow;
4215 static const struct {
4225 static const size_t table_length =
sizeof(table) /
sizeof(table[0]);
4228 for (i = 0; i < table_length; ++i) {
4230 if (strncmp(
str, table[i].
str, table[i].
len) != 0) {
4234 p =
str + table[i].len;
4235 while (*p &&
ISSPACE(*p)) ++p;
4239 switch (table[i].sign) {
4272VpAlloc(
size_t mx,
const char *szVal,
int strict_p,
int exc)
4274 const char *orig_szVal = szVal;
4275 size_t i, j, ni, ipf, nf, ipe,
ne, dot_seen, exp_seen, nalloc;
4287 while (
ISSPACE(*szVal)) szVal++;
4290 if (*szVal !=
'#') {
4329 v = psz[i] = szVal[j];
4330 if ((v ==
'-') || (v ==
'+')) {
4338 while ((v = psz[i] = szVal[j]) !=
'\0') {
4339 if (!strict_p &&
ISSPACE(v)) {
4375 if ((psz[i] = szVal[j]) ==
'.') {
4380 while ((v = psz[i] = szVal[j]) !=
'\0') {
4381 if (!strict_p &&
ISSPACE(v)) {
4386 if (nf > 0 &&
ISDIGIT(szVal[j+1])) {
4408 switch ((psz[i] = szVal[j])) {
4417 v = psz[i] = szVal[j];
4418 if ((v ==
'-') || (v ==
'+')) {
4422 while ((v = psz[i] = szVal[j]) !=
'\0') {
4423 if (!strict_p &&
ISSPACE(v)) {
4454 while (
ISSPACE(szVal[j])) ++j;
4457 if (szVal[j] && strict_p) {
4465 if (strict_p && (((ni == 0 || dot_seen) && nf == 0) || (exp_seen &&
ne == 0))) {
4480 if (mx == 0) mx = 1;
4481 nalloc =
Max(nalloc, mx);
4487 VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe,
ne);
4528 VpInternalRound(c, n, (n>0) ? a->
frac[n-1] : 0, a->
frac[n]);
4552 Real *a_ptr, *b_ptr;
4553 size_t n, na, nb, i;
4556#ifdef BIGDECIMAL_DEBUG
4558 VPrint(stdout,
"VpAddSub(enter) a=% \n", a);
4559 VPrint(stdout,
" b=% \n", b);
4560 printf(
" operation=%d\n", operation);
4591 if (operation < 0) sw = -1;
4609 for (i=0; i < n; ++i) {
4615 else if (a->
frac[i] < b->
frac[i]) {
4651 mrv = VpAddAbs(a_ptr, b_ptr, c);
4656 mrv = VpSubAbs(a_ptr, b_ptr, c);
4664 VpInternalRound(c, 0, (c->
Prec > 0) ? c->
frac[c->
Prec-1] : 0, mrv);
4666#ifdef BIGDECIMAL_DEBUG
4668 VPrint(stdout,
"VpAddSub(result) c=% \n", c);
4669 VPrint(stdout,
" a=% \n", a);
4670 VPrint(stdout,
" b=% \n", b);
4671 printf(
" operation=%d\n", operation);
4690 size_t b_pos, b_pos_with_word_shift;
4692 BDIGIT av, bv, carry, mrv;
4694#ifdef BIGDECIMAL_DEBUG
4696 VPrint(stdout,
"VpAddAbs called: a = %\n", a);
4697 VPrint(stdout,
" b = %\n", b);
4701 word_shift = VpSetPTR(a, b, c, &ap, &
bp, &cp, &av, &bv);
4706 if (word_shift == (
size_t)-1L)
return 0;
4707 if (b_pos == (
size_t)-1L)
goto Assign_a;
4714 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4715 c->
frac[--c_pos] = b->
frac[--b_pos];
4718 if (b_pos == 0 && word_shift > a_pos) {
4719 while (word_shift-- > a_pos) {
4720 c->
frac[--c_pos] = 0;
4726 b_pos_with_word_shift = b_pos + word_shift;
4727 while (a_pos > b_pos_with_word_shift) {
4728 c->
frac[--c_pos] = a->
frac[--a_pos];
4735 c->
frac[--c_pos] = a->
frac[--a_pos] + b->
frac[--b_pos] + carry;
4748 c->
frac[--c_pos] = a->
frac[--a_pos] + carry;
4757 if (c_pos) c->
frac[c_pos - 1] += carry;
4766#ifdef BIGDECIMAL_DEBUG
4768 VPrint(stdout,
"VpAddAbs exit: c=% \n", c);
4785 size_t b_pos, b_pos_with_word_shift;
4787 BDIGIT av, bv, borrow, mrv;
4789#ifdef BIGDECIMAL_DEBUG
4791 VPrint(stdout,
"VpSubAbs called: a = %\n", a);
4792 VPrint(stdout,
" b = %\n", b);
4796 word_shift = VpSetPTR(a, b, c, &ap, &
bp, &cp, &av, &bv);
4800 if (word_shift == (
size_t)-1L)
return 0;
4801 if (b_pos == (
size_t)-1L)
goto Assign_a;
4815 if (b_pos + word_shift > a_pos) {
4816 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4821 while (word_shift > a_pos) {
4831 b_pos_with_word_shift = b_pos + word_shift;
4832 while (a_pos > b_pos_with_word_shift) {
4833 c->
frac[--c_pos] = a->
frac[--a_pos];
4840 if (a->
frac[--a_pos] < b->
frac[--b_pos] + borrow) {
4845 c->
frac[c_pos] = a->
frac[a_pos] - b->
frac[b_pos] - borrow;
4854 if (a->
frac[--a_pos] < borrow) {
4859 c->
frac[c_pos] = a->
frac[a_pos] - borrow;
4863 if (c_pos) c->
frac[c_pos - 1] -= borrow;
4871#ifdef BIGDECIMAL_DEBUG
4873 VPrint(stdout,
"VpSubAbs exit: c=% \n", c);
4896 size_t left_word, right_word, word_shift;
4906 left_word = b->
Prec + word_shift;
4907 right_word =
Max(a->
Prec, left_word);
4913 if (right_word > left_word) {
4923 *c_pos = right_word = left_word + 1;
4932 if (*a_pos <= round_limit) {
4933 *av = a->
frac[*a_pos];
4951 if (c->
MaxPrec >= word_shift + 1) {
4952 *b_pos = c->
MaxPrec - word_shift - 1;
4953 if (*b_pos + word_shift <= round_limit) {
4954 *bv = b->
frac[*b_pos];
4980 *c_pos = right_word + 1;
4984 if (!AddExponent(c, 1))
return (
size_t)-1L;
5006 size_t MxIndA, MxIndB, MxIndAB, MxIndC;
5007 size_t ind_c, i, ii, nc;
5008 size_t ind_as, ind_ae, ind_bs;
5013#ifdef BIGDECIMAL_DEBUG
5015 VPrint(stdout,
"VpMult(Enter): a=% \n", a);
5016 VPrint(stdout,
" b=% \n", b);
5020 if (!VpIsDefOP(c, a, b,
OP_SW_MULT))
return 0;
5043 MxIndA = a->
Prec - 1;
5044 MxIndB = b->
Prec - 1;
5048 if (MxIndC < MxIndAB) {
5057 if (!AddExponent(c, b->
exponent)) {
5063 nc = ind_c = MxIndAB;
5064 memset(c->
frac, 0, (nc + 1) *
sizeof(
BDIGIT));
5066 for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
5068 ind_as = MxIndA - nc;
5072 else if (nc <= MxIndA) {
5073 ind_as = MxIndA - nc;
5074 ind_ae = MxIndA - (nc - MxIndB);
5079 ind_ae = MxIndAB - nc - 1;
5080 ind_bs = MxIndB - (nc - MxIndA);
5083 for (i = ind_as; i <= ind_ae; ++i) {
5096 c->
frac[ii] += carry;
5119#ifdef BIGDECIMAL_DEBUG
5121 VPrint(stdout,
"VpMult(c=a*b): c=% \n", c);
5122 VPrint(stdout,
" a=% \n", a);
5123 VPrint(stdout,
" b=% \n", b);
5135 size_t word_a, word_b, word_c, word_r;
5136 size_t i, n, ind_a, ind_b, ind_c, ind_r;
5139 BDIGIT borrow, borrow1, borrow2;
5142#ifdef BIGDECIMAL_DEBUG
5144 VPrint(stdout,
" VpDivd(c=a/b) a=% \n", a);
5145 VPrint(stdout,
" b=% \n", b);
5150 if (!VpIsDefOP(c, a, b,
OP_SW_DIV))
goto Exit;
5180 if (word_a >= word_r)
goto space_error;
5183 while (ind_r <= word_a) {
5184 r->
frac[ind_r] = a->
frac[ind_r - 1];
5188 while (ind_r < word_r) r->
frac[ind_r++] = 0;
5189 while (ind_c < word_c) c->
frac[ind_c++] = 0;
5192 b1 = b1p1 = b->
frac[0];
5194 b1b2p1 = b1b2 = b1p1 *
BASE;
5198 b1b2p1 = b1b2 = b1 *
BASE + b->
frac[1];
5199 if (b->
Prec > 2) ++b1b2p1;
5205 nLoop =
Min(word_c,ind_c);
5207 while (ind_c < nLoop) {
5208 if (r->
frac[ind_c] == 0) {
5217 while (ind_b < word_b) {
5218 if (r->
frac[ind_a] < b->
frac[ind_b])
goto div_b1p1;
5219 if (r->
frac[ind_a] > b->
frac[ind_b])
break;
5227 ind_b = b->
Prec - 1;
5228 ind_r = ind_c + ind_b;
5229 if (ind_r >= word_r)
goto space_error;
5231 for (i = 0; i <= n; ++i) {
5232 if (r->
frac[ind_r] < b->
frac[ind_b] + borrow) {
5237 r->
frac[ind_r] = r->
frac[ind_r] - b->
frac[ind_b] - borrow;
5248 if (r1r2 >= b1b2p1) {
5251 ind_r = b->
Prec + ind_c - 1;
5256 if (ind_c + 1 >= word_c)
goto out_side;
5259 ind_r = b->
Prec + ind_c;
5262 borrow1 = borrow2 = 0;
5264 if (ind_r >= word_r)
goto space_error;
5266 for (i = 0; i <= n; ++i) {
5268 qb = q * b->
frac[ind_b];
5269 if (qb <
BASE) borrow1 = 0;
5274 if(r->
frac[ind_r] < qb) {
5276 borrow2 = borrow2 + borrow1 + 1;
5283 if(r->
frac[ind_r - 1] < borrow2) {
5284 r->
frac[ind_r - 1] += (
BASE - borrow2);
5288 r->
frac[ind_r - 1] -= borrow2;
5296 r->
frac[ind_r] -= borrow2;
5309 if (!AddExponent(c, 2))
return 0;
5310 if (!AddExponent(c, -(b->
exponent)))
return 0;
5316 if (!AddExponent(r, 1))
return 0;
5322#ifdef BIGDECIMAL_DEBUG
5324 printf(
" word_a=%"PRIuSIZE"\n", word_a);
5325 printf(
" word_b=%"PRIuSIZE"\n", word_b);
5326 printf(
" word_c=%"PRIuSIZE"\n", word_c);
5327 printf(
" word_r=%"PRIuSIZE"\n", word_r);
5328 printf(
" ind_r =%"PRIuSIZE"\n", ind_r);
5331 rb_bug(
"ERROR(VpDivd): space for remainder too small.");
5334#ifdef BIGDECIMAL_DEBUG
5336 VPrint(stdout,
" VpDivd(c=a/b), c=% \n", c);
5337 VPrint(stdout,
" r=% \n", r);
5357 if (a->
frac[ind_a]) {
5358 a->
Prec = ind_a + 1;
5360 while (a->
frac[i] == 0) ++i;
5397 if (e > 0)
return 1;
5398 else if (e < 0)
return -1;
5403 if (e > 0)
return 1;
5459 if (val > 1) val = 1;
5460 else if (val < -1) val = -1;
5462#ifdef BIGDECIMAL_DEBUG
5464 VPrint(stdout,
" VpComp a=%\n", a);
5465 VPrint(stdout,
" b=%\n", b);
5466 printf(
" ans=%d\n", val);
5482#ifdef BIGDECIMAL_ENABLE_VPRINT
5484VPrint(
FILE *fp,
const char *cntl_chr,
Real *a)
5486 size_t i, j, nc, nd, ZeroSup, sep = 10;
5494 while (*(cntl_chr + j)) {
5495 if (*(cntl_chr + j) ==
'%' && *(cntl_chr + j + 1) !=
'%') {
5514 nc += fprintf(fp,
"0.");
5515 switch (*(cntl_chr + j + 1)) {
5525 for (i = 0; i < a->
Prec; ++i) {
5530 if (!ZeroSup || nn) {
5531 nc += fprintf(fp,
"%lu", (
unsigned long)nn);
5539 nc += fprintf(fp,
" ");
5549 nc += fprintf(fp,
"0.0");
5554 if (*(cntl_chr + j) ==
'\\') {
5555 switch (*(cntl_chr + j + 1)) {
5569 fprintf(fp,
"%c", *(cntl_chr + j));
5574 fprintf(fp,
"%c", *(cntl_chr + j));
5575 if (*(cntl_chr + j) ==
'%') ++j;
5586VpFormatSt(
char *psz,
size_t fFmt)
5588 size_t ie, i, nf = 0;
5591 if (fFmt == 0)
return;
5594 for (i = 0; i < ie; ++i) {
5597 if (
ISSPACE(ch) || ch==
'-' || ch==
'+')
continue;
5598 if (ch ==
'.') { nf = 0;
continue; }
5599 if (ch ==
'E' || ch ==
'e')
break;
5602 memmove(psz + i + 1, psz + i, ie - i + 1);
5620 while ((a->
frac[0] / n) == 0) {
5630 size_t i, n, ZeroSup;
5650 for (i = 0; i < n; ++i) {
5655 if (!ZeroSup || nn) {
5656 sprintf(psz,
"%lu", (
unsigned long)nn);
5666 while (psz[-1] ==
'0') *(--psz) = 0;
5670 else sprintf(psz,
"-0");
5687 else if (fPlus == 2) {
5699 if (fPlus == 1) sprintf(psz,
" 0.0");
5700 else if (fPlus == 2) sprintf(psz,
"+0.0");
5701 else sprintf(psz,
"0.0");
5703 else sprintf(psz,
"-0.0");
5713 size_t i, n, ZeroSup;
5723 else if (fPlus == 1) *psz++ =
' ';
5724 else if (fPlus == 2) *psz++ =
'+';
5729 for (i = 0; i < n; ++i) {
5734 if (!ZeroSup || nn) {
5735 sprintf(psz,
"%lu", (
unsigned long)nn);
5746 while (a->
frac[0] / shift == 0) {
5750 while (psz[-1] ==
'0') {
5754 if (fFmt) VpFormatSt(pszSav, fFmt);
5769 else if (fPlus == 1) *psz++ =
' ';
5770 else if (fPlus == 2) *psz++ =
'+';
5775 *psz++ =
'0';*psz++ =
'.';
5777 for (i=0; i <
BASE_FIG; ++i) *psz++ =
'0';
5783 for (i = 0; i < n; ++i) {
5785 if (i == 0 && ex >= 0) {
5786 sprintf(psz,
"%lu", (
unsigned long)a->
frac[i]);
5794 *psz++ = (char)(nn +
'0');
5799 if (ex == 0) *psz++ =
'.';
5803 while (m /= 10) *psz++ =
'0';
5804 if (ex == 0) *psz++ =
'.';
5807 while (psz[-1] ==
'0') *(--psz) = 0;
5808 if (psz[-1] ==
'.') sprintf(psz,
"0");
5809 if (fFmt) VpFormatSt(pszSav, fFmt);
5824VpCtoV(
Real *a,
const char *int_chr,
size_t ni,
const char *frac,
size_t nf,
const char *exp_chr,
size_t ne)
5826 size_t i, j, ind_a, ma, mi, me;
5828 int sign, signe, exponent_overflow;
5836 exponent_overflow = 0;
5840 if (exp_chr[0] ==
'-') {
5845 else if (exp_chr[0] ==
'+') {
5858 e = e * 10 + exp_chr[i] -
'0';
5863 exponent_overflow = 1;
5875 if (int_chr[0] ==
'-') {
5880 else if (int_chr[0] ==
'+') {
5889 if (e > 0) signe = 1;
5908 if (exponent_overflow) {
5910 for ( ; i < mi && zero; i++) zero = int_chr[i] ==
'0';
5911 for (i = 0; i < nf && zero; i++) zero = frac[i] ==
'0';
5912 if (!zero && signe > 0) {
5924 a->
frac[ind_a] = a->
frac[ind_a] * 10 + int_chr[i] -
'0';
5930 if (ind_a >= ma)
goto over_flow;
5940 a->
frac[ind_a] = a->
frac[ind_a] * 10 + frac[i] -
'0';
5946 if (ind_a >= ma)
goto over_flow;
5953 rb_warn(
"Conversion from String to BigDecimal overflow (last few digits discarded).");
5956 if (ind_a >= ma) ind_a = ma - 1;
5958 a->
frac[ind_a] = a->
frac[ind_a] * 10;
5961 a->
Prec = ind_a + 1;
5986 size_t ind_m, mm, fig;
6026 while (ind_m < mm) {
6028 *d = *d + (double)m->
frac[ind_m++] *
div;
6034#ifdef BIGDECIMAL_DEBUG
6036 VPrint(stdout,
" VpVtoD: m=%\n", m);
6037 printf(
" d=%e * 10 **%ld\n", *d, *e);
6038 printf(
" DBLE_FIG = %d\n",
DBLE_FIG);
6069 val = (d > 0.) ? d : -d;
6072 while (val >= 1.0) {
6073 val /= (double)
BASE;
6078 val2 = 1.0 / (double)
BASE;
6079 while (val < val2) {
6080 val *= (double)
BASE;
6088 for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
6089 val *= (double)
BASE;
6094 if (ind_m >= mm) ind_m = mm - 1;
6096 m->
Prec = ind_m + 1;
6099 VpInternalRound(m, 0, (m->
Prec > 0) ? m->
frac[m->
Prec-1] : 0,
6103#ifdef BIGDECIMAL_DEBUG
6105 printf(
"VpDtoV d=%30.30e\n", d);
6106 VPrint(stdout,
" m=%\n", m);
6120 size_t val, v1, v2, v;
6132 val =(size_t)(-ival);
6137 while (ind_m < mm) {
6146 while (v1 >=
BASE) {
6150 val = val - v2 * v1;
6160 m->
Prec = ind_m - 1;
6166#ifdef BIGDECIMAL_DEBUG
6168 printf(
" VpItoV i=%d\n", ival);
6169 VPrint(stdout,
" m=%\n", m);
6224 prec = x->
exponent - (ssize_t)y_prec;
6233 if (e - n * 2 != 0) {
6256#ifdef BIGDECIMAL_DEBUG
6258 printf(
"ERROR(VpSqrt): did not converge within %ld iterations.\n", nr);
6265#ifdef BIGDECIMAL_DEBUG
6269 printf(
"VpSqrt: iterations = %"PRIdSIZE"\n", nr);
6270 VPrint(stdout,
" y =% \n", y);
6271 VPrint(stdout,
" x =% \n", x);
6272 VPrint(stdout,
" x-y*y = % \n",
f);
6294 int fracf, fracf_1further;
6295 ssize_t n,i,ix,ioffset, exptoadd;
6312 if ((
size_t)ix >= y->
Prec)
return 0;
6315 ioffset = nf - ix*(ssize_t)
BASE_FIG;
6316 n = (ssize_t)
BASE_FIG - ioffset - 1;
6317 for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
6346 fracf = (v % (shifter * 10) > 0);
6347 fracf_1further = ((v % shifter) > 0);
6363 for (i = ix + 1; (size_t)i < y->Prec; i++) {
6365 fracf = fracf_1further = 1;
6376 memset(y->
frac + ix + 1, 0, (y->
Prec - (ix + 1)) *
sizeof(
BDIGIT));
6388 if (v > 5 || (v == 5 && fracf_1further)) ++
div;
6399 if (fracf_1further) {
6409 if (ix && (y->
frac[ix-1] % 2)) ++
div;
6418 for (i = 0; i <= n; ++i)
div *= 10;
6439 for (i = 0; i < exptoadd; i++) {
6460 while ((v /= 10) != 0) nf--;
6469 if (
VpAsgn(y, x, 10) <= 1)
return 0;
6474VpLimitRound(
Real *c,
size_t ixDigit)
6477 if (!VpNmlz(c))
return -1;
6479 if (!ixDigit) ixDigit = c->
Prec-1;
6493 if (VpLimitRound(c, ixDigit))
return;
6497 switch (rounding_mode) {
6522 else if (v == 5 && vPrev % 2)
f = 1;
6535VpRdup(
Real *m,
size_t ind_m)
6539 if (!ind_m) ind_m = m->
Prec;
6542 while (carry > 0 && ind_m--) {
6543 m->
frac[ind_m] += carry;
6548 if (!AddExponent(m, 1))
return 0;
6563 size_t my, ind_y, ind_x;
6588 while (ind_y < my) {
6596#ifdef BIGDECIMAL_DEBUG
6598 VPrint(stdout,
"VpFrac y=%\n", y);
6599 VPrint(stdout,
" x=%\n", x);
6624 if (sign < 0) sign = (n % 2) ? -1 : 1;
6628 if (sign < 0) sign = (n % 2) ? -1 : 1;
6654 if ((n % 2) == 0)
goto Exit;
6659 if (n > 0) sign = 1;
6680 while (ss = s, (s += s) <= (
size_t)n) {
6689 VpDivd(w1, w2, VpConstOne, y);
6694#ifdef BIGDECIMAL_DEBUG
6696 VPrint(stdout,
"VpPower y=%\n", y);
6697 VPrint(stdout,
"VpPower x=%\n", x);
6706#ifdef BIGDECIMAL_DEBUG
6721 printf(
"ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
6726 printf(
"ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->
Prec);
6730 for (i = 0; i < v->
Prec; ++i) {
6732 printf(
"ERROR(VpVarCheck): Illegal fraction\n");
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
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)
#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 rb_category_warn(category,...)
#define VP_EXCEPTION_UNDERFLOW
#define BDIGIT_DBL_SIGNED
#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
VALUE rb_big2str(VALUE x, int base)
VALUE rb_big_cmp(VALUE x, VALUE y)
VALUE rb_dbl2big(double d)
void rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
VALUE rb_complex_real(VALUE self)
VALUE rb_complex_imag(VALUE self)
Our own, locale independent, character handling routines.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
VALUE rb_eFloatDomainError
VALUE rb_eMathDomainError
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_define_module(const char *name)
void rb_undef_method(VALUE klass, const char *name)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
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(*proc)(VALUE), VALUE data, int *pstate)
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)
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
@ RB_WARN_CATEGORY_DEPRECATED
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
void rb_ext_ractor_safe(bool flag)
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
VALUE rb_num_coerce_relop(VALUE, VALUE, ID)
VALUE rb_Rational(VALUE, VALUE)
VALUE rb_str_resize(VALUE, long)
st_index_t rb_memhash(const void *ptr, long len)
#define rb_str_new(str, len)
#define rb_usascii_str_new(str, len)
VALUE rb_check_string_type(VALUE)
VALUE rb_str_tmp_new(long)
VALUE rb_thread_local_aref(VALUE, ID)
void rb_thread_check_ints(void)
VALUE rb_thread_current(void)
VALUE rb_class_name(VALUE)
void rb_undef_alloc_func(VALUE)
ID rb_intern(const char *)
void rb_define_const(VALUE, const char *, VALUE)
void * memmove(void *, const void *, size_t)
#define DECIMAL_SIZE_OF_BITS(n)
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
Internal header for Math.
#define MEMCPY(p1, p2, type, n)
#define RARRAY_AREF(a, i)
#define StringValueCStr(v)
#define RTYPEDDATA_DATA(v)
#define TypedData_Wrap_Struct(klass, data_type, sval)
@ RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FROZEN_SHAREABLE
size_t strlen(const char *)
BDIGIT frac[FLEXIBLE_ARRAY_SIZE]
if((ID)(DISPID) nameid !=nameid)