You've already forked lidgren-network-gen3
mirror of
https://github.com/lidgren/lidgren-network-gen3.git
synced 2026-05-06 10:21:09 +09:00
NetRandom updated; four implementations provided: Multiply with carry, XorShift, Mersenne Twister and RNGCryptoServiceProvider based
This commit is contained in:
209
Lidgren.Network/NetRandom.Implementations.cs
Normal file
209
Lidgren.Network/NetRandom.Implementations.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Lidgren.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// Multiply With Carry random
|
||||
/// </summary>
|
||||
public class MWCRandom : NetRandom
|
||||
{
|
||||
public static readonly MWCRandom Instance = new MWCRandom();
|
||||
|
||||
private uint m_w, m_z;
|
||||
|
||||
public MWCRandom()
|
||||
{
|
||||
Initialize(NetRandomSeed.GetUInt64());
|
||||
}
|
||||
|
||||
public override void Initialize(uint seed)
|
||||
{
|
||||
m_w = seed;
|
||||
m_z = seed * 16777619;
|
||||
}
|
||||
|
||||
public void Initialize(ulong seed)
|
||||
{
|
||||
m_w = (uint)seed;
|
||||
m_z = (uint)(seed >> 32);
|
||||
}
|
||||
|
||||
public override uint NextUInt32()
|
||||
{
|
||||
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
|
||||
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
|
||||
return ((m_z << 16) + m_w);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xor Shift based random
|
||||
/// </summary>
|
||||
public sealed class XorShiftRandom : NetRandom
|
||||
{
|
||||
public static readonly XorShiftRandom Instance = new XorShiftRandom();
|
||||
|
||||
private const uint c_x = 123456789;
|
||||
private const uint c_y = 362436069;
|
||||
private const uint c_z = 521288629;
|
||||
private const uint c_w = 88675123;
|
||||
|
||||
private uint m_x, m_y, m_z, m_w;
|
||||
|
||||
public XorShiftRandom()
|
||||
{
|
||||
Initialize(NetRandomSeed.GetUInt64());
|
||||
}
|
||||
|
||||
public XorShiftRandom(ulong seed)
|
||||
{
|
||||
Initialize(seed);
|
||||
}
|
||||
|
||||
public override void Initialize(uint seed)
|
||||
{
|
||||
m_x = (uint)seed;
|
||||
m_y = c_y;
|
||||
m_z = c_z;
|
||||
m_w = c_w;
|
||||
}
|
||||
|
||||
public void Initialize(ulong seed)
|
||||
{
|
||||
m_x = (uint)seed;
|
||||
m_y = c_y;
|
||||
m_z = (uint)(seed << 32);
|
||||
m_w = c_w;
|
||||
}
|
||||
|
||||
public override uint NextUInt32()
|
||||
{
|
||||
uint t = (m_x ^ (m_x << 11));
|
||||
m_x = m_y; m_y = m_z; m_z = m_w;
|
||||
return (m_w = (m_w ^ (m_w >> 19)) ^ (t ^ (t >> 8)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mersenne Twister based random
|
||||
/// </summary>
|
||||
public sealed class MersenneTwisterRandom : NetRandom
|
||||
{
|
||||
public static readonly MersenneTwisterRandom Instance = new MersenneTwisterRandom();
|
||||
|
||||
private const int N = 624;
|
||||
private const int M = 397;
|
||||
private const uint MATRIX_A = 0x9908b0dfU;
|
||||
private const uint UPPER_MASK = 0x80000000U;
|
||||
private const uint LOWER_MASK = 0x7fffffffU;
|
||||
private const uint TEMPER1 = 0x9d2c5680U;
|
||||
private const uint TEMPER2 = 0xefc60000U;
|
||||
private const int TEMPER3 = 11;
|
||||
private const int TEMPER4 = 7;
|
||||
private const int TEMPER5 = 15;
|
||||
private const int TEMPER6 = 18;
|
||||
|
||||
private UInt32[] mt;
|
||||
private int mti;
|
||||
private UInt32[] mag01;
|
||||
|
||||
private const double c_realUnitInt = 1.0 / ((double)int.MaxValue + 1.0);
|
||||
|
||||
public MersenneTwisterRandom()
|
||||
{
|
||||
Initialize(NetRandomSeed.GetUInt32());
|
||||
}
|
||||
|
||||
public MersenneTwisterRandom(uint seed)
|
||||
{
|
||||
Initialize(seed);
|
||||
}
|
||||
|
||||
public override void Initialize(uint seed)
|
||||
{
|
||||
mt = new UInt32[N];
|
||||
mti = N + 1;
|
||||
mag01 = new UInt32[] { 0x0U, MATRIX_A };
|
||||
mt[0] = seed;
|
||||
for (int i = 1; i < N; i++)
|
||||
mt[i] = (UInt32)(1812433253 * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i);
|
||||
}
|
||||
|
||||
public override uint NextUInt32()
|
||||
{
|
||||
UInt32 y;
|
||||
if (mti >= N)
|
||||
{
|
||||
GenRandAll();
|
||||
mti = 0;
|
||||
}
|
||||
y = mt[mti++];
|
||||
y ^= (y >> TEMPER3);
|
||||
y ^= (y << TEMPER4) & TEMPER1;
|
||||
y ^= (y << TEMPER5) & TEMPER2;
|
||||
y ^= (y >> TEMPER6);
|
||||
return y;
|
||||
}
|
||||
|
||||
private void GenRandAll()
|
||||
{
|
||||
int kk = 1;
|
||||
UInt32 y;
|
||||
UInt32 p;
|
||||
y = mt[0] & UPPER_MASK;
|
||||
do
|
||||
{
|
||||
p = mt[kk];
|
||||
mt[kk - 1] = mt[kk + (M - 1)] ^ ((y | (p & LOWER_MASK)) >> 1) ^ mag01[p & 1];
|
||||
y = p & UPPER_MASK;
|
||||
} while (++kk < N - M + 1);
|
||||
do
|
||||
{
|
||||
p = mt[kk];
|
||||
mt[kk - 1] = mt[kk + (M - N - 1)] ^ ((y | (p & LOWER_MASK)) >> 1) ^ mag01[p & 1];
|
||||
y = p & UPPER_MASK;
|
||||
} while (++kk < N);
|
||||
p = mt[0];
|
||||
mt[N - 1] = mt[M - 1] ^ ((y | (p & LOWER_MASK)) >> 1) ^ mag01[p & 1];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RNGCryptoServiceProvider based random; very slow but cryptographically safe
|
||||
/// </summary>
|
||||
public class CryptoRandom : NetRandom
|
||||
{
|
||||
public static readonly CryptoRandom Instance = new CryptoRandom();
|
||||
|
||||
private RandomNumberGenerator m_rnd = new RNGCryptoServiceProvider();
|
||||
|
||||
/// <summary>
|
||||
/// Seed in CryptoRandom does not create deterministic sequences
|
||||
/// </summary>
|
||||
public override void Initialize(uint seed)
|
||||
{
|
||||
byte[] tmp = new byte[seed % 16];
|
||||
m_rnd.GetBytes(tmp); // just prime it
|
||||
}
|
||||
|
||||
public override uint NextUInt32()
|
||||
{
|
||||
var bytes = new byte[4];
|
||||
m_rnd.GetBytes(bytes);
|
||||
return (uint)bytes[0] | (((uint)bytes[1]) << 8) | (((uint)bytes[2]) << 16) | (((uint)bytes[3]) << 24);
|
||||
}
|
||||
|
||||
public override void NextBytes(byte[] buffer)
|
||||
{
|
||||
m_rnd.GetBytes(buffer);
|
||||
}
|
||||
|
||||
public override void NextBytes(byte[] buffer, int offset, int length)
|
||||
{
|
||||
var bytes = new byte[length];
|
||||
m_rnd.GetBytes(bytes);
|
||||
Array.Copy(bytes, 0, buffer, offset, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user