TSRandom.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. using System;
  2. namespace TrueSync {
  3. /**
  4. * @brief Generates random numbers based on a deterministic approach.
  5. **/
  6. public class TSRandom {
  7. // From http://www.codeproject.com/Articles/164087/Random-Number-Generation
  8. // Class TSRandom generates random numbers
  9. // from a uniform distribution using the Mersenne
  10. // Twister algorithm.
  11. private const int N = 624;
  12. private const int M = 397;
  13. private const uint MATRIX_A = 0x9908b0dfU;
  14. private const uint UPPER_MASK = 0x80000000U;
  15. private const uint LOWER_MASK = 0x7fffffffU;
  16. private const int MAX_RAND_INT = 0x7fffffff;
  17. private uint[] mag01 = { 0x0U, MATRIX_A };
  18. private uint[] mt = new uint[N];
  19. private int mti = N + 1;
  20. /**
  21. * @brief Static instance of {@link TSRandom} with seed 1.
  22. **/
  23. public static TSRandom instance;
  24. internal static void Init() {
  25. instance = New(1);
  26. }
  27. /**
  28. * @brief Generates a new instance based on a given seed.
  29. **/
  30. public static TSRandom New(int seed) {
  31. TSRandom r = new TSRandom(seed);
  32. return r;
  33. }
  34. private TSRandom() {
  35. init_genrand((uint)DateTime.Now.Millisecond);
  36. }
  37. private TSRandom(int seed) {
  38. init_genrand((uint)seed);
  39. }
  40. private TSRandom(int[] init) {
  41. uint[] initArray = new uint[init.Length];
  42. for (int i = 0; i < init.Length; ++i)
  43. initArray[i] = (uint)init[i];
  44. init_by_array(initArray, (uint)initArray.Length);
  45. }
  46. public static int MaxRandomInt { get { return 0x7fffffff; } }
  47. /**
  48. * @brief Returns a random integer.
  49. **/
  50. public int Next() {
  51. return genrand_int31();
  52. }
  53. /**
  54. * @brief Returns a random integer.
  55. **/
  56. public static int CallNext() {
  57. return instance.Next();
  58. }
  59. /**
  60. * @brief Returns a integer between a min value [inclusive] and a max value [exclusive].
  61. **/
  62. public int Next(int minValue, int maxValue) {
  63. if (minValue > maxValue) {
  64. int tmp = maxValue;
  65. maxValue = minValue;
  66. minValue = tmp;
  67. }
  68. int range = maxValue - minValue;
  69. return minValue + Next() % range;
  70. }
  71. /**
  72. * @brief Returns a {@link FP} between a min value [inclusive] and a max value [inclusive].
  73. **/
  74. public FP Next(float minValue, float maxValue) {
  75. int minValueInt = (int)(minValue * 1000), maxValueInt = (int)(maxValue * 1000);
  76. if (minValueInt > maxValueInt) {
  77. int tmp = maxValueInt;
  78. maxValueInt = minValueInt;
  79. minValueInt = tmp;
  80. }
  81. return (FP.Floor((maxValueInt - minValueInt + 1) * NextFP() +
  82. minValueInt)) / 1000;
  83. }
  84. /**
  85. * @brief Returns a integer between a min value [inclusive] and a max value [exclusive].
  86. **/
  87. public static int Range(int minValue, int maxValue) {
  88. return instance.Next(minValue, maxValue);
  89. }
  90. /**
  91. * @brief Returns a {@link FP} between a min value [inclusive] and a max value [inclusive].
  92. **/
  93. public static FP Range(float minValue, float maxValue) {
  94. return instance.Next(minValue, maxValue);
  95. }
  96. /**
  97. * @brief Returns a {@link FP} between 0.0 [inclusive] and 1.0 [inclusive].
  98. **/
  99. public FP NextFP() {
  100. return ((FP) Next()) / (MaxRandomInt);
  101. }
  102. /**
  103. * @brief Returns a {@link FP} between 0.0 [inclusive] and 1.0 [inclusive].
  104. **/
  105. public static FP value {
  106. get {
  107. return instance.NextFP();
  108. }
  109. }
  110. /**
  111. * @brief Returns a random {@link TSVector} representing a point inside a sphere with radius 1.
  112. **/
  113. public static TSVector insideUnitSphere {
  114. get {
  115. return new TSVector(value, value, value);
  116. }
  117. }
  118. private float NextFloat() {
  119. return (float)genrand_real2();
  120. }
  121. private float NextFloat(bool includeOne) {
  122. if (includeOne) {
  123. return (float)genrand_real1();
  124. }
  125. return (float)genrand_real2();
  126. }
  127. private float NextFloatPositive() {
  128. return (float)genrand_real3();
  129. }
  130. private double NextDouble() {
  131. return genrand_real2();
  132. }
  133. private double NextDouble(bool includeOne) {
  134. if (includeOne) {
  135. return genrand_real1();
  136. }
  137. return genrand_real2();
  138. }
  139. private double NextDoublePositive() {
  140. return genrand_real3();
  141. }
  142. private double Next53BitRes() {
  143. return genrand_res53();
  144. }
  145. public void Initialize() {
  146. init_genrand((uint)DateTime.Now.Millisecond);
  147. }
  148. public void Initialize(int seed) {
  149. init_genrand((uint)seed);
  150. }
  151. public void Initialize(int[] init) {
  152. uint[] initArray = new uint[init.Length];
  153. for (int i = 0; i < init.Length; ++i)
  154. initArray[i] = (uint)init[i];
  155. init_by_array(initArray, (uint)initArray.Length);
  156. }
  157. private void init_genrand(uint s) {
  158. mt[0] = s & 0xffffffffU;
  159. for (mti = 1; mti < N; mti++) {
  160. mt[mti] = (uint)(1812433253U * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti);
  161. mt[mti] &= 0xffffffffU;
  162. }
  163. }
  164. private void init_by_array(uint[] init_key, uint key_length) {
  165. int i, j, k;
  166. init_genrand(19650218U);
  167. i = 1;
  168. j = 0;
  169. k = (int)(N > key_length ? N : key_length);
  170. for (; k > 0; k--) {
  171. mt[i] = (uint)((uint)(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525U)) + init_key[j] + j);
  172. mt[i] &= 0xffffffffU;
  173. i++;
  174. j++;
  175. if (i >= N) {
  176. mt[0] = mt[N - 1];
  177. i = 1;
  178. }
  179. if (j >= key_length)
  180. j = 0;
  181. }
  182. for (k = N - 1; k > 0; k--) {
  183. mt[i] = (uint)((uint)(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) *
  184. 1566083941U)) - i);
  185. mt[i] &= 0xffffffffU;
  186. i++;
  187. if (i >= N) {
  188. mt[0] = mt[N - 1];
  189. i = 1;
  190. }
  191. }
  192. mt[0] = 0x80000000U;
  193. }
  194. uint genrand_int32() {
  195. uint y;
  196. if (mti >= N) {
  197. int kk;
  198. if (mti == N + 1)
  199. init_genrand(5489U);
  200. for (kk = 0; kk < N - M; kk++) {
  201. y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
  202. mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1U];
  203. }
  204. for (; kk < N - 1; kk++) {
  205. y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
  206. mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1U];
  207. }
  208. y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
  209. mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1U];
  210. mti = 0;
  211. }
  212. y = mt[mti++];
  213. y ^= (y >> 11);
  214. y ^= (y << 7) & 0x9d2c5680U;
  215. y ^= (y << 15) & 0xefc60000U;
  216. y ^= (y >> 18);
  217. return y;
  218. }
  219. private int genrand_int31() {
  220. return (int)(genrand_int32() >> 1);
  221. }
  222. FP genrand_FP() {
  223. return (FP)genrand_int32() * (FP.One / (FP)4294967295);
  224. }
  225. double genrand_real1() {
  226. return genrand_int32() * (1.0 / 4294967295.0);
  227. }
  228. double genrand_real2() {
  229. return genrand_int32() * (1.0 / 4294967296.0);
  230. }
  231. double genrand_real3() {
  232. return (((double)genrand_int32()) + 0.5) * (1.0 / 4294967296.0);
  233. }
  234. double genrand_res53() {
  235. uint a = genrand_int32() >> 5, b = genrand_int32() >> 6;
  236. return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
  237. }
  238. }
  239. }