[libmath-prime-util-perl] 67/72: Iterator object tests and fixes for next/prev prime behavior near native boundary
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:49:42 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.32
in repository libmath-prime-util-perl.
commit 722ec20738dd3b2a9cdda5d0ba25a90011f66095
Author: Dana Jacobsen <dana at acm.org>
Date: Mon Oct 14 12:30:54 2013 -0700
Iterator object tests and fixes for next/prev prime behavior near native boundary
---
Changes | 3 +-
lib/Math/Prime/Util.pm | 14 +++---
lib/Math/Prime/Util/PP.pm | 2 +-
lib/Math/Prime/Util/PrimeIterator.pm | 30 ++++++-------
t/32-iterators.t | 84 +++++++++++++++++++++++++++++++++++-
5 files changed, 106 insertions(+), 27 deletions(-)
diff --git a/Changes b/Changes
index 68b2c81..c2e766d 100644
--- a/Changes
+++ b/Changes
@@ -50,7 +50,8 @@ Revision history for Perl module Math::Prime::Util
- Montgomery reduction used in Lucas and Frobenius tests. Up to 2x
speedup for 33 to 64-bit inputs on x86_64/gcc platforms.
- - Some fixes around near maxint primes, forprimes, etc.
+ - Some fixes around near maxint primes, forprimes, etc. Includes
+ more workarounds for Math::BigInt::GMP's constructor sign bug.
- Bytes::Random::Secure is loaded only when random prime functionality
is used. Shaves a few milliseconds and bytes off of startup.
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index a2e14f4..38cd325 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -62,7 +62,6 @@ sub _import_nobigint {
undef *nth_prime; *nth_prime = \&_XS_nth_prime;
undef *is_pseudoprime; *is_pseudoprime = \&_XS_is_pseudoprime;
undef *is_strong_pseudoprime; *is_strong_pseudoprime = \&_XS_miller_rabin;
- undef *miller_rabin; *miller_rabin = \&_XS_miller_rabin;
undef *moebius; *moebius = \&_XS_moebius;
undef *mertens; *mertens = \&_XS_mertens;
undef *euler_phi; *euler_phi = \&_XS_totient;
@@ -1247,7 +1246,7 @@ sub primorial {
if ($_HAVE_GMP && defined &Math::Prime::Util::GMP::primorial) {
if (ref($pn) eq 'Math::BigInt') {
- $pn->bzero->badd( Math::Prime::Util::GMP::primorial($n) );
+ $pn->bzero->badd( ''.Math::Prime::Util::GMP::primorial($n) );
} else {
$pn = int( Math::Prime::Util::GMP::primorial($n) );
}
@@ -1265,7 +1264,7 @@ sub pn_primorial {
_validate_num($n) || _validate_positive_integer($n);
my $pn = Math::Prime::Util::GMP::pn_primorial($n);
return int($pn) if $n < (($_Config{'maxbits'} == 32) ? 10 : 16);
- return $_[0]->copy->bzero->badd($pn) if ref($_[0]) eq 'Math::BigInt';
+ return $_[0]->copy->bzero->badd("$pn") if ref($_[0]) eq 'Math::BigInt';
if (!defined $Math::BigInt::VERSION) {
eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; }
or do { croak "Cannot load Math::BigInt"; };
@@ -1827,10 +1826,11 @@ sub _generic_next_prime {
if ($_HAVE_GMP) {
# If $n is a bigint object, try to make the return value the same
return (ref($_[0]) eq 'Math::BigInt')
- ? $_[0]->copy->bzero->badd(Math::Prime::Util::GMP::next_prime($n))
+ ? $_[0]->copy->bzero->badd(''.Math::Prime::Util::GMP::next_prime($n))
: Math::Prime::Util::GMP::next_prime($n);
}
- return Math::Prime::Util::PP::next_prime($n);
+ # Pass original argument to preserve bigint status
+ return Math::Prime::Util::PP::next_prime($_[0]);
}
sub _generic_prev_prime {
@@ -1842,7 +1842,7 @@ sub _generic_prev_prime {
if ($_HAVE_GMP) {
# If $n is a bigint object, try to make the return value the same
return (ref($_[0]) eq 'Math::BigInt')
- ? $n->copy->bzero->badd(Math::Prime::Util::GMP::prev_prime($n))
+ ? $n->copy->bzero->badd(''.Math::Prime::Util::GMP::prev_prime($n))
: Math::Prime::Util::GMP::prev_prime($n);
}
return Math::Prime::Util::PP::prev_prime($n);
@@ -1900,7 +1900,7 @@ sub factor {
if ($_HAVE_GMP) {
my @factors = Math::Prime::Util::GMP::factor($n);
if (ref($_[0]) eq 'Math::BigInt') {
- @factors = map { ($_ > ~0) ? $n->copy->bzero->badd($_) : $_ } @factors;
+ @factors = map { ($_ > ~0) ? $n->copy->bzero->badd(''.$_) : $_ } @factors;
}
return @factors;
}
diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm
index 7bad4f1..a4c147d 100644
--- a/lib/Math/Prime/Util/PP.pm
+++ b/lib/Math/Prime/Util/PP.pm
@@ -1353,7 +1353,7 @@ sub is_aks_prime {
->bsqrt->bmul($log2n)->bfloor->bstr);
$_poly_bignum = 1;
- if ( $n < ( (~0 == 4294967295) ? 65535 : 4294967295 ) ) {
+ if ( $n < ($_half_word-1) ) {
$_poly_bignum = 0;
$n = int($n->bstr) if ref($n) eq 'Math::BigInt';
}
diff --git a/lib/Math/Prime/Util/PrimeIterator.pm b/lib/Math/Prime/Util/PrimeIterator.pm
index da70c05..7aa20f9 100644
--- a/lib/Math/Prime/Util/PrimeIterator.pm
+++ b/lib/Math/Prime/Util/PrimeIterator.pm
@@ -14,23 +14,24 @@ our %EXPORT_TAGS = (all => [ @EXPORT_OK ]);
use Math::Prime::Util qw/next_prime prev_prime/;
use Math::BigInt try => "GMP,Pari";
-#use Carp qw/carp croak confess/;
+
+my $bigprime = Math::BigInt->new(
+ (~0 == 4294967295) ? "4294967311" : "18446744073709551629"
+);
sub new {
- my $class = shift;
- my($start) = @_;
+ my ($class, $start) = @_;
my $self = bless {
p => 2,
}, $class;
- $self->rewind($start) if defined $start && $start > 2;
+ $self->rewind($start) if defined $start;
return $self;
}
sub value { $_[0]->{p}; }
sub next {
my $self = shift;
- my $np = next_prime($self->{p});
- $np = next_prime(Math::BigInt->new(''.~0)) if $np == 0;
+ my $np = next_prime($self->{p}) || $bigprime;
$self->{p} = $np;
return $self;
}
@@ -43,23 +44,20 @@ sub prev {
sub iterate {
my $self = shift;
my $p = $self->{p};
- my $np = next_prime($p);
- $np = next_prime(Math::BigInt->new(''.~0)) if $np == 0;
+ my $np = next_prime($p) || $bigprime;
$self->{p} = $np;
return $p;
}
sub rewind {
- my $self = shift;
- my($start) = @_;
- if (defined $start) {
+ my ($self, $start) = @_;
+ $self->{p} = 2;
+ if (defined $start && $start ne '2') {
Math::Prime::Util::_validate_num($start)
|| Math::Prime::Util::_validate_positive_integer($start);
- $self->{p} = ($start > 2) ? next_prime($start-1) : 2;
- $self->{p} = next_prime(Math::BigInt->new(''.~0))
- if $self->{p} == 0 && $start > 0;
- } else {
- $self->{p} = 2;
+ if ($start > 2) {
+ $self->{p} = next_prime($start-1) || $bigprime;
+ }
}
return $self;
}
diff --git a/t/32-iterators.t b/t/32-iterators.t
index 645c1d3..b7fc19c 100644
--- a/t/32-iterators.t
+++ b/t/32-iterators.t
@@ -3,14 +3,19 @@ use strict;
use warnings;
use Test::More;
-use Math::Prime::Util qw/primes forprimes prime_iterator/;
+use Math::Prime::Util qw/primes prev_prime next_prime
+ forprimes prime_iterator prime_iterator_object/;
+use Math::BigInt try => "GMP,Pari";
my $use64 = Math::Prime::Util::prime_get_config->{'maxbits'} > 32;
plan tests => 8 + 5
+ 12
+ 3 + 7
- + 2;
+ + 2
+ + 3 + 7
+ + 22
+ + 0;
ok(!eval { forprimes { 1 } undef; }, "forprimes undef");
ok(!eval { forprimes { 1 } 2, undef; }, "forprimes 2,undef");
@@ -102,3 +107,78 @@ ok(!eval { prime_iterator(4.5); }, "iterator 4.5");
}
is_deeply( [@t], [qw/23 29 31 29 31 37 31 37 41 37 41 43 47 53 59 61 59 61 67 71 73 79 73 79 83 79 83 89/], "triple nested iterator" );
}
+
+# Test new object iterator
+ok(!eval { prime_iterator_object(-2); }, "iterator -2");
+ok(!eval { prime_iterator_object("abc"); }, "iterator abc");
+ok(!eval { prime_iterator_object(4.5); }, "iterator 4.5");
+
+{ my $it = prime_iterator_object();
+ is_deeply( [map { $it->iterate() } 1..10], [2,3,5,7,11,13,17,19,23,29], "iterator first 10 primes" );
+}
+{my $it = prime_iterator_object(47);
+ is_deeply( [map { $it->iterate() } 1..5], [47,53,59,61,67], "iterator 5 primes starting at 47" );
+}
+{my $it = prime_iterator_object(199);
+ is_deeply( [map { $it->iterate() } 1..3], [199,211,223], "iterator 3 primes starting at 199" );
+}
+{my $it = prime_iterator_object(200);
+ is_deeply( [map { $it->iterate() } 1..3], [211,223,227], "iterator 3 primes starting at 200" );
+}
+{my $it = prime_iterator_object(31397);
+ is_deeply( [map { $it->iterate() } 1..3], [31397,31469,31477], "iterator 3 primes starting at 31397" );
+}
+{my $it = prime_iterator_object(31396);
+ is_deeply( [map { $it->iterate() } 1..3], [31397,31469,31477], "iterator 3 primes starting at 31396" );
+}
+{my $it = prime_iterator_object(31398);
+ is_deeply( [map { $it->iterate() } 1..3], [31469,31477,31481], "iterator 3 primes starting at 31398" );
+}
+
+{
+ my $it = prime_iterator_object;
+ do { $it->next } for 1..10;
+ is( $it->value(), 31, "iterator object moved forward 10 now returns 31");
+ $it->prev;
+ is( $it->value(), 29, "iterator object moved back now returns 29");
+ is( $it->iterate(), 29, "iterator object iterates to 29");
+ is( $it->iterate(), 31, "iterator object iterates to 31");
+ $it->rewind->next->next->next->prev;
+ is( $it->value(), 5, "iterator object rewind and move returns 5");
+ # Validate that it automatically handles bigint range traversal.
+ my $top_prime = prev_prime(~0);
+ my $big_prime = next_prime(Math::BigInt->new(''.~0));
+ ok( $big_prime > ~0, "internal check, next_prime on big int works");
+ $it->rewind($top_prime);
+ is( $it->value(), $top_prime, "iterator object can rewind to $top_prime");
+ $it->next;
+ is( $it->value(), $big_prime, "iterator object next is $big_prime");
+ $it->rewind(~0);
+ is( $it->value(), $big_prime, "iterator object rewound to ~0 is $big_prime");
+ $it->prev;
+ is( $it->value(), $top_prime, "iterator object prev goes back to $top_prime");
+
+ # Validation for the Math::NumSeq compatiblity stuff
+ $it->rewind;
+ do { $it->next } for 1..200;
+ is( $it->tell_i(), 201, "iterator object tell_i");
+ is( $it->i_start, 1, "iterator object i_start = 1");
+ like( $it->description, qr/prime numbers/, "iterator object description");
+ is( $it->values_min, 2, "iterator object values_min = 2");
+ is( $it->values_max, undef, "iterator object values_max = undef");
+ # missing: characteristic
+ is( $it->oeis_anum, "A000040", "iterator object oeis_anum = A000040");
+ # missing: parameter_info_array / parameter_info_list
+ is( $it->seek_to_i(156)->value, 911, "iterator object seek_to_i goes to nth prime");
+ is( $it->seek_to_value(156)->value, 157, "iterator object seek_to_value goes to value");
+ is( $it->ith(589), 4289, "iterator object ith returns nth prime");
+ ok( $it->pred(577), "iterator object pred returns true if is_prime");
+ is( $it->value_to_i(4289), 589, "iterator object value_to_i works");
+ # missing: value_to_i_ceil
+ # missing: value_to_i_floor
+ my $est = $it->value_to_i_estimate( 4171510507 );
+ my $act = 197710788;
+ # We will get an estimate that is much, much closer than Math::NumSeq
+ ok( ($est > ($act-500)) && ($est < ($act+500)),
+ "iterator object value_to_i_estimage is in range");
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git
More information about the Pkg-perl-cvs-commits
mailing list