MersenneTwister.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. using Ryujinx.Common;
  2. using System.Numerics;
  3. namespace Ryujinx.HLE.HOS.Kernel.Common
  4. {
  5. class MersenneTwister
  6. {
  7. private int _index;
  8. private uint[] _mt;
  9. public MersenneTwister(uint seed)
  10. {
  11. _mt = new uint[624];
  12. _mt[0] = seed;
  13. for (int mtIdx = 1; mtIdx < _mt.Length; mtIdx++)
  14. {
  15. uint prev = _mt[mtIdx - 1];
  16. _mt[mtIdx] = (uint)(0x6c078965 * (prev ^ (prev >> 30)) + mtIdx);
  17. }
  18. _index = _mt.Length;
  19. }
  20. public long GenRandomNumber(long min, long max)
  21. {
  22. long range = max - min;
  23. if (min == max)
  24. {
  25. return min;
  26. }
  27. if (range == -1)
  28. {
  29. // Increment would cause a overflow, special case.
  30. return GenRandomNumber(2, 2, 32, 0xffffffffu, 0xffffffffu);
  31. }
  32. range++;
  33. // This is log2(Range) plus one.
  34. int nextRangeLog2 = 64 - BitOperations.LeadingZeroCount((ulong)range);
  35. // If Range is already power of 2, subtract one to use log2(Range) directly.
  36. int rangeLog2 = nextRangeLog2 - (BitOperations.IsPow2(range) ? 1 : 0);
  37. int parts = rangeLog2 > 32 ? 2 : 1;
  38. int bitsPerPart = rangeLog2 / parts;
  39. int fullParts = parts - (rangeLog2 - parts * bitsPerPart);
  40. uint mask = 0xffffffffu >> (32 - bitsPerPart);
  41. uint maskPlus1 = 0xffffffffu >> (31 - bitsPerPart);
  42. long randomNumber;
  43. do
  44. {
  45. randomNumber = GenRandomNumber(parts, fullParts, bitsPerPart, mask, maskPlus1);
  46. }
  47. while ((ulong)randomNumber >= (ulong)range);
  48. return min + randomNumber;
  49. }
  50. private long GenRandomNumber(
  51. int parts,
  52. int fullParts,
  53. int bitsPerPart,
  54. uint mask,
  55. uint maskPlus1)
  56. {
  57. long randomNumber = 0;
  58. int part = 0;
  59. for (; part < fullParts; part++)
  60. {
  61. randomNumber <<= bitsPerPart;
  62. randomNumber |= GenRandomNumber() & mask;
  63. }
  64. for (; part < parts; part++)
  65. {
  66. randomNumber <<= bitsPerPart + 1;
  67. randomNumber |= GenRandomNumber() & maskPlus1;
  68. }
  69. return randomNumber;
  70. }
  71. private uint GenRandomNumber()
  72. {
  73. if (_index >= _mt.Length)
  74. {
  75. Twist();
  76. }
  77. uint value = _mt[_index++];
  78. value ^= value >> 11;
  79. value ^= (value << 7) & 0x9d2c5680;
  80. value ^= (value << 15) & 0xefc60000;
  81. value ^= value >> 18;
  82. return value;
  83. }
  84. private void Twist()
  85. {
  86. for (int mtIdx = 0; mtIdx < _mt.Length; mtIdx++)
  87. {
  88. uint value = (_mt[mtIdx] & 0x80000000) + (_mt[(mtIdx + 1) % _mt.Length] & 0x7fffffff);
  89. _mt[mtIdx] = _mt[(mtIdx + 397) % _mt.Length] ^ (value >> 1);
  90. if ((value & 1) != 0)
  91. {
  92. _mt[mtIdx] ^= 0x9908b0df;
  93. }
  94. }
  95. _index = 0;
  96. }
  97. }
  98. }