PageRenderTime 37ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/Utilities/Math/Random250Algorithm.cs

#
C# | 173 lines | 102 code | 24 blank | 47 comment | 10 complexity | db5f855e4b5dab8266c3555c6916faa1 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using NUnit.Framework;
  3. namespace Delta.Utilities.Math
  4. {
  5. /// <summary>
  6. /// This class represents an implementation of the R250 algorith comes
  7. /// originally from the "Random isn't Really Random -- C# Random Number
  8. /// Generation" article by Matthew Cochran. For more details see:
  9. /// http://www.shadlen.org/ichbin/random/generators.htm#r250
  10. /// http://www.c-sharpcorner.com/UploadFile/rmcochran/random07172006175425PM/random.aspx
  11. /// <para />
  12. /// Implements the GFSR: x_n = x_(n-P) ^ x_(n-Q), which has period 2^P - 1.
  13. /// </summary>
  14. public class Random250Algorithm : RandomBase
  15. {
  16. #region Constants
  17. /// <summary>
  18. /// P, used as degree of larger term (250 or 7)
  19. /// </summary>
  20. private static readonly int P = 250;
  21. /// <summary>
  22. /// Q, used as degree of smaller term (103 or 4)
  23. /// </summary>
  24. private static readonly int Q = 103;
  25. /// <summary>
  26. /// L, used as word length (32 or 3)
  27. /// </summary>
  28. private static readonly int L = 32;
  29. #endregion
  30. #region Private
  31. #region x (Private)
  32. /// <summary>
  33. /// X array with all the random values.
  34. /// </summary>
  35. private readonly uint[] x;
  36. #endregion
  37. #region pointer (Private)
  38. /// <summary>
  39. /// Pointer to element we are working on.
  40. /// </summary>
  41. private int pointer;
  42. #endregion
  43. #endregion
  44. #region Constructors
  45. /// <summary>
  46. /// Create R250
  47. /// </summary>
  48. public Random250Algorithm()
  49. : this(Convert.ToInt32(DateTime.Now.Ticks & 0x000000007FFFFFFF))
  50. {
  51. }
  52. /// <summary>
  53. /// Create R250
  54. /// </summary>
  55. /// <param name="seed">Seed</param>
  56. public Random250Algorithm(int seed)
  57. : base(seed)
  58. {
  59. x = new uint[P];
  60. // get the memory we need for initialization
  61. uint[] e = new uint[P]; // new unsigned long int[P];
  62. uint[] a = new uint[2 * P]; // new unsigned short int[2*P];
  63. for (int i = 0; i < 7; i++)
  64. {
  65. x[i] = GetBaseNextUInt32();
  66. }
  67. pointer = Convert.ToInt32(P * GetBaseNextDouble());
  68. // construct P linearly independent basis vectors
  69. for (int i = 0; i < P; i++)
  70. {
  71. //mini_rand(s);
  72. int k = L * i / P;
  73. e[i] = GetBaseNextUInt32() << k; // zeros to right of bit k
  74. e[i] = e[i] | (0x01U << k); // and a one at bit k
  75. }
  76. // construct 2P-1 coefficient bits
  77. for (int i = 0; i < P; i++)
  78. {
  79. a[i] =
  80. (uint)
  81. (GetBaseNextDouble() > 0.5
  82. ? 1
  83. : 0);
  84. }
  85. for (int i = P; i < 2 * P; i++)
  86. {
  87. a[i] = a[i - P] ^ a[i - Q];
  88. }
  89. // construct first P-1 entries (``matrix seed'') by
  90. // combining basis vectors according to coefficient bits
  91. for (int i = 0; i < P; i++)
  92. {
  93. x[i] = 0;
  94. for (int j = 0; j < P; j++)
  95. {
  96. if (a[i + j] != 0)
  97. {
  98. x[i] = x[i] ^ e[j];
  99. }
  100. }
  101. }
  102. // set pointer to last element
  103. pointer = P - 1;
  104. }
  105. #endregion
  106. #region Next (Public)
  107. /// <summary>
  108. /// Next
  109. /// </summary>
  110. public override int Next()
  111. {
  112. uint ret;
  113. int newP = pointer;
  114. // advance pointer
  115. if (newP == P - 1)
  116. {
  117. newP = 0;
  118. }
  119. else
  120. {
  121. newP++;
  122. }
  123. // compute next value
  124. ret =
  125. (newP < Q)
  126. ? x[newP] ^ x[(newP - Q + P)]
  127. : x[newP] ^ x[(newP - Q)];
  128. // replace value and pointer and return
  129. pointer = newP;
  130. x[pointer] = ret;
  131. return ConvertToInt32(ret & 0x7fffffffU);
  132. }
  133. #endregion
  134. /// <summary>
  135. /// Tests for Random250Algorithm
  136. /// </summary>
  137. internal class Random250AlgorithmTests
  138. {
  139. #region CreateRandom250Algorithm
  140. [Test]
  141. public void CreateRandom250Algorithm()
  142. {
  143. RandomBase generator = new Random250Algorithm();
  144. Assert.NotEqual(generator.NextDouble(), generator.NextDouble());
  145. }
  146. #endregion
  147. }
  148. }
  149. }