/*
 * Java Genetic Algorithm Library (@__identifier__@).
 * Copyright (c) @__year__@ Franz Wilhelmstötter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author:
 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
 */
package org.jenetics.tool.trial;

import static java.lang.String.format;

import java.util.function.Consumer;
import java.util.stream.Collector;

import org.jenetics.internal.util.require;

import org.jenetics.stat.DoubleMomentStatistics;
import org.jenetics.util.ISeq;
import org.jenetics.util.MSeq;

/**
 * A state object for collecting statistics such as count, min, max, sum, mean,
 * variance, skewness and kurtosis. The design of this class is similar to the
 * {@link java.util.DoubleSummaryStatistics} class.
 * <p>
 * <pre>{@code
 * final Stream<Sample> stream = ...
 * final SampleSummaryStatistics statistics = stream.collect(
 *         () -> new SampleSummaryStatistics(parameterCount),
 *         SampleSummaryStatistics::accept,
 *         SampleSummaryStatistics::combine
 *     );
 * }</pre>
 *
 * <p>
 * <b>Implementation note:</b>
 * <i>This implementation is not thread safe. However, it is safe to use
 * {@link #toSampleStatistics(int)}  on a parallel stream,
 * because the parallel implementation of
 * {@link java.util.stream.Stream#collect Stream.collect()}
 * provides the necessary partitioning, isolation, and merging of results for
 * safe and efficient parallel execution.</i>
 *
 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz  Wilhelmstötter</a>
 * @version 3.4
 * @since 3.4
 */
public class SampleSummaryStatistics implements Consumer<Sample> {

	private final int _parameterCount;
	private final ISeq<DoubleMomentStatistics> _moments;
	private final ISeq<ExactQuantile> _quantiles;

	/**
	 * Create a new statistics object with the given expected parameter count of
	 * the accepted samples.
	 *
	 * @param parameterCount the parameter count or sample size, respectively
	 * @throws IllegalArgumentException if the given {@code parameterCount}
	 *         is smaller then one
	 */
	public SampleSummaryStatistics(final int parameterCount) {
		_parameterCount = require.positive(parameterCount);
		_moments = MSeq.of(DoubleMomentStatistics::new, parameterCount).toISeq();
		_quantiles = MSeq.of(ExactQuantile::new, parameterCount).toISeq();
	}

	@Override
	public void accept(final Sample sample) {
		if (sample.size() != _parameterCount) {
			throw new IllegalArgumentException(format(
				"Expected sample size of %d, but got %d.",
				_moments.size(), sample.size()
			));
		}

		for (int i = 0; i < _parameterCount; ++i) {
			_moments.get(i).accept(sample.get(i));
			_quantiles.get(i).accept(sample.get(i));
		}
	}

	/**
	 * Combine two {@code SampleSummaryStatistics} statistic objects.
	 *
	 * @param other the other {@code SampleSummaryStatistics} statistics to
	 *        combine with {@code this} one.
	 * @return {@code this} statistics object
	 * @throws IllegalArgumentException if the {@code parameterCount} of the
	 *         {@code other} statistics object is different to {@code this} one
	 * @throws NullPointerException if the other statistical summary is
	 *         {@code null}.
	 */
	public SampleSummaryStatistics combine(final SampleSummaryStatistics other) {
		if (other._parameterCount != _parameterCount) {
			throw new IllegalArgumentException(format(
				"Expected sample size of %d, but got %d.",
				_parameterCount, other._parameterCount
			));
		}

		for (int i = 0; i < _parameterCount; ++i) {
			_moments.get(i).combine(other._moments.get(i));
			_quantiles.get(i).combine(other._quantiles.get(i));
		}

		return this;
	}

	/**
	 * Return the <i>raw</i> {@code DoubleMomentStatistics} objects.
	 *
	 * @return the <i>raw</i> {@code DoubleMomentStatistics} objects
	 */
	public ISeq<DoubleMomentStatistics> getMoments() {
		return _moments;
	}

	/**
	 * Return the quantile object.
	 *
	 * @return the quantile object
	 */
	public ISeq<ExactQuantile> getQuantiles() {
		return _quantiles;
	}

	/**
	 * Return a {@code Collector} which applies an double-producing mapping
	 * function to each input element, and returns moments-statistics for the
	 * resulting values.
	 *
	 * <pre>{@code
	 * final Stream<Sample> stream = ...
	 * final SampleSummaryStatistics statistics = stream
	 *     .collect(toDoubleMomentStatistics(parameterCount));
	 * }</pre>
	 *
	 * @param parameterCount the number of parameter of the accumulated
	 *        {@code Sample} objects
	 * @return a {@code Collector} implementing the sample reduction
	 * @throws IllegalArgumentException if the given {@code parameterCount}
	 *         is smaller then one
	 */
	public static Collector<Sample, ?, SampleSummaryStatistics>
	toSampleStatistics(final int parameterCount) {
		require.positive(parameterCount);

		return Collector.of(
			() -> new SampleSummaryStatistics(parameterCount),
			SampleSummaryStatistics::accept,
			SampleSummaryStatistics::combine
		);
	}

}

@@ -1253,20 +1253,16 @@
 lass.%0A *
- %3Cp%3E
 %0A * %3Cpre

Fix Javadoc.