This is a basic implementation of the non-cryptographic Xorgens4096 pseudo random number generator with a global, thread safe seeder. The goal is to provide a high quality generator that can be instantiated in multiple threads while still guaranteeing that the seed for each generator is unique. To ensure uniqueness of each generator's state, SHA512 is used in feedback mode (if that's the right word).
Is this the right approach? Any criticism and tips are very much appreciated.
using System;
using System.Diagnostics;
using System.Text;
using System.Security.Cryptography;
// big state non-cryptographic PRNG with a global seeder
class Xorgens4096
{
// seeder part
static private SHA512 sha512;
static public byte[] hash;
// set master seed using some common data for uniqueness
static Xorgens4096()
{
sha512 = SHA512.Create();
SetMasterSeed(String.Format("{0}-{1}-{2}",
DateTime.UtcNow.Ticks,
Process.GetCurrentProcess().Id,
Guid.NewGuid()));
}
// set master seed used to derive states of all generator instances
static public void SetMasterSeed(string seed)
{
hash = Encoding.Unicode.GetBytes(seed);
}
// create generator state using a seed or master seed (thread safe)
static private void Seed(string seed, ulong[] state)
{
lock (hash)
{
if (String.IsNullOrEmpty(seed) == false)
hash = Encoding.Unicode.GetBytes(seed);
for (int i = 0; i < 8; i++)
{
hash = sha512.ComputeHash(hash);
Buffer.BlockCopy(hash, 0, state, i * 64, 64);
}
}
}
// generator part
public ulong[] state = new ulong[64];
public ulong index;
public ulong weyl;
public Xorgens4096(string seed = "")
{
Seed(seed);
}
public void Seed(string seed)
{
Seed(seed, state);
index = 0;
weyl = 0;
}
// actual xorgens4096 generator
public ulong Gen()
{
ulong t = state[index = (index + 1) & 63];
t ^= t << 33;
t ^= t >> 26;
ulong v = state[(index + 11) & 63];
v ^= v << 27;
v ^= v >> 29;
state[index] = (v ^= t);
weyl += 0x61c8864680b583eb;
return v + (weyl ^ (weyl >> 27));
}
}
state
,index
,weyl
andhash
public? \$\endgroup\$