diff --git a/Basic/Core/Core.xs b/Basic/Core/Core.xs index 5ab0d8e1d..231ebfa15 100644 --- a/Basic/Core/Core.xs +++ b/Basic/Core/Core.xs @@ -212,6 +212,13 @@ _inf(...) MODULE = PDL::Core PACKAGE = PDL::Core +IV +seed() + CODE: + RETVAL = pdl_pdl_seed(); + OUTPUT: + RETVAL + int online_cpus() CODE: diff --git a/Basic/Core/pdlcore.c b/Basic/Core/pdlcore.c index 6bb6e2b5b..4281c9be7 100644 --- a/Basic/Core/pdlcore.c +++ b/Basic/Core/pdlcore.c @@ -1190,3 +1190,23 @@ pdl_slice_args* pdl_slice_args_parse(SV* sv) { PDLDEBUG_f(pdl_dump_slice_args(retval)); return retval; } + +/* pdl_seed() - prefix as "seed" #define-d by Perl + * + * Used to seed PDL's built-in RNG. + */ +uint64_t pdl_pdl_seed() { + /* This implementation is from section 7.1 Seeding of + * + * Helmut G. Katzgraber. "Random Numbers in Scientific Computing: + * An Introduction". . + */ + uint64_t s, pid; + /* Start of Perl-specific symbols */ + Time_t seconds; + pid = (uint64_t)PerlProc_getpid(); + (void)time(&seconds); + /* End of Perl-specific symbols */ + s = (uint64_t)seconds; + return abs(((s*181)*((pid-83)*359))%104729); +} diff --git a/Basic/Core/pdlcore.h b/Basic/Core/pdlcore.h index 17acdd687..6eae52a6f 100644 --- a/Basic/Core/pdlcore.h +++ b/Basic/Core/pdlcore.h @@ -12,6 +12,8 @@ #include "XSUB.h" /* for the win32 perlCAPI crap */ #include "ppport.h" /* include this AFTER XSUB.h */ +#include + #if defined(CONTEXT) && defined(__osf__) #undef CONTEXT #endif @@ -127,7 +129,8 @@ void pdl_readdata_vaffine(pdl *it); X(slice_args_parse_string, pdl_slice_args, ( char* )) \ X(slice_args_parse, pdl_slice_args*, ( SV* )) \ X(online_cpus, int, ()) \ - X(magic_get_thread, int, (pdl *)) + X(magic_get_thread, int, (pdl *)) \ + X(pdl_seed, uint64_t, ()) /*************** Function prototypes *********************/ #define X(sym, rettype, args) \ diff --git a/Basic/Primitive/primitive.pd b/Basic/Primitive/primitive.pd index bceece9d7..3edc4e068 100644 --- a/Basic/Primitive/primitive.pd +++ b/Basic/Primitive/primitive.pd @@ -2008,7 +2008,7 @@ void pdl_srand(uint64_t **s, uint64_t seed, int n); double pdl_drand(uint64_t *s); #define PDL_MAYBE_SRAND \ if (pdl_srand_threads < 0) \ - pdl_srand(&pdl_rand_state, (uint64_t)time(NULL), PDL->online_cpus()); + pdl_srand(&pdl_rand_state, PDL->pdl_seed(), PDL->online_cpus()); #define PDL_RAND_SET_OFFSET(v, thr, pdl) \ if (v < 0) \ v = thr.mag_nthr >= 0 ? PDL->magic_get_thread(pdl) % PDL->online_cpus() : 0 @@ -2038,11 +2038,7 @@ L. EOF PMCode=><<'EOD', *srand = \&PDL::srand; -sub PDL::srand { - my $pdl = shift; - $pdl //= longlong(time); - PDL::_srand_int($pdl); -} +sub PDL::srand { PDL::_srand_int($_[0] // PDL::Core::seed()) } EOD ); diff --git a/Changes b/Changes index ea81e88ce..57726729c 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,5 @@ +- PDL::Core::seed - thanks @zmughal + 2.062 2021-11-19 - Primitive::srand() added, random() calls if not done yet - thanks @whumann for report - Primitive::random() et al to use xoroshiro256plus instead of Perl's rand()