public Sampler createSampler()

in commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/TruncatedNormalDistribution.java [237:280]


    public Sampler createSampler(UniformRandomProvider rng) {
        // If the truncation covers a reasonable amount of the normal distribution
        // then a rejection sampler can be used.
        double threshold = REJECTION_THRESHOLD;
        // If the truncation is entirely in the upper or lower half then adjust the
        // threshold as twice the samples can be used
        if (lower >= 0 || upper <= 0) {
            threshold *= 0.5;
        }

        if (cdfDelta > threshold) {
            // Create the rejection sampler
            final ZigguratSampler.NormalizedGaussian sampler = ZigguratSampler.NormalizedGaussian.of(rng);
            final DoubleSupplier gen;
            // Use mirroring if possible
            if (lower >= 0) {
                // Return the upper-half of the Gaussian
                gen = () -> Math.abs(sampler.sample());
            } else if (upper <= 0) {
                // Return the lower-half of the Gaussian
                gen = () -> -Math.abs(sampler.sample());
            } else {
                // Return the full range of the Gaussian
                gen = sampler::sample;
            }
            // Map the bounds to a standard normal distribution
            final double u = parentNormal.getMean();
            final double s = parentNormal.getStandardDeviation();
            final double a = (lower - u) / s;
            final double b = (upper - u) / s;
            // Sample in [a, b] using rejection
            return () -> {
                double x = gen.getAsDouble();
                while (x < a || x > b) {
                    x = gen.getAsDouble();
                }
                // Avoid floating-point error when mapping back
                return clipToRange(u + x * s);
            };
        }

        // Default to an inverse CDF sampler
        return super.createSampler(rng);
    }