public override void SetSeed(ulong[] seed) { // Don't allow all zero values with this generator. if (seed == null || CleromUtil.IsArrayZero(seed)) { SetStartingState(); // Important to reset base cache ResetCache(); } else if (seed.Length > 0) { if (seed.Length == 1) { SetStartingState(); state0 = seed[0]; } else { state0 = seed[0]; state1 = seed[1]; } ResetCache(); } }
/// <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; } } }
public override void SetSeed(ulong[] seed) { // Don't allow all zero values with this generator. if (seed == null || CleromUtil.IsArrayZero(seed)) { SetStartingState(); // Important to reset base cache ResetCache(); } else if (seed.Length > 0) { if (seed.Length < StateSize) { SetStartingState(); Buffer.BlockCopy(seed, 0, state, 0, seed.Length * sizeof(ulong)); } else { Buffer.BlockCopy(seed, 0, state, 0, StateSize * sizeof(ulong)); } stateIdx = 0; ResetCache(); } }
/// <summary> /// Generates a new random seed of SeedLength values for use with seeding the generator, /// but does not modify the state of the generator itself. It is called by Randomize(). /// <para>The seed is generated by the underlying OS via the RNGCryptoServiceProvider /// class. It may be overridden to generate seeds according to custom requirements.</para> /// </summary> public virtual TInteg[] GenerateSeed() { TInteg[] rslt = null; byte[] bytes = new byte[SeedLength * TypeSize]; if (bytes.Length > 0) { RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider(); crypto.GetBytes(bytes); rslt = CleromUtil.ConvertBytesToArray <TInteg>(bytes); } return(rslt); }
/// <summary> /// Sets the generator to a new state, defined by a single 64-bit integer seed value. /// <para>This overloaded variant of SetSeed() provides a convenient means to seed /// any generator with a single integer value.</para> /// <para>Its behavior is as follows:</para> /// <para>If SeedLength is 1, the seed value will be cast to the corresponding TInteg /// type, copied to an array of length 1, and passed directly to SetSeed(TInteg[]).</para> /// <para>If SeedLength is larger than 1, the integer seed will be "expanded" to an array /// of SeedLength values, which will then be passed to SetSeed(TInteg[]).</para> /// <para>The number of possible seed values using this method may, therefore, be /// significantly less than that supported by the SetSeed(TInteg[]) array variant.</para> /// <para>Seeding with this method or, indeed, with any single integer value, should /// not be considered suitable for cryptographic use.</para> /// <para>Furthermore, seed expansions are to be considered implementation dependent, /// in the sense that the implementation may potentially change with some future update /// to the library.</para> /// <para>Currently, expansions are performed using the SPLITMIX64 generator which, /// itself, has a 64-bit seed type. If you require future-proof repeatability, /// override this method with your own.</para> /// </summary> /// <param name="seed">Integer seed value</param> public virtual void SetSeed(ulong seed) { if (SeedLength == 1) { var arr = new TInteg[1]; arr[0] = (TInteg)(dynamic)seed; SetSeed(arr); } else { SplitMix64 temp = new SplitMix64(); temp.SetSeed(seed); byte[] bs = temp.GetBytes(TypeSize * SeedLength); SetSeed(CleromUtil.ConvertBytesToArray <TInteg>(bs)); } }
/// <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(); */ }