Skip Menu |

This queue is for tickets about the Math-BigInt CPAN distribution.

Report information
The Basics
Id: 99242
Status: resolved
Priority: 0/
Queue: Math-BigInt

People
Owner: Nobody in particular
Requestors: DANAJ [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 1.9993
Fixed in: (no value)



Subject: Forward of RT43460 with patch
Math::BigFloat seems to have a different set of maintainers though it's included in the Math::BigInt distribution, so I'm making a new ticket here. https://rt.cpan.org/Ticket/Display.html?id=43460 I'm marking this critical because I keep getting hit by this bug and it produces incorrect results for very normal inputs (see below for some examples). There has been a fix on that thread for almost a year. Attached is an updated patch. The first change is a performance update for exp, and can be skipped if you do not feel comfortable with it, although it is a few orders of magnitude for large positive or negative values. The second part fixes results of negative and fractional bases in powers and exp. time perl -Mbignum -E 'say Math::BigFloat->new(-394.84010945715266885,20)->bexp();' Old: 2112036032039567973928673635099992827419000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 23.100s New: 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003335179622786491387299832160510130749927 0.350s perl -Mbignum=lib,GMP -le 'print 2**(-1034.5)' Old: 797870447579789479633740082394929951909700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 New: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003841222690408590466868250378242558090957 perl -Mbignum -E 'say .01**28.4' Old: 648531815674.9002481119466764195627749488 New: 0.000000000000000000000000000000000000000000000000000000001584893192461113485202101373391507013269 time perl -Mbignum=lib,GMP -E 'for (1..10000) { $s += exp(8000.01) } say $s' Old: 418.233s (output elided -- identical for both in this case) New: 0.470s
Subject: bigfloat-bpow-fix2.patch
--- /home/djacobsen/perl5/perlbrew/build/perl-5.21.2/lib/Math/BigFloat.pm 2014-07-18 07:55:23.000000000 -0700 +++ /home/djacobsen/perl5/perlbrew/perls/perl-5.21.2/lib/5.21.2/Math/BigFloat.pm 2014-09-30 16:35:39.639178662 -0700 @@ -1197,8 +1197,22 @@ # $x contains now an estimate of e, with some surplus digits, so we can round if (!$x_org->is_one()) { - # raise $x to the wanted power and round it in one step: - $x->bpow($x_org, @params); + # Reduce size of fractional part, followup with integer power of two. + my $lshift = 0; + while ($lshift < 30 && $x_org->bacmp(2 << $lshift) > 0) + { + $lshift++; + } + # Raise $x to the wanted power and round it. + if ($lshift == 0) + { + $x->bpow($x_org, @params); + } + else + { + my($mul, $rescale) = (1 << $lshift, $scale+1+$lshift); + $x->bpow(scalar $x_org->bdiv($mul,$rescale),$rescale)->bpow($mul, @params); + } } else { @@ -2394,6 +2408,8 @@ my ($limit,$v,$u,$below,$factor,$next,$over); $u = $x->copy()->blog(undef,$scale)->bmul($y); + my $do_invert = ($u->{sign} eq '-'); + $u->bneg() if $do_invert; $v = $self->bone(); # 1 $factor = $self->new(2); # 2 $x->bone(); # first term: 1 @@ -2418,6 +2434,12 @@ #$steps++; } + + if ($do_invert) + { + my $x_copy = $x->copy; + $x->bone->bdiv($x_copy, $scale); + } # shortcut to not run through _find_round_parameters again if (defined $params[0])
Fixed a long time ago.