From 7b2cfce543b876744544c8b43abdee3c72cab910 Mon Sep 17 00:00:00 2001 From: Kenta Murata Date: Fri, 22 Jan 2021 13:49:46 +0900 Subject: [ruby/bigdecimal] Let BigDecimal_DoDivmod use the same precision calculation as BigDecimal_divide https://github.com/ruby/bigdecimal/commit/11cb2c8840 --- ext/bigdecimal/bigdecimal.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'ext/bigdecimal') diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 71499a7a19..0558a17fd9 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -1613,26 +1613,33 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) return Qtrue; } - mx = a->Prec + vabs(a->exponent); - if (mxPrec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent); - mx = (mx + 1) * VpBaseFig(); - GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); - GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true)); + mx = (a->Prec > b->Prec) ? a->Prec : b->Prec; + mx *= BASE_FIG; + if (2*BIGDECIMAL_DOUBLE_FIGURES > mx) + mx = 2*BIGDECIMAL_DOUBLE_FIGURES; + + GUARD_OBJ(c, VpCreateRbObject(mx + 2*BASE_FIG, "0", true)); + GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true)); VpDivd(c, res, a, b); - mx = c->Prec * (VpBaseFig() + 1); + + mx = c->Prec * BASE_FIG; GUARD_OBJ(d, VpCreateRbObject(mx, "0", true)); 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); + /* remainder adjustment for negative case */ + VpAddSub(res, d, VpOne(), -1); GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0", true)); - VpAddSub(d, c, b, 1); - *div = res; - *mod = d; - } else { - *div = d; - *mod = c; + VpAddSub(d, c, b, 1); + *div = res; + *mod = d; + } + else { + *div = d; + *mod = c; } return Qtrue; -- cgit v1.2.3