MersenneTwister.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. using Ryujinx.Common;
  2. namespace Ryujinx.HLE.HOS.Kernel
  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. }