Advertisement
Gassa

randommt.h

Dec 15th, 2018
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.60 KB | None | 0 0
  1. #ifndef __randommt_h__
  2. #define __randommt_h__
  3.  
  4. #define VERSION_A 0
  5. #define VERSION_B 8
  6. #define VERSION_C 459
  7.  
  8. #include <algorithm>
  9. #include <cassert>
  10. #include <cstdarg>
  11. #include <cstdio>
  12. #include <cstring>
  13. #include <ctime>
  14. #include <limits.h>
  15. #include <stdint.h>
  16.  
  17. void initrand (uint32_t seed);
  18. void initrand_str (const char * str);
  19. void initrand_array (const unsigned * key, int len);
  20. void initrand_time ();
  21. uint32_t randhash (const char * str);
  22. inline double rndvalue (void);
  23. inline double rndvalue (double range);
  24. inline double rndvalue (double lo, double hi);
  25. inline uint32_t rndvalue (int range);
  26. inline uint32_t rndvalue (uint32_t range);
  27. inline int32_t rndvalue (int32_t lo, int32_t hi);
  28. inline uint64_t rndvalue (uint64_t range);
  29. inline int64_t rndvalue (int64_t lo, int64_t hi);
  30. template <class T> void rndshuffle (T a, T b);
  31.  
  32. namespace gentools_random_internal
  33. {
  34. const int POW = 19937, MARR = POW >> 5;
  35. const int ARR = MARR + 1, EXTRA = (ARR << 5) - POW;
  36. const int SHIFT = 397, SHIFT_LIM = ARR - SHIFT, MSHIFT = SHIFT - ARR;
  37. const uint32_t LO_BITS = (1U << EXTRA) - 1U, HI_BITS = 0xFFFFFFFF ^ LO_BITS;
  38. const uint32_t A [2] = {0U, 0x9908B0DFU};
  39. const int TSHR1 = 11, TSHL2 = 7, TSHL3 = 15, TSHR4 = 18;
  40. const uint32_t TMASK2 = 0x9D2C5680U, TMASK3 = 0xEFC60000U;
  41. const uint32_t RND_MULT1 = 1812433253U;
  42. const uint32_t RND_MULT2 = 1664525U, RND_MULT3 = 1566083941U;
  43. const uint32_t DEFAULT_SEED = 5489U, ARRAY_SEED = 19650218U;
  44. const double NORM_MULT = 1.0 / 4294967296.0;
  45.  
  46. const int UTEST_LEN = 4;
  47. const uint32_t UTEST_KEY [UTEST_LEN] = {0x123, 0x234, 0x345, 0x456};
  48. const int UTEST_STEPS = 1000;
  49. const uint32_t UTEST_EXPECTED_RESULT = 0xFA0596C7U;
  50.  
  51. uint32_t cur_state [ARR];
  52. int cur_index = ARR + 1;
  53.  
  54. int64_t Time()
  55. {
  56. #ifdef __GNUC__
  57. int64_t res;
  58. asm volatile ("rdtsc" : "=A" (res));
  59. return res;
  60. #else
  61. int low, hi;
  62. __asm
  63. {
  64. rdtsc
  65. mov low, eax
  66. mov hi, edx
  67. }
  68. return ((ll)hi << 32) | low;
  69. #endif
  70. }
  71.  
  72. inline uint32_t generate_element (uint32_t v0, uint32_t v1, uint32_t vshift)
  73. {
  74. uint32_t res, temp;
  75.  
  76. temp = (v0 & HI_BITS) | (v1 & LO_BITS);
  77. res = vshift ^ (temp >> 1) ^ A[temp & 1U];
  78.  
  79. return res;
  80. }
  81.  
  82. inline void generate_array (void)
  83. {
  84. int i;
  85.  
  86. for (i = 0; i < SHIFT_LIM; i++)
  87. cur_state[i] = generate_element (cur_state[i],
  88. cur_state[i + 1],
  89. cur_state[i + SHIFT]);
  90.  
  91. for ( ; i < MARR; i++)
  92. cur_state[i] = generate_element (cur_state[i],
  93. cur_state[i + 1],
  94. cur_state[i + MSHIFT]);
  95.  
  96. cur_state[i] = generate_element (cur_state[i],
  97. cur_state[0],
  98. cur_state[i + MSHIFT]);
  99. }
  100.  
  101. inline uint32_t get_raw (void)
  102. {
  103. if (cur_index >= ARR)
  104. {
  105. if (cur_index > ARR)
  106. initrand (DEFAULT_SEED);
  107. assert (cur_index == ARR); // error if not initialized
  108. cur_index = 0;
  109. generate_array ();
  110. }
  111.  
  112. return cur_state[cur_index++];
  113. }
  114.  
  115. inline uint32_t get_tempered (void)
  116. {
  117. uint32_t val;
  118.  
  119. val = get_raw ();
  120. val ^= val >> TSHR1;
  121. val ^= (val << TSHL2) & TMASK2;
  122. val ^= (val << TSHL3) & TMASK3;
  123. val ^= val >> TSHR4;
  124.  
  125. return val;
  126. }
  127.  
  128. inline void unit_test (void)
  129. {
  130. uint32_t res;
  131. int i;
  132.  
  133. initrand_array (UTEST_KEY, UTEST_LEN);
  134. res = 0;
  135. for (i = 0; i < UTEST_STEPS; i++)
  136. res = res * RND_MULT1 + rndvalue (0);
  137.  
  138. printf ("%08X\n", res);
  139. assert (res == UTEST_EXPECTED_RESULT);
  140. }
  141.  
  142. struct random_state
  143. {
  144. uint32_t cur_state [ARR];
  145. int cur_index;
  146.  
  147. random_state (void): cur_index (ARR + 1) {}
  148. };
  149.  
  150. void save_state (random_state & st)
  151. {
  152. memmove (st.cur_state, cur_state, ARR * sizeof (uint32_t));
  153. st.cur_index = cur_index;
  154. }
  155.  
  156. void restore_state (const random_state & st)
  157. {
  158. memmove (cur_state, st.cur_state, ARR * sizeof (uint32_t));
  159. cur_index = st.cur_index;
  160. }
  161. } // namespace gentools_random_internal
  162.  
  163.  
  164. void initrand (uint32_t seed)
  165. {
  166. int i;
  167.  
  168. using namespace gentools_random_internal;
  169.  
  170. assert (seed != 0U);
  171. cur_state[0] = seed;
  172. for (i = 1; i < ARR; i++)
  173. cur_state[i] = RND_MULT1 * (cur_state[i - 1] ^ (cur_state[i - 1] >> 30)) + i;
  174. cur_index = ARR;
  175. }
  176.  
  177. void initrand_time (){
  178. using namespace gentools_random_internal;
  179. uint32_t t = (uint32_t)Time();
  180. fprintf (stderr, "Using seed : %u\n", t);
  181. initrand (t);
  182. }
  183.  
  184. void initrand_str (const char * str)
  185. {
  186. int i, j, k, len;
  187.  
  188. using namespace gentools_random_internal;
  189.  
  190. initrand (ARRAY_SEED);
  191.  
  192. len = strlen (str);
  193. for (i = 1, j = 0, k = std::max (ARR, len); k > 0; k--)
  194. {
  195. cur_state[i] = (cur_state[i] ^ (RND_MULT2 *
  196. (cur_state[i - 1] ^
  197. (cur_state[i - 1] >> 30)))) +
  198. (uint32_t) str[j] + j;
  199. i++;
  200. if (i >= ARR)
  201. {
  202. cur_state[0] = cur_state[MARR];
  203. i = 1;
  204. }
  205. j++;
  206. if (j >= len)
  207. j = 0;
  208. }
  209.  
  210. for (k = MARR; k > 0; k--)
  211. {
  212. cur_state[i] = (cur_state[i] ^ (RND_MULT3 *
  213. (cur_state[i - 1] ^
  214. (cur_state[i - 1] >> 30)))) - i;
  215. i++;
  216. if (i >= ARR)
  217. {
  218. cur_state[0] = cur_state[MARR];
  219. i = 1;
  220. }
  221. }
  222.  
  223. cur_state[0] = 1U << 31; // only the highest bit is relevant here
  224. cur_index = ARR;
  225. }
  226.  
  227. // strip all characters with ASCII codes 32 (Space) or less
  228. void initrand_str_strip (const char * str)
  229. {
  230. int old_len = strlen (str);
  231. char new_str [old_len + 1];
  232. char * new_p;
  233. const char * old_p;
  234.  
  235. new_p = new_str;
  236. for (old_p = str; *old_p != '\0'; old_p++)
  237. if (*old_p > 32)
  238. *(new_p++) = *old_p;
  239. *new_p = '\0';
  240.  
  241. initrand_str (new_str);
  242. }
  243.  
  244. void initrand_array (const unsigned * key, int len)
  245. {
  246. int i, j, k;
  247.  
  248. using namespace gentools_random_internal;
  249.  
  250. initrand (ARRAY_SEED);
  251.  
  252. for (i = 1, j = 0, k = std::max (ARR, len); k > 0; k--)
  253. {
  254. cur_state[i] = (cur_state[i] ^ (RND_MULT2 *
  255. (cur_state[i - 1] ^
  256. (cur_state[i - 1] >> 30)))) +
  257. key[j] + j;
  258. i++;
  259. if (i >= ARR)
  260. {
  261. cur_state[0] = cur_state[MARR];
  262. i = 1;
  263. }
  264. j++;
  265. if (j >= len)
  266. j = 0;
  267. }
  268.  
  269. for (k = MARR; k > 0; k--)
  270. {
  271. cur_state[i] = (cur_state[i] ^ (RND_MULT3 *
  272. (cur_state[i - 1] ^
  273. (cur_state[i - 1] >> 30)))) - i;
  274. i++;
  275. if (i >= ARR)
  276. {
  277. cur_state[0] = cur_state[MARR];
  278. i = 1;
  279. }
  280. }
  281.  
  282. cur_state[0] = 1U << 31; // only the highest bit is relevant here
  283. cur_index = ARR;
  284. }
  285.  
  286. uint32_t randhash (const char * str)
  287. {
  288. int i;
  289. uint32_t res;
  290.  
  291. using namespace gentools_random_internal;
  292.  
  293. res = 0;
  294. for (i = 0; str[i] != '\0'; i++)
  295. res = RND_MULT1 * (res ^ (res >> 30)) + (uint32_t) str[i];
  296.  
  297. return res;
  298. }
  299.  
  300. inline double rndvalue (void)
  301. {
  302. using namespace gentools_random_internal;
  303.  
  304. return get_tempered () * NORM_MULT;
  305. }
  306.  
  307. inline double rndvalue (double range)
  308. {
  309. return rndvalue () * (range);
  310. }
  311.  
  312. inline double rndvalue (double lo, double hi)
  313. {
  314. return rndvalue (hi - lo) + lo;
  315. }
  316.  
  317. inline uint32_t rndvalue (uint32_t range)
  318. {
  319. using namespace gentools_random_internal;
  320.  
  321. if (!range)
  322. return get_tempered ();
  323. else
  324. return (uint32_t) (((uint64_t) get_tempered () *
  325. range + (range >> 1)) >> 32ULL);
  326. }
  327.  
  328. inline uint32_t rndvalue (int range)
  329. {
  330. return rndvalue ((uint32_t) range);
  331. }
  332.  
  333. inline int32_t rndvalue (int32_t lo, int32_t hi)
  334. {
  335. return lo + (int32_t) rndvalue (hi - lo + 1);
  336. }
  337.  
  338. inline uint64_t rndvalue (uint64_t range)
  339. {
  340. using namespace gentools_random_internal;
  341.  
  342. uint64_t res;
  343. if (!range)
  344. {
  345. res = (uint64_t) get_tempered () << 32ULL;
  346. res |= (uint64_t) get_tempered ();
  347. }
  348. else
  349. {
  350. uint64_t lim;
  351. lim = uint64_t (-1);
  352. if (range <= (lim >> 32ULL))
  353. lim >>= 32ULL;
  354. if (range <= (lim >> 16ULL))
  355. lim >>= 16ULL;
  356. if (range <= (lim >> 8ULL))
  357. lim >>= 8ULL;
  358. if (range <= (lim >> 4ULL))
  359. lim >>= 4ULL;
  360. if (range <= (lim >> 2ULL))
  361. lim >>= 2ULL;
  362. if (range <= (lim >> 1ULL))
  363. lim >>= 1ULL;
  364. assert (range <= lim);
  365. do
  366. {
  367. res = (uint64_t) get_tempered () << 32ULL;
  368. res |= (uint64_t) get_tempered ();
  369. res &= lim;
  370. }
  371. while (res >= range);
  372. }
  373.  
  374. return res;
  375. }
  376.  
  377. inline int64_t rndvalue (int64_t lo, int64_t hi)
  378. {
  379. return lo + (int64_t) rndvalue ((uint64_t) (hi - lo + 1));
  380. }
  381.  
  382. template <class T> void rndshuffle (T a, T b)
  383. {
  384. int i, k;
  385.  
  386. for (i = 0; a + i != b; i++)
  387. {
  388. k = rndvalue (i + 1);
  389. std::swap (a[i], a[k]);
  390. }
  391. }
  392.  
  393.  
  394. #endif // __randommt_h__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement