[前][次][番号順一覧][スレッド一覧]

ruby-changes:72038

From: Nobuyoshi <ko1@a...>
Date: Thu, 2 Jun 2022 10:42:37 +0900 (JST)
Subject: [ruby-changes:72038] 9108db961d (master): Fix the condition when a new buffer is needed without GMP

https://git.ruby-lang.org/ruby.git/commit/?id=9108db961d

From 9108db961dc24615d3fd1093d95521e53f41e61c Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Mon, 9 May 2022 17:15:59 +0900
Subject: Fix the condition when a new buffer is needed without GMP

---
 bignum.c                 | 16 ++++++++++++++--
 test/ruby/test_bignum.rb |  9 +++++++++
 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) https://github.com/ruby/ruby/blob/trunk/bignum.c#L1645
     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, https://github.com/ruby/ruby/blob/trunk/bignum.c#L1668
     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 https://github.com/ruby/ruby/blob/trunk/test/ruby/test_bignum.rb#L203
     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)
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]