Subject: | bsqrt() breaks on floats with enough digits |

Hi,
there's a problem with bsqrt() on floats with more than 88 digits
(2*div_scale+4). I'm attaching a failing testcase and a proposed fix:
the result here with Math-BigInt 1.87 before the fix is
ok 708
not ok 709
# Test 709 got: "3.16227766016837933199889354443271853372" (t/mbimbf.t
at line 107 fail #2)
# Expected: "1"
Illegal division by zero at ../lib/Math/BigInt/Calc.pm line 922, <DATA>
line 77.
dubious
Test returned status 255 (wstat 65280, 0xff00)
DIED. FAILED tests 709-710
FWIW, this was originally reported as Debian bug #417528,
<http://bugs.debian.org/417528>, and the original scenario was
# perl -le 'use bignum; print sqrt(sqrt(2)**3)'
which gives the wrong answer of about 5.318 with 1.87 and another wrong
answer of about 9.102 with some earlier versions.
Please let me know if you need more information.
Thanks for your work on Math-BigInt,
--
Niko Tyni
ntyni@debian.org

Subject: | 417528.patch |

diff --git a/lib/Math/BigFloat.pm b/lib/Math/BigFloat.pm
index f2eb0a4..9f986be 100644
--- a/lib/Math/BigFloat.pm
+++ b/lib/Math/BigFloat.pm
@@ -2142,8 +2142,9 @@ sub bsqrt
# But we need at least $scale digits, so calculate how many are missing
my $shift = $scale - $digits;
- # That should never happen (we take care of integer guesses above)
- # $shift = 0 if $shift < 0;
+ # This happens if the input had enough digits
+ # (we take care of integer guesses above)
+ $shift = 0 if $shift < 0;
# Multiply in steps of 100, by shifting left two times the "missing" digits
my $s2 = $shift * 2;
diff --git a/t/mbimbf.t b/t/mbimbf.t
index fae3c8c..88201e1 100755
--- a/t/mbimbf.t
+++ b/t/mbimbf.t
@@ -32,7 +32,7 @@ BEGIN
print "# INC = @INC\n";
plan tests => 684
- + 23; # own tests
+ + 26; # own tests
}
use Math::BigInt 1.70;
@@ -100,3 +100,9 @@ $x = Math::BigFloat->new(100);
$x = $x->blog(Math::BigInt->new(10));
ok ($x,2);
+
+for my $i (80,88,100) {
+ $x = Math::BigFloat->new("1." . ("0" x $i) . "1");
+ $x = $x->bsqrt;
+ ok ($x, 1);
+}