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

ruby-changes:32075

From: mrkn <ko1@a...>
Date: Fri, 13 Dec 2013 02:02:36 +0900 (JST)
Subject: [ruby-changes:32075] mrkn:r44153 (trunk): * ext/bigdecimal/bigdecimal.c (VpSetPTR): fix for limitation of the resulting

mrkn	2013-12-13 02:02:27 +0900 (Fri, 13 Dec 2013)

  New Revision: 44153

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=44153

  Log:
    * ext/bigdecimal/bigdecimal.c (VpSetPTR): fix for limitation of the resulting
      precision.
    
    * test/bigdecimal/test_bigdecimal.rb (test_limit): add tests for the above
       change.

  Modified files:
    trunk/ChangeLog
    trunk/ext/bigdecimal/bigdecimal.c
    trunk/test/bigdecimal/test_bigdecimal.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 44152)
+++ ChangeLog	(revision 44153)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Dec 13 02:00:00 2013  Kenta Murata  <mrkn@m...>
+
+	* ext/bigdecimal/bigdecimal.c (VpSetPTR): fix for limitation of the resulting
+	  precision.
+
+	* test/bigdecimal/test_bigdecimal.rb (test_limit): add tests for the above
+	  change.
+
 Wed Dec 13 01:56:00 2013  Kenta Murata  <mrkn@m...>
 
 	* ext/bigdecimal/bigdecimal.c (VpAddAbs): put out a conditional branch from
Index: ext/bigdecimal/bigdecimal.c
===================================================================
--- ext/bigdecimal/bigdecimal.c	(revision 44152)
+++ ext/bigdecimal/bigdecimal.c	(revision 44153)
@@ -4189,6 +4189,7 @@ VpAddAbs(Real *a, Real *b, Real *c) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4189
     a_pos = ap;
     b_pos = bp;
     c_pos = cp;
+
     if (word_shift == (size_t)-1L) return 0; /* Overflow */
     if (b_pos == (size_t)-1L) goto Assign_a;
 
@@ -4380,12 +4381,19 @@ static size_t https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4381
 VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, BDIGIT *av, BDIGIT *bv)
 {
     size_t left_word, right_word, word_shift;
+
+    size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
+
+    assert(a->exponent >= b->expoennt);
+
     c->frac[0] = 0;
     *av = *bv = 0;
+
     word_shift = (a->exponent - b->exponent);
     left_word = b->Prec + word_shift;
     right_word = Max(a->Prec, left_word);
     left_word = c->MaxPrec - 1;    /* -1 ... prepare for round up */
+
     /*
      * check if 'round' is needed.
      */
@@ -4408,7 +4416,9 @@ VpSetPTR(Real *a, Real *b, Real *c, size https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4416
 	     *   a_pos =    |
 	     */
 	    *a_pos = left_word;
-	    *av = a->frac[*a_pos];    /* av is 'A' shown in above. */
+	    if (*a_pos <= round_limit) {
+		*av = a->frac[*a_pos];    /* av is 'A' shown in above. */
+	    }
 	}
 	else {
 	    /*
@@ -4427,7 +4437,9 @@ VpSetPTR(Real *a, Real *b, Real *c, size https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4437
 	     */
 	    if (c->MaxPrec >= word_shift + 1) {
 		*b_pos = c->MaxPrec - word_shift - 1;
-		*bv = b->frac[*b_pos];
+		if (*b_pos + word_shift <= round_limit) {
+		    *bv = b->frac[*b_pos];
+		}
 	    }
 	    else {
 		*b_pos = -1L;
Index: test/bigdecimal/test_bigdecimal.rb
===================================================================
--- test/bigdecimal/test_bigdecimal.rb	(revision 44152)
+++ test/bigdecimal/test_bigdecimal.rb	(revision 44153)
@@ -1151,6 +1151,25 @@ class TestBigDecimal < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/bigdecimal/test_bigdecimal.rb#L1151
     assert_equal(90, x ** 4) # OK? must it be 80?
     # 3 * 3 * 3 * 3 = 10 * 3 * 3 = 30 * 3 = 90 ???
     assert_raise(ArgumentError) { BigDecimal.limit(-1) }
+
+    bug7458 = '[ruby-core:50269] [#7458]'
+    one = BigDecimal('1')
+    epsilon = BigDecimal('0.7E-18')
+    BigDecimal.save_limit do
+      BigDecimal.limit(0)
+      assert_equal(BigDecimal("1.0000000000000000007"), one + epsilon, "limit(0) #{bug7458}")
+
+      1.upto(18) do |lim|
+        BigDecimal.limit(lim)
+        assert_equal(BigDecimal("1.0"), one + epsilon, "limit(#{lim}) #{bug7458}")
+      end
+
+      BigDecimal.limit(19)
+      assert_equal(BigDecimal("1.000000000000000001"), one + epsilon, "limit(19) #{bug7458}")
+
+      BigDecimal.limit(20)
+      assert_equal(BigDecimal("1.0000000000000000007"), one + epsilon, "limit(20) #{bug7458}")
+    end
   end
 
   def test_sign

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

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