# leto/math--primality

refactored new method _check_two_and_even, test suite for it

1 parent f8333c8 commit 20f51cf11461e58363efd20ffd31ca5dfaff15f2 Bob Kuo committed Jun 2, 2009
Showing with 33 additions and 12 deletions.
1. +21 −9 lib/Math/Primality.pm
2. +1 −1 t/is_prime.t
3. +5 −1 t/is_strong_lucas_pseudoprime.t
4. +6 −1 t/is_strong_pseudoprime.t
 @@ -104,9 +104,8 @@ sub is_strong_pseudoprime(\$;\$) \$base = GMP->new(\$base); \$n = GMP->new(\$n); - my \$cmp = Rmpz_cmp_ui(\$n, 2 ); - return 1 if \$cmp == 0; - return 0 if \$cmp < 0; + my \$cmp = _check_two_and_even(\$n); + return \$cmp if \$cmp != 2; # unnecessary but faster if \$n is even return 0 if Rmpz_even_p(\$n); @@ -172,10 +171,8 @@ sub is_strong_lucas_pseudoprime(\$) return 0; } # we also need to weed out all N < 3 and all even N - my \$cmp = Rmpz_cmp_ui(\$n, 2 ); - return 1 if \$cmp == 0; - return 0 if \$cmp < 0; - return 0 if Rmpz_even_p(\$n); + my \$cmp = _check_two_and_even(\$n); + return \$cmp if \$cmp != 2; # determine Selfridge parameters D, P and Q my (\$D, \$P, \$Q) = _find_dpq_selfridge(\$n); if (\$D == 0) { #_find_dpq_selfridge found a factor of N @@ -271,7 +268,7 @@ sub is_strong_lucas_pseudoprime(\$) return 0; } -#selfridge's method for finding the tuple (D,P,Q) for is_strong_lucas_pseudoprime +# selfridge's method for finding the tuple (D,P,Q) for is_strong_lucas_pseudoprime sub _find_dpq_selfridge(\$) { my \$n = GMP->new(\$_[0]); my (\$d,\$sign,\$wd) = (5,1,0); @@ -305,18 +302,33 @@ sub _find_dpq_selfridge(\$) { # Q = (1 - D) / 4 \$q = (1 - \$wd) / 4; } + debug "found P and Q: (\$p, \$q)"; return (\$wd, \$p, \$q); } -#alternate method for finding the tuple (D,P,Q) for is_strong_lucas_pseudoprime +# alternate method for finding the tuple (D,P,Q) for is_strong_lucas_pseudoprime sub _find_dpq_alternate(\$) { } +# method returns 0 if N < two or even, returns 1 if N == 2 +# returns 2 if N > 2 and odd +sub _check_two_and_even(\$) { + my \$n = GMP->new(\$_[0]); + + my \$cmp = Rmpz_cmp_ui(\$n, 2 ); + return 1 if \$cmp == 0; + return 0 if \$cmp < 0; + return 0 if Rmpz_even_p(\$n); + return 2; +} + # should do exactly what it says - returns true if number is prime, false if number is composite sub is_prime(\$) { my \$n = GMP->new(\$_[0]); # first eliminate all n < 2 and even n > 3 + my \$cmp = _check_two_and_even(\$n); + return \$cmp if \$cmp != 2; # trial division of n up to some small number (perhaps a thousand) # try Miller-Rabin strong psuedoprime test with base 2 # try Lucas-Selfridge strong psuedoprime test
 @@ -11,11 +11,11 @@ use Math::GMPz; my \$z = Math::GMPz->new(3); ok( is_prime(3), "is_prime should handle Math::GMPz objects, three is prime" ); ok( is_prime(2), "is_prime should handle 2 as a prime"); +ok( !is_prime(20), "is_prime should even numbers"); TODO: { local \$TODO = "is_prime is being worked on"; - ok( !is_prime(20), "is_prime should even numbers"); ### test small numbers (<1000) ### ### test known Miller-Rabin psuedoprimes base 2 ### ### test Carmichael numbers ###
 @@ -2,7 +2,7 @@ use strict; use warnings; -use Test::More tests => 20; +use Test::More tests => 23; use Math::Primality qw/ is_strong_lucas_pseudoprime/; use Math::GMPz; @@ -15,6 +15,10 @@ ok(is_strong_lucas_pseudoprime(\$z), "is_strong_lucas_pseudoprime should handle M ok(!is_strong_lucas_pseudoprime(9), 'is_strong_lucas_pseudoprime deals with perfect squares'); ok(!is_strong_lucas_pseudoprime(16), 'is_strong_lucas_pseudoprime deals with perfect squares'); ok(!is_strong_lucas_pseudoprime(100), 'is_strong_lucas_pseudoprime deals with perfect squares'); +### test _check_two_and_even ### +ok (Math::Primality::_check_two_and_even(2) == 1, '_check_two_and_even(2) should return 1'); +ok (Math::Primality::_check_two_and_even(20) == 0, '_check_two_and_even(20) should return 0'); +ok (Math::Primality::_check_two_and_even(1) == 0, '_check_two_and_even(1) should return 0'); ### first five strong Lucas psuedoprimes ### ok(is_strong_lucas_pseudoprime(5459), "is_strong_lucas_pseudoprime should return true for the first lucas pseudoprime"); ok(is_strong_lucas_pseudoprime(5777), "is_strong_lucas_pseudoprime should return true for the second lucas pseudoprime");
 @@ -2,13 +2,18 @@ use strict; use warnings; -use Test::More tests => 509; +use Test::More tests => 512; use Math::Primality qw/ is_strong_pseudoprime /; use Math::GMPz; my \$z = Math::GMPz->new(3); ok(is_strong_pseudoprime(\$z), 'is_strong_pseudoprime groks Math::GMPz objects'); +### test _check_two_and_even ### +ok (Math::Primality::_check_two_and_even(2) == 1, '_check_two_and_even(2) should return 1'); +ok (Math::Primality::_check_two_and_even(20) == 0, '_check_two_and_even(20) should return 0'); +ok (Math::Primality::_check_two_and_even(1) == 0, '_check_two_and_even(1) should return 0'); +### test is_strong_pseudoprime ### ok(!is_strong_pseudoprime(-1),'-1 is not a spsp' ); ok(!is_strong_pseudoprime(0),'0 is not a spsp' ); ok(!is_strong_pseudoprime(1),'1 is not a spsp' );