3 * @brief double precision SIMD-oriented Fast Mersenne Twister (dSFMT)
4 * based on IEEE 754 format.
6 * @author Mutsuo Saito (Hiroshima University)
7 * @author Makoto Matsumoto (Hiroshima University)
9 * Copyright (C) 2007,2008 Mutsuo Saito, Makoto Matsumoto and Hiroshima
10 * University. All rights reserved.
12 * The new BSD License is applied to this software, see LICENSE.txt
17 #include "dSFMT-params.h"
19 /** dsfmt internal state vector */
20 dsfmt_t dsfmt_global_data
;
21 /** dsfmt mexp for check */
22 static const int dsfmt_mexp
= DSFMT_MEXP
;
27 inline static uint32_t ini_func1(uint32_t x
);
28 inline static uint32_t ini_func2(uint32_t x
);
29 inline static void gen_rand_array_c1o2(dsfmt_t
*dsfmt
, w128_t
*array
,
31 inline static void gen_rand_array_c0o1(dsfmt_t
*dsfmt
, w128_t
*array
,
33 inline static void gen_rand_array_o0c1(dsfmt_t
*dsfmt
, w128_t
*array
,
35 inline static void gen_rand_array_o0o1(dsfmt_t
*dsfmt
, w128_t
*array
,
37 inline static int idxof(int i
);
38 static void initial_mask(dsfmt_t
*dsfmt
);
39 static void period_certification(dsfmt_t
*dsfmt
);
41 #if defined(HAVE_SSE2)
42 # include <emmintrin.h>
43 /** mask data for sse2 */
44 static __m128i sse2_param_mask
;
45 /** 1 in 64bit for sse2 */
46 static __m128i sse2_int_one
;
47 /** 2.0 double for sse2 */
48 static __m128d sse2_double_two
;
49 /** -1.0 double for sse2 */
50 static __m128d sse2_double_m_one
;
52 static void setup_const(void);
56 * This function simulate a 32-bit array index overlapped to 64-bit
57 * array of LITTLE ENDIAN in BIG ENDIAN machine.
59 #if defined(DSFMT_BIG_ENDIAN)
60 inline static int idxof(int i
) {
64 inline static int idxof(int i
) {
70 * This function represents the recursion formula.
72 * @param a a 128-bit part of the internal state array
73 * @param b a 128-bit part of the internal state array
74 * @param lung a 128-bit part of the internal state array
76 #if defined(HAVE_ALTIVEC)
77 inline static void do_recursion(w128_t
*r
, w128_t
*a
, w128_t
* b
,
79 const vector
unsigned char sl1
= ALTI_SL1
;
80 const vector
unsigned char sl1_perm
= ALTI_SL1_PERM
;
81 const vector
unsigned int sl1_msk
= ALTI_SL1_MSK
;
82 const vector
unsigned char sr1
= ALTI_SR
;
83 const vector
unsigned char sr1_perm
= ALTI_SR_PERM
;
84 const vector
unsigned int sr1_msk
= ALTI_SR_MSK
;
85 const vector
unsigned char perm
= ALTI_PERM
;
86 const vector
unsigned int msk1
= ALTI_MSK
;
87 vector
unsigned int w
, x
, y
, z
;
91 x
= vec_perm(w
, (vector
unsigned int)perm
, perm
);
92 y
= vec_perm(z
, sl1_perm
, sl1_perm
);
94 y
= vec_and(y
, sl1_msk
);
97 x
= vec_perm(w
, (vector
unsigned int)sr1_perm
, sr1_perm
);
99 x
= vec_and(x
, sr1_msk
);
100 y
= vec_and(w
, msk1
);
102 r
->s
= vec_xor(z
, x
);
105 #elif defined(HAVE_SSE2)
107 * This function setup some constant variables for SSE2.
109 static void setup_const(void) {
110 static int first
= 1;
114 sse2_param_mask
= _mm_set_epi32(DSFMT_MSK32_3
, DSFMT_MSK32_4
,
115 DSFMT_MSK32_1
, DSFMT_MSK32_2
);
116 sse2_int_one
= _mm_set_epi32(0, 1, 0, 1);
117 sse2_double_two
= _mm_set_pd(2.0, 2.0);
118 sse2_double_m_one
= _mm_set_pd(-1.0, -1.0);
123 * This function represents the recursion formula.
124 * @param r output 128-bit
125 * @param a a 128-bit part of the internal state array
126 * @param b a 128-bit part of the internal state array
127 * @param d a 128-bit part of the internal state array (I/O)
129 inline static void do_recursion(w128_t
*r
, w128_t
*a
, w128_t
*b
, w128_t
*u
) {
130 __m128i v
, w
, x
, y
, z
;
133 z
= _mm_slli_epi64(x
, DSFMT_SL1
);
134 y
= _mm_shuffle_epi32(u
->si
, SSE2_SHUFF
);
135 z
= _mm_xor_si128(z
, b
->si
);
136 y
= _mm_xor_si128(y
, z
);
138 v
= _mm_srli_epi64(y
, DSFMT_SR
);
139 w
= _mm_and_si128(y
, sse2_param_mask
);
140 v
= _mm_xor_si128(v
, x
);
141 v
= _mm_xor_si128(v
, w
);
145 #else /* standard C */
147 * This function represents the recursion formula.
148 * @param r output 128-bit
149 * @param a a 128-bit part of the internal state array
150 * @param b a 128-bit part of the internal state array
151 * @param lung a 128-bit part of the internal state array (I/O)
153 inline static void do_recursion(w128_t
*r
, w128_t
*a
, w128_t
* b
,
155 uint64_t t0
, t1
, L0
, L1
;
161 lung
->u
[0] = (t0
<< DSFMT_SL1
) ^ (L1
>> 32) ^ (L1
<< 32) ^ b
->u
[0];
162 lung
->u
[1] = (t1
<< DSFMT_SL1
) ^ (L0
>> 32) ^ (L0
<< 32) ^ b
->u
[1];
163 r
->u
[0] = (lung
->u
[0] >> DSFMT_SR
) ^ (lung
->u
[0] & DSFMT_MSK1
) ^ t0
;
164 r
->u
[1] = (lung
->u
[1] >> DSFMT_SR
) ^ (lung
->u
[1] & DSFMT_MSK2
) ^ t1
;
168 #if defined(HAVE_SSE2)
170 * This function converts the double precision floating point numbers which
171 * distribute uniformly in the range [1, 2) to those which distribute uniformly
172 * in the range [0, 1).
173 * @param w 128bit stracture of double precision floating point numbers (I/O)
175 inline static void convert_c0o1(w128_t
*w
) {
176 w
->sd
= _mm_add_pd(w
->sd
, sse2_double_m_one
);
180 * This function converts the double precision floating point numbers which
181 * distribute uniformly in the range [1, 2) to those which distribute uniformly
182 * in the range (0, 1].
183 * @param w 128bit stracture of double precision floating point numbers (I/O)
185 inline static void convert_o0c1(w128_t
*w
) {
186 w
->sd
= _mm_sub_pd(sse2_double_two
, w
->sd
);
190 * This function converts the double precision floating point numbers which
191 * distribute uniformly in the range [1, 2) to those which distribute uniformly
192 * in the range (0, 1).
193 * @param w 128bit stracture of double precision floating point numbers (I/O)
195 inline static void convert_o0o1(w128_t
*w
) {
196 w
->si
= _mm_or_si128(w
->si
, sse2_int_one
);
197 w
->sd
= _mm_add_pd(w
->sd
, sse2_double_m_one
);
199 #else /* standard C and altivec */
201 * This function converts the double precision floating point numbers which
202 * distribute uniformly in the range [1, 2) to those which distribute uniformly
203 * in the range [0, 1).
204 * @param w 128bit stracture of double precision floating point numbers (I/O)
206 inline static void convert_c0o1(w128_t
*w
) {
212 * This function converts the double precision floating point numbers which
213 * distribute uniformly in the range [1, 2) to those which distribute uniformly
214 * in the range (0, 1].
215 * @param w 128bit stracture of double precision floating point numbers (I/O)
217 inline static void convert_o0c1(w128_t
*w
) {
218 w
->d
[0] = 2.0 - w
->d
[0];
219 w
->d
[1] = 2.0 - w
->d
[1];
223 * This function converts the double precision floating point numbers which
224 * distribute uniformly in the range [1, 2) to those which distribute uniformly
225 * in the range (0, 1).
226 * @param w 128bit stracture of double precision floating point numbers (I/O)
228 inline static void convert_o0o1(w128_t
*w
) {
237 * This function fills the user-specified array with double precision
238 * floating point pseudorandom numbers of the IEEE 754 format.
239 * @param dsfmt dsfmt state vector.
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.
243 inline static void gen_rand_array_c1o2(dsfmt_t
*dsfmt
, w128_t
*array
,
248 lung
= dsfmt
->status
[DSFMT_N
];
249 do_recursion(&array
[0], &dsfmt
->status
[0], &dsfmt
->status
[DSFMT_POS1
],
251 for (i
= 1; i
< DSFMT_N
- DSFMT_POS1
; i
++) {
252 do_recursion(&array
[i
], &dsfmt
->status
[i
],
253 &dsfmt
->status
[i
+ DSFMT_POS1
], &lung
);
255 for (; i
< DSFMT_N
; i
++) {
256 do_recursion(&array
[i
], &dsfmt
->status
[i
],
257 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
259 for (; i
< size
- DSFMT_N
; i
++) {
260 do_recursion(&array
[i
], &array
[i
- DSFMT_N
],
261 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
263 for (j
= 0; j
< 2 * DSFMT_N
- size
; j
++) {
264 dsfmt
->status
[j
] = array
[j
+ size
- DSFMT_N
];
266 for (; i
< size
; i
++, j
++) {
267 do_recursion(&array
[i
], &array
[i
- DSFMT_N
],
268 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
269 dsfmt
->status
[j
] = array
[i
];
271 dsfmt
->status
[DSFMT_N
] = lung
;
275 * This function fills the user-specified array with double precision
276 * floating point pseudorandom numbers of the IEEE 754 format.
277 * @param dsfmt dsfmt state vector.
278 * @param array an 128-bit array to be filled by pseudorandom numbers.
279 * @param size number of 128-bit pseudorandom numbers to be generated.
281 inline static void gen_rand_array_c0o1(dsfmt_t
*dsfmt
, w128_t
*array
,
286 lung
= dsfmt
->status
[DSFMT_N
];
287 do_recursion(&array
[0], &dsfmt
->status
[0], &dsfmt
->status
[DSFMT_POS1
],
289 for (i
= 1; i
< DSFMT_N
- DSFMT_POS1
; i
++) {
290 do_recursion(&array
[i
], &dsfmt
->status
[i
],
291 &dsfmt
->status
[i
+ DSFMT_POS1
], &lung
);
293 for (; i
< DSFMT_N
; i
++) {
294 do_recursion(&array
[i
], &dsfmt
->status
[i
],
295 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
297 for (; i
< size
- DSFMT_N
; i
++) {
298 do_recursion(&array
[i
], &array
[i
- DSFMT_N
],
299 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
300 convert_c0o1(&array
[i
- DSFMT_N
]);
302 for (j
= 0; j
< 2 * DSFMT_N
- size
; j
++) {
303 dsfmt
->status
[j
] = array
[j
+ size
- DSFMT_N
];
305 for (; i
< size
; i
++, j
++) {
306 do_recursion(&array
[i
], &array
[i
- DSFMT_N
],
307 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
308 dsfmt
->status
[j
] = array
[i
];
309 convert_c0o1(&array
[i
- DSFMT_N
]);
311 for (i
= size
- DSFMT_N
; i
< size
; i
++) {
312 convert_c0o1(&array
[i
]);
314 dsfmt
->status
[DSFMT_N
] = lung
;
318 * This function fills the user-specified array with double precision
319 * floating point pseudorandom numbers of the IEEE 754 format.
320 * @param dsfmt dsfmt state vector.
321 * @param array an 128-bit array to be filled by pseudorandom numbers.
322 * @param size number of 128-bit pseudorandom numbers to be generated.
324 inline static void gen_rand_array_o0o1(dsfmt_t
*dsfmt
, w128_t
*array
,
329 lung
= dsfmt
->status
[DSFMT_N
];
330 do_recursion(&array
[0], &dsfmt
->status
[0], &dsfmt
->status
[DSFMT_POS1
],
332 for (i
= 1; i
< DSFMT_N
- DSFMT_POS1
; i
++) {
333 do_recursion(&array
[i
], &dsfmt
->status
[i
],
334 &dsfmt
->status
[i
+ DSFMT_POS1
], &lung
);
336 for (; i
< DSFMT_N
; i
++) {
337 do_recursion(&array
[i
], &dsfmt
->status
[i
],
338 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
340 for (; i
< size
- DSFMT_N
; i
++) {
341 do_recursion(&array
[i
], &array
[i
- DSFMT_N
],
342 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
343 convert_o0o1(&array
[i
- DSFMT_N
]);
345 for (j
= 0; j
< 2 * DSFMT_N
- size
; j
++) {
346 dsfmt
->status
[j
] = array
[j
+ size
- DSFMT_N
];
348 for (; i
< size
; i
++, j
++) {
349 do_recursion(&array
[i
], &array
[i
- DSFMT_N
],
350 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
351 dsfmt
->status
[j
] = array
[i
];
352 convert_o0o1(&array
[i
- DSFMT_N
]);
354 for (i
= size
- DSFMT_N
; i
< size
; i
++) {
355 convert_o0o1(&array
[i
]);
357 dsfmt
->status
[DSFMT_N
] = lung
;
361 * This function fills the user-specified array with double precision
362 * floating point pseudorandom numbers of the IEEE 754 format.
363 * @param dsfmt dsfmt state vector.
364 * @param array an 128-bit array to be filled by pseudorandom numbers.
365 * @param size number of 128-bit pseudorandom numbers to be generated.
367 inline static void gen_rand_array_o0c1(dsfmt_t
*dsfmt
, w128_t
*array
,
372 lung
= dsfmt
->status
[DSFMT_N
];
373 do_recursion(&array
[0], &dsfmt
->status
[0], &dsfmt
->status
[DSFMT_POS1
],
375 for (i
= 1; i
< DSFMT_N
- DSFMT_POS1
; i
++) {
376 do_recursion(&array
[i
], &dsfmt
->status
[i
],
377 &dsfmt
->status
[i
+ DSFMT_POS1
], &lung
);
379 for (; i
< DSFMT_N
; i
++) {
380 do_recursion(&array
[i
], &dsfmt
->status
[i
],
381 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
383 for (; i
< size
- DSFMT_N
; i
++) {
384 do_recursion(&array
[i
], &array
[i
- DSFMT_N
],
385 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
386 convert_o0c1(&array
[i
- DSFMT_N
]);
388 for (j
= 0; j
< 2 * DSFMT_N
- size
; j
++) {
389 dsfmt
->status
[j
] = array
[j
+ size
- DSFMT_N
];
391 for (; i
< size
; i
++, j
++) {
392 do_recursion(&array
[i
], &array
[i
- DSFMT_N
],
393 &array
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
394 dsfmt
->status
[j
] = array
[i
];
395 convert_o0c1(&array
[i
- DSFMT_N
]);
397 for (i
= size
- DSFMT_N
; i
< size
; i
++) {
398 convert_o0c1(&array
[i
]);
400 dsfmt
->status
[DSFMT_N
] = lung
;
404 * This function represents a function used in the initialization
406 * @param x 32-bit integer
407 * @return 32-bit integer
409 static uint32_t ini_func1(uint32_t x
) {
410 return (x
^ (x
>> 27)) * (uint32_t)1664525UL;
414 * This function represents a function used in the initialization
416 * @param x 32-bit integer
417 * @return 32-bit integer
419 static uint32_t ini_func2(uint32_t x
) {
420 return (x
^ (x
>> 27)) * (uint32_t)1566083941UL;
424 * This function initializes the internal state array to fit the IEEE
426 * @param dsfmt dsfmt state vector.
428 static void initial_mask(dsfmt_t
*dsfmt
) {
432 psfmt
= &dsfmt
->status
[0].u
[0];
433 for (i
= 0; i
< DSFMT_N
* 2; i
++) {
434 psfmt
[i
] = (psfmt
[i
] & DSFMT_LOW_MASK
) | DSFMT_HIGH_CONST
;
439 * This function certificate the period of 2^{SFMT_MEXP}-1.
440 * @param dsfmt dsfmt state vector.
442 static void period_certification(dsfmt_t
*dsfmt
) {
443 uint64_t pcv
[2] = {DSFMT_PCV1
, DSFMT_PCV2
};
447 #if (DSFMT_PCV2 & 1) != 1
452 tmp
[0] = (dsfmt
->status
[DSFMT_N
].u
[0] ^ DSFMT_FIX1
);
453 tmp
[1] = (dsfmt
->status
[DSFMT_N
].u
[1] ^ DSFMT_FIX2
);
455 inner
= tmp
[0] & pcv
[0];
456 inner
^= tmp
[1] & pcv
[1];
457 for (i
= 32; i
> 0; i
>>= 1) {
465 /* check NG, and modification */
466 #if (DSFMT_PCV2 & 1) == 1
467 dsfmt
->status
[DSFMT_N
].u
[1] ^= 1;
469 for (i
= 1; i
>= 0; i
--) {
471 for (j
= 0; j
< 64; j
++) {
472 if ((work
& pcv
[i
]) != 0) {
473 dsfmt
->status
[DSFMT_N
].u
[i
] ^= work
;
487 * This function returns the identification string. The string shows
488 * the Mersenne exponent, and all parameters of this generator.
491 const char *dsfmt_get_idstring(void) {
496 * This function returns the minimum size of array used for \b
497 * fill_array functions.
498 * @return minimum size of array used for fill_array functions.
500 int dsfmt_get_min_array_size(void) {
505 * This function fills the internal state array with double precision
506 * floating point pseudorandom numbers of the IEEE 754 format.
507 * @param dsfmt dsfmt state vector.
509 void dsfmt_gen_rand_all(dsfmt_t
*dsfmt
) {
513 lung
= dsfmt
->status
[DSFMT_N
];
514 do_recursion(&dsfmt
->status
[0], &dsfmt
->status
[0],
515 &dsfmt
->status
[DSFMT_POS1
], &lung
);
516 for (i
= 1; i
< DSFMT_N
- DSFMT_POS1
; i
++) {
517 do_recursion(&dsfmt
->status
[i
], &dsfmt
->status
[i
],
518 &dsfmt
->status
[i
+ DSFMT_POS1
], &lung
);
520 for (; i
< DSFMT_N
; i
++) {
521 do_recursion(&dsfmt
->status
[i
], &dsfmt
->status
[i
],
522 &dsfmt
->status
[i
+ DSFMT_POS1
- DSFMT_N
], &lung
);
524 dsfmt
->status
[DSFMT_N
] = lung
;
528 * This function generates double precision floating point
529 * pseudorandom numbers which distribute in the range [1, 2) to the
530 * specified array[] by one call. The number of pseudorandom numbers
531 * is specified by the argument \b size, which must be at least (SFMT_MEXP
532 * / 128) * 2 and a multiple of two. The function
533 * get_min_array_size() returns this minimum size. The generation by
534 * this function is much faster than the following fill_array_xxx functions.
536 * For initialization, init_gen_rand() or init_by_array() must be called
537 * before the first call of this function. This function can not be
538 * used after calling genrand_xxx functions, without initialization.
540 * @param dsfmt dsfmt state vector.
541 * @param array an array where pseudorandom numbers are filled
542 * by this function. The pointer to the array must be "aligned"
543 * (namely, must be a multiple of 16) in the SIMD version, since it
544 * refers to the address of a 128-bit integer. In the standard C
545 * version, the pointer is arbitrary.
547 * @param size the number of 64-bit pseudorandom integers to be
548 * generated. size must be a multiple of 2, and greater than or equal
549 * to (SFMT_MEXP / 128) * 2.
551 * @note \b memalign or \b posix_memalign is available to get aligned
552 * memory. Mac OSX doesn't have these functions, but \b malloc of OSX
553 * returns the pointer to the aligned memory block.
555 void dsfmt_fill_array_close1_open2(dsfmt_t
*dsfmt
, double array
[], int size
) {
556 assert(size
% 2 == 0);
557 assert(size
>= DSFMT_N64
);
558 gen_rand_array_c1o2(dsfmt
, (w128_t
*)array
, size
/ 2);
562 * This function generates double precision floating point
563 * pseudorandom numbers which distribute in the range (0, 1] to the
564 * specified array[] by one call. This function is the same as
565 * fill_array_close1_open2() except the distribution range.
567 * @param dsfmt dsfmt state vector.
568 * @param array an array where pseudorandom numbers are filled
570 * @param size the number of pseudorandom numbers to be generated.
571 * see also \sa fill_array_close1_open2()
573 void dsfmt_fill_array_open_close(dsfmt_t
*dsfmt
, double array
[], int size
) {
574 assert(size
% 2 == 0);
575 assert(size
>= DSFMT_N64
);
576 gen_rand_array_o0c1(dsfmt
, (w128_t
*)array
, size
/ 2);
580 * This function generates double precision floating point
581 * pseudorandom numbers which distribute in the range [0, 1) to the
582 * specified array[] by one call. This function is the same as
583 * fill_array_close1_open2() except the distribution range.
585 * @param array an array where pseudorandom numbers are filled
587 * @param dsfmt dsfmt state vector.
588 * @param size the number of pseudorandom numbers to be generated.
589 * see also \sa fill_array_close1_open2()
591 void dsfmt_fill_array_close_open(dsfmt_t
*dsfmt
, double array
[], int size
) {
592 assert(size
% 2 == 0);
593 assert(size
>= DSFMT_N64
);
594 gen_rand_array_c0o1(dsfmt
, (w128_t
*)array
, size
/ 2);
598 * This function generates double precision floating point
599 * pseudorandom numbers which distribute in the range (0, 1) to the
600 * specified array[] by one call. This function is the same as
601 * fill_array_close1_open2() except the distribution range.
603 * @param dsfmt dsfmt state vector.
604 * @param array an array where pseudorandom numbers are filled
606 * @param size the number of pseudorandom numbers to be generated.
607 * see also \sa fill_array_close1_open2()
609 void dsfmt_fill_array_open_open(dsfmt_t
*dsfmt
, double array
[], int size
) {
610 assert(size
% 2 == 0);
611 assert(size
>= DSFMT_N64
);
612 gen_rand_array_o0o1(dsfmt
, (w128_t
*)array
, size
/ 2);
615 #if defined(__INTEL_COMPILER)
616 # pragma warning(disable:981)
619 * This function initializes the internal state array with a 32-bit
621 * @param dsfmt dsfmt state vector.
622 * @param seed a 32-bit integer used as the seed.
623 * @param mexp caller's mersenne expornent
625 void dsfmt_chk_init_gen_rand(dsfmt_t
*dsfmt
, uint32_t seed
, int mexp
) {
629 /* make sure caller program is compiled with the same MEXP */
630 if (mexp
!= dsfmt_mexp
) {
631 fprintf(stderr
, "DSFMT_MEXP doesn't match with dSFMT.c\n");
634 psfmt
= &dsfmt
->status
[0].u32
[0];
635 psfmt
[idxof(0)] = seed
;
636 for (i
= 1; i
< (DSFMT_N
+ 1) * 4; i
++) {
637 psfmt
[idxof(i
)] = 1812433253UL
638 * (psfmt
[idxof(i
- 1)] ^ (psfmt
[idxof(i
- 1)] >> 30)) + i
;
641 period_certification(dsfmt
);
642 dsfmt
->idx
= DSFMT_N64
;
643 #if defined(HAVE_SSE2)
649 * This function initializes the internal state array,
650 * with an array of 32-bit integers used as the seeds
651 * @param dsfmt dsfmt state vector.
652 * @param init_key the array of 32-bit integers, used as a seed.
653 * @param key_length the length of init_key.
654 * @param mexp caller's mersenne expornent
656 void dsfmt_chk_init_by_array(dsfmt_t
*dsfmt
, uint32_t init_key
[],
657 int key_length
, int mexp
) {
663 int size
= (DSFMT_N
+ 1) * 4; /* pulmonary */
665 /* make sure caller program is compiled with the same MEXP */
666 if (mexp
!= dsfmt_mexp
) {
667 fprintf(stderr
, "DSFMT_MEXP doesn't match with dSFMT.c\n");
672 } else if (size
>= 68) {
674 } else if (size
>= 39) {
679 mid
= (size
- lag
) / 2;
681 psfmt32
= &dsfmt
->status
[0].u32
[0];
682 memset(dsfmt
->status
, 0x8b, sizeof(dsfmt
->status
));
683 if (key_length
+ 1 > size
) {
684 count
= key_length
+ 1;
688 r
= ini_func1(psfmt32
[idxof(0)] ^ psfmt32
[idxof(mid
% size
)]
689 ^ psfmt32
[idxof((size
- 1) % size
)]);
690 psfmt32
[idxof(mid
% size
)] += r
;
692 psfmt32
[idxof((mid
+ lag
) % size
)] += r
;
693 psfmt32
[idxof(0)] = r
;
695 for (i
= 1, j
= 0; (j
< count
) && (j
< key_length
); j
++) {
696 r
= ini_func1(psfmt32
[idxof(i
)]
697 ^ psfmt32
[idxof((i
+ mid
) % size
)]
698 ^ psfmt32
[idxof((i
+ size
- 1) % size
)]);
699 psfmt32
[idxof((i
+ mid
) % size
)] += r
;
700 r
+= init_key
[j
] + i
;
701 psfmt32
[idxof((i
+ mid
+ lag
) % size
)] += r
;
702 psfmt32
[idxof(i
)] = r
;
705 for (; j
< count
; j
++) {
706 r
= ini_func1(psfmt32
[idxof(i
)]
707 ^ psfmt32
[idxof((i
+ mid
) % size
)]
708 ^ psfmt32
[idxof((i
+ size
- 1) % size
)]);
709 psfmt32
[idxof((i
+ mid
) % size
)] += r
;
711 psfmt32
[idxof((i
+ mid
+ lag
) % size
)] += r
;
712 psfmt32
[idxof(i
)] = r
;
715 for (j
= 0; j
< size
; j
++) {
716 r
= ini_func2(psfmt32
[idxof(i
)]
717 + psfmt32
[idxof((i
+ mid
) % size
)]
718 + psfmt32
[idxof((i
+ size
- 1) % size
)]);
719 psfmt32
[idxof((i
+ mid
) % size
)] ^= r
;
721 psfmt32
[idxof((i
+ mid
+ lag
) % size
)] ^= r
;
722 psfmt32
[idxof(i
)] = r
;
726 period_certification(dsfmt
);
727 dsfmt
->idx
= DSFMT_N64
;
728 #if defined(HAVE_SSE2)
732 #if defined(__INTEL_COMPILER)
733 # pragma warning(default:981)