Mercurial > audlegacy-plugins
comparison src/madplug/SFMT.c @ 922:7e14701aef54 trunk
[svn] - replace random number generator in dithering code with SIMD-oriented Fast Mersenne Twister (SFMT). it reduces CPU load on SSE2 or AltiVec capable platform.
author | yaz |
---|---|
date | Sun, 08 Apr 2007 21:30:22 -0700 |
parents | |
children | b9cbd2e62186 |
comparison
equal
deleted
inserted
replaced
921:8b0850943335 | 922:7e14701aef54 |
---|---|
1 /** | |
2 * @file SFMT.c | |
3 * @brief SIMD oriented Fast Mersenne Twister(SFMT) | |
4 * | |
5 * @author Mutsuo Saito (Hiroshima University) | |
6 * @author Makoto Matsumoto (Hiroshima University) | |
7 * | |
8 * Copyright (C) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima | |
9 * University. All rights reserved. | |
10 * | |
11 * The new BSD License is applied to this software, see LICENSE.txt | |
12 */ | |
13 #include <string.h> | |
14 #include <assert.h> | |
15 #include "SFMT.h" | |
16 #include "SFMT-params.h" | |
17 | |
18 #if defined(ALTIVEC) | |
19 #include "SFMT-alti.h" | |
20 #elif defined(SSE2) | |
21 #include "SFMT-sse2.h" | |
22 #else | |
23 /*------------------------------------------ | |
24 128-bit SIMD like data type for standard C | |
25 ------------------------------------------*/ | |
26 /** 128-bit data structure */ | |
27 struct W128_T { | |
28 uint32_t u[4]; | |
29 }; | |
30 | |
31 /** 128-bit data type */ | |
32 typedef struct W128_T w128_t; | |
33 | |
34 #endif | |
35 | |
36 /*-------------------------------------- | |
37 FILE GLOBAL VARIABLES | |
38 internal state, index counter and flag | |
39 --------------------------------------*/ | |
40 /** the 128-bit internal state array */ | |
41 static w128_t sfmt[N]; | |
42 /** the 32bit integer pointer to the 128-bit internal state array */ | |
43 static uint32_t *psfmt32 = &sfmt[0].u[0]; | |
44 #if !defined(BIG_ENDIAN64) || defined(ONLY64) | |
45 /** the 64bit integer pointer to the 128-bit internal state array */ | |
46 static uint64_t *psfmt64 = (uint64_t *)&sfmt[0].u[0]; | |
47 #endif | |
48 /** index counter to the 32-bit internal state array */ | |
49 static int idx; | |
50 /** a flag: it is 0 if and only if the internal state is not yet | |
51 * initialized. */ | |
52 static int initialized = 0; | |
53 /** a parity check vector which certificate the period of 2^{MEXP} */ | |
54 static uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4}; | |
55 | |
56 /*---------------- | |
57 STATIC FUNCTIONS | |
58 ----------------*/ | |
59 inline static int idxof(int i); | |
60 inline static void rshift128(w128_t *out, w128_t const *in, int shift); | |
61 inline static void lshift128(w128_t *out, w128_t const *in, int shift); | |
62 inline static void gen_rand_all(void); | |
63 inline static void gen_rand_array(w128_t array[], int size); | |
64 inline static uint32_t func1(uint32_t x); | |
65 inline static uint32_t func2(uint32_t x); | |
66 static void period_certification(void); | |
67 #if defined(BIG_ENDIAN64) && !defined(ONLY64) | |
68 inline static void swap(w128_t array[], int size); | |
69 #endif | |
70 | |
71 #if defined(ALTIVEC) | |
72 #include "SFMT-alti.c" | |
73 #elif defined(SSE2) | |
74 #include "SFMT-sse2.c" | |
75 #endif | |
76 | |
77 /** | |
78 * This function simulate a 64-bit index of LITTLE ENDIAN | |
79 * in BIG ENDIAN machine. | |
80 */ | |
81 #ifdef ONLY64 | |
82 inline static int idxof(int i) { | |
83 return i ^ 1; | |
84 } | |
85 #else | |
86 inline static int idxof(int i) { | |
87 return i; | |
88 } | |
89 #endif | |
90 /** | |
91 * This function simulates SIMD 128-bit right shift by the standard C. | |
92 * The 128-bit integer given in in is shifted by (shift * 8) bits. | |
93 * This function simulates the LITTLE ENDIAN SIMD. | |
94 * @param out the output of this function | |
95 * @param in the 128-bit data to be shifted | |
96 * @param shift the shift value | |
97 */ | |
98 #ifdef ONLY64 | |
99 inline static void rshift128(w128_t *out, w128_t const *in, int shift) { | |
100 uint64_t th, tl, oh, ol; | |
101 | |
102 th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]); | |
103 tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]); | |
104 | |
105 oh = th >> (shift * 8); | |
106 ol = tl >> (shift * 8); | |
107 ol |= th << (64 - shift * 8); | |
108 out->u[0] = (uint32_t)(ol >> 32); | |
109 out->u[1] = (uint32_t)ol; | |
110 out->u[2] = (uint32_t)(oh >> 32); | |
111 out->u[3] = (uint32_t)oh; | |
112 } | |
113 #else | |
114 inline static void rshift128(w128_t *out, w128_t const *in, int shift) { | |
115 uint64_t th, tl, oh, ol; | |
116 | |
117 th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]); | |
118 tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]); | |
119 | |
120 oh = th >> (shift * 8); | |
121 ol = tl >> (shift * 8); | |
122 ol |= th << (64 - shift * 8); | |
123 out->u[1] = (uint32_t)(ol >> 32); | |
124 out->u[0] = (uint32_t)ol; | |
125 out->u[3] = (uint32_t)(oh >> 32); | |
126 out->u[2] = (uint32_t)oh; | |
127 } | |
128 #endif | |
129 /** | |
130 * This function simulates SIMD 128-bit left shift by the standard C. | |
131 * The 128-bit integer given in in is shifted by (shift * 8) bits. | |
132 * This function simulates the LITTLE ENDIAN SIMD. | |
133 * @param out the output of this function | |
134 * @param in the 128-bit data to be shifted | |
135 * @param shift the shift value | |
136 */ | |
137 #ifdef ONLY64 | |
138 inline static void lshift128(w128_t *out, w128_t const *in, int shift) { | |
139 uint64_t th, tl, oh, ol; | |
140 | |
141 th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]); | |
142 tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]); | |
143 | |
144 oh = th << (shift * 8); | |
145 ol = tl << (shift * 8); | |
146 oh |= tl >> (64 - shift * 8); | |
147 out->u[0] = (uint32_t)(ol >> 32); | |
148 out->u[1] = (uint32_t)ol; | |
149 out->u[2] = (uint32_t)(oh >> 32); | |
150 out->u[3] = (uint32_t)oh; | |
151 } | |
152 #else | |
153 inline static void lshift128(w128_t *out, w128_t const *in, int shift) { | |
154 uint64_t th, tl, oh, ol; | |
155 | |
156 th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]); | |
157 tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]); | |
158 | |
159 oh = th << (shift * 8); | |
160 ol = tl << (shift * 8); | |
161 oh |= tl >> (64 - shift * 8); | |
162 out->u[1] = (uint32_t)(ol >> 32); | |
163 out->u[0] = (uint32_t)ol; | |
164 out->u[3] = (uint32_t)(oh >> 32); | |
165 out->u[2] = (uint32_t)oh; | |
166 } | |
167 #endif | |
168 | |
169 /** | |
170 * This function represents the recursion formula. | |
171 * @param r output | |
172 * @param a a 128-bit part of the internal state array | |
173 * @param b a 128-bit part of the internal state array | |
174 * @param c a 128-bit part of the internal state array | |
175 * @param d a 128-bit part of the internal state array | |
176 */ | |
177 #ifdef ONLY64 | |
178 inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, | |
179 w128_t *d) { | |
180 w128_t x; | |
181 w128_t y; | |
182 | |
183 lshift128(&x, a, SL2); | |
184 rshift128(&y, c, SR2); | |
185 r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0] | |
186 ^ (d->u[0] << SL1); | |
187 r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1] | |
188 ^ (d->u[1] << SL1); | |
189 r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2] | |
190 ^ (d->u[2] << SL1); | |
191 r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3] | |
192 ^ (d->u[3] << SL1); | |
193 } | |
194 #else | |
195 inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, | |
196 w128_t *d) { | |
197 w128_t x; | |
198 w128_t y; | |
199 | |
200 lshift128(&x, a, SL2); | |
201 rshift128(&y, c, SR2); | |
202 r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0] | |
203 ^ (d->u[0] << SL1); | |
204 r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1] | |
205 ^ (d->u[1] << SL1); | |
206 r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2] | |
207 ^ (d->u[2] << SL1); | |
208 r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3] | |
209 ^ (d->u[3] << SL1); | |
210 } | |
211 #endif | |
212 | |
213 #if (!defined(ALTIVEC)) && (!defined(SSE2)) | |
214 /** | |
215 * This function fills the internal state array with pseudorandom | |
216 * integers. | |
217 */ | |
218 inline static void gen_rand_all(void) { | |
219 int i; | |
220 w128_t *r1, *r2; | |
221 | |
222 r1 = &sfmt[N - 2]; | |
223 r2 = &sfmt[N - 1]; | |
224 for (i = 0; i < N - POS1; i++) { | |
225 do_recursion(&sfmt[i], &sfmt[i], &sfmt[i + POS1], r1, r2); | |
226 r1 = r2; | |
227 r2 = &sfmt[i]; | |
228 } | |
229 for (; i < N; i++) { | |
230 do_recursion(&sfmt[i], &sfmt[i], &sfmt[i + POS1 - N], r1, r2); | |
231 r1 = r2; | |
232 r2 = &sfmt[i]; | |
233 } | |
234 } | |
235 | |
236 /** | |
237 * This function fills the user-specified array with pseudorandom | |
238 * integers. | |
239 * | |
240 * @param array an 128-bit array to be filled by pseudorandom numbers. | |
241 * @param size number of 128-bit pseudorandom numbers to be generated. | |
242 */ | |
243 inline static void gen_rand_array(w128_t array[], int size) { | |
244 int i, j; | |
245 w128_t *r1, *r2; | |
246 | |
247 r1 = &sfmt[N - 2]; | |
248 r2 = &sfmt[N - 1]; | |
249 for (i = 0; i < N - POS1; i++) { | |
250 do_recursion(&array[i], &sfmt[i], &sfmt[i + POS1], r1, r2); | |
251 r1 = r2; | |
252 r2 = &array[i]; | |
253 } | |
254 for (; i < N; i++) { | |
255 do_recursion(&array[i], &sfmt[i], &array[i + POS1 - N], r1, r2); | |
256 r1 = r2; | |
257 r2 = &array[i]; | |
258 } | |
259 for (; i < size - N; i++) { | |
260 do_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2); | |
261 r1 = r2; | |
262 r2 = &array[i]; | |
263 } | |
264 for (j = 0; j < 2 * N - size; j++) { | |
265 sfmt[j] = array[j + size - N]; | |
266 } | |
267 for (; i < size; i++, j++) { | |
268 do_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2); | |
269 r1 = r2; | |
270 r2 = &array[i]; | |
271 sfmt[j] = array[i]; | |
272 } | |
273 } | |
274 #endif | |
275 | |
276 #if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(ALTIVEC) | |
277 inline static void swap(w128_t array[], int size) { | |
278 int i; | |
279 uint32_t x, y; | |
280 | |
281 for (i = 0; i < size; i++) { | |
282 x = array[i].u[0]; | |
283 y = array[i].u[2]; | |
284 array[i].u[0] = array[i].u[1]; | |
285 array[i].u[2] = array[i].u[3]; | |
286 array[i].u[1] = x; | |
287 array[i].u[3] = y; | |
288 } | |
289 } | |
290 #endif | |
291 /** | |
292 * This function represents a function used in the initialization | |
293 * by init_by_array | |
294 * @param x 32-bit integer | |
295 * @return 32-bit integer | |
296 */ | |
297 static uint32_t func1(uint32_t x) { | |
298 return (x ^ (x >> 27)) * (uint32_t)1664525UL; | |
299 } | |
300 | |
301 /** | |
302 * This function represents a function used in the initialization | |
303 * by init_by_array | |
304 * @param x 32-bit integer | |
305 * @return 32-bit integer | |
306 */ | |
307 static uint32_t func2(uint32_t x) { | |
308 return (x ^ (x >> 27)) * (uint32_t)1566083941UL; | |
309 } | |
310 | |
311 /** | |
312 * This function certificate the period of 2^{MEXP} | |
313 */ | |
314 static void period_certification(void) { | |
315 int inner = 0; | |
316 int i, j; | |
317 uint32_t work; | |
318 | |
319 for (i = 0; i < 4; i++) { | |
320 work = psfmt32[idxof(i)] & parity[i]; | |
321 for (j = 0; j < 32; j++) { | |
322 inner ^= work & 1; | |
323 work = work >> 1; | |
324 } | |
325 } | |
326 /* check OK */ | |
327 if (inner == 1) { | |
328 return; | |
329 } | |
330 /* check NG, and modification */ | |
331 for (i = 0; i < 4; i++) { | |
332 work = 1; | |
333 for (j = 0; j < 32; j++) { | |
334 if ((work & parity[i]) != 0) { | |
335 psfmt32[idxof(i)] ^= work; | |
336 return; | |
337 } | |
338 work = work << 1; | |
339 } | |
340 } | |
341 } | |
342 | |
343 /*---------------- | |
344 PUBLIC FUNCTIONS | |
345 ----------------*/ | |
346 /** | |
347 * This function returns the identification string. | |
348 * The string shows the word size, the Mersenne exponent, | |
349 * and all parameters of this generator. | |
350 */ | |
351 char *get_idstring(void) { | |
352 return IDSTR; | |
353 } | |
354 | |
355 /** | |
356 * This function returns the minimum size of array used for \b | |
357 * fill_array32() function. | |
358 * @return minimum size of array used for fill_array32() function. | |
359 */ | |
360 int get_min_array_size32(void) { | |
361 return N32; | |
362 } | |
363 | |
364 /** | |
365 * This function returns the minimum size of array used for \b | |
366 * fill_array64() function. | |
367 * @return minimum size of array used for fill_array64() function. | |
368 */ | |
369 int get_min_array_size64(void) { | |
370 return N64; | |
371 } | |
372 | |
373 #ifndef ONLY64 | |
374 /** | |
375 * This function generates and returns 32-bit pseudorandom number. | |
376 * init_gen_rand or init_by_array must be called before this function. | |
377 * @return 32-bit pseudorandom number | |
378 */ | |
379 inline uint32_t gen_rand32(void) { | |
380 uint32_t r; | |
381 | |
382 assert(initialized); | |
383 if (idx >= N32) { | |
384 gen_rand_all(); | |
385 idx = 0; | |
386 } | |
387 r = psfmt32[idx++]; | |
388 return r; | |
389 } | |
390 #endif | |
391 /** | |
392 * This function generates and returns 64-bit pseudorandom number. | |
393 * init_gen_rand or init_by_array must be called before this function. | |
394 * The function gen_rand64 should not be called after gen_rand32, | |
395 * unless an initialization is again executed. | |
396 * @return 64-bit pseudorandom number | |
397 */ | |
398 inline uint64_t gen_rand64(void) { | |
399 #if defined(BIG_ENDIAN64) && !defined(ONLY64) | |
400 uint32_t r1, r2; | |
401 #else | |
402 uint64_t r; | |
403 #endif | |
404 | |
405 assert(initialized); | |
406 assert(idx % 2 == 0); | |
407 | |
408 if (idx >= N32) { | |
409 gen_rand_all(); | |
410 idx = 0; | |
411 } | |
412 #if defined(BIG_ENDIAN64) && !defined(ONLY64) | |
413 r1 = psfmt32[idx]; | |
414 r2 = psfmt32[idx + 1]; | |
415 idx += 2; | |
416 return ((uint64_t)r2 << 32) | r1; | |
417 #else | |
418 r = psfmt64[idx / 2]; | |
419 idx += 2; | |
420 return r; | |
421 #endif | |
422 } | |
423 | |
424 #ifndef ONLY64 | |
425 /** | |
426 * This function generates pseudorandom 32-bit integers in the | |
427 * specified array[] by one call. The number of pseudorandom integers | |
428 * is specified by the argument size, which must be at least 624 and a | |
429 * multiple of four. The generation by this function is much faster | |
430 * than the following gen_rand function. | |
431 * | |
432 * For initialization, init_gen_rand or init_by_array must be called | |
433 * before the first call of this function. This function can not be | |
434 * used after calling gen_rand function, without initialization. | |
435 * | |
436 * @param array an array where pseudorandom 32-bit integers are filled | |
437 * by this function. The pointer to the array must be \b "aligned" | |
438 * (namely, must be a multiple of 16) in the SIMD version, since it | |
439 * refers to the address of a 128-bit integer. In the standard C | |
440 * version, the pointer is arbitrary. | |
441 * | |
442 * @param size the number of 32-bit pseudorandom integers to be | |
443 * generated. size must be a multiple of 4, and greater than or equal | |
444 * to (MEXP / 128 + 1) * 4. | |
445 * | |
446 * @note \b memalign or \b posix_memalign is available to get aligned | |
447 * memory. Mac OSX doesn't have these functions, but \b malloc of OSX | |
448 * returns the pointer to the aligned memory block. | |
449 */ | |
450 inline void fill_array32(uint32_t array[], int size) { | |
451 assert(initialized); | |
452 assert(idx == N32); | |
453 assert(size % 4 == 0); | |
454 assert(size >= N32); | |
455 | |
456 gen_rand_array((w128_t *)array, size / 4); | |
457 idx = N32; | |
458 } | |
459 #endif | |
460 | |
461 /** | |
462 * This function generates pseudorandom 64-bit integers in the | |
463 * specified array[] by one call. The number of pseudorandom integers | |
464 * is specified by the argument size, which must be at least 312 and a | |
465 * multiple of two. The generation by this function is much faster | |
466 * than the following gen_rand function. | |
467 * | |
468 * For initialization, init_gen_rand or init_by_array must be called | |
469 * before the first call of this function. This function can not be | |
470 * used after calling gen_rand function, without initialization. | |
471 * | |
472 * @param array an array where pseudorandom 64-bit integers are filled | |
473 * by this function. The pointer to the array must be "aligned" | |
474 * (namely, must be a multiple of 16) in the SIMD version, since it | |
475 * refers to the address of a 128-bit integer. In the standard C | |
476 * version, the pointer is arbitrary. | |
477 * | |
478 * @param size the number of 64-bit pseudorandom integers to be | |
479 * generated. size must be a multiple of 2, and greater than or equal | |
480 * to (MEXP / 128 + 1) * 2 | |
481 * | |
482 * @note \b memalign or \b posix_memalign is available to get aligned | |
483 * memory. Mac OSX doesn't have these functions, but \b malloc of OSX | |
484 * returns the pointer to the aligned memory block. | |
485 */ | |
486 inline void fill_array64(uint64_t array[], int size) { | |
487 assert(initialized); | |
488 assert(idx == N32); | |
489 assert(size % 2 == 0); | |
490 assert(size >= N64); | |
491 | |
492 gen_rand_array((w128_t *)array, size / 2); | |
493 idx = N32; | |
494 | |
495 #if defined(BIG_ENDIAN64) && !defined(ONLY64) | |
496 swap((w128_t *)array, size /2); | |
497 #endif | |
498 } | |
499 | |
500 /** | |
501 * This function initializes the internal state array with a 32-bit | |
502 * integer seed. | |
503 * | |
504 * @param seed a 32-bit integer used as the seed. | |
505 */ | |
506 void init_gen_rand(uint32_t seed) { | |
507 int i; | |
508 | |
509 psfmt32[idxof(0)] = seed; | |
510 for (i = 1; i < N32; i++) { | |
511 psfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] | |
512 ^ (psfmt32[idxof(i - 1)] >> 30)) | |
513 + i; | |
514 } | |
515 idx = N32; | |
516 period_certification(); | |
517 initialized = 1; | |
518 } | |
519 | |
520 /** | |
521 * This function initializes the internal state array, | |
522 * with an array of 32-bit integers used as the seeds | |
523 * @param init_key the array of 32-bit integers, used as a seed. | |
524 * @param key_length the length of init_key. | |
525 */ | |
526 void init_by_array(uint32_t init_key[], int key_length) { | |
527 int i, j, count; | |
528 uint32_t r; | |
529 int lag; | |
530 int mid; | |
531 int size = N * 4; | |
532 | |
533 if (size >= 623) { | |
534 lag = 11; | |
535 } else if (size >= 68) { | |
536 lag = 7; | |
537 } else if (size >= 39) { | |
538 lag = 5; | |
539 } else { | |
540 lag = 3; | |
541 } | |
542 mid = (size - lag) / 2; | |
543 | |
544 memset(sfmt, 0x8b, sizeof(sfmt)); | |
545 if (key_length + 1 > N32) { | |
546 count = key_length + 1; | |
547 } else { | |
548 count = N32; | |
549 } | |
550 r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] | |
551 ^ psfmt32[idxof(N32 - 1)]); | |
552 psfmt32[idxof(mid)] += r; | |
553 r += key_length; | |
554 psfmt32[idxof(mid + lag)] += r; | |
555 psfmt32[idxof(0)] = r; | |
556 i = 1; | |
557 count--; | |
558 for (i = 1, j = 0; (j < count) && (j < key_length); j++) { | |
559 r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] | |
560 ^ psfmt32[idxof((i + N32 - 1) % N32)]); | |
561 psfmt32[idxof((i + mid) % N32)] += r; | |
562 r += init_key[j] + i; | |
563 psfmt32[idxof((i + mid + lag) % N32)] += r; | |
564 psfmt32[idxof(i)] = r; | |
565 i = (i + 1) % N32; | |
566 } | |
567 for (; j < count; j++) { | |
568 r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] | |
569 ^ psfmt32[idxof((i + N32 - 1) % N32)]); | |
570 psfmt32[idxof((i + mid) % N32)] += r; | |
571 r += i; | |
572 psfmt32[idxof((i + mid + lag) % N32)] += r; | |
573 psfmt32[idxof(i)] = r; | |
574 i = (i + 1) % N32; | |
575 } | |
576 for (j = 0; j < N32; j++) { | |
577 r = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)] | |
578 + psfmt32[idxof((i + N32 - 1) % N32)]); | |
579 psfmt32[idxof((i + mid) % N32)] ^= r; | |
580 r -= i; | |
581 psfmt32[idxof((i + mid + lag) % N32)] ^= r; | |
582 psfmt32[idxof(i)] = r; | |
583 i = (i + 1) % N32; | |
584 } | |
585 | |
586 idx = N32; | |
587 period_certification(); | |
588 initialized = 1; | |
589 } |