Petr Savicky
2007-Sep-23 10:43 UTC
[Rd] initial scrambling of seed in do_setseed / RNG_Init
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.