TSRandom.cs 8.1 KB

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