PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/dep/SFMT/SFMT.h

https://github.com/Bootz/Singularity
C Header | 308 lines | 202 code | 34 blank | 72 comment | 27 complexity | 83dc2eccd135cf46acd134e776279e08 MD5 | raw file
  1. /*
  2. * Copyright notice
  3. * ================
  4. * GNU General Public License http://www.gnu.org/licenses/gpl.html
  5. * This C++ implementation of SFMT contains parts of the original C code
  6. * which was published under the following BSD license, which is therefore
  7. * in effect in addition to the GNU General Public License.
  8. * Copyright (c) 2006, 2007 by Mutsuo Saito, Makoto Matsumoto and Hiroshima University.
  9. * Copyright (c) 2008 by Agner Fog.
  10. * Copyright (c) 2010 Trinity Core
  11. *
  12. * BSD License:
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions are met:
  15. * > Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * > Redistributions in binary form must reproduce the above copyright notice,
  18. * this list of conditions and the following disclaimer in the documentation
  19. * and/or other materials provided with the distribution.
  20. * > Neither the name of the Hiroshima University nor the names of its
  21. * contributors may be used to endorse or promote products derived from
  22. * this software without specific prior written permission.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  26. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  27. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  28. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  29. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  30. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  33. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. #ifndef SFMT_H
  36. #define SFMT_H
  37. #include <emmintrin.h> // Define SSE2 intrinsics
  38. #include "randomc.h" // Define integer types etc
  39. #include <time.h>
  40. // Choose one of the possible Mersenne exponents.
  41. // Higher values give longer cycle length and use more memory:
  42. //#define MEXP 607
  43. //#define MEXP 1279
  44. //#define MEXP 2281
  45. //#define MEXP 4253
  46. #define MEXP 11213
  47. //#define MEXP 19937
  48. //#define MEXP 44497
  49. // Define constants for the selected Mersenne exponent:
  50. #if MEXP == 44497
  51. #define SFMT_N 348 // Size of state vector
  52. #define SFMT_M 330 // Position of intermediate feedback
  53. #define SFMT_SL1 5 // Left shift of W[N-1], 32-bit words
  54. #define SFMT_SL2 3 // Left shift of W[0], *8, 128-bit words
  55. #define SFMT_SR1 9 // Right shift of W[M], 32-bit words
  56. #define SFMT_SR2 3 // Right shift of W[N-2], *8, 128-bit words
  57. #define SFMT_MASK 0xeffffffb,0xdfbebfff,0xbfbf7bef,0x9ffd7bff // AND mask
  58. #define SFMT_PARITY 1,0,0xa3ac4000,0xecc1327a // Period certification vector
  59. #elif MEXP == 19937
  60. #define SFMT_N 156 // Size of state vector
  61. #define SFMT_M 122 // Position of intermediate feedback
  62. #define SFMT_SL1 18 // Left shift of W[N-1], 32-bit words
  63. #define SFMT_SL2 1 // Left shift of W[0], *8, 128-bit words
  64. #define SFMT_SR1 11 // Right shift of W[M], 32-bit words
  65. #define SFMT_SR2 1 // Right shift of W[N-2], *8, 128-bit words
  66. #define SFMT_MASK 0xdfffffef,0xddfecb7f,0xbffaffff,0xbffffff6 // AND mask
  67. #define SFMT_PARITY 1,0,0,0x13c9e684 // Period certification vector
  68. #elif MEXP == 11213
  69. #define SFMT_N 88 // Size of state vector
  70. #define SFMT_M 68 // Position of intermediate feedback
  71. #define SFMT_SL1 14 // Left shift of W[N-1], 32-bit words
  72. #define SFMT_SL2 3 // Left shift of W[0], *8, 128-bit words
  73. #define SFMT_SR1 7 // Right shift of W[M], 32-bit words
  74. #define SFMT_SR2 3 // Right shift of W[N-2], *8, 128-bit words
  75. #define SFMT_MASK 0xeffff7fb,0xffffffef,0xdfdfbfff,0x7fffdbfd // AND mask
  76. #define SFMT_PARITY 1,0,0xe8148000,0xd0c7afa3 // Period certification vector
  77. #elif MEXP == 4253
  78. #define SFMT_N 34 // Size of state vector
  79. #define SFMT_M 17 // Position of intermediate feedback
  80. #define SFMT_SL1 20 // Left shift of W[N-1], 32-bit words
  81. #define SFMT_SL2 1 // Left shift of W[0], *8, 128-bit words
  82. #define SFMT_SR1 7 // Right shift of W[M], 32-bit words
  83. #define SFMT_SR2 1 // Right shift of W[N-2], *8, 128-bit words
  84. #define SFMT_MASK 0x9f7bffff, 0x9fffff5f, 0x3efffffb, 0xfffff7bb // AND mask
  85. #define SFMT_PARITY 0xa8000001, 0xaf5390a3, 0xb740b3f8, 0x6c11486d // Period certification vector
  86. #elif MEXP == 2281
  87. #define SFMT_N 18 // Size of state vector
  88. #define SFMT_M 12 // Position of intermediate feedback
  89. #define SFMT_SL1 19 // Left shift of W[N-1], 32-bit words
  90. #define SFMT_SL2 1 // Left shift of W[0], *8, 128-bit words
  91. #define SFMT_SR1 5 // Right shift of W[M], 32-bit words
  92. #define SFMT_SR2 1 // Right shift of W[N-2], *8, 128-bit words
  93. #define SFMT_MASK 0xbff7ffbf, 0xfdfffffe, 0xf7ffef7f, 0xf2f7cbbf // AND mask
  94. #define SFMT_PARITY 0x00000001, 0x00000000, 0x00000000, 0x41dfa600 // Period certification vector
  95. #elif MEXP == 1279
  96. #define SFMT_N 10 // Size of state vector
  97. #define SFMT_M 7 // Position of intermediate feedback
  98. #define SFMT_SL1 14 // Left shift of W[N-1], 32-bit words
  99. #define SFMT_SL2 3 // Left shift of W[0], *8, 128-bit words
  100. #define SFMT_SR1 5 // Right shift of W[M], 32-bit words
  101. #define SFMT_SR2 1 // Right shift of W[N-2], *8, 128-bit words
  102. #define SFMT_MASK 0xf7fefffd, 0x7fefcfff, 0xaff3ef3f, 0xb5ffff7f // AND mask
  103. #define SFMT_PARITY 0x00000001, 0x00000000, 0x00000000, 0x20000000 // Period certification vector
  104. #elif MEXP == 607
  105. #define SFMT_N 5 // Size of state vector
  106. #define SFMT_M 2 // Position of intermediate feedback
  107. #define SFMT_SL1 15 // Left shift of W[N-1], 32-bit words
  108. #define SFMT_SL2 3 // Left shift of W[0], *8, 128-bit words
  109. #define SFMT_SR1 13 // Right shift of W[M], 32-bit words
  110. #define SFMT_SR2 3 // Right shift of W[N-2], *8, 128-bit words
  111. #define SFMT_MASK 0xfdff37ff, 0xef7f3f7d, 0xff777b7d, 0x7ff7fb2f // AND mask
  112. #define SFMT_PARITY 0x00000001, 0x00000000, 0x00000000, 0x5986f054 // Period certification vector
  113. #endif
  114. // Functions used by SFMTRand::RandomInitByArray
  115. static uint32_t func1(uint32_t x) {
  116. return (x ^ (x >> 27)) * 1664525U;
  117. }
  118. static uint32_t func2(uint32_t x) {
  119. return (x ^ (x >> 27)) * 1566083941U;
  120. }
  121. // Subfunction for the sfmt algorithm
  122. static inline __m128i sfmt_recursion(__m128i const &a, __m128i const &b,
  123. __m128i const &c, __m128i const &d, __m128i const &mask) {
  124. __m128i a1, b1, c1, d1, z1, z2;
  125. b1 = _mm_srli_epi32(b, SFMT_SR1);
  126. a1 = _mm_slli_si128(a, SFMT_SL2);
  127. c1 = _mm_srli_si128(c, SFMT_SR2);
  128. d1 = _mm_slli_epi32(d, SFMT_SL1);
  129. b1 = _mm_and_si128(b1, mask);
  130. z1 = _mm_xor_si128(a, a1);
  131. z2 = _mm_xor_si128(b1, d1);
  132. z1 = _mm_xor_si128(z1, c1);
  133. z2 = _mm_xor_si128(z1, z2);
  134. return z2;
  135. }
  136. // Class for SFMT generator
  137. class SFMTRand { // Encapsulate random number generator
  138. public:
  139. SFMTRand() { LastInterval = 0; RandomInit((int)(time(0))); }
  140. void RandomInit(int seed) // Re-seed
  141. {
  142. // Re-seed
  143. uint32_t i; // Loop counter
  144. uint32_t y = seed; // Temporary
  145. uint32_t statesize = SFMT_N*4; // Size of state vector
  146. // Fill state vector with random numbers from seed
  147. ((uint32_t*)state)[0] = y;
  148. const uint32_t factor = 1812433253U;// Multiplication factor
  149. for (i = 1; i < statesize; i++) {
  150. y = factor * (y ^ (y >> 30)) + i;
  151. ((uint32_t*)state)[i] = y;
  152. }
  153. // Further initialization and period certification
  154. Init2();
  155. }
  156. int32_t IRandom(int32_t min, int32_t max) // Output random integer
  157. {
  158. // Output random integer in the interval min <= x <= max
  159. // Slightly inaccurate if (max-min+1) is not a power of 2
  160. if (max <= min) {
  161. if (max == min) return min; else return 0x80000000;
  162. }
  163. // Assume 64 bit integers supported. Use multiply and shift method
  164. uint32_t interval; // Length of interval
  165. uint64_t longran; // Random bits * interval
  166. uint32_t iran; // Longran / 2^32
  167. interval = (uint32_t)(max - min + 1);
  168. longran = (uint64_t)BRandom() * interval;
  169. iran = (uint32_t)(longran >> 32);
  170. // Convert back to signed and return result
  171. return (int32_t)iran + min;
  172. }
  173. uint32_t URandom(uint32_t min, uint32_t max)
  174. {
  175. // Output random integer in the interval min <= x <= max
  176. // Slightly inaccurate if (max-min+1) is not a power of 2
  177. if (max <= min) {
  178. if (max == min) return min; else return 0;
  179. }
  180. // Assume 64 bit integers supported. Use multiply and shift method
  181. uint32_t interval; // Length of interval
  182. uint64_t longran; // Random bits * interval
  183. uint32_t iran; // Longran / 2^32
  184. interval = (uint32_t)(max - min + 1);
  185. longran = (uint64_t)BRandom() * interval;
  186. iran = (uint32_t)(longran >> 32);
  187. // Convert back to signed and return result
  188. return iran + min;
  189. }
  190. double Random() // Output random floating point number
  191. {
  192. // Output random floating point number
  193. if (ix >= SFMT_N*4-1) {
  194. // Make sure we have at least two 32-bit numbers
  195. Generate();
  196. }
  197. uint64_t r = *(uint64_t*)((uint32_t*)state+ix);
  198. ix += 2;
  199. // 52 bits resolution for compatibility with assembly version:
  200. return (int64_t)(r >> 12) * (1./(67108864.0*67108864.0));
  201. }
  202. uint32_t BRandom() // Output random bits
  203. {
  204. // Output 32 random bits
  205. uint32_t y;
  206. if (ix >= SFMT_N*4) {
  207. Generate();
  208. }
  209. y = ((uint32_t*)state)[ix++];
  210. return y;
  211. }
  212. private:
  213. void Init2() // Various initializations and period certification
  214. {
  215. // Various initializations and period certification
  216. uint32_t i, j, temp;
  217. // Initialize mask
  218. static const uint32_t maskinit[4] = {SFMT_MASK};
  219. mask = _mm_loadu_si128((__m128i*)maskinit);
  220. // Period certification
  221. // Define period certification vector
  222. static const uint32_t parityvec[4] = {SFMT_PARITY};
  223. // Check if parityvec & state[0] has odd parity
  224. temp = 0;
  225. for (i = 0; i < 4; i++)
  226. temp ^= parityvec[i] & ((uint32_t*)state)[i];
  227. for (i = 16; i > 0; i >>= 1) temp ^= temp >> i;
  228. if (!(temp & 1)) {
  229. // parity is even. Certification failed
  230. // Find a nonzero bit in period certification vector
  231. for (i = 0; i < 4; i++) {
  232. if (parityvec[i]) {
  233. for (j = 1; j; j <<= 1) {
  234. if (parityvec[i] & j) {
  235. // Flip the corresponding bit in state[0] to change parity
  236. ((uint32_t*)state)[i] ^= j;
  237. // Done. Exit i and j loops
  238. i = 5; break;
  239. }
  240. }
  241. }
  242. }
  243. }
  244. // Generate first random numbers and set ix = 0
  245. Generate();
  246. }
  247. void Generate() // Fill state array with new random numbers
  248. {
  249. // Fill state array with new random numbers
  250. int i;
  251. __m128i r, r1, r2;
  252. r1 = state[SFMT_N - 2];
  253. r2 = state[SFMT_N - 1];
  254. for (i = 0; i < SFMT_N - SFMT_M; i++) {
  255. r = sfmt_recursion(state[i], state[i + SFMT_M], r1, r2, mask);
  256. state[i] = r;
  257. r1 = r2;
  258. r2 = r;
  259. }
  260. for (; i < SFMT_N; i++) {
  261. r = sfmt_recursion(state[i], state[i + SFMT_M - SFMT_N], r1, r2, mask);
  262. state[i] = r;
  263. r1 = r2;
  264. r2 = r;
  265. }
  266. ix = 0;
  267. }
  268. uint32_t ix; // Index into state array
  269. uint32_t LastInterval; // Last interval length for IRandom
  270. uint32_t RLimit; // Rejection limit used by IRandom
  271. __m128i mask; // AND mask
  272. __m128i state[SFMT_N]; // State vector for SFMT generator
  273. };
  274. #endif // SFMT_H