This is an automated email from the git hooks/post-receive script. ppm-guest pushed a commit to annotated tag v0.06 in repository libmath-prime-util-perl.
commit e8a0765cd9de6c5f6e1b72290a797cf4c1a40f22 Author: Dana Jacobsen <d...@acm.org> Date: Thu Jun 14 09:25:31 2012 -0500 Move from mallloc/free to New/Safefree --- Changes | 3 +++ MANIFEST | 2 ++ Makefile.PL | 6 ++++- TODO | 3 +++ XS.xs | 16 ++++++------ cache.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cache.h | 15 +++++++++++ sieve.c | 72 +++------------------------------------------------- sieve.h | 4 --- util.c | 21 ++-------------- util.h | 4 --- 11 files changed, 126 insertions(+), 104 deletions(-) diff --git a/Changes b/Changes index f845e32..bf0ce81 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,8 @@ Revision history for Perl extension Math::Prime::Util. +0.06 18 June 2012 + - Change to New/Safefree from malloc. Oops. + 0.05 11 June 2012 - Speed up mulmod: asm for GCC + x86_64, native 64-bit for 32-bit Perl is uint64_t is available, and range tests for others. This speeds up diff --git a/MANIFEST b/MANIFEST index 0fca5aa..7102ba0 100644 --- a/MANIFEST +++ b/MANIFEST @@ -8,6 +8,8 @@ TODO XS.xs bitarray.h ptypes.h +cache.h +cache.c factor.h factor.c sieve.h diff --git a/Makefile.PL b/Makefile.PL index 752dcef..16d53ac 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -10,7 +10,11 @@ WriteMakefile1( LIBS => [''], # e.g., '-lm' DEFINE => '', # e.g., '-DHAVE_SOMETHING' INC => '', # e.g., '-I/usr/include/other' - OBJECT => 'factor.o sieve.o util.o XS.o', + OBJECT => 'cache.o ' . + 'factor.o ' . + 'sieve.o ' . + 'util.o ' . + 'XS.o', PREREQ_PM => { 'Test::More' => '0.45', diff --git a/TODO b/TODO index 6f36135..6134228 100644 --- a/TODO +++ b/TODO @@ -24,3 +24,6 @@ 1) mutex (holy slowdown, batman) 2) use one cache, and malloc/free if the cache isn't available. For sieve I think we'll need a counting semaphore. + +- Move .c / .h files into separate directory. + version does it in a painful way. Something simpler to be had? diff --git a/XS.xs b/XS.xs index f1e072d..c43a013 100644 --- a/XS.xs +++ b/XS.xs @@ -4,6 +4,7 @@ #include "XSUB.h" /* We're not using anything for which we need ppport.h */ #include "ptypes.h" +#include "cache.h" #include "sieve.h" #include "util.h" #include "bitarray.h" @@ -128,11 +129,9 @@ trial_primes(IN UV low, IN UV high) RETVAL SV* -segment_primes(IN UV low, IN UV high, IN UV segment_size = 65536UL) +segment_primes(IN UV low, IN UV high); PREINIT: AV* av = newAV(); - unsigned char* sieve; - UV low_d, high_d; CODE: if ((low <= 2) && (high >= 2)) { av_push(av, newSVuv( 2 )); } if ((low <= 3) && (high >= 3)) { av_push(av, newSVuv( 3 )); } @@ -140,9 +139,11 @@ segment_primes(IN UV low, IN UV high, IN UV segment_size = 65536UL) if (low < 7) low = 7; if (low <= high) { /* Call the segment siever one or more times */ - sieve = (unsigned char*) malloc( segment_size ); + UV low_d, high_d; + UV segment_size = SEGMENT_CHUNK_SIZE; + unsigned char* sieve = get_prime_segment(); if (sieve == 0) - croak("Could not allocate %"UVuf" bytes for segment sieve", segment_size); + croak("Could not get segment cache"); /* To protect vs. overflow, work entirely with d. */ low_d = low / 30; @@ -178,7 +179,6 @@ segment_primes(IN UV low, IN UV high, IN UV segment_size = 65536UL) low_d += range_d; low = seghigh+2; } - free(sieve); } RETVAL = newRV_noinc( (SV*) av ); OUTPUT: @@ -202,7 +202,7 @@ erat_primes(IN UV low, IN UV high) START_DO_FOR_EACH_SIEVE_PRIME( sieve, low, high ) { av_push(av,newSVuv(p)); } END_DO_FOR_EACH_SIEVE_PRIME - free(sieve); + Safefree(sieve); } } RETVAL = newRV_noinc( (SV*) av ); @@ -230,7 +230,7 @@ erat_simple_primes(IN UV low, IN UV high) av_push(av,newSVuv( 2*s+1 )); } } - free(sieve); + Safefree(sieve); } } RETVAL = newRV_noinc( (SV*) av ); diff --git a/cache.c b/cache.c new file mode 100644 index 0000000..593564f --- /dev/null +++ b/cache.c @@ -0,0 +1,84 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ptypes.h" +#include "cache.h" +#include "sieve.h" + + +static unsigned char* prime_cache_sieve = 0; +static UV prime_cache_size = 0; + +/* Get the maximum sieved value of the cached prime sieve. */ +UV get_prime_cache_size(void) { return prime_cache_size; } + +/* + * Get the size and a pointer to the cached prime sieve. + * Returns the maximum sieved value in the sieve. + * Allocates and sieves if needed. + * + * The sieve holds 30 numbers per byte, using a mod-30 wheel. + */ +UV get_prime_cache(UV n, const unsigned char** sieve) +{ + if (prime_cache_size < n) { + + if (prime_cache_sieve != 0) + Safefree(prime_cache_sieve); + prime_cache_sieve = 0; + prime_cache_size = 0; + + /* Sieve a bit more than asked, to mitigate thrashing */ + if (n >= (UV_MAX-3840)) + n = UV_MAX; + else + n = ((n + 3840)/30)*30; + /* TODO: testing near 2^32-1 */ + + prime_cache_sieve = sieve_erat30(n); + + if (prime_cache_sieve != 0) + prime_cache_size = n; + } + + if (sieve != 0) + *sieve = prime_cache_sieve; + return prime_cache_size; +} + + + +static unsigned char* prime_segment = 0; +unsigned char* get_prime_segment(void) { + if (prime_segment == 0) + New(0, prime_segment, SEGMENT_CHUNK_SIZE, unsigned char); + if (prime_segment == 0) + croak("Could not allocate %"UVuf" bytes for segment sieve", SEGMENT_CHUNK_SIZE); + return prime_segment; +} +void free_prime_segment(void) { + if (prime_segment != 0) + Safefree(prime_segment); + prime_segment = 0; +} + + + +void _prime_memfreeall(void) +{ + if (prime_cache_sieve != 0) + Safefree(prime_cache_sieve); + prime_cache_sieve = 0; + prime_cache_size = 0; + + free_prime_segment(); +} + +void prime_memfree(void) +{ + _prime_memfreeall(); + + prime_precalc(0); +} + diff --git a/cache.h b/cache.h new file mode 100644 index 0000000..7423df2 --- /dev/null +++ b/cache.h @@ -0,0 +1,15 @@ +#ifndef MPU_CACHE_H +#define MPU_CACHE_H + +#include "EXTERN.h" +#include "perl.h" + +extern UV get_prime_cache_size(void); +extern UV get_prime_cache(UV n, const unsigned char** sieve); + +extern void prime_memfree(void); + +#define SEGMENT_CHUNK_SIZE UVCONST(262144) +extern unsigned char* get_prime_segment(void); + +#endif diff --git a/sieve.c b/sieve.c index 14092ce..e2b3662 100644 --- a/sieve.c +++ b/sieve.c @@ -6,60 +6,13 @@ #include "sieve.h" #include "ptypes.h" #include "bitarray.h" -#include "util.h" /* For freeing the segment cache */ - - -static unsigned char* prime_cache_sieve = 0; -static UV prime_cache_size = 0; - -/* Get the maximum sieved value of the cached prime sieve. */ -UV get_prime_cache_size(void) { return prime_cache_size; } - -/* - * Get the size and a pointer to the cached prime sieve. - * Returns the maximum sieved value in the sieve. - * Allocates and sieves if needed. - * - * The sieve holds 30 numbers per byte, using a mod-30 wheel. - */ -UV get_prime_cache(UV n, const unsigned char** sieve) -{ - if (prime_cache_size < n) { - - if (prime_cache_sieve != 0) - free(prime_cache_sieve); - prime_cache_sieve = 0; - prime_cache_size = 0; - - /* Sieve a bit more than asked, to mitigate thrashing */ - if (n >= (UV_MAX-3840)) - n = UV_MAX; - else - n = ((n + 3840)/30)*30; - /* TODO: testing near 2^32-1 */ - - prime_cache_sieve = sieve_erat30(n); - - if (prime_cache_sieve != 0) - prime_cache_size = n; - } - - if (sieve != 0) - *sieve = prime_cache_sieve; - return prime_cache_size; -} - void prime_precalc(UV n) { - if ( (n == 0) && (prime_cache_sieve == 0) ) { + if (n == 0) { /* On initialization, make a few primes (2-30k using 1k memory) */ - UV initial_primes_to = 30 * (1024-8); - prime_cache_sieve = sieve_erat30(initial_primes_to); - if (prime_cache_sieve != 0) - prime_cache_size = initial_primes_to; - return; + n = (1024-16)*30; } get_prime_cache(n, 0); /* Sieve to n */ @@ -67,23 +20,6 @@ void prime_precalc(UV n) /* TODO: should we prealloc the segment here? */ } -void _prime_memfreeall(void) -{ - if (prime_cache_sieve != 0) - free(prime_cache_sieve); - prime_cache_sieve = 0; - prime_cache_size = 0; - - free_prime_segment(); -} - -void prime_memfree(void) -{ - _prime_memfreeall(); - - prime_precalc(0); -} - UV* sieve_erat(UV end) @@ -92,7 +28,7 @@ UV* sieve_erat(UV end) UV n, s; UV last = (end+1)/2; - mem = (UV*) calloc( NWORDS(last), sizeof(UV) ); + Newz(0, mem, NWORDS(last), UV ); if (mem == 0) { croak("allocation failure in sieve_erat: could not alloc %"UVuf" bits", last); return 0; @@ -121,7 +57,7 @@ unsigned char* sieve_erat30(UV end) max_buf = (end/30) + ((end%30) != 0); buffer_words = (max_buf + sizeof(UV) - 1) / sizeof(UV); - mem = (unsigned char*) calloc( buffer_words, sizeof(UV) ); + Newz(0, mem, buffer_words*sizeof(UV), unsigned char ); if (mem == 0) { croak("allocation failure in sieve_erat30: could not alloc %"UVuf" bytes", (buffer_words*sizeof(UV))); return 0; diff --git a/sieve.h b/sieve.h index e693b5b..587627f 100644 --- a/sieve.h +++ b/sieve.h @@ -4,11 +4,7 @@ #include "EXTERN.h" #include "perl.h" -extern UV get_prime_cache_size(void); -extern UV get_prime_cache(UV n, const unsigned char** sieve); - extern void prime_precalc(UV x); -extern void prime_memfree(void); extern UV* sieve_erat(UV end); extern unsigned char* sieve_erat30(UV end); extern int sieve_segment(unsigned char* mem, UV startd, UV endd); diff --git a/util.c b/util.c index 5ef0459..b85fb21 100644 --- a/util.c +++ b/util.c @@ -8,28 +8,11 @@ #define INFINITY (DBL_MAX + DBL_MAX) #endif +#include "ptypes.h" #include "util.h" #include "sieve.h" #include "factor.h" -#include "ptypes.h" - -/* - * I'm undecided as to whether we want this, or just let the functions alloc - * and free it per call. - */ -static unsigned char* prime_segment = 0; -unsigned char* get_prime_segment(void) { - if (prime_segment == 0) - prime_segment = (unsigned char*) malloc( SEGMENT_CHUNK_SIZE ); - if (prime_segment == 0) - croak("Could not allocate %"UVuf" bytes for segment sieve", SEGMENT_CHUNK_SIZE); - return prime_segment; -} -void free_prime_segment(void) { - if (prime_segment != 0) - free(prime_segment); - prime_segment = 0; -} +#include "cache.h" static const unsigned char byte_zeros[256] = {8,7,7,6,7,6,6,5,7,6,6,5,6,5,5,4,7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3, diff --git a/util.h b/util.h index b4eca82..a506ec2 100644 --- a/util.h +++ b/util.h @@ -23,10 +23,6 @@ extern double ExponentialIntegral(double x); extern double LogarithmicIntegral(double x); extern double RiemannR(double x); -#define SEGMENT_CHUNK_SIZE UVCONST(262144) -extern unsigned char* get_prime_segment(void); -extern void free_prime_segment(void); - /* Above this value, is_prime will do deterministic Miller-Rabin */ /* With 64-bit math, we can do much faster mulmods from 2^16-2^32 */ #if (BITS_PER_WORD == 64) || HAVE_STD_U64 -- 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