Xorgens4096 PRNG with global seeder in C# 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 &lt; 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) &amp; 63];
        t ^= t &lt;&lt; 33;
        t ^= t &gt;&gt; 26;

        ulong v = state[(index + 11) &amp; 63];
        v ^= v &lt;&lt; 27;
        v ^= v &gt;&gt; 29;

        state[index] = (v ^= t);

        weyl += 0x61c8864680b583eb;

        return v + (weyl ^ (weyl &gt;&gt; 27));
    }
}
The only thing I see that needs correcting is the locking.  Remember that 

lock (hash) {
    // body
}


is syntactic sugar for:

var local = hash;
try
{
    System.Threading.Monitor.Enter(local);
    // body
}
finally
{
    System.Threading.Monitor.Exit(local);
}


When you update the hash variable in one thread, the next thread to come in will have a different object that it locks, and so the blocks will execute in parallel.  It's usually a mistake to try to reuse part of your model as a lock.  I always recommend a dedicated object like

static readonly Object _lock = new Object();


Other than that, I only suggest:

if (String.IsNullOrEmpty(seed) == false)


should be:

if (!String.IsNullOrEmpty(seed))