From savicky at cs.cas.cz  Sun Sep 23 12:43:48 2007
From: savicky at cs.cas.cz (Petr Savicky)
Date: Sun, 23 Sep 2007 12:43:48 +0200
Subject: [Rd] initial scrambling of seed in do_setseed / RNG_Init
Message-ID: <20070923104348.GA2032@cs.cas.cz>

I would like to suggest a modification of initial scrambling of the
seed in RNG_Init (called from do_setseed). The modified code is
equivalent, but faster. Patch against R-devel_2007-09-22 follows

--- R-devel-orig/src/main/RNG.c	2007-09-02 07:49:35.000000000 +0200
+++ R-devel-modif/src/main/RNG.c	2007-09-23 10:51:59.234566440 +0200
@@ -216,8 +216,8 @@
     BM_norm_keep = 0.0; /* zap Box-Muller history */
 
     /* Initial scrambling */
-    for(j = 0; j < 50; j++)
-	seed = (69069 * seed + 1);
+    /* Equivalent to 50 iterations of seed = (69069 * seed + 1) */
+    seed = (1100682473U * seed + 2358491998U);
     switch(kind) {
     case WICHMANN_HILL:
     case MARSAGLIA_MULTICARRY:

Let me add also the following remark. The help(Random.user) page says

     Optionally, the user can supply the entry point 'user_unif_init',
     which is called with an 'unsigned int' argument when 'RNGkind' (or
     'set.seed') is called, and is intended to be used to initialize
     the user's RNG code. The argument is intended to be used to set
     the "seeds"; it is the 'seed' argument to 'set.seed' or an
     essentially random seed if 'RNGkind' is called.

I want to comment on the sentence
   The argument is intended to be used to set
   the "seeds"; it is the 'seed' argument to 'set.seed' or ....
This is not correct. If user_unif_init is called from set.seed, then
it receives the argument of set.seed after the initial scrambling.
If someone writes a user defined generator and wishes to get the original
seed specified in set.seed (which is my situation), then it may be useful
for him to know that the transformation 
  seed = 3602842457U * (seed - 2358491998U);
is the inverse to the initial scrambling. Hence, if it is applied to the
value received by user_unif_init, it provides the original value specified
by the user in set.seed.

Let me point out that the initial scrambling does not eliminate seed 0.
It only decreases the probability that this seed is sent to the generator.
Due to scrambling, the entry point user_unif_init receives 0 not as a
consequence of set.seed(0), but as a consequence of set.seed(105890386).
This is less likely, but still possible.

I suggest to clarify the page help(Random.user) concerning the transformation
of the seed. For example, the sentence
  it is the 'seed' argument to 'set.seed'
may be extended to
  it is the 'seed' argument to 'set.seed' after a transformation described
  in function RNG_Init in src/main/RNG.c

Also, a remark concerning the inverse transformation may be add. In my opinion,
the best way to do this could be to add a comment to RNG_Init in src/main/RNG.c,
saying, for example:
  If you need to undo the initial scrambling in user_unif_init, use
  seed = 3602842457U * (seed - 2358491998U);

Petr Savicky.



[Rd] initial scrambling of seed in do_setseed / RNG_Init
Petr Savicky