public static Sampler
	triangular(final double a, final double c, final double b) {
		if (!Double.isFinite(a) || !Double.isFinite(b) || !Double.isFinite(c) ||
			a < 0 || b < 0 || c < 0  ||
			a > 1 || b > 1 || c > 1 ||
			b <= a || c > b || c < a)
		{
			throw new IllegalArgumentException(
				"Invalid triangular: [a=%f, c=%f, b=%f].".formatted(a, c, b)
			);
		}

		final double fc = (c - a)/(b - a);

		return (random, range) -> {
			final var r = random.nextDouble();

			final double sample;
			if (Double.compare(r, 0.0) == 0) {
				sample = 0;
			} else if (r < fc) {
				sample = a + sqrt(r*(b - a)*(c - a));
			} else {
				sample = b - sqrt((1 - r)*(b - a)*(b - c));
			}

			return stretch(sample, range);
		};
	}
Create a new sampler for a triangle distribution with the given
parameters. All parameters must be within the <em>normalized</em> range
{@code [0, 1]}. The sample value, returned by the
{@link Sampler#sample(RandomGenerator, DoubleRange)} method, is then
<em>stretched</em> to the desired range.
<p>
	<img src="doc-files/TriangularDistributionPDF.svg" width="450"
	     alt="Triangle distribution sampler" >

@see #triangular(double)

@param a the <em>normalized</em> start point of the triangle
@param c the <em>normalized</em> middle point of the triangle
@param b the <em>normalized</em> end point of the triangle
@return a new triangle distribution sampler
@throws IllegalArgumentException if one of the parameters is not within
        the range {@code [0, 1]} or {@code b <= a || c > b || c < a}
jenetics/src/main/java/io/jenetics/stat/Samplers.java