summaryrefslogtreecommitdiff
path: root/ext/bigdecimal/bigdecimal.c
diff options
context:
space:
mode:
authorKenta Murata <mrkn@mrkn.jp>2021-01-22 13:49:46 +0900
committerKenta Murata <mrkn@mrkn.jp>2021-12-24 02:28:55 +0900
commit7b2cfce543b876744544c8b43abdee3c72cab910 (patch)
tree7d41e1f733856b4206a9987d6c8a7d462fad24f2 /ext/bigdecimal/bigdecimal.c
parente1265c819870c6a4d6763529e9fbd2d70c722fe0 (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/bigdecimal/bigdecimal.c')
-rw-r--r--ext/bigdecimal/bigdecimal.c33
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;