Mercurial > vba-linux
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/SFMT/SFMT.c Sun Mar 04 17:38:32 2012 -0600 1.3 @@ -0,0 +1,620 @@ 1.4 +/** 1.5 + * @file SFMT.c 1.6 + * @brief SIMD oriented Fast Mersenne Twister(SFMT) 1.7 + * 1.8 + * @author Mutsuo Saito (Hiroshima University) 1.9 + * @author Makoto Matsumoto (Hiroshima University) 1.10 + * 1.11 + * Copyright (C) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima 1.12 + * University. All rights reserved. 1.13 + * 1.14 + * The new BSD License is applied to this software, see LICENSE.txt 1.15 + */ 1.16 +#include <string.h> 1.17 +#include <assert.h> 1.18 +#include "SFMT.h" 1.19 +#include "SFMT-params.h" 1.20 + 1.21 +#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64) 1.22 +#define BIG_ENDIAN64 1 1.23 +#endif 1.24 +#if defined(HAVE_ALTIVEC) && !defined(BIG_ENDIAN64) 1.25 +#define BIG_ENDIAN64 1 1.26 +#endif 1.27 +#if defined(ONLY64) && !defined(BIG_ENDIAN64) 1.28 + #if defined(__GNUC__) 1.29 + #error "-DONLY64 must be specified with -DBIG_ENDIAN64" 1.30 + #endif 1.31 +#undef ONLY64 1.32 +#endif 1.33 +/*------------------------------------------------------ 1.34 + 128-bit SIMD data type for Altivec, SSE2 or standard C 1.35 + ------------------------------------------------------*/ 1.36 +#if defined(HAVE_ALTIVEC) 1.37 + #if !defined(__APPLE__) 1.38 + #include <altivec.h> 1.39 + #endif 1.40 +/** 128-bit data structure */ 1.41 +union W128_T { 1.42 + vector unsigned int s; 1.43 + uint32_t u[4]; 1.44 +}; 1.45 +/** 128-bit data type */ 1.46 +typedef union W128_T w128_t; 1.47 + 1.48 +#elif defined(HAVE_SSE2) 1.49 + #include <emmintrin.h> 1.50 + 1.51 +/** 128-bit data structure */ 1.52 +union W128_T { 1.53 + __m128i si; 1.54 + uint32_t u[4]; 1.55 +}; 1.56 +/** 128-bit data type */ 1.57 +typedef union W128_T w128_t; 1.58 + 1.59 +#else 1.60 + 1.61 +/** 128-bit data structure */ 1.62 +struct W128_T { 1.63 + uint32_t u[4]; 1.64 +}; 1.65 +/** 128-bit data type */ 1.66 +typedef struct W128_T w128_t; 1.67 + 1.68 +#endif 1.69 + 1.70 +/*-------------------------------------- 1.71 + FILE GLOBAL VARIABLES 1.72 + internal state, index counter and flag 1.73 + --------------------------------------*/ 1.74 +/** the 128-bit internal state array */ 1.75 +static w128_t sfmt[N]; 1.76 +/** the 32bit integer pointer to the 128-bit internal state array */ 1.77 +static uint32_t *psfmt32 = &sfmt[0].u[0]; 1.78 +#if !defined(BIG_ENDIAN64) || defined(ONLY64) 1.79 +/** the 64bit integer pointer to the 128-bit internal state array */ 1.80 +static uint64_t *psfmt64 = (uint64_t *)&sfmt[0].u[0]; 1.81 +#endif 1.82 +/** index counter to the 32-bit internal state array */ 1.83 +static int idx; 1.84 +/** a flag: it is 0 if and only if the internal state is not yet 1.85 + * initialized. */ 1.86 +static int initialized = 0; 1.87 +/** a parity check vector which certificate the period of 2^{MEXP} */ 1.88 +static uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4}; 1.89 + 1.90 +/*---------------- 1.91 + STATIC FUNCTIONS 1.92 + ----------------*/ 1.93 +inline static int idxof(int i); 1.94 +inline static void rshift128(w128_t *out, w128_t const *in, int shift); 1.95 +inline static void lshift128(w128_t *out, w128_t const *in, int shift); 1.96 +inline static void gen_rand_all(void); 1.97 +inline static void gen_rand_array(w128_t *array, int size); 1.98 +inline static uint32_t func1(uint32_t x); 1.99 +inline static uint32_t func2(uint32_t x); 1.100 +static void period_certification(void); 1.101 +#if defined(BIG_ENDIAN64) && !defined(ONLY64) 1.102 +inline static void swap(w128_t *array, int size); 1.103 +#endif 1.104 + 1.105 +#if defined(HAVE_ALTIVEC) 1.106 + #include "SFMT-alti.h" 1.107 +#elif defined(HAVE_SSE2) 1.108 + #include "SFMT-sse2.h" 1.109 +#endif 1.110 + 1.111 +/** 1.112 + * This function simulate a 64-bit index of LITTLE ENDIAN 1.113 + * in BIG ENDIAN machine. 1.114 + */ 1.115 +#ifdef ONLY64 1.116 +inline static int idxof(int i) { 1.117 + return i ^ 1; 1.118 +} 1.119 +#else 1.120 +inline static int idxof(int i) { 1.121 + return i; 1.122 +} 1.123 +#endif 1.124 +/** 1.125 + * This function simulates SIMD 128-bit right shift by the standard C. 1.126 + * The 128-bit integer given in in is shifted by (shift * 8) bits. 1.127 + * This function simulates the LITTLE ENDIAN SIMD. 1.128 + * @param out the output of this function 1.129 + * @param in the 128-bit data to be shifted 1.130 + * @param shift the shift value 1.131 + */ 1.132 +#ifdef ONLY64 1.133 +inline static void rshift128(w128_t *out, w128_t const *in, int shift) { 1.134 + uint64_t th, tl, oh, ol; 1.135 + 1.136 + th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]); 1.137 + tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]); 1.138 + 1.139 + oh = th >> (shift * 8); 1.140 + ol = tl >> (shift * 8); 1.141 + ol |= th << (64 - shift * 8); 1.142 + out->u[0] = (uint32_t)(ol >> 32); 1.143 + out->u[1] = (uint32_t)(ol & 0xffffffff); 1.144 + out->u[2] = (uint32_t)(oh >> 32); 1.145 + out->u[3] = (uint32_t)(oh & 0xffffffff); 1.146 +} 1.147 +#else 1.148 +inline static void rshift128(w128_t *out, w128_t const *in, int shift) { 1.149 + uint64_t th, tl, oh, ol; 1.150 + 1.151 + th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]); 1.152 + tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]); 1.153 + 1.154 + oh = th >> (shift * 8); 1.155 + ol = tl >> (shift * 8); 1.156 + ol |= th << (64 - shift * 8); 1.157 + out->u[1] = (uint32_t)(ol >> 32); 1.158 + out->u[0] = (uint32_t)(ol & 0xffffffff); 1.159 + out->u[3] = (uint32_t)(oh >> 32); 1.160 + out->u[2] = (uint32_t)(oh & 0xffffffff); 1.161 +} 1.162 +#endif 1.163 +/** 1.164 + * This function simulates SIMD 128-bit left shift by the standard C. 1.165 + * The 128-bit integer given in in is shifted by (shift * 8) bits. 1.166 + * This function simulates the LITTLE ENDIAN SIMD. 1.167 + * @param out the output of this function 1.168 + * @param in the 128-bit data to be shifted 1.169 + * @param shift the shift value 1.170 + */ 1.171 +#ifdef ONLY64 1.172 +inline static void lshift128(w128_t *out, w128_t const *in, int shift) { 1.173 + uint64_t th, tl, oh, ol; 1.174 + 1.175 + th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]); 1.176 + tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]); 1.177 + 1.178 + oh = th << (shift * 8); 1.179 + ol = tl << (shift * 8); 1.180 + oh |= tl >> (64 - shift * 8); 1.181 + out->u[0] = (uint32_t)(ol >> 32); 1.182 + out->u[1] = (uint32_t)(ol & 0xffffffff); 1.183 + out->u[2] = (uint32_t)(oh >> 32); 1.184 + out->u[3] = (uint32_t)(oh & 0xffffffff); 1.185 +} 1.186 +#else 1.187 +inline static void lshift128(w128_t *out, w128_t const *in, int shift) { 1.188 + uint64_t th, tl, oh, ol; 1.189 + 1.190 + th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]); 1.191 + tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]); 1.192 + 1.193 + oh = th << (shift * 8); 1.194 + ol = tl << (shift * 8); 1.195 + oh |= tl >> (64 - shift * 8); 1.196 + out->u[1] = (uint32_t)(ol >> 32); 1.197 + out->u[0] = (uint32_t)(ol & 0xffffffff); 1.198 + out->u[3] = (uint32_t)(oh >> 32); 1.199 + out->u[2] = (uint32_t)(oh & 0xffffffff); 1.200 +} 1.201 +#endif 1.202 + 1.203 +/** 1.204 + * This function represents the recursion formula. 1.205 + * @param r output 1.206 + * @param a a 128-bit part of the internal state array 1.207 + * @param b a 128-bit part of the internal state array 1.208 + * @param c a 128-bit part of the internal state array 1.209 + * @param d a 128-bit part of the internal state array 1.210 + */ 1.211 +#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2)) 1.212 +#ifdef ONLY64 1.213 +inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, 1.214 + w128_t *d) { 1.215 + w128_t x; 1.216 + w128_t y; 1.217 + 1.218 + lshift128(&x, a, SL2); 1.219 + rshift128(&y, c, SR2); 1.220 + r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0] 1.221 + ^ (d->u[0] << SL1); 1.222 + r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1] 1.223 + ^ (d->u[1] << SL1); 1.224 + r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2] 1.225 + ^ (d->u[2] << SL1); 1.226 + r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3] 1.227 + ^ (d->u[3] << SL1); 1.228 +} 1.229 +#else 1.230 +inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, 1.231 + w128_t *d) { 1.232 + w128_t x; 1.233 + w128_t y; 1.234 + 1.235 + lshift128(&x, a, SL2); 1.236 + rshift128(&y, c, SR2); 1.237 + r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0] 1.238 + ^ (d->u[0] << SL1); 1.239 + r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1] 1.240 + ^ (d->u[1] << SL1); 1.241 + r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2] 1.242 + ^ (d->u[2] << SL1); 1.243 + r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3] 1.244 + ^ (d->u[3] << SL1); 1.245 +} 1.246 +#endif 1.247 +#endif 1.248 + 1.249 +#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2)) 1.250 +/** 1.251 + * This function fills the internal state array with pseudorandom 1.252 + * integers. 1.253 + */ 1.254 +inline static void gen_rand_all(void) { 1.255 + int i; 1.256 + w128_t *r1, *r2; 1.257 + 1.258 + r1 = &sfmt[N - 2]; 1.259 + r2 = &sfmt[N - 1]; 1.260 + for (i = 0; i < N - POS1; i++) { 1.261 + do_recursion(&sfmt[i], &sfmt[i], &sfmt[i + POS1], r1, r2); 1.262 + r1 = r2; 1.263 + r2 = &sfmt[i]; 1.264 + } 1.265 + for (; i < N; i++) { 1.266 + do_recursion(&sfmt[i], &sfmt[i], &sfmt[i + POS1 - N], r1, r2); 1.267 + r1 = r2; 1.268 + r2 = &sfmt[i]; 1.269 + } 1.270 +} 1.271 + 1.272 +/** 1.273 + * This function fills the user-specified array with pseudorandom 1.274 + * integers. 1.275 + * 1.276 + * @param array an 128-bit array to be filled by pseudorandom numbers. 1.277 + * @param size number of 128-bit pseudorandom numbers to be generated. 1.278 + */ 1.279 +inline static void gen_rand_array(w128_t *array, int size) { 1.280 + int i, j; 1.281 + w128_t *r1, *r2; 1.282 + 1.283 + r1 = &sfmt[N - 2]; 1.284 + r2 = &sfmt[N - 1]; 1.285 + for (i = 0; i < N - POS1; i++) { 1.286 + do_recursion(&array[i], &sfmt[i], &sfmt[i + POS1], r1, r2); 1.287 + r1 = r2; 1.288 + r2 = &array[i]; 1.289 + } 1.290 + for (; i < N; i++) { 1.291 + do_recursion(&array[i], &sfmt[i], &array[i + POS1 - N], r1, r2); 1.292 + r1 = r2; 1.293 + r2 = &array[i]; 1.294 + } 1.295 + for (; i < size - N; i++) { 1.296 + do_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2); 1.297 + r1 = r2; 1.298 + r2 = &array[i]; 1.299 + } 1.300 + for (j = 0; j < 2 * N - size; j++) { 1.301 + sfmt[j] = array[j + size - N]; 1.302 + } 1.303 + for (; i < size; i++, j++) { 1.304 + do_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2); 1.305 + r1 = r2; 1.306 + r2 = &array[i]; 1.307 + sfmt[j] = array[i]; 1.308 + } 1.309 +} 1.310 +#endif 1.311 + 1.312 +#if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(HAVE_ALTIVEC) 1.313 +inline static void swap(w128_t *array, int size) { 1.314 + int i; 1.315 + uint32_t x, y; 1.316 + 1.317 + for (i = 0; i < size; i++) { 1.318 + x = array[i].u[0]; 1.319 + y = array[i].u[2]; 1.320 + array[i].u[0] = array[i].u[1]; 1.321 + array[i].u[2] = array[i].u[3]; 1.322 + array[i].u[1] = x; 1.323 + array[i].u[3] = y; 1.324 + } 1.325 +} 1.326 +#endif 1.327 +/** 1.328 + * This function represents a function used in the initialization 1.329 + * by init_by_array 1.330 + * @param x 32-bit integer 1.331 + * @return 32-bit integer 1.332 + */ 1.333 +static uint32_t func1(uint32_t x) { 1.334 + return (x ^ (x >> 27)) * (uint32_t)1664525UL; 1.335 +} 1.336 + 1.337 +/** 1.338 + * This function represents a function used in the initialization 1.339 + * by init_by_array 1.340 + * @param x 32-bit integer 1.341 + * @return 32-bit integer 1.342 + */ 1.343 +static uint32_t func2(uint32_t x) { 1.344 + return (x ^ (x >> 27)) * (uint32_t)1566083941UL; 1.345 +} 1.346 + 1.347 +/** 1.348 + * This function certificate the period of 2^{MEXP} 1.349 + */ 1.350 +static void period_certification(void) { 1.351 + int inner = 0; 1.352 + int i, j; 1.353 + uint32_t work; 1.354 + 1.355 + for (i = 0; i < 4; i++) 1.356 + inner ^= psfmt32[idxof(i)] & parity[i]; 1.357 + for (i = 16; i > 0; i >>= 1) 1.358 + inner ^= inner >> i; 1.359 + inner &= 1; 1.360 + /* check OK */ 1.361 + if (inner == 1) { 1.362 + return; 1.363 + } 1.364 + /* check NG, and modification */ 1.365 + for (i = 0; i < 4; i++) { 1.366 + work = 1; 1.367 + for (j = 0; j < 32; j++) { 1.368 + if ((work & parity[i]) != 0) { 1.369 + psfmt32[idxof(i)] ^= work; 1.370 + return; 1.371 + } 1.372 + work = work << 1; 1.373 + } 1.374 + } 1.375 +} 1.376 + 1.377 +/*---------------- 1.378 + PUBLIC FUNCTIONS 1.379 + ----------------*/ 1.380 +/** 1.381 + * This function returns the identification string. 1.382 + * The string shows the word size, the Mersenne exponent, 1.383 + * and all parameters of this generator. 1.384 + */ 1.385 +const char *get_idstring(void) { 1.386 + return IDSTR; 1.387 +} 1.388 + 1.389 +/** 1.390 + * This function returns the minimum size of array used for \b 1.391 + * fill_array32() function. 1.392 + * @return minimum size of array used for fill_array32() function. 1.393 + */ 1.394 +int get_min_array_size32(void) { 1.395 + return N32; 1.396 +} 1.397 + 1.398 +/** 1.399 + * This function returns the minimum size of array used for \b 1.400 + * fill_array64() function. 1.401 + * @return minimum size of array used for fill_array64() function. 1.402 + */ 1.403 +int get_min_array_size64(void) { 1.404 + return N64; 1.405 +} 1.406 + 1.407 +#ifndef ONLY64 1.408 +/** 1.409 + * This function generates and returns 32-bit pseudorandom number. 1.410 + * init_gen_rand or init_by_array must be called before this function. 1.411 + * @return 32-bit pseudorandom number 1.412 + */ 1.413 +uint32_t gen_rand32(void) { 1.414 + uint32_t r; 1.415 + 1.416 + assert(initialized); 1.417 + if (idx >= N32) { 1.418 + gen_rand_all(); 1.419 + idx = 0; 1.420 + } 1.421 + r = psfmt32[idx++]; 1.422 + return r; 1.423 +} 1.424 +#endif 1.425 +/** 1.426 + * This function generates and returns 64-bit pseudorandom number. 1.427 + * init_gen_rand or init_by_array must be called before this function. 1.428 + * The function gen_rand64 should not be called after gen_rand32, 1.429 + * unless an initialization is again executed. 1.430 + * @return 64-bit pseudorandom number 1.431 + */ 1.432 +uint64_t gen_rand64(void) { 1.433 +#if defined(BIG_ENDIAN64) && !defined(ONLY64) 1.434 + uint32_t r1, r2; 1.435 +#else 1.436 + uint64_t r; 1.437 +#endif 1.438 + 1.439 + assert(initialized); 1.440 + assert(idx % 2 == 0); 1.441 + 1.442 + if (idx >= N32) { 1.443 + gen_rand_all(); 1.444 + idx = 0; 1.445 + } 1.446 +#if defined(BIG_ENDIAN64) && !defined(ONLY64) 1.447 + r1 = psfmt32[idx]; 1.448 + r2 = psfmt32[idx + 1]; 1.449 + idx += 2; 1.450 + return ((uint64_t)r2 << 32) | r1; 1.451 +#else 1.452 + r = psfmt64[idx / 2]; 1.453 + idx += 2; 1.454 + return r; 1.455 +#endif 1.456 +} 1.457 + 1.458 +#ifndef ONLY64 1.459 +/** 1.460 + * This function generates pseudorandom 32-bit integers in the 1.461 + * specified array[] by one call. The number of pseudorandom integers 1.462 + * is specified by the argument size, which must be at least 624 and a 1.463 + * multiple of four. The generation by this function is much faster 1.464 + * than the following gen_rand function. 1.465 + * 1.466 + * For initialization, init_gen_rand or init_by_array must be called 1.467 + * before the first call of this function. This function can not be 1.468 + * used after calling gen_rand function, without initialization. 1.469 + * 1.470 + * @param array an array where pseudorandom 32-bit integers are filled 1.471 + * by this function. The pointer to the array must be \b "aligned" 1.472 + * (namely, must be a multiple of 16) in the SIMD version, since it 1.473 + * refers to the address of a 128-bit integer. In the standard C 1.474 + * version, the pointer is arbitrary. 1.475 + * 1.476 + * @param size the number of 32-bit pseudorandom integers to be 1.477 + * generated. size must be a multiple of 4, and greater than or equal 1.478 + * to (MEXP / 128 + 1) * 4. 1.479 + * 1.480 + * @note \b memalign or \b posix_memalign is available to get aligned 1.481 + * memory. Mac OSX doesn't have these functions, but \b malloc of OSX 1.482 + * returns the pointer to the aligned memory block. 1.483 + */ 1.484 +void fill_array32(uint32_t *array, int size) { 1.485 + assert(initialized); 1.486 + assert(idx == N32); 1.487 + assert(size % 4 == 0); 1.488 + assert(size >= N32); 1.489 + 1.490 + gen_rand_array((w128_t *)array, size / 4); 1.491 + idx = N32; 1.492 +} 1.493 +#endif 1.494 + 1.495 +/** 1.496 + * This function generates pseudorandom 64-bit integers in the 1.497 + * specified array[] by one call. The number of pseudorandom integers 1.498 + * is specified by the argument size, which must be at least 312 and a 1.499 + * multiple of two. The generation by this function is much faster 1.500 + * than the following gen_rand function. 1.501 + * 1.502 + * For initialization, init_gen_rand or init_by_array must be called 1.503 + * before the first call of this function. This function can not be 1.504 + * used after calling gen_rand function, without initialization. 1.505 + * 1.506 + * @param array an array where pseudorandom 64-bit integers are filled 1.507 + * by this function. The pointer to the array must be "aligned" 1.508 + * (namely, must be a multiple of 16) in the SIMD version, since it 1.509 + * refers to the address of a 128-bit integer. In the standard C 1.510 + * version, the pointer is arbitrary. 1.511 + * 1.512 + * @param size the number of 64-bit pseudorandom integers to be 1.513 + * generated. size must be a multiple of 2, and greater than or equal 1.514 + * to (MEXP / 128 + 1) * 2 1.515 + * 1.516 + * @note \b memalign or \b posix_memalign is available to get aligned 1.517 + * memory. Mac OSX doesn't have these functions, but \b malloc of OSX 1.518 + * returns the pointer to the aligned memory block. 1.519 + */ 1.520 +void fill_array64(uint64_t *array, int size) { 1.521 + assert(initialized); 1.522 + assert(idx == N32); 1.523 + assert(size % 2 == 0); 1.524 + assert(size >= N64); 1.525 + 1.526 + gen_rand_array((w128_t *)array, size / 2); 1.527 + idx = N32; 1.528 + 1.529 +#if defined(BIG_ENDIAN64) && !defined(ONLY64) 1.530 + swap((w128_t *)array, size /2); 1.531 +#endif 1.532 +} 1.533 + 1.534 +/** 1.535 + * This function initializes the internal state array with a 32-bit 1.536 + * integer seed. 1.537 + * 1.538 + * @param seed a 32-bit integer used as the seed. 1.539 + */ 1.540 +void init_gen_rand(uint32_t seed) { 1.541 + int i; 1.542 + 1.543 + psfmt32[idxof(0)] = seed; 1.544 + for (i = 1; i < N32; i++) { 1.545 + psfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] 1.546 + ^ (psfmt32[idxof(i - 1)] >> 30)) 1.547 + + i; 1.548 + } 1.549 + idx = N32; 1.550 + period_certification(); 1.551 + initialized = 1; 1.552 +} 1.553 + 1.554 +/** 1.555 + * This function initializes the internal state array, 1.556 + * with an array of 32-bit integers used as the seeds 1.557 + * @param init_key the array of 32-bit integers, used as a seed. 1.558 + * @param key_length the length of init_key. 1.559 + */ 1.560 +void init_by_array(uint32_t *init_key, int key_length) { 1.561 + int i, j, count; 1.562 + uint32_t r; 1.563 + int lag; 1.564 + int mid; 1.565 + int size = N * 4; 1.566 + 1.567 + if (size >= 623) { 1.568 + lag = 11; 1.569 + } else if (size >= 68) { 1.570 + lag = 7; 1.571 + } else if (size >= 39) { 1.572 + lag = 5; 1.573 + } else { 1.574 + lag = 3; 1.575 + } 1.576 + mid = (size - lag) / 2; 1.577 + 1.578 + memset(sfmt, 0x8b, sizeof(sfmt)); 1.579 + if (key_length + 1 > N32) { 1.580 + count = key_length + 1; 1.581 + } else { 1.582 + count = N32; 1.583 + } 1.584 + r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] 1.585 + ^ psfmt32[idxof(N32 - 1)]); 1.586 + psfmt32[idxof(mid)] += r; 1.587 + r += key_length; 1.588 + psfmt32[idxof(mid + lag)] += r; 1.589 + psfmt32[idxof(0)] = r; 1.590 + 1.591 + count--; 1.592 + for (i = 1, j = 0; (j < count) && (j < key_length); j++) { 1.593 + r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] 1.594 + ^ psfmt32[idxof((i + N32 - 1) % N32)]); 1.595 + psfmt32[idxof((i + mid) % N32)] += r; 1.596 + r += init_key[j] + i; 1.597 + psfmt32[idxof((i + mid + lag) % N32)] += r; 1.598 + psfmt32[idxof(i)] = r; 1.599 + i = (i + 1) % N32; 1.600 + } 1.601 + for (; j < count; j++) { 1.602 + r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] 1.603 + ^ psfmt32[idxof((i + N32 - 1) % N32)]); 1.604 + psfmt32[idxof((i + mid) % N32)] += r; 1.605 + r += i; 1.606 + psfmt32[idxof((i + mid + lag) % N32)] += r; 1.607 + psfmt32[idxof(i)] = r; 1.608 + i = (i + 1) % N32; 1.609 + } 1.610 + for (j = 0; j < N32; j++) { 1.611 + r = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)] 1.612 + + psfmt32[idxof((i + N32 - 1) % N32)]); 1.613 + psfmt32[idxof((i + mid) % N32)] ^= r; 1.614 + r -= i; 1.615 + psfmt32[idxof((i + mid + lag) % N32)] ^= r; 1.616 + psfmt32[idxof(i)] = r; 1.617 + i = (i + 1) % N32; 1.618 + } 1.619 + 1.620 + idx = N32; 1.621 + period_certification(); 1.622 + initialized = 1; 1.623 +}