зеркало из https://github.com/github/ruby.git
[ruby/bigdecimal] Refactor object allocation
https://github.com/ruby/bigdecimal/commit/271cebe567
This commit is contained in:
Родитель
4569e46550
Коммит
a8014dae47
|
@ -266,7 +266,7 @@ again:
|
||||||
if (prec > (long)DBLE_FIG) goto SomeOneMayDoIt;
|
if (prec > (long)DBLE_FIG) goto SomeOneMayDoIt;
|
||||||
d = RFLOAT_VALUE(v);
|
d = RFLOAT_VALUE(v);
|
||||||
if (!isfinite(d)) {
|
if (!isfinite(d)) {
|
||||||
pv = VpCreateRbObject(1, NULL);
|
pv = VpCreateRbObject(1, NULL, true);
|
||||||
VpDtoV(pv, d);
|
VpDtoV(pv, d);
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
|
@ -275,9 +275,9 @@ again:
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
if (1/d < 0.0) {
|
if (1/d < 0.0) {
|
||||||
return VpCreateRbObject(prec, "-0");
|
return VpCreateRbObject(prec, "-0", true);
|
||||||
}
|
}
|
||||||
return VpCreateRbObject(prec, "0");
|
return VpCreateRbObject(prec, "0", true);
|
||||||
|
|
||||||
case T_RATIONAL:
|
case T_RATIONAL:
|
||||||
if (prec < 0) goto unable_to_coerce_without_prec;
|
if (prec < 0) goto unable_to_coerce_without_prec;
|
||||||
|
@ -306,20 +306,20 @@ again:
|
||||||
|
|
||||||
case T_FIXNUM:
|
case T_FIXNUM:
|
||||||
sprintf(szD, "%ld", FIX2LONG(v));
|
sprintf(szD, "%ld", FIX2LONG(v));
|
||||||
return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
|
return VpCreateRbObject(VpBaseFig() * 2 + 1, szD, true);
|
||||||
|
|
||||||
#ifdef ENABLE_NUMERIC_STRING
|
#ifdef ENABLE_NUMERIC_STRING
|
||||||
case T_STRING:
|
case T_STRING:
|
||||||
StringValueCStr(v);
|
StringValueCStr(v);
|
||||||
return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
|
return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
|
||||||
RSTRING_PTR(v));
|
RSTRING_PTR(v), true);
|
||||||
#endif /* ENABLE_NUMERIC_STRING */
|
#endif /* ENABLE_NUMERIC_STRING */
|
||||||
|
|
||||||
case T_BIGNUM:
|
case T_BIGNUM:
|
||||||
bg = rb_big2str(v, 10);
|
bg = rb_big2str(v, 10);
|
||||||
PUSH(bg);
|
PUSH(bg);
|
||||||
return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
|
return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
|
||||||
RSTRING_PTR(bg));
|
RSTRING_PTR(bg), true);
|
||||||
default:
|
default:
|
||||||
goto SomeOneMayDoIt;
|
goto SomeOneMayDoIt;
|
||||||
}
|
}
|
||||||
|
@ -559,7 +559,7 @@ BigDecimal_load(VALUE self, VALUE str)
|
||||||
m = m*10 + (unsigned long)(ch-'0');
|
m = m*10 + (unsigned long)(ch-'0');
|
||||||
}
|
}
|
||||||
if (m > VpBaseFig()) m -= VpBaseFig();
|
if (m > VpBaseFig()) m -= VpBaseFig();
|
||||||
GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self));
|
GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true));
|
||||||
m /= VpBaseFig();
|
m /= VpBaseFig();
|
||||||
if (m && pv->MaxPrec > m) {
|
if (m && pv->MaxPrec > m) {
|
||||||
pv->MaxPrec = m+1;
|
pv->MaxPrec = m+1;
|
||||||
|
@ -774,21 +774,39 @@ GetPrecisionInt(VALUE v)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
BigDecimal_wrap_struct(VALUE obj, Real *vp)
|
||||||
|
{
|
||||||
|
assert(is_kind_of_BigDecimal(obj));
|
||||||
|
assert(vp != NULL);
|
||||||
|
|
||||||
|
if (vp->obj == obj && RTYPEDDATA_DATA(obj) == vp)
|
||||||
|
return obj;
|
||||||
|
|
||||||
|
assert(RTYPEDDATA_DATA(obj) == NULL);
|
||||||
|
assert(vp->obj == 0);
|
||||||
|
|
||||||
|
RTYPEDDATA_DATA(obj) = vp;
|
||||||
|
vp->obj = obj;
|
||||||
|
RB_OBJ_FREEZE(obj);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
VP_EXPORT Real *
|
VP_EXPORT Real *
|
||||||
VpNewRbClass(size_t mx, const char *str, VALUE klass)
|
VpNewRbClass(size_t mx, const char *str, VALUE klass, bool strict_p, bool raise_exception)
|
||||||
{
|
{
|
||||||
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
||||||
Real *pv = VpAlloc(mx, str, 1, 1);
|
Real *pv = VpAlloc(mx, str, strict_p, raise_exception);
|
||||||
RTYPEDDATA_DATA(obj) = pv;
|
if (!pv)
|
||||||
pv->obj = obj;
|
return NULL;
|
||||||
RB_OBJ_FREEZE(obj);
|
BigDecimal_wrap_struct(obj, pv);
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
|
|
||||||
VP_EXPORT Real *
|
VP_EXPORT Real *
|
||||||
VpCreateRbObject(size_t mx, const char *str)
|
VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
|
||||||
{
|
{
|
||||||
return VpNewRbClass(mx, str, rb_cBigDecimal);
|
return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
|
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
|
||||||
|
@ -1076,11 +1094,11 @@ BigDecimal_add(VALUE self, VALUE r)
|
||||||
|
|
||||||
mx = GetAddSubPrec(a, b);
|
mx = GetAddSubPrec(a, b);
|
||||||
if (mx == (size_t)-1L) {
|
if (mx == (size_t)-1L) {
|
||||||
GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
|
||||||
VpAddSub(c, a, b, 1);
|
VpAddSub(c, a, b, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true));
|
||||||
if(!mx) {
|
if(!mx) {
|
||||||
VpSetInf(c, VpGetSign(a));
|
VpSetInf(c, VpGetSign(a));
|
||||||
}
|
}
|
||||||
|
@ -1134,11 +1152,11 @@ BigDecimal_sub(VALUE self, VALUE r)
|
||||||
|
|
||||||
mx = GetAddSubPrec(a,b);
|
mx = GetAddSubPrec(a,b);
|
||||||
if (mx == (size_t)-1L) {
|
if (mx == (size_t)-1L) {
|
||||||
GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
|
||||||
VpAddSub(c, a, b, -1);
|
VpAddSub(c, a, b, -1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
|
GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
|
||||||
if (!mx) {
|
if (!mx) {
|
||||||
VpSetInf(c,VpGetSign(a));
|
VpSetInf(c,VpGetSign(a));
|
||||||
}
|
}
|
||||||
|
@ -1351,7 +1369,7 @@ BigDecimal_neg(VALUE self)
|
||||||
ENTER(5);
|
ENTER(5);
|
||||||
Real *c, *a;
|
Real *c, *a;
|
||||||
GUARD_OBJ(a, GetVpValue(self, 1));
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
||||||
GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
|
GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
|
||||||
VpAsgn(c, a, -1);
|
VpAsgn(c, a, -1);
|
||||||
return VpCheckGetValue(c);
|
return VpCheckGetValue(c);
|
||||||
}
|
}
|
||||||
|
@ -1393,7 +1411,7 @@ BigDecimal_mult(VALUE self, VALUE r)
|
||||||
SAVE(b);
|
SAVE(b);
|
||||||
|
|
||||||
mx = a->Prec + b->Prec;
|
mx = a->Prec + b->Prec;
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
|
||||||
VpMult(c, a, b);
|
VpMult(c, a, b);
|
||||||
return VpCheckGetValue(c);
|
return VpCheckGetValue(c);
|
||||||
}
|
}
|
||||||
|
@ -1426,8 +1444,8 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
|
||||||
mx++; /* NOTE: An additional digit is needed for the compatibility to
|
mx++; /* NOTE: An additional digit is needed for the compatibility to
|
||||||
the version 1.2.1 and the former. */
|
the version 1.2.1 and the former. */
|
||||||
mx = (mx + 1) * VpBaseFig();
|
mx = (mx + 1) * VpBaseFig();
|
||||||
GUARD_OBJ((*c), VpCreateRbObject(mx, "#0"));
|
GUARD_OBJ((*c), VpCreateRbObject(mx, "#0", true));
|
||||||
GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
|
GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true));
|
||||||
VpDivd(*c, *res, a, b);
|
VpDivd(*c, *res, a, b);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
@ -1492,22 +1510,22 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
||||||
rb_raise(rb_eZeroDivError, "divided by 0");
|
rb_raise(rb_eZeroDivError, "divided by 0");
|
||||||
}
|
}
|
||||||
if (VpIsInf(a)) {
|
if (VpIsInf(a)) {
|
||||||
GUARD_OBJ(d, VpCreateRbObject(1, "0"));
|
GUARD_OBJ(d, VpCreateRbObject(1, "0", true));
|
||||||
VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1));
|
VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1));
|
||||||
GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
|
GUARD_OBJ(c, VpCreateRbObject(1, "NaN", true));
|
||||||
*div = d;
|
*div = d;
|
||||||
*mod = c;
|
*mod = c;
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
if (VpIsInf(b)) {
|
if (VpIsInf(b)) {
|
||||||
GUARD_OBJ(d, VpCreateRbObject(1, "0"));
|
GUARD_OBJ(d, VpCreateRbObject(1, "0", true));
|
||||||
*div = d;
|
*div = d;
|
||||||
*mod = a;
|
*mod = a;
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
if (VpIsZero(a)) {
|
if (VpIsZero(a)) {
|
||||||
GUARD_OBJ(c, VpCreateRbObject(1, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(1, "0", true));
|
||||||
GUARD_OBJ(d, VpCreateRbObject(1, "0"));
|
GUARD_OBJ(d, VpCreateRbObject(1, "0", true));
|
||||||
*div = d;
|
*div = d;
|
||||||
*mod = c;
|
*mod = c;
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
|
@ -1516,17 +1534,17 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
||||||
mx = a->Prec + vabs(a->exponent);
|
mx = a->Prec + vabs(a->exponent);
|
||||||
if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
|
if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
|
||||||
mx = (mx + 1) * VpBaseFig();
|
mx = (mx + 1) * VpBaseFig();
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
|
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true));
|
||||||
VpDivd(c, res, a, b);
|
VpDivd(c, res, a, b);
|
||||||
mx = c->Prec * (VpBaseFig() + 1);
|
mx = c->Prec * (VpBaseFig() + 1);
|
||||||
GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
||||||
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
|
||||||
VpMult(res, d, b);
|
VpMult(res, d, b);
|
||||||
VpAddSub(c, a, res, -1);
|
VpAddSub(c, a, res, -1);
|
||||||
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
|
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
|
||||||
VpAddSub(res, d, VpOne(), -1);
|
VpAddSub(res, d, VpOne(), -1);
|
||||||
GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0"));
|
GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0", true));
|
||||||
VpAddSub(d, c, b, 1);
|
VpAddSub(d, c, b, 1);
|
||||||
*div = res;
|
*div = res;
|
||||||
*mod = d;
|
*mod = d;
|
||||||
|
@ -1537,8 +1555,8 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
|
|
||||||
NaN:
|
NaN:
|
||||||
GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
|
GUARD_OBJ(c, VpCreateRbObject(1, "NaN", true));
|
||||||
GUARD_OBJ(d, VpCreateRbObject(1, "NaN"));
|
GUARD_OBJ(d, VpCreateRbObject(1, "NaN", true));
|
||||||
*div = d;
|
*div = d;
|
||||||
*mod = c;
|
*mod = c;
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
|
@ -1588,17 +1606,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
||||||
SAVE(b);
|
SAVE(b);
|
||||||
|
|
||||||
mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
|
mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
||||||
GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
||||||
GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
||||||
|
|
||||||
VpDivd(c, res, a, b);
|
VpDivd(c, res, a, b);
|
||||||
|
|
||||||
mx = c->Prec *(VpBaseFig() + 1);
|
mx = c->Prec *(VpBaseFig() + 1);
|
||||||
|
|
||||||
GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
||||||
GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
|
||||||
|
|
||||||
VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
|
||||||
|
|
||||||
|
@ -1692,12 +1710,12 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
||||||
size_t mx = ix + VpBaseFig()*2;
|
size_t mx = ix + VpBaseFig()*2;
|
||||||
size_t pl = VpSetPrecLimit(0);
|
size_t pl = VpSetPrecLimit(0);
|
||||||
|
|
||||||
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
|
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true));
|
||||||
GUARD_OBJ(av, GetVpValue(self, 1));
|
GUARD_OBJ(av, GetVpValue(self, 1));
|
||||||
GUARD_OBJ(bv, GetVpValue(b, 1));
|
GUARD_OBJ(bv, GetVpValue(b, 1));
|
||||||
mx = av->Prec + bv->Prec + 2;
|
mx = av->Prec + bv->Prec + 2;
|
||||||
if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
|
if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
|
||||||
GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
|
GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
|
||||||
VpDivd(cv, res, av, bv);
|
VpDivd(cv, res, av, bv);
|
||||||
VpSetPrecLimit(pl);
|
VpSetPrecLimit(pl);
|
||||||
VpLeftRound(cv, VpGetRoundMode(), ix);
|
VpLeftRound(cv, VpGetRoundMode(), ix);
|
||||||
|
@ -1830,7 +1848,7 @@ BigDecimal_abs(VALUE self)
|
||||||
|
|
||||||
GUARD_OBJ(a, GetVpValue(self, 1));
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
||||||
mx = a->Prec *(VpBaseFig() + 1);
|
mx = a->Prec *(VpBaseFig() + 1);
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
VpAsgn(c, a, 1);
|
VpAsgn(c, a, 1);
|
||||||
VpChangeSign(c, 1);
|
VpChangeSign(c, 1);
|
||||||
return VpCheckGetValue(c);
|
return VpCheckGetValue(c);
|
||||||
|
@ -1855,7 +1873,7 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
|
||||||
|
|
||||||
n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
|
n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
|
||||||
if (mx <= n) mx = n;
|
if (mx <= n) mx = n;
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
VpSqrt(c, a);
|
VpSqrt(c, a);
|
||||||
return VpCheckGetValue(c);
|
return VpCheckGetValue(c);
|
||||||
}
|
}
|
||||||
|
@ -1871,7 +1889,7 @@ BigDecimal_fix(VALUE self)
|
||||||
|
|
||||||
GUARD_OBJ(a, GetVpValue(self, 1));
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
||||||
mx = a->Prec *(VpBaseFig() + 1);
|
mx = a->Prec *(VpBaseFig() + 1);
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
|
VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
|
||||||
return VpCheckGetValue(c);
|
return VpCheckGetValue(c);
|
||||||
}
|
}
|
||||||
|
@ -1944,7 +1962,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
|
||||||
pl = VpSetPrecLimit(0);
|
pl = VpSetPrecLimit(0);
|
||||||
GUARD_OBJ(a, GetVpValue(self, 1));
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
||||||
mx = a->Prec * (VpBaseFig() + 1);
|
mx = a->Prec * (VpBaseFig() + 1);
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
VpSetPrecLimit(pl);
|
VpSetPrecLimit(pl);
|
||||||
VpActiveRound(c, a, sw, iLoc);
|
VpActiveRound(c, a, sw, iLoc);
|
||||||
if (round_to_int) {
|
if (round_to_int) {
|
||||||
|
@ -1990,7 +2008,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
|
||||||
|
|
||||||
GUARD_OBJ(a, GetVpValue(self, 1));
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
||||||
mx = a->Prec * (VpBaseFig() + 1);
|
mx = a->Prec * (VpBaseFig() + 1);
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
VpSetPrecLimit(pl);
|
VpSetPrecLimit(pl);
|
||||||
VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
|
VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
|
@ -2010,7 +2028,7 @@ BigDecimal_frac(VALUE self)
|
||||||
|
|
||||||
GUARD_OBJ(a, GetVpValue(self, 1));
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
||||||
mx = a->Prec * (VpBaseFig() + 1);
|
mx = a->Prec * (VpBaseFig() + 1);
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
VpFrac(c, a);
|
VpFrac(c, a);
|
||||||
return VpCheckGetValue(c);
|
return VpCheckGetValue(c);
|
||||||
}
|
}
|
||||||
|
@ -2050,7 +2068,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
|
||||||
|
|
||||||
GUARD_OBJ(a, GetVpValue(self, 1));
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
||||||
mx = a->Prec * (VpBaseFig() + 1);
|
mx = a->Prec * (VpBaseFig() + 1);
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
VpSetPrecLimit(pl);
|
VpSetPrecLimit(pl);
|
||||||
VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
|
VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
|
||||||
#ifdef BIGDECIMAL_DEBUG
|
#ifdef BIGDECIMAL_DEBUG
|
||||||
|
@ -2096,7 +2114,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
||||||
|
|
||||||
GUARD_OBJ(a, GetVpValue(self, 1));
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
||||||
mx = a->Prec * (VpBaseFig() + 1);
|
mx = a->Prec * (VpBaseFig() + 1);
|
||||||
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
||||||
VpSetPrecLimit(pl);
|
VpSetPrecLimit(pl);
|
||||||
VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
|
VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
|
@ -2404,7 +2422,7 @@ rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n)
|
||||||
volatile VALUE obj = exp->obj;
|
volatile VALUE obj = exp->obj;
|
||||||
|
|
||||||
if (VpIsZero(exp)) {
|
if (VpIsZero(exp)) {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "1"));
|
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
||||||
}
|
}
|
||||||
|
|
||||||
log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
|
log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
|
||||||
|
@ -2442,7 +2460,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
||||||
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
||||||
|
|
||||||
if (VpIsNaN(x)) {
|
if (VpIsNaN(x)) {
|
||||||
y = VpCreateRbObject(n, "0");
|
y = VpCreateRbObject(n, "0", true);
|
||||||
RB_GC_GUARD(y->obj);
|
RB_GC_GUARD(y->obj);
|
||||||
VpSetNaN(y);
|
VpSetNaN(y);
|
||||||
return VpCheckGetValue(y);
|
return VpCheckGetValue(y);
|
||||||
|
@ -2514,7 +2532,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
||||||
|
|
||||||
if (VpIsZero(x)) {
|
if (VpIsZero(x)) {
|
||||||
if (is_negative(vexp)) {
|
if (is_negative(vexp)) {
|
||||||
y = VpCreateRbObject(n, "#0");
|
y = VpCreateRbObject(n, "#0", true);
|
||||||
RB_GC_GUARD(y->obj);
|
RB_GC_GUARD(y->obj);
|
||||||
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
||||||
if (is_integer(vexp)) {
|
if (is_integer(vexp)) {
|
||||||
|
@ -2539,15 +2557,15 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
||||||
return VpCheckGetValue(y);
|
return VpCheckGetValue(y);
|
||||||
}
|
}
|
||||||
else if (is_zero(vexp)) {
|
else if (is_zero(vexp)) {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "1"));
|
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_zero(vexp)) {
|
if (is_zero(vexp)) {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "1"));
|
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
||||||
}
|
}
|
||||||
else if (is_one(vexp)) {
|
else if (is_one(vexp)) {
|
||||||
return self;
|
return self;
|
||||||
|
@ -2559,24 +2577,24 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
||||||
if (is_integer(vexp)) {
|
if (is_integer(vexp)) {
|
||||||
if (is_even(vexp)) {
|
if (is_even(vexp)) {
|
||||||
/* (-Infinity) ** (-even_integer) -> +0 */
|
/* (-Infinity) ** (-even_integer) -> +0 */
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* (-Infinity) ** (-odd_integer) -> -0 */
|
/* (-Infinity) ** (-odd_integer) -> -0 */
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "-0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* (-Infinity) ** (-non_integer) -> -0 */
|
/* (-Infinity) ** (-non_integer) -> -0 */
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "-0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
y = VpCreateRbObject(n, "0");
|
y = VpCreateRbObject(n, "0", true);
|
||||||
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
||||||
if (is_integer(vexp)) {
|
if (is_integer(vexp)) {
|
||||||
if (is_even(vexp)) {
|
if (is_even(vexp)) {
|
||||||
|
@ -2605,11 +2623,11 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
||||||
else if (RB_TYPE_P(vexp, T_BIGNUM)) {
|
else if (RB_TYPE_P(vexp, T_BIGNUM)) {
|
||||||
VALUE abs_value = BigDecimal_abs(self);
|
VALUE abs_value = BigDecimal_abs(self);
|
||||||
if (is_one(abs_value)) {
|
if (is_one(abs_value)) {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "1"));
|
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
||||||
}
|
}
|
||||||
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
||||||
if (is_negative(vexp)) {
|
if (is_negative(vexp)) {
|
||||||
y = VpCreateRbObject(n, "0");
|
y = VpCreateRbObject(n, "0", true);
|
||||||
if (is_even(vexp)) {
|
if (is_even(vexp)) {
|
||||||
VpSetInf(y, VpGetSign(x));
|
VpSetInf(y, VpGetSign(x));
|
||||||
}
|
}
|
||||||
|
@ -2619,15 +2637,15 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
||||||
return VpCheckGetValue(y);
|
return VpCheckGetValue(y);
|
||||||
}
|
}
|
||||||
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "-0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (is_positive(vexp)) {
|
if (is_positive(vexp)) {
|
||||||
y = VpCreateRbObject(n, "0");
|
y = VpCreateRbObject(n, "0", true);
|
||||||
if (is_even(vexp)) {
|
if (is_even(vexp)) {
|
||||||
VpSetInf(y, VpGetSign(x));
|
VpSetInf(y, VpGetSign(x));
|
||||||
}
|
}
|
||||||
|
@ -2637,10 +2655,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
||||||
return VpCheckGetValue(y);
|
return VpCheckGetValue(y);
|
||||||
}
|
}
|
||||||
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "-0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return VpCheckGetValue(VpCreateRbObject(n, "0"));
|
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2652,10 +2670,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
||||||
|
|
||||||
if (VpIsDef(x)) {
|
if (VpIsDef(x)) {
|
||||||
mp = x->Prec * (VpBaseFig() + 1);
|
mp = x->Prec * (VpBaseFig() + 1);
|
||||||
GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0"));
|
GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GUARD_OBJ(y, VpCreateRbObject(1, "0"));
|
GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
|
||||||
}
|
}
|
||||||
VpPower(y, x, int_exp);
|
VpPower(y, x, int_exp);
|
||||||
if (!NIL_P(prec) && VpIsDef(y)) {
|
if (!NIL_P(prec) && VpIsDef(y)) {
|
||||||
|
@ -2747,7 +2765,7 @@ rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
||||||
{
|
{
|
||||||
double d = RFLOAT_VALUE(val);
|
double d = RFLOAT_VALUE(val);
|
||||||
if (!isfinite(d)) {
|
if (!isfinite(d)) {
|
||||||
Real *vp = VpCreateRbObject(1, NULL); /* vp->obj is allocated */
|
Real *vp = VpCreateRbObject(1, NULL, true); /* vp->obj is allocated */
|
||||||
VpDtoV(vp, d);
|
VpDtoV(vp, d);
|
||||||
return check_exception(vp->obj);
|
return check_exception(vp->obj);
|
||||||
}
|
}
|
||||||
|
@ -2790,13 +2808,9 @@ rb_str_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
||||||
digs = 0;
|
digs = 0;
|
||||||
|
|
||||||
const char *c_str = StringValueCStr(val);
|
const char *c_str = StringValueCStr(val);
|
||||||
VALUE obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
Real *vp = VpCreateRbObject(digs, c_str, raise_exception);
|
||||||
Real *vp = VpAlloc(digs, c_str, 1, raise_exception);
|
|
||||||
if (!vp)
|
if (!vp)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
RTYPEDDATA_DATA(obj) = vp;
|
|
||||||
vp->obj = obj;
|
|
||||||
RB_OBJ_FREEZE(obj);
|
|
||||||
return VpCheckGetValue(vp);
|
return VpCheckGetValue(vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2825,9 +2839,7 @@ rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
||||||
|
|
||||||
VALUE copy = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
VALUE copy = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
||||||
vp = VpCopy(NULL, vp);
|
vp = VpCopy(NULL, vp);
|
||||||
RTYPEDDATA_DATA(copy) = vp;
|
BigDecimal_wrap_struct(copy, vp);
|
||||||
vp->obj = copy;
|
|
||||||
RB_OBJ_FREEZE(vp->obj);
|
|
||||||
return VpCheckGetValue(vp);
|
return VpCheckGetValue(vp);
|
||||||
}
|
}
|
||||||
else if (RB_INTEGER_TYPE_P(val)) {
|
else if (RB_INTEGER_TYPE_P(val)) {
|
||||||
|
@ -2931,17 +2943,12 @@ f_BigDecimal(int argc, VALUE *argv, VALUE self)
|
||||||
static VALUE
|
static VALUE
|
||||||
BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
|
BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
|
||||||
{
|
{
|
||||||
ENTER(1);
|
|
||||||
|
|
||||||
char const *c_str = StringValueCStr(str);
|
char const *c_str = StringValueCStr(str);
|
||||||
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
Real *vp = VpNewRbClass(0, c_str, klass, false, true);
|
||||||
|
if (!vp)
|
||||||
Real *pv;
|
return Qnil;
|
||||||
GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1));
|
else
|
||||||
RTYPEDDATA_DATA(obj) = pv;
|
return VpCheckGetValue(vp);
|
||||||
pv->obj = obj;
|
|
||||||
RB_OBJ_FREEZE(pv->obj);
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call-seq:
|
/* call-seq:
|
||||||
|
@ -3142,7 +3149,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Real* vy;
|
Real* vy;
|
||||||
vy = VpCreateRbObject(prec, "#0");
|
vy = VpCreateRbObject(prec, "#0", true);
|
||||||
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
||||||
RB_GC_GUARD(vy->obj);
|
RB_GC_GUARD(vy->obj);
|
||||||
return VpCheckGetValue(vy);
|
return VpCheckGetValue(vy);
|
||||||
|
@ -3150,7 +3157,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
||||||
}
|
}
|
||||||
else if (nan) {
|
else if (nan) {
|
||||||
Real* vy;
|
Real* vy;
|
||||||
vy = VpCreateRbObject(prec, "#0");
|
vy = VpCreateRbObject(prec, "#0", true);
|
||||||
VpSetNaN(vy);
|
VpSetNaN(vy);
|
||||||
RB_GC_GUARD(vy->obj);
|
RB_GC_GUARD(vy->obj);
|
||||||
return VpCheckGetValue(vy);
|
return VpCheckGetValue(vy);
|
||||||
|
@ -3170,7 +3177,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
||||||
VpSetSign(vx, 1);
|
VpSetSign(vx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
one = VpCheckGetValue(VpCreateRbObject(1, "1"));
|
one = VpCheckGetValue(VpCreateRbObject(1, "1", true));
|
||||||
y = one;
|
y = one;
|
||||||
d = y;
|
d = y;
|
||||||
i = 1;
|
i = 1;
|
||||||
|
@ -3298,14 +3305,14 @@ get_vp_value:
|
||||||
}
|
}
|
||||||
if (infinite && !negative) {
|
if (infinite && !negative) {
|
||||||
Real* vy;
|
Real* vy;
|
||||||
vy = VpCreateRbObject(prec, "#0");
|
vy = VpCreateRbObject(prec, "#0", true);
|
||||||
RB_GC_GUARD(vy->obj);
|
RB_GC_GUARD(vy->obj);
|
||||||
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
||||||
return VpCheckGetValue(vy);
|
return VpCheckGetValue(vy);
|
||||||
}
|
}
|
||||||
else if (nan) {
|
else if (nan) {
|
||||||
Real* vy;
|
Real* vy;
|
||||||
vy = VpCreateRbObject(prec, "#0");
|
vy = VpCreateRbObject(prec, "#0", true);
|
||||||
RB_GC_GUARD(vy->obj);
|
RB_GC_GUARD(vy->obj);
|
||||||
VpSetNaN(vy);
|
VpSetNaN(vy);
|
||||||
return VpCheckGetValue(vy);
|
return VpCheckGetValue(vy);
|
||||||
|
@ -3319,8 +3326,8 @@ get_vp_value:
|
||||||
}
|
}
|
||||||
x = VpCheckGetValue(vx);
|
x = VpCheckGetValue(vx);
|
||||||
|
|
||||||
RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1"));
|
RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1", true));
|
||||||
RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2"));
|
RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true));
|
||||||
|
|
||||||
n = prec + rmpd_double_figures();
|
n = prec + rmpd_double_figures();
|
||||||
RB_GC_GUARD(vn) = SSIZET2NUM(n);
|
RB_GC_GUARD(vn) = SSIZET2NUM(n);
|
||||||
|
@ -3328,7 +3335,7 @@ get_vp_value:
|
||||||
if (expo < 0 || expo >= 3) {
|
if (expo < 0 || expo >= 3) {
|
||||||
char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
|
char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
|
||||||
snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
|
snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
|
||||||
x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf)), vn);
|
x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expo = 0;
|
expo = 0;
|
||||||
|
|
|
@ -285,10 +285,9 @@ typedef struct {
|
||||||
* ------------------
|
* ------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VP_EXPORT Real *
|
VP_EXPORT Real *VpNewRbClass(size_t mx, char const *str, VALUE klass, bool strict_p, bool raise_exception);
|
||||||
VpNewRbClass(size_t mx, char const *str, VALUE klass);
|
|
||||||
|
|
||||||
VP_EXPORT Real *VpCreateRbObject(size_t mx,const char *str);
|
VP_EXPORT Real *VpCreateRbObject(size_t mx, const char *str, bool raise_exception);
|
||||||
|
|
||||||
static inline BDIGIT
|
static inline BDIGIT
|
||||||
rmpd_base_value(void) { return RMPD_BASE; }
|
rmpd_base_value(void) { return RMPD_BASE; }
|
||||||
|
|
Загрузка…
Ссылка в новой задаче