This is an automated email from the git hooks/post-receive script. ppm-guest pushed a commit to annotated tag v0.28 in repository libmath-prime-util-perl.
commit b1a7215698bdcec89ced51b3013599828e3baf9d Author: Dana Jacobsen <d...@acm.org> Date: Thu May 23 01:45:47 2013 -0700 tests for forprimes and iterator --- Changes | 3 ++ TODO | 9 ------ XS.xs | 9 +++--- factor.c | 35 +++++++++++++-------- lib/Math/Prime/Util.pm | 17 ++++++----- lib/Math/Prime/Util/PP.pm | 7 +++-- lib/Math/Prime/Util/PrimeArray.pm | 2 +- t/32-iterators.t | 64 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 109 insertions(+), 37 deletions(-) diff --git a/Changes b/Changes index e97dbdb..52e67ed 100644 --- a/Changes +++ b/Changes @@ -12,6 +12,9 @@ Revision history for Perl extension Math::Prime::Util. $sum = 0; forprimes { $sum += $_ } 1000,50000; say $sum; forprimes { say if is_prime($_+2) } 10000; # print twin primes + - my $it = prime_iterator(10000); say $it->(); + This is experimental (that is, the interface may change). + 0.27 20 May 2013 - is_prime, is_prob_prime, next_prime, and prev_prime now all go straight diff --git a/TODO b/TODO index bc275d1..aaa6311 100644 --- a/TODO +++ b/TODO @@ -41,15 +41,6 @@ - LMO prime count - QS factoring -- forprimes { say } 1000,2000 - - Tests - - Examples - -- prime_iterator - - Documentation - - Tests - - Examples - - Make forprimes use a segment sieve - Figure out a way to make the internal FOR_EACH_PRIME macros use a segmented diff --git a/XS.xs b/XS.xs index f395c63..86066d9 100644 --- a/XS.xs +++ b/XS.xs @@ -5,7 +5,6 @@ #include "perl.h" #include "XSUB.h" #include "multicall.h" /* only works in 5.6 and newer */ -#include <ctype.h> /* We're not using anything for which we need ppport.h */ #ifndef XSRETURN_UV /* Er, almost. Fix 21086 from Sep 2003 */ #define XST_mUV(i,v) (ST(i) = sv_2mortal(newSVuv(v)) ) @@ -23,7 +22,7 @@ #if PERL_REVISION <= 5 && PERL_VERSION <= 6 && BITS_PER_WORD == 64 /* This could be blown up with a wacky string, but it's just for 5.6 */ #define set_val_from_sv(val, sv) \ - { char*ptr = SvPV_nolen(sv); val = strtoul(ptr, NULL, 10); } + { char*ptr = SvPV_nolen(sv); val = Strtoul(ptr, NULL, 10); } #else #define set_val_from_sv(val, sv) \ val = SvUV(sv) @@ -72,10 +71,12 @@ static int _validate_int(SV* n, int negok) ptr = SvPV(n, len); if (len == 0) croak("Parameter '' must be a positive integer"); for (i = 0; i < len; i++) { - if (!isdigit(ptr[i])) { + if (!isDIGIT(ptr[i])) { if (i == 0 && ptr[i] == '-' && negok) isneg = 1; - else if (i == 0 && ptr[i] != '+') + else if (i == 0 && ptr[i] == '+') + /* Allowed */ ; + else croak("Parameter '%s' must be a positive integer", ptr); /* TODO NULL */ } } diff --git a/factor.c b/factor.c index 5a3a3b0..2eb88d6 100644 --- a/factor.c +++ b/factor.c @@ -354,13 +354,14 @@ int _XS_is_prob_prime(UV n) if (n < 2809) /* 53*53 */ return 2; #if BITS_PER_WORD == 32 + /* These aren't ideal. Could use 1 when n < 49191, 2 when n < 360018361 */ if (n < UVCONST(9080191)) { bases[0] = 31; bases[1] = 73; nbases = 2; } else { bases[0] = 2; bases[1] = 7; bases[2] = 61; nbases = 3; } #else - /* Better bases from http://miller-rabin.appspot.com/, 18 May 2013 */ + /* Better bases from http://miller-rabin.appspot.com/, 23 May 2013 */ if (n < UVCONST(341531)) { bases[0] = UVCONST(9345883071009581737); nbases = 1; @@ -368,24 +369,32 @@ int _XS_is_prob_prime(UV n) bases[0] = 15; bases[1] = UVCONST( 13393019396194701 ); nbases = 2; - } else if (n < UVCONST(242175507817)) { + } else if (n < UVCONST(273919523041)) { bases[0] = 15; - bases[1] = UVCONST( 7363882082 ); - bases[2] = UVCONST( 211573017068182 ); + bases[1] = UVCONST( 7363882082 ); + bases[2] = UVCONST( 992620450144556 ); nbases = 3; - } else if (n < UVCONST(47636622961201)) { + } else if (n < UVCONST(55245642489451)) { bases[0] = 2; - bases[1] = UVCONST( 2570940 ); - bases[2] = UVCONST( 211991001 ); - bases[3] = UVCONST( 3749873356 ); + bases[1] = UVCONST( 141889084524735 ); + bases[2] = UVCONST( 1199124725622454117 ); + bases[3] = UVCONST( 11096072698276303650 ); nbases = 4; - } else if (n < UVCONST(3770579582154547)) { + } else if (n < UVCONST(7999252175582851)) { bases[0] = 2; - bases[1] = UVCONST( 2570940 ); - bases[2] = UVCONST( 880937 ); - bases[3] = UVCONST( 610386380 ); - bases[4] = UVCONST( 4130785767 ); + bases[1] = UVCONST( 4130806001517 ); + bases[2] = UVCONST( 149795463772692060 ); + bases[3] = UVCONST( 186635894390467037 ); + bases[4] = UVCONST( 3967304179347715805 ); nbases = 5; + } else if (n < UVCONST(585226005592931977)) { + bases[0] = 2; + bases[1] = UVCONST( 123635709730000 ); + bases[2] = UVCONST( 9233062284813009 ); + bases[3] = UVCONST( 43835965440333360 ); + bases[4] = UVCONST( 761179012939631437 ); + bases[5] = UVCONST( 1263739024124850375 ); + nbases = 6; } else { bases[0] = 2; bases[1] = UVCONST( 325 ); diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm index 3af8fa8..b0a5c79 100644 --- a/lib/Math/Prime/Util.pm +++ b/lib/Math/Prime/Util.pm @@ -1352,7 +1352,8 @@ sub divisor_sum { return $sum; } -sub _generic_forprimes (&$;$) { + # Need proto for the block +sub _generic_forprimes (&$;$) { ## no critic qw(ProhibitSubroutinePrototypes) my($sub, $beg, $end) = @_; if (!defined $end) { $end = $beg; $beg = 2; } _validate_num($beg) || _validate_positive_integer($beg); @@ -1367,7 +1368,9 @@ sub _generic_forprimes (&$;$) { sub prime_iterator { my($start) = @_; - my $p = (defined $start && $start > 0) ? $start-1 : 0; + $start = 0 unless defined $start; + _validate_num($start) || _validate_positive_integer($start); + my $p = ($start > 0) ? $start-1 : 0; if (ref($p) ne 'Math::BigInt' && $p <= $_XS_MAXVAL) { return sub { $p = _XS_next_prime($p); return $p; }; } elsif ($_HAVE_GMP) { @@ -2368,7 +2371,7 @@ __END__ =encoding utf8 -=for stopwords Möbius Deléglise totient moebius mertens irand primesieve uniqued k-tuples von SoE pari yafu fonction qui compte le nombre nombres voor PhD +=for stopwords forprimes Möbius Deléglise totient moebius mertens irand primesieve uniqued k-tuples von SoE pari yafu fonction qui compte le nombre nombres voor PhD =head1 NAME @@ -2688,10 +2691,8 @@ input is C<2> or lower. Given a block and either an end count or a start and end pair, calls the block for each prime in the range. Compared to getting a big array of primes and iterating through it, this is more memory efficient and perhaps more -convenient. - -Inside the block, you may use C<last> to exit early, or C<return> to skip to -the next entry. +convenient. There is no way to exit the loop early, so the iterator may +be more appropriate for those uses. =head2 prime_iterator @@ -2711,7 +2712,7 @@ On each call, the iterator returns the current value and increments to the next prime. In general, L</forprimes> will be more efficient, but the generic iterator has -a little more flexibility. +more flexibility (e.g. exiting a loop early, or passing the iterator around). =head2 prime_count diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm index aa5d818..e413d0b 100644 --- a/lib/Math/Prime/Util/PP.pm +++ b/lib/Math/Prime/Util/PP.pm @@ -1070,8 +1070,11 @@ sub is_aks_prime { return 0 if _is_perfect_power($n); # limit = floor( log2(n) * log2(n) ). o_r(n) must be larger than this - my $sqrtn = int(Math::BigFloat->new($n)->bsqrt->bfloor->bstr); - my $log2n = Math::BigFloat->new("$n")->blog(2); + my $floatn = Math::BigFloat->new($n); + my $sqrtn = int($floatn->copy->bsqrt->bfloor->bstr); + # The following line seems to trigger a memory leak in Math::BigFloat::blog + # (the part where $MBI is copied to $int) if $n is a Math::BigInt::GMP. + my $log2n = $floatn->copy->blog(2); my $log2_squared_n = $log2n * $log2n; my $limit = int($log2_squared_n->bfloor->bstr); diff --git a/lib/Math/Prime/Util/PrimeArray.pm b/lib/Math/Prime/Util/PrimeArray.pm index 377b418..0d0f08b 100644 --- a/lib/Math/Prime/Util/PrimeArray.pm +++ b/lib/Math/Prime/Util/PrimeArray.pm @@ -180,7 +180,7 @@ An array that acts like the infinite set of primes. This may be more convenient than using L<Math::Prime::Util> directly, and in some cases it can be faster than calling C<next_prime> and C<prev_prime>. -If the access pattern is ascending or decending, then a window is sieved and +If the access pattern is ascending or descending, then a window is sieved and results returned from the window as needed. If the access pattern is random, then C<nth_prime> is used. diff --git a/t/32-iterators.t b/t/32-iterators.t new file mode 100644 index 0000000..202ad66 --- /dev/null +++ b/t/32-iterators.t @@ -0,0 +1,64 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use Test::More; +use Math::Prime::Util qw/primes forprimes prime_iterator/; + +my $use64 = Math::Prime::Util::prime_get_config->{'maxbits'} > 32; + +plan tests => 8 + 5 + + 3 + 7; + +ok(!eval { forprimes { 1 } undef; }, "forprimes undef"); +ok(!eval { forprimes { 1 } 2, undef; }, "forprimes 2,undef"); +ok(!eval { forprimes { 1 } undef, 2; }, "forprimes 2,undef"); +# This is caught at compile type because of the prototype +#ok(!eval { forprimes { 1 } 2, 3, 4; }, "forprimes 2,3,4"); +ok(!eval { forprimes { 1 } -2, 3; }, "forprimes -2,3"); +ok(!eval { forprimes { 1 } 2, -3; }, "forprimes 2,-3"); +ok(!eval { forprimes { 1 } "abc"; }, "forprimes abc"); +ok(!eval { forprimes { 1 } 2, "abc"; }, "forprimes 2, abc"); +ok(!eval { forprimes { 1 } 5.6; }, "forprimes abc"); + +{ my @t; forprimes { push @t, $_ } 50; + is_deeply( [@t], [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47], "forprimes 50" ); +} +{ my @t; forprimes { push @t, $_ } 2,20; + is_deeply( [@t], [2,3,5,7,11,13,17,19], "forprimes 2,20" ); +} +{ my @t; forprimes { push @t, $_ } 20,30; + is_deeply( [@t], [23,29], "forprimes 20,30" ); +} +{ my @t; forprimes { push @t, $_ } 199, 223; + is_deeply( [@t], [199,211,223], "forprimes 199,223" ); +} +{ my @t; forprimes { push @t, $_ } 31398, 31468; + is_deeply( [@t], [], "forprimes 31398,31468 (empty region)" ); +} + +ok(!eval { prime_iterator(-2); }, "iterator -2"); +ok(!eval { prime_iterator("abc"); }, "iterator abc"); +ok(!eval { prime_iterator(4.5); }, "iterator 4.5"); + +{ my $it = prime_iterator(); + is_deeply( [map { $it->() } 1..10], [2,3,5,7,11,13,17,19,23,29], "iterator first 10 primes" ); +} +{my $it = prime_iterator(47); + is_deeply( [map { $it->() } 1..5], [47,53,59,61,67], "iterator 5 primes starting at 47" ); +} +{my $it = prime_iterator(199); + is_deeply( [map { $it->() } 1..3], [199,211,223], "iterator 3 primes starting at 199" ); +} +{my $it = prime_iterator(200); + is_deeply( [map { $it->() } 1..3], [211,223,227], "iterator 3 primes starting at 200" ); +} +{my $it = prime_iterator(31397); + is_deeply( [map { $it->() } 1..3], [31397,31469,31477], "iterator 3 primes starting at 31397" ); +} +{my $it = prime_iterator(31396); + is_deeply( [map { $it->() } 1..3], [31397,31469,31477], "iterator 3 primes starting at 31396" ); +} +{my $it = prime_iterator(31398); + is_deeply( [map { $it->() } 1..3], [31469,31477,31481], "iterator 3 primes starting at 31398" ); +} -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git _______________________________________________ Pkg-perl-cvs-commits mailing list Pkg-perl-cvs-commits@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits