diff options
author | Kenta Murata <mrkn@mrkn.jp> | 2021-01-22 13:49:46 +0900 |
---|---|---|
committer | Kenta Murata <mrkn@mrkn.jp> | 2021-12-24 02:28:55 +0900 |
commit | 7b2cfce543b876744544c8b43abdee3c72cab910 (patch) | |
tree | 7d41e1f733856b4206a9987d6c8a7d462fad24f2 /ext | |
parent | e1265c819870c6a4d6763529e9fbd2d70c722fe0 (diff) |
[ruby/bigdecimal] Let BigDecimal_DoDivmod use the same precision calculation as BigDecimal_divide
https://github.com/ruby/bigdecimal/commit/11cb2c8840
Diffstat (limited to 'ext')
-rw-r--r-- | ext/bigdecimal/bigdecimal.c | 33 |
1 files changed, 20 insertions, 13 deletions
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 (mx<b->Prec + 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; |