17 #ifdef BIGDECIMAL_DEBUG
18 # define BIGDECIMAL_ENABLE_VPRINT 1
22 #ifndef BIGDECIMAL_DEBUG
63 #define ENTER(n) volatile VALUE vStack[n];int iStack=0
64 #define PUSH(x) vStack[iStack++] = (VALUE)(x);
65 #define SAVE(p) PUSH(p->obj);
66 #define GUARD_OBJ(p,y) {p=y;SAVE(p);}
68 #define BASE_FIG RMPD_COMPONENT_FIGURES
69 #define BASE RMPD_BASE
71 #define HALF_BASE (BASE/2)
72 #define BASE1 (BASE/10)
75 #define DBLE_FIG (DBL_DIG+1)
78 #ifndef RBIGNUM_ZERO_P
79 # define RBIGNUM_ZERO_P(x) (RBIGNUM_LEN(x) == 0 || \
80 (RBIGNUM_DIGITS(x)[0] == 0 && \
81 (RBIGNUM_LEN(x) == 1 || bigzero_p(x))))
96 #ifndef RRATIONAL_ZERO_P
97 # define RRATIONAL_ZERO_P(x) (FIXNUM_P(RRATIONAL(x)->num) && \
98 FIX2LONG(RRATIONAL(x)->num) == 0)
101 #ifndef RRATIONAL_NEGATIVE_P
102 # define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0)))
106 # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
107 # define RB_OBJ_STRING(obj) (obj)
109 # define PRIsVALUE "s"
110 # define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
111 # define RB_OBJ_STRING(obj) StringValueCStr(obj)
117 #define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
159 return pv ? (
sizeof(*pv) + pv->
MaxPrec *
sizeof(
BDIGIT)) : 0;
195 " can't be coerced into BigDecimal");
199 " can't be coerced into BigDecimal");
219 if (prec < 0)
goto unable_to_coerce_without_prec;
220 if (prec >
DBL_DIG+1)
goto SomeOneMayDoIt;
224 if (prec < 0)
goto unable_to_coerce_without_prec;
226 if (orig ==
Qundef ? (orig = v, 1) : orig != v) {
229 if (pv ==
NULL)
goto SomeOneMayDoIt;
254 #ifdef ENABLE_NUMERIC_STRING
275 unable_to_coerce_without_prec:
278 "%s can't be coerced into BigDecimal without a precision",
376 while((*pch)!=(
unsigned char)
'\0' && (ch=*pch++)!=(
unsigned char)
':') {
380 m = m*10 + (
unsigned long)(ch-
'0');
389 static unsigned short
485 (fo&(~VP_EXCEPTION_INFINITY))));
490 (fo&(~VP_EXCEPTION_NaN))));
495 (fo&(~VP_EXCEPTION_UNDERFLOW))));
500 (fo&(~VP_EXCEPTION_ZERODIVIDE))));
526 if(mx < b->Prec) mx = b->
Prec;
693 if (
VpVtoD(&d, &e, p) != 1)
731 ssize_t sign, power, denomi_power;
732 VALUE a, digits, numerator;
747 if (denomi_power < 0) {
839 if (mx == (
size_t)-1L) {
891 if (mx == (
size_t)-1L) {
971 if(e==0)
return Qtrue;
975 if(e>=0)
return Qtrue;
979 if(e> 0)
return Qtrue;
983 if(e<=0)
return Qtrue;
987 if(e< 0)
return Qtrue;
994 rb_bug(
"Undefined operation in BigDecimalCmp()");
1190 r = BigDecimal_divide(&c, &res, &div,
self, r);
1363 if(f!=(
VALUE)0)
return f;
1414 if (ix == 0)
return BigDecimal_div(
self, b);
1424 mx = av->
Prec + bv->Prec + 2;
1425 if(mx <= cv->MaxPrec) mx = cv->MaxPrec+1;
1581 switch (
rb_scan_args(argc, argv,
"02", &vLoc, &vRound)) {
1710 #ifdef BIGDECIMAL_DEBUG
1711 VPrint(stderr,
"floor: c=%\n", c);
1818 else if (*psz ==
'+') {
1822 while ((ch = *psz++) != 0) {
1827 if (ch ==
'F' || ch ==
'f') {
1832 mc = mc * 10 + ch -
'0';
1846 nc += (nc + mc - 1) / mc + 1;
1907 if(psz1[0]==
'N') s=0;
1955 sprintf(psz,
"#<BigDecimal:%"PRIxVALUE",'",
self);
1967 #define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n))
1968 #define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n))
1991 #define is_positive(x) (!is_negative(x))
2061 VALUE log_x, multiplied, y;
2106 switch (
TYPE(vexp)) {
2115 if (d ==
round(d)) {
2116 vexp = LL2NUM((LONG_LONG)
round(d));
2150 "wrong argument type %s (expected scalar Numeric)",
2231 "a non-integral exponent for a negative base");
2289 if (ma < 0) ma = -ma;
2290 if (ma == 0) ma = 1;
2340 if (
rb_scan_args(argc, argv,
"11", &iniValue, &nFig) == 1) {
2347 switch (
TYPE(iniValue)) {
2368 "can't omit precision for a %"PRIsVALUE".",
2410 if(nFig==
Qnil)
return nCur;
2532 infinite =
isinf(flo);
2534 if (!infinite && !nan) {
2565 else if (vx ==
NULL) {
2587 ssize_t
m = n -
vabs(ey - ed);
2673 if (zero || negative)
break;
2681 infinite =
isinf(flo);
2683 if (!zero && !negative && !infinite && !nan) {
2691 if (zero || negative)
break;
2697 "Complex argument for BigMath.log");
2702 if (infinite && !negative) {
2716 else if (zero || negative) {
2718 "Zero or negative argument for log");
2720 else if (vx ==
NULL) {
2731 if (expo < 0 || expo >= 3) {
2750 ssize_t
m = n -
vabs(ey - ed);
2768 VALUE log10, vexpo, dy;
3106 #ifdef BIGDECIMAL_DEBUG
3107 static int gfDebug = 1;
3109 static int gfCheckVal = 1;
3119 #define MemCmp(x,y,z) memcmp(x,y,z)
3120 #define StrCmp(x,y) strcmp(x,y)
3128 static void VpFormatSt(
char *psz,
size_t fFmt);
3131 #ifdef BIGDECIMAL_DEBUG
3132 static int gnAlloc=0;
3143 #ifdef BIGDECIMAL_DEBUG
3154 #ifdef BIGDECIMAL_DEBUG
3157 printf(
" *************** All memories allocated freed ****************");
3161 printf(
" ??????????? Too many memory free calls(%d) ?????????????\n",gnAlloc);
3172 #define rmpd_set_thread_local_exception_mode(mode) \
3173 rb_thread_local_aset( \
3174 rb_thread_current(), \
3175 id_BigDecimal_exception_mode, \
3176 INT2FIX((int)(mode)) \
3179 static unsigned short
3192 return (
unsigned short)
FIX2UINT(vmode);
3205 #define rmpd_set_thread_local_precision_limit(limit) \
3206 rb_thread_local_aset( \
3207 rb_thread_current(), \
3208 id_BigDecimal_precision_limit, \
3211 #define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0)
3222 if (
NIL_P(vlimit)) {
3242 #define rmpd_set_thread_local_rounding_mode(mode) \
3243 rb_thread_local_aset( \
3244 rb_thread_current(), \
3245 id_BigDecimal_rounding_mode, \
3246 INT2FIX((int)(mode)) \
3262 return (
unsigned short)
FIX2INT(vmode);
3333 static double fNaN = 0.0;
3334 if(fNaN==0.0) fNaN =
Zero()/
Zero();
3341 static double fInf = 0.0;
3342 if(fInf==0.0) fInf =
One()/
Zero();
3349 static double fInf = 0.0;
3350 if(fInf==0.0) fInf = -(
One()/
Zero());
3357 static double nzero = 1000.0;
3364 VpIsNegDoubleZero(
double v)
3367 return MemCmp(&v,&z,
sizeof(v))==0;
3380 if (always || (exception_mode & f)) {
3526 if((
size_t)ex > vp->
Prec) {
3562 VpConstOne =
VpAlloc(1UL,
"1");
3565 #ifdef BIGDECIMAL_DEBUG
3569 #ifdef BIGDECIMAL_DEBUG
3571 printf(
"VpInit: BaseVal = %lu\n", BaseVal);
3572 printf(
" BASE = %lu\n",
BASE);
3573 printf(
" HALF_BASE = %lu\n",
HALF_BASE);
3574 printf(
" BASE1 = %lu\n",
BASE1);
3575 printf(
" BASE_FIG = %u\n",
BASE_FIG);
3576 printf(
" DBLE_FIG = %d\n",
DBLE_FIG);
3600 if(mb<eb)
goto overflow;
3605 if(mb>eb)
goto underflow;
3636 size_t i, ni, ipn, ipf,
nf, ipe,
ne, nalloc;
3645 while (
ISSPACE(*szVal)) szVal++;
3646 if (*szVal !=
'#') {
3675 while ((psz[i]=szVal[ipn]) != 0) {
3677 if (psz[i] ==
'_') {
3678 if (ni > 0) { ipn++;
continue; }
3715 if (szVal[i] ==
'-') { sign=-1; ++
i; }
3716 else if (szVal[i] ==
'+') ++
i;
3719 while ((v = szVal[i]) != 0) {
3730 if (szVal[i] ==
'.') {
3733 while ((v = szVal[i]) != 0) {
3749 if ((v ==
'-') || (v ==
'+')) ++
i;
3750 while ((v=szVal[i]) != 0) {
3762 if (mx <= 0) mx = 1;
3763 nalloc =
Max(nalloc, mx);
3769 VpCtoV(vp, &szVal[ipn], ni, &szVal[ipf], nf, &szVal[ipe], ne);
3832 Real *a_ptr, *b_ptr;
3833 size_t n, na, nb,
i;
3836 #ifdef BIGDECIMAL_DEBUG
3838 VPrint(stdout,
"VpAddSub(enter) a=% \n", a);
3839 VPrint(stdout,
" b=% \n", b);
3840 printf(
" operation=%d\n", operation);
3844 if(!
VpIsDefOP(c,a,b,(operation>0)?1:2))
return 0;
3869 if(operation < 0) sw = -1;
3887 for(i=0;i <
n; ++
i) {
3892 }
else if(a->
frac[i] < b->
frac[i]) {
3902 }
else if(na < nb) {
3940 #ifdef BIGDECIMAL_DEBUG
3942 VPrint(stdout,
"VpAddSub(result) c=% \n", c);
3943 VPrint(stdout,
" a=% \n", a);
3944 VPrint(stdout,
" b=% \n", b);
3945 printf(
" operation=%d\n", operation);
3964 size_t b_pos, b_pos_with_word_shift;
3968 #ifdef BIGDECIMAL_DEBUG
3970 VPrint(stdout,
"VpAddAbs called: a = %\n", a);
3971 VPrint(stdout,
" b = %\n", b);
3975 word_shift =
VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
3979 if(word_shift==(
size_t)-1L)
return 0;
3980 if(b_pos == (
size_t)-1L)
goto Assign_a;
3986 while(b_pos + word_shift > a_pos) {
3998 b_pos_with_word_shift = b_pos + word_shift;
3999 while(a_pos > b_pos_with_word_shift) {
4000 c->
frac[--c_pos] = a->
frac[--a_pos];
4007 c->
frac[--c_pos] = a->
frac[--a_pos] + b->
frac[--b_pos] + carry;
4019 c->
frac[--c_pos] = a->
frac[--a_pos] + carry;
4027 if(c_pos) c->
frac[c_pos - 1] += carry;
4036 #ifdef BIGDECIMAL_DEBUG
4038 VPrint(stdout,
"VpAddAbs exit: c=% \n", c);
4055 size_t b_pos, b_pos_with_word_shift;
4059 #ifdef BIGDECIMAL_DEBUG
4061 VPrint(stdout,
"VpSubAbs called: a = %\n", a);
4062 VPrint(stdout,
" b = %\n", b);
4066 word_shift =
VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
4070 if(word_shift==(
size_t)-1L)
return 0;
4071 if(b_pos == (
size_t)-1L)
goto Assign_a;
4084 if(b_pos + word_shift > a_pos) {
4085 while(b_pos + word_shift > a_pos) {
4099 b_pos_with_word_shift = b_pos + word_shift;
4100 while(a_pos > b_pos_with_word_shift) {
4101 c->
frac[--c_pos] = a->
frac[--a_pos];
4108 if(a->
frac[--a_pos] < b->
frac[--b_pos] + borrow) {
4112 c->
frac[c_pos] = a->
frac[a_pos] - b->
frac[b_pos] - borrow;
4121 if(a->
frac[--a_pos] < borrow) {
4125 c->
frac[c_pos] = a->
frac[a_pos] - borrow;
4129 if(c_pos) c->
frac[c_pos - 1] -= borrow;
4137 #ifdef BIGDECIMAL_DEBUG
4139 VPrint(stdout,
"VpSubAbs exit: c=% \n", c);
4162 size_t left_word, right_word, word_shift;
4166 left_word = b->
Prec + word_shift;
4167 right_word =
Max((a->
Prec),left_word);
4172 if(right_word > left_word) {
4182 *c_pos = right_word = left_word + 1;
4191 *av = a->
frac[*a_pos];
4207 if(c->
MaxPrec >=(word_shift + 1)) {
4208 *b_pos = c->
MaxPrec - word_shift - 1;
4209 *bv = b->
frac[*b_pos];
4231 *c_pos = right_word + 1;
4257 size_t MxIndA, MxIndB, MxIndAB, MxIndC;
4258 size_t ind_c,
i, ii, nc;
4259 size_t ind_as, ind_ae, ind_bs, ind_be;
4264 #ifdef BIGDECIMAL_DEBUG
4266 VPrint(stdout,
"VpMult(Enter): a=% \n", a);
4267 VPrint(stdout,
" b=% \n", b);
4294 MxIndA = a->
Prec - 1;
4295 MxIndB = b->
Prec - 1;
4299 if(MxIndC < MxIndAB) {
4314 nc = ind_c = MxIndAB;
4317 for(nc = 0; nc < MxIndAB; ++nc, --ind_c) {
4319 ind_as = MxIndA - nc;
4322 ind_be = MxIndB - nc;
4323 }
else if(nc <= MxIndA) {
4324 ind_as = MxIndA - nc;
4325 ind_ae = MxIndA -(nc - MxIndB);
4328 }
else if(nc > MxIndA) {
4330 ind_ae = MxIndAB - nc - 1;
4331 ind_bs = MxIndB -(nc - MxIndA);
4335 for(i = ind_as; i <= ind_ae; ++
i) {
4348 c->
frac[ii] += carry;
4369 #ifdef BIGDECIMAL_DEBUG
4371 VPrint(stdout,
"VpMult(c=a*b): c=% \n", c);
4372 VPrint(stdout,
" a=% \n", a);
4373 VPrint(stdout,
" b=% \n", b);
4385 size_t word_a, word_b, word_c, word_r;
4386 size_t i,
n, ind_a, ind_b, ind_c, ind_r;
4389 BDIGIT borrow, borrow1, borrow2;
4392 #ifdef BIGDECIMAL_DEBUG
4394 VPrint(stdout,
" VpDivd(c=a/b) a=% \n", a);
4395 VPrint(stdout,
" b=% \n", b);
4430 if(word_a >= word_r)
goto space_error;
4433 while(ind_r <= word_a) {
4434 r->
frac[ind_r] = a->
frac[ind_r - 1];
4438 while(ind_r < word_r) r->
frac[ind_r++] = 0;
4439 while(ind_c < word_c) c->
frac[ind_c++] = 0;
4442 b1 = b1p1 = b->
frac[0];
4444 b1b2p1 = b1b2 = b1p1 *
BASE;
4447 b1b2p1 = b1b2 = b1 *
BASE + b->
frac[1];
4448 if(b->
Prec > 2) ++b1b2p1;
4454 nLoop =
Min(word_c,ind_c);
4456 while(ind_c < nLoop) {
4457 if(r->
frac[ind_c] == 0) {
4466 while(ind_b < word_b) {
4467 if(r->
frac[ind_a] < b->
frac[ind_b])
goto div_b1p1;
4468 if(r->
frac[ind_a] > b->
frac[ind_b])
break;
4476 ind_b = b->
Prec - 1;
4477 ind_r = ind_c + ind_b;
4478 if(ind_r >= word_r)
goto space_error;
4480 for(i = 0; i <=
n; ++
i) {
4481 if(r->
frac[ind_r] < b->
frac[ind_b] + borrow) {
4485 r->
frac[ind_r] = r->
frac[ind_r] - b->
frac[ind_b] - borrow;
4496 if(r1r2 >= b1b2p1) {
4499 ind_r = b->
Prec + ind_c - 1;
4504 if(ind_c + 1 >= word_c)
goto out_side;
4507 ind_r = b->
Prec + ind_c;
4510 borrow1 = borrow2 = 0;
4512 if(ind_r >= word_r)
goto space_error;
4514 for(i = 0; i <=
n; ++
i) {
4516 qb = q * b->
frac[ind_b];
4517 if (qb <
BASE) borrow1 = 0;
4522 if(r->
frac[ind_r] < qb) {
4524 borrow2 = borrow2 + borrow1 + 1;
4530 if(r->
frac[ind_r - 1] < borrow2) {
4531 r->
frac[ind_r - 1] += (
BASE - borrow2);
4534 r->
frac[ind_r - 1] -= borrow2;
4542 r->
frac[ind_r] -= borrow2;
4568 #ifdef BIGDECIMAL_DEBUG
4570 printf(
" word_a=%lu\n", word_a);
4571 printf(
" word_b=%lu\n", word_b);
4572 printf(
" word_c=%lu\n", word_c);
4573 printf(
" word_r=%lu\n", word_r);
4574 printf(
" ind_r =%lu\n", ind_r);
4577 rb_bug(
"ERROR(VpDivd): space for remainder too small.");
4580 #ifdef BIGDECIMAL_DEBUG
4582 VPrint(stdout,
" VpDivd(c=a/b), c=% \n", c);
4583 VPrint(stdout,
" r=% \n", r);
4603 if (a->
frac[ind_a]) {
4604 a->
Prec = ind_a + 1;
4606 while (a->
frac[i] == 0) ++
i;
4643 else if(e<0)
return -1;
4686 if((a->
frac[ind]) >(b->
frac[ind])) {
4690 if((a->
frac[ind]) <(b->
frac[ind])) {
4703 if (val> 1) val = 1;
4704 else if(val<-1) val = -1;
4706 #ifdef BIGDECIMAL_DEBUG
4708 VPrint(stdout,
" VpComp a=%\n", a);
4709 VPrint(stdout,
" b=%\n", b);
4710 printf(
" ans=%d\n", val);
4716 #ifdef BIGDECIMAL_ENABLE_VPRINT
4728 VPrint(
FILE *fp,
const char *cntl_chr,
Real *a)
4730 size_t i, j, nc, nd, ZeroSup;
4756 while(*(cntl_chr + j)) {
4757 if((*(cntl_chr + j) ==
'%') &&(*(cntl_chr + j + 1) !=
'%')) {
4764 nc += fprintf(fp,
"0.");
4765 for(i=0; i < a->
Prec; ++
i) {
4770 if((!ZeroSup) || nn) {
4771 nc += fprintf(fp,
"%lu", (
unsigned long)nn);
4779 nc += fprintf(fp,
" ");
4787 nc += fprintf(fp,
"0.0");
4791 if(*(cntl_chr + j) ==
'\\') {
4792 switch(*(cntl_chr + j + 1)) {
4806 fprintf(fp,
"%c", *(cntl_chr + j));
4810 fprintf(fp,
"%c", *(cntl_chr + j));
4811 if(*(cntl_chr + j) ==
'%') ++j;
4823 size_t ie,
i,
nf = 0;
4829 for(i = 0; i < ie; ++
i) {
4832 if(
ISSPACE(ch) || ch==
'-' || ch==
'+')
continue;
4833 if(ch ==
'.') { nf = 0;
continue;}
4834 if(ch ==
'E')
break;
4837 memmove(psz + i + 1, psz + i, ie - i + 1);
4855 while ((a->
frac[0] / n) == 0) {
4865 size_t i,
n, ZeroSup;
4885 for (i=0; i <
n; ++
i) {
4890 if((!ZeroSup) || nn) {
4891 sprintf(psz,
"%lu", (
unsigned long)nn);
4901 while(psz[-1]==
'0') *(--psz) = 0;
4904 else sprintf(psz,
"-0");
4920 }
else if(fPlus==2) {
4932 if(fPlus==1) sprintf(psz,
" 0.0");
4933 else if(fPlus==2) sprintf(psz,
"+0.0");
4934 else sprintf(psz,
"0.0");
4935 }
else sprintf(psz,
"-0.0");
4945 size_t i,
n, ZeroSup;
4955 else if (fPlus == 1) *psz++ =
' ';
4956 else if (fPlus == 2) *psz++ =
'+';
4961 for(i=0;i <
n;++
i) {
4966 if((!ZeroSup) || nn) {
4967 sprintf(psz,
"%lu", (
unsigned long)nn);
4982 while(psz[-1]==
'0') *(--psz) = 0;
4999 else if(fPlus==1) *psz++ =
' ';
5000 else if(fPlus==2) *psz++ =
'+';
5005 *psz++ =
'0';*psz++ =
'.';
5013 for(i=0;i <
n;++
i) {
5015 if(i==0 && ex >= 0) {
5016 sprintf(psz,
"%lu", (
unsigned long)a->
frac[i]);
5023 *psz++ = (char)(nn +
'0');
5028 if(ex == 0) *psz++ =
'.';
5032 while(m/=10) *psz++ =
'0';
5033 if(ex == 0) *psz++ =
'.';
5036 while(psz[-1]==
'0') *(--psz) = 0;
5037 if(psz[-1]==
'.') sprintf(psz,
"0");
5055 size_t i, j, ind_a, ma, mi, me;
5058 int sign, signe, exponent_overflow;
5066 exponent_overflow = 0;
5070 if (exp_chr[0] ==
'-') {
5075 else if (exp_chr[0] ==
'+') {
5081 e = e * 10 + exp_chr[
i] -
'0';
5083 exponent_overflow = 1;
5095 if(int_chr[0] ==
'-') {
5099 }
else if(int_chr[0] ==
'+') {
5108 if (e > 0) signe = 1;
5127 if (exponent_overflow) {
5129 for ( ; i < mi &&
zero; i++) zero = int_chr[i] ==
'0';
5130 for (i = 0; i < nf &&
zero; i++) zero = frac[i] ==
'0';
5131 if (!zero && signe > 0) {
5142 while ((j <
BASE_FIG) && (i < mi)) {
5143 a->
frac[ind_a] = a->
frac[ind_a] * 10 + int_chr[
i] -
'0';
5149 if (ind_a >= ma)
goto over_flow;
5159 while((j <
BASE_FIG) && (i < nf)) {
5160 a->
frac[ind_a] = a->
frac[ind_a] * 10 + frac[
i] -
'0';
5166 if(ind_a >= ma)
goto over_flow;
5173 rb_warn(
"Conversion from String to BigDecimal overflow (last few digits discarded).");
5176 if (ind_a >= ma) ind_a = ma - 1;
5178 a->
frac[ind_a] = a->
frac[ind_a] * 10;
5181 a->
Prec = ind_a + 1;
5206 size_t ind_m, mm, fig;
5247 div /= (double)
BASE;
5248 *d = *d + (double)m->
frac[ind_m++] * div;
5254 #ifdef BIGDECIMAL_DEBUG
5256 VPrint(stdout,
" VpVtoD: m=%\n", m);
5257 printf(
" d=%e * 10 **%ld\n", *d, *e);
5258 printf(
" DBLE_FIG = %d\n",
DBLE_FIG);
5289 val =(d > 0.) ? d :(-
d);
5293 val /= (double)
BASE;
5297 val2 = 1.0 /(double)
BASE;
5299 val *= (double)
BASE;
5307 for(ind_m = 0;val > 0.0 && ind_m < mm;ind_m++) {
5308 val *= (double)
BASE;
5313 if(ind_m >= mm) ind_m = mm - 1;
5315 m->
Prec = ind_m + 1;
5322 #ifdef BIGDECIMAL_DEBUG
5324 printf(
"VpDtoV d=%30.30e\n", d);
5325 VPrint(stdout,
" m=%\n", m);
5339 size_t val, v1, v2,
v;
5351 val =(size_t)(-ival);
5369 val = val - v2 * v1;
5378 m->
Prec = ind_m - 1;
5384 #ifdef BIGDECIMAL_DEBUG
5386 printf(
" VpItoV i=%d\n", ival);
5387 VPrint(stdout,
" m=%\n", m);
5402 size_t y_prec, f_prec;
5441 prec = x->
exponent - (ssize_t)y_prec;
5450 if (e - n * 2 != 0) {
5471 if(f->
exponent <= prec)
goto converge;
5474 #ifdef BIGDECIMAL_DEBUG
5476 printf(
"ERROR(VpSqrt): did not converge within %ld iterations.\n",
5484 #ifdef BIGDECIMAL_DEBUG
5488 printf(
"VpSqrt: iterations = %"PRIdSIZE"\n", nr);
5489 VPrint(stdout,
" y =% \n", y);
5490 VPrint(stdout,
" x =% \n", x);
5491 VPrint(stdout,
" x-y*y = % \n", f);
5518 int fracf, fracf_1further;
5536 if ((
size_t)ix >= y->
Prec)
return 0;
5539 ioffset = nf - ix*(ssize_t)
BASE_FIG;
5540 n = (ssize_t)
BASE_FIG - ioffset - 1;
5541 for (shifter=1,i=0; i<
n; ++
i) shifter *= 10;
5565 fracf = (v % (shifter * 10) > 0);
5566 fracf_1further = ((v %
shifter) > 0);
5582 for (i=ix+1; (size_t)i < y->Prec; i++) {
5584 fracf = fracf_1further = 1;
5607 if (v > 5 || (v == 5 && fracf_1further)) ++
div;
5618 if (fracf_1further) {
5628 if (ix && (y->
frac[ix-1] % 2)) ++
div;
5637 for (i=0; i<=
n; ++
i) div *= 10;
5677 while ((v /= 10) != 0) nf--;
5686 if (
VpAsgn(y, x, 10) <= 1)
return 0;
5694 if(!
VpNmlz(c))
return -1;
5696 if(!ixDigit) ixDigit = c->
Prec-1;
5714 switch (rounding_mode) {
5739 else if (v == 5 && vPrev % 2) f = 1;
5756 if (!ind_m) ind_m = m->
Prec;
5759 while (carry > 0 && (ind_m--)) {
5760 m->
frac[ind_m] += carry;
5779 size_t my, ind_y, ind_x;
5812 #ifdef BIGDECIMAL_DEBUG
5814 VPrint(stdout,
"VpFrac y=%\n", y);
5815 VPrint(stdout,
" x=%\n", x);
5840 if(sign<0) sign = (n%2)?(-1):(1);
5843 if(sign<0) sign = (n%2)?(-1):(1);
5869 if((n % 2) == 0)
goto Exit;
5894 while (ss = s, (s += s) <= (
size_t)n) {
5903 VpDivd(w1, w2, VpConstOne, y);
5908 #ifdef BIGDECIMAL_DEBUG
5910 VPrint(stdout,
"VpPower y=%\n", y);
5911 VPrint(stdout,
"VpPower x=%\n", x);
5912 printf(
" n=%d\n", n);
5920 #ifdef BIGDECIMAL_DEBUG
5922 VpVarCheck(
Real * v)
5935 printf(
"ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
5940 printf(
"ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->
Prec);
5944 for(i = 0; i < v->
Prec; ++
i) {
5946 printf(
"ERROR(VpVarCheck): Illegal fraction\n");
5950 printf(
" BASE =%lu\n",
BASE);
VP_EXPORT size_t VpDivd(Real *c, Real *r, Real *a, Real *b)
#define RSTRING_LEN(string)
VP_EXPORT double VpGetDoublePosInf(void)
VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il)
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,...)
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_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)
if(len<=MAX_WORD_LENGTH &&len >=MIN_WORD_LENGTH)
static int bigzero_p(VALUE x)
#define VP_SIGN_POSITIVE_FINITE
static unsigned short VpGetException(void)
#define VP_SIGN_NEGATIVE_ZERO
#define RFLOAT_VALUE(val)
#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)
static VALUE INT2NUM(int v)
VP_EXPORT unsigned short VpSetRoundMode(unsigned short n)
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)
#define RSTRING_PTR(string)
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)
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 * VpDup(Real const *const x)
const char * rb_obj_classname(VALUE)
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)
RUBY_EXTERN void * memmove(void *, const void *, size_t)
#define VP_EXCEPTION_INFINITY
static VALUE BigDecimal_div2(int, VALUE *, VALUE)
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)
VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf)
static size_t BigDecimal_memsize(const void *ptr)
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
static VALUE BigDecimal_divmod(VALUE self, VALUE r)
static VALUE BigDecimal_inspect(VALUE self)
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)
static VALUE BigDecimal_exponent(VALUE self)
#define VP_EXCEPTION_UNDERFLOW
VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
static int VpIsDefOP(Real *c, Real *a, Real *b, int sw)
#define BDIGIT_DBL_SIGNED
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.
VP_EXPORT void * VpMemAlloc(size_t mb)
void rb_define_const(VALUE, const char *, VALUE)
static VALUE BigDecimal_new(int argc, VALUE *argv, VALUE self)
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)
unsigned char buf[MIME_BUF_SIZE]
#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)
#define RBIGNUM_DIGITS(b)
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,...)
#define RB_GC_GUARD(object)
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)
static VALUE BigDecimal_ge(VALUE self, VALUE r)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
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)
VP_EXPORT int VpToSpecialString(Real *a, char *psz, int fPlus)
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)
register unsigned int len
VALUE rb_num_coerce_relop(VALUE, VALUE, ID)
RUBY_EXTERN VALUE rb_cNumeric
void rb_jump_tag(int tag)
static VALUE BigDecimal_to_i(VALUE self)
VP_EXPORT double VpGetDoubleNegInf(void)
static VALUE BigDecimal_zero(VALUE self)
VALUE rb_float_new(double)
static VALUE BigDecimal_IsFinite(VALUE self)
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw)
static size_t rmpd_double_figures(void)
#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)
VALUE rb_exc_new3(VALUE etype, VALUE str)
RUBY_EXTERN double round(double)
#define RB_OBJ_CLASSNAME(obj)
static void BigDecimal_check_num(Real *p)
static const unsigned char cv[]
#define RMPD_ROUNDING_MODE_DEFAULT
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)
static VALUE BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf)
VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n)
#define SafeStringValue(v)
static SIGNED_VALUE GetPositiveInt(VALUE v)
VALUE rb_ary_new2(long capa)
#define assert(condition)
#define VP_ROUND_HALF_EVEN
return rb_funcall(q->proc, ID_call, 0)
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)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_str_new2(const char *)
void rb_warn(const char *fmt,...)
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)
STATIC void unsigned char * cp
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)