dSFMT.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /**
  2. * @file dSFMT.c
  3. * @brief double precision SIMD-oriented Fast Mersenne Twister (dSFMT)
  4. * based on IEEE 754 format.
  5. *
  6. * @author Mutsuo Saito (Hiroshima University)
  7. * @author Makoto Matsumoto (Hiroshima University)
  8. *
  9. * Copyright (C) 2007,2008 Mutsuo Saito, Makoto Matsumoto and Hiroshima
  10. * University. All rights reserved.
  11. *
  12. * The new BSD License is applied to this software, see LICENSE.txt
  13. */
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include "dSFMT-params.h"
  18. #include "dSFMT-common.h"
  19. #if defined(__cplusplus)
  20. extern "C" {
  21. #endif
  22. /** dsfmt internal state vector */
  23. dsfmt_t dsfmt_global_data;
  24. /** dsfmt mexp for check */
  25. static const int dsfmt_mexp = DSFMT_MEXP;
  26. /*----------------
  27. STATIC FUNCTIONS
  28. ----------------*/
  29. inline static uint32_t ini_func1(uint32_t x);
  30. inline static uint32_t ini_func2(uint32_t x);
  31. inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array,
  32. int size);
  33. inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array,
  34. int size);
  35. inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array,
  36. int size);
  37. inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array,
  38. int size);
  39. inline static int idxof(int i);
  40. static void initial_mask(dsfmt_t *dsfmt);
  41. static void period_certification(dsfmt_t *dsfmt);
  42. #if defined(HAVE_SSE2)
  43. /** 1 in 64bit for sse2 */
  44. static const union X128I_T sse2_int_one = {{1, 1}};
  45. /** 2.0 double for sse2 */
  46. static const union X128D_T sse2_double_two = {{2.0, 2.0}};
  47. /** -1.0 double for sse2 */
  48. static const union X128D_T sse2_double_m_one = {{-1.0, -1.0}};
  49. #endif
  50. /**
  51. * This function simulate a 32-bit array index overlapped to 64-bit
  52. * array of LITTLE ENDIAN in BIG ENDIAN machine.
  53. */
  54. #if defined(DSFMT_BIG_ENDIAN)
  55. inline static int idxof(int i) {
  56. return i ^ 1;
  57. }
  58. #else
  59. inline static int idxof(int i) {
  60. return i;
  61. }
  62. #endif
  63. #if defined(HAVE_SSE2)
  64. /**
  65. * This function converts the double precision floating point numbers which
  66. * distribute uniformly in the range [1, 2) to those which distribute uniformly
  67. * in the range [0, 1).
  68. * @param w 128bit stracture of double precision floating point numbers (I/O)
  69. */
  70. inline static void convert_c0o1(w128_t *w) {
  71. w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128);
  72. }
  73. /**
  74. * This function converts the double precision floating point numbers which
  75. * distribute uniformly in the range [1, 2) to those which distribute uniformly
  76. * in the range (0, 1].
  77. * @param w 128bit stracture of double precision floating point numbers (I/O)
  78. */
  79. inline static void convert_o0c1(w128_t *w) {
  80. w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd);
  81. }
  82. /**
  83. * This function converts the double precision floating point numbers which
  84. * distribute uniformly in the range [1, 2) to those which distribute uniformly
  85. * in the range (0, 1).
  86. * @param w 128bit stracture of double precision floating point numbers (I/O)
  87. */
  88. inline static void convert_o0o1(w128_t *w) {
  89. w->si = _mm_or_si128(w->si, sse2_int_one.i128);
  90. w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128);
  91. }
  92. #else /* standard C and altivec */
  93. /**
  94. * This function converts the double precision floating point numbers which
  95. * distribute uniformly in the range [1, 2) to those which distribute uniformly
  96. * in the range [0, 1).
  97. * @param w 128bit stracture of double precision floating point numbers (I/O)
  98. */
  99. inline static void convert_c0o1(w128_t *w) {
  100. w->d[0] -= 1.0;
  101. w->d[1] -= 1.0;
  102. }
  103. /**
  104. * This function converts the double precision floating point numbers which
  105. * distribute uniformly in the range [1, 2) to those which distribute uniformly
  106. * in the range (0, 1].
  107. * @param w 128bit stracture of double precision floating point numbers (I/O)
  108. */
  109. inline static void convert_o0c1(w128_t *w) {
  110. w->d[0] = 2.0 - w->d[0];
  111. w->d[1] = 2.0 - w->d[1];
  112. }
  113. /**
  114. * This function converts the double precision floating point numbers which
  115. * distribute uniformly in the range [1, 2) to those which distribute uniformly
  116. * in the range (0, 1).
  117. * @param w 128bit stracture of double precision floating point numbers (I/O)
  118. */
  119. inline static void convert_o0o1(w128_t *w) {
  120. w->u[0] |= 1;
  121. w->u[1] |= 1;
  122. w->d[0] -= 1.0;
  123. w->d[1] -= 1.0;
  124. }
  125. #endif
  126. /**
  127. * This function fills the user-specified array with double precision
  128. * floating point pseudorandom numbers of the IEEE 754 format.
  129. * @param dsfmt dsfmt state vector.
  130. * @param array an 128-bit array to be filled by pseudorandom numbers.
  131. * @param size number of 128-bit pseudorandom numbers to be generated.
  132. */
  133. inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array,
  134. int size) {
  135. int i, j;
  136. w128_t lung;
  137. lung = dsfmt->status[DSFMT_N];
  138. do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1],
  139. &lung);
  140. for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) {
  141. do_recursion(&array[i], &dsfmt->status[i],
  142. &dsfmt->status[i + DSFMT_POS1], &lung);
  143. }
  144. for (; i < DSFMT_N; i++) {
  145. do_recursion(&array[i], &dsfmt->status[i],
  146. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  147. }
  148. for (; i < size - DSFMT_N; i++) {
  149. do_recursion(&array[i], &array[i - DSFMT_N],
  150. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  151. }
  152. for (j = 0; j < 2 * DSFMT_N - size; j++) {
  153. dsfmt->status[j] = array[j + size - DSFMT_N];
  154. }
  155. for (; i < size; i++, j++) {
  156. do_recursion(&array[i], &array[i - DSFMT_N],
  157. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  158. dsfmt->status[j] = array[i];
  159. }
  160. dsfmt->status[DSFMT_N] = lung;
  161. }
  162. /**
  163. * This function fills the user-specified array with double precision
  164. * floating point pseudorandom numbers of the IEEE 754 format.
  165. * @param dsfmt dsfmt state vector.
  166. * @param array an 128-bit array to be filled by pseudorandom numbers.
  167. * @param size number of 128-bit pseudorandom numbers to be generated.
  168. */
  169. inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array,
  170. int size) {
  171. int i, j;
  172. w128_t lung;
  173. lung = dsfmt->status[DSFMT_N];
  174. do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1],
  175. &lung);
  176. for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) {
  177. do_recursion(&array[i], &dsfmt->status[i],
  178. &dsfmt->status[i + DSFMT_POS1], &lung);
  179. }
  180. for (; i < DSFMT_N; i++) {
  181. do_recursion(&array[i], &dsfmt->status[i],
  182. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  183. }
  184. for (; i < size - DSFMT_N; i++) {
  185. do_recursion(&array[i], &array[i - DSFMT_N],
  186. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  187. convert_c0o1(&array[i - DSFMT_N]);
  188. }
  189. for (j = 0; j < 2 * DSFMT_N - size; j++) {
  190. dsfmt->status[j] = array[j + size - DSFMT_N];
  191. }
  192. for (; i < size; i++, j++) {
  193. do_recursion(&array[i], &array[i - DSFMT_N],
  194. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  195. dsfmt->status[j] = array[i];
  196. convert_c0o1(&array[i - DSFMT_N]);
  197. }
  198. for (i = size - DSFMT_N; i < size; i++) {
  199. convert_c0o1(&array[i]);
  200. }
  201. dsfmt->status[DSFMT_N] = lung;
  202. }
  203. /**
  204. * This function fills the user-specified array with double precision
  205. * floating point pseudorandom numbers of the IEEE 754 format.
  206. * @param dsfmt dsfmt state vector.
  207. * @param array an 128-bit array to be filled by pseudorandom numbers.
  208. * @param size number of 128-bit pseudorandom numbers to be generated.
  209. */
  210. inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array,
  211. int size) {
  212. int i, j;
  213. w128_t lung;
  214. lung = dsfmt->status[DSFMT_N];
  215. do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1],
  216. &lung);
  217. for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) {
  218. do_recursion(&array[i], &dsfmt->status[i],
  219. &dsfmt->status[i + DSFMT_POS1], &lung);
  220. }
  221. for (; i < DSFMT_N; i++) {
  222. do_recursion(&array[i], &dsfmt->status[i],
  223. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  224. }
  225. for (; i < size - DSFMT_N; i++) {
  226. do_recursion(&array[i], &array[i - DSFMT_N],
  227. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  228. convert_o0o1(&array[i - DSFMT_N]);
  229. }
  230. for (j = 0; j < 2 * DSFMT_N - size; j++) {
  231. dsfmt->status[j] = array[j + size - DSFMT_N];
  232. }
  233. for (; i < size; i++, j++) {
  234. do_recursion(&array[i], &array[i - DSFMT_N],
  235. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  236. dsfmt->status[j] = array[i];
  237. convert_o0o1(&array[i - DSFMT_N]);
  238. }
  239. for (i = size - DSFMT_N; i < size; i++) {
  240. convert_o0o1(&array[i]);
  241. }
  242. dsfmt->status[DSFMT_N] = lung;
  243. }
  244. /**
  245. * This function fills the user-specified array with double precision
  246. * floating point pseudorandom numbers of the IEEE 754 format.
  247. * @param dsfmt dsfmt state vector.
  248. * @param array an 128-bit array to be filled by pseudorandom numbers.
  249. * @param size number of 128-bit pseudorandom numbers to be generated.
  250. */
  251. inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array,
  252. int size) {
  253. int i, j;
  254. w128_t lung;
  255. lung = dsfmt->status[DSFMT_N];
  256. do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1],
  257. &lung);
  258. for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) {
  259. do_recursion(&array[i], &dsfmt->status[i],
  260. &dsfmt->status[i + DSFMT_POS1], &lung);
  261. }
  262. for (; i < DSFMT_N; i++) {
  263. do_recursion(&array[i], &dsfmt->status[i],
  264. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  265. }
  266. for (; i < size - DSFMT_N; i++) {
  267. do_recursion(&array[i], &array[i - DSFMT_N],
  268. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  269. convert_o0c1(&array[i - DSFMT_N]);
  270. }
  271. for (j = 0; j < 2 * DSFMT_N - size; j++) {
  272. dsfmt->status[j] = array[j + size - DSFMT_N];
  273. }
  274. for (; i < size; i++, j++) {
  275. do_recursion(&array[i], &array[i - DSFMT_N],
  276. &array[i + DSFMT_POS1 - DSFMT_N], &lung);
  277. dsfmt->status[j] = array[i];
  278. convert_o0c1(&array[i - DSFMT_N]);
  279. }
  280. for (i = size - DSFMT_N; i < size; i++) {
  281. convert_o0c1(&array[i]);
  282. }
  283. dsfmt->status[DSFMT_N] = lung;
  284. }
  285. /**
  286. * This function represents a function used in the initialization
  287. * by init_by_array
  288. * @param x 32-bit integer
  289. * @return 32-bit integer
  290. */
  291. static uint32_t ini_func1(uint32_t x) {
  292. return (x ^ (x >> 27)) * (uint32_t)1664525UL;
  293. }
  294. /**
  295. * This function represents a function used in the initialization
  296. * by init_by_array
  297. * @param x 32-bit integer
  298. * @return 32-bit integer
  299. */
  300. static uint32_t ini_func2(uint32_t x) {
  301. return (x ^ (x >> 27)) * (uint32_t)1566083941UL;
  302. }
  303. /**
  304. * This function initializes the internal state array to fit the IEEE
  305. * 754 format.
  306. * @param dsfmt dsfmt state vector.
  307. */
  308. static void initial_mask(dsfmt_t *dsfmt) {
  309. int i;
  310. uint64_t *psfmt;
  311. psfmt = &dsfmt->status[0].u[0];
  312. for (i = 0; i < DSFMT_N * 2; i++) {
  313. psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST;
  314. }
  315. }
  316. /**
  317. * This function certificate the period of 2^{SFMT_MEXP}-1.
  318. * @param dsfmt dsfmt state vector.
  319. */
  320. static void period_certification(dsfmt_t *dsfmt) {
  321. uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2};
  322. uint64_t tmp[2];
  323. uint64_t inner;
  324. int i;
  325. #if (DSFMT_PCV2 & 1) != 1
  326. int j;
  327. uint64_t work;
  328. #endif
  329. tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1);
  330. tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2);
  331. inner = tmp[0] & pcv[0];
  332. inner ^= tmp[1] & pcv[1];
  333. for (i = 32; i > 0; i >>= 1) {
  334. inner ^= inner >> i;
  335. }
  336. inner &= 1;
  337. /* check OK */
  338. if (inner == 1) {
  339. return;
  340. }
  341. /* check NG, and modification */
  342. #if (DSFMT_PCV2 & 1) == 1
  343. dsfmt->status[DSFMT_N].u[1] ^= 1;
  344. #else
  345. for (i = 1; i >= 0; i--) {
  346. work = 1;
  347. for (j = 0; j < 64; j++) {
  348. if ((work & pcv[i]) != 0) {
  349. dsfmt->status[DSFMT_N].u[i] ^= work;
  350. return;
  351. }
  352. work = work << 1;
  353. }
  354. }
  355. #endif
  356. return;
  357. }
  358. /*----------------
  359. PUBLIC FUNCTIONS
  360. ----------------*/
  361. /**
  362. * This function returns the identification string. The string shows
  363. * the Mersenne exponent, and all parameters of this generator.
  364. * @return id string.
  365. */
  366. const char *dsfmt_get_idstring(void) {
  367. return DSFMT_IDSTR;
  368. }
  369. /**
  370. * This function returns the minimum size of array used for \b
  371. * fill_array functions.
  372. * @return minimum size of array used for fill_array functions.
  373. */
  374. int dsfmt_get_min_array_size(void) {
  375. return DSFMT_N64;
  376. }
  377. /**
  378. * This function fills the internal state array with double precision
  379. * floating point pseudorandom numbers of the IEEE 754 format.
  380. * @param dsfmt dsfmt state vector.
  381. */
  382. void dsfmt_gen_rand_all(dsfmt_t *dsfmt) {
  383. int i;
  384. w128_t lung;
  385. lung = dsfmt->status[DSFMT_N];
  386. do_recursion(&dsfmt->status[0], &dsfmt->status[0],
  387. &dsfmt->status[DSFMT_POS1], &lung);
  388. for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) {
  389. do_recursion(&dsfmt->status[i], &dsfmt->status[i],
  390. &dsfmt->status[i + DSFMT_POS1], &lung);
  391. }
  392. for (; i < DSFMT_N; i++) {
  393. do_recursion(&dsfmt->status[i], &dsfmt->status[i],
  394. &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung);
  395. }
  396. dsfmt->status[DSFMT_N] = lung;
  397. }
  398. /**
  399. * This function generates double precision floating point
  400. * pseudorandom numbers which distribute in the range [1, 2) to the
  401. * specified array[] by one call. The number of pseudorandom numbers
  402. * is specified by the argument \b size, which must be at least (SFMT_MEXP
  403. * / 128) * 2 and a multiple of two. The function
  404. * get_min_array_size() returns this minimum size. The generation by
  405. * this function is much faster than the following fill_array_xxx functions.
  406. *
  407. * For initialization, init_gen_rand() or init_by_array() must be called
  408. * before the first call of this function. This function can not be
  409. * used after calling genrand_xxx functions, without initialization.
  410. *
  411. * @param dsfmt dsfmt state vector.
  412. * @param array an array where pseudorandom numbers are filled
  413. * by this function. The pointer to the array must be "aligned"
  414. * (namely, must be a multiple of 16) in the SIMD version, since it
  415. * refers to the address of a 128-bit integer. In the standard C
  416. * version, the pointer is arbitrary.
  417. *
  418. * @param size the number of 64-bit pseudorandom integers to be
  419. * generated. size must be a multiple of 2, and greater than or equal
  420. * to (SFMT_MEXP / 128) * 2.
  421. *
  422. * @note \b memalign or \b posix_memalign is available to get aligned
  423. * memory. Mac OSX doesn't have these functions, but \b malloc of OSX
  424. * returns the pointer to the aligned memory block.
  425. */
  426. void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) {
  427. assert(size % 2 == 0);
  428. assert(size >= DSFMT_N64);
  429. gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2);
  430. }
  431. /**
  432. * This function generates double precision floating point
  433. * pseudorandom numbers which distribute in the range (0, 1] to the
  434. * specified array[] by one call. This function is the same as
  435. * fill_array_close1_open2() except the distribution range.
  436. *
  437. * @param dsfmt dsfmt state vector.
  438. * @param array an array where pseudorandom numbers are filled
  439. * by this function.
  440. * @param size the number of pseudorandom numbers to be generated.
  441. * see also \sa fill_array_close1_open2()
  442. */
  443. void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) {
  444. assert(size % 2 == 0);
  445. assert(size >= DSFMT_N64);
  446. gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2);
  447. }
  448. /**
  449. * This function generates double precision floating point
  450. * pseudorandom numbers which distribute in the range [0, 1) to the
  451. * specified array[] by one call. This function is the same as
  452. * fill_array_close1_open2() except the distribution range.
  453. *
  454. * @param array an array where pseudorandom numbers are filled
  455. * by this function.
  456. * @param dsfmt dsfmt state vector.
  457. * @param size the number of pseudorandom numbers to be generated.
  458. * see also \sa fill_array_close1_open2()
  459. */
  460. void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) {
  461. assert(size % 2 == 0);
  462. assert(size >= DSFMT_N64);
  463. gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2);
  464. }
  465. /**
  466. * This function generates double precision floating point
  467. * pseudorandom numbers which distribute in the range (0, 1) to the
  468. * specified array[] by one call. This function is the same as
  469. * fill_array_close1_open2() except the distribution range.
  470. *
  471. * @param dsfmt dsfmt state vector.
  472. * @param array an array where pseudorandom numbers are filled
  473. * by this function.
  474. * @param size the number of pseudorandom numbers to be generated.
  475. * see also \sa fill_array_close1_open2()
  476. */
  477. void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) {
  478. assert(size % 2 == 0);
  479. assert(size >= DSFMT_N64);
  480. gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2);
  481. }
  482. #if defined(__INTEL_COMPILER)
  483. # pragma warning(disable:981)
  484. #endif
  485. /**
  486. * This function initializes the internal state array with a 32-bit
  487. * integer seed.
  488. * @param dsfmt dsfmt state vector.
  489. * @param seed a 32-bit integer used as the seed.
  490. * @param mexp caller's mersenne expornent
  491. */
  492. void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) {
  493. int i;
  494. uint32_t *psfmt;
  495. /* make sure caller program is compiled with the same MEXP */
  496. if (mexp != dsfmt_mexp) {
  497. fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n");
  498. exit(1);
  499. }
  500. psfmt = &dsfmt->status[0].u32[0];
  501. psfmt[idxof(0)] = seed;
  502. for (i = 1; i < (DSFMT_N + 1) * 4; i++) {
  503. psfmt[idxof(i)] = 1812433253UL
  504. * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i;
  505. }
  506. initial_mask(dsfmt);
  507. period_certification(dsfmt);
  508. dsfmt->idx = DSFMT_N64;
  509. }
  510. /**
  511. * This function initializes the internal state array,
  512. * with an array of 32-bit integers used as the seeds
  513. * @param dsfmt dsfmt state vector.
  514. * @param init_key the array of 32-bit integers, used as a seed.
  515. * @param key_length the length of init_key.
  516. * @param mexp caller's mersenne expornent
  517. */
  518. void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[],
  519. int key_length, int mexp) {
  520. int i, j, count;
  521. uint32_t r;
  522. uint32_t *psfmt32;
  523. int lag;
  524. int mid;
  525. int size = (DSFMT_N + 1) * 4; /* pulmonary */
  526. /* make sure caller program is compiled with the same MEXP */
  527. if (mexp != dsfmt_mexp) {
  528. fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n");
  529. exit(1);
  530. }
  531. if (size >= 623) {
  532. lag = 11;
  533. } else if (size >= 68) {
  534. lag = 7;
  535. } else if (size >= 39) {
  536. lag = 5;
  537. } else {
  538. lag = 3;
  539. }
  540. mid = (size - lag) / 2;
  541. psfmt32 = &dsfmt->status[0].u32[0];
  542. memset(dsfmt->status, 0x8b, sizeof(dsfmt->status));
  543. if (key_length + 1 > size) {
  544. count = key_length + 1;
  545. } else {
  546. count = size;
  547. }
  548. r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)]
  549. ^ psfmt32[idxof((size - 1) % size)]);
  550. psfmt32[idxof(mid % size)] += r;
  551. r += key_length;
  552. psfmt32[idxof((mid + lag) % size)] += r;
  553. psfmt32[idxof(0)] = r;
  554. count--;
  555. for (i = 1, j = 0; (j < count) && (j < key_length); j++) {
  556. r = ini_func1(psfmt32[idxof(i)]
  557. ^ psfmt32[idxof((i + mid) % size)]
  558. ^ psfmt32[idxof((i + size - 1) % size)]);
  559. psfmt32[idxof((i + mid) % size)] += r;
  560. r += init_key[j] + i;
  561. psfmt32[idxof((i + mid + lag) % size)] += r;
  562. psfmt32[idxof(i)] = r;
  563. i = (i + 1) % size;
  564. }
  565. for (; j < count; j++) {
  566. r = ini_func1(psfmt32[idxof(i)]
  567. ^ psfmt32[idxof((i + mid) % size)]
  568. ^ psfmt32[idxof((i + size - 1) % size)]);
  569. psfmt32[idxof((i + mid) % size)] += r;
  570. r += i;
  571. psfmt32[idxof((i + mid + lag) % size)] += r;
  572. psfmt32[idxof(i)] = r;
  573. i = (i + 1) % size;
  574. }
  575. for (j = 0; j < size; j++) {
  576. r = ini_func2(psfmt32[idxof(i)]
  577. + psfmt32[idxof((i + mid) % size)]
  578. + psfmt32[idxof((i + size - 1) % size)]);
  579. psfmt32[idxof((i + mid) % size)] ^= r;
  580. r -= i;
  581. psfmt32[idxof((i + mid + lag) % size)] ^= r;
  582. psfmt32[idxof(i)] = r;
  583. i = (i + 1) % size;
  584. }
  585. initial_mask(dsfmt);
  586. period_certification(dsfmt);
  587. dsfmt->idx = DSFMT_N64;
  588. }
  589. #if defined(__INTEL_COMPILER)
  590. # pragma warning(default:981)
  591. #endif
  592. #if defined(__cplusplus)
  593. }
  594. #endif