This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
srand: change to return its seed
authorKarl Williamson <khw@khw-desktop.(none)>
Tue, 27 Jul 2010 14:18:25 +0000 (08:18 -0600)
committerRafael Garcia-Suarez <rgs@consttype.org>
Wed, 28 Jul 2010 08:07:23 +0000 (10:07 +0200)
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.

opcode.h
opcode.pl
pod/perl5134delta.pod
pod/perlfunc.pod
pp.c

index 0849839..0d85906 100644 (file)
--- 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 */
index 01db025..1dadb53 100755 (executable)
--- 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?
index 356a247..f7e76bd 100644 (file)
@@ -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
index 42095a0..affd834 100644 (file)
@@ -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 (file)
--- 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)