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