10 #ifdef BIGDECIMAL_DEBUG 11 # define BIGDECIMAL_ENABLE_VPRINT 1 15 #ifndef BIGDECIMAL_DEBUG 34 #define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \ 36 (a) == -1 ? (b) < -(max) : \ 38 ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \ 39 ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b))) 40 #define SIGNED_VALUE_MAX INTPTR_MAX 41 #define SIGNED_VALUE_MIN INTPTR_MIN 42 #define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX) 66 #define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0 67 #define PUSH(x) vStack[iStack++] = (VALUE)(x); 68 #define SAVE(p) PUSH(p->obj); 69 #define GUARD_OBJ(p,y) {p=y;SAVE(p);} 71 #define BASE_FIG RMPD_COMPONENT_FIGURES 72 #define BASE RMPD_BASE 74 #define HALF_BASE (BASE/2) 75 #define BASE1 (BASE/10) 78 #define DBLE_FIG (DBL_DIG+1) 81 #ifndef RBIGNUM_ZERO_P 82 # define RBIGNUM_ZERO_P(x) rb_bigzero_p(x) 85 #ifndef RRATIONAL_ZERO_P 86 # define RRATIONAL_ZERO_P(x) (FIXNUM_P(RRATIONAL(x)->num) && \ 87 FIX2LONG(RRATIONAL(x)->num) == 0) 90 #ifndef RRATIONAL_NEGATIVE_P 91 # define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0))) 97 #define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f) 122 #ifdef BIGDECIMAL_ENABLE_VPRINT 123 static int VPrint(
FILE *fp,
const char *cntl_chr,
Real *a);
139 const Real *pv = ptr;
140 return pv ? (
sizeof(*pv) + pv->
MaxPrec *
sizeof(
BDIGIT)) : 0;
146 #ifdef RUBY_TYPED_FREE_IMMEDIATELY 204 if (prec < 0)
goto unable_to_coerce_without_prec;
205 if (prec >
DBL_DIG+1)
goto SomeOneMayDoIt;
217 if (prec < 0)
goto unable_to_coerce_without_prec;
219 if (orig ==
Qundef ? (orig = v, 1) : orig != v) {
222 if (pv ==
NULL)
goto SomeOneMayDoIt;
245 #ifdef ENABLE_NUMERIC_STRING 266 unable_to_coerce_without_prec:
269 "%s can't be coerced into BigDecimal without a precision",
387 while((*pch) != (
unsigned char)
'\0' && (ch = *pch++) != (
unsigned char)
':') {
391 m = m*10 + (
unsigned long)(ch-
'0');
402 static unsigned short 538 if (mx < b->Prec) mx = b->
Prec;
579 #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT)) 580 #define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT)) 707 if (
VpVtoD(&d, &e, p) != 1)
719 if (
errno == ERANGE) {
720 if (d == 0.0)
goto underflow;
721 if (fabs(d) >= HUGE_VAL)
goto overflow;
747 ssize_t sign, power, denomi_power;
748 VALUE a, digits, numerator;
763 if (denomi_power < 0) {
870 if (mx == (
size_t)-1L) {
928 if (mx == (
size_t)-1L) {
1010 if (e == 0)
return Qtrue;
1014 if (e >= 0)
return Qtrue;
1018 if (e > 0)
return Qtrue;
1022 if (e <= 0)
return Qtrue;
1026 if (e < 0)
return Qtrue;
1033 rb_bug(
"Undefined operation in BigDecimalCmp()");
1253 if (!
NIL_P(r))
return r;
1495 mx = av->
Prec + bv->Prec + 2;
1496 if (mx <= cv->MaxPrec) mx =
cv->MaxPrec + 1;
1619 if (mx <= n) mx = n;
1802 #ifdef BIGDECIMAL_DEBUG 1803 VPrint(stderr,
"floor: c=%\n", c);
1911 else if (*psz ==
'+') {
1915 while ((ch = *psz++) != 0) {
1920 if (ch ==
'F' || ch ==
'f') {
1925 mc = mc*10 + ch -
'0';
1939 nc += (nc + mc - 1) / mc + 1;
1993 if(psz1[0] ==
'-') {
1994 size_t len =
strlen(psz1 + 1);
2000 if (psz1[0] ==
'N') s = 0;
2044 nc += (nc + 9) / 10;
2048 sprintf(psz,
"#<BigDecimal:%"PRIxVALUE",'",
self);
2060 #define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n)) 2061 #define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n)) 2084 #define is_positive(x) (!is_negative(x)) 2158 VALUE log_x, multiplied, y;
2207 switch (
TYPE(vexp)) {
2216 if (d ==
round(d)) {
2256 "wrong argument type %s (expected scalar Numeric)",
2337 "a non-integral exponent for a negative base");
2395 if (ma < 0) ma = -ma;
2396 if (ma == 0) ma = 1;
2479 if (
self != other) {
2499 switch (
TYPE(iniValue)) {
2519 "can't omit precision for a %"PRIsVALUE".",
2566 if (
NIL_P(nFig))
return nCur;
2725 infinite =
isinf(flo);
2727 if (!infinite && !nan) {
2758 else if (vx ==
NULL) {
2777 ssize_t m = n -
vabs(ey - ed);
2865 if (
zero || negative)
break;
2873 infinite =
isinf(flo);
2875 if (!
zero && !negative && !infinite && !nan) {
2883 if (
zero || negative)
break;
2889 "Complex argument for BigMath.log");
2894 if (infinite && !negative) {
2908 else if (
zero || negative) {
2910 "Zero or negative argument for log");
2912 else if (vx ==
NULL) {
2923 if (expo < 0 || expo >= 3) {
2940 ssize_t m = n -
vabs(ey - ed);
2956 VALUE log10, vexpo, dy;
3306 #ifdef BIGDECIMAL_DEBUG 3307 static int gfDebug = 1;
3309 static int gfCheckVal = 1;
3319 #define MemCmp(x,y,z) memcmp(x,y,z) 3320 #define StrCmp(x,y) strcmp(x,y) 3328 static void VpFormatSt(
char *psz,
size_t fFmt);
3331 #ifdef BIGDECIMAL_DEBUG 3332 static int gnAlloc = 0;
3343 #ifdef BIGDECIMAL_DEBUG 3364 #ifdef BIGDECIMAL_DEBUG 3367 printf(
" *************** All memories allocated freed ****************");
3371 printf(
" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
3382 #define rmpd_set_thread_local_exception_mode(mode) \ 3383 rb_thread_local_aset( \ 3384 rb_thread_current(), \ 3385 id_BigDecimal_exception_mode, \ 3386 INT2FIX((int)(mode)) \ 3389 static unsigned short 3402 return (
unsigned short)
FIX2UINT(vmode);
3415 #define rmpd_set_thread_local_precision_limit(limit) \ 3416 rb_thread_local_aset( \ 3417 rb_thread_current(), \ 3418 id_BigDecimal_precision_limit, \ 3421 #define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0) 3432 if (
NIL_P(vlimit)) {
3452 #define rmpd_set_thread_local_rounding_mode(mode) \ 3453 rb_thread_local_aset( \ 3454 rb_thread_current(), \ 3455 id_BigDecimal_rounding_mode, \ 3456 INT2FIX((int)(mode)) \ 3472 return (
unsigned short)
FIX2INT(vmode);
3543 static double fNaN = 0.0;
3544 if (fNaN == 0.0) fNaN =
Zero()/
Zero();
3551 static double fInf = 0.0;
3552 if (fInf == 0.0) fInf =
One()/
Zero();
3559 static double fInf = 0.0;
3560 if (fInf == 0.0) fInf = -(
One()/
Zero());
3567 static double nzero = 1000.0;
3574 VpIsNegDoubleZero(
double v)
3577 return MemCmp(&v,&z,
sizeof(v))==0;
3588 if (always || (exception_mode &
f)) {
3721 if ((
size_t)ex > vp->
Prec) {
3761 #ifdef BIGDECIMAL_DEBUG 3765 #ifdef BIGDECIMAL_DEBUG 3767 printf(
"VpInit: BaseVal = %lu\n", BaseVal);
3768 printf(
" BASE = %lu\n",
BASE);
3769 printf(
" HALF_BASE = %lu\n",
HALF_BASE);
3770 printf(
" BASE1 = %lu\n",
BASE1);
3771 printf(
" BASE_FIG = %u\n",
BASE_FIG);
3772 printf(
" DBLE_FIG = %d\n",
DBLE_FIG);
3799 if (mb < eb)
goto overflow;
3808 if (mb > eb)
goto underflow;
3839 size_t i, ni, ipn, ipf, nf, ipe,
ne, nalloc;
3850 while (
ISSPACE(*szVal)) szVal++;
3851 if (*szVal !=
'#') {
3880 while ((psz[i] = szVal[ipn]) != 0) {
3882 if (psz[i] ==
'_') {
3895 if (
ISSPACE(psz[i])) psz[i] = 0;
3922 if (szVal[i] ==
'-') { sign=-1; ++i; }
3923 else if (szVal[i] ==
'+') ++i;
3926 while ((v = szVal[i]) != 0) {
3937 if (szVal[i] ==
'.') {
3940 while ((v = szVal[i]) != 0) {
3956 if ((v ==
'-') || (v ==
'+')) ++i;
3957 while ((v=szVal[i]) != 0) {
3969 if (mx == 0) mx = 1;
3970 nalloc =
Max(nalloc, mx);
3976 VpCtoV(vp, &szVal[ipn], ni, &szVal[ipf], nf, &szVal[ipe],
ne);
4041 Real *a_ptr, *b_ptr;
4042 size_t n, na, nb, i;
4045 #ifdef BIGDECIMAL_DEBUG 4047 VPrint(stdout,
"VpAddSub(enter) a=% \n", a);
4048 VPrint(stdout,
" b=% \n", b);
4049 printf(
" operation=%d\n", operation);
4053 if (!
VpIsDefOP(c, a, b, (operation > 0) ? 1 : 2))
return 0;
4080 if (operation < 0) sw = -1;
4098 for (i=0; i < n; ++i) {
4104 else if (a->
frac[i] < b->
frac[i]) {
4155 #ifdef BIGDECIMAL_DEBUG 4157 VPrint(stdout,
"VpAddSub(result) c=% \n", c);
4158 VPrint(stdout,
" a=% \n", a);
4159 VPrint(stdout,
" b=% \n", b);
4160 printf(
" operation=%d\n", operation);
4179 size_t b_pos, b_pos_with_word_shift;
4181 BDIGIT av, bv, carry, mrv;
4183 #ifdef BIGDECIMAL_DEBUG 4185 VPrint(stdout,
"VpAddAbs called: a = %\n", a);
4186 VPrint(stdout,
" b = %\n", b);
4190 word_shift =
VpSetPTR(a, b, c, &ap, &
bp, &cp, &av, &bv);
4195 if (word_shift == (
size_t)-1L)
return 0;
4196 if (b_pos == (
size_t)-1L)
goto Assign_a;
4203 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4204 c->
frac[--c_pos] = b->
frac[--b_pos];
4207 if (b_pos == 0 && word_shift > a_pos) {
4208 while (word_shift-- > a_pos) {
4209 c->
frac[--c_pos] = 0;
4215 b_pos_with_word_shift = b_pos + word_shift;
4216 while (a_pos > b_pos_with_word_shift) {
4217 c->
frac[--c_pos] = a->
frac[--a_pos];
4224 c->
frac[--c_pos] = a->
frac[--a_pos] + b->
frac[--b_pos] + carry;
4237 c->
frac[--c_pos] = a->
frac[--a_pos] + carry;
4246 if (c_pos) c->
frac[c_pos - 1] += carry;
4255 #ifdef BIGDECIMAL_DEBUG 4257 VPrint(stdout,
"VpAddAbs exit: c=% \n", c);
4274 size_t b_pos, b_pos_with_word_shift;
4276 BDIGIT av, bv, borrow, mrv;
4278 #ifdef BIGDECIMAL_DEBUG 4280 VPrint(stdout,
"VpSubAbs called: a = %\n", a);
4281 VPrint(stdout,
" b = %\n", b);
4285 word_shift =
VpSetPTR(a, b, c, &ap, &
bp, &cp, &av, &bv);
4289 if (word_shift == (
size_t)-1L)
return 0;
4290 if (b_pos == (
size_t)-1L)
goto Assign_a;
4304 if (b_pos + word_shift > a_pos) {
4305 while (b_pos > 0 && b_pos + word_shift > a_pos) {
4310 while (word_shift > a_pos) {
4320 b_pos_with_word_shift = b_pos + word_shift;
4321 while (a_pos > b_pos_with_word_shift) {
4322 c->
frac[--c_pos] = a->
frac[--a_pos];
4329 if (a->
frac[--a_pos] < b->
frac[--b_pos] + borrow) {
4334 c->
frac[c_pos] = a->
frac[a_pos] - b->
frac[b_pos] - borrow;
4343 if (a->
frac[--a_pos] < borrow) {
4348 c->
frac[c_pos] = a->
frac[a_pos] - borrow;
4352 if (c_pos) c->
frac[c_pos - 1] -= borrow;
4360 #ifdef BIGDECIMAL_DEBUG 4362 VPrint(stdout,
"VpSubAbs exit: c=% \n", c);
4385 size_t left_word, right_word, word_shift;
4395 left_word = b->
Prec + word_shift;
4396 right_word =
Max(a->
Prec, left_word);
4402 if (right_word > left_word) {
4412 *c_pos = right_word = left_word + 1;
4421 if (*a_pos <= round_limit) {
4422 *av = a->
frac[*a_pos];
4440 if (c->
MaxPrec >= word_shift + 1) {
4441 *b_pos = c->
MaxPrec - word_shift - 1;
4442 if (*b_pos + word_shift <= round_limit) {
4443 *bv = b->
frac[*b_pos];
4469 *c_pos = right_word + 1;
4495 size_t MxIndA, MxIndB, MxIndAB, MxIndC;
4496 size_t ind_c, i, ii, nc;
4497 size_t ind_as, ind_ae, ind_bs;
4502 #ifdef BIGDECIMAL_DEBUG 4504 VPrint(stdout,
"VpMult(Enter): a=% \n", a);
4505 VPrint(stdout,
" b=% \n", b);
4532 MxIndA = a->
Prec - 1;
4533 MxIndB = b->
Prec - 1;
4537 if (MxIndC < MxIndAB) {
4552 nc = ind_c = MxIndAB;
4553 memset(c->
frac, 0, (nc + 1) *
sizeof(
BDIGIT));
4555 for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
4557 ind_as = MxIndA - nc;
4561 else if (nc <= MxIndA) {
4562 ind_as = MxIndA - nc;
4563 ind_ae = MxIndA - (nc - MxIndB);
4568 ind_ae = MxIndAB - nc - 1;
4569 ind_bs = MxIndB - (nc - MxIndA);
4572 for (i = ind_as; i <= ind_ae; ++i) {
4585 c->
frac[ii] += carry;
4608 #ifdef BIGDECIMAL_DEBUG 4610 VPrint(stdout,
"VpMult(c=a*b): c=% \n", c);
4611 VPrint(stdout,
" a=% \n", a);
4612 VPrint(stdout,
" b=% \n", b);
4624 size_t word_a, word_b, word_c, word_r;
4625 size_t i, n, ind_a, ind_b, ind_c, ind_r;
4628 BDIGIT borrow, borrow1, borrow2;
4631 #ifdef BIGDECIMAL_DEBUG 4633 VPrint(stdout,
" VpDivd(c=a/b) a=% \n", a);
4634 VPrint(stdout,
" b=% \n", b);
4669 if (word_a >= word_r)
goto space_error;
4672 while (ind_r <= word_a) {
4673 r->
frac[ind_r] = a->
frac[ind_r - 1];
4677 while (ind_r < word_r) r->
frac[ind_r++] = 0;
4678 while (ind_c < word_c) c->
frac[ind_c++] = 0;
4681 b1 = b1p1 = b->
frac[0];
4683 b1b2p1 = b1b2 = b1p1 *
BASE;
4687 b1b2p1 = b1b2 = b1 *
BASE + b->
frac[1];
4688 if (b->
Prec > 2) ++b1b2p1;
4694 nLoop =
Min(word_c,ind_c);
4696 while (ind_c < nLoop) {
4697 if (r->
frac[ind_c] == 0) {
4706 while (ind_b < word_b) {
4707 if (r->
frac[ind_a] < b->
frac[ind_b])
goto div_b1p1;
4708 if (r->
frac[ind_a] > b->
frac[ind_b])
break;
4716 ind_b = b->
Prec - 1;
4717 ind_r = ind_c + ind_b;
4718 if (ind_r >= word_r)
goto space_error;
4720 for (i = 0; i <= n; ++i) {
4721 if (r->
frac[ind_r] < b->
frac[ind_b] + borrow) {
4726 r->
frac[ind_r] = r->
frac[ind_r] - b->
frac[ind_b] - borrow;
4737 if (r1r2 >= b1b2p1) {
4740 ind_r = b->
Prec + ind_c - 1;
4745 if (ind_c + 1 >= word_c)
goto out_side;
4748 ind_r = b->
Prec + ind_c;
4751 borrow1 = borrow2 = 0;
4753 if (ind_r >= word_r)
goto space_error;
4755 for (i = 0; i <= n; ++i) {
4757 qb = q * b->
frac[ind_b];
4758 if (qb <
BASE) borrow1 = 0;
4763 if(r->
frac[ind_r] < qb) {
4765 borrow2 = borrow2 + borrow1 + 1;
4772 if(r->
frac[ind_r - 1] < borrow2) {
4773 r->
frac[ind_r - 1] += (
BASE - borrow2);
4777 r->
frac[ind_r - 1] -= borrow2;
4785 r->
frac[ind_r] -= borrow2;
4811 #ifdef BIGDECIMAL_DEBUG 4813 printf(
" word_a=%lu\n", word_a);
4814 printf(
" word_b=%lu\n", word_b);
4815 printf(
" word_c=%lu\n", word_c);
4816 printf(
" word_r=%lu\n", word_r);
4817 printf(
" ind_r =%lu\n", ind_r);
4820 rb_bug(
"ERROR(VpDivd): space for remainder too small.");
4823 #ifdef BIGDECIMAL_DEBUG 4825 VPrint(stdout,
" VpDivd(c=a/b), c=% \n", c);
4826 VPrint(stdout,
" r=% \n", r);
4846 if (a->
frac[ind_a]) {
4847 a->
Prec = ind_a + 1;
4849 while (a->
frac[i] == 0) ++i;
4886 if (e > 0)
return 1;
4887 else if (e < 0)
return -1;
4892 if (e > 0)
return 1;
4949 else if (
val < -1)
val = -1;
4951 #ifdef BIGDECIMAL_DEBUG 4953 VPrint(stdout,
" VpComp a=%\n", a);
4954 VPrint(stdout,
" b=%\n", b);
4955 printf(
" ans=%d\n",
val);
4971 #ifdef BIGDECIMAL_ENABLE_VPRINT 4973 VPrint(
FILE *fp,
const char *cntl_chr,
Real *a)
4975 size_t i, j, nc, nd, ZeroSup, sep = 10;
5001 while (*(cntl_chr + j)) {
5002 if (*(cntl_chr + j) ==
'%' && *(cntl_chr + j + 1) !=
'%') {
5009 nc += fprintf(fp,
"0.");
5010 switch (*(cntl_chr + j + 1)) {
5020 for (i = 0; i < a->
Prec; ++i) {
5025 if (!ZeroSup || nn) {
5026 nc += fprintf(fp,
"%lu", (
unsigned long)nn);
5034 nc += fprintf(fp,
" ");
5044 nc += fprintf(fp,
"0.0");
5049 if (*(cntl_chr + j) ==
'\\') {
5050 switch (*(cntl_chr + j + 1)) {
5064 fprintf(fp,
"%c", *(cntl_chr + j));
5069 fprintf(fp,
"%c", *(cntl_chr + j));
5070 if (*(cntl_chr + j) ==
'%') ++j;
5083 size_t ie, i, nf = 0;
5086 if (fFmt == 0)
return;
5089 for (i = 0; i < ie; ++i) {
5092 if (
ISSPACE(ch) || ch==
'-' || ch==
'+')
continue;
5093 if (ch ==
'.') { nf = 0;
continue; }
5094 if (ch ==
'E')
break;
5097 memmove(psz + i + 1, psz + i, ie - i + 1);
5115 while ((a->
frac[0] / n) == 0) {
5125 size_t i, n, ZeroSup;
5145 for (i = 0; i < n; ++i) {
5150 if (!ZeroSup || nn) {
5151 sprintf(psz,
"%lu", (
unsigned long)nn);
5161 while (psz[-1] ==
'0') *(--psz) = 0;
5165 else sprintf(psz,
"-0");
5182 else if (fPlus == 2) {
5194 if (fPlus == 1) sprintf(psz,
" 0.0");
5195 else if (fPlus == 2) sprintf(psz,
"+0.0");
5196 else sprintf(psz,
"0.0");
5198 else sprintf(psz,
"-0.0");
5208 size_t i, n, ZeroSup;
5218 else if (fPlus == 1) *psz++ =
' ';
5219 else if (fPlus == 2) *psz++ =
'+';
5224 for (i = 0; i < n; ++i) {
5229 if (!ZeroSup || nn) {
5230 sprintf(psz,
"%lu", (
unsigned long)nn);
5245 while (psz[-1] ==
'0') {
5264 else if (fPlus == 1) *psz++ =
' ';
5265 else if (fPlus == 2) *psz++ =
'+';
5270 *psz++ =
'0';*psz++ =
'.';
5272 for (i=0; i <
BASE_FIG; ++i) *psz++ =
'0';
5278 for (i = 0; i < n; ++i) {
5280 if (i == 0 && ex >= 0) {
5281 sprintf(psz,
"%lu", (
unsigned long)a->
frac[i]);
5289 *psz++ = (char)(nn +
'0');
5294 if (ex == 0) *psz++ =
'.';
5298 while (m /= 10) *psz++ =
'0';
5299 if (ex == 0) *psz++ =
'.';
5302 while (psz[-1] ==
'0') *(--psz) = 0;
5303 if (psz[-1] ==
'.') sprintf(psz,
"0");
5321 size_t i, j, ind_a, ma, mi, me;
5323 int sign, signe, exponent_overflow;
5331 exponent_overflow = 0;
5335 if (exp_chr[0] ==
'-') {
5340 else if (exp_chr[0] ==
'+') {
5353 e = e * 10 + exp_chr[i] -
'0';
5358 exponent_overflow = 1;
5384 if (e > 0) signe = 1;
5403 if (exponent_overflow) {
5406 for (i = 0; i < nf &&
zero; i++)
zero = frac[i] ==
'0';
5407 if (!
zero && signe > 0) {
5425 if (ind_a >= ma)
goto over_flow;
5435 a->
frac[ind_a] = a->
frac[ind_a] * 10 + frac[i] -
'0';
5441 if (ind_a >= ma)
goto over_flow;
5448 rb_warn(
"Conversion from String to BigDecimal overflow (last few digits discarded).");
5451 if (ind_a >= ma) ind_a = ma - 1;
5453 a->
frac[ind_a] = a->
frac[ind_a] * 10;
5456 a->
Prec = ind_a + 1;
5481 size_t ind_m, mm, fig;
5521 while (ind_m < mm) {
5523 *d = *d + (double)m->
frac[ind_m++] *
div;
5529 #ifdef BIGDECIMAL_DEBUG 5531 VPrint(stdout,
" VpVtoD: m=%\n", m);
5532 printf(
" d=%e * 10 **%ld\n", *d, *e);
5533 printf(
" DBLE_FIG = %d\n",
DBLE_FIG);
5564 val = (d > 0.) ? d : -d;
5567 while (
val >= 1.0) {
5573 val2 = 1.0 / (double)
BASE;
5574 while (
val < val2) {
5583 for (ind_m = 0;
val > 0.0 && ind_m < mm; ind_m++) {
5589 if (ind_m >= mm) ind_m = mm - 1;
5591 m->
Prec = ind_m + 1;
5598 #ifdef BIGDECIMAL_DEBUG 5600 printf(
"VpDtoV d=%30.30e\n", d);
5601 VPrint(stdout,
" m=%\n", m);
5615 size_t val, v1, v2, v;
5627 val =(size_t)(-ival);
5632 while (ind_m < mm) {
5641 while (v1 >=
BASE) {
5655 m->
Prec = ind_m - 1;
5661 #ifdef BIGDECIMAL_DEBUG 5663 printf(
" VpItoV i=%d\n", ival);
5664 VPrint(stdout,
" m=%\n", m);
5718 prec = x->
exponent - (ssize_t)y_prec;
5727 if (e - n * 2 != 0) {
5750 #ifdef BIGDECIMAL_DEBUG 5752 printf(
"ERROR(VpSqrt): did not converge within %ld iterations.\n", nr);
5759 #ifdef BIGDECIMAL_DEBUG 5763 printf(
"VpSqrt: iterations = %"PRIdSIZE"\n", nr);
5764 VPrint(stdout,
" y =% \n", y);
5765 VPrint(stdout,
" x =% \n", x);
5766 VPrint(stdout,
" x-y*y = % \n",
f);
5793 int fracf, fracf_1further;
5794 ssize_t n,i,ix,ioffset, exptoadd;
5811 if ((
size_t)ix >= y->
Prec)
return 0;
5814 ioffset = nf - ix*(ssize_t)
BASE_FIG;
5815 n = (ssize_t)
BASE_FIG - ioffset - 1;
5816 for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
5845 fracf = (v % (shifter * 10) > 0);
5846 fracf_1further = ((v % shifter) > 0);
5862 for (i = ix + 1; (size_t)i < y->Prec; i++) {
5864 fracf = fracf_1further = 1;
5875 memset(y->
frac + ix + 1, 0, (y->
Prec - (ix + 1)) *
sizeof(
BDIGIT));
5887 if (v > 5 || (v == 5 && fracf_1further)) ++
div;
5898 if (fracf_1further) {
5908 if (ix && (y->
frac[ix-1] % 2)) ++
div;
5917 for (i = 0; i <= n; ++i)
div *= 10;
5938 for (i = 0; i < exptoadd; i++) {
5959 while ((v /= 10) != 0) nf--;
5968 if (
VpAsgn(y, x, 10) <= 1)
return 0;
5976 if (!
VpNmlz(c))
return -1;
5978 if (!ixDigit) ixDigit = c->
Prec-1;
5996 switch (rounding_mode) {
6021 else if (v == 5 && vPrev % 2)
f = 1;
6038 if (!ind_m) ind_m = m->
Prec;
6041 while (carry > 0 && ind_m--) {
6042 m->
frac[ind_m] += carry;
6062 size_t my, ind_y, ind_x;
6087 while (ind_y < my) {
6095 #ifdef BIGDECIMAL_DEBUG 6097 VPrint(stdout,
"VpFrac y=%\n", y);
6098 VPrint(stdout,
" x=%\n", x);
6123 if (sign < 0) sign = (n % 2) ? -1 : 1;
6127 if (sign < 0) sign = (n % 2) ? -1 : 1;
6153 if ((n % 2) == 0)
goto Exit;
6158 if (n > 0) sign = 1;
6179 while (ss = s, (s += s) <= (
size_t)n) {
6193 #ifdef BIGDECIMAL_DEBUG 6195 VPrint(stdout,
"VpPower y=%\n", y);
6196 VPrint(stdout,
"VpPower x=%\n", x);
6197 printf(
" n=%d\n", n);
6205 #ifdef BIGDECIMAL_DEBUG 6207 VpVarCheck(
Real * v)
6220 printf(
"ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
6225 printf(
"ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->
Prec);
6229 for (i = 0; i < v->
Prec; ++i) {
6231 printf(
"ERROR(VpVarCheck): Illegal fraction\n");
6235 printf(
" BASE =%lu\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)
VP_EXPORT double VpGetDoublePosInf(void)
static VALUE BigDecimal_coerce(VALUE self, VALUE other)
#define RMPD_EXCEPTION_MODE_DEFAULT
static BDIGIT VpAddAbs(Real *a, Real *b, Real *c)
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)
static ID id_BigDecimal_rounding_mode
static VALUE BigDecimal_lt(VALUE self, VALUE r)
static VALUE BigDecimal_sign(VALUE self)
VP_EXPORT int VpException(unsigned short f, const char *str, int always)
void rb_bug(const char *fmt,...)
#define RUBY_TYPED_FREE_IMMEDIATELY
static VALUE BigDecimal_power(int argc, VALUE *argv, VALUE self)
static void VpFormatSt(char *psz, size_t fFmt)
static VALUE BigDecimal_load(VALUE self, VALUE str)
size_t strlen(const char *)
static VALUE BigDecimal_div3(int argc, VALUE *argv, VALUE self)
static VALUE BigDecimal_to_r(VALUE self)
VALUE rb_Rational(VALUE, VALUE)
static VALUE BigDecimal_abs(VALUE self)
static int is_zero(VALUE x)
static Real * GetVpValue(VALUE v, int must)
#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.
static VALUE BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
VP_EXPORT int VpIsRoundMode(unsigned short n)
#define VP_SIGN_POSITIVE_FINITE
static unsigned short VpGetException(void)
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)
static VALUE BigDecimal_eq(VALUE self, VALUE r)
static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
static VALUE ToValue(Real *p)
static VALUE BigMath_s_log(VALUE, VALUE, VALUE)
static VALUE BigDecimal_dump(int argc, VALUE *argv, VALUE self)
VALUE rb_ary_push(VALUE ary, VALUE item)
static VALUE BigDecimal_limit(int argc, VALUE *argv, VALUE self)
static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self)
static int VpRdup(Real *m, size_t ind_m)
RUBY_EXTERN VALUE rb_eMathDomainError
st_index_t rb_memhash(const void *ptr, long len)
static VALUE BigMath_s_exp(VALUE, VALUE, VALUE)
VP_EXPORT unsigned short VpGetRoundMode(void)
VP_EXPORT unsigned short VpSetRoundMode(unsigned short n)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
static VALUE BigDecimal_mod(VALUE self, VALUE r)
VP_EXPORT void VpDtoV(Real *m, double d)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
if((ID)(DISPID) nameid !=nameid)
static void cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
void rb_raise(VALUE exc, const char *fmt,...)
VP_EXPORT void VpFrac(Real *y, Real *x)
#define VP_SIGN_POSITIVE_ZERO
static VALUE BigDecimal_sqrt(VALUE self, VALUE nFig)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
static void VpSetException(unsigned short f)
#define VP_ROUND_HALF_DOWN
#define VP_SIGN_POSITIVE_INFINITE
#define VP_EXCEPTION_OVERFLOW
#define RRATIONAL_NEGATIVE_P(x)
static VALUE BigDecimal_prec(VALUE self)
static VALUE BigDecimal_comp(VALUE self, VALUE r)
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.
static int is_one(VALUE x)
static VALUE BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
static VALUE BigDecimal_fix(VALUE self)
static VALUE BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
VALUE rb_str_tmp_new(long)
static void BigDecimal_delete(void *pv)
RUBY_EXTERN VALUE rb_eZeroDivError
#define DoSomeOne(x, y, f)
VP_EXPORT int VpComp(Real *a, Real *b)
static VALUE BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
static size_t GetAddSubPrec(Real *a, Real *b)
static const unsigned char dv[]
static Real * VpCopy(Real *pv, Real const *const x)
const char * rb_obj_classname(VALUE)
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)
VP_EXPORT Real * VpNewRbClass(size_t mx, const char *str, VALUE klass)
void rb_exc_raise(VALUE mesg)
static VALUE BigDecimal_mode(int argc, VALUE *argv, VALUE self)
#define VP_SIGN_NEGATIVE_FINITE
#define RB_TYPE_P(obj, type)
#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b)
static size_t BigDecimal_memsize(const void *ptr)
static VALUE BigDecimal_divmod(VALUE self, VALUE r)
static VALUE BigDecimal_inspect(VALUE self)
static VALUE BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
static VALUE BigDecimalCmp(VALUE self, VALUE r, char op)
static VALUE BigDecimal_neg(VALUE self)
static VALUE BigDecimal_save_rounding_mode(VALUE self)
VALUE rb_class_name(VALUE)
static VALUE BigDecimal_nonzero(VALUE self)
static int VpLimitRound(Real *c, size_t ixDigit)
VALUE rb_dbl2big(double d)
#define RMPD_COMPONENT_FIGURES
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE))
static VALUE BigDecimal_exponent(VALUE self)
#define VP_EXCEPTION_UNDERFLOW
static int VpIsDefOP(Real *c, Real *a, Real *b, int sw)
static VALUE BigDecimal_remainder(VALUE self, VALUE r)
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
VALUE rb_str_cat2(VALUE, const char *)
static VALUE BigDecimal_to_f(VALUE self)
#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.
static VALUE BigDecimal_div(VALUE self, VALUE r)
VP_EXPORT void * VpMemAlloc(size_t mb)
#define BDIGIT_DBL_SIGNED
void rb_define_const(VALUE, const char *, VALUE)
#define VpAllocReal(prec)
static VALUE BigDecimal_IsNaN(VALUE self)
VP_EXPORT size_t VpMult(Real *c, Real *a, Real *b)
static int VpNmlz(Real *a)
volatile const double gOne_ABCED9B4_CE73__00400511F31D
static int is_kind_of_BigDecimal(VALUE const v)
static VALUE BigDecimal_add2(VALUE self, VALUE b, VALUE n)
VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
static VALUE BigDecimal_initialize_copy(VALUE self, VALUE other)
#define MEMCPY(p1, p2, type, n)
RUBY_EXTERN int isinf(double)
VP_EXPORT Real * VpOne(void)
VP_EXPORT void VpSzMantissa(Real *a, char *psz)
static VALUE int_chr(int argc, VALUE *argv, VALUE num)
VALUE rb_big2str(VALUE x, int base)
static VALUE BigDecimal_version(VALUE self)
static VALUE BigDecimal_double_fig(VALUE self)
static VALUE BigDecimal_floor(int argc, VALUE *argv, VALUE self)
#define RBIGNUM_ZERO_P(x)
VP_EXPORT void VpFree(Real *pv)
void Init_bigdecimal(void)
VALUE rb_str_resize(VALUE, long)
static VALUE BigDecimal_add(VALUE self, VALUE r)
#define VP_EXCEPTION_ZERODIVIDE
static ID id_BigDecimal_exception_mode
static Real * GetVpValueWithPrec(VALUE v, long prec, int must)
static void VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
volatile const double gZero_ABCED9B1_CE73__00400511F31D
static const rb_data_type_t BigDecimal_data_type
#define VP_SIGN_NEGATIVE_INFINITE
void rb_fatal(const char *fmt,...)
static VALUE BigDecimal_uplus(VALUE self)
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]
static VALUE BigDecimal_ge(VALUE self, VALUE r)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
static VALUE BigDecimal_div2(VALUE, VALUE, VALUE)
static VALUE BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
static VALUE BigDecimal_split(VALUE self)
#define VP_EXCEPTION_MEMORY
static int is_integer(VALUE x)
static ID id_BigDecimal_precision_limit
VP_EXPORT size_t VpInit(BDIGIT BaseVal)
static VALUE rmpd_power_by_big_decimal(Real const *x, Real const *exp, ssize_t const n)
VALUE rb_num_coerce_relop(VALUE, VALUE, ID)
static void shift(struct cparse_params *v, long act, VALUE tok, VALUE val)
RUBY_EXTERN VALUE rb_cNumeric
void rb_jump_tag(int tag)
static VALUE BigDecimal_to_i(VALUE self)
static VALUE BigDecimal_s_allocate(VALUE klass)
VP_EXPORT double VpGetDoubleNegInf(void)
static VALUE BigDecimal_zero(VALUE self)
#define StringValueCStr(v)
static VALUE BigDecimal_IsFinite(VALUE self)
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw)
static size_t rmpd_double_figures(void)
BDIGIT frac[FLEXIBLE_ARRAY_SIZE]
#define RMPD_PRECISION_LIMIT_DEFAULT
static VALUE BigDecimal_gt(VALUE self, VALUE r)
#define rmpd_set_thread_local_precision_limit(limit)
static VALUE BigDecimal_mult(VALUE self, VALUE r)
static int is_negative(VALUE x)
#define VpChangeSign(a, s)
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
RUBY_EXTERN double round(double)
static void BigDecimal_check_num(Real *p)
static const unsigned char cv[]
static Real * BigDecimal_new(int argc, VALUE *argv)
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)
static VALUE BigDecimal_power_op(VALUE self, VALUE exp)
static int rb_special_const_p(VALUE obj)
static int is_even(VALUE x)
void rb_thread_check_ints(void)
static VALUE BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n)
static unsigned int hash(const char *str, unsigned int len)
#define SafeStringValue(v)
static SIGNED_VALUE GetPositiveInt(VALUE v)
static VALUE BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
#define assert(condition)
#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)
static BDIGIT VpSubAbs(Real *a, Real *b, Real *c)
VP_EXPORT size_t VpNumOfChars(Real *vp, const char *pszFmt)
#define rb_intern_const(str)
#define RBIGNUM_NEGATIVE_P(b)
static VALUE BigDecimal_hash(VALUE self)
VALUE rb_define_module(const char *name)
static unsigned short check_rounding_mode(VALUE const v)
static VALUE BigDecimal_save_limit(VALUE self)
static VALUE BigDecimal_le(VALUE self, VALUE r)
static VALUE BigDecimal_save_exception_mode(VALUE self)
static int AddExponent(Real *a, SIGNED_VALUE n)
VP_EXPORT double VpGetDoubleNegZero(void)
#define VpReallocReal(ptr, prec)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
void rb_warn(const char *fmt,...)
VP_EXPORT void * VpMemRealloc(void *ptr, size_t mb)
static VALUE BigDecimal_IsInfinite(VALUE self)
VP_EXPORT ssize_t VpExponent10(Real *a)
static VALUE BigDecimal_frac(VALUE self)
static VALUE BigDecimal_sub(VALUE self, VALUE r)
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
static VALUE BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
VALUE rb_str_new(const char *, long)
VALUE rb_obj_class(VALUE)
VP_EXPORT int VpSqrt(Real *y, Real *x)