MersenneTwister.cs 3.2 KB

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