[libmath-prime-util-perl] 07/35: Document partitions, tweak implementation for a little more speed

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:50:02 UTC 2015


This is an automated email from the git hooks/post-receive script.

ppm-guest pushed a commit to annotated tag v0.33
in repository libmath-prime-util-perl.

commit 0684fcac10e58d9c2ce357daaf5f8932de695ddf
Author: Dana Jacobsen <dana at acm.org>
Date:   Mon Oct 21 14:29:17 2013 -0700

    Document partitions, tweak implementation for a little more speed
---
 TODO                   |  2 --
 lib/Math/Prime/Util.pm | 45 ++++++++++++++++++++++++++++++++++-----------
 2 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/TODO b/TODO
index be09f83..8802eee 100644
--- a/TODO
+++ b/TODO
@@ -59,7 +59,5 @@
 
 - tests for factor_exp, liouville, partitions.
 
-- document partitions()
-
 - speedups for partitions()
 
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index d8301a3..65ed7e0 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -1660,14 +1660,11 @@ sub liouville {
   return $l;
 }
 
-# This is faster than most regular implementations I've seen, e.g. the ones
-# on stackoverflow or praxis.  The same algorithm in C+GMP is 300x faster.
-# It's much slower than Pari's floating point Rademacher algorithm.
 # See 2011+ FLINT and Fredrik Johansson's work for state of the art.
 #   Perl-comb   partitions(10^5)  ~ 300 seconds
 #   GMP-comb    partitions(10^6)  ~ 120 seconds  ( ~300x faster than Perl-comb)
 #   Pari        partitions(10^8)  ~ 100 seconds  (~1000x faster than GMP-comb)
-#   Bober       partitions(10^9)  ~  20 seconds  (~  50x faster than Pari)
+#   Bober 0.6   partitions(10^9)  ~  20 seconds  (~  50x faster than Pari)
 #   Johansson   partitions(10^12) ~  10 seconds  (>1000x faster than Pari)
 sub partitions {
   my($n) = @_;
@@ -1680,21 +1677,20 @@ sub partitions {
   if ($_HAVE_GMP && defined &Math::Prime::Util::GMP::partitions) {
     return Math::BigInt->new( '' . Math::Prime::Util::GMP::partitions($n) );
   }
-  my $d = int(sqrt($n+1));
+  my @part = (Math::BigInt->bone);
   my @pent = (1);
+  my $d = int(sqrt($n+1));
   foreach my $i ( 1 .. $d ) {
     push @pent, int(($i*(3*$i+1))/2), int((($i+1)*(3*$i+2))/2);
   }
-  my @part = (Math::BigInt->bone);
   foreach my $j (scalar @part .. $n) {
-    my $psum = Math::BigInt->bzero;
-    my $k = 1;
+    my ($psum1, $psum2, $k) = (Math::BigInt->bzero, Math::BigInt->bzero, 1);
     foreach my $p (@pent) {
       last if $p > $j;
-      if ((++$k) & 2) { $psum->badd( $part[ $j - $p ] ); }
-      else            { $psum->bsub( $part[ $j - $p ] ); }
+      if ((++$k) & 2) { $psum1->badd( $part[ $j - $p ] ); }
+      else            { $psum2->badd( $part[ $j - $p ] ); }
     }
-    $part[$j] = $psum;
+    $part[$j] = $psum1 - $psum2;
   }
   return $part[$n];
 }
@@ -3830,6 +3826,27 @@ to C<n>, resulting in much faster and memory-friendly results than using
 a factorial.
 
 
+=head2 partitions
+
+Calculates the partition function p(n) for a non-negative integer input.
+This is the number of ways of writing the integer n as a sum of positive
+integers, without restrictions.  This corresponds to Pari's C<numbpart>
+function and Mathematica's C<PartitionsP> function.  The values produced
+in order are L<OEIS series A000041|http://oeis.org/A000041>.
+
+This uses a combinatorial calculation, which means it will not be very
+fast compared to Pari, Mathematica, or FLINT which use the Rademacher
+formula using multiprecision floating point.  In 10 seconds, the pure
+Perl version can produce C<partitions(10000)> while with
+L<Math::Prime::Util::GMP> it can do C<partitions(200000)>.  In contrast,
+in about 10 seconds Pari can solve C<numbpart(22000000)>.
+
+If you want the enumerated partitions, see L<Integer::Partition>.  It is
+very fast and uses an extremely memory efficient iterator.  It is not,
+however, practical for producing the partition I<number> for values
+over 100 or so.
+
+
 =head2 carmichael_lambda
 
 Returns the Carmichael function (also called the reduced totient function,
@@ -4822,6 +4839,12 @@ Similar to MPU's L</moebius>.  Comparisons are similar to C<eulerphi>.
 Similar to MPU's L</divisor_sum>.  MPU is ~10x faster for native integers
 and about 2x slower for bigints.
 
+=item C<numbpart>
+
+Similar to MPU's L</partitions>.  This function is not in Pari 2.1, which
+is the default version used by Math::Pari.  With Pari 2.3 or newer, the
+functions produce identical results, but Pari is much, much faster.
+
 =item C<eint1>
 
 Similar to MPU's L</ExponentialIntegral>.

-- 
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