TSRandom.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. [MemoryPackIgnore]
  101. public FP value {
  102. get {
  103. return this.NextFP();
  104. }
  105. }
  106. /**
  107. * @brief Returns a random {@link TSVector} representing a point inside a sphere with radius 1.
  108. **/
  109. [MemoryPackIgnore]
  110. public TSVector insideUnitSphere {
  111. get {
  112. return new TSVector(value, value, value);
  113. }
  114. }
  115. private float NextFloat() {
  116. return (float)genrand_real2();
  117. }
  118. private float NextFloat(bool includeOne) {
  119. if (includeOne) {
  120. return (float)genrand_real1();
  121. }
  122. return (float)genrand_real2();
  123. }
  124. private float NextFloatPositive() {
  125. return (float)genrand_real3();
  126. }
  127. private double NextDouble() {
  128. return genrand_real2();
  129. }
  130. private double NextDouble(bool includeOne) {
  131. if (includeOne) {
  132. return genrand_real1();
  133. }
  134. return genrand_real2();
  135. }
  136. private double NextDoublePositive() {
  137. return genrand_real3();
  138. }
  139. private double Next53BitRes() {
  140. return genrand_res53();
  141. }
  142. public void Initialize() {
  143. init_genrand((uint)DateTime.Now.Millisecond);
  144. }
  145. public void Initialize(int seed) {
  146. init_genrand((uint)seed);
  147. }
  148. public void Initialize(int[] init) {
  149. uint[] initArray = new uint[init.Length];
  150. for (int i = 0; i < init.Length; ++i)
  151. initArray[i] = (uint)init[i];
  152. init_by_array(initArray, (uint)initArray.Length);
  153. }
  154. private void init_genrand(uint s) {
  155. mt[0] = s & 0xffffffffU;
  156. for (mti = 1; mti < N; mti++) {
  157. mt[mti] = (uint)(1812433253U * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti);
  158. mt[mti] &= 0xffffffffU;
  159. }
  160. }
  161. private void init_by_array(uint[] init_key, uint key_length) {
  162. int i, j, k;
  163. init_genrand(19650218U);
  164. i = 1;
  165. j = 0;
  166. k = (int)(N > key_length ? N : key_length);
  167. for (; k > 0; k--) {
  168. mt[i] = (uint)((uint)(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525U)) + init_key[j] + j);
  169. mt[i] &= 0xffffffffU;
  170. i++;
  171. j++;
  172. if (i >= N) {
  173. mt[0] = mt[N - 1];
  174. i = 1;
  175. }
  176. if (j >= key_length)
  177. j = 0;
  178. }
  179. for (k = N - 1; k > 0; k--) {
  180. mt[i] = (uint)((uint)(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) *
  181. 1566083941U)) - i);
  182. mt[i] &= 0xffffffffU;
  183. i++;
  184. if (i >= N) {
  185. mt[0] = mt[N - 1];
  186. i = 1;
  187. }
  188. }
  189. mt[0] = 0x80000000U;
  190. }
  191. uint genrand_int32() {
  192. uint y;
  193. if (mti >= N) {
  194. int kk;
  195. if (mti == N + 1)
  196. init_genrand(5489U);
  197. for (kk = 0; kk < N - M; kk++) {
  198. y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
  199. mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1U];
  200. }
  201. for (; kk < N - 1; kk++) {
  202. y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
  203. mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1U];
  204. }
  205. y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
  206. mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1U];
  207. mti = 0;
  208. }
  209. y = mt[mti++];
  210. y ^= (y >> 11);
  211. y ^= (y << 7) & 0x9d2c5680U;
  212. y ^= (y << 15) & 0xefc60000U;
  213. y ^= (y >> 18);
  214. return y;
  215. }
  216. private int genrand_int31() {
  217. return (int)(genrand_int32() >> 1);
  218. }
  219. FP genrand_FP() {
  220. return (FP)genrand_int32() * (FP.One / (FP)4294967295);
  221. }
  222. double genrand_real1() {
  223. return genrand_int32() * (1.0 / 4294967295.0);
  224. }
  225. double genrand_real2() {
  226. return genrand_int32() * (1.0 / 4294967296.0);
  227. }
  228. double genrand_real3() {
  229. return (((double)genrand_int32()) + 0.5) * (1.0 / 4294967296.0);
  230. }
  231. double genrand_res53() {
  232. uint a = genrand_int32() >> 5, b = genrand_int32() >> 6;
  233. return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
  234. }
  235. }
  236. }