aboutsummaryrefslogtreecommitdiffstats
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
parentf35c5a28562af6dd5d2192fab02b81b352505b68 (diff)
downloadruby-9108db961dc24615d3fd1093d95521e53f41e61c.tar.gz
Fix the condition when a new buffer is needed without GMP
-rw-r--r--bignum.c16
-rw-r--r--test/ruby/test_bignum.rb9
2 files changed, 23 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);
}
diff --git a/test/ruby/test_bignum.rb b/test/ruby/test_bignum.rb
index 53a2b20cc8..065a944853 100644
--- a/test/ruby/test_bignum.rb
+++ b/test/ruby/test_bignum.rb
@@ -203,6 +203,15 @@ class TestBignum < Test::Unit::TestCase
assert_equal(00_02, '00_02'.to_i)
end
+ def test_very_big_str_to_inum
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ digits = [["3", 700], ["0", 2700], ["1", 1], ["0", 26599]]
+ num = digits.inject("") {|s,(c,n)|s << c*n}.to_i
+ assert_equal digits.sum {|c,n|n}, num.to_s.size
+ end;
+ end
+
def test_to_s2
assert_raise(ArgumentError) { T31P.to_s(37) }
assert_equal("9" * 32768, (10**32768-1).to_s)