1 /* Mersenne Twister pseudo-random number generator functions.
3 Copyright 2002, 2003 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 MA 02110-1301, USA. */
27 /* Calculate (b^e) mod (2^n-k) for e=1074888996, n=19937 and k=20023,
28 needed by the seeding function below. */
30 mangle_seed (mpz_ptr r, mpz_srcptr b_orig)
33 unsigned long e = 0x40118124;
34 unsigned long bit = 0x20000000;
37 mpz_init_set (b, b_orig); /* in case r==b_orig */
47 mpz_tdiv_q_2exp (t, r, 19937L);
50 mpz_tdiv_r_2exp (r, r, 19937L);
51 mpz_addmul_ui (r, t, 20023L);
70 /* Seeding function. Uses powering modulo a non-Mersenne prime to obtain
71 a permutation of the input seed space. The modulus is 2^19937-20023,
72 which is probably prime. The power is 1074888996. In order to avoid
73 seeds 0 and 1 generating invalid or strange output, the input seed is
74 first manipulated as follows:
76 seed1 = seed mod (2^19937-20027) + 2
78 so that seed1 lies between 2 and 2^19937-20026 inclusive. Then the
79 powering is performed as follows:
81 seed2 = (seed1^1074888996) mod (2^19937-20023)
83 and then seed2 is used to bootstrap the buffer.
85 This method aims to give guarantees that:
86 a) seed2 will never be zero,
87 b) seed2 will very seldom have a very low population of ones in its
88 binary representation, and
89 c) every seed between 0 and 2^19937-20028 (inclusive) will yield a
94 The period of the seeding function is 2^19937-20027. This means that
95 with seeds 2^19937-20027, 2^19937-20026, ... the exact same sequences
96 are obtained as with seeds 0, 1, etc.; it also means that seed -1
97 produces the same sequence as seed 2^19937-20028, etc.
101 randseed_mt (gmp_randstate_t rstate, mpz_srcptr seed)
106 gmp_rand_mt_struct *p;
107 mpz_t mod; /* Modulus. */
108 mpz_t seed1; /* Intermediate result. */
110 p = (gmp_rand_mt_struct *) RNG_STATE (rstate);
115 mpz_set_ui (mod, 0L);
116 mpz_setbit (mod, 19937L);
117 mpz_sub_ui (mod, mod, 20027L);
118 mpz_mod (seed1, seed, mod); /* Reduce `seed' modulo `mod'. */
119 mpz_add_ui (seed1, seed1, 2L); /* seed1 is now ready. */
120 mangle_seed (seed1, seed1); /* Perform the mangling by powering. */
122 /* Copy the last bit into bit 31 of mt[0] and clear it. */
123 p->mt[0] = (mpz_tstbit (seed1, 19936L) != 0) ? 0x80000000 : 0;
124 mpz_clrbit (seed1, 19936L);
126 /* Split seed1 into N-1 32-bit chunks. */
127 mpz_export (&p->mt[1], &cnt, -1, sizeof (p->mt[1]), 0,
128 8 * sizeof (p->mt[1]) - 32, seed1);
137 /* Warm the generator up if necessary. */
139 for (i = 0; i < WARM_UP / N; i++)
140 __gmp_mt_recalc_buffer (p->mt);
142 p->mti = WARM_UP % N;
146 static const gmp_randfnptr_t Mersenne_Twister_Generator = {
153 /* Initialize MT-specific data. */
155 gmp_randinit_mt (gmp_randstate_t rstate)
157 __gmp_randinit_mt_noseed (rstate);
158 RNG_FNPTR (rstate) = (void *) &Mersenne_Twister_Generator;