From 9cc7e9d1e8cea421808340ac2ccbc0c484b527fc Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 11 May 2012 04:50:54 +0000 Subject: Revert r35616 "* ext/bigdecimal/bigdecimal.c: use RB_GC_GUARD. [ruby-dev:45627]" RB_GC_GUARD() is only for variables on the machine stack, because it forces a VALUE to be stored in a variable which should be referenced from the GC, but does not add any reference path to the variable. So it makes no sense for objects in heap. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35618 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/bigdecimal/bigdecimal.c | 506 +++++++++++++++++++------------------------- 1 file changed, 213 insertions(+), 293 deletions(-) (limited to 'ext/bigdecimal') diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 073228a3b2..a2d705ce20 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -59,6 +59,12 @@ static ID id_floor; static ID id_to_r; static ID id_eq; +/* MACRO's to guard objects from GC by keeping them in stack */ +#define ENTER(n) volatile VALUE vStack[n];int iStack=0 +#define PUSH(x) vStack[iStack++] = (unsigned long)(x); +#define SAVE(p) PUSH(p->obj); +#define GUARD_OBJ(p,y) {p=y;SAVE(p);} + #define BASE_FIG RMPD_COMPONENT_FIGURES #define BASE RMPD_BASE @@ -296,13 +302,13 @@ BigDecimal_double_fig(VALUE self) static VALUE BigDecimal_prec(VALUE self) { + ENTER(1); Real *p; VALUE obj; - p = GetVpValue(self,1); + GUARD_OBJ(p,GetVpValue(self,1)); obj = rb_assoc_new(INT2NUM(p->Prec*VpBaseFig()), INT2NUM(p->MaxPrec*VpBaseFig())); - RB_GC_GUARD(p->obj); return obj; } @@ -315,36 +321,36 @@ BigDecimal_prec(VALUE self) static VALUE BigDecimal_hash(VALUE self) { + ENTER(1); Real *p; st_index_t hash; - p = GetVpValue(self,1); + GUARD_OBJ(p,GetVpValue(self,1)); hash = (st_index_t)p->sign; /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */ if(hash == 2 || hash == (st_index_t)-2) { hash ^= rb_memhash(p->frac, sizeof(BDIGIT)*p->Prec); hash += p->exponent; } - RB_GC_GUARD(p->obj); return INT2FIX(hash); } static VALUE BigDecimal_dump(int argc, VALUE *argv, VALUE self) { + ENTER(5); Real *vp; char *psz; VALUE dummy; volatile VALUE dump; rb_scan_args(argc, argv, "01", &dummy); - vp = GetVpValue(self,1); + GUARD_OBJ(vp,GetVpValue(self,1)); dump = rb_str_new(0,VpNumOfChars(vp,"E")+50); psz = RSTRING_PTR(dump); sprintf(psz, "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig()); VpToString(vp, psz+strlen(psz), 0, 0); rb_str_resize(dump, strlen(psz)); - RB_GC_GUARD(vp->obj); return dump; } @@ -354,6 +360,7 @@ BigDecimal_dump(int argc, VALUE *argv, VALUE self) static VALUE BigDecimal_load(VALUE self, VALUE str) { + ENTER(2); Real *pv; unsigned char *pch; unsigned char ch; @@ -369,10 +376,9 @@ BigDecimal_load(VALUE self, VALUE str) m = m*10 + (unsigned long)(ch-'0'); } if(m>VpBaseFig()) m -= VpBaseFig(); - pv = VpNewRbClass(m, (char *)pch, self); + GUARD_OBJ(pv,VpNewRbClass(m,(char *)pch,self)); m /= VpBaseFig(); if(m && pv->MaxPrec>m) pv->MaxPrec = m+1; - RB_GC_GUARD(pv->obj); return ToValue(pv); } @@ -625,10 +631,11 @@ static VALUE BigDecimal_split(VALUE self); static VALUE BigDecimal_to_i(VALUE self) { + ENTER(5); ssize_t e, nf; Real *p; - p = GetVpValue(self, 1); + GUARD_OBJ(p,GetVpValue(self,1)); BigDecimal_check_num(p); e = VpExponent10(p); @@ -658,8 +665,6 @@ BigDecimal_to_i(VALUE self) INT2FIX(dpower))); if (TYPE(ret) == T_FLOAT) rb_raise(rb_eFloatDomainError, "Infinity"); - - RB_GC_GUARD(p->obj); return ret; } } @@ -671,13 +676,14 @@ BigDecimal_to_i(VALUE self) static VALUE BigDecimal_to_f(VALUE self) { + ENTER(1); Real *p; double d; SIGNED_VALUE e; char *buf; volatile VALUE str; - p = GetVpValue(self, 1); + GUARD_OBJ(p, GetVpValue(self, 1)); if (VpVtoD(&d, &e, p) != 1) return rb_float_new(d); if (e > (SIGNED_VALUE)(DBL_MAX_10_EXP+BASE_FIG)) @@ -692,8 +698,6 @@ BigDecimal_to_f(VALUE self) d = strtod(buf, 0); if (errno == ERANGE) goto overflow; - - RB_GC_GUARD(p->obj); return rb_float_new(d); overflow: @@ -763,6 +767,7 @@ BigDecimal_to_r(VALUE self) static VALUE BigDecimal_coerce(VALUE self, VALUE other) { + ENTER(2); VALUE obj; Real *b; @@ -772,13 +777,12 @@ BigDecimal_coerce(VALUE self, VALUE other) else { if (TYPE(other) == T_RATIONAL) { Real* pv = DATA_PTR(self); - b = GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1); + GUARD_OBJ(b, GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1)); } else { - b = GetVpValue(other, 1); + GUARD_OBJ(b, GetVpValue(other, 1)); } obj = rb_assoc_new(b->obj, self); - RB_GC_GUARD(b->obj); } return obj; @@ -812,28 +816,27 @@ BigDecimal_uplus(VALUE self) static VALUE BigDecimal_add(VALUE self, VALUE r) { + ENTER(5); Real *c, *a, *b; size_t mx; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); b = GetVpValue(r,0); if(!b) return DoSomeOne(self,r,'+'); + SAVE(b); if(VpIsNaN(b)) return b->obj; if(VpIsNaN(a)) return a->obj; mx = GetAddSubPrec(a,b); if (mx == (size_t)-1L) { - c = VpCreateRbObject(VpBaseFig() + 1, "0"); + GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0")); VpAddSub(c, a, b, 1); } else { - c = VpCreateRbObject(mx *(VpBaseFig() + 1), "0"); + GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0")); if(!mx) { VpSetInf(c,VpGetSign(a)); } else { VpAddSub(c, a, b, 1); } } - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -851,42 +854,40 @@ BigDecimal_add(VALUE self, VALUE r) static VALUE BigDecimal_sub(VALUE self, VALUE r) { + ENTER(5); Real *c, *a, *b; size_t mx; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); b = GetVpValue(r,0); if(!b) return DoSomeOne(self,r,'-'); + SAVE(b); if(VpIsNaN(b)) return b->obj; if(VpIsNaN(a)) return a->obj; mx = GetAddSubPrec(a,b); if (mx == (size_t)-1L) { - c = VpCreateRbObject(VpBaseFig() + 1, "0"); + GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0")); VpAddSub(c, a, b, -1); } else { - c = VpCreateRbObject(mx *(VpBaseFig() + 1), "0"); + GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0")); if(!mx) { VpSetInf(c,VpGetSign(a)); } else { VpAddSub(c, a, b, -1); } } - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } static VALUE BigDecimalCmp(VALUE self, VALUE r,char op) { + ENTER(5); SIGNED_VALUE e; Real *a, *b=0; - - a = GetVpValue(self, 1); - + GUARD_OBJ(a,GetVpValue(self,1)); switch (TYPE(r)) { case T_DATA: if (!is_kind_of_BigDecimal(r)) break; @@ -894,15 +895,15 @@ BigDecimalCmp(VALUE self, VALUE r,char op) case T_FIXNUM: /* fall through */ case T_BIGNUM: - b = GetVpValue(r,0); + GUARD_OBJ(b, GetVpValue(r,0)); break; case T_FLOAT: - b = GetVpValueWithPrec(r, DBL_DIG+1, 0); + GUARD_OBJ(b, GetVpValueWithPrec(r, DBL_DIG+1, 0)); break; case T_RATIONAL: - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 0); + GUARD_OBJ(b, GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 0)); break; default: @@ -937,14 +938,10 @@ BigDecimalCmp(VALUE self, VALUE r,char op) } return rb_num_coerce_relop(self, r, f); } - + SAVE(b); e = VpComp(a, b); - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - if (e == 999) return (op == '*') ? Qnil : Qfalse; - switch (op) { case '*': return INT2FIX(e); /* any op */ @@ -1078,12 +1075,11 @@ BigDecimal_ge(VALUE self, VALUE r) static VALUE BigDecimal_neg(VALUE self) { + ENTER(5); Real *c, *a; - a = GetVpValue(self, 1); - c = VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"); + GUARD_OBJ(a,GetVpValue(self,1)); + GUARD_OBJ(c,VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0")); VpAsgn(c, a, -1); - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1101,19 +1097,18 @@ BigDecimal_neg(VALUE self) static VALUE BigDecimal_mult(VALUE self, VALUE r) { + ENTER(5); Real *c, *a, *b; size_t mx; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); b = GetVpValue(r,0); if(!b) return DoSomeOne(self,r,'*'); + SAVE(b); mx = a->Prec + b->Prec; - c = VpCreateRbObject(mx *(VpBaseFig() + 1), "0"); + GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0")); VpMult(c, a, b); - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1121,23 +1116,21 @@ static VALUE BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r) /* For c = self.div(r): with round operation */ { + ENTER(5); Real *a, *b; size_t mx; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); b = GetVpValue(r,0); if(!b) return DoSomeOne(self,r,'/'); + SAVE(b); *div = b; mx = a->Prec + vabs(a->exponent); if(mxPrec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent); mx =(mx + 1) * VpBaseFig(); - *c = VpCreateRbObject(mx, "#0"); - *res = VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"); + GUARD_OBJ((*c),VpCreateRbObject(mx, "#0")); + GUARD_OBJ((*res),VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); VpDivd(*c, *res, a, b); - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD((*c)->obj); - RB_GC_GUARD((*res)->obj); return (VALUE)0; } @@ -1162,9 +1155,11 @@ static VALUE BigDecimal_div(VALUE self, VALUE r) /* For c = self/r: with round operation */ { + ENTER(5); Real *c=NULL, *res=NULL, *div = NULL; r = BigDecimal_divide(&c, &res, &div, self, r); - if (r != (VALUE)0) return r; /* coerced by other */ + if(r!=(VALUE)0) return r; /* coerced by other */ + SAVE(c);SAVE(res);SAVE(div); /* a/b = c + r/b */ /* c xxxxx r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE @@ -1172,10 +1167,7 @@ BigDecimal_div(VALUE self, VALUE r) /* Round */ if(VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */ VpInternalRound(c, 0, c->frac[c->Prec-1], (BDIGIT)(VpBaseVal()*(BDIGIT_DBL)res->frac[0]/div->frac[0])); - RB_GC_GUARD(res->obj); - RB_GC_GUARD(div->obj); } - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1186,13 +1178,15 @@ BigDecimal_div(VALUE self, VALUE r) static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) { + ENTER(8); Real *c=NULL, *d=NULL, *res=NULL; Real *a, *b; size_t mx; - a = GetVpValue(self, 1); - b = GetVpValue(r, 0); + GUARD_OBJ(a,GetVpValue(self,1)); + b = GetVpValue(r,0); if(!b) return Qfalse; + SAVE(b); if(VpIsNaN(a) || VpIsNaN(b)) goto NaN; if(VpIsInf(a) && VpIsInf(b)) goto NaN; @@ -1200,75 +1194,55 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) rb_raise(rb_eZeroDivError, "divided by 0"); } if(VpIsInf(a)) { - d = VpCreateRbObject(1, "0"); + GUARD_OBJ(d,VpCreateRbObject(1, "0")); VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1)); - c = VpCreateRbObject(1, "NaN"); + GUARD_OBJ(c,VpCreateRbObject(1, "NaN")); *div = d; *mod = c; - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); - RB_GC_GUARD(d->obj); return Qtrue; } if(VpIsInf(b)) { - d = VpCreateRbObject(1, "0"); + GUARD_OBJ(d,VpCreateRbObject(1, "0")); *div = d; *mod = a; - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); - RB_GC_GUARD(d->obj); return Qtrue; } if(VpIsZero(a)) { - c = VpCreateRbObject(1, "0"); - d = VpCreateRbObject(1, "0"); + GUARD_OBJ(c,VpCreateRbObject(1, "0")); + GUARD_OBJ(d,VpCreateRbObject(1, "0")); *div = d; *mod = c; - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); - RB_GC_GUARD(d->obj); return Qtrue; } mx = a->Prec + vabs(a->exponent); if(mxPrec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent); mx =(mx + 1) * VpBaseFig(); - c = VpCreateRbObject(mx, "0"); - res = VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); + GUARD_OBJ(res,VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); VpDivd(c, res, a, b); mx = c->Prec *(VpBaseFig() + 1); - d = VpCreateRbObject(mx, "0"); + GUARD_OBJ(d,VpCreateRbObject(mx, "0")); VpActiveRound(d,c,VP_ROUND_DOWN,0); VpMult(res,d,b); VpAddSub(c,a,res,-1); if(!VpIsZero(c) && (VpGetSign(a)*VpGetSign(b)<0)) { - VpAddSub(res,d,VpOne(),-1); - d = VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0"); - VpAddSub(d ,c,b, 1); - *div = res; - *mod = d; + VpAddSub(res,d,VpOne(),-1); + GUARD_OBJ(d,VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0")); + VpAddSub(d ,c,b, 1); + *div = res; + *mod = d; } else { - *div = d; - *mod = c; + *div = d; + *mod = c; } - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); - RB_GC_GUARD(d->obj); return Qtrue; NaN: - c = VpCreateRbObject(1, "NaN"); - d = VpCreateRbObject(1, "NaN"); + GUARD_OBJ(c,VpCreateRbObject(1, "NaN")); + GUARD_OBJ(d,VpCreateRbObject(1, "NaN")); *div = d; *mod = c; - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); - RB_GC_GUARD(d->obj); return Qtrue; } @@ -1281,11 +1255,11 @@ NaN: static VALUE BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */ { + ENTER(3); Real *div=NULL, *mod=NULL; if(BigDecimal_DoDivmod(self,r,&div,&mod)) { - RB_GC_GUARD(div->obj); - RB_GC_GUARD(mod->obj); + SAVE(div); SAVE(mod); return ToValue(mod); } return DoSomeOne(self,r,'%'); @@ -1294,26 +1268,28 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */ static VALUE BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv) { + ENTER(10); size_t mx; Real *a=NULL, *b=NULL, *c=NULL, *res=NULL, *d=NULL, *rr=NULL, *ff=NULL; Real *f=NULL; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); b = GetVpValue(r,0); - if (!b) return DoSomeOne(self, r, rb_intern("remainder")); + if(!b) return DoSomeOne(self,r,rb_intern("remainder")); + SAVE(b); mx =(a->MaxPrec + b->MaxPrec) *VpBaseFig(); - c = VpCreateRbObject(mx, "0"); - res = VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"); - rr = VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"); - ff = VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"); + GUARD_OBJ(c ,VpCreateRbObject(mx, "0")); + GUARD_OBJ(res,VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); + GUARD_OBJ(rr ,VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); + GUARD_OBJ(ff ,VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); VpDivd(c, res, a, b); mx = c->Prec *(VpBaseFig() + 1); - d = VpCreateRbObject(mx, "0"); - f = VpCreateRbObject(mx, "0"); + GUARD_OBJ(d,VpCreateRbObject(mx, "0")); + GUARD_OBJ(f,VpCreateRbObject(mx, "0")); VpActiveRound(d,c,VP_ROUND_DOWN,0); /* 0: round off */ @@ -1323,15 +1299,6 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv) *dv = d; *rv = ff; - - RB_GC_GUARD(a->obj); - RB_GC_GUARD(b->obj); - RB_GC_GUARD(c->obj); - RB_GC_GUARD(res->obj); - RB_GC_GUARD(rr->obj); - RB_GC_GUARD(ff->obj); - RB_GC_GUARD(d->obj); - RB_GC_GUARD(f->obj); return (VALUE)0; } @@ -1371,11 +1338,11 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */ static VALUE BigDecimal_divmod(VALUE self, VALUE r) { + ENTER(5); Real *div=NULL, *mod=NULL; - if (BigDecimal_DoDivmod(self,r,&div,&mod)) { - RB_GC_GUARD(div->obj); - RB_GC_GUARD(mod->obj); + if(BigDecimal_DoDivmod(self,r,&div,&mod)) { + SAVE(div); SAVE(mod); return rb_assoc_new(ToValue(div), ToValue(mod)); } return DoSomeOne(self,r,rb_intern("divmod")); @@ -1384,47 +1351,35 @@ BigDecimal_divmod(VALUE self, VALUE r) static VALUE BigDecimal_div2(int argc, VALUE *argv, VALUE self) { + ENTER(5); VALUE b,n; - int na = rb_scan_args(argc, argv, "11", &b, &n); - - if (na == 1) { - /* div in Float sense */ - Real *div=NULL; - Real *mod; - if (BigDecimal_DoDivmod(self, b, &div, &mod)) { - return BigDecimal_to_i(ToValue(div)); - } - return DoSomeOne(self, b, rb_intern("div")); - } - else { - /* div in BigDecimal sense */ - SIGNED_VALUE ix = GetPositiveInt(n); - if (ix == 0) { - return BigDecimal_div(self, b); - } - else { - Real *res=NULL; - Real *av=NULL, *bv=NULL, *cv=NULL; - size_t mx = ix + VpBaseFig()*2; - size_t pl = VpSetPrecLimit(0); - - cv = VpCreateRbObject(mx, "0"); - av = GetVpValue(self, 1); - bv = GetVpValue(b, 1); - mx = av->Prec + bv->Prec + 2; - if (mx <= cv->MaxPrec) { - mx = cv->MaxPrec + 1; - } - res = VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"); - VpDivd(cv, res, av, bv); - VpSetPrecLimit(pl); - VpLeftRound(cv, VpGetRoundMode(), ix); - - RB_GC_GUARD(cv->obj); - RB_GC_GUARD(av->obj); - RB_GC_GUARD(bv->obj); - RB_GC_GUARD(res->obj); - return ToValue(cv); + int na = rb_scan_args(argc,argv,"11",&b,&n); + if(na==1) { /* div in Float sense */ + Real *div=NULL; + Real *mod; + if(BigDecimal_DoDivmod(self,b,&div,&mod)) { + return BigDecimal_to_i(ToValue(div)); + } + return DoSomeOne(self,b,rb_intern("div")); + } else { /* div in BigDecimal sense */ + SIGNED_VALUE ix = GetPositiveInt(n); + if (ix == 0) return BigDecimal_div(self, b); + else { + Real *res=NULL; + Real *av=NULL, *bv=NULL, *cv=NULL; + size_t mx = (ix+VpBaseFig()*2); + size_t pl = VpSetPrecLimit(0); + + GUARD_OBJ(cv,VpCreateRbObject(mx,"0")); + GUARD_OBJ(av,GetVpValue(self,1)); + GUARD_OBJ(bv,GetVpValue(b,1)); + mx = av->Prec + bv->Prec + 2; + if(mx <= cv->MaxPrec) mx = cv->MaxPrec+1; + GUARD_OBJ(res,VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0")); + VpDivd(cv,res,av,bv); + VpSetPrecLimit(pl); + VpLeftRound(cv,VpGetRoundMode(),ix); + return ToValue(cv); } } } @@ -1432,37 +1387,33 @@ BigDecimal_div2(int argc, VALUE *argv, VALUE self) static VALUE BigDecimal_add2(VALUE self, VALUE b, VALUE n) { + ENTER(2); Real *cv; SIGNED_VALUE mx = GetPositiveInt(n); - if (mx == 0) { - return BigDecimal_add(self, b); - } + if (mx == 0) return BigDecimal_add(self, b); else { - size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_add(self, b); - VpSetPrecLimit(pl); - cv = GetVpValue(c, 1); - VpLeftRound(cv, VpGetRoundMode(), mx); - RB_GC_GUARD(cv->obj); - return ToValue(cv); + size_t pl = VpSetPrecLimit(0); + VALUE c = BigDecimal_add(self,b); + VpSetPrecLimit(pl); + GUARD_OBJ(cv,GetVpValue(c,1)); + VpLeftRound(cv,VpGetRoundMode(),mx); + return ToValue(cv); } } static VALUE BigDecimal_sub2(VALUE self, VALUE b, VALUE n) { + ENTER(2); Real *cv; SIGNED_VALUE mx = GetPositiveInt(n); - if (mx == 0) { - return BigDecimal_sub(self, b); - } + if (mx == 0) return BigDecimal_sub(self, b); else { size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_sub(self, b); + VALUE c = BigDecimal_sub(self,b); VpSetPrecLimit(pl); - cv = GetVpValue(c, 1); - VpLeftRound(cv, VpGetRoundMode(), mx); - RB_GC_GUARD(cv->obj); + GUARD_OBJ(cv,GetVpValue(c,1)); + VpLeftRound(cv,VpGetRoundMode(),mx); return ToValue(cv); } } @@ -1470,18 +1421,16 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n) static VALUE BigDecimal_mult2(VALUE self, VALUE b, VALUE n) { + ENTER(2); Real *cv; SIGNED_VALUE mx = GetPositiveInt(n); - if (mx == 0) { - return BigDecimal_mult(self, b); - } + if (mx == 0) return BigDecimal_mult(self, b); else { size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_mult(self, b); + VALUE c = BigDecimal_mult(self,b); VpSetPrecLimit(pl); - cv = GetVpValue(c, 1); - VpLeftRound(cv, VpGetRoundMode(), mx); - RB_GC_GUARD(cv->obj); + GUARD_OBJ(cv,GetVpValue(c,1)); + VpLeftRound(cv,VpGetRoundMode(),mx); return ToValue(cv); } } @@ -1495,16 +1444,15 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n) static VALUE BigDecimal_abs(VALUE self) { + ENTER(5); Real *c, *a; size_t mx; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); - c = VpCreateRbObject(mx, "0"); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpAsgn(c, a, 1); VpChangeSign(c, 1); - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1518,18 +1466,17 @@ BigDecimal_abs(VALUE self) static VALUE BigDecimal_sqrt(VALUE self, VALUE nFig) { + ENTER(5); Real *c, *a; size_t mx, n; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); n = GetPositiveInt(nFig) + VpDblFig() + 1; - if (mx <= n) mx = n; - c = VpCreateRbObject(mx, "0"); + if(mx <= n) mx = n; + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSqrt(c, a); - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1538,15 +1485,14 @@ BigDecimal_sqrt(VALUE self, VALUE nFig) static VALUE BigDecimal_fix(VALUE self) { + ENTER(5); Real *c, *a; size_t mx; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); - c = VpCreateRbObject(mx, "0"); - VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */ - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); + VpActiveRound(c,a,VP_ROUND_DOWN,0); /* 0: round off */ return ToValue(c); } @@ -1575,6 +1521,7 @@ BigDecimal_fix(VALUE self) static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self) { + ENTER(5); Real *c, *a; int iLoc = 0; VALUE vLoc; @@ -1599,16 +1546,14 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) } pl = VpSetPrecLimit(0); - a = GetVpValue(self, 1); - mx = a->Prec * (VpBaseFig() + 1); - c = VpCreateRbObject(mx, "0"); + GUARD_OBJ(a,GetVpValue(self,1)); + mx = a->Prec *(VpBaseFig() + 1); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSetPrecLimit(pl); - VpActiveRound(c, a, sw, iLoc); + VpActiveRound(c,a,sw,iLoc); if (argc == 0) { return BigDecimal_to_i(ToValue(c)); } - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1634,6 +1579,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self) static VALUE BigDecimal_truncate(int argc, VALUE *argv, VALUE self) { + ENTER(5); Real *c, *a; int iLoc; VALUE vLoc; @@ -1646,16 +1592,14 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self) iLoc = FIX2INT(vLoc); } - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); - c = VpCreateRbObject(mx, "0"); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSetPrecLimit(pl); VpActiveRound(c,a,VP_ROUND_DOWN,iLoc); /* 0: truncate */ if (argc == 0) { return BigDecimal_to_i(ToValue(c)); } - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1664,15 +1608,14 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self) static VALUE BigDecimal_frac(VALUE self) { + ENTER(5); Real *c, *a; size_t mx; - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); - c = VpCreateRbObject(mx, "0"); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpFrac(c, a); - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1698,6 +1641,7 @@ BigDecimal_frac(VALUE self) static VALUE BigDecimal_floor(int argc, VALUE *argv, VALUE self) { + ENTER(5); Real *c, *a; int iLoc; VALUE vLoc; @@ -1710,9 +1654,9 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self) iLoc = FIX2INT(vLoc); } - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); - c = VpCreateRbObject(mx, "0"); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSetPrecLimit(pl); VpActiveRound(c,a,VP_ROUND_FLOOR,iLoc); #ifdef BIGDECIMAL_DEBUG @@ -1721,8 +1665,6 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self) if (argc == 0) { return BigDecimal_to_i(ToValue(c)); } - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1748,6 +1690,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self) static VALUE BigDecimal_ceil(int argc, VALUE *argv, VALUE self) { + ENTER(5); Real *c, *a; int iLoc; VALUE vLoc; @@ -1760,16 +1703,14 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self) iLoc = FIX2INT(vLoc); } - a = GetVpValue(self, 1); + GUARD_OBJ(a,GetVpValue(self,1)); mx = a->Prec *(VpBaseFig() + 1); - c = VpCreateRbObject(mx, "0"); + GUARD_OBJ(c,VpCreateRbObject(mx, "0")); VpSetPrecLimit(pl); VpActiveRound(c,a,VP_ROUND_CEIL,iLoc); if (argc == 0) { return BigDecimal_to_i(ToValue(c)); } - RB_GC_GUARD(a->obj); - RB_GC_GUARD(c->obj); return ToValue(c); } @@ -1806,6 +1747,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self) static VALUE BigDecimal_to_s(int argc, VALUE *argv, VALUE self) { + ENTER(5); int fmt=0; /* 0:E format */ int fPlus=0; /* =0:default,=1: set ' ' before digits ,set '+' before digits. */ Real *vp; @@ -1815,53 +1757,45 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self) size_t nc, mc = 0; VALUE f; - vp = GetVpValue(self, 1); + GUARD_OBJ(vp,GetVpValue(self,1)); - if (rb_scan_args(argc, argv, "01", &f) == 1) { - if (TYPE(f) == T_STRING) { - SafeStringValue(f); - psz = RSTRING_PTR(f); - if (*psz == ' ') { - fPlus = 1; psz++; - } - else if (*psz == '+') { - fPlus = 2; psz++; - } - while ((ch = *psz++) != 0) { - if (ISSPACE(ch)) continue; - if (!ISDIGIT(ch)) { - if (ch == 'F' || ch == 'f') { - fmt = 1; /* F format */ - } - break; - } - mc = mc * 10 + ch - '0'; - } - } + if(rb_scan_args(argc,argv,"01",&f)==1) { + if(TYPE(f)==T_STRING) { + SafeStringValue(f); + psz = RSTRING_PTR(f); + if(*psz==' ') { + fPlus = 1; psz++; + } else if(*psz=='+') { + fPlus = 2; psz++; + } + while((ch=*psz++)!=0) { + if(ISSPACE(ch)) continue; + if(!ISDIGIT(ch)) { + if(ch=='F' || ch=='f') fmt = 1; /* F format */ + break; + } + mc = mc * 10 + ch - '0'; + } + } else { - mc = (size_t)GetPositiveInt(f); - } - } - if (fmt) { - nc = VpNumOfChars(vp,"F"); - } - else { - nc = VpNumOfChars(vp,"E"); + mc = (size_t)GetPositiveInt(f); + } } - if (mc > 0) { - nc += (nc + mc - 1) / mc + 1; + if(fmt) { + nc = VpNumOfChars(vp,"F"); + } else { + nc = VpNumOfChars(vp,"E"); } + if(mc>0) nc += (nc + mc - 1) / mc + 1; str = rb_str_new(0, nc); psz = RSTRING_PTR(str); - if (fmt) { - VpToFString(vp, psz, mc, fPlus); - } - else { - VpToString (vp, psz, mc, fPlus); + if(fmt) { + VpToFString(vp, psz, mc, fPlus); + } else { + VpToString (vp, psz, mc, fPlus); } - RB_GC_GUARD(vp->obj); rb_str_resize(str, strlen(psz)); return str; } @@ -1893,29 +1827,27 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self) static VALUE BigDecimal_split(VALUE self) { + ENTER(5); Real *vp; VALUE obj,str; ssize_t e, s; char *psz1; - vp = GetVpValue(self, 1); - str = rb_str_new(0, VpNumOfChars(vp, "E")); + GUARD_OBJ(vp,GetVpValue(self,1)); + str = rb_str_new(0, VpNumOfChars(vp,"E")); psz1 = RSTRING_PTR(str); - VpSzMantissa(vp, psz1); + VpSzMantissa(vp,psz1); s = 1; + if(psz1[0]=='-') { + size_t len = strlen(psz1+1); - if (psz1[0] == '-') { - size_t len = strlen(psz1 + 1); - - memmove(psz1, psz1 + 1, len); + memmove(psz1, psz1+1, len); psz1[len] = '\0'; - s = -1; + s = -1; } - if (psz1[0] == 'N') s = 0; /* NaN */ + if(psz1[0]=='N') s=0; /* NaN */ e = VpExponent10(vp); - RB_GC_GUARD(vp->obj); - - obj = rb_ary_new2(4); + obj = rb_ary_new2(4); rb_ary_push(obj, INT2FIX(s)); rb_ary_push(obj, str); rb_str_resize(str, strlen(psz1)); @@ -1949,23 +1881,23 @@ BigDecimal_exponent(VALUE self) static VALUE BigDecimal_inspect(VALUE self) { + ENTER(5); Real *vp; volatile VALUE obj; size_t nc; char *psz, *tmp; - vp = GetVpValue(self, 1); - nc = VpNumOfChars(vp, "E"); - nc += (nc + 9) / 10; + GUARD_OBJ(vp,GetVpValue(self,1)); + nc = VpNumOfChars(vp,"E"); + nc +=(nc + 9) / 10; obj = rb_str_new(0, nc+256); psz = RSTRING_PTR(obj); - sprintf(psz, "#", VpPrec(vp)*VpBaseFig(), VpMaxPrec(vp)*VpBaseFig()); - RB_GC_GUARD(vp->obj); rb_str_resize(obj, strlen(psz)); return obj; } @@ -2091,6 +2023,7 @@ rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n) static VALUE BigDecimal_power(int argc, VALUE*argv, VALUE self) { + ENTER(5); VALUE vexp, prec; Real* exp = NULL; Real *x, *y; @@ -2100,11 +2033,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self) rb_scan_args(argc, argv, "11", &vexp, &prec); - x = GetVpValue(self, 1); + GUARD_OBJ(x, GetVpValue(self, 1)); n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec); if (VpIsNaN(x)) { - RB_GC_GUARD(x->obj); y = VpCreateRbObject(n, "0#"); RB_GC_GUARD(y->obj); VpSetNaN(y); @@ -2161,11 +2093,10 @@ retry: } if (VpIsZero(x)) { - RB_GC_GUARD(x->obj); if (is_negative(vexp)) { y = VpCreateRbObject(n, "#0"); + RB_GC_GUARD(y->obj); if (VpGetSign(x) < 0) { - RB_GC_GUARD(x->obj); if (is_integer(vexp)) { if (is_even(vexp)) { /* (-0) ** (-even_integer) -> Infinity */ @@ -2185,7 +2116,6 @@ retry: /* (+0) ** (-num) -> Infinity */ VpSetPosInf(y); } - RB_GC_GUARD(y->obj); return ToValue(y); } else if (is_zero(vexp)) { @@ -2204,10 +2134,8 @@ retry: } if (VpIsInf(x)) { - RB_GC_GUARD(x->obj); if (is_negative(vexp)) { if (VpGetSign(x) < 0) { - RB_GC_GUARD(x->obj); if (is_integer(vexp)) { if (is_even(vexp)) { /* (-Infinity) ** (-even_integer) -> +0 */ @@ -2230,7 +2158,6 @@ retry: else { y = VpCreateRbObject(n, "0#"); if (VpGetSign(x) < 0) { - RB_GC_GUARD(x->obj); if (is_integer(vexp)) { if (is_even(vexp)) { VpSetPosInf(y); @@ -2248,7 +2175,6 @@ retry: else { VpSetPosInf(y); } - RB_GC_GUARD(y->obj); return ToValue(y); } } @@ -2259,11 +2185,9 @@ retry: else if (TYPE(vexp) == T_BIGNUM) { VALUE abs_value = BigDecimal_abs(self); if (is_one(abs_value)) { - RB_GC_GUARD(abs_value); return ToValue(VpCreateRbObject(n, "1")); } else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) { - RB_GC_GUARD(abs_value); if (is_negative(vexp)) { y = VpCreateRbObject(n, "0#"); if (is_even(vexp)) { @@ -2272,7 +2196,6 @@ retry: else { VpSetInf(y, -VpGetSign(x)); } - RB_GC_GUARD(y->obj); return ToValue(y); } else if (VpGetSign(x) < 0 && is_even(vexp)) { @@ -2291,7 +2214,6 @@ retry: else { VpSetInf(y, -VpGetSign(x)); } - RB_GC_GUARD(y->obj); return ToValue(y); } else if (VpGetSign(x) < 0 && is_even(vexp)) { @@ -2310,14 +2232,12 @@ retry: if (VpIsDef(x)) { mp = x->Prec * (VpBaseFig() + 1); - y = VpCreateRbObject(mp * (ma + 1), "0"); + GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0")); } else { - y = VpCreateRbObject(1, "0"); + GUARD_OBJ(y, VpCreateRbObject(1, "0")); } VpPower(y, x, int_exp); - RB_GC_GUARD(x->obj); - RB_GC_GUARD(y->obj); return ToValue(y); } -- cgit v1.2.3