[libmath-prime-util-perl] 52/72: Make factor consistent in scalar context
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:49:40 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 99042b204d0875e3fd1bfea9e49f5f95772b3ee5
Author: Dana Jacobsen <dana at acm.org>
Date: Fri Sep 27 17:51:03 2013 -0700
Make factor consistent in scalar context
---
Changes | 5 +++++
TODO | 7 +++++++
XS.xs | 10 +++++++---
factor.c | 2 +-
lib/Math/Prime/Util.pm | 10 +++++++++-
lib/Math/Prime/Util/PP.pm | 11 +++++++----
t/50-factoring.t | 12 +++++++++++-
7 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/Changes b/Changes
index 2eaea16..7e34d7a 100644
--- a/Changes
+++ b/Changes
@@ -49,6 +49,11 @@ Revision history for Perl module Math::Prime::Util
- Speedup for Perl (no GMP) primality and random nbit primes.
+ - factor() can be called in scalar context to give the number of
+ prime factors. The XS function was ignoring the context, and now
+ is more consistent. It also slightly speeds up looking at the
+ number of factors, e.g. Omega(x) A001222.
+
0.31 2013-08-07
- Change proof certificate documentation to reflect the new text format.
diff --git a/TODO b/TODO
index 3ca6697..4dd824b 100644
--- a/TODO
+++ b/TODO
@@ -46,3 +46,10 @@
(1) optional second argument. Easily handled, and not hard to do in
generic sub call.
(2) generic sub returns an array. This is the sticking point.
+
+- Factoring in PP code is really wasteful -- we're calling _isprime7 before
+ we've done enough trial division, and later we're calling it on known
+ composites. Note how the XS code splits the factor code into the public
+ API (small factors, isprime, then call main code) and main code (just the
+ algorithm). The PP code isn't doing that, which means we're doing lots of
+ extra primality checks, which aren't cheap in PP.
diff --git a/XS.xs b/XS.xs
index b6cd063..401af40 100644
--- a/XS.xs
+++ b/XS.xs
@@ -402,9 +402,13 @@ _XS_factor(IN UV n)
int i, nfactors;
PPCODE:
nfactors = factor(n, factors);
- EXTEND(SP, nfactors);
- for (i = 0; i < nfactors; i++) {
- PUSHs(sv_2mortal(newSVuv( factors[i] )));
+ if (GIMME_V == G_SCALAR) {
+ PUSHs(sv_2mortal(newSVuv(nfactors)));
+ } else if (GIMME_V == G_ARRAY) {
+ EXTEND(SP, nfactors);
+ for (i = 0; i < nfactors; i++) {
+ PUSHs(sv_2mortal(newSVuv( factors[i] )));
+ }
}
void
diff --git a/factor.c b/factor.c
index 82d09c7..ab1c77d 100644
--- a/factor.c
+++ b/factor.c
@@ -161,7 +161,7 @@ int trial_factor(UV n, UV *factors, UV maxtrial)
if (maxtrial == 0) maxtrial = UV_MAX;
/* Cover the cases 0/1/2/3 now */
- if ( (n < 4) || (maxtrial < 4) ) {
+ if (n < 4 || maxtrial < 2) {
factors[0] = n;
return 1;
}
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 0c5cd10..49e7008 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -3090,6 +3090,10 @@ Returning composite for all non-2 even input makes the function match most
other implementations including L<Math::Primality>'s C<is_strong_pseudoprime>
function.
+=head2 miller_rabin
+
+An alias for C<is_strong_pseudoprime>. This name is deprecated.
+
=head2 is_lucas_pseudoprime
Takes a positive number as input, and returns 1 if the input is a standard
@@ -4018,6 +4022,10 @@ guarantees multiplying the factors together will always result in the
input value, though those are the only cases where the returned factors
are not prime.
+In scalar context, returns the number of prime factors with multiplicity
+(L<OEIS A001222|http://oeis.org/A001222>). This is the expected result,
+as if we put the result into an array and then took the scalar result.
+
The current algorithm for non-bigints is a sequence of small trial division,
a few rounds of Pollard's Rho, SQUFOF, Pollard's p-1, Hart's OLF, a long
run of Pollard's Rho, and finally trial division if anything survives. This
@@ -4353,7 +4361,7 @@ Project Euler, problem 187, stupid brute force solution, ~4 minutes:
use Math::Prime::Util qw/factor -nobigint/;
my $nsemis = 0;
- do { my @f = factor($_); $nsemis++ if scalar @f == 2; }
+ do { $nsemis++ if scalar factor($_) == 2; }
for 1 .. int(10**8)-1;
say $nsemis;
diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm
index aaa130a..31f835c 100644
--- a/lib/Math/Prime/Util/PP.pm
+++ b/lib/Math/Prime/Util/PP.pm
@@ -1398,10 +1398,12 @@ sub trial_factor {
_validate_positive_integer($n);
$maxlim = $n unless defined $maxlim && _validate_positive_integer($maxlim);
- # Don't use _basic factor here -- they want a trial forced.
- #my @factors = _basic_factor($n);
- return ($n) if $n < 4;
+ # Don't use _basic_factor here -- they want a trial forced.
my @factors;
+ if ($n < 4) {
+ @factors = ($n);
+ return @factors;
+ }
while ( !($n % 2) ) { push @factors, 2; $n = int($n / 2); }
while ( !($n % 3) ) { push @factors, 3; $n = int($n / 3); }
while ( !($n % 5) ) { push @factors, 5; $n = int($n / 5); }
@@ -1499,7 +1501,8 @@ sub factor {
}
push @factors, $n if $n != 1;
}
- sort {$a<=>$b} @factors;
+ @factors = sort {$a<=>$b} @factors;
+ return @factors;
}
sub _found_factor {
diff --git a/t/50-factoring.t b/t/50-factoring.t
index 8365d7a..042975b 100644
--- a/t/50-factoring.t
+++ b/t/50-factoring.t
@@ -74,7 +74,7 @@ my %all_factors = (
0 => [],
);
-plan tests => (2 * scalar @testn) + scalar(keys %all_factors) + 10*9 + 1;
+plan tests => (2 * scalar @testn) + scalar(keys %all_factors) + 10*9 + 8 + 1;
foreach my $n (@testn) {
my @f = factor($n);
@@ -126,3 +126,13 @@ sub extra_factor_test {
is_deeply( [ sort {$a<=>$b} $fsub->(403) ], [13, 31], "$fname(403)" );
is_deeply( [ sort {$a<=>$b} $fsub->(549900) ], [2,2,3,3,5,5,13,47], "$fname(549900)" );
}
+
+# Factor in scalar context
+is( scalar factor(0), 1, "scalar factor(0) should be 1" );
+is( scalar factor(1), 1, "scalar factor(1) should be 1" );
+is( scalar factor(3), 1, "scalar factor(3) should be 1" );
+is( scalar factor(4), 2, "scalar factor(4) should be 2" );
+is( scalar factor(5), 1, "scalar factor(5) should be 1" );
+is( scalar factor(6), 2, "scalar factor(6) should be 2" );
+is( scalar factor(30107), 4, "scalar factor(30107) should be 4" );
+is( scalar factor(174636000), 15, "scalar factor(174636000) should be 15" );
--
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