ruby-changes:31685
From: mrkn <ko1@a...>
Date: Thu, 21 Nov 2013 21:37:53 +0900 (JST)
Subject: [ruby-changes:31685] mrkn:r43764 (trunk): * ext/bigdecimal/bigdecimal.c (BigDecimal_sqrt): Fix the precision of
mrkn 2013-11-21 21:37:46 +0900 (Thu, 21 Nov 2013) New Revision: 43764 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43764 Log: * ext/bigdecimal/bigdecimal.c (BigDecimal_sqrt): Fix the precision of the result BigDecimal of sqrt. [Bug #5266] [ruby-dev:44450] * test/bigdecimal/test_bigdecimal.rb: add tests for the above changes. Modified files: trunk/ChangeLog trunk/ext/bigdecimal/bigdecimal.c trunk/test/bigdecimal/test_bigdecimal.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 43763) +++ ChangeLog (revision 43764) @@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Nov 21 21:36:00 2013 Kenta Murata <mrkn@m...> + + * ext/bigdecimal/bigdecimal.c (BigDecimal_sqrt): Fix the precision of + the result BigDecimal of sqrt. + [Bug #5266] [ruby-dev:44450] + + * test/bigdecimal/test_bigdecimal.rb: add tests for the above changes. + Thu Nov 21 18:49:02 2013 Nobuyoshi Nakada <nobu@r...> * gc.c (vm_xrealloc, vm_xfree): use malloc_usable_size() to obtain old Index: ext/bigdecimal/bigdecimal.c =================================================================== --- ext/bigdecimal/bigdecimal.c (revision 43763) +++ ext/bigdecimal/bigdecimal.c (revision 43764) @@ -1591,10 +1591,10 @@ BigDecimal_sqrt(VALUE self, VALUE nFig) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1591 size_t mx, n; GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec *(VpBaseFig() + 1); + mx = a->Prec * (VpBaseFig() + 1); - n = GetPositiveInt(nFig) + VpDblFig() + 1; - if(mx <= n) mx = n; + n = GetPositiveInt(nFig) + VpDblFig() + BASE_FIG; + if (mx <= n) mx = n; GUARD_OBJ(c, VpCreateRbObject(mx, "0")); VpSqrt(c, a); return ToValue(c); @@ -5654,6 +5654,7 @@ VpSqrt(Real *y, Real *x) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L5654 n = (SIGNED_VALUE)y->MaxPrec; if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec; + /* allocate temporally variables */ f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1"); r = VpAlloc((n + n) * (BASE_FIG + 2), "#1"); @@ -5691,8 +5692,7 @@ VpSqrt(Real *y, Real *x) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L5692 if (VpIsZero(f)) goto converge; VpAddSub(r, f, y, 1); /* r = y + f */ VpAsgn(y, r, 1); /* y = r */ - if (f->exponent <= prec) goto converge; - } while(++nr < n); + } while (++nr < n); #ifdef BIGDECIMAL_DEBUG if (gfDebug) { Index: test/bigdecimal/test_bigdecimal.rb =================================================================== --- test/bigdecimal/test_bigdecimal.rb (revision 43763) +++ test/bigdecimal/test_bigdecimal.rb (revision 43764) @@ -804,6 +804,20 @@ class TestBigDecimal < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/bigdecimal/test_bigdecimal.rb#L804 assert_equal(1, BigDecimal.new("1").sqrt(1)) end + def test_sqrt_5266 + x = BigDecimal('2' + '0'*100) + assert_equal('0.14142135623730950488016887242096980785696718753769480731', + x.sqrt(56).to_s(56).split(' ')[0]) + assert_equal('0.1414213562373095048801688724209698078569671875376948073', + x.sqrt(55).to_s(55).split(' ')[0]) + + x = BigDecimal('2' + '0'*200) + assert_equal('0.14142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462', + x.sqrt(110).to_s(110).split(' ')[0]) + assert_equal('0.1414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641572735013846', + x.sqrt(109).to_s(109).split(' ')[0]) + end + def test_fix x = BigDecimal.new("1.1") assert_equal(1, x.fix) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/