7
\$\begingroup\$

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));
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ Do you have a link to the specification of Xorgens4096? I couldn't find anything useful. \$\endgroup\$
    – t3chb0t
    Commented Nov 3, 2017 at 17:02
  • \$\begingroup\$ @t3chb0t: maths-people.anu.edu.au/~brent/random.html \$\endgroup\$
    – Thorham
    Commented Nov 4, 2017 at 10:16
  • \$\begingroup\$ This observation is not worth full answer, but why are state, index, weyl and hash public? \$\endgroup\$
    – user52292
    Commented Nov 14, 2018 at 16:42

1 Answer 1

8
\$\begingroup\$

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))
\$\endgroup\$
2
  • \$\begingroup\$ And I make every lock readonly (if possible), but am not against reusing parts, so, readonly ulong[] state would be a candidate (btw: why are these public?) \$\endgroup\$
    – user52292
    Commented Nov 14, 2018 at 16:40
  • \$\begingroup\$ Yeah, those are both good points \$\endgroup\$ Commented Nov 14, 2018 at 16:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.