TSRandom.cs 8.0 KB

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