xref: /netbsd-src/external/lgpl3/gmp/dist/rand/randmt.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
1 /* Mersenne Twister pseudo-random number generator functions.
2 
3    THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY.  THEY'RE ALMOST
4    CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
5    FUTURE GNU MP RELEASES.
6 
7 Copyright 2002, 2003, 2006 Free Software Foundation, Inc.
8 
9 This file is part of the GNU MP Library.
10 
11 The GNU MP Library is free software; you can redistribute it and/or modify
12 it under the terms of either:
13 
14   * the GNU Lesser General Public License as published by the Free
15     Software Foundation; either version 3 of the License, or (at your
16     option) any later version.
17 
18 or
19 
20   * the GNU General Public License as published by the Free Software
21     Foundation; either version 2 of the License, or (at your option) any
22     later version.
23 
24 or both in parallel, as here.
25 
26 The GNU MP Library is distributed in the hope that it will be useful, but
27 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
28 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
29 for more details.
30 
31 You should have received copies of the GNU General Public License and the
32 GNU Lesser General Public License along with the GNU MP Library.  If not,
33 see https://www.gnu.org/licenses/.  */
34 
35 #include <stdio.h>   /* for NULL */
36 
37 #include "gmp-impl.h"
38 #include "randmt.h"
39 
40 
41 /* This code implements the Mersenne Twister pseudorandom number generator
42    by Takuji Nishimura and Makoto Matsumoto.  The buffer initialization
43    function is different in order to permit seeds greater than 2^32-1.
44 
45    This file contains a special __gmp_randinit_mt_noseed which excludes the
46    seeding function from the gmp_randfnptr_t routines.  This is for use by
47    mpn_random and mpn_random2 on the global random generator.  MT seeding
48    uses mpz functions, and we don't want mpn routines dragging mpz functions
49    into the link.  */
50 
51 
52 /* Default seed to use when the generator is not initialized.  */
53 #define DEFAULT_SEED 5489 /* was 4357 */
54 
55 /* Tempering masks.  */
56 #define MASK_1 0x9D2C5680
57 #define MASK_2 0xEFC60000
58 
59 /* Initial state of buffer when initialized with default seed.  */
60 static const gmp_uint_least32_t default_state[N] =
61 {
62   0xD247B233,0x9E5AA8F1,0x0FFA981B,0x9DCB0980,0x74200F2B,0xA576D044,
63   0xE9F05ADF,0x1538BFF5,0x59818BBF,0xCF9E58D8,0x09FCE032,0x6A1C663F,
64   0x5116E78A,0x69B3E0FA,0x6D92D665,0xD0A8BE98,0xF669B734,0x41AC1B68,
65   0x630423F1,0x4B8D6B8A,0xC2C46DD7,0x5680747D,0x43703E8F,0x3B6103D2,
66   0x49E5EB3F,0xCBDAB4C1,0x9C988E23,0x747BEE0B,0x9111E329,0x9F031B5A,
67   0xECCA71B9,0x2AFE4EF8,0x8421C7ED,0xAC89AFF1,0xAED90DF3,0x2DD74F01,
68   0x14906A13,0x75873FA9,0xFF83F877,0x5028A0C9,0x11B4C41D,0x7CAEDBC4,
69   0x8672D0A7,0x48A7C109,0x8320E59F,0xBC0B3D5F,0x75A30886,0xF9E0D128,
70   0x41AF7580,0x239BB94D,0xC67A3C81,0x74EEBD6E,0xBC02B53C,0x727EA449,
71   0x6B8A2806,0x5853B0DA,0xBDE032F4,0xCE234885,0x320D6145,0x48CC053F,
72   0x00DBC4D2,0xD55A2397,0xE1059B6F,0x1C3E05D1,0x09657C64,0xD07CB661,
73   0x6E982E34,0x6DD1D777,0xEDED1071,0xD79DFD65,0xF816DDCE,0xB6FAF1E4,
74   0x1C771074,0x311835BD,0x18F952F7,0xF8F40350,0x4ECED354,0x7C8AC12B,
75   0x31A9994D,0x4FD47747,0xDC227A23,0x6DFAFDDF,0x6796E748,0x0C6F634F,
76   0xF992FA1D,0x4CF670C9,0x067DFD31,0xA7A3E1A5,0x8CD7D9DF,0x972CCB34,
77   0x67C82156,0xD548F6A8,0x045CEC21,0xF3240BFB,0xDEF656A7,0x43DE08C5,
78   0xDAD1F92F,0x3726C56B,0x1409F19A,0x942FD147,0xB926749C,0xADDC31B8,
79   0x53D0D869,0xD1BA52FE,0x6722DF8C,0x22D95A74,0x7DC1B52A,0x1DEC6FD5,
80   0x7262874D,0x0A725DC9,0xE6A8193D,0xA052835A,0xDC9AD928,0xE59EBB90,
81   0x70DBA9FF,0xD612749D,0x5A5A638C,0x6086EC37,0x2A579709,0x1449EA3A,
82   0xBC8E3C06,0x2F900666,0xFBE74FD1,0x6B35B911,0xF8335008,0xEF1E979D,
83   0x738AB29D,0xA2DC0FDC,0x7696305D,0xF5429DAC,0x8C41813B,0x8073E02E,
84   0xBEF83CCD,0x7B50A95A,0x05EE5862,0x00829ECE,0x8CA1958C,0xBE4EA2E2,
85   0x4293BB73,0x656F7B23,0x417316D8,0x4467D7CF,0x2200E63B,0x109050C8,
86   0x814CBE47,0x36B1D4A8,0x36AF9305,0x308327B3,0xEBCD7344,0xA738DE27,
87   0x5A10C399,0x4142371D,0x64A18528,0x0B31E8B2,0x641057B9,0x6AFC363B,
88   0x108AD953,0x9D4DA234,0x0C2D9159,0x1C8A1A1F,0x310C66BA,0x87AA1070,
89   0xDAC832FF,0x0A433422,0x7AF15812,0x2D8D9BD0,0x995A25E9,0x25326CAC,
90   0xA34384DB,0x4C8421CC,0x4F0315EC,0x29E8649E,0xA7732D6F,0x2E94D3E3,
91   0x7D98A340,0x397C4D74,0x659DB4DE,0x747D4E9A,0xD9DB8435,0x4659DBE9,
92   0x313E6DC5,0x29D104DC,0x9F226CBA,0x452F18B0,0xD0BC5068,0x844CA299,
93   0x782B294E,0x4AE2EB7B,0xA4C475F8,0x70A81311,0x4B3E8BCC,0x7E20D4BA,
94   0xABCA33C9,0x57BE2960,0x44F9B419,0x2E567746,0x72EB757A,0x102CC0E8,
95   0xB07F32B9,0xD0DABD59,0xBA85AD6B,0xF3E20667,0x98D77D81,0x197AFA47,
96   0x518EE9AC,0xE10CE5A2,0x01CF2C2A,0xD3A3AF3D,0x16DDFD65,0x669232F8,
97   0x1C50A301,0xB93D9151,0x9354D3F4,0x847D79D0,0xD5FE2EC6,0x1F7B0610,
98   0xFA6B90A5,0xC5879041,0x2E7DC05E,0x423F1F32,0xEF623DDB,0x49C13280,
99   0x98714E92,0xC7B6E4AD,0xC4318466,0x0737F312,0x4D3C003F,0x9ACC1F1F,
100   0x5F1C926D,0x085FA771,0x185A83A2,0xF9AA159D,0x0B0B0132,0xF98E7A43,
101   0xCD9EBDBE,0x0190CB29,0x10D93FB6,0x3B8A4D97,0x66A65A41,0xE43E766F,
102   0x77BE3C41,0xB9686364,0xCB36994D,0x6846A287,0x567E77F7,0x36178DD8,
103   0xBDE6B1F2,0xB6EFDC64,0x82950324,0x42053F47,0xC09BE51C,0x0942D762,
104   0x35F92C7F,0x367DEC61,0x6EE3D983,0xDBAAF78A,0x265D2C47,0x8EB4BF5C,
105   0x33B232D7,0xB0137E77,0x373C39A7,0x8D2B2E76,0xC7510F01,0x50F9E032,
106   0x7B1FDDDB,0x724C2AAE,0xB10ECB31,0xCCA3D1B8,0x7F0BCF10,0x4254BBBD,
107   0xE3F93B97,0x2305039B,0x53120E22,0x1A2F3B9A,0x0FDDBD97,0x0118561E,
108   0x0A798E13,0x9E0B3ACD,0xDB6C9F15,0xF512D0A2,0x9E8C3A28,0xEE2184AE,
109   0x0051EC2F,0x2432F74F,0xB0AA66EA,0x55128D88,0xF7D83A38,0x4DAE8E82,
110   0x3FDC98D6,0x5F0BD341,0x7244BE1D,0xC7B48E78,0x2D473053,0x43892E20,
111   0xBA0F1F2A,0x524D4895,0x2E10BCB1,0x4C372D81,0x5C3E50CD,0xCF61CC2E,
112   0x931709AB,0x81B3AEFC,0x39E9405E,0x7FFE108C,0x4FBB3FF8,0x06ABE450,
113   0x7F5BF51E,0xA4E3CDFD,0xDB0F6C6F,0x159A1227,0x3B9FED55,0xD20B6F7F,
114   0xFBE9CC83,0x64856619,0xBF52B8AF,0x9D7006B0,0x71165BC6,0xAE324AEE,
115   0x29D27F2C,0x794C2086,0x74445CE2,0x782915CC,0xD4CE6886,0x3289AE7C,
116   0x53DEF297,0x4185F7ED,0x88B72400,0x3C09DC11,0xBCE3AAB6,0x6A75934A,
117   0xB267E399,0x000DF1BF,0x193BA5E2,0xFA3E1977,0x179E14F6,0x1EEDE298,
118   0x691F0B06,0xB84F78AC,0xC1C15316,0xFFFF3AD6,0x0B457383,0x518CD612,
119   0x05A00F3E,0xD5B7D275,0x4C5ECCD7,0xE02CD0BE,0x5558E9F2,0x0C89BBF0,
120   0xA3D96227,0x2832D2B2,0xF667B897,0xD4556554,0xF9D2F01F,0xFA1E3FAE,
121   0x52C2E1EE,0xE5451F31,0x7E849729,0xDABDB67A,0x54BF5E7E,0xF831C271,
122   0x5F1A17E3,0x9D140AFE,0x92741C47,0x48CFABCE,0x9CBBE477,0x9C3EE57F,
123   0xB07D4C39,0xCC21BCE2,0x697708B1,0x58DA2A6B,0x2370DB16,0x6E641948,
124   0xACC5BD52,0x868F24CC,0xCA1DB0F5,0x4CADA492,0x3F443E54,0xC4A4D5E9,
125   0xF00AD670,0xE93C86E0,0xFE90651A,0xDDE532A3,0xA66458DF,0xAB7D7151,
126   0x0E2E775F,0xC9109F99,0x8D96D59F,0x73CEF14C,0xC74E88E9,0x02712DC0,
127   0x04F41735,0x2E5914A2,0x59F4B2FB,0x0287FC83,0x80BC0343,0xF6B32559,
128   0xC74178D4,0xF1D99123,0x383CCC07,0xACC0637D,0x0863A548,0xA6FCAC85,
129   0x2A13EFF0,0xAF2EEDB1,0x41E72750,0xE0C6B342,0x5DA22B46,0x635559E0,
130   0xD2EA40AC,0x10AA98C0,0x19096497,0x112C542B,0x2C85040C,0xA868E7D0,
131   0x6E260188,0xF596D390,0xC3BB5D7A,0x7A2AA937,0xDFD15032,0x6780AE3B,
132   0xDB5F9CD8,0x8BD266B0,0x7744AF12,0xB463B1B0,0x589629C9,0xE30DBC6E,
133   0x880F5569,0x209E6E16,0x9DECA50C,0x02987A57,0xBED3EA57,0xD3A678AA,
134   0x70DD030D,0x0CFD9C5D,0x92A18E99,0xF5740619,0x7F6F0A7D,0x134CAF9A,
135   0x70F5BAE4,0x23DCA7B5,0x4D788FCD,0xC7F07847,0xBCF77DA1,0x9071D568,
136   0xFC627EA1,0xAE004B77,0x66B54BCB,0x7EF2DAAC,0xDCD5AC30,0xB9BDF730,
137   0x505A97A7,0x9D881FD3,0xADB796CC,0x94A1D202,0x97535D7F,0x31EC20C0,
138   0xB1887A98,0xC1475069,0xA6F73AF3,0x71E4E067,0x46A569DE,0xD2ADE430,
139   0x6F0762C7,0xF50876F4,0x53510542,0x03741C3E,0x53502224,0xD8E54D60,
140   0x3C44AB1A,0x34972B46,0x74BFA89D,0xD7D768E0,0x37E605DC,0xE13D1BDF,
141   0x5051C421,0xB9E057BE,0xB717A14C,0xA1730C43,0xB99638BE,0xB5D5F36D,
142   0xE960D9EA,0x6B1388D3,0xECB6D3B6,0xBDBE8B83,0x2E29AFC5,0x764D71EC,
143   0x4B8F4F43,0xC21DDC00,0xA63F657F,0x82678130,0xDBF535AC,0xA594FC58,
144   0x942686BC,0xBD9B657B,0x4A0F9B61,0x44FF184F,0x38E10A2F,0x61910626,
145   0x5E247636,0x7106D137,0xC62802F0,0xBD1D1F00,0x7CC0DCB2,0xED634909,
146   0xDC13B24E,0x9799C499,0xD77E3D6A,0x14773B68,0x967A4FB7,0x35EECFB1,
147   0x2A5110B8,0xE2F0AF94,0x9D09DEA5,0x20255D27,0x5771D34B,0xE1089EE4,
148   0x246F330B,0x8F7CAEE5,0xD3064712,0x75CAFBEE,0xB94F7028,0xED953666,
149   0x5D1975B4,0x5AF81271,0x13BE2025,0x85194659,0x30805331,0xEC9D46C0,
150   0xBC027C36,0x2AF84188,0xC2141B80,0xC02B1E4A,0x04D36177,0xFC50E9D7,
151   0x39CE79DA,0x917E0A00,0xEF7A0BF4,0xA98BD8D1,0x19424DD2,0x9439DF1F,
152   0xC42AF746,0xADDBE83E,0x85221F0D,0x45563E90,0x9095EC52,0x77887B25,
153   0x8AE46064,0xBD43B71A,0xBB541956,0x7366CF9D,0xEE8E1737,0xB5A727C9,
154   0x5076B3E7,0xFC70BACA,0xCE135B75,0xC4E91AA3,0xF0341911,0x53430C3F,
155   0x886B0824,0x6BB5B8B7,0x33E21254,0xF193B456,0x5B09617F,0x215FFF50,
156   0x48D97EF1,0x356479AB,0x6EA9DDC4,0x0D352746,0xA2F5CE43,0xB226A1B3,
157   0x1329EA3C,0x7A337CC2,0xB5CCE13D,0x563E3B5B,0x534E8E8F,0x561399C9,
158   0xE1596392,0xB0F03125,0x4586645B,0x1F371847,0x94EAABD1,0x41F97EDD,
159   0xE3E5A39B,0x71C774E2,0x507296F4,0x5960133B,0x7852C494,0x3F5B2691,
160   0xA3F87774,0x5A7AF89E,0x17DA3F28,0xE9D9516D,0xFCC1C1D5,0xE4618628,
161   0x04081047,0xD8E4DB5F,0xDC380416,0x8C4933E2,0x95074D53,0xB1B0032D,
162   0xCC8102EA,0x71641243,0x98D6EB6A,0x90FEC945,0xA0914345,0x6FAB037D,
163   0x70F49C4D,0x05BF5B0E,0x927AAF7F,0xA1940F61,0xFEE0756F,0xF815369F,
164   0x5C00253B,0xF2B9762F,0x4AEB3CCC,0x1069F386,0xFBA4E7B9,0x70332665,
165   0x6BCA810E,0x85AB8058,0xAE4B2B2F,0x9D120712,0xBEE8EACB,0x776A1112
166 };
167 
168 void
__gmp_mt_recalc_buffer(gmp_uint_least32_t mt[])169 __gmp_mt_recalc_buffer (gmp_uint_least32_t mt[])
170 {
171   gmp_uint_least32_t y;
172   int kk;
173 
174   for (kk = 0; kk < N - M; kk++)
175     {
176       y = (mt[kk] & 0x80000000) | (mt[kk + 1] & 0x7FFFFFFF);
177       mt[kk] = mt[kk + M] ^ (y >> 1) ^ ((y & 0x01) != 0 ? MATRIX_A : 0);
178     }
179   for (; kk < N - 1; kk++)
180     {
181       y = (mt[kk] & 0x80000000) | (mt[kk + 1] & 0x7FFFFFFF);
182       mt[kk] = mt[kk - (N - M)] ^ (y >> 1) ^ ((y & 0x01) != 0 ? MATRIX_A : 0);
183     }
184 
185   y = (mt[N - 1] & 0x80000000) | (mt[0] & 0x7FFFFFFF);
186   mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ ((y & 0x01) != 0 ? MATRIX_A : 0);
187 }
188 
189 
190 /* Get nbits bits of output from the generator into dest.
191    Note that Mersenne Twister is designed to produce outputs in
192    32-bit words.  */
193 void
__gmp_randget_mt(gmp_randstate_t rstate,mp_ptr dest,unsigned long int nbits)194 __gmp_randget_mt (gmp_randstate_t rstate, mp_ptr dest, unsigned long int nbits)
195 {
196   gmp_uint_least32_t y;
197   int rbits;
198   mp_size_t i;
199   mp_size_t nlimbs;
200   int *pmti;
201   gmp_uint_least32_t *mt;
202 
203   pmti = &((gmp_rand_mt_struct *) RNG_STATE (rstate))->mti;
204   mt = ((gmp_rand_mt_struct *) RNG_STATE (rstate))->mt;
205 
206   nlimbs = nbits / GMP_NUMB_BITS;
207   rbits = nbits % GMP_NUMB_BITS;
208 
209 #define NEXT_RANDOM			\
210   do					\
211     {					\
212       if (*pmti >= N)			\
213 	{				\
214 	  __gmp_mt_recalc_buffer (mt);  \
215 	  *pmti = 0;			\
216 	}				\
217       y = mt[(*pmti)++];		\
218       y ^= (y >> 11);			\
219       y ^= (y << 7) & MASK_1;		\
220       y ^= (y << 15) & MASK_2;		\
221       y ^= (y >> 18);			\
222     }					\
223   while (0)
224 
225 
226   /* Handle the common cases of 32- or 64-bit limbs with fast,
227      optimized routines, and the rest of cases with a general
228      routine.  In all cases, no more than 31 bits are rejected
229      for the last limb so that every version of the code is
230      consistent with the others.  */
231 
232 #if (GMP_NUMB_BITS == 32)
233 
234   for (i = 0; i < nlimbs; i++)
235     {
236       NEXT_RANDOM;
237       dest[i] = (mp_limb_t) y;
238     }
239   if (rbits)
240     {
241       NEXT_RANDOM;
242       dest[nlimbs] = (mp_limb_t) (y & ~(ULONG_MAX << rbits));
243     }
244 
245 #else /* GMP_NUMB_BITS != 32 */
246 #if (GMP_NUMB_BITS == 64)
247 
248   for (i = 0; i < nlimbs; i++)
249     {
250       NEXT_RANDOM;
251       dest[i] = (mp_limb_t) y;
252       NEXT_RANDOM;
253       dest[i] |= (mp_limb_t) y << 32;
254     }
255   if (rbits)
256     {
257       if (rbits < 32)
258 	{
259 	  NEXT_RANDOM;
260 	  dest[nlimbs] = (mp_limb_t) (y & ~(ULONG_MAX << rbits));
261 	}
262       else
263 	{
264 	  NEXT_RANDOM;
265 	  dest[nlimbs] = (mp_limb_t) y;
266 	  if (rbits > 32)
267 	    {
268 	      NEXT_RANDOM;
269 	      dest[nlimbs] |=
270 		((mp_limb_t) (y & ~(ULONG_MAX << (rbits-32)))) << 32;
271 	    }
272 	}
273     }
274 
275 #else /* GMP_NUMB_BITS != 64 */
276 
277   {
278     /* Fall back to a general algorithm.  This algorithm works by
279        keeping a pool of up to 64 bits (2 outputs from MT) acting
280        as a shift register from which bits are consumed as needed.
281        Bits are consumed using the LSB bits of bitpool_l, and
282        inserted via bitpool_h and shifted to the right place.  */
283 
284     gmp_uint_least32_t bitpool_h = 0;
285     gmp_uint_least32_t bitpool_l = 0;
286     int bits_in_pool = 0;	/* Holds number of valid bits in the pool.  */
287     int bits_to_fill;		/* Holds total number of bits to put in
288 				   destination.  */
289     int bitidx;			/* Holds the destination bit position.  */
290     mp_size_t nlimbs2;		/* Number of whole+partial limbs to fill.  */
291 
292     nlimbs2 = nlimbs + (rbits != 0);
293 
294     for (i = 0; i < nlimbs2; i++)
295       {
296 	bitidx = 0;
297 	if (i < nlimbs)
298 	  bits_to_fill = GMP_NUMB_BITS;
299 	else
300 	  bits_to_fill = rbits;
301 
302 	dest[i] = CNST_LIMB (0);
303 	while (bits_to_fill >= 32) /* Process whole 32-bit blocks first.  */
304 	  {
305 	    if (bits_in_pool < 32)	/* Need more bits.  */
306 	      {
307 		/* 64-bit right shift.  */
308 		NEXT_RANDOM;
309 		bitpool_h = y;
310 		bitpool_l |= (bitpool_h << bits_in_pool) & 0xFFFFFFFF;
311 		if (bits_in_pool == 0)
312 		  bitpool_h = 0;
313 		else
314 		  bitpool_h >>= 32 - bits_in_pool;
315 		bits_in_pool += 32;	/* We've got 32 more bits.  */
316 	      }
317 
318 	    /* Fill a 32-bit chunk.  */
319 	    dest[i] |= ((mp_limb_t) bitpool_l) << bitidx;
320 	    bitpool_l = bitpool_h;
321 	    bits_in_pool -= 32;
322 	    bits_to_fill -= 32;
323 	    bitidx += 32;
324 	  }
325 
326 	/* Cover the case where GMP_NUMB_BITS is not a multiple of 32.  */
327 	if (bits_to_fill != 0)
328 	  {
329 	    if (bits_in_pool < bits_to_fill)
330 	      {
331 		NEXT_RANDOM;
332 		bitpool_h = y;
333 		bitpool_l |= (bitpool_h << bits_in_pool) & 0xFFFFFFFF;
334 		if (bits_in_pool == 0)
335 		  bitpool_h = 0;
336 		else
337 		  bitpool_h >>= 32 - bits_in_pool;
338 		bits_in_pool += 32;
339 	      }
340 
341 	    dest[i] |= (((mp_limb_t) bitpool_l
342 			 & ~(~CNST_LIMB (0) << bits_to_fill))
343 			<< bitidx);
344 	    bitpool_l = ((bitpool_l >> bits_to_fill)
345 			 | (bitpool_h << (32 - bits_to_fill))) & 0xFFFFFFFF;
346 	    bitpool_h >>= bits_to_fill;
347 	    bits_in_pool -= bits_to_fill;
348 	  }
349       }
350   }
351 
352 #endif /* GMP_NUMB_BITS != 64 */
353 #endif /* GMP_NUMB_BITS != 32 */
354 }
355 
356 void
__gmp_randclear_mt(gmp_randstate_t rstate)357 __gmp_randclear_mt (gmp_randstate_t rstate)
358 {
359   (*__gmp_free_func) ((void *) RNG_STATE (rstate),
360 		      ALLOC (rstate->_mp_seed) * GMP_LIMB_BYTES);
361 }
362 
363 void __gmp_randiset_mt (gmp_randstate_ptr, gmp_randstate_srcptr);
364 
365 static const gmp_randfnptr_t Mersenne_Twister_Generator_Noseed = {
366   NULL,
367   __gmp_randget_mt,
368   __gmp_randclear_mt,
369   __gmp_randiset_mt
370 };
371 
372 void
__gmp_randiset_mt(gmp_randstate_ptr dst,gmp_randstate_srcptr src)373 __gmp_randiset_mt (gmp_randstate_ptr dst, gmp_randstate_srcptr src)
374 {
375   const mp_size_t sz = ((sizeof (gmp_rand_mt_struct) - 1) / GMP_LIMB_BYTES) + 1;
376   gmp_rand_mt_struct *dstp, *srcp;
377   mp_size_t i;
378 
379   /* Set the generator functions.  */
380   RNG_FNPTR (dst) = RNG_FNPTR(src);
381 
382   /* Allocate the MT-specific state.  */
383   dstp = (gmp_rand_mt_struct *) __GMP_ALLOCATE_FUNC_LIMBS (sz);
384   RNG_STATE (dst) = (mp_ptr) dstp;
385   ALLOC (dst->_mp_seed) = sz;     /* Initialize alloc field to placate Camm.  */
386 
387   /* Copy state.  */
388   srcp = (gmp_rand_mt_struct *) RNG_STATE (src);
389   for (i = 0; i < N; i++)
390     dstp->mt[i] = srcp->mt[i];
391 
392   dstp->mti = srcp->mti;
393 }
394 
395 void
__gmp_randinit_mt_noseed(gmp_randstate_ptr dst)396 __gmp_randinit_mt_noseed (gmp_randstate_ptr dst)
397 {
398   const mp_size_t sz = ((sizeof (gmp_rand_mt_struct) - 1) / GMP_LIMB_BYTES) + 1;
399   gmp_rand_mt_struct *dstp;
400   mp_size_t i;
401 
402   /* Set the generator functions.  */
403   RNG_FNPTR (dst) = (void *) &Mersenne_Twister_Generator_Noseed;
404 
405   /* Allocate the MT-specific state.  */
406   dstp = (gmp_rand_mt_struct *) __GMP_ALLOCATE_FUNC_LIMBS (sz);
407   RNG_STATE (dst) = (mp_ptr) dstp;
408   ALLOC (dst->_mp_seed) = sz;     /* Initialize alloc field to placate Camm.  */
409 
410   /* Set state for default seed.  */
411   for (i = 0; i < N; i++)
412     dstp->mt[i] = default_state[i];
413 
414   dstp->mti = WARM_UP % N;
415 }
416