/*
 * Copyright (C) 2012 The Guava Authors
 *
 * 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.
 */

package com.google.common.math;

import static com.google.common.math.StatsTesting.ALLOWED_ERROR;
import static com.google.common.math.StatsTesting.ALL_MANY_VALUES;
import static com.google.common.math.StatsTesting.INTEGER_MANY_VALUES;
import static com.google.common.math.StatsTesting.INTEGER_MANY_VALUES_COUNT;
import static com.google.common.math.StatsTesting.INTEGER_MANY_VALUES_MAX;
import static com.google.common.math.StatsTesting.INTEGER_MANY_VALUES_MEAN;
import static com.google.common.math.StatsTesting.INTEGER_MANY_VALUES_MIN;
import static com.google.common.math.StatsTesting.INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS;
import static com.google.common.math.StatsTesting.LONG_MANY_VALUES;
import static com.google.common.math.StatsTesting.LONG_MANY_VALUES_COUNT;
import static com.google.common.math.StatsTesting.LONG_MANY_VALUES_MAX;
import static com.google.common.math.StatsTesting.LONG_MANY_VALUES_MEAN;
import static com.google.common.math.StatsTesting.LONG_MANY_VALUES_MIN;
import static com.google.common.math.StatsTesting.LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS;
import static com.google.common.math.StatsTesting.MANY_VALUES;
import static com.google.common.math.StatsTesting.MANY_VALUES_COUNT;
import static com.google.common.math.StatsTesting.MANY_VALUES_MAX;
import static com.google.common.math.StatsTesting.MANY_VALUES_MEAN;
import static com.google.common.math.StatsTesting.MANY_VALUES_MIN;
import static com.google.common.math.StatsTesting.MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS;
import static com.google.common.math.StatsTesting.ONE_VALUE;
import static com.google.common.math.StatsTesting.OTHER_ONE_VALUE;
import static com.google.common.math.StatsTesting.TWO_VALUES;
import static com.google.common.math.StatsTesting.TWO_VALUES_MAX;
import static com.google.common.math.StatsTesting.TWO_VALUES_MEAN;
import static com.google.common.math.StatsTesting.TWO_VALUES_MIN;
import static com.google.common.math.StatsTesting.TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS;
import static com.google.common.truth.Truth.assertThat;
import static java.lang.Math.sqrt;

import com.google.common.collect.ImmutableList;
import com.google.common.math.StatsTesting.ManyValues;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Longs;
import junit.framework.TestCase;

/**
 * Tests for {@link StatsAccumulator}. This tests the stats methods for instances built with {@link
 * StatsAccumulator#add} and {@link StatsAccumulator#addAll}, and various error cases of the {@link
 * StatsAccumulator#add} and {@link StatsAccumulator#addAll} methods. For tests of the {@link
 * StatsAccumulator#snapshot} method which returns {@link Stats} instances, see {@link StatsTest}.
 *
 * @author Pete Gillin
 */
public class StatsAccumulatorTest extends TestCase {

  private StatsAccumulator emptyAccumulator;
  private StatsAccumulator emptyAccumulatorByAddAllEmptyIterable;
  private StatsAccumulator emptyAccumulatorByAddAllEmptyStats;
  private StatsAccumulator oneValueAccumulator;
  private StatsAccumulator oneValueAccumulatorByAddAllEmptyStats;
  private StatsAccumulator twoValuesAccumulator;
  private StatsAccumulator twoValuesAccumulatorByAddAllStats;
  private StatsAccumulator manyValuesAccumulatorByAddAllIterable;
  private StatsAccumulator manyValuesAccumulatorByAddAllIterator;
  private StatsAccumulator manyValuesAccumulatorByAddAllVarargs;
  private StatsAccumulator manyValuesAccumulatorByRepeatedAdd;
  private StatsAccumulator manyValuesAccumulatorByAddAndAddAll;
  private StatsAccumulator manyValuesAccumulatorByAddAllStats;
  private StatsAccumulator integerManyValuesAccumulatorByAddAllIterable;
  private StatsAccumulator longManyValuesAccumulatorByAddAllIterator;
  private StatsAccumulator longManyValuesAccumulatorByAddAllVarargs;

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    emptyAccumulator = new StatsAccumulator();

    emptyAccumulatorByAddAllEmptyIterable = new StatsAccumulator();
    emptyAccumulatorByAddAllEmptyIterable.addAll(ImmutableList.<Double>of());

    emptyAccumulatorByAddAllEmptyStats = new StatsAccumulator();
    emptyAccumulatorByAddAllEmptyStats.addAll(Stats.of());

    oneValueAccumulator = new StatsAccumulator();
    oneValueAccumulator.add(ONE_VALUE);

    oneValueAccumulatorByAddAllEmptyStats = new StatsAccumulator();
    oneValueAccumulatorByAddAllEmptyStats.add(ONE_VALUE);
    oneValueAccumulatorByAddAllEmptyStats.addAll(Stats.of());

    twoValuesAccumulator = new StatsAccumulator();
    twoValuesAccumulator.addAll(TWO_VALUES);

    twoValuesAccumulatorByAddAllStats = new StatsAccumulator();
    twoValuesAccumulatorByAddAllStats.addAll(Stats.of(ONE_VALUE));
    twoValuesAccumulatorByAddAllStats.addAll(Stats.of(OTHER_ONE_VALUE));

    manyValuesAccumulatorByAddAllIterable = new StatsAccumulator();
    manyValuesAccumulatorByAddAllIterable.addAll(MANY_VALUES);

    manyValuesAccumulatorByAddAllIterator = new StatsAccumulator();
    manyValuesAccumulatorByAddAllIterator.addAll(MANY_VALUES.iterator());

    manyValuesAccumulatorByAddAllVarargs = new StatsAccumulator();
    manyValuesAccumulatorByAddAllVarargs.addAll(Doubles.toArray(MANY_VALUES));

    manyValuesAccumulatorByRepeatedAdd = new StatsAccumulator();
    for (double value : MANY_VALUES) {
      manyValuesAccumulatorByRepeatedAdd.add(value);
    }

    manyValuesAccumulatorByAddAndAddAll = new StatsAccumulator();
    manyValuesAccumulatorByAddAndAddAll.add(MANY_VALUES.get(0));
    manyValuesAccumulatorByAddAndAddAll.addAll(MANY_VALUES.subList(1, MANY_VALUES.size()));

    manyValuesAccumulatorByAddAllStats = new StatsAccumulator();
    manyValuesAccumulatorByAddAllStats.addAll(
        Stats.of(MANY_VALUES.subList(0, MANY_VALUES.size() / 2)));
    manyValuesAccumulatorByAddAllStats.addAll(
        Stats.of(MANY_VALUES.subList(MANY_VALUES.size() / 2, MANY_VALUES.size())));

    integerManyValuesAccumulatorByAddAllIterable = new StatsAccumulator();
    integerManyValuesAccumulatorByAddAllIterable.addAll(INTEGER_MANY_VALUES);

    longManyValuesAccumulatorByAddAllIterator = new StatsAccumulator();
    longManyValuesAccumulatorByAddAllIterator.addAll(LONG_MANY_VALUES.iterator());

    longManyValuesAccumulatorByAddAllVarargs = new StatsAccumulator();
    longManyValuesAccumulatorByAddAllVarargs.addAll(Longs.toArray(LONG_MANY_VALUES));
  }

  public void testCount() {
    assertThat(emptyAccumulator.count()).isEqualTo(0);
    assertThat(emptyAccumulatorByAddAllEmptyIterable.count()).isEqualTo(0);
    assertThat(emptyAccumulatorByAddAllEmptyStats.count()).isEqualTo(0);
    assertThat(oneValueAccumulator.count()).isEqualTo(1);
    assertThat(oneValueAccumulatorByAddAllEmptyStats.count()).isEqualTo(1);
    assertThat(twoValuesAccumulator.count()).isEqualTo(2);
    assertThat(twoValuesAccumulatorByAddAllStats.count()).isEqualTo(2);
    assertThat(manyValuesAccumulatorByAddAllIterable.count()).isEqualTo(MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllIterator.count()).isEqualTo(MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllVarargs.count()).isEqualTo(MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByRepeatedAdd.count()).isEqualTo(MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAndAddAll.count()).isEqualTo(MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllStats.count()).isEqualTo(MANY_VALUES_COUNT);
    assertThat(integerManyValuesAccumulatorByAddAllIterable.count())
        .isEqualTo(StatsTesting.INTEGER_MANY_VALUES_COUNT);
    assertThat(longManyValuesAccumulatorByAddAllIterator.count())
        .isEqualTo(StatsTesting.LONG_MANY_VALUES_COUNT);
    assertThat(longManyValuesAccumulatorByAddAllVarargs.count())
        .isEqualTo(StatsTesting.LONG_MANY_VALUES_COUNT);
  }

  public void testCountOverflow_doesNotThrow() {
    StatsAccumulator accumulator = new StatsAccumulator();
    accumulator.add(ONE_VALUE);
    for (int power = 1; power < Long.SIZE - 1; power++) {
      accumulator.addAll(accumulator.snapshot());
    }
    // Should overflow without throwing.
    accumulator.addAll(accumulator.snapshot());
    assertThat(accumulator.count()).isLessThan(0L);
  }

  public void testMean() {
    try {
      emptyAccumulator.mean();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyIterable.mean();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyStats.mean();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    assertThat(oneValueAccumulator.mean()).isWithin(ALLOWED_ERROR).of(ONE_VALUE);
    assertThat(oneValueAccumulatorByAddAllEmptyStats.mean()).isWithin(ALLOWED_ERROR).of(ONE_VALUE);
    assertThat(twoValuesAccumulator.mean()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MEAN);
    assertThat(twoValuesAccumulatorByAddAllStats.mean())
        .isWithin(ALLOWED_ERROR)
        .of(TWO_VALUES_MEAN);
    assertThat(manyValuesAccumulatorByAddAllIterable.mean())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN);
    assertThat(manyValuesAccumulatorByAddAllIterator.mean())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN);
    assertThat(manyValuesAccumulatorByAddAllVarargs.mean())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN);
    assertThat(manyValuesAccumulatorByRepeatedAdd.mean())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN);
    assertThat(manyValuesAccumulatorByAddAndAddAll.mean())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN);
    assertThat(manyValuesAccumulatorByAddAllStats.mean())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN);
    // For datasets of many double values created from an iterable, we test many combinations of
    // finite and non-finite values:
    for (ManyValues values : ALL_MANY_VALUES) {
      StatsAccumulator accumulator = new StatsAccumulator();
      StatsAccumulator accumulatorByAddAllStats = new StatsAccumulator();
      accumulator.addAll(values.asIterable());
      for (double value : values.asIterable()) {
        accumulatorByAddAllStats.addAll(Stats.of(value));
      }
      double mean = accumulator.mean();
      double meanByAddAllStats = accumulatorByAddAllStats.mean();
      if (values.hasAnyNaN()) {
        assertThat(mean).named("mean of " + values).isNaN();
        assertThat(meanByAddAllStats).named("mean by addAll(Stats) of " + values).isNaN();
      } else if (values.hasAnyPositiveInfinity() && values.hasAnyNegativeInfinity()) {
        assertThat(mean).named("mean of " + values).isNaN();
        assertThat(meanByAddAllStats).named("mean by addAll(Stats) of " + values).isNaN();
      } else if (values.hasAnyPositiveInfinity()) {
        assertThat(mean).named("mean of " + values).isPositiveInfinity();
        assertThat(meanByAddAllStats)
            .named("mean by addAll(Stats) of " + values)
            .isPositiveInfinity();
      } else if (values.hasAnyNegativeInfinity()) {
        assertThat(mean).named("mean of " + values).isNegativeInfinity();
        assertThat(meanByAddAllStats)
            .named("mean by addAll(Stats) of " + values)
            .isNegativeInfinity();
      } else {
        assertThat(mean).named("mean of " + values).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MEAN);
        assertThat(meanByAddAllStats)
            .named("mean by addAll(Stats) of " + values)
            .isWithin(ALLOWED_ERROR)
            .of(MANY_VALUES_MEAN);
      }
    }
    assertThat(integerManyValuesAccumulatorByAddAllIterable.mean())
        .isWithin(ALLOWED_ERROR)
        .of(INTEGER_MANY_VALUES_MEAN);
    assertThat(longManyValuesAccumulatorByAddAllIterator.mean())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_MEAN);
    assertThat(longManyValuesAccumulatorByAddAllVarargs.mean())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_MEAN);
  }

  public void testSum() {
    assertThat(emptyAccumulator.sum()).isWithin(0.0).of(0.0);
    assertThat(emptyAccumulatorByAddAllEmptyIterable.sum()).isWithin(0.0).of(0.0);
    assertThat(emptyAccumulatorByAddAllEmptyStats.sum()).isWithin(0.0).of(0.0);
    assertThat(oneValueAccumulator.sum()).isWithin(ALLOWED_ERROR).of(ONE_VALUE);
    assertThat(oneValueAccumulatorByAddAllEmptyStats.sum()).isWithin(ALLOWED_ERROR).of(ONE_VALUE);
    assertThat(twoValuesAccumulator.sum()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MEAN * 2);
    assertThat(twoValuesAccumulatorByAddAllStats.sum())
        .isWithin(ALLOWED_ERROR)
        .of(TWO_VALUES_MEAN * 2);
    assertThat(manyValuesAccumulatorByAddAllIterable.sum())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllIterator.sum())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllVarargs.sum())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByRepeatedAdd.sum())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAndAddAll.sum())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllStats.sum())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT);
    assertThat(integerManyValuesAccumulatorByAddAllIterable.sum())
        .isWithin(ALLOWED_ERROR)
        .of(INTEGER_MANY_VALUES_MEAN * INTEGER_MANY_VALUES_COUNT);
    assertThat(longManyValuesAccumulatorByAddAllIterator.sum())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT);
    assertThat(longManyValuesAccumulatorByAddAllVarargs.sum())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT);
  }

  public void testPopulationVariance() {
    try {
      emptyAccumulator.populationVariance();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyIterable.populationVariance();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyStats.populationVariance();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    assertThat(oneValueAccumulator.populationVariance()).isWithin(0.0).of(0.0);
    assertThat(oneValueAccumulatorByAddAllEmptyStats.populationVariance()).isWithin(0.0).of(0.0);
    assertThat(twoValuesAccumulator.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS / 2);
    assertThat(twoValuesAccumulatorByAddAllStats.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS / 2);
    assertThat(manyValuesAccumulatorByAddAllIterable.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllIterator.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllVarargs.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByRepeatedAdd.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAndAddAll.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT);
    assertThat(manyValuesAccumulatorByAddAllStats.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT);
    // For datasets of many double values created from an iterator, we test many combinations of
    // finite and non-finite values:
    for (ManyValues values : ALL_MANY_VALUES) {
      StatsAccumulator accumulator = new StatsAccumulator();
      StatsAccumulator accumulatorByAddAllStats = new StatsAccumulator();
      accumulator.addAll(values.asIterable().iterator());
      for (double value : values.asIterable()) {
        accumulatorByAddAllStats.addAll(Stats.of(value));
      }
      double populationVariance = accumulator.populationVariance();
      double populationVarianceByAddAllStats = accumulatorByAddAllStats.populationVariance();
      if (values.hasAnyNonFinite()) {
        assertThat(populationVariance).named("population variance of " + values).isNaN();
        assertThat(populationVarianceByAddAllStats)
            .named("population variance by addAll(Stats) of " + values)
            .isNaN();
      } else {
        assertThat(populationVariance)
            .named("population variance of " + values)
            .isWithin(ALLOWED_ERROR)
            .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT);
        assertThat(populationVarianceByAddAllStats)
            .named("population variance by addAll(Stats) of " + values)
            .isWithin(ALLOWED_ERROR)
            .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT);
      }
    }
    assertThat(integerManyValuesAccumulatorByAddAllIterable.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT);
    assertThat(longManyValuesAccumulatorByAddAllIterator.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT);
    assertThat(longManyValuesAccumulatorByAddAllVarargs.populationVariance())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT);
  }

  public void testPopulationStandardDeviation() {
    try {
      emptyAccumulator.populationStandardDeviation();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyIterable.populationStandardDeviation();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyStats.populationStandardDeviation();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    assertThat(oneValueAccumulator.populationStandardDeviation()).isWithin(0.0).of(0.0);
    assertThat(oneValueAccumulatorByAddAllEmptyStats.populationStandardDeviation())
        .isWithin(0.0)
        .of(0.0);
    assertThat(twoValuesAccumulator.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS / 2));
    assertThat(twoValuesAccumulatorByAddAllStats.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS / 2));
    assertThat(manyValuesAccumulatorByAddAllIterable.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT));
    assertThat(manyValuesAccumulatorByAddAllIterator.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT));
    assertThat(manyValuesAccumulatorByAddAllVarargs.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT));
    assertThat(manyValuesAccumulatorByRepeatedAdd.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT));
    assertThat(manyValuesAccumulatorByAddAndAddAll.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT));
    assertThat(manyValuesAccumulatorByAddAllStats.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT));
    assertThat(integerManyValuesAccumulatorByAddAllIterable.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT));
    assertThat(longManyValuesAccumulatorByAddAllIterator.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT));
    assertThat(longManyValuesAccumulatorByAddAllVarargs.populationStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT));
  }

  public void testSampleVariance() {
    try {
      emptyAccumulator.sampleVariance();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyIterable.sampleVariance();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyStats.sampleVariance();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      oneValueAccumulator.sampleVariance();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      oneValueAccumulatorByAddAllEmptyStats.sampleVariance();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    assertThat(twoValuesAccumulator.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS);
    assertThat(twoValuesAccumulatorByAddAllStats.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS);
    assertThat(manyValuesAccumulatorByAddAllIterable.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1));
    assertThat(manyValuesAccumulatorByAddAllIterator.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1));
    assertThat(manyValuesAccumulatorByAddAllVarargs.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1));
    assertThat(manyValuesAccumulatorByRepeatedAdd.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1));
    assertThat(manyValuesAccumulatorByAddAndAddAll.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1));
    assertThat(manyValuesAccumulatorByAddAllStats.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1));
    assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1));
    assertThat(longManyValuesAccumulatorByAddAllIterator.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1));
    assertThat(longManyValuesAccumulatorByAddAllVarargs.sampleVariance())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1));
  }

  public void testSampleStandardDeviation() {
    try {
      emptyAccumulator.sampleStandardDeviation();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyIterable.sampleStandardDeviation();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyStats.sampleStandardDeviation();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      oneValueAccumulator.sampleStandardDeviation();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      oneValueAccumulatorByAddAllEmptyStats.sampleStandardDeviation();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    assertThat(twoValuesAccumulator.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS));
    assertThat(twoValuesAccumulatorByAddAllStats.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS));
    assertThat(manyValuesAccumulatorByAddAllIterable.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)));
    assertThat(manyValuesAccumulatorByAddAllIterator.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)));
    assertThat(manyValuesAccumulatorByAddAllVarargs.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)));
    assertThat(manyValuesAccumulatorByRepeatedAdd.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)));
    assertThat(manyValuesAccumulatorByAddAndAddAll.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)));
    assertThat(manyValuesAccumulatorByAddAllStats.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)));
    assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1)));
    assertThat(longManyValuesAccumulatorByAddAllIterator.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)));
    assertThat(longManyValuesAccumulatorByAddAllVarargs.sampleStandardDeviation())
        .isWithin(ALLOWED_ERROR)
        .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)));
  }

  public void testMax() {
    try {
      emptyAccumulator.max();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyIterable.max();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyStats.max();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    assertThat(oneValueAccumulator.max()).isWithin(ALLOWED_ERROR).of(ONE_VALUE);
    assertThat(oneValueAccumulatorByAddAllEmptyStats.max()).isWithin(ALLOWED_ERROR).of(ONE_VALUE);
    assertThat(twoValuesAccumulator.max()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MAX);
    assertThat(twoValuesAccumulatorByAddAllStats.max()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MAX);
    assertThat(manyValuesAccumulatorByAddAllIterable.max())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MAX);
    assertThat(manyValuesAccumulatorByAddAllIterator.max())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MAX);
    assertThat(manyValuesAccumulatorByAddAllVarargs.max())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MAX);
    assertThat(manyValuesAccumulatorByRepeatedAdd.max())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MAX);
    assertThat(manyValuesAccumulatorByAddAndAddAll.max())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MAX);
    assertThat(manyValuesAccumulatorByAddAllStats.max())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MAX);
    // For datasets of many double values created from an array, we test many combinations of
    // finite and non-finite values:
    for (ManyValues values : ALL_MANY_VALUES) {
      StatsAccumulator accumulator = new StatsAccumulator();
      StatsAccumulator accumulatorByAddAllStats = new StatsAccumulator();
      accumulator.addAll(values.asArray());
      for (double value : values.asIterable()) {
        accumulatorByAddAllStats.addAll(Stats.of(value));
      }
      double max = accumulator.max();
      double maxByAddAllStats = accumulatorByAddAllStats.max();
      if (values.hasAnyNaN()) {
        assertThat(max).named("max of " + values).isNaN();
        assertThat(maxByAddAllStats).named("max by addAll(Stats) of " + values).isNaN();
      } else if (values.hasAnyPositiveInfinity()) {
        assertThat(max).named("max of " + values).isPositiveInfinity();
        assertThat(maxByAddAllStats)
            .named("max by addAll(Stats) of " + values)
            .isPositiveInfinity();
      } else {
        assertThat(max).named("max of " + values).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX);
        assertThat(maxByAddAllStats)
            .named("max by addAll(Stats) of " + values)
            .isWithin(ALLOWED_ERROR)
            .of(MANY_VALUES_MAX);
      }
    }
    assertThat(integerManyValuesAccumulatorByAddAllIterable.max())
        .isWithin(ALLOWED_ERROR)
        .of(INTEGER_MANY_VALUES_MAX);
    assertThat(longManyValuesAccumulatorByAddAllIterator.max())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_MAX);
    assertThat(longManyValuesAccumulatorByAddAllVarargs.max())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_MAX);
  }

  public void testMin() {
    try {
      emptyAccumulator.min();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyIterable.min();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    try {
      emptyAccumulatorByAddAllEmptyStats.min();
      fail("Expected IllegalStateException");
    } catch (IllegalStateException expected) {
    }
    assertThat(oneValueAccumulator.min()).isWithin(ALLOWED_ERROR).of(ONE_VALUE);
    assertThat(oneValueAccumulatorByAddAllEmptyStats.min()).isWithin(ALLOWED_ERROR).of(ONE_VALUE);
    assertThat(twoValuesAccumulator.min()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MIN);
    assertThat(twoValuesAccumulatorByAddAllStats.min()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MIN);
    assertThat(manyValuesAccumulatorByAddAllIterable.min())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MIN);
    assertThat(manyValuesAccumulatorByAddAllIterator.min())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MIN);
    assertThat(manyValuesAccumulatorByAddAllVarargs.min())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MIN);
    assertThat(manyValuesAccumulatorByRepeatedAdd.min())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MIN);
    assertThat(manyValuesAccumulatorByAddAndAddAll.min())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MIN);
    assertThat(manyValuesAccumulatorByAddAllStats.min())
        .isWithin(ALLOWED_ERROR)
        .of(MANY_VALUES_MIN);
    // For datasets of many double values created by adding elements individually, we test many
    // combinations of finite and non-finite values:
    for (ManyValues values : ALL_MANY_VALUES) {
      StatsAccumulator accumulator = new StatsAccumulator();
      StatsAccumulator accumulatorByAddAllStats = new StatsAccumulator();
      for (double value : values.asIterable()) {
        accumulator.add(value);
        accumulatorByAddAllStats.addAll(Stats.of(value));
      }
      double min = accumulator.min();
      double minByAddAllStats = accumulatorByAddAllStats.min();
      if (values.hasAnyNaN()) {
        assertThat(min).named("min of " + values).isNaN();
        assertThat(minByAddAllStats).named("min by addAll(Stats) of " + values).isNaN();
      } else if (values.hasAnyNegativeInfinity()) {
        assertThat(min).named("min of " + values).isNegativeInfinity();
        assertThat(minByAddAllStats)
            .named("min by addAll(Stats) of " + values)
            .isNegativeInfinity();
      } else {
        assertThat(min).named("min of " + values).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN);
        assertThat(minByAddAllStats)
            .named("min by addAll(Stats) of " + values)
            .isWithin(ALLOWED_ERROR)
            .of(MANY_VALUES_MIN);
      }
    }
    assertThat(integerManyValuesAccumulatorByAddAllIterable.min())
        .isWithin(ALLOWED_ERROR)
        .of(INTEGER_MANY_VALUES_MIN);
    assertThat(longManyValuesAccumulatorByAddAllIterator.min())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_MIN);
    assertThat(longManyValuesAccumulatorByAddAllVarargs.min())
        .isWithin(ALLOWED_ERROR)
        .of(LONG_MANY_VALUES_MIN);
  }
}
