[libmath-prime-util-perl] 19/72: Add speedup for divisor count
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:49:37 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 c2a0056165a28e490109adf3e4d907d712990c2d
Author: Dana Jacobsen <dana at acm.org>
Date: Thu Sep 5 13:50:30 2013 -0700
Add speedup for divisor count
---
Changes | 3 +++
lib/Math/Prime/Util.pm | 21 +++++++++++++++++++++
t/19-moebius.t | 10 +++++++++-
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/Changes b/Changes
index 499227f..695ed5b 100644
--- a/Changes
+++ b/Changes
@@ -17,6 +17,9 @@ Revision history for Perl module Math::Prime::Util
should stay under ~150MB even with giant sizes.
Thanks to Kim Walisch for all discussions about this.
+ - divisor_sum can take a '1' as the second argument as an alias for
+ sub {1}, but works much faster.
+
0.31 2013-08-07
- Change proof certificate documentation to reflect the new text format.
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index 7399339..a2d7743 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -1437,6 +1437,22 @@ sub divisor_sum {
return $product;
}
+ if (ref($sub) ne 'CODE' && int($sub) == 1) {
+ return 1 if $n == 1;
+ my ($product, $exponent) = (1, 1);
+ my @factors = ($n <= $_XS_MAXVAL) ? _XS_factor($n) : factor($n);
+ while (@factors) {
+ if (@factors > 1 && $factors[0] == $factors[1]) {
+ $exponent++;
+ } else {
+ $product *= ($exponent+1);
+ $exponent = 1;
+ }
+ shift @factors;
+ }
+ return $product;
+ }
+
croak "Second argument must be a code ref" unless ref($sub) eq 'CODE';
my $sum = $sub->(1);
return $sum if $n == 1;
@@ -2419,6 +2435,7 @@ Version 0.31
# divisor sum
$sigma = divisor_sum( $n );
+ $sigma0 = divisor_sum( $n, 1 );
$sigma2 = divisor_sum( $n, sub { $_[0]*$_[0] } );
# primorial n#, primorial p(n)#, and lcm
@@ -3394,6 +3411,10 @@ This function takes a positive integer as input and returns the sum of all
the divisors of the input, including 1 and itself. This is known as the
sigma function (see Hardy and Wright section 16.7, or OEIS A000203).
+If a second argument is given that is numerically equal to 1, then we do
+a summation of the number of divisors. This is identical to the general
+form below with C<sub { 1 }>, but runs faster.
+
The more general form takes a code reference as a second parameter, which
is applied to each divisor before the summation. This allows computation
of numerous functions such as OEIS A000005 [d(n), sigma_0(n), tau(n)]:
diff --git a/t/19-moebius.t b/t/19-moebius.t
index 057f8ff..2e3796e 100644
--- a/t/19-moebius.t
+++ b/t/19-moebius.t
@@ -169,7 +169,7 @@ plan tests => 0 + 1
+ 2 # Dedekind psi calculated two ways
+ 1 # Calculate J5 two different ways
+ 2 * $use64 # Jordan totient example
- + 1 + scalar(keys %sigmak)
+ + 1 + scalar(keys %sigmak) + 2
+ scalar(keys %mangoldt)
+ scalar(keys %chebyshev1)
+ scalar(keys %chebyshev2);
@@ -263,6 +263,14 @@ while (my($k, $sigmaref) = each (%sigmak)) {
my @slist = map { divisor_sum($_) } 1 .. scalar @{$sigmak{1}};
is_deeply(\@slist, $sigmak{1}, "divisor_sum(n)");
}
+# tau two ways
+{
+ my $len = scalar @{$sigmak{0}};
+ my @slist1 = map { divisor_sum($_, sub {1}) } 1 .. $len;
+ my @slist2 = map { divisor_sum($_, 1 ) } 1 .. $len;
+ is_deeply( \@slist1, $sigmak{0}, "tau as divisor_sum(n, sub {1})" );
+ is_deeply( \@slist2, $sigmak{0}, "tau as divisor_sum(n, 1)" );
+}
###### Exponential of von Mangoldt
while (my($n, $em) = each (%mangoldt)) {
--
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