1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
using Ryujinx.Common;
namespace Ryujinx.HLE.HOS.Kernel
{
class MersenneTwister
{
private int Index;
private uint[] Mt;
public MersenneTwister(uint Seed)
{
Mt = new uint[624];
Mt[0] = Seed;
for (int MtIdx = 1; MtIdx < Mt.Length; MtIdx++)
{
uint Prev = Mt[MtIdx - 1];
Mt[MtIdx] = (uint)(0x6c078965 * (Prev ^ (Prev >> 30)) + MtIdx);
}
Index = Mt.Length;
}
public long GenRandomNumber(long Min, long Max)
{
long Range = Max - Min;
if (Min == Max)
{
return Min;
}
if (Range == -1)
{
//Increment would cause a overflow, special case.
return GenRandomNumber(2, 2, 32, 0xffffffffu, 0xffffffffu);
}
Range++;
//This is log2(Range) plus one.
int NextRangeLog2 = 64 - BitUtils.CountLeadingZeros64(Range);
//If Range is already power of 2, subtract one to use log2(Range) directly.
int RangeLog2 = NextRangeLog2 - (BitUtils.IsPowerOfTwo64(Range) ? 1 : 0);
int Parts = RangeLog2 > 32 ? 2 : 1;
int BitsPerPart = RangeLog2 / Parts;
int FullParts = Parts - (RangeLog2 - Parts * BitsPerPart);
uint Mask = 0xffffffffu >> (32 - BitsPerPart);
uint MaskPlus1 = 0xffffffffu >> (31 - BitsPerPart);
long RandomNumber;
do
{
RandomNumber = GenRandomNumber(Parts, FullParts, BitsPerPart, Mask, MaskPlus1);
}
while ((ulong)RandomNumber >= (ulong)Range);
return Min + RandomNumber;
}
private long GenRandomNumber(
int Parts,
int FullParts,
int BitsPerPart,
uint Mask,
uint MaskPlus1)
{
long RandomNumber = 0;
int Part = 0;
for (; Part < FullParts; Part++)
{
RandomNumber <<= BitsPerPart;
RandomNumber |= GenRandomNumber() & Mask;
}
for (; Part < Parts; Part++)
{
RandomNumber <<= BitsPerPart + 1;
RandomNumber |= GenRandomNumber() & MaskPlus1;
}
return RandomNumber;
}
private uint GenRandomNumber()
{
if (Index >= Mt.Length)
{
Twist();
}
uint Value = Mt[Index++];
Value ^= Value >> 11;
Value ^= (Value << 7) & 0x9d2c5680;
Value ^= (Value << 15) & 0xefc60000;
Value ^= Value >> 18;
return Value;
}
private void Twist()
{
for (int MtIdx = 0; MtIdx < Mt.Length; MtIdx++)
{
uint Value = (Mt[MtIdx] & 0x80000000) + (Mt[(MtIdx + 1) % Mt.Length] & 0x7fffffff);
Mt[MtIdx] = Mt[(MtIdx + 397) % Mt.Length] ^ (Value >> 1);
if ((Value & 1) != 0)
{
Mt[MtIdx] ^= 0x9908b0df;
}
}
Index = 0;
}
}
}
|