IT++ Logo
random_dsfmt.h
Go to the documentation of this file.
1 
29 #ifndef RANDOM_DSFMT_H
30 #define RANDOM_DSFMT_H
31 
32 #include <itpp/base/ittypes.h>
33 #include <itpp/base/vec.h>
34 #include <cstring> // required for memset()
35 #include <ctime>
36 #include <limits>
37 #include <itpp/itexports.h>
38 
39 #if defined(__SSE2__)
40 # include <emmintrin.h>
41 #endif
42 
43 namespace itpp
44 {
45 
46 namespace random_details
47 {
48 
96 template < int MEXP, int POS1, int SL1, uint64_t MSK1, uint64_t MSK2,
97  uint64_t FIX1_V, uint64_t FIX2_V, uint64_t PCV1_V, uint64_t PCV2_V >
98 class ITPP_EXPORT DSFMT
99 {
100 
101 public:
102  //make usefull constants available in typedefed definitions
103  static const int N = (MEXP - 128) / 104 + 1;
104  static const uint64_t FIX1 = FIX1_V;
105  static const uint64_t FIX2 = FIX2_V;
106  static const uint64_t PCV1 = PCV1_V;
107  static const uint64_t PCV2 = PCV2_V;
108 
109 #if defined(__SSE2__)
110  static const uint32_t MSK32_1 = static_cast<uint32_t>((MSK1 >> 32) & (0xffffffffULL));
111  static const uint32_t MSK32_2 = static_cast<uint32_t>(MSK1 & (0xffffffffULL));
112  static const uint32_t MSK32_3 = static_cast<uint32_t>((MSK2 >> 32) & (0xffffffffULL));
113  static const uint32_t MSK32_4 = static_cast<uint32_t>(MSK2 & (0xffffffffULL));
114 #endif
115 
122  struct Context {
124  union W128_T {
125 #if defined(__SSE2__)
126  __m128i si;
127  __m128d sd;
128 #endif // __SSE2__
129  uint64_t u[2];
130  uint32_t u32[4];
131  double d[2];
132  };
134  typedef union W128_T w128_t;
136  w128_t status[N + 1];
138  int idx;
140  unsigned int last_seed;
141  };
142 
143 public:
145  DSFMT(Context& c): _context(c) {}
146 
154  void init_gen_rand(unsigned int seed) {
155  uint32_t *psfmt = &_context.status[0].u32[0];
156  psfmt[idxof(0)] = seed;
157  for(int i = 1; i < (N + 1) * 4; i++) {
158  psfmt[idxof(i)] = 1812433253UL
159  * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i;
160  }
161  initial_mask();
162  period_certification();
163  _context.idx = Nx2;
164  _context.last_seed = seed;
165  }
166 
168  uint32_t genrand_uint32() {
169  uint64_t *psfmt64 = &_context.status[0].u[0];
170  if(_context.idx >= Nx2) {
171  dsfmt_gen_rand_all();
172  _context.idx = 0;
173  }
174  return (uint32_t)(psfmt64[_context.idx++] & 0xffffffffU);
175  }
176 
187  double *psfmt64 = &_context.status[0].d[0];
188  if(_context.idx >= Nx2) {
189  dsfmt_gen_rand_all();
190  _context.idx = 0;
191  }
192  return psfmt64[_context.idx++];
193  }
194 
203  double genrand_open_open() {
204  double *dsfmt64 = &_context.status[0].d[0];
205  union {
206  double d;
207  uint64_t u;
208  } r;
209 
210  if(_context.idx >= Nx2) {
211  dsfmt_gen_rand_all();
212  _context.idx = 0;
213  }
214  r.d = dsfmt64[_context.idx++];
215  r.u |= 1;
216  return r.d - 1.0;
217  }
218 
219 private:
220  static const int Nx2 = N * 2;
221  static const unsigned int SR = 12U;
223  static const bool bigendian;
224 
225 #if defined(__SSE2__)
226 
227  static const __m128i sse2_param_mask;
228 #endif // __SSE2__
229 
231  Context& _context;
232 
233 
238  static int idxof(int i) { return (bigendian ? (i ^ 1) : i); }
239 
244  void initial_mask() {
245 
246  const uint64_t LOW_MASK = 0x000fffffffffffffULL;
247  const uint64_t HIGH_CONST = 0x3ff0000000000000ULL;
248 
249  uint64_t *psfmt = &_context.status[0].u[0];
250  for(int i = 0; i < Nx2; i++) {
251  psfmt[i] = (psfmt[i] & LOW_MASK) | HIGH_CONST;
252  }
253  }
254 
256  void period_certification() {
257  uint64_t pcv[2] = {PCV1, PCV2};
258  uint64_t tmp[2];
259  uint64_t inner;
260 
261  tmp[0] = (_context.status[N].u[0] ^ FIX1);
262  tmp[1] = (_context.status[N].u[1] ^ FIX2);
263 
264  inner = tmp[0] & pcv[0];
265  inner ^= tmp[1] & pcv[1];
266  for(int i = 32; i > 0; i >>= 1) {
267  inner ^= inner >> i;
268  }
269  inner &= 1;
270  /* check OK */
271  if(inner == 1) {
272  return;
273  }
274  /* check NG, and modification */
275 #if (PCV2 & 1) == 1
276  _context.status[N].u[1] ^= 1;
277 #else
278  uint64_t work;
279  for(int i = 1; i >= 0; i--) {
280  work = 1;
281  for(int j = 0; j < 64; j++) {
282  if((work & pcv[i]) != 0) {
283  _context.status[N].u[i] ^= work;
284  return;
285  }
286  work = work << 1;
287  }
288  }
289 #endif // (PCV2 & 1) == 1
290  return;
291  }
292 
300  static void do_recursion(typename Context::w128_t *r, typename Context::w128_t *a, typename Context::w128_t *b, typename Context::w128_t *lung) {
301 #if defined(__SSE2__)
302  const unsigned int SSE2_SHUFF = 0x1bU;
303 
304  __m128i x = a->si;
305  __m128i z = _mm_slli_epi64(x, SL1);
306  __m128i y = _mm_shuffle_epi32(lung->si, SSE2_SHUFF);
307  z = _mm_xor_si128(z, b->si);
308  y = _mm_xor_si128(y, z);
309 
310  __m128i v = _mm_srli_epi64(y, SR);
311  __m128i w = _mm_and_si128(y, sse2_param_mask);
312  v = _mm_xor_si128(v, x);
313  v = _mm_xor_si128(v, w);
314  r->si = v;
315  lung->si = y;
316 #else // standard C++
317  uint64_t t0 = a->u[0];
318  uint64_t t1 = a->u[1];
319  uint64_t L0 = lung->u[0];
320  uint64_t L1 = lung->u[1];
321  lung->u[0] = (t0 << SL1) ^ (L1 >> 32) ^ (L1 << 32) ^ b->u[0];
322  lung->u[1] = (t1 << SL1) ^ (L0 >> 32) ^ (L0 << 32) ^ b->u[1];
323  r->u[0] = (lung->u[0] >> SR) ^ (lung->u[0] & MSK1) ^ t0;
324  r->u[1] = (lung->u[1] >> SR) ^ (lung->u[1] & MSK2) ^ t1;
325 #endif // __SSE2__
326  }
327 
332  void dsfmt_gen_rand_all() {
333  int i;
334  typename Context::w128_t *status = _context.status;
335  typename Context::w128_t lung = status[N];
336  do_recursion(&status[0], &status[0], &status[POS1], &lung);
337  for(i = 1; i < N - POS1; i++) {
338  do_recursion(&status[i], &status[i], &status[i + POS1], &lung);
339  }
340  for(; i < N; i++) {
341  do_recursion(&status[i], &status[i], &status[i + POS1 - N], &lung);
342  }
343  status[N] = lung;
344  }
345 
346 };
347 
348 
349 // ----------------------------------------------------------------------
350 // typedefs of different RNG
351 // ----------------------------------------------------------------------
352 
353 typedef DSFMT < 521, 3, 25,
354  0x000fbfefff77efffULL, 0x000ffeebfbdfbfdfULL,
355  0xcfb393d661638469ULL, 0xc166867883ae2adbULL,
356  0xccaa588000000000ULL, 0x0000000000000001ULL > DSFMT_521_RNG;
357 
358 typedef DSFMT < 1279, 9, 19,
359  0x000efff7ffddffeeULL, 0x000fbffffff77fffULL,
360  0xb66627623d1a31beULL, 0x04b6c51147b6109bULL,
361  0x7049f2da382a6aebULL, 0xde4ca84a40000001ULL > DSFMT_1279_RNG;
362 
363 typedef DSFMT < 2203, 7, 19,
364  0x000fdffff5edbfffULL, 0x000f77fffffffbfeULL,
365  0xb14e907a39338485ULL, 0xf98f0735c637ef90ULL,
366  0x8000000000000000ULL, 0x0000000000000001ULL > DSFMT_2203_RNG;
367 
368 typedef DSFMT < 4253, 19, 19,
369  0x0007b7fffef5feffULL, 0x000ffdffeffefbfcULL,
370  0x80901b5fd7a11c65ULL, 0x5a63ff0e7cb0ba74ULL,
371  0x1ad277be12000000ULL, 0x0000000000000001ULL > DSFMT_4253_RNG;
372 
373 typedef DSFMT < 11213, 37, 19,
374  0x000ffffffdf7fffdULL, 0x000dfffffff6bfffULL,
375  0xd0ef7b7c75b06793ULL, 0x9c50ff4caae0a641ULL,
376  0x8234c51207c80000ULL, 0x0000000000000001ULL > DSFMT_11213_RNG;
377 
378 typedef DSFMT < 19937, 117, 19,
379  0x000ffafffffffb3fULL, 0x000ffdfffc90fffdULL,
380  0x90014964b32f4329ULL, 0x3b8d12ac548a7c7aULL,
381  0x3d84e1ac0dc82880ULL, 0x0000000000000001ULL > DSFMT_19937_RNG;
382 
383 
384 
396 
397 
398 
409 
410 ITPP_EXPORT ActiveDSFMT::Context& lc_get();
412 ITPP_EXPORT bool lc_is_initialized();
414 ITPP_EXPORT void lc_mark_initialized();
415 
417 
418 }
419 
420 } // namespace itpp
421 
422 #endif // #ifndef RANDOM_DSFMT_H
SourceForge Logo

Generated on Sat May 25 2013 16:32:19 for IT++ by Doxygen 1.8.2