develooper Front page | perl.perl5.porters | Postings from January 2011

[perl #82966] [PATCH] bmodpow() fails when GMP library is used.

Thread Next
From:
perlbug-followup
Date:
January 30, 2011 06:05
Subject:
[perl #82966] [PATCH] bmodpow() fails when GMP library is used.
Message ID:
rt-3.6.HEAD-20807-1296236900-1733.82966-75-0@perl.org
# New Ticket Created by  (Peter J. Acklam) 
# Please include the string:  [perl #82966]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=82966 >


This bug is not seen when the libraries Calc and FastCalc are used,
because their _modpow() method modifies the first argument. However,
the GMP library's _modpow() does not modify the first argument,
causing a so far undetected bug to show up and fail tests.

Using the Calc library prints the correct "-4":

    use Math::BigInt lib => Calc;
    $x = Math::BigInt->new(8);
    $y = Math::BigInt->new(8);
    $z = Math::BigInt->new(-5);
    print $x -> bmodpow($y, $z), "\n";

Using the GMP library prints the incorrect "--":

    use Math::BigInt lib => GMP;
    $x = Math::BigInt->new(8);
    $y = Math::BigInt->new(8);
    $z = Math::BigInt->new(-5);
    print $x -> bmodpow($y, $z), "\n";
---
 dist/Math-BigInt/lib/Math/BigInt.pm |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/dist/Math-BigInt/lib/Math/BigInt.pm b/dist/Math-BigInt/lib/Math/BigInt.pm
index 45a0f01..177894a 100644
--- a/dist/Math-BigInt/lib/Math/BigInt.pm
+++ b/dist/Math-BigInt/lib/Math/BigInt.pm
@@ -18,7 +18,7 @@ package Math::BigInt;
 my $class = "Math::BigInt";
 use 5.006002;
 
-$VERSION = '1.99_04';
+$VERSION = '1.99_05';
 
 @ISA = qw(Exporter);
 @EXPORT_OK = qw(objectify bgcd blcm); 
@@ -1858,9 +1858,9 @@ sub bmodinv
 
 sub bmodpow
   {
-  # takes a very large number to a very large exponent in a given very
-  # large modulus, quickly, thanks to binary exponentiation. Supports
-  # negative exponents.
+  # Modular exponentiation. Raises a very large number to a very large exponent
+  # in a given very large modulus quickly, thanks to binary exponentiation.
+  # Supports negative exponents.
   my ($self,$num,$exp,$mod,@r) = objectify(3,@_);
 
   return $num if $num->modify('bmodpow');
@@ -1890,7 +1890,7 @@ sub bmodpow
   # If the resulting value is non-zero, we have four special cases, depending
   # on the signs on 'a' and 'm'.
 
-  unless ($CALC->_is_zero($num->{value})) {
+  unless ($CALC->_is_zero($value)) {
 
       # There is a negative sign on 'a' (= $num**$exp) only if the number we
       # are exponentiating ($num) is negative and the exponent ($exp) is odd.
@@ -1913,7 +1913,7 @@ sub bmodpow
           else {
               # Use copy of $mod since _sub() modifies the first argument.
               my $mod = $CALC->_copy($mod->{value});
-              $value = $CALC->_sub($mod, $num->{value});
+              $value = $CALC->_sub($mod, $value);
               $sign  = '+';
           }
 
@@ -1925,8 +1925,9 @@ sub bmodpow
           #               = -(m - (a (mod m)))
 
           if ($mod->{sign} eq '-') {
+              # Use copy of $mod since _sub() modifies the first argument.
               my $mod = $CALC->_copy($mod->{value});
-              $value = $CALC->_sub($mod, $num->{value});
+              $value = $CALC->_sub($mod, $value);
               $sign  = '-';
           }
 
-- 
1.7.3.3


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About