| /* |
| * 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())); |
| } |
| } |
| } |