forked from space-wizards/RobustToolbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNetRandom.cs
177 lines (156 loc) · 4.26 KB
/
NetRandom.cs
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
using System;
using System.Collections.Generic;
using System.Threading;
namespace Lidgren.Network
{
/// <summary>
/// NetRandom base class
/// </summary>
public abstract class NetRandom : Random
{
/// <summary>
/// Get global instance of NetRandom (uses MWCRandom)
/// </summary>
public static NetRandom Instance = new MWCRandom();
private const double c_realUnitInt = 1.0 / ((double)int.MaxValue + 1.0);
/// <summary>
/// Constructor with randomized seed
/// </summary>
public NetRandom()
{
Initialize(NetRandomSeed.GetUInt32());
}
/// <summary>
/// Constructor with provided 32 bit seed
/// </summary>
public NetRandom(int seed)
{
Initialize((uint)seed);
}
/// <summary>
/// (Re)initialize this instance with provided 32 bit seed
/// </summary>
[CLSCompliant(false)]
public virtual void Initialize(uint seed)
{
// should be abstract, but non-CLS compliant methods can't be abstract!
throw new NotImplementedException("Implement this in inherited classes");
}
/// <summary>
/// Generates a random value from UInt32.MinValue to UInt32.MaxValue, inclusively
/// </summary>
[CLSCompliant(false)]
public virtual uint NextUInt32()
{
// should be abstract, but non-CLS compliant methods can't be abstract!
throw new NotImplementedException("Implement this in inherited classes");
}
/// <summary>
/// Generates a random value that is greater or equal than 0 and less than Int32.MaxValue
/// </summary>
public override int Next()
{
var retval = (int)(0x7FFFFFFF & NextUInt32());
if (retval == 0x7FFFFFFF)
return NextInt32();
return retval;
}
/// <summary>
/// Generates a random value greater or equal than 0 and less or equal than Int32.MaxValue (inclusively)
/// </summary>
public int NextInt32()
{
return (int)(0x7FFFFFFF & NextUInt32());
}
/// <summary>
/// Returns random value larger or equal to 0.0 and less than 1.0
/// </summary>
public override double NextDouble()
{
return c_realUnitInt * NextInt32();
}
/// <summary>
/// Returns random value is greater or equal than 0.0 and less than 1.0
/// </summary>
protected override double Sample()
{
return c_realUnitInt * NextInt32();
}
/// <summary>
/// Returns random value is greater or equal than 0.0f and less than 1.0f
/// </summary>
public float NextSingle()
{
var retval = (float)(c_realUnitInt * NextInt32());
if (retval == 1.0f)
return NextSingle();
return retval;
}
/// <summary>
/// Returns a random value is greater or equal than 0 and less than maxValue
/// </summary>
public override int Next(int maxValue)
{
return (int)(NextDouble() * maxValue);
}
/// <summary>
/// Returns a random value is greater or equal than minValue and less than maxValue
/// </summary>
public override int Next(int minValue, int maxValue)
{
return minValue + (int)(NextDouble() * (double)(maxValue - minValue));
}
/// <summary>
/// Generates a random value between UInt64.MinValue to UInt64.MaxValue
/// </summary>
[CLSCompliant(false)]
public ulong NextUInt64()
{
ulong retval = NextUInt32();
retval |= NextUInt32() << 32;
return retval;
}
private uint m_boolValues;
private int m_nextBoolIndex;
/// <summary>
/// Returns true or false, randomly
/// </summary>
public bool NextBool()
{
if (m_nextBoolIndex >= 32)
{
m_boolValues = NextUInt32();
m_nextBoolIndex = 1;
}
var retval = ((m_boolValues >> m_nextBoolIndex) & 1) == 1;
m_nextBoolIndex++;
return retval;
}
/// <summary>
/// Fills all bytes from offset to offset + length in buffer with random values
/// </summary>
public virtual void NextBytes(byte[] buffer, int offset, int length)
{
int full = length / 4;
int ptr = offset;
for (int i = 0; i < full; i++)
{
uint r = NextUInt32();
buffer[ptr++] = (byte)r;
buffer[ptr++] = (byte)(r >> 8);
buffer[ptr++] = (byte)(r >> 16);
buffer[ptr++] = (byte)(r >> 24);
}
int rest = length - (full * 4);
for (int i = 0; i < rest; i++)
buffer[ptr++] = (byte)NextUInt32();
}
/// <summary>
/// Fill the specified buffer with random values
/// </summary>
public override void NextBytes(byte[] buffer)
{
NextBytes(buffer, 0, buffer.Length);
}
}
}