summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Williamson <khw@khw-desktop.(none)>2010-07-27 08:18:25 -0600
committerRafael Garcia-Suarez <rgs@consttype.org>2010-07-28 10:07:23 +0200
commit83832992940e343002e924b1307988d2604ee165 (patch)
tree6ead241b56a400abd516361b20cf2236859d75c4
parent401a9b146916c60dc9bbd897355c3c83888d61f3 (diff)
downloadperl-83832992940e343002e924b1307988d2604ee165.tar.gz
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.
-rw-r--r--opcode.h2
-rwxr-xr-xopcode.pl2
-rw-r--r--pod/perl5134delta.pod10
-rw-r--r--pod/perlfunc.pod51
-rw-r--r--pp.c6
5 files changed, 43 insertions, 28 deletions
diff --git a/opcode.h b/opcode.h
index 0849839c7a..0d859062a6 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 01db025242..1dadb5358a 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 356a247e01..f7e76bd923 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 42095a0a25..affd834fe0 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 129c94811f..ec585ab933 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)