From e2f4eba6369abc8f1e5790304d8374807ada8027 Mon Sep 17 00:00:00 2001 From: peteg Date: Wed, 16 Oct 2019 03:35:45 -0700 Subject: [PATCH] Add Stream support to Stats and StatsAccumulator. This adds: - A static method Stats.toStats() that returns a Collector. - Stats.of overloads and StatsAccumulator.addAll overloads that take DoubleStream, IntStream, and LongStream. - A StatsAccumulator.addAll overload that takes StatsAccumulator. (In passing, this also improves the tests in a couple of ways. It removes the use of static initializer blocks in StatsTesting, which is contrary to best practice. And it fixes some tolerances on the assertions: the min() and max() ones should use exact equality, and the ones with INTEGER_MANY_VALUES and LONG_MANY_VALUES should scale up the tolerance to match the order of magnitude of the values. This latter change fixes the ErrorProne warnings that, in some cases, the tolerance was actually less than the difference between the expected value and the next nearest double. It just happened that everything was close enough before.) RELNOTES=Add Stream support to Stats and StatsAccumulator. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=274998178 --- .../common/math/StatsAccumulatorTest.java | 166 +++++++------- .../com/google/common/math/StatsTest.java | 114 +++++----- .../com/google/common/math/StatsTesting.java | 38 ++-- .../src/com/google/common/math/Stats.java | 3 +- .../google/common/math/StatsAccumulator.java | 48 ++-- .../common/math/StatsAccumulatorTest.java | 212 +++++++++++------- .../com/google/common/math/StatsTest.java | 177 +++++++++------ .../com/google/common/math/StatsTesting.java | 67 ++++-- guava/src/com/google/common/math/Stats.java | 79 ++++++- .../google/common/math/StatsAccumulator.java | 82 +++++-- 10 files changed, 624 insertions(+), 362 deletions(-) diff --git a/android/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java b/android/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java index bb26a6ff1e21..6926a69c6cf3 100644 --- a/android/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java +++ b/android/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java @@ -76,6 +76,7 @@ public class StatsAccumulatorTest extends TestCase { private StatsAccumulator manyValuesAccumulatorByRepeatedAdd; private StatsAccumulator manyValuesAccumulatorByAddAndAddAll; private StatsAccumulator manyValuesAccumulatorByAddAllStats; + private StatsAccumulator manyValuesAccumulatorByAddAllStatsAccumulator; private StatsAccumulator integerManyValuesAccumulatorByAddAllIterable; private StatsAccumulator longManyValuesAccumulatorByAddAllIterator; private StatsAccumulator longManyValuesAccumulatorByAddAllVarargs; @@ -130,6 +131,12 @@ protected void setUp() throws Exception { manyValuesAccumulatorByAddAllStats.addAll( Stats.of(MANY_VALUES.subList(MANY_VALUES.size() / 2, MANY_VALUES.size()))); + manyValuesAccumulatorByAddAllStatsAccumulator = new StatsAccumulator(); + manyValuesAccumulatorByAddAllStatsAccumulator.addAll( + statsAccumulatorOf(MANY_VALUES.subList(0, MANY_VALUES.size() / 2))); + manyValuesAccumulatorByAddAllStatsAccumulator.addAll( + statsAccumulatorOf(MANY_VALUES.subList(MANY_VALUES.size() / 2, MANY_VALUES.size()))); + integerManyValuesAccumulatorByAddAllIterable = new StatsAccumulator(); integerManyValuesAccumulatorByAddAllIterable.addAll(INTEGER_MANY_VALUES); @@ -140,6 +147,12 @@ protected void setUp() throws Exception { longManyValuesAccumulatorByAddAllVarargs.addAll(Longs.toArray(LONG_MANY_VALUES)); } + private static StatsAccumulator statsAccumulatorOf(Iterable values) { + StatsAccumulator accumulator = new StatsAccumulator(); + accumulator.addAll(values); + return accumulator; + } + public void testCount() { assertThat(emptyAccumulator.count()).isEqualTo(0); assertThat(emptyAccumulatorByAddAllEmptyIterable.count()).isEqualTo(0); @@ -154,6 +167,7 @@ public void testCount() { assertThat(manyValuesAccumulatorByRepeatedAdd.count()).isEqualTo(MANY_VALUES_COUNT); assertThat(manyValuesAccumulatorByAddAndAddAll.count()).isEqualTo(MANY_VALUES_COUNT); assertThat(manyValuesAccumulatorByAddAllStats.count()).isEqualTo(MANY_VALUES_COUNT); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.count()).isEqualTo(MANY_VALUES_COUNT); assertThat(integerManyValuesAccumulatorByAddAllIterable.count()) .isEqualTo(StatsTesting.INTEGER_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllIterator.count()) @@ -213,6 +227,9 @@ public void testMean() { assertThat(manyValuesAccumulatorByAddAllStats.mean()) .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_MEAN); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.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) { @@ -252,13 +269,13 @@ public void testMean() { } } assertThat(integerManyValuesAccumulatorByAddAllIterable.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); assertThat(longManyValuesAccumulatorByAddAllIterator.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); assertThat(longManyValuesAccumulatorByAddAllVarargs.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); } @@ -290,14 +307,17 @@ public void testSum() { assertThat(manyValuesAccumulatorByAddAllStats.sum()) .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT); - assertThat(integerManyValuesAccumulatorByAddAllIterable.sum()) + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.sum()) .isWithin(ALLOWED_ERROR) + .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT); + assertThat(integerManyValuesAccumulatorByAddAllIterable.sum()) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN * INTEGER_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllIterator.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllVarargs.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT); } @@ -343,6 +363,9 @@ public void testPopulationVariance() { assertThat(manyValuesAccumulatorByAddAllStats.populationVariance()) .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.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) { @@ -371,13 +394,13 @@ public void testPopulationVariance() { } } assertThat(integerManyValuesAccumulatorByAddAllIterable.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllIterator.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllVarargs.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT); } @@ -425,14 +448,17 @@ public void testPopulationStandardDeviation() { assertThat(manyValuesAccumulatorByAddAllStats.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); - assertThat(integerManyValuesAccumulatorByAddAllIterable.populationStandardDeviation()) + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) + .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); + assertThat(integerManyValuesAccumulatorByAddAllIterable.populationStandardDeviation()) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT)); assertThat(longManyValuesAccumulatorByAddAllIterator.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT)); assertThat(longManyValuesAccumulatorByAddAllVarargs.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT)); } @@ -486,14 +512,17 @@ public void testSampleVariance() { assertThat(manyValuesAccumulatorByAddAllStats.sampleVariance()) .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)); - assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleVariance()) + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.sampleVariance()) .isWithin(ALLOWED_ERROR) + .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)); + assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleVariance()) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1)); assertThat(longManyValuesAccumulatorByAddAllIterator.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)); assertThat(longManyValuesAccumulatorByAddAllVarargs.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)); } @@ -547,14 +576,17 @@ public void testSampleStandardDeviation() { assertThat(manyValuesAccumulatorByAddAllStats.sampleStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1))); - assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleStandardDeviation()) + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.sampleStandardDeviation()) .isWithin(ALLOWED_ERROR) + .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1))); + assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleStandardDeviation()) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1))); assertThat(longManyValuesAccumulatorByAddAllIterator.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1))); assertThat(longManyValuesAccumulatorByAddAllVarargs.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1))); } @@ -574,28 +606,17 @@ public void testMax() { 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); + assertThat(oneValueAccumulator.max()).isEqualTo(ONE_VALUE); + assertThat(oneValueAccumulatorByAddAllEmptyStats.max()).isEqualTo(ONE_VALUE); + assertThat(twoValuesAccumulator.max()).isEqualTo(TWO_VALUES_MAX); + assertThat(twoValuesAccumulatorByAddAllStats.max()).isEqualTo(TWO_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllIterable.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllIterator.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllVarargs.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByRepeatedAdd.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAndAddAll.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllStats.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.max()).isEqualTo(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) { @@ -616,22 +637,16 @@ public void testMax() { .that(maxByAddAllStats) .isPositiveInfinity(); } else { - assertWithMessage("max of " + values).that(max).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); + assertWithMessage("max of " + values).that(max).isEqualTo(MANY_VALUES_MAX); assertWithMessage("max by addAll(Stats) of " + values) .that(maxByAddAllStats) - .isWithin(ALLOWED_ERROR) - .of(MANY_VALUES_MAX); + .isEqualTo(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); + .isEqualTo(INTEGER_MANY_VALUES_MAX); + assertThat(longManyValuesAccumulatorByAddAllIterator.max()).isEqualTo(LONG_MANY_VALUES_MAX); + assertThat(longManyValuesAccumulatorByAddAllVarargs.max()).isEqualTo(LONG_MANY_VALUES_MAX); } public void testMin() { @@ -650,28 +665,17 @@ public void testMin() { 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); + assertThat(oneValueAccumulator.min()).isEqualTo(ONE_VALUE); + assertThat(oneValueAccumulatorByAddAllEmptyStats.min()).isEqualTo(ONE_VALUE); + assertThat(twoValuesAccumulator.min()).isEqualTo(TWO_VALUES_MIN); + assertThat(twoValuesAccumulatorByAddAllStats.min()).isEqualTo(TWO_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllIterable.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllIterator.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllVarargs.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByRepeatedAdd.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAndAddAll.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllStats.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.min()).isEqualTo(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) { @@ -692,21 +696,15 @@ public void testMin() { .that(minByAddAllStats) .isNegativeInfinity(); } else { - assertWithMessage("min of " + values).that(min).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); + assertWithMessage("min of " + values).that(min).isEqualTo(MANY_VALUES_MIN); assertWithMessage("min by addAll(Stats) of " + values) .that(minByAddAllStats) - .isWithin(ALLOWED_ERROR) - .of(MANY_VALUES_MIN); + .isEqualTo(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); + .isEqualTo(INTEGER_MANY_VALUES_MIN); + assertThat(longManyValuesAccumulatorByAddAllIterator.min()).isEqualTo(LONG_MANY_VALUES_MIN); + assertThat(longManyValuesAccumulatorByAddAllVarargs.min()).isEqualTo(LONG_MANY_VALUES_MIN); } } diff --git a/android/guava-tests/test/com/google/common/math/StatsTest.java b/android/guava-tests/test/com/google/common/math/StatsTest.java index 4de67c927576..76de5b55c739 100644 --- a/android/guava-tests/test/com/google/common/math/StatsTest.java +++ b/android/guava-tests/test/com/google/common/math/StatsTest.java @@ -145,19 +145,19 @@ public void testMean() { .isWithin(ALLOWED_ERROR * Double.MAX_VALUE) .of(LARGE_VALUES_MEAN); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); assertThat(LARGE_INTEGER_VALUES_STATS.mean()) .isWithin(ALLOWED_ERROR * Integer.MAX_VALUE) .of(LARGE_INTEGER_VALUES_MEAN); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); assertThat(LARGE_LONG_VALUES_STATS.mean()) .isWithin(ALLOWED_ERROR * Long.MAX_VALUE) @@ -182,16 +182,16 @@ public void testSum() { .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN * INTEGER_MANY_VALUES_COUNT); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN * INTEGER_MANY_VALUES_COUNT); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT); } @@ -236,19 +236,19 @@ public void testPopulationVariance() { .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT); assertThat(LARGE_INTEGER_VALUES_STATS.populationVariance()) .isWithin(ALLOWED_ERROR * Integer.MAX_VALUE * Integer.MAX_VALUE) .of(LARGE_INTEGER_VALUES_POPULATION_VARIANCE); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT); assertThat(LARGE_LONG_VALUES_STATS.populationVariance()) .isWithin(ALLOWED_ERROR * Long.MAX_VALUE * Long.MAX_VALUE) @@ -283,16 +283,16 @@ public void testPopulationStandardDeviation() { .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT)); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT)); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT)); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT)); } @@ -328,16 +328,16 @@ public void testSampleVariance() { .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1)); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1)); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)); } @@ -373,16 +373,16 @@ public void testSampleStandardDeviation() { .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1))); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1))); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1))); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1))); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1))); } @@ -397,13 +397,13 @@ public void testMax() { fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { } - assertThat(ONE_VALUE_STATS.max()).isWithin(ALLOWED_ERROR).of(ONE_VALUE); + assertThat(ONE_VALUE_STATS.max()).isEqualTo(ONE_VALUE); assertThat(Stats.of(POSITIVE_INFINITY).max()).isPositiveInfinity(); assertThat(Stats.of(NEGATIVE_INFINITY).max()).isNegativeInfinity(); assertThat(Stats.of(NaN).max()).isNaN(); - assertThat(TWO_VALUES_STATS.max()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MAX); - assertThat(MANY_VALUES_STATS_VARARGS.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); - assertThat(MANY_VALUES_STATS_ITERABLE.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); + assertThat(TWO_VALUES_STATS.max()).isEqualTo(TWO_VALUES_MAX); + assertThat(MANY_VALUES_STATS_VARARGS.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(MANY_VALUES_STATS_ITERABLE.max()).isEqualTo(MANY_VALUES_MAX); // 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) { @@ -413,22 +413,14 @@ public void testMax() { } else if (values.hasAnyPositiveInfinity()) { assertWithMessage("max of " + values).that(max).isPositiveInfinity(); } else { - assertWithMessage("max of " + values).that(max).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); + assertWithMessage("max of " + values).that(max).isEqualTo(MANY_VALUES_MAX); } } - assertThat(MANY_VALUES_STATS_SNAPSHOT.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); - assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.max()) - .isWithin(ALLOWED_ERROR) - .of(INTEGER_MANY_VALUES_MAX); - assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.max()) - .isWithin(ALLOWED_ERROR) - .of(INTEGER_MANY_VALUES_MAX); - assertThat(LONG_MANY_VALUES_STATS_ITERATOR.max()) - .isWithin(ALLOWED_ERROR) - .of(LONG_MANY_VALUES_MAX); - assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.max()) - .isWithin(ALLOWED_ERROR) - .of(LONG_MANY_VALUES_MAX); + assertThat(MANY_VALUES_STATS_SNAPSHOT.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.max()).isEqualTo(INTEGER_MANY_VALUES_MAX); + assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.max()).isEqualTo(INTEGER_MANY_VALUES_MAX); + assertThat(LONG_MANY_VALUES_STATS_ITERATOR.max()).isEqualTo(LONG_MANY_VALUES_MAX); + assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.max()).isEqualTo(LONG_MANY_VALUES_MAX); } public void testMin() { @@ -442,14 +434,14 @@ public void testMin() { fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { } - assertThat(ONE_VALUE_STATS.min()).isWithin(ALLOWED_ERROR).of(ONE_VALUE); + assertThat(ONE_VALUE_STATS.min()).isEqualTo(ONE_VALUE); assertThat(Stats.of(POSITIVE_INFINITY).min()).isPositiveInfinity(); assertThat(Stats.of(NEGATIVE_INFINITY).min()).isNegativeInfinity(); assertThat(Stats.of(NaN).min()).isNaN(); - assertThat(TWO_VALUES_STATS.min()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MIN); - assertThat(MANY_VALUES_STATS_VARARGS.min()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); - assertThat(MANY_VALUES_STATS_ITERABLE.min()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); - assertThat(MANY_VALUES_STATS_ITERATOR.min()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); + assertThat(TWO_VALUES_STATS.min()).isEqualTo(TWO_VALUES_MIN); + assertThat(MANY_VALUES_STATS_VARARGS.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(MANY_VALUES_STATS_ITERABLE.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(MANY_VALUES_STATS_ITERATOR.min()).isEqualTo(MANY_VALUES_MIN); // For datasets of many double values created from an accumulator snapshot, we test many // combinations of finite and non-finite values: for (ManyValues values : ALL_MANY_VALUES) { @@ -461,21 +453,13 @@ public void testMin() { } else if (values.hasAnyNegativeInfinity()) { assertWithMessage("min of " + values).that(min).isNegativeInfinity(); } else { - assertWithMessage("min of " + values).that(min).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); + assertWithMessage("min of " + values).that(min).isEqualTo(MANY_VALUES_MIN); } } - assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.min()) - .isWithin(ALLOWED_ERROR) - .of(INTEGER_MANY_VALUES_MIN); - assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.min()) - .isWithin(ALLOWED_ERROR) - .of(INTEGER_MANY_VALUES_MIN); - assertThat(LONG_MANY_VALUES_STATS_ITERATOR.min()) - .isWithin(ALLOWED_ERROR) - .of(LONG_MANY_VALUES_MIN); - assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.min()) - .isWithin(ALLOWED_ERROR) - .of(LONG_MANY_VALUES_MIN); + assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.min()).isEqualTo(INTEGER_MANY_VALUES_MIN); + assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.min()).isEqualTo(INTEGER_MANY_VALUES_MIN); + assertThat(LONG_MANY_VALUES_STATS_ITERATOR.min()).isEqualTo(LONG_MANY_VALUES_MIN); + assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.min()).isEqualTo(LONG_MANY_VALUES_MIN); } public void testEqualsAndHashCode() { @@ -558,14 +542,16 @@ public void testMeanOf() { assertThat(Stats.meanOf(MANY_VALUES)).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MEAN); assertThat(Stats.meanOf(MANY_VALUES.iterator())).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MEAN); assertThat(Stats.meanOf(INTEGER_MANY_VALUES)) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); assertThat(Stats.meanOf(Ints.toArray(INTEGER_MANY_VALUES))) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); - assertThat(Stats.meanOf(LONG_MANY_VALUES)).isWithin(ALLOWED_ERROR).of(LONG_MANY_VALUES_MEAN); + assertThat(Stats.meanOf(LONG_MANY_VALUES)) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) + .of(LONG_MANY_VALUES_MEAN); assertThat(Stats.meanOf(Longs.toArray(LONG_MANY_VALUES))) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); } diff --git a/android/guava-tests/test/com/google/common/math/StatsTesting.java b/android/guava-tests/test/com/google/common/math/StatsTesting.java index cb69fc4e7e13..12689d3e345e 100644 --- a/android/guava-tests/test/com/google/common/math/StatsTesting.java +++ b/android/guava-tests/test/com/google/common/math/StatsTesting.java @@ -222,7 +222,7 @@ private static ImmutableList createAll() { static final Stats MANY_VALUES_STATS_VARARGS = Stats.of(1.1, -44.44, 33.33, 555.555, -2.2); static final Stats MANY_VALUES_STATS_ITERABLE = Stats.of(MANY_VALUES); static final Stats MANY_VALUES_STATS_ITERATOR = Stats.of(MANY_VALUES.iterator()); - static final Stats MANY_VALUES_STATS_SNAPSHOT; + static final Stats MANY_VALUES_STATS_SNAPSHOT = buildManyValuesStatsSnapshot(); static final Stats LARGE_VALUES_STATS = Stats.of(LARGE_VALUES); static final Stats OTHER_MANY_VALUES_STATS = Stats.of(OTHER_MANY_VALUES); static final Stats INTEGER_MANY_VALUES_STATS_VARARGS = @@ -230,20 +230,21 @@ private static ImmutableList createAll() { static final Stats INTEGER_MANY_VALUES_STATS_ITERABLE = Stats.of(INTEGER_MANY_VALUES); static final Stats LARGE_INTEGER_VALUES_STATS = Stats.of(LARGE_INTEGER_VALUES); static final Stats LONG_MANY_VALUES_STATS_ITERATOR = Stats.of(LONG_MANY_VALUES.iterator()); - static final Stats LONG_MANY_VALUES_STATS_SNAPSHOT; + static final Stats LONG_MANY_VALUES_STATS_SNAPSHOT = buildLongManyValuesStatsSnapshot(); static final Stats LARGE_LONG_VALUES_STATS = Stats.of(LARGE_LONG_VALUES); - static { + private static Stats buildManyValuesStatsSnapshot() { StatsAccumulator accumulator = new StatsAccumulator(); accumulator.addAll(MANY_VALUES); - MANY_VALUES_STATS_SNAPSHOT = accumulator.snapshot(); + Stats stats = accumulator.snapshot(); accumulator.add(999.999); // should do nothing to the snapshot + return stats; } - static { + private static Stats buildLongManyValuesStatsSnapshot() { StatsAccumulator accumulator = new StatsAccumulator(); accumulator.addAll(LONG_MANY_VALUES); - LONG_MANY_VALUES_STATS_SNAPSHOT = accumulator.snapshot(); + return accumulator.snapshot(); } static final ImmutableList ALL_STATS = @@ -275,42 +276,43 @@ private static ImmutableList createAll() { createPairedStatsOf(ImmutableList.of(ONE_VALUE), ImmutableList.of(OTHER_ONE_VALUE)); static final PairedStats TWO_VALUES_PAIRED_STATS = createPairedStatsOf(TWO_VALUES, OTHER_TWO_VALUES); - static final PairedStats MANY_VALUES_PAIRED_STATS; + static final PairedStats MANY_VALUES_PAIRED_STATS = buildManyValuesPairedStats(); static final PairedStats DUPLICATE_MANY_VALUES_PAIRED_STATS = createPairedStatsOf(MANY_VALUES, OTHER_MANY_VALUES); - static final PairedStats HORIZONTAL_VALUES_PAIRED_STATS; - static final PairedStats VERTICAL_VALUES_PAIRED_STATS; - static final PairedStats CONSTANT_VALUES_PAIRED_STATS; + static final PairedStats HORIZONTAL_VALUES_PAIRED_STATS = buildHorizontalValuesPairedStats(); + static final PairedStats VERTICAL_VALUES_PAIRED_STATS = buildVerticalValuesPairedStats(); + static final PairedStats CONSTANT_VALUES_PAIRED_STATS = buildConstantValuesPairedStats(); - static { + private static PairedStats buildManyValuesPairedStats() { PairedStatsAccumulator accumulator = createFilledPairedStatsAccumulator(MANY_VALUES, OTHER_MANY_VALUES); - MANY_VALUES_PAIRED_STATS = accumulator.snapshot(); + PairedStats stats = accumulator.snapshot(); accumulator.add(99.99, 9999.9999); // should do nothing to the snapshot + return stats; } - static { + private static PairedStats buildHorizontalValuesPairedStats() { PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); for (double x : MANY_VALUES) { accumulator.add(x, OTHER_ONE_VALUE); } - HORIZONTAL_VALUES_PAIRED_STATS = accumulator.snapshot(); + return accumulator.snapshot(); } - static { + private static PairedStats buildVerticalValuesPairedStats() { PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); for (double y : OTHER_MANY_VALUES) { accumulator.add(ONE_VALUE, y); } - VERTICAL_VALUES_PAIRED_STATS = accumulator.snapshot(); + return accumulator.snapshot(); } - static { + private static PairedStats buildConstantValuesPairedStats() { PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); for (int i = 0; i < MANY_VALUES_COUNT; ++i) { accumulator.add(ONE_VALUE, OTHER_ONE_VALUE); } - CONSTANT_VALUES_PAIRED_STATS = accumulator.snapshot(); + return accumulator.snapshot(); } static final ImmutableList ALL_PAIRED_STATS = diff --git a/android/guava/src/com/google/common/math/Stats.java b/android/guava/src/com/google/common/math/Stats.java index 69469b12b847..c557e10d69ba 100644 --- a/android/guava/src/com/google/common/math/Stats.java +++ b/android/guava/src/com/google/common/math/Stats.java @@ -103,7 +103,8 @@ public static Stats of(Iterable values) { } /** - * Returns statistics over a dataset containing the given values. + * Returns statistics over a dataset containing the given values. The iterator will be completely + * consumed by this method. * * @param values a series of values, which will be converted to {@code double} values (this may * cause loss of precision) diff --git a/android/guava/src/com/google/common/math/StatsAccumulator.java b/android/guava/src/com/google/common/math/StatsAccumulator.java index a3977caedbf6..2ae29fabbe34 100644 --- a/android/guava/src/com/google/common/math/StatsAccumulator.java +++ b/android/guava/src/com/google/common/math/StatsAccumulator.java @@ -136,27 +136,47 @@ public void addAll(Stats values) { if (values.count() == 0) { return; } + merge(values.count(), values.mean(), values.sumOfSquaresOfDeltas(), values.min(), values.max()); + } + + /** + * Adds the given statistics to the dataset, as if the individual values used to compute the + * statistics had been added directly. + * + * @since NEXT + */ + public void addAll(StatsAccumulator values) { + if (values.count() == 0) { + return; + } + merge(values.count(), values.mean(), values.sumOfSquaresOfDeltas(), values.min(), values.max()); + } + private void merge( + long otherCount, + double otherMean, + double otherSumOfSquaresOfDeltas, + double otherMin, + double otherMax) { if (count == 0) { - count = values.count(); - mean = values.mean(); - sumOfSquaresOfDeltas = values.sumOfSquaresOfDeltas(); - min = values.min(); - max = values.max(); + count = otherCount; + mean = otherMean; + sumOfSquaresOfDeltas = otherSumOfSquaresOfDeltas; + min = otherMin; + max = otherMax; } else { - count += values.count(); - if (isFinite(mean) && isFinite(values.mean())) { + count += otherCount; + if (isFinite(mean) && isFinite(otherMean)) { // This is a generalized version of the calculation in add(double) above. - double delta = values.mean() - mean; - mean += delta * values.count() / count; - sumOfSquaresOfDeltas += - values.sumOfSquaresOfDeltas() + delta * (values.mean() - mean) * values.count(); + double delta = otherMean - mean; + mean += delta * otherCount / count; + sumOfSquaresOfDeltas += otherSumOfSquaresOfDeltas + delta * (otherMean - mean) * otherCount; } else { - mean = calculateNewMeanNonFinite(mean, values.mean()); + mean = calculateNewMeanNonFinite(mean, otherMean); sumOfSquaresOfDeltas = NaN; } - min = Math.min(min, values.min()); - max = Math.max(max, values.max()); + min = Math.min(min, otherMin); + max = Math.max(max, otherMax); } } diff --git a/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java b/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java index bb26a6ff1e21..2dba5fb27cf5 100644 --- a/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java +++ b/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java @@ -36,6 +36,11 @@ 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.MEGA_STREAM_COUNT; +import static com.google.common.math.StatsTesting.MEGA_STREAM_MAX; +import static com.google.common.math.StatsTesting.MEGA_STREAM_MEAN; +import static com.google.common.math.StatsTesting.MEGA_STREAM_MIN; +import static com.google.common.math.StatsTesting.MEGA_STREAM_POPULATION_VARIANCE; 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; @@ -43,6 +48,8 @@ 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.math.StatsTesting.megaPrimitiveDoubleStreamPart1; +import static com.google.common.math.StatsTesting.megaPrimitiveDoubleStreamPart2; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static java.lang.Math.sqrt; @@ -76,6 +83,7 @@ public class StatsAccumulatorTest extends TestCase { private StatsAccumulator manyValuesAccumulatorByRepeatedAdd; private StatsAccumulator manyValuesAccumulatorByAddAndAddAll; private StatsAccumulator manyValuesAccumulatorByAddAllStats; + private StatsAccumulator manyValuesAccumulatorByAddAllStatsAccumulator; private StatsAccumulator integerManyValuesAccumulatorByAddAllIterable; private StatsAccumulator longManyValuesAccumulatorByAddAllIterator; private StatsAccumulator longManyValuesAccumulatorByAddAllVarargs; @@ -130,6 +138,12 @@ protected void setUp() throws Exception { manyValuesAccumulatorByAddAllStats.addAll( Stats.of(MANY_VALUES.subList(MANY_VALUES.size() / 2, MANY_VALUES.size()))); + manyValuesAccumulatorByAddAllStatsAccumulator = new StatsAccumulator(); + manyValuesAccumulatorByAddAllStatsAccumulator.addAll( + statsAccumulatorOf(MANY_VALUES.subList(0, MANY_VALUES.size() / 2))); + manyValuesAccumulatorByAddAllStatsAccumulator.addAll( + statsAccumulatorOf(MANY_VALUES.subList(MANY_VALUES.size() / 2, MANY_VALUES.size()))); + integerManyValuesAccumulatorByAddAllIterable = new StatsAccumulator(); integerManyValuesAccumulatorByAddAllIterable.addAll(INTEGER_MANY_VALUES); @@ -140,6 +154,12 @@ protected void setUp() throws Exception { longManyValuesAccumulatorByAddAllVarargs.addAll(Longs.toArray(LONG_MANY_VALUES)); } + private static StatsAccumulator statsAccumulatorOf(Iterable values) { + StatsAccumulator accumulator = new StatsAccumulator(); + accumulator.addAll(values); + return accumulator; + } + public void testCount() { assertThat(emptyAccumulator.count()).isEqualTo(0); assertThat(emptyAccumulatorByAddAllEmptyIterable.count()).isEqualTo(0); @@ -154,6 +174,7 @@ public void testCount() { assertThat(manyValuesAccumulatorByRepeatedAdd.count()).isEqualTo(MANY_VALUES_COUNT); assertThat(manyValuesAccumulatorByAddAndAddAll.count()).isEqualTo(MANY_VALUES_COUNT); assertThat(manyValuesAccumulatorByAddAllStats.count()).isEqualTo(MANY_VALUES_COUNT); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.count()).isEqualTo(MANY_VALUES_COUNT); assertThat(integerManyValuesAccumulatorByAddAllIterable.count()) .isEqualTo(StatsTesting.INTEGER_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllIterator.count()) @@ -213,6 +234,9 @@ public void testMean() { assertThat(manyValuesAccumulatorByAddAllStats.mean()) .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_MEAN); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.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) { @@ -252,13 +276,13 @@ public void testMean() { } } assertThat(integerManyValuesAccumulatorByAddAllIterable.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); assertThat(longManyValuesAccumulatorByAddAllIterator.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); assertThat(longManyValuesAccumulatorByAddAllVarargs.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); } @@ -290,14 +314,17 @@ public void testSum() { assertThat(manyValuesAccumulatorByAddAllStats.sum()) .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT); - assertThat(integerManyValuesAccumulatorByAddAllIterable.sum()) + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.sum()) .isWithin(ALLOWED_ERROR) + .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT); + assertThat(integerManyValuesAccumulatorByAddAllIterable.sum()) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN * INTEGER_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllIterator.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllVarargs.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT); } @@ -343,6 +370,9 @@ public void testPopulationVariance() { assertThat(manyValuesAccumulatorByAddAllStats.populationVariance()) .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.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) { @@ -371,13 +401,13 @@ public void testPopulationVariance() { } } assertThat(integerManyValuesAccumulatorByAddAllIterable.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllIterator.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT); assertThat(longManyValuesAccumulatorByAddAllVarargs.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT); } @@ -425,14 +455,17 @@ public void testPopulationStandardDeviation() { assertThat(manyValuesAccumulatorByAddAllStats.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); - assertThat(integerManyValuesAccumulatorByAddAllIterable.populationStandardDeviation()) + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) + .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); + assertThat(integerManyValuesAccumulatorByAddAllIterable.populationStandardDeviation()) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT)); assertThat(longManyValuesAccumulatorByAddAllIterator.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT)); assertThat(longManyValuesAccumulatorByAddAllVarargs.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT)); } @@ -486,14 +519,17 @@ public void testSampleVariance() { assertThat(manyValuesAccumulatorByAddAllStats.sampleVariance()) .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)); - assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleVariance()) + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.sampleVariance()) .isWithin(ALLOWED_ERROR) + .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)); + assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleVariance()) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1)); assertThat(longManyValuesAccumulatorByAddAllIterator.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)); assertThat(longManyValuesAccumulatorByAddAllVarargs.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)); } @@ -547,14 +583,17 @@ public void testSampleStandardDeviation() { assertThat(manyValuesAccumulatorByAddAllStats.sampleStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1))); - assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleStandardDeviation()) + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.sampleStandardDeviation()) .isWithin(ALLOWED_ERROR) + .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1))); + assertThat(integerManyValuesAccumulatorByAddAllIterable.sampleStandardDeviation()) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1))); assertThat(longManyValuesAccumulatorByAddAllIterator.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1))); assertThat(longManyValuesAccumulatorByAddAllVarargs.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1))); } @@ -574,28 +613,17 @@ public void testMax() { 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); + assertThat(oneValueAccumulator.max()).isEqualTo(ONE_VALUE); + assertThat(oneValueAccumulatorByAddAllEmptyStats.max()).isEqualTo(ONE_VALUE); + assertThat(twoValuesAccumulator.max()).isEqualTo(TWO_VALUES_MAX); + assertThat(twoValuesAccumulatorByAddAllStats.max()).isEqualTo(TWO_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllIterable.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllIterator.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllVarargs.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByRepeatedAdd.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAndAddAll.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllStats.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.max()).isEqualTo(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) { @@ -616,22 +644,16 @@ public void testMax() { .that(maxByAddAllStats) .isPositiveInfinity(); } else { - assertWithMessage("max of " + values).that(max).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); + assertWithMessage("max of " + values).that(max).isEqualTo(MANY_VALUES_MAX); assertWithMessage("max by addAll(Stats) of " + values) .that(maxByAddAllStats) - .isWithin(ALLOWED_ERROR) - .of(MANY_VALUES_MAX); + .isEqualTo(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); + .isEqualTo(INTEGER_MANY_VALUES_MAX); + assertThat(longManyValuesAccumulatorByAddAllIterator.max()).isEqualTo(LONG_MANY_VALUES_MAX); + assertThat(longManyValuesAccumulatorByAddAllVarargs.max()).isEqualTo(LONG_MANY_VALUES_MAX); } public void testMin() { @@ -650,28 +672,17 @@ public void testMin() { 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); + assertThat(oneValueAccumulator.min()).isEqualTo(ONE_VALUE); + assertThat(oneValueAccumulatorByAddAllEmptyStats.min()).isEqualTo(ONE_VALUE); + assertThat(twoValuesAccumulator.min()).isEqualTo(TWO_VALUES_MIN); + assertThat(twoValuesAccumulatorByAddAllStats.min()).isEqualTo(TWO_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllIterable.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllIterator.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllVarargs.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByRepeatedAdd.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAndAddAll.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllStats.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(manyValuesAccumulatorByAddAllStatsAccumulator.min()).isEqualTo(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) { @@ -692,21 +703,54 @@ public void testMin() { .that(minByAddAllStats) .isNegativeInfinity(); } else { - assertWithMessage("min of " + values).that(min).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); + assertWithMessage("min of " + values).that(min).isEqualTo(MANY_VALUES_MIN); assertWithMessage("min by addAll(Stats) of " + values) .that(minByAddAllStats) - .isWithin(ALLOWED_ERROR) - .of(MANY_VALUES_MIN); + .isEqualTo(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); + .isEqualTo(INTEGER_MANY_VALUES_MIN); + assertThat(longManyValuesAccumulatorByAddAllIterator.min()).isEqualTo(LONG_MANY_VALUES_MIN); + assertThat(longManyValuesAccumulatorByAddAllVarargs.min()).isEqualTo(LONG_MANY_VALUES_MIN); + } + + public void testAddAllPrimitiveDoubleStream() { + StatsAccumulator accumulator = new StatsAccumulator(); + accumulator.addAll(megaPrimitiveDoubleStreamPart1()); + accumulator.addAll(megaPrimitiveDoubleStreamPart2()); + assertThat(accumulator.count()).isEqualTo(MEGA_STREAM_COUNT); + assertThat(accumulator.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN); + assertThat(accumulator.populationVariance()) + .isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT) + .of(MEGA_STREAM_POPULATION_VARIANCE); + assertThat(accumulator.min()).isEqualTo(MEGA_STREAM_MIN); + assertThat(accumulator.max()).isEqualTo(MEGA_STREAM_MAX); + } + + public void testAddAllPrimitiveIntStream() { + StatsAccumulator accumulator = new StatsAccumulator(); + accumulator.addAll(megaPrimitiveDoubleStreamPart1().mapToInt(x -> (int) x)); + accumulator.addAll(megaPrimitiveDoubleStreamPart2().mapToInt(x -> (int) x)); + assertThat(accumulator.count()).isEqualTo(MEGA_STREAM_COUNT); + assertThat(accumulator.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN); + assertThat(accumulator.populationVariance()) + .isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT) + .of(MEGA_STREAM_POPULATION_VARIANCE); + assertThat(accumulator.min()).isEqualTo(MEGA_STREAM_MIN); + assertThat(accumulator.max()).isEqualTo(MEGA_STREAM_MAX); + } + + public void testAddAllPrimitiveLongStream() { + StatsAccumulator accumulator = new StatsAccumulator(); + accumulator.addAll(megaPrimitiveDoubleStreamPart1().mapToLong(x -> (long) x)); + accumulator.addAll(megaPrimitiveDoubleStreamPart2().mapToLong(x -> (long) x)); + assertThat(accumulator.count()).isEqualTo(MEGA_STREAM_COUNT); + assertThat(accumulator.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN); + assertThat(accumulator.populationVariance()) + .isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT) + .of(MEGA_STREAM_POPULATION_VARIANCE); + assertThat(accumulator.min()).isEqualTo(MEGA_STREAM_MIN); + assertThat(accumulator.max()).isEqualTo(MEGA_STREAM_MAX); } } diff --git a/guava-tests/test/com/google/common/math/StatsTest.java b/guava-tests/test/com/google/common/math/StatsTest.java index cb2021e419a3..9112ef3700f5 100644 --- a/guava-tests/test/com/google/common/math/StatsTest.java +++ b/guava-tests/test/com/google/common/math/StatsTest.java @@ -16,6 +16,7 @@ package com.google.common.math; +import static com.google.common.math.Stats.toStats; 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.ALL_STATS; @@ -55,6 +56,11 @@ import static com.google.common.math.StatsTesting.MANY_VALUES_STATS_SNAPSHOT; import static com.google.common.math.StatsTesting.MANY_VALUES_STATS_VARARGS; import static com.google.common.math.StatsTesting.MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS; +import static com.google.common.math.StatsTesting.MEGA_STREAM_COUNT; +import static com.google.common.math.StatsTesting.MEGA_STREAM_MAX; +import static com.google.common.math.StatsTesting.MEGA_STREAM_MEAN; +import static com.google.common.math.StatsTesting.MEGA_STREAM_MIN; +import static com.google.common.math.StatsTesting.MEGA_STREAM_POPULATION_VARIANCE; import static com.google.common.math.StatsTesting.ONE_VALUE; import static com.google.common.math.StatsTesting.ONE_VALUE_STATS; import static com.google.common.math.StatsTesting.TWO_VALUES; @@ -63,6 +69,7 @@ import static com.google.common.math.StatsTesting.TWO_VALUES_MIN; import static com.google.common.math.StatsTesting.TWO_VALUES_STATS; import static com.google.common.math.StatsTesting.TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS; +import static com.google.common.math.StatsTesting.megaPrimitiveDoubleStream; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static java.lang.Double.NEGATIVE_INFINITY; @@ -77,6 +84,7 @@ import com.google.common.primitives.Longs; import com.google.common.testing.EqualsTester; import com.google.common.testing.SerializableTester; +import java.math.BigDecimal; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.DoubleSummaryStatistics; @@ -147,19 +155,19 @@ public void testMean() { .isWithin(ALLOWED_ERROR * Double.MAX_VALUE) .of(LARGE_VALUES_MEAN); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); assertThat(LARGE_INTEGER_VALUES_STATS.mean()) .isWithin(ALLOWED_ERROR * Integer.MAX_VALUE) .of(LARGE_INTEGER_VALUES_MEAN); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.mean()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); assertThat(LARGE_LONG_VALUES_STATS.mean()) .isWithin(ALLOWED_ERROR * Long.MAX_VALUE) @@ -184,16 +192,16 @@ public void testSum() { .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_MEAN * MANY_VALUES_COUNT); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN * INTEGER_MANY_VALUES_COUNT); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN * INTEGER_MANY_VALUES_COUNT); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.sum()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN * LONG_MANY_VALUES_COUNT); } @@ -238,19 +246,19 @@ public void testPopulationVariance() { .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT); assertThat(LARGE_INTEGER_VALUES_STATS.populationVariance()) .isWithin(ALLOWED_ERROR * Integer.MAX_VALUE * Integer.MAX_VALUE) .of(LARGE_INTEGER_VALUES_POPULATION_VARIANCE); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.populationVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT); assertThat(LARGE_LONG_VALUES_STATS.populationVariance()) .isWithin(ALLOWED_ERROR * Long.MAX_VALUE * Long.MAX_VALUE) @@ -285,16 +293,16 @@ public void testPopulationStandardDeviation() { .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT)); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT)); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT)); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.populationStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / LONG_MANY_VALUES_COUNT)); } @@ -330,16 +338,16 @@ public void testSampleVariance() { .isWithin(ALLOWED_ERROR) .of(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1)); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1)); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1)); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.sampleVariance()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS) .of(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1)); } @@ -375,16 +383,16 @@ public void testSampleStandardDeviation() { .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (MANY_VALUES_COUNT - 1))); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1))); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (INTEGER_MANY_VALUES_COUNT - 1))); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1))); assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.sampleStandardDeviation()) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS)) .of(sqrt(LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / (LONG_MANY_VALUES_COUNT - 1))); } @@ -399,13 +407,13 @@ public void testMax() { fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { } - assertThat(ONE_VALUE_STATS.max()).isWithin(ALLOWED_ERROR).of(ONE_VALUE); + assertThat(ONE_VALUE_STATS.max()).isEqualTo(ONE_VALUE); assertThat(Stats.of(POSITIVE_INFINITY).max()).isPositiveInfinity(); assertThat(Stats.of(NEGATIVE_INFINITY).max()).isNegativeInfinity(); assertThat(Stats.of(NaN).max()).isNaN(); - assertThat(TWO_VALUES_STATS.max()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MAX); - assertThat(MANY_VALUES_STATS_VARARGS.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); - assertThat(MANY_VALUES_STATS_ITERABLE.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); + assertThat(TWO_VALUES_STATS.max()).isEqualTo(TWO_VALUES_MAX); + assertThat(MANY_VALUES_STATS_VARARGS.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(MANY_VALUES_STATS_ITERABLE.max()).isEqualTo(MANY_VALUES_MAX); // 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) { @@ -415,22 +423,14 @@ public void testMax() { } else if (values.hasAnyPositiveInfinity()) { assertWithMessage("max of " + values).that(max).isPositiveInfinity(); } else { - assertWithMessage("max of " + values).that(max).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); + assertWithMessage("max of " + values).that(max).isEqualTo(MANY_VALUES_MAX); } } - assertThat(MANY_VALUES_STATS_SNAPSHOT.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); - assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.max()) - .isWithin(ALLOWED_ERROR) - .of(INTEGER_MANY_VALUES_MAX); - assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.max()) - .isWithin(ALLOWED_ERROR) - .of(INTEGER_MANY_VALUES_MAX); - assertThat(LONG_MANY_VALUES_STATS_ITERATOR.max()) - .isWithin(ALLOWED_ERROR) - .of(LONG_MANY_VALUES_MAX); - assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.max()) - .isWithin(ALLOWED_ERROR) - .of(LONG_MANY_VALUES_MAX); + assertThat(MANY_VALUES_STATS_SNAPSHOT.max()).isEqualTo(MANY_VALUES_MAX); + assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.max()).isEqualTo(INTEGER_MANY_VALUES_MAX); + assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.max()).isEqualTo(INTEGER_MANY_VALUES_MAX); + assertThat(LONG_MANY_VALUES_STATS_ITERATOR.max()).isEqualTo(LONG_MANY_VALUES_MAX); + assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.max()).isEqualTo(LONG_MANY_VALUES_MAX); } public void testMin() { @@ -444,14 +444,14 @@ public void testMin() { fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { } - assertThat(ONE_VALUE_STATS.min()).isWithin(ALLOWED_ERROR).of(ONE_VALUE); + assertThat(ONE_VALUE_STATS.min()).isEqualTo(ONE_VALUE); assertThat(Stats.of(POSITIVE_INFINITY).min()).isPositiveInfinity(); assertThat(Stats.of(NEGATIVE_INFINITY).min()).isNegativeInfinity(); assertThat(Stats.of(NaN).min()).isNaN(); - assertThat(TWO_VALUES_STATS.min()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MIN); - assertThat(MANY_VALUES_STATS_VARARGS.min()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); - assertThat(MANY_VALUES_STATS_ITERABLE.min()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); - assertThat(MANY_VALUES_STATS_ITERATOR.min()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); + assertThat(TWO_VALUES_STATS.min()).isEqualTo(TWO_VALUES_MIN); + assertThat(MANY_VALUES_STATS_VARARGS.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(MANY_VALUES_STATS_ITERABLE.min()).isEqualTo(MANY_VALUES_MIN); + assertThat(MANY_VALUES_STATS_ITERATOR.min()).isEqualTo(MANY_VALUES_MIN); // For datasets of many double values created from an accumulator snapshot, we test many // combinations of finite and non-finite values: for (ManyValues values : ALL_MANY_VALUES) { @@ -463,21 +463,68 @@ public void testMin() { } else if (values.hasAnyNegativeInfinity()) { assertWithMessage("min of " + values).that(min).isNegativeInfinity(); } else { - assertWithMessage("min of " + values).that(min).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MIN); + assertWithMessage("min of " + values).that(min).isEqualTo(MANY_VALUES_MIN); } } - assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.min()) - .isWithin(ALLOWED_ERROR) - .of(INTEGER_MANY_VALUES_MIN); - assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.min()) - .isWithin(ALLOWED_ERROR) - .of(INTEGER_MANY_VALUES_MIN); - assertThat(LONG_MANY_VALUES_STATS_ITERATOR.min()) - .isWithin(ALLOWED_ERROR) - .of(LONG_MANY_VALUES_MIN); - assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.min()) - .isWithin(ALLOWED_ERROR) - .of(LONG_MANY_VALUES_MIN); + assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.min()).isEqualTo(INTEGER_MANY_VALUES_MIN); + assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.min()).isEqualTo(INTEGER_MANY_VALUES_MIN); + assertThat(LONG_MANY_VALUES_STATS_ITERATOR.min()).isEqualTo(LONG_MANY_VALUES_MIN); + assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.min()).isEqualTo(LONG_MANY_VALUES_MIN); + } + + public void testOfPrimitiveDoubleStream() { + Stats stats = Stats.of(megaPrimitiveDoubleStream()); + assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT); + assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN); + assertThat(stats.populationVariance()) + .isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT) + .of(MEGA_STREAM_POPULATION_VARIANCE); + assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN); + assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX); + } + + public void testOfPrimitiveIntStream() { + Stats stats = Stats.of(megaPrimitiveDoubleStream().mapToInt(x -> (int) x)); + assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT); + assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN); + assertThat(stats.populationVariance()) + .isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT) + .of(MEGA_STREAM_POPULATION_VARIANCE); + assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN); + assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX); + } + + public void testOfPrimitiveLongStream() { + Stats stats = Stats.of(megaPrimitiveDoubleStream().mapToLong(x -> (long) x)); + assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT); + assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN); + assertThat(stats.populationVariance()) + .isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT) + .of(MEGA_STREAM_POPULATION_VARIANCE); + assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN); + assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX); + } + + public void testBoxedDoubleStreamToStats() { + Stats stats = megaPrimitiveDoubleStream().boxed().collect(toStats()); + assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT); + assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN); + assertThat(stats.populationVariance()) + .isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT) + .of(MEGA_STREAM_POPULATION_VARIANCE); + assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN); + assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX); + } + + public void testBoxedBigDecimalStreamToStats() { + Stats stats = megaPrimitiveDoubleStream().mapToObj(BigDecimal::valueOf).collect(toStats()); + assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT); + assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN); + assertThat(stats.populationVariance()) + .isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT) + .of(MEGA_STREAM_POPULATION_VARIANCE); + assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN); + assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX); } public void testEqualsAndHashCode() { @@ -560,14 +607,16 @@ public void testMeanOf() { assertThat(Stats.meanOf(MANY_VALUES)).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MEAN); assertThat(Stats.meanOf(MANY_VALUES.iterator())).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MEAN); assertThat(Stats.meanOf(INTEGER_MANY_VALUES)) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); assertThat(Stats.meanOf(Ints.toArray(INTEGER_MANY_VALUES))) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * INTEGER_MANY_VALUES_MEAN) .of(INTEGER_MANY_VALUES_MEAN); - assertThat(Stats.meanOf(LONG_MANY_VALUES)).isWithin(ALLOWED_ERROR).of(LONG_MANY_VALUES_MEAN); + assertThat(Stats.meanOf(LONG_MANY_VALUES)) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) + .of(LONG_MANY_VALUES_MEAN); assertThat(Stats.meanOf(Longs.toArray(LONG_MANY_VALUES))) - .isWithin(ALLOWED_ERROR) + .isWithin(ALLOWED_ERROR * LONG_MANY_VALUES_MEAN) .of(LONG_MANY_VALUES_MEAN); } diff --git a/guava-tests/test/com/google/common/math/StatsTesting.java b/guava-tests/test/com/google/common/math/StatsTesting.java index cb69fc4e7e13..261cdd4b1c1d 100644 --- a/guava-tests/test/com/google/common/math/StatsTesting.java +++ b/guava-tests/test/com/google/common/math/StatsTesting.java @@ -31,6 +31,7 @@ import com.google.common.primitives.Ints; import java.math.BigInteger; import java.util.List; +import java.util.stream.DoubleStream; /** * Inputs, expected outputs, and helper methods for tests of {@link StatsAccumulator}, {@link @@ -211,6 +212,34 @@ private static ImmutableList createAll() { .divide(BigInteger.valueOf(16L)) .doubleValue(); + /** + * Returns a stream of a million primitive doubles. The stream is parallel, which should cause + * {@code collect} calls to run in multi-threaded mode, so testing the combiner as well as the + * supplier and accumulator. + */ + static DoubleStream megaPrimitiveDoubleStream() { + return DoubleStream.iterate(0.0, x -> x + 1.0).limit(MEGA_STREAM_COUNT).parallel(); + } + + /** Returns a stream containing half the values from {@link #megaPrimitiveDoubleStream}. */ + static DoubleStream megaPrimitiveDoubleStreamPart1() { + return DoubleStream.iterate(0.0, x -> x + 2.0).limit(MEGA_STREAM_COUNT / 2).parallel(); + } + + /** + * Returns a stream containing the values from {@link #megaPrimitiveDoubleStream} not in {@link + * #megaPrimitiveDoubleStreamPart1()}. + */ + static DoubleStream megaPrimitiveDoubleStreamPart2() { + return DoubleStream.iterate(999_999.0, x -> x - 2.0).limit(MEGA_STREAM_COUNT / 2).parallel(); + } + + static final long MEGA_STREAM_COUNT = 1_000_000; + static final double MEGA_STREAM_MEAN = 999_999.0 / 2; + static final double MEGA_STREAM_POPULATION_VARIANCE = 999_999.0 * 1_000_001.0 / 12; + static final double MEGA_STREAM_MIN = 0.0; + static final double MEGA_STREAM_MAX = 999_999.0; + // Stats instances: static final Stats EMPTY_STATS_VARARGS = Stats.of(); @@ -222,7 +251,7 @@ private static ImmutableList createAll() { static final Stats MANY_VALUES_STATS_VARARGS = Stats.of(1.1, -44.44, 33.33, 555.555, -2.2); static final Stats MANY_VALUES_STATS_ITERABLE = Stats.of(MANY_VALUES); static final Stats MANY_VALUES_STATS_ITERATOR = Stats.of(MANY_VALUES.iterator()); - static final Stats MANY_VALUES_STATS_SNAPSHOT; + static final Stats MANY_VALUES_STATS_SNAPSHOT = buildManyValuesStatsSnapshot(); static final Stats LARGE_VALUES_STATS = Stats.of(LARGE_VALUES); static final Stats OTHER_MANY_VALUES_STATS = Stats.of(OTHER_MANY_VALUES); static final Stats INTEGER_MANY_VALUES_STATS_VARARGS = @@ -230,20 +259,21 @@ private static ImmutableList createAll() { static final Stats INTEGER_MANY_VALUES_STATS_ITERABLE = Stats.of(INTEGER_MANY_VALUES); static final Stats LARGE_INTEGER_VALUES_STATS = Stats.of(LARGE_INTEGER_VALUES); static final Stats LONG_MANY_VALUES_STATS_ITERATOR = Stats.of(LONG_MANY_VALUES.iterator()); - static final Stats LONG_MANY_VALUES_STATS_SNAPSHOT; + static final Stats LONG_MANY_VALUES_STATS_SNAPSHOT = buildLongManyValuesStatsSnapshot(); static final Stats LARGE_LONG_VALUES_STATS = Stats.of(LARGE_LONG_VALUES); - static { + private static Stats buildManyValuesStatsSnapshot() { StatsAccumulator accumulator = new StatsAccumulator(); accumulator.addAll(MANY_VALUES); - MANY_VALUES_STATS_SNAPSHOT = accumulator.snapshot(); + Stats stats = accumulator.snapshot(); accumulator.add(999.999); // should do nothing to the snapshot + return stats; } - static { + private static Stats buildLongManyValuesStatsSnapshot() { StatsAccumulator accumulator = new StatsAccumulator(); accumulator.addAll(LONG_MANY_VALUES); - LONG_MANY_VALUES_STATS_SNAPSHOT = accumulator.snapshot(); + return accumulator.snapshot(); } static final ImmutableList ALL_STATS = @@ -275,42 +305,43 @@ private static ImmutableList createAll() { createPairedStatsOf(ImmutableList.of(ONE_VALUE), ImmutableList.of(OTHER_ONE_VALUE)); static final PairedStats TWO_VALUES_PAIRED_STATS = createPairedStatsOf(TWO_VALUES, OTHER_TWO_VALUES); - static final PairedStats MANY_VALUES_PAIRED_STATS; + static final PairedStats MANY_VALUES_PAIRED_STATS = buildManyValuesPairedStats(); static final PairedStats DUPLICATE_MANY_VALUES_PAIRED_STATS = createPairedStatsOf(MANY_VALUES, OTHER_MANY_VALUES); - static final PairedStats HORIZONTAL_VALUES_PAIRED_STATS; - static final PairedStats VERTICAL_VALUES_PAIRED_STATS; - static final PairedStats CONSTANT_VALUES_PAIRED_STATS; + static final PairedStats HORIZONTAL_VALUES_PAIRED_STATS = buildHorizontalValuesPairedStats(); + static final PairedStats VERTICAL_VALUES_PAIRED_STATS = buildVerticalValuesPairedStats(); + static final PairedStats CONSTANT_VALUES_PAIRED_STATS = buildConstantValuesPairedStats(); - static { + private static PairedStats buildManyValuesPairedStats() { PairedStatsAccumulator accumulator = createFilledPairedStatsAccumulator(MANY_VALUES, OTHER_MANY_VALUES); - MANY_VALUES_PAIRED_STATS = accumulator.snapshot(); + PairedStats stats = accumulator.snapshot(); accumulator.add(99.99, 9999.9999); // should do nothing to the snapshot + return stats; } - static { + private static PairedStats buildHorizontalValuesPairedStats() { PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); for (double x : MANY_VALUES) { accumulator.add(x, OTHER_ONE_VALUE); } - HORIZONTAL_VALUES_PAIRED_STATS = accumulator.snapshot(); + return accumulator.snapshot(); } - static { + private static PairedStats buildVerticalValuesPairedStats() { PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); for (double y : OTHER_MANY_VALUES) { accumulator.add(ONE_VALUE, y); } - VERTICAL_VALUES_PAIRED_STATS = accumulator.snapshot(); + return accumulator.snapshot(); } - static { + private static PairedStats buildConstantValuesPairedStats() { PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); for (int i = 0; i < MANY_VALUES_COUNT; ++i) { accumulator.add(ONE_VALUE, OTHER_ONE_VALUE); } - CONSTANT_VALUES_PAIRED_STATS = accumulator.snapshot(); + return accumulator.snapshot(); } static final ImmutableList ALL_PAIRED_STATS = diff --git a/guava/src/com/google/common/math/Stats.java b/guava/src/com/google/common/math/Stats.java index 273bb8e6a9e3..6da1b8aa9162 100644 --- a/guava/src/com/google/common/math/Stats.java +++ b/guava/src/com/google/common/math/Stats.java @@ -32,6 +32,10 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Iterator; +import java.util.stream.Collector; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -103,7 +107,8 @@ public static Stats of(Iterable values) { } /** - * Returns statistics over a dataset containing the given values. + * Returns statistics over a dataset containing the given values. The iterator will be completely + * consumed by this method. * * @param values a series of values, which will be converted to {@code double} values (this may * cause loss of precision) @@ -148,6 +153,78 @@ public static Stats of(long... values) { return acummulator.snapshot(); } + /** + * Returns statistics over a dataset containing the given values. The stream will be completely + * consumed by this method. + * + *

If you have a {@code Stream} rather than a {@code DoubleStream}, you should collect + * the values using {@link #toStats()} instead. + * + * @param values a series of values + * @since NEXT + */ + public static Stats of(DoubleStream values) { + return values + .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) + .snapshot(); + } + + /** + * Returns statistics over a dataset containing the given values. The stream will be completely + * consumed by this method. + * + *

If you have a {@code Stream} rather than an {@code IntStream}, you should collect + * the values using {@link #toStats()} instead. + * + * @param values a series of values + * @since NEXT + */ + public static Stats of(IntStream values) { + return values + .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) + .snapshot(); + } + + /** + * Returns statistics over a dataset containing the given values. The stream will be completely + * consumed by this method. + * + *

If you have a {@code Stream} rather than a {@code LongStream}, you should collect the + * values using {@link #toStats()} instead. + * + * @param values a series of values, which will be converted to {@code double} values (this may + * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) + * @since NEXT + */ + public static Stats of(LongStream values) { + return values + .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll) + .snapshot(); + } + + /** + * Returns a {@link Collector} which accumulates statistics from a {@link java.util.stream.Stream} + * of any type of boxed {@link Number} into a {@link Stats}. Use by calling {@code + * boxedNumericStream.collect(toStats())}. The numbers will be converted to {@code double} values + * (which may cause loss of precision). + * + *

If you have any of the primitive streams {@code DoubleStream}, {@code IntStream}, or {@code + * LongStream}, you should use the factory method {@link #of} instead. + * + * @since NEXT + */ + public static Collector toStats() { + return Collector.of( + StatsAccumulator::new, + (a, x) -> a.add(x.doubleValue()), + (l, r) -> { + l.addAll(r); + return l; + }, + StatsAccumulator::snapshot, + Collector.Characteristics.UNORDERED); + } + /** Returns the number of values. */ public long count() { return count; diff --git a/guava/src/com/google/common/math/StatsAccumulator.java b/guava/src/com/google/common/math/StatsAccumulator.java index a3977caedbf6..5d5dfbaff806 100644 --- a/guava/src/com/google/common/math/StatsAccumulator.java +++ b/guava/src/com/google/common/math/StatsAccumulator.java @@ -23,6 +23,9 @@ import com.google.common.annotations.Beta; import com.google.common.annotations.GwtIncompatible; import java.util.Iterator; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; /** * A mutable object which accumulates double values and tracks some basic statistics over all the @@ -128,6 +131,37 @@ public void addAll(long... values) { } } + /** + * Adds the given values to the dataset. The stream will be completely consumed by this method. + * + * @param values a series of values + * @since NEXT + */ + public void addAll(DoubleStream values) { + addAll(values.collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll)); + } + + /** + * Adds the given values to the dataset. The stream will be completely consumed by this method. + * + * @param values a series of values + * @since NEXT + */ + public void addAll(IntStream values) { + addAll(values.collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll)); + } + + /** + * Adds the given values to the dataset. The stream will be completely consumed by this method. + * + * @param values a series of values, which will be converted to {@code double} values (this may + * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) + * @since NEXT + */ + public void addAll(LongStream values) { + addAll(values.collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll)); + } + /** * Adds the given statistics to the dataset, as if the individual values used to compute the * statistics had been added directly. @@ -136,27 +170,47 @@ public void addAll(Stats values) { if (values.count() == 0) { return; } + merge(values.count(), values.mean(), values.sumOfSquaresOfDeltas(), values.min(), values.max()); + } + + /** + * Adds the given statistics to the dataset, as if the individual values used to compute the + * statistics had been added directly. + * + * @since NEXT + */ + public void addAll(StatsAccumulator values) { + if (values.count() == 0) { + return; + } + merge(values.count(), values.mean(), values.sumOfSquaresOfDeltas(), values.min(), values.max()); + } + private void merge( + long otherCount, + double otherMean, + double otherSumOfSquaresOfDeltas, + double otherMin, + double otherMax) { if (count == 0) { - count = values.count(); - mean = values.mean(); - sumOfSquaresOfDeltas = values.sumOfSquaresOfDeltas(); - min = values.min(); - max = values.max(); + count = otherCount; + mean = otherMean; + sumOfSquaresOfDeltas = otherSumOfSquaresOfDeltas; + min = otherMin; + max = otherMax; } else { - count += values.count(); - if (isFinite(mean) && isFinite(values.mean())) { + count += otherCount; + if (isFinite(mean) && isFinite(otherMean)) { // This is a generalized version of the calculation in add(double) above. - double delta = values.mean() - mean; - mean += delta * values.count() / count; - sumOfSquaresOfDeltas += - values.sumOfSquaresOfDeltas() + delta * (values.mean() - mean) * values.count(); + double delta = otherMean - mean; + mean += delta * otherCount / count; + sumOfSquaresOfDeltas += otherSumOfSquaresOfDeltas + delta * (otherMean - mean) * otherCount; } else { - mean = calculateNewMeanNonFinite(mean, values.mean()); + mean = calculateNewMeanNonFinite(mean, otherMean); sumOfSquaresOfDeltas = NaN; } - min = Math.min(min, values.min()); - max = Math.max(max, values.max()); + min = Math.min(min, otherMin); + max = Math.max(max, otherMax); } }