/*
 * Copyright 2016 Google Inc.
 *
 * 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.gwt.emultest.java8.util;

import com.google.gwt.emultest.java.util.EmulTestBase;

import static java.lang.Double.MAX_VALUE;
import static java.lang.Double.MIN_VALUE;
import static java.lang.Double.NEGATIVE_INFINITY;
import static java.lang.Double.NaN;
import static java.lang.Double.POSITIVE_INFINITY;

import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.List;

/**
 * Tests {@link DoubleSummaryStatistics}.
 */
public class DoubleSummaryStatisticsTest extends EmulTestBase {

  private DoubleSummaryStatistics stats;

  @Override
  protected void gwtSetUp() throws Exception {
    stats = new DoubleSummaryStatistics();
  }

  public void testAverageAndSumWithCompensation() throws Exception {
    assertEquals(0d, stats.getAverage());
    assertEquals(0d, stats.getSum());

    double initial = 1.0d;
    long count = 100000;

    // 'precision' is the hardcoded result of Math.ulp(initial) in JVM,
    // since GWT does not emulate Math.ulp().
    // This value represents the distance from 'initial' (1.0d) to the
    // previous/next double. If we add half or less of that distance/precision
    // to 'initial' then the result will be truncated to 'initial' again due to
    // floating point arithmetic rounding.
    // With Kahan summation such rounding errors are detected and compensated
    // so the summation result should (nearly) equal the expected sum.
    double precision = 2.220446049250313E-16;
    double value = precision / 2;
    double expectedSum = initial + (count * value);
    long expectedCount = count + 1;
    double expectedAverage = expectedSum / expectedCount;

    stats.accept(initial);
    for (int i = 0; i < count; ++i) {
      stats.accept(value);
    }

    // TODO (jnehlmeier): While delta = 0 works we probably want to allow some error?
    // Or maybe use ulp differences instead of a delta?
    assertEquals(expectedAverage, stats.getAverage(), 0);
    assertEquals(expectedSum, stats.getSum(), 0);
  }

  public void testCombine() throws Exception {
    stats.accept(1.0d);
    stats.accept(2.0d);

    DoubleSummaryStatistics otherStats = new DoubleSummaryStatistics();
    otherStats.accept(3.0d);
    otherStats.accept(4.0d);

    stats.combine(otherStats);

    assertEquals(2.5d, stats.getAverage());
    assertEquals(1d, stats.getMin());
    assertEquals(4d, stats.getMax());
    assertEquals(10d, stats.getSum());
    assertEquals(4, stats.getCount());
  }

  public void testCountMaxMin() {
    assertEquals(0, stats.getCount());
    assertEquals(NEGATIVE_INFINITY, stats.getMax());
    assertEquals(POSITIVE_INFINITY, stats.getMin());

    double[][] testData = {
        //          aDouble,               max,               min
        {               1.0,               1.0,               1.0 },
        {              -1.0,               1.0,              -1.0 },
        {               2.5,               2.5,              -1.0 },
        {              -2.5,               2.5,              -2.5 },
        {         MAX_VALUE,         MAX_VALUE,              -2.5 },
        {         MIN_VALUE,         MAX_VALUE,              -2.5 },
        { POSITIVE_INFINITY, POSITIVE_INFINITY,              -2.5 },
        { NEGATIVE_INFINITY, POSITIVE_INFINITY, NEGATIVE_INFINITY },
    };

    for (int i = 0; i < testData.length; ++i) {
      long expectedCount = i + 1;
      double aDouble = testData[i][0];
      double expectedMax = testData[i][1];
      double expectedMin = testData[i][2];

      stats.accept(aDouble);

      assertEquals(expectedCount, stats.getCount());
      assertEquals(expectedMax, stats.getMax());
      assertEquals(expectedMin, stats.getMin());
    }
  }

  public void testInfinity() {
    stats.accept(NEGATIVE_INFINITY);
    stats.accept(NEGATIVE_INFINITY);
    assertEquals(NEGATIVE_INFINITY, stats.getAverage());
    assertEquals(NEGATIVE_INFINITY, stats.getMax());
    assertEquals(NEGATIVE_INFINITY, stats.getMin());
    assertEquals(NEGATIVE_INFINITY, stats.getSum());

    stats.accept(POSITIVE_INFINITY);
    assertTrue(Double.isNaN(stats.getAverage()));
    assertEquals(POSITIVE_INFINITY, stats.getMax());
    assertEquals(NEGATIVE_INFINITY, stats.getMin());
    assertTrue(Double.isNaN(stats.getSum()));

    stats = new DoubleSummaryStatistics();
    stats.accept(POSITIVE_INFINITY);
    stats.accept(POSITIVE_INFINITY);
    assertEquals(POSITIVE_INFINITY, stats.getAverage());
    assertEquals(POSITIVE_INFINITY, stats.getMax());
    assertEquals(POSITIVE_INFINITY, stats.getMin());
    assertEquals(POSITIVE_INFINITY, stats.getSum());

    stats.accept(NEGATIVE_INFINITY);
    assertTrue(Double.isNaN(stats.getAverage()));
    assertEquals(POSITIVE_INFINITY, stats.getMax());
    assertEquals(NEGATIVE_INFINITY, stats.getMin());
    assertTrue(Double.isNaN(stats.getSum()));
  }

  public void testNaN() {
    List<Double> testData = Arrays.asList(
        NaN, -1.5d, 2.5d, MAX_VALUE, MIN_VALUE, NaN,
        NEGATIVE_INFINITY, POSITIVE_INFINITY);

    stats.accept(5.0d);
    for (Double aDouble : testData) {
      stats.accept(aDouble);
      assertTrue(Double.isNaN(stats.getAverage()));
      assertTrue(Double.isNaN(stats.getMax()));
      assertTrue(Double.isNaN(stats.getMin()));
      assertTrue(Double.isNaN(stats.getSum()));
    }
  }
}
