Skip Menu |
 

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

Report information
The Basics
Id: 6253
Status: resolved
Worked: 2 min
Priority: 0/
Queue: Math-BigInt

People
Owner: TELS [...] cpan.org
Requestors: jeff [...] thekidders.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in:
  • 1.60
  • 1.61
  • 1.62
  • 1.63
  • 1.64
  • 1.65
  • 1.66
  • 1.67
  • 1.68
  • 1.69
  • 1.70
  • 1.71
  • 1.72
Fixed in: 1.73



Content-Type: text/plain
Content-Disposition: inline
Content-Transfer-Encoding: binary
MIME-Version: 1.0
X-Mailer: MIME-tools 5.411 (Entity 5.404)
Subject: bpow doesn't handle negative first arguments correctly
X-RT-Original-Encoding: iso-8859-1
Content-Length: 5273
Download (untitled) / with headers
text/plain 5.1k
This file, BigIntTest.pl: use Math::BigInt; use PowFix; sub ppow { my $x = shift; my $y = shift; my $expect = shift; my $res = Math::BigInt->bpow($x,$y); my $myres = Math::BigInt->kpow($x,$y); print "$x**$y = $res"; if ($res eq $expect) { print " \t#as expected.\n"; } else { print " \t#should this be $expect?\n"; } if ($myres eq $expect) { # print " \t#as expected.\n"; } else { print "\t#oops, I get $x**$y=$myres not $expect?\n"; } } &ppow(-2,2,4); &ppow('-inf',2,'inf'); &ppow('-inf',0,'NaN'); &ppow('-inf',-1,0); &ppow('-inf','inf','NaN'); &ppow(2,'inf','inf'); &ppow(2,'-inf',0); &ppow(0,'inf',0); &ppow(0,'-inf','inf'); &ppow(-2,'inf','NaN'); &ppow(-2,'-inf',0); &ppow(-1,'-inf','NaN'); &ppow(-1,'inf','NaN'); &ppow('-inf','NaN','NaN'); &ppow('inf','NaN','NaN'); &ppow(1,'inf',1); &ppow(1,'-inf',1); &ppow(0,0,1); &ppow(-1,-1,-1); &ppow(-2,3,-8); Produces this output: Show quoted text
> perl -w BigIntTest.pl
-2**2 = -4 #should this be 4? -inf**2 = -inf #should this be inf? -inf**0 = -inf #should this be NaN? -inf**-1 = -inf #should this be 0? -inf**inf = -inf #should this be NaN? 2**inf = 2 #should this be inf? 2**-inf = 2 #should this be 0? 0**inf = 0 #as expected. 0**-inf = 0 #should this be inf? -2**inf = -2 #should this be NaN? -2**-inf = -2 #should this be 0? -1**-inf = 1 #should this be NaN? -1**inf = 1 #should this be NaN? -inf**NaN = -inf #should this be NaN? inf**NaN = inf #should this be NaN? 1**inf = 1 #as expected. 1**-inf = 1 #as expected. 0**0 = 1 #as expected. -1**-1 = -1 #as expected. -2**3 = -8 #as expected. With my proposed fix in the module PowFix.pm: package Math::BigInt; my $nan = "NaN"; my $CALC = 'Math::BigInt::Calc'; # module to do low level math sub kpow { # (BINT or num_str, BINT or num_str) return BINT # compute power of two numbers -- stolen from Knuth Vol 2 pg 233 # modifies first argument # set up parameters my ($self,$x,$y,@r) = (ref($_[0]),@_); # objectify is costly, so avoid it if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) { ($self,$x,$y,@r) = objectify(2,@_); } return $x if $x->modify('bpow'); return $upgrade->bpow($upgrade->new($x),$y,@r) if defined $upgrade && !$y->isa($self); $r[3] = $y; # no push! #if x or y is NaN x**y = NaN return $x->bnan() if ($x->{sign} eq $nan || $y->{sign} eq $nan); #Now that NaNs are gone.. # if x==0, 0**y = inf/1/0 if y is <0/==0/>0 if($x->{sign} eq '+' && $CALC->_is_zero($x->{value})) { # e.g., 0 ** -7 => ( 1 / (0 ** 7)) => 1 / 0 => +inf return $x->binf() if $y->{sign} =~ /^-/; # -inf or y<0 # y=0: 0**0 = 1 return $x->bone() if $y->{sign} eq '+' && $CALC->_is_zero($y->{value}); # y>0 is only case left # y==+inf or y>0: 0**y = 0 return $x; } if ($CALC->_is_one($x->{value})) { #if x==1, 1**y = 1, even for y = +/-inf return $x if $x->{sign} eq '+'; # if x == -1 ... # -1 ** +/-inf = NaN since inf is neither odd nor even return $x->bnan() if $y->{sign} =~ /^[-+]inf/; # x<0: x ** +inf # -1 ** y = -1 if y is odd and 1 if y is even my $new_sign = $y->is_odd() ? '-' : '+'; $x->{sign} = $new_sign; # -inf/+inf ** y odd/even return $x; } # if y == inf if ($y->{sign} eq '+inf') { # x ** +inf (x is not NaN, +/-Inf) # x<0: x ** +inf = NaN return $x->bnan() if $x->{sign} =~ /^-/; # we have ruled out x is -inf, x<0, 0, 1, or NaN, so inf>x>1... # x ** inf = inf for x > 1 return $x->binf(); # x>1: x ** +inf } # if y == -inf if ($y->{sign} eq '-inf') { # we have ruled out x is 0, -1, 1, or NaN, so |x|>1... # x ** -inf = 0 for |x| > 1 return $x->bzero(); } # if x == +/-inf if ($x->{sign} =~ /^[+-]inf$/) { # +/-inf ** 0 = NaN return $x->bnan() if $CALC->_is_zero($y->{value}); # y<0: +/-inf ** y = 0 return $x->bzero() if $y->{sign} =~ /^-/; # we have ruled out y is 0, <0, -Inf, NaN, or +inf, so y>0... # inf>y>0: inf ** y = inf # inf>y>0: -inf ** y = -inf if y is odd and 1 if y is even if ($x->{sign} eq '-inf') { my $new_sign = $y->is_odd() ? '-inf' : '+inf'; $x->{sign} = $new_sign; # -inf/+inf ** y odd/even } return $x; } # cases 0 ** Y, X ** 0, X ** 1, 1 ** Y are handled by Calc or Emu # but we have handled 0 ** Y, 1 ** Y, and -1 ** Y already my $new_sign = '+'; $new_sign = $y->is_odd() ? '-' : '+' if ($x->{sign} ne '+'); # |x|>1, y<0: x ** y => 1 / (x ** -y) # so do test for negative $y after above's clause return $x->bnan() if $y->{sign} eq '-'; #if rounding is allowed, shouldn't we round? $x->{value} = $CALC->_pow($x->{value},$y->{value}); $x->{sign} = $new_sign; $x->{sign} = '+' if $CALC->_is_zero($y->{value}); $x->round(@r) if !exists $x->{_f} || $x->{_f} & MB_NEVER_ROUND == 0; $x; } 1; Show quoted text
> perl -v
This is perl, v5.8.0 built for MSWin32-x86-multi-thread (with 1 registered patch, see perl -V for more detail) Copyright 1987-2002, Larry Wall Binary build 805 provided by ActiveState Corp. http://www.ActiveState.com Built 18:08:02 Feb 4 2003 I have also tried this on 5.00503. As well as under linux with perl 5.8.2. Regards, Jeff
Content-Type: text/plain
Content-Disposition: inline
Content-Transfer-Encoding: binary
MIME-Version: 1.0
X-Mailer: MIME-tools 5.411 (Entity 5.404)
From: perl_dummy [...] bloodgate.com
X-RT-Original-Encoding: iso-8859-1
Content-Length: 320
Download (untitled) / with headers
text/plain 320b
[guest - Thu May 6 20:57:59 2004]: Helo Jeff, thank you for your detailed report and fix! I totally miss the rt bugs because somehow their email never reaches me :( Sorry for the late reply. I got a similiar bug report about negative powers today, so I am looking now for 1.73 to fix these bugs. Best wishes, Tels


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.