public static EmpiricalDistribution of(
		final Partition partition,
		final double[] expected
	) {
		if (partition.size() != expected.length) {
			throw new IllegalArgumentException(
				"Different partition and expected values size: %s != %s"
					.formatted(partition.size(), expected.length)
			);
		}
		for (var value : expected) {
			if (!Double.isFinite(value)) {
				throw new IllegalArgumentException(
					"Expected values must be finite: %s."
						.formatted(Arrays.toString(expected)));
			}
			if (value < 0) {
				throw new IllegalArgumentException(
					"Expected values must be non-negative: %s."
						.formatted(Arrays.toString(expected)));
			}
		}

		final var sum = DoubleAdder.sum(expected);
		final var normalized = expected.clone();
		for (int i = 0; i < normalized.length; ++i) {
			normalized[i] /= sum;
		}

		final var frequencies = Arrays.stream(normalized)
			.mapToLong(v -> (long)(v*Integer.MAX_VALUE))
			.toArray();
		final var histogram = new Histogram(new Buckets(partition, frequencies));

		return new EmpiricalDistribution(histogram);
	}
Create a new <em>observed</em> distribution object for the given
{@code partition} and the {@code expected} frequencies.

@param partition the partition of the observation
@param expected the observed frequencies
@return a newly created distribution object
@throws IllegalArgumentException if {@code partition.size() != expected.length}
        or the frequencies are not {@link Double#isInfinite(double)} or
        smaller than zero
jenetics.incubator/src/main/java/io/jenetics/incubator/stat/EmpiricalDistribution.java