summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2022-05-09 17:15:59 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2022-06-02 10:29:53 +0900
commit9108db961dc24615d3fd1093d95521e53f41e61c (patch)
tree30f49aa0fcf494e61f94e8baf4e7eada238cec62 /bignum.c
parentf35c5a28562af6dd5d2192fab02b81b352505b68 (diff)
Fix the condition when a new buffer is needed without GMP
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/bignum.c b/bignum.c
index 8f351ee208..75651f9524 100644
--- a/bignum.c
+++ b/bignum.c
@@ -1645,6 +1645,12 @@ rb_big_sq_fast(VALUE x)
return z;
}
+static inline size_t
+max_size(size_t a, size_t b)
+{
+ return (a > b ? a : b);
+}
+
/* balancing multiplication by slicing larger argument */
static void
bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
@@ -1662,8 +1668,14 @@ bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
BDIGITS_ZERO(zds, xn);
if (wn < xn) {
- const size_t r = (yn % xn) ? (yn % xn) : xn;
- if ((2 * xn + yn + r) > zn) {
+ /* The condition when a new buffer is needed:
+ * 1. (2(xn+r) > zn-(yn-r)) => (2xn+r > zn-yn), at the last
+ * iteration (or r == 0)
+ * 2. (2(xn+xn) > zn-(yn-r-xn)) => (3xn-r > zn-yn), at the
+ * previous iteration.
+ */
+ const size_t r = yn % xn;
+ if (2*xn + yn + max_size(xn-r, r) > zn) {
wn = xn;
wds = ALLOCV_N(BDIGIT, work, wn);
}