/// <summary> /// Initializes a new instance of the <see cref="Palf"/> class. /// </summary> /// <param name="seed">The seed value.</param> /// <param name="threadSafe">if set to <c>true</c>, the class is thread safe.</param> /// <param name="shortLag">The ShortLag value</param> /// <param name="longLag">TheLongLag value</param> public Palf(int seed, bool threadSafe, int shortLag, int longLag) : base(threadSafe) { if (shortLag < 1) { throw new ArgumentException(Resources.ArgumentMustBePositive, "shortLag"); } if (longLag <= shortLag) { throw new ArgumentException(Resources.ArgumentUpperBoundMustBeLargerThanLowerBound, "longLag"); } if (seed == 0) { seed = 1; } _threads = Control.MaxDegreeOfParallelism; ShortLag = shortLag; // Align LongLag to number of worker threads. if (longLag % _threads == 0) { LongLag = longLag; } else { LongLag = ((longLag / _threads) + 1) * _threads; } _x = Generate.Map(MersenneTwister.Doubles(LongLag, seed), uniform => (uint)(uniform * uint.MaxValue)); _k = LongLag; }
/// <summary> /// Initializes a new instance of the <see cref="Palf"/> class. /// </summary> /// <param name="seed">The seed value.</param> /// <param name="threadSafe">if set to <c>true</c>, the class is thread safe.</param> /// <param name="shortLag">The ShortLag value</param> /// <param name="longLag">TheLongLag value</param> public Palf(int seed, bool threadSafe, int shortLag, int longLag) : base(threadSafe) { if (shortLag < 1) { throw new ArgumentException("Value must be positive.", nameof(shortLag)); } if (longLag <= shortLag) { throw new ArgumentException("The upper bound must be strictly larger than the lower bound.", nameof(longLag)); } if (seed == 0) { seed = 1; } _threads = Control.MaxDegreeOfParallelism; ShortLag = shortLag; // Align LongLag to number of worker threads. if (longLag % _threads == 0) { LongLag = longLag; } else { LongLag = ((longLag / _threads) + 1) * _threads; } _x = Generate.Map(MersenneTwister.Doubles(LongLag, seed), uniform => (uint)(uniform * uint.MaxValue)); _k = LongLag; }
/// <summary> /// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0. /// </summary> /// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks> public static IEnumerable <double> DoubleSequence(int seed) { if (seed == 0) { seed = 1; } int threads = Control.MaxDegreeOfParallelism; const int shortLag = DefaultShortLag; var longLag = DefaultLongLag; // Align LongLag to number of worker threads. if (longLag % threads != 0) { longLag = ((longLag / threads) + 1) * threads; } var x = Generate.Map(MersenneTwister.Doubles(longLag, seed), uniform => (uint)(uniform * uint.MaxValue)); var k = longLag; while (true) { if (k >= longLag) { for (int index = 0; index < threads; index++) { // Two loops to avoid costly modulo operations for (var j = index; j < shortLag; j = j + threads) { x[j] += x[j + (longLag - shortLag)]; } for (var j = shortLag + index; j < longLag; j = j + threads) { x[j] += x[j - shortLag - index]; } } k = 0; } yield return(x[k++] * Reciprocal); } }
/// <summary> /// Fills an array with random numbers greater than or equal to 0.0 and less than 1.0. /// </summary> /// <remarks>Supports being called in parallel from multiple threads.</remarks> public static void Doubles(double[] values, int seed) { if (seed == 0) { seed = 1; } int threads = Control.MaxDegreeOfParallelism; const int shortLag = DefaultShortLag; var longLag = DefaultLongLag; // Align LongLag to number of worker threads. if (longLag % threads != 0) { longLag = ((longLag / threads) + 1) * threads; } var x = Generate.Map(MersenneTwister.Doubles(longLag, seed), uniform => (uint)(uniform * uint.MaxValue)); var k = longLag; for (int i = 0; i < values.Length; i++) { if (k >= longLag) { for (int index = 0; index < threads; index++) { // Two loops to avoid costly modulo operations for (var j = index; j < shortLag; j = j + threads) { x[j] += x[j + (longLag - shortLag)]; } for (var j = shortLag + index; j < longLag; j = j + threads) { x[j] += x[j - shortLag - index]; } } k = 0; } values[i] = (int)(x[k++] >> 1) * IntToDoubleMultiplier; } }