/// <summary> /// LCG constructor. /// <para>It is possible to define a randMax value less than or equal to m-1, as used by /// Rand48Lcg. Setting m to 0 negates the modulus.</para> /// </summary> /// <param name="randMax">Maximum value returned by Next()</param> /// <param name="a">Multiplier</param> /// <param name="c">Increment</param> /// <param name="m">Modulus</param> public LcgRng(ulong randMax, ulong a, ulong c, ulong m) : base(randMax) { if (m != 0 && m <= randMax) { throw new ArgumentException("randMax", "The RandMax value " + randMax + "is invalid (not possible with modulus " + m + ")."); } mult = a; inc = c; mod = m; // Determine a bit mask to use instead of modulus, if possible. // This yields as big performance improvement as the C# "%" operator // does not appear optimized where the maximum result is a power of 2 value. // Default where modulus is 0, // which implicitly means 2^64. modMask = UInt64.MaxValue; if (mod != 0) { modMask = mod - 1; // Number of bits needed by modulus int mbits = CleromUtil.BitSize(modMask); // If not equal, we can't use a mask. if (modMask != UInt64.MaxValue >> (64 - mbits)) { modMask = 0; } } }
/// <summary> /// Subclasses must supply 'randMax', the maximum possible value returned by the /// implementation of the Next() method. /// </summary> /// <param name="randMax">Maximum value returned by Next()</param> public Rng(ulong randMax) { if (randMax == 0) { throw new ArgumentException("randMax", "RandMax cannot be zero!"); } // Set read-only values nativeMax = randMax; native64 = (randMax == UInt64.MaxValue); native32 = (randMax == UInt32.MaxValue); // Get number of bits to use from Next(). // A RandMax of 2^31-1 gives us 31. shiftBits = CleromUtil.BitSize(randMax); shiftMax = UInt64.MaxValue >> (64 - shiftBits); if (randMax != shiftMax) { --shiftBits; shiftMax >>= 1; } // Initialize cache values ResetCache(); // Useful for confirming properties when debugging /* * Console.WriteLine(); * Console.WriteLine("NAME : " + AlgorithmName); * Console.WriteLine("RandMax : " + randMax); * Console.WriteLine("RandMax : 0x" + randMax.ToString("X16")); * Console.WriteLine("Native32 : " + native32); * Console.WriteLine("Native64 : " + native64); * Console.WriteLine("BitShift : " + shiftBits); * Console.WriteLine(); */ }