[libmath-prime-util-perl] 05/08: Put segment mutex back
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:47:22 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.22
in repository libmath-prime-util-perl.
commit 11422a594d692d8194756c7e5405dd8d977087bd
Author: Dana Jacobsen <dana at acm.org>
Date: Mon Feb 25 20:50:40 2013 -0800
Put segment mutex back
---
MANIFEST | 4 +-
TODO | 11 ++-
XS.xs | 2 +-
cache.c | 2 +
examples/test-euler-pari.pl | 2 +-
xt/factor-holf.pl | 27 +++++++
xt/make-script-test-data.pl | 179 ++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 219 insertions(+), 8 deletions(-)
diff --git a/MANIFEST b/MANIFEST
index bcd426f..945ec81 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -46,7 +46,6 @@ examples/test-factor-yafu.pl
examples/test-factor-mpxs.pl
examples/test-nextprime-yafu.pl
examples/test-primes-yafu.pl
-examples/test-holf.pl
examples/test-nthapprox.pl
examples/test-pcapprox.pl
examples/sophie_germain.pl
@@ -56,7 +55,6 @@ examples/parallel_fibprime.pl
examples/test-bpsw.pl
examples/test-euler-pari.pl
examples/test-factor-gnufactor.pl
-examples/make-script-test-data.pl
examples/test-primes-script.pl
examples/test-primes-script2.pl
bin/primes.pl
@@ -88,4 +86,6 @@ t/91-release-pod-syntax.t
t/92-release-pod-coverage.t
xt/moebius-mertens.pl
xt/primality-small.pl
+xt/factor-holf.pl
+xt/make-script-test-data.pl
.travis.yml
diff --git a/TODO b/TODO
index 80ecaae..a3df769 100644
--- a/TODO
+++ b/TODO
@@ -40,7 +40,10 @@
- Dynamically use a mulmodadd in PP aks, just like the new C code does.
This will mean it'll work for full-size native ints.
-- Perl's rand() is a mess. I believe a decent workaround is to include
- tinymt32, seed it using the system rand (multiple calls, just use 8-bits
- each), then use it to get 32-bit irands. This would only be used if they
- didn't give us a RNG (so they don't care about strict crypto).
+- More efficient Mertens. The current version has poor growth.
+
+- Add first and second Chebyshev functions. See Planat and Solé (2011).
+
+- Keep speeding up factoring for very large values.
+
+- More efficient totient segment. Do we really need primes to n/2?
diff --git a/XS.xs b/XS.xs
index 8c53bb2..fca7d50 100644
--- a/XS.xs
+++ b/XS.xs
@@ -387,7 +387,7 @@ _XS_totient(IN UV lo, IN UV hi = 0)
Safefree(totients);
} else {
- UV facs[64]; /* maximum number of factors is log2n */
+ UV facs[MPU_MAX_FACTORS+1]; /* maximum number of factors is log2n */
UV i, nfacs, totient, lastf;
UV n = lo;
if (n <= 1) XSRETURN_UV(n);
diff --git a/cache.c b/cache.c
index c6b9d2a..0e8b101 100644
--- a/cache.c
+++ b/cache.c
@@ -220,6 +220,7 @@ void release_prime_segment(unsigned char* mem) {
void prime_precalc(UV n)
{
if (!mutex_init) {
+ MUTEX_INIT(&segment_mutex);
MUTEX_INIT(&primary_cache_mutex);
COND_INIT(&primary_cache_turn);
mutex_init = 1;
@@ -257,6 +258,7 @@ void _prime_memfreeall(void)
{
/* No locks. We're shutting everything down. */
if (mutex_init) {
+ MUTEX_DESTROY(&segment_mutex);
MUTEX_DESTROY(&primary_cache_mutex);
COND_DESTROY(&primary_cache_turn);
mutex_init = 0;
diff --git a/examples/test-euler-pari.pl b/examples/test-euler-pari.pl
index 2e86359..9be3147 100755
--- a/examples/test-euler-pari.pl
+++ b/examples/test-euler-pari.pl
@@ -9,7 +9,7 @@ use Math::Pari;
Math::Prime::Util::prime_precalc(10_000_000);
my $nlinear = 100000;
my $nrandom = shift || 100000;
-my $randmax = ~0;
+my $randmax = 10**16;
# Looks like MPU is 4x faster than Pari for 1 .. 1M, 5x faster for 1M - 10_000M.
#
diff --git a/xt/factor-holf.pl b/xt/factor-holf.pl
new file mode 100755
index 0000000..b1b0f32
--- /dev/null
+++ b/xt/factor-holf.pl
@@ -0,0 +1,27 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Math::Prime::Util qw/is_prime/;
+use List::Util qw/min max/;
+my $count = shift || -2;
+my $is64bit = (~0 > 4294967295);
+my $maxdigits = ($is64bit) ? 20 : 10; # Noting the range is limited for max.
+
+my $hrounds = 64*1024*1024;
+for (2 .. 100000000) {
+ my @fs;
+ my $s_fact = join(".",sort {$a<=>$b} Math::Prime::Util::factor($_));
+
+ my @p_holf;
+ push @fs, $_;
+ while (@fs) {
+ my $n = pop @fs;
+ if (is_prime($n)) { push @p_holf, $n; }
+ else { push @fs, Math::Prime::Util::holf_factor($n); }
+ }
+ my $s_holf = join(".",sort {$a<=>$b} @p_holf);
+
+ die "$_ $s_fact holf $s_holf\n" unless $s_fact eq $s_holf;
+
+ print "$_\n" if ($_ % 100000) == 0;
+}
diff --git a/xt/make-script-test-data.pl b/xt/make-script-test-data.pl
new file mode 100755
index 0000000..d72f463
--- /dev/null
+++ b/xt/make-script-test-data.pl
@@ -0,0 +1,179 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use File::Spec::Functions;
+use FindBin;
+use bigint try => 'GMP';
+use Data::BitStream::XS;
+use Math::Prime::Util qw/is_prime/;
+$|++;
+
+# Encode all the OEIS text files for our primes.pl testing into a bitstream.
+# This not only makes the test script run much faster, but it turns 18 text
+# files of 5MB into one ~300k file.
+
+my @test_data = (
+ # OEIS# TEXT NAME script-arg skip if > this
+ [ 7529, "Triplet", "triplet", 0],
+ [ 7530, "Quadruplet", "quadruplet", 0],
+ [23200, "Cousin", "cousin", 0],
+ [23201, "Sexy", "sexy", 0],
+ [ 1359, "Twin", "twin", 0],
+ [ 5385, "Safe", "safe", 0],
+ [ 5384, "SG", "sophie", 0],
+ [68652, "Circular", "circular", 0],
+ [27862, "Panaitopol", "panaitopol", 0],
+ [ 2407, "Cuban y+1", "cuban1", 0],
+ [ 2648, "Cuban y+2", "cuban2", 0],
+ [ 2385, "Palindromic", "palin", 32_965_656_923],
+ [ 668, "Mersenne", "mersenne", 10**100],
+ [ 5479, "Lucas", "lucas", 0],
+ [ 5478, "Fibonacci", "fibonacci", 0],
+ [63980, "Pillai", "pillai", 0],
+ [28388, "Good", "good", 20000],
+ [31157, "Lucky", "lucky", 0],
+ [ 5234, "Primorial+1", "pnp1", 2500],
+ [ 6794, "Primorial-1", "pnm1", 2500],
+ [18239, "Euclid", "euclid", 0],
+);
+
+foreach my $test (@test_data) {
+ my $oeis_no = $test->[0];
+ my $filename = sprintf("b%06d.txt", $oeis_no);
+ my $link = sprintf("http://oeis.org/A%06d/b%06d.txt", $oeis_no, $oeis_no);
+ if (!-r $filename) {
+ warn "Getting $filename from $link\n";
+ qx/wget $link/;
+ die "Could not retrieve. Bailing\n" unless -r $filename;
+ }
+ my $ref_data = read_oeis(@$test);
+ push @$test, $ref_data;
+}
+
+my $stream = Data::BitStream::XS->new( file => 'script-test-data.bs', mode => 'w' );
+foreach my $test (@test_data) {
+ encode_oeis(@$test);
+}
+$stream->write_close();
+
+sub read_oeis {
+ my($oeis_no, $name, $script_arg, $restrict) = @_;
+ die "Restrict isn't defined for $oeis_no : $name" unless defined $restrict;
+
+ my $filename = sprintf("b%06d.txt", $oeis_no);
+ my $link = sprintf("http://oeis.org/A%06d/b%06d.txt", $oeis_no, $oeis_no);
+
+ my @ref;
+ {
+ open my $fh, '<', $filename
+ or die "Can't read $filename.\nYou should run:\n wget $link\n";
+ printf "%12s primes: reading %12s...", $name, $filename;
+ my $char = " ";
+ while (<$fh>) {
+ next unless /^(\d+)\s+(\d+)/;
+ my $v = (length($2) < 20) ? $2 : Math::BigInt->new("$2");
+ if ($restrict > 0 && $v > $restrict) {
+ $char = '*';
+ last;
+ }
+ push @ref, $v;
+ }
+ close $fh;
+ print "$char";
+ }
+ printf " %7d.", scalar @ref;
+ print " Testing..";
+ if ($ref[-1] > 18446744073709551615) {
+ print ",";
+ # Check for monotonic and primeness
+ foreach my $i (0 .. $#ref) {
+ die "non-prime in $oeis_no $name\n" unless is_prime($ref[$i]);
+ if ($i > 0) {
+ die "non-monotonic sequence in $oeis_no $name ($i $ref[$i-1] $ref[$i])\n" if $ref[$i] <= $ref[$i-1];
+ die "even number in $oeis_no $name\n" if ($ref[$i] % 2) == 0;
+ }
+ }
+ } else {
+ no bigint;
+ print ".";
+ # Check for monotonic and primeness
+ foreach my $i (0 .. $#ref) {
+ die "non-prime in $oeis_no $name\n" unless is_prime($ref[$i]);
+ if ($i > 0) {
+ die "non-monotonic sequence in $oeis_no $name\n" if $ref[$i] <= $ref[$i-1];
+ die "even number in $oeis_no $name\n" if ($ref[$i] % 2) == 0;
+ }
+ }
+ }
+ print "done\n";
+ return \@ref;
+}
+
+sub encode_oeis {
+ my($oeis_no, $name, $script_arg, $restrict, $ref_data) = @_;
+
+ my @ref = @$ref_data;
+ printf "%12s primes: stream..", $name;
+
+ put_text_string($stream, $script_arg);
+ put_text_string($stream, $name);
+
+ if ($ref[-1] > 18446744073709551615) {
+ print ",";
+ # Store the first two values, then a list of deltas
+ $stream->put_gamma($oeis_no, 1, scalar @ref, $ref[0], $ref[1]);
+ print ".";
+ my @deltas = map { ($ref[$_] - $ref[$_-1] - 2)/2 } (2..$#ref);
+ print ".";
+ # Ugly... Check for anything really big;
+ my @giant;
+ foreach my $d (@deltas) {
+ if ($d >= 18446744073709551614) {
+ push @giant, $d;
+ $d = 18446744073709551614;
+ }
+ }
+ print ".";
+ my $k = 2;
+ $stream->put_arice($k, @deltas);
+ print ".";
+ # Store giant deltas raw
+ foreach my $d (@giant) {
+ if (ref($d) ne 'Math::BigInt') {
+ warn "big delta $d isn't a bigint.\n";
+ $d = Math::BigInt->new(0);
+ }
+ my $binstr = substr($d->as_bin, 2);
+ $stream->put_gamma(length($binstr));
+ $stream->put_string($binstr);
+ }
+ } else {
+ no bigint;
+ print ".";
+ # Store the first two values, then a list of deltas
+ $stream->put_gamma($oeis_no, 0, scalar @ref, $ref[0], $ref[1]);
+ print ".";
+ my @deltas = map { ($ref[$_] - $ref[$_-1] - 2)/2 } (2..$#ref);
+ print ".";
+ my $k = 2;
+ $stream->put_arice($k, @deltas);
+ }
+
+ print "done\n";
+}
+
+sub put_text_string {
+ my ($stream, $str) = @_;
+ $stream->put_gamma(ord($_)) for (split "", $str);
+ $stream->put_gamma(0);
+ 1;
+}
+
+sub get_text_string {
+ my ($stream) = @_;
+ my $str = '';
+ while (my $c = $stream->get_gamma) {
+ $str .= chr($c);
+ }
+ $str;
+}
--
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