diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | ext/bigdecimal/bigdecimal.c | 10 | ||||
-rw-r--r-- | test/bigdecimal/test_bigdecimal.rb | 14 |
3 files changed, 27 insertions, 5 deletions
@@ -1,3 +1,11 @@ +Thu Nov 21 21:36:00 2013 Kenta Murata <mrkn@mrkn.jp> + + * 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@ruby-lang.org> * gc.c (vm_xrealloc, vm_xfree): use malloc_usable_size() to obtain old diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index e82ac38189..53efafd24b 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -1591,10 +1591,10 @@ BigDecimal_sqrt(VALUE self, VALUE nFig) 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) 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) 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) { diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb index 91eeafcff5..78ecd8bd30 100644 --- a/test/bigdecimal/test_bigdecimal.rb +++ b/test/bigdecimal/test_bigdecimal.rb @@ -804,6 +804,20 @@ class TestBigDecimal < Test::Unit::TestCase 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) |