public HaltonRandomSeries( int haltonCount, IRandomUniform randomUniform) { m_haltonStateArray = new double[haltonCount].SetByIndex( i => randomUniform.UniformDouble()); m_randomUniform = randomUniform; }
public static V2d UniformV2dDirection(this IRandomUniform rnd) { double phi = rnd.UniformDouble() * Constant.PiTimesTwo; return(new V2d(System.Math.Cos(phi), System.Math.Sin(phi))); }
/// <summary> /// Returns a random subset of the enumeration with a supplied number of /// elements (subsetCount). The elements in the subset are in the /// same order as in the input. O(count). /// NOTE: The number of elements of the Enumerable need to be calculated, in case of true enumerations /// the implementation of .Count() results in a second evaluation of the enumerable. /// </summary> public static T[] CreateRandomSubsetOfSize <T>( this IEnumerable <T> input, long subsetCount, IRandomUniform rnd = null) { if (rnd == null) { rnd = new RandomSystem(); } long count = input.Count(); if (!(subsetCount >= 0 && subsetCount <= count)) { throw new ArgumentOutOfRangeException(nameof(subsetCount)); } var subset = new T[subsetCount]; long si = 0, ai = 0; foreach (var a in input) { if (ai < count && si < subsetCount) { var p = (double)(subsetCount - si) / (double)(count - ai++); if (rnd.UniformDouble() <= p) { subset[si++] = a; } } else { break; } } return(subset); }
/// <summary> /// Returns a random subset of an array with a supplied number of /// elements (subsetCount). The elements in the subset are in the /// same order as in the original array. O(count). /// NOTE: this method needs to generate one random number for each /// element of the original array. If subsetCount is significantly /// smaller than count, it is more efficient to use /// <see cref="CreateSmallRandomSubsetIndexArray"/> or /// <see cref="CreateSmallRandomSubsetIndexArrayLong"/> or /// <see cref="CreateSmallRandomOrderedSubsetIndexArray"/> or /// <see cref="CreateSmallRandomOrderedSubsetIndexArrayLong"/>. /// </summary> public static T[] CreateRandomSubsetOfSize <T>( this T[] array, long subsetCount, IRandomUniform rnd = null) { if (rnd == null) { rnd = new RandomSystem(); } long count = array.LongLength; if (!(subsetCount >= 0 && subsetCount <= count)) { throw new ArgumentOutOfRangeException(nameof(subsetCount)); } var subset = new T[subsetCount]; long si = 0; for (int ai = 0; ai < count && si < subsetCount; ai++) { var p = (double)(subsetCount - si) / (double)(count - ai); if (rnd.UniformDouble() <= p) { subset[si++] = array[ai]; } } return(subset); }
/// <summary> /// Returns a fully uniformly distributed vector (corresponds to a /// uniformly distributed point on the surface of the unit sphere). /// Note however, that the returned vector will never be equal to /// [0, 0, -1]. /// </summary> public static V3d UniformV3dFullDirection(this IRandomUniform rnd) { double phi = rnd.UniformDoubleFull() * Constant.PiTimesTwo; double z = 1.0 - rnd.UniformDoubleFull() * 2.0; double s = System.Math.Sqrt(1.0 - z * z); return(new V3d(System.Math.Cos(phi) * s, System.Math.Sin(phi) * s, z)); }
/// <summary> /// Randomly permute the specified number of elements in the supplied /// array starting at the specified index. /// </summary> public static void Randomize <T>( this IRandomUniform rnd, T[] array, long start, long count) { for (long i = start, e = start + count; i < e; i++) { array.Swap(i, start + rnd.UniformLong(count)); } }
/// <summary> /// Creates an array that contains a random permutation of the /// numbers in the interval [0, count-1]. /// </summary> public static long[] CreatePermutationArrayLong( this IRandomUniform rnd, long count) { var p = new long[count].SetByIndexLong(i => i); rnd.Randomize(p); return(p); }
/// <summary> /// Creates an array that contains a random permutation of the /// ints in the interval [0, count-1]. /// </summary> public static int[] CreatePermutationArray( this IRandomUniform rnd, int count) { var p = new int[count].SetByIndex(i => i); rnd.Randomize(p); return(p); }
/// <summary> /// Create a random array of full doubles in the half-open interval /// [0.0, 1.0) of the specified length. /// </summary> public static double[] CreateUniformDoubleFullArray( this IRandomUniform rnd, long length) { var array = new double[length]; rnd.FillUniformFull(array); return(array); }
/// <summary> /// Create a random array of floats in the half-open interval /// [0.0, 1.0) of the specified length. /// </summary> public static float[] CreateUniformFloatArray( this IRandomUniform rnd, long length) { var array = new float[length]; rnd.FillUniform(array); return(array); }
/// <summary> /// Randomly permute the specified number of elements in the supplied /// array starting at the specified index. /// </summary> public static void Randomize <T>( this IRandomUniform rnd, T[] array, int start, int count) { for (int i = start, e = start + count; i < e; i++) { array.Swap(i, start + rnd.UniformInt(count)); } }
/// <summary> /// Creates an ordered array of subsetCount int indices that /// constitute a subset of all ints in the range [0, count-1]. /// O(subsetCount * log(subsetCount)) for subsetCount << count. /// NOTE: It is assumed that subsetCount is significantly smaller /// than count. If this is not the case, use /// CreateRandomSubsetOfSize instead. /// WARNING: As subsetCount approaches count execution time /// increases significantly. /// </summary> public static int[] CreateSmallRandomOrderedSubsetIndexArray( this IRandomUniform rnd, int subsetCount, int count) { var subsetIndexArray = rnd.CreateSmallRandomSubsetIndexArray(subsetCount, count); subsetIndexArray.QuickSortAscending(); return(subsetIndexArray); }
/// <summary> /// Creates an ordered array of subsetCount long indices that /// constitute a subset of all longs in the range [0, count-1]. /// O(subsetCount * log(subsetCount)) for subsetCount << count. /// NOTE: It is assumed that subsetCount is significantly smaller /// than count. If this is not the case, use /// CreateRandomSubsetOfSize instead. /// WARNING: As subsetCount approaches count execution time /// increases significantly. /// </summary> public static long[] CreateSmallRandomOrderedSubsetIndexArrayLong( this IRandomUniform rnd, long subsetCount, long count) { var subsetIndexArray = rnd.CreateSmallRandomSubsetIndexArrayLong(subsetCount, count); subsetIndexArray.QuickSortAscending(); return(subsetIndexArray); }
/// <summary> /// Randomly permute the specified number of elements in the supplied /// list starting at the specified index. /// </summary> public static void Randomize <T>( this IRandomUniform rnd, List <T> list, int start, int count) { for (int i = start; i < start + count; i++) { list.Swap(i, start + rnd.UniformInt(count)); } }
/// <summary> /// Fills the specified array with random floats in the half-open /// interval [0.0f, 1.0f). /// </summary> public static void FillUniform(this IRandomUniform rnd, float[] array) { long count = array.LongLength; for (long i = 0; i < count; i++) { array[i] = rnd.UniformFloat(); } }
/// <summary> /// Returns a uniform long which is guaranteed not to be zero. /// </summary> public static long UniformLongNonZero(this IRandomUniform rnd) { long r; do { r = rnd.UniformLong(); } while (r == 0); return(r); }
/// <summary> /// Returns a uniform int which is guaranteed not to be zero. /// </summary> public static int UniformIntNonZero(this IRandomUniform rnd) { int r; do { r = rnd.UniformInt(); } while (r == 0); return(r); }
/// <summary> /// Generates normal distributed random variable with given mean and standard deviation. /// Uses the Box-Muller Transformation to transform two uniform distributed random variables to one normal distributed value. /// NOTE: If multiple normal distributed random values are required, consider using <see cref="RandomGaussian"/>. /// </summary> public static double Gaussian(this IRandomUniform rnd, double mean = 0.0, double stdDev = 1.0) { // Box-Muller Transformation var u1 = 1.0 - rnd.UniformDouble(); // uniform (0,1] -> log requires > 0 var u2 = rnd.UniformDouble(); // uniform [0,1) var randStdNormal = Fun.Sqrt(-2.0 * Fun.Log(u1)) * Fun.Sin(Constant.PiTimesTwo * u2); return(mean + stdDev * randStdNormal); }
/// <summary> /// Create a ForcedRandomSeries with the given sample sequence and the seed as offset. /// The sequence is supposed to contain NxN points in random order. /// </summary> public ForcedRandomSeries(V2i[] series, int matrixSize, IRandomUniform rnd, bool jitter = true) { m_series = series; m_matrixSize = matrixSize; m_norm = 1.0 / m_matrixSize; // [0, 1) m_rnd = rnd; m_jitter = jitter; // random offset of sample pattern m_seed = new V2i(rnd.UniformInt(m_matrixSize), rnd.UniformInt(m_matrixSize)); }
/// <summary> /// Randomly permute the elements of the supplied list. /// </summary> public static void Randomize <T>( this IRandomUniform rnd, List <T> list) { int count = list.Count; for (int i = 0; i < count; i++) { list.Swap(i, rnd.UniformInt(count)); } }
/// <summary> /// Creates clusters for all points which are within an epsilon /// distance from each other. This algorithm uses a hash-grid and /// only works fast if the supplied epsilon is small enough that /// not too many points fall within each cluster. Thus it is ideal /// for merging vertices in meshes and point sets, that are different /// due to numerical inaccuracies. /// </summary> public PointEpsilonClustering(V3d[] pa, double epsilon, IRandomUniform rnd = null) { rnd = rnd ?? new RandomSystem(); var count = pa.Length; Alloc(count); var ca = m_indexArray; var dict = new IntDict <int>(count, stackDuplicateKeys: true); int rndBits = 0; int bit = 0; var ha = new int[8]; var eps2 = epsilon * epsilon; for (int i = 0; i < count; i++) { var p = pa[i]; p.HashCodes8(epsilon, ha); int ci = ca[i]; if (ca[ci] != ci) { do { ci = ca[ci]; } while (ca[ci] != ci); ca[i] = ci; } for (int hi = 0; hi < 8; hi++) { foreach (var j in dict.ValuesWithKey(ha[hi])) { int cj = ca[j]; if (ca[cj] != cj) { do { cj = ca[cj]; } while (ca[cj] != cj); ca[j] = cj; } if (ci == cj || V3d.DistanceSquared(p, pa[j]) >= eps2) { continue; } bit >>= 1; if (bit == 0) { rndBits = rnd.UniformInt(); bit = 1 << 30; } if ((rndBits & bit) != 0) { ca[ci] = cj; ca[i] = cj; ci = cj; } else { ca[cj] = ci; ca[j] = ci; } } } dict[ha[0]] = i; } Init(); }
/// <summary> /// Returns a uniformly distributed int in the interval [0, count-1]. /// In order to avoid excessive aliasing, two random numbers are used /// when count is greater or equal 2^24 and the random generator /// delivers 32 random bits or less. The method thus works fairly /// decently for all integers. /// </summary> public static int UniformInt(this IRandomUniform rnd, int size) { if (rnd.GeneratesFullDoubles || size < 16777216) { return((int)(rnd.UniformDouble() * size)); } else { return((int)(rnd.UniformDoubleFull() * size)); } }
/// <summary> /// Returns a uniformly distributed long in the interval [0, size-1]. /// NOTE: If count has more than about 48 bits, aliasing leads to /// noticeable (greater 5%) shifts in the probabilities (i.e. one /// long has a probability of x and the other a probability of /// x * (2^(52-b)-1)/(2^(52-b)), where b is log(size)/log(2)). /// </summary> public static long UniformLong(this IRandomUniform rnd, long size) { if (rnd.GeneratesFullDoubles || size < 16777216) { return((long)(rnd.UniformDouble() * size)); } else { return((long)(rnd.UniformDoubleFull() * size)); } }
/// <summary> /// Returns a uniformly distributed double in the closed interval /// [0.0, 1.0]. Note, that two random values are used to make all 53 /// bits random. /// </summary> public static double UniformDoubleFullClosed(this IRandomUniform rnd) { if (rnd.GeneratesFullDoubles) { return(rnd.UniformDoubleClosed()); } long r = ((~0xfL & (long)rnd.UniformInt()) << 22) | ((long)rnd.UniformInt() >> 5); return(r * (1.0 / 9007199254740991.0)); }
/// <summary> /// Enumerates elements in random order. /// </summary> public static IEnumerable <T> RandomOrder <T>(this IEnumerable <T> self, IRandomUniform rnd = null) { var tmp = self.ToArray(); if (rnd == null) { rnd = new RandomSystem(); } var perm = rnd.CreatePermutationArray(tmp.Length); return(perm.Select(index => tmp[index])); }
/// <summary> /// Uniform vector in the closed unit sphere (i.e vectors to /// the surface of the sphere may be generated). /// </summary> public static V3d UniformV3dClosedSphere(this IRandomUniform rnd) { double r2; V3d p; do { p = (rnd.UniformV3dClosed() + c_shift) * 2.0; r2 = p.LengthSquared; }while (r2 > 1.0); return(p); }
/// <summary> /// Merge clusters of exactly equal points. The supplied epsilon is used to define a /// grid as acceleration data structure and the algorithm is only fast if not too many /// points fall within the supplied epsilon. /// </summary> public PointEqualClustering(V3d[] pa, double eps, IRandomUniform rnd = null) { rnd = rnd ?? new RandomSystem(); var count = pa.Length; Alloc(count); var ca = m_indexArray; var dict = new IntDict <int>(count, stackDuplicateKeys: true); int rndBits = 0; int bit = 0; for (int i = 0; i < count; i++) { var p = pa[i]; var hc = p.HashCode1(eps); int ci = ca[i]; if (ca[ci] != ci) { do { ci = ca[ci]; } while (ca[ci] != ci); ca[i] = ci; } foreach (var j in dict.ValuesWithKey(hc)) { int cj = ca[j]; if (ca[cj] != cj) { do { cj = ca[cj]; } while (ca[cj] != cj); ca[j] = cj; } if (ci == cj || p != pa[j]) { continue; } bit >>= 1; if (bit == 0) { rndBits = rnd.UniformInt(); bit = 1 << 30; } if ((rndBits & bit) != 0) { ca[ci] = cj; ca[i] = cj; ci = cj; } else { ca[cj] = ci; ca[j] = ci; } } dict[hc] = i; } Init(); }
/// <summary> /// Returns a uniformly distributed double in the open interval /// (0.0, 1.0). Note, that two random values are used to make all 53 /// bits random. /// </summary> public static double UniformDoubleFullOpen(this IRandomUniform rnd) { if (rnd.GeneratesFullDoubles) { return(rnd.UniformDoubleOpen()); } long r; do { r = ((~0xfL & (long)rnd.UniformInt()) << 22) | ((long)rnd.UniformInt() >> 5); }while (r == 0); return(r * (1.0 / 9007199254740992.0)); }
/// <summary> /// Creates an unordered array of subsetCount int indices that /// constitute a subset of all ints in the range [0, count-1]. /// O(subsetCount) for subsetCount << count. /// NOTE: It is assumed that subsetCount is significantly smaller /// than count. If this is not the case, use /// CreateRandomSubsetOfSize instead. /// WARNING: As subsetCount approaches count execution time /// increases significantly. /// </summary> public static int[] CreateSmallRandomSubsetIndexArray( this IRandomUniform rnd, int subsetCount, int count) { Requires.That(subsetCount >= 0 && subsetCount <= count); var subsetIndices = new IntSet(subsetCount); for (int i = 0; i < subsetCount; i++) { int index; do { index = rnd.UniformInt(count); }while (!subsetIndices.TryAdd(index)); } return(subsetIndices.ToArray()); }
/// <summary> /// Creates an unordered array of subsetCount long indices that /// constitute a subset of all longs in the range [0, count-1]. /// O(subsetCount) for subsetCount << count. /// NOTE: It is assumed that subsetCount is significantly smaller /// than count. If this is not the case, use /// CreateRandomSubsetOfSize instead. /// WARNING: As subsetCount approaches count execution time /// increases significantly. /// </summary> public static long[] CreateSmallRandomSubsetIndexArrayLong( this IRandomUniform rnd, long subsetCount, long count) { Requires.That(subsetCount >= 0 && subsetCount <= count); var subsetIndices = new LongSet(subsetCount); for (int i = 0; i < subsetCount; i++) { long index; do { index = rnd.UniformLong(count); }while (!subsetIndices.TryAdd(index)); } return(subsetIndices.ToArray()); }