A fast random number generator for .NET Colin Green, January 2005 Key points: 1) Based on a simple and fast xor-shift pseudo random number generator (RNG) specified in: Marsaglia, George. (2003). Xorshift RNGs. http://www.jstatsoft.org/v08/i14/paper This particular implementation of xorshift has a period of 2^128-1. See the above paper to see how this can be easily extened if you need a longer period. At the time of writing I could find no information on the period of System.Random for comparison. 2) Faster than System.Random. Up to 8x faster, depending on which methods are called. 3) Direct replacement for System.Random. This class implements all of the methods that System.Random does plus some additional methods. The like named methods are functionally equivalent. 4) Allows fast re-initialisation with a seed, unlike System.Random which accepts a seed at construction time which then executes a relatively expensive initialisation routine. This provides a vast speed improvement if you need to reset the pseudo-random number sequence many times, e.g. if you want to re-generate the same sequence of random numbers many times. An alternative might be to cache random numbers in an array, but that approach is limited by memory capacity and the fact that you may also want a large number of different sequences cached. Each sequence can be represented by a single seed value (int) when using FastRandom. Notes. A further performance improvement can be obtained by declaring local variables as static, thus avoiding re-allocation of variables on each call. However care should be taken if multiple instances of FastRandom are in use or if being used in a multi-threaded environment. Colin Green, September 4th 2005 - Added NextBytesUnsafe() - commented out by default. - Fixed bug in Reinitialise() - y,z and w variables were not being reset. Colin Green, December 2008. - Fix to Next() - Was previously able to return int.MaxValue, contrary to the method's contract and comments. - Modified NextBool() to use _bitMask instead of a count of remaining bits. Also reset the bit buffer in Reinitialise(). Colin Green, 2011-08-31 - Added NextByte() method. - Added new statically declared seedRng FastRandom to allow easy creation of multiple FastRandoms with different seeds within a single clock tick. Colin Green, 2011-10-04 - Seeds are now hashed. Without this the first random sample for nearby seeds (1,2,3, etc.) are very similar (have a similar bit pattern). Thanks to Francois Guibert for identifying this problem.
        /// <summary>
        /// Performs a single throw onto a roulette wheel where the wheel's space is unevenly divided between outcomes.
        /// The probabilty that a segment will be selected is given by that segment's value in the 'probabilities'
        /// array within the specified RouletteWheelLayout. The probabilities within a RouletteWheelLayout have already 
        /// been normalised so that their total is always equal to 1.0.
        /// </summary>
        /// <param name="layout">The roulette wheel layout.</param>
        /// <param name="rng">Random number generator.</param>
        public static int SingleThrow(RouletteWheelLayout layout, FastRandom rng)
        {
            // Throw the ball and return an integer indicating the outcome.
            double throwValue = layout.ProbabilitiesTotal * rng.NextDouble();
            double accumulator = 0.0;
            for(int i=0; i<layout.Probabilities.Length; i++)
            {
                accumulator += layout.Probabilities[i];
                if(throwValue < accumulator) {
                    return layout.Labels[i];
                }
            }

            // We might get here through floating point arithmetic rounding issues. 
            // e.g. accumulator == throwValue. 

            // Find a nearby non-zero probability to select.
            // Wrap around to start of array.
            for(int i=0; i<layout.Probabilities.Length; i++)
            {
                if(layout.Probabilities[i] != 0.0) {
                    return layout.Labels[i];
                }
            }

            // If we get here then we have an array of zero probabilities.
            throw new SharpNeatException("Invalid operation. No non-zero probabilities to select.");
        }
 /// <summary>
 /// Genetic mutation for auxiliary argument data.
 /// </summary>
 public void MutateAuxArgs(double[] auxArgs, FastRandom rng, ZigguratGaussianSampler gaussianSampler, double connectionWeightRange)
 {
     throw new SharpNeatException("MutateAuxArgs() called on activation function that does not use auxiliary arguments.");
 }
 /// <summary>
 /// For activation functions that accept auxiliary arguments; generates random initial values for aux arguments for newly
 /// added nodes (from an 'add neuron' mutation).
 /// </summary>
 public double[] GetRandomAuxArgs(FastRandom rng, double connectionWeightRange)
 {
     throw new SharpNeatException("GetRandomAuxArgs() called on activation function that does not use auxiliary arguments.");
 }
 /// <summary>
 /// Gets the single NEAT activation function provided at construction time.
 /// The provided random number generator is not used in this implementation.
 /// </summary>
 /// <param name="rng"></param>
 /// <returns></returns>
 public ActivationFunctionInfo GetRandomFunction(FastRandom rng)
 {
     return _activationFnInfo;
 }
 /// <summary>
 /// Performs a single throw for a given number of outcomes with equal probabilities.
 /// </summary>
 /// <param name="numberOfOutcomes">The number of possible outcomes.</param>
 /// <param name="rng">Random number generator.</param>
 /// <returns>An integer between 0..numberOfOutcomes-1. In effect this routine selects one of the possible outcomes.</returns>
 public static int SingleThrowEven(int numberOfOutcomes, FastRandom rng)
 {
     return (int)(rng.NextDouble() * numberOfOutcomes);
 }
 /// <summary>
 /// A simple single throw routine.
 /// </summary>
 /// <param name="probability">A probability between 0..1 that the throw will result in a true result.</param>
 /// <param name="rng">Random number generator.</param>
 public static bool SingleThrow(double probability, FastRandom rng)
 {
     return rng.NextDouble() < probability;
 }
 /// <summary>
 /// Default constructor.
 /// </summary>
 public TestCaseField()
 {
     _rng = new FastRandom();
 }
 /// <summary>
 /// Randomly select a function based on each function's selection probability.
 /// </summary>
 public ActivationFunctionInfo GetRandomFunction(FastRandom rng)
 {
     return _functionList[RouletteWheel.SingleThrow(_rwl, rng)];
 }