/// <summary> /// Performs a high-quality random shuffling of the list. /// Uses a user-provided random number generator, which /// </summary> /// <typeparam name="T">The type of elements in the list.</typeparam> /// <typeparam name="N">The type of numbers generated by the random numbers generator.</typeparam> /// <param name="list">The calling list object.</param> /// <param name="generator">A floating-point random number generator for the <typeparamref name="N"/> type.</param> /// <param name="numericComparer">An optional numeric comparer for <typeparamref name="N"/> type. If <c>null</c>, a standard comparer will be used (if exists, otherwise, an exception will be thrown).</param> public static void Shuffle <T, N>(this IList <T> list, IRandomFloatingPoint <N> generator, IComparer <N> numericComparer = null) { Contract.Requires <ArgumentNullException>(list != null, "list"); Contract.Requires <ArgumentNullException>(generator != null, "generator"); if (numericComparer == null) { numericComparer = Comparer <N> .Default; } // Генерируем массив пар со случайными ключами, // сортируем их по ключу (а значения оказываются случайно перемешанными). List <KeyValuePair <N, T> > pairList = new List <KeyValuePair <N, T> >(list.Count); foreach (T element in list) { pairList.Add(new KeyValuePair <N, T>(generator.Next_SingleInterval(), element)); } IComparer <KeyValuePair <N, T> > pairComparer = numericComparer.createKVPComparerOnKey <N, T>(); pairList.Sort(pairComparer); // Восстанавливаем. for (int i = 0; i < pairList.Count; i++) { list[i] = pairList[i].Value; } }
/// <summary> /// Constructs a Fibonacci lagged pseudo-random number generator using the lag values and /// another generator for the first sequence members. /// /// Examples of recommended lag values: /// /// a) 17; 5 /// b) 55; 24 /// c) 97; 33. /// /// It is not recommended to provide random lag values as it will affect /// the quality of the generator randomization. /// </summary> /// <param name="firstGenerator">The IRandom(T) implementer object to receive the first values of the pseudo-random sequence.</param> /// <param name="a">The first lag of the fibonacci generator. Optional. By default, equals 97.</param> /// <param name="b">The second lag of the fibonacci generator. Optional. By default, equals 33.</param> public RandomLaggedFibonacci(IRandomFloatingPoint <double> firstGenerator, int a = 97, int b = 33) { this.a = a; this.b = b; this.max = Math.Max(a, b); for (int i = 0; i < max; i++) { list.AddLast(firstGenerator.Next_SingleInterval()); } xkmaNode = list.First; xkmbNode = list.First; for (int i = 0; i < max - a; i++) { xkmaNode = xkmaNode.Next; } for (int i = 0; i < max - b; i++) { xkmbNode = xkmbNode.Next; } return; }
/// <summary> /// Initializes the wrapper instance with a floating-point generator /// and a numeric interval. /// </summary> /// <param name="gen">A floating-point generator.</param> /// <param name="minimum">The lower inclusive boundary for generated numbers.</param> /// <param name="maximum">The upper exclusive boundary for generated numbers.</param> public ___RandomFP_UnboundedWrapper(IRandomFloatingPoint <T> gen, T minimum, T maximum) { Contract.Requires <ArgumentNullException>(gen != null, "gen"); Contract.Requires <ArgumentException>(Numeric <T, C> .Calculator.mor(maximum, minimum), "The upper boundary of generated values should be bigger than the lower boundary."); this.Generator = gen; this.Minimum = minimum; this.Maximum = maximum; }
public RandomNormalBoxMuller(IRandomFloatingPoint <T> uniformGenerator, T mean, T standardDeviation, Func <T, T> naturalLogarithmFunction, Func <T, T> squareRootFunction) { this.generator = uniformGenerator; this.mean = mean; this.standardDeviation = standardDeviation; this.naturalLogarithmFunction = naturalLogarithmFunction; this.squareRootFunction = squareRootFunction; this.nextAvailable = false; this.next = default(T); this.transformFunction = delegate(T value, T squareSum) { return((Numeric <T, C>)value * squareRootFunction(-Numeric <T, C> ._2 * naturalLogarithmFunction(squareSum) / squareSum)); }; }
// ------------------------------------------------------------------------------ // ----------------------------- Floating-point generator extensions ------------ /// <summary> /// Makes use of an <c>IRandomFloatingPoint<<typeparamref name="T"/>></c> /// instance and enables it to produce values in an arbitrary range (i.e. wraps it /// around to make it an <c>IRandomBounded<<typeparamref name="T"/>></c> object). /// </summary> /// <remarks> /// Because the wrapper object will use multiplication scaling to produce random numbers, /// please notice that for bigger intervals the quality of the distribution /// may seriously suffer due to scale irregularity of some numeric types, e.g. <c>double</c>. /// </remarks> /// <typeparam name="T">The type of numbers generated by <paramref name="gen"/>.</typeparam> /// <typeparam name="C">A calculator type for the <typeparamref name="T"/> type.</typeparam> /// <param name="gen">An <c>IRandomFloatingPoint<<typeparamref name="T"/>></c> instance.</param> /// <returns> /// An <c>IRandomBounded<<typeparamref name="T"/>></c> object that makes use /// of <paramref name="gen"/> and produces values in arbitrary ranges by scaling.</returns> public static IRandomBounded <T> TreatAsBoundedGenerator <T, C>(this IRandomFloatingPoint <T> gen) where C : ICalc <T>, new() { return(new ___RandomFP_BoundedWrapper <T, C>(gen)); }
/// <summary> /// Initializes the wrapper instance with a floating-point generator. /// </summary> /// <param name="gen">A floating-point generator for the type <typeparamref name="T"/></param> public ___RandomFP_BoundedWrapper(IRandomFloatingPoint <T> gen) { Contract.Requires <ArgumentNullException>(gen != null, "gen"); this.Generator = gen; }
/// <summary> /// Makes use of an <c>IRandomFloatingPoint<<typeparamref name="T"/>></c> /// instance and enables it to produce values in a constant, pre-set range (i.e. wraps it /// around to make it an as an <c>IRandomUnbounded<<typeparamref name="T"/>></c> object). /// </summary> /// <remarks> /// Because the wrapper object will use multiplication scaling to produce random numbers, /// please notice that for bigger intervals the quality of the distribution /// may seriously suffer due to scale irregularity of some numeric types, e.g. <c>double</c>. /// </remarks> /// <typeparam name="T">The type of numbers generated by <paramref name="gen"/>.</typeparam> /// <typeparam name="C">A calculator type for the <typeparamref name="T"/> type.</typeparam> /// <param name="gen">An <c>IRandomFloatingPoint<<typeparamref name="T"/>></c> instance.</param> /// <param name="minimum">The lower inclusive boundary for generated values.</param> /// <param name="maximum">The upper exclusive boundary for generated values.</param> /// <returns> /// An <c>IRandomBounded<<typeparamref name="T"/>></c> object that makes use /// of <paramref name="gen"/> and produces values in arbitrary ranges by scaling.</returns> public static IRandomUnbounded <T> TreatAsUnboundedGenerator <T, C>(this IRandomFloatingPoint <T> gen, T minimum, T maximum) where C : ICalc <T>, new() { return(new ___RandomFP_UnboundedWrapper <T, C>(gen, minimum, maximum)); }
public RandomNormalBoxMuller(IRandomFloatingPoint <T> uniformGenerator, Func <T, T> naturalLogarithmFunction, Func <T, T> squareRootFunction) : this(uniformGenerator, Numeric <T, C> .Zero, Numeric <T, C> ._1, naturalLogarithmFunction, squareRootFunction) { }