/// <summary>
        /// Sample from the provided discrete probability distribution.
        /// </summary>
        /// <param name="rng">Random source.</param>
        /// <param name="dist">The discrete distribution to sample from.</param>
        /// <returns>A sample from the discrete distribution.</returns>
        public static int Sample(IRandomSource rng, DiscreteDistribution dist)
        {
            double[] pArr = dist.Probabilities;

            // Obtain a random threshold value by sampling uniformly from interval [0,1).
            double thresh = rng.NextDouble();

            // ENHANCEMENT: Precalc running sum over pArr, and use binary search over pArr if its length is > 10 (or thereabouts).
            // Loop through the discrete probabilities, accumulating as we go and stopping once
            // the accumulator is greater than the random sample.
            double acc = 0.0;

            for (int i = 0; i < pArr.Length; i++)
            {
                acc += pArr[i];
                if (acc > thresh)
                {
                    return(dist.Labels[i]);
                }
            }

            // We might get here through floating point arithmetic rounding issues.
            // e.g. accumulator == throwValue.

            // Find a nearby non-zero probability to select.
            // Wrap around to start of array.
            for (int i = 0; i < pArr.Length; i++)
            {
                if (pArr[i] != 0.0)
                {
                    return(dist.Labels[i]);
                }
            }

            // If we get here then we have an array of zero probabilities.
            throw new InvalidOperationException("Invalid operation. No non-zero probabilities to select.");
        }
 /// <summary>
 /// Fills the provided span with random samples from the discrete distribution.
 /// </summary>
 /// <param name="span">The span to fill with random samples.</param>
 public void Sample(Span <int> span)
 {
     DiscreteDistribution.Sample(_rng, _dist, span);
 }
 /// <summary>
 /// Returns a random sample from the discrete distribution.
 /// </summary>
 /// <returns>A new random sample.</returns>
 public int Sample()
 {
     return(DiscreteDistribution.Sample(_rng, _dist));
 }
 /// <summary>
 /// Construct with the given distribution and a random source.
 /// </summary>
 /// <param name="dist">Discrete distribution.</param>
 /// <param name="rng">Random source.</param>
 public DiscreteDistributionSampler(DiscreteDistribution dist, IRandomSource rng)
 {
     _dist = dist;
     _rng  = rng;
 }
 /// <summary>
 /// Construct with the given distribution and a new random source.
 /// </summary>
 /// <param name="dist">Discrete distribution.</param>
 /// <param name="seed">Random source seed.</param>
 public DiscreteDistributionSampler(DiscreteDistribution dist, ulong seed)
 {
     _dist = dist;
     _rng  = RandomDefaults.CreateRandomSource(seed);
 }
 /// <summary>
 /// Fill an array with samples from a distribution.
 /// </summary>
 /// <param name="buf">The array to fill with samples.</param>
 public void Sample(int[] buf)
 {
     DiscreteDistribution.Sample(_rng, _dist, buf);
 }