In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/1c761d95ce3e122676f2110e57e721b7689cd4c2?hp=401a9b146916c60dc9bbd897355c3c83888d61f3>
- Log ----------------------------------------------------------------- commit 1c761d95ce3e122676f2110e57e721b7689cd4c2 Author: Rafael Garcia-Suarez <[email protected]> Date: Wed Jul 28 10:25:47 2010 +0200 Add a test for srand's return value M t/op/srand.t commit 83832992940e343002e924b1307988d2604ee165 Author: Karl Williamson <k...@khw-desktop.(none)> Date: Tue Jul 27 08:18:25 2010 -0600 srand: change to return its seed This commit changes srand to to return the seed instead of always returning 1. The motivation behind this is to allow applications to not have to come up with their own pseudo-random generator if they want repeatable results. The previous return behavior has never been documented. Note that it is possible, but very unlikely, for the seed to end up being 0, which means that if someone were relying on the undocumented previous behavior of srand returning true, that in very rare instances it would return 0, failing, and the next time they ran it, it would succeed, possibly leading to puzzlement and very rare unexplained failures. M opcode.h M opcode.pl M pod/perl5134delta.pod M pod/perlfunc.pod M pp.c ----------------------------------------------------------------------- Summary of changes: opcode.h | 2 +- opcode.pl | 2 +- pod/perl5134delta.pod | 10 +++++++++ pod/perlfunc.pod | 51 ++++++++++++++++++++++++++---------------------- pp.c | 6 ++-- t/op/srand.t | 6 ++++- 6 files changed, 48 insertions(+), 29 deletions(-) diff --git a/opcode.h b/opcode.h index 0849839..0d85906 100644 --- a/opcode.h +++ b/opcode.h @@ -1658,7 +1658,7 @@ EXTCONST U32 PL_opargs[] = { 0x0001378e, /* sin */ 0x0001378e, /* cos */ 0x0001370c, /* rand */ - 0x00013604, /* srand */ + 0x0001370c, /* srand */ 0x0001378e, /* exp */ 0x0001378e, /* log */ 0x0001378e, /* sqrt */ diff --git a/opcode.pl b/opcode.pl index 01db025..1dadb53 100755 --- a/opcode.pl +++ b/opcode.pl @@ -757,7 +757,7 @@ atan2 atan2 ck_fun fsT@ S S sin sin ck_fun fsTu% S? cos cos ck_fun fsTu% S? rand rand ck_fun sT% S? -srand srand ck_fun s% S? +srand srand ck_fun sT% S? exp exp ck_fun fsTu% S? log log ck_fun fsTu% S? sqrt sqrt ck_fun fsTu% S? diff --git a/pod/perl5134delta.pod b/pod/perl5134delta.pod index 356a247..f7e76bd 100644 --- a/pod/perl5134delta.pod +++ b/pod/perl5134delta.pod @@ -38,6 +38,16 @@ C<\N{}>, C<charnames::vianame>, C<charnames::viacode> now know about every character in Unicode. Previously, they didn't know about the Hangul syllables nor a number of CJK (Chinese/Japanese/Korean) characters. +=head2 C<srand()> now returns the seed + +This allows programs which need to have repeatable results to not have to come +up with their own seed generating mechanism. Instead, they can use C<srand()> +and somehow stash the return for future use. Typical is a test program which +has too many combinations to test comprehensively in the time available to it +each run. It can test a random subset each time, and should there be a +failure, log the seed used for that run so that it can later be used to +reproduce the exact results. + =head1 Security XXX Any security-related notices go here. In particular, any security diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index 42095a0..affd834 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -6157,34 +6157,34 @@ X<srand> X<seed> X<randseed> =item srand -Sets the random number seed for the C<rand> operator. +Sets and returns the random number seed for the C<rand> operator. The point of the function is to "seed" the C<rand> function so that C<rand> can produce a different sequence each time you run your -program. - -If srand() is not called explicitly, it is called implicitly at the -first use of the C<rand> operator. However, this was not true of -versions of Perl before 5.004, so if your script will run under older -Perl versions, it should call C<srand>. - -Most programs won't even call srand() at all, except those that -need a cryptographically-strong starting point rather than the -generally acceptable default, which is based on time of day, -process ID, and memory allocation, or the F</dev/urandom> device -if available. You may also want to call srand() after a fork() to -avoid child processes sharing the same seed value as the parent (and -consequently each other). - -You can call srand($seed) with the same $seed to reproduce the -I<same> sequence from rand(), but this is usually reserved for -generating predictable results for testing or debugging. -Otherwise, don't call srand() more than once in your program. - -Do B<not> call srand() (i.e., without an argument) more than once per +program. When called with a parameter, C<srand> uses that for the seed; +otherwise it (semi-)randomly chooses a seed. In either case, starting with +Perl 5.14, it returns the seed. + +If C<srand()> is not called explicitly, it is called implicitly without a +parameter at the first use of the C<rand> operator. However, this was not true +of versions of Perl before 5.004, so if your script will run under older +Perl versions, it should call C<srand>; otherwise most programs won't call +C<srand()> at all. + +But there are a few situations in recent Perls where programs are likely to +want to call C<srand>. One is for generating predictable results generally for +testing or debugging. There, you use C<srand($seed)>, with the same C<$seed> +each time. Another other case is where you need a cryptographically-strong +starting point rather than the generally acceptable default, which is based on +time of day, process ID, and memory allocation, or the F</dev/urandom> device +if available. And still another case is that you may want to call C<srand()> +after a C<fork()> to avoid child processes sharing the same seed value as the +parent (and consequently each other). + +Do B<not> call C<srand()> (i.e., without an argument) more than once per process. The internal state of the random number generator should contain more entropy than can be provided by any seed, so calling -srand() again actually I<loses> randomness. +C<srand()> again actually I<loses> randomness. Most implementations of C<srand> take an integer and will silently truncate decimal numbers. This means C<srand(42)> will usually @@ -6216,6 +6216,11 @@ for a seed can fall prey to the mathematical property that one-third of the time. So don't do that. +A typical use of the returned seed is for a test program which has too many +combinations to test comprehensively in the time available to it each run. It +can test a random subset each time, and should there be a failure, log the seed +used for that run so that it can later be used to reproduce the exact results. + =item stat FILEHANDLE X<stat> X<file, status> X<ctime> diff --git a/pp.c b/pp.c index 129c948..ec585ab 100644 --- a/pp.c +++ b/pp.c @@ -2950,12 +2950,12 @@ PP(pp_rand) PP(pp_srand) { - dVAR; dSP; + dVAR; dSP; dTARGET; const UV anum = (MAXARG < 1) ? seed() : POPu; (void)seedDrand01((Rand_seed_t)anum); PL_srand_called = TRUE; - EXTEND(SP, 1); - RETPUSHYES; + XPUSHu(anum); + RETURN; } PP(pp_int) diff --git a/t/op/srand.t b/t/op/srand.t index 5753a5d..34fa9af 100644 --- a/t/op/srand.t +++ b/t/op/srand.t @@ -10,7 +10,7 @@ BEGIN { use strict; require "test.pl"; -plan(tests => 4); +plan(tests => 5); # Generate a load of random numbers. # int() avoids possible floating point error. @@ -57,3 +57,7 @@ sleep(1); # in case our srand() is too time-dependent @second_run = `$^X -le "print int rand 100 for 1..100"`; ok( !eq_array(\...@first_run, \...@second_run), 'srand() called automatically'); + +# check srand's return value +my $seed = srand(1764); +is( $seed, 1764, "return value" ); -- Perl5 Master Repository
