private void TestContinuousDistributionShapeMatchesCumulativeDensity(
     ContinuousDistribution distribution,
     double min, double max,
     int numberOfBuckets, int avgSamplesPerBucket,
     double absoluteAccuracy, string message)
 {
     double[] shape = new double[numberOfBuckets];
     double bucketWidth = (max - min) / numberOfBuckets;
     double previous = distribution.CumulativeDistribution(min);
     double underflow = previous;
     double position = min;
     for(int i = 0; i < numberOfBuckets; i++)
     {
         position += bucketWidth;
         double current = distribution.CumulativeDistribution(position);
         shape[i] = current - previous;
         previous = current;
     }
     double overflow = 1 - previous;
     
     TestContinuousDistributionShape(distribution, min, max,
         shape, underflow, overflow,
         avgSamplesPerBucket, absoluteAccuracy, message);
 }
 private void TestContinuousDistributionShape(
     ContinuousDistribution distribution,
     double min, double max,
     double[] expectedShape, double expectedUnderflow, double expectedOverflow,
     int avgSamplesPerBucket, double absoluteAccuracy, string message)
 {
     DistributionShape shape = DistributionShape.CreateMinMax(expectedShape.Length, min, max);
     int sampleCount = expectedShape.Length * avgSamplesPerBucket;
     for(int i = 0; i < sampleCount; i++)
     {
         shape.Push(distribution.NextDouble());
     }
     double scale = 1.0 / (avgSamplesPerBucket * expectedShape.Length);
     Assert.AreEqual(expectedUnderflow, shape.Underflow * scale, absoluteAccuracy, message + " Underflow");
     Assert.AreEqual(expectedOverflow, shape.Overflow * scale, absoluteAccuracy, message + " Overflow");
     for(int i = 0; i < expectedShape.Length; i++)
     {
         Assert.AreEqual(expectedShape[i], shape[i] * scale, absoluteAccuracy, message + " Bucket " + i.ToString());
     }
 }