| /* |
| * Copyright (C) 2013 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.common.math; |
| |
| import static com.google.common.base.Preconditions.checkArgument; |
| import static com.google.common.truth.Truth.assertThat; |
| import static java.lang.Double.NEGATIVE_INFINITY; |
| import static java.lang.Double.NaN; |
| import static java.lang.Double.POSITIVE_INFINITY; |
| import static org.junit.Assert.fail; |
| |
| import com.google.common.base.Predicates; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Iterables; |
| import com.google.common.collect.Lists; |
| import com.google.common.primitives.Doubles; |
| import com.google.common.primitives.Ints; |
| import java.math.BigInteger; |
| import java.util.List; |
| |
| /** |
| * Inputs, expected outputs, and helper methods for tests of {@link StatsAccumulator}, {@link |
| * Stats}, {@link PairedStatsAccumulator}, and {@link PairedStats}. |
| * |
| * @author Pete Gillin |
| */ |
| class StatsTesting { |
| |
| static final double ALLOWED_ERROR = 1e-10; |
| |
| // Inputs and their statistics: |
| |
| static final double ONE_VALUE = 12.34; |
| |
| static final double OTHER_ONE_VALUE = -56.78; |
| |
| static final ImmutableList<Double> TWO_VALUES = ImmutableList.of(12.34, -56.78); |
| static final double TWO_VALUES_MEAN = (12.34 - 56.78) / 2; |
| static final double TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS = |
| (12.34 - TWO_VALUES_MEAN) * (12.34 - TWO_VALUES_MEAN) |
| + (-56.78 - TWO_VALUES_MEAN) * (-56.78 - TWO_VALUES_MEAN); |
| static final double TWO_VALUES_MAX = 12.34; |
| static final double TWO_VALUES_MIN = -56.78; |
| |
| static final ImmutableList<Double> OTHER_TWO_VALUES = ImmutableList.of(123.456, -789.012); |
| static final double OTHER_TWO_VALUES_MEAN = (123.456 - 789.012) / 2; |
| static final double TWO_VALUES_SUM_OF_PRODUCTS_OF_DELTAS = |
| (12.34 - TWO_VALUES_MEAN) * (123.456 - OTHER_TWO_VALUES_MEAN) |
| + (-56.78 - TWO_VALUES_MEAN) * (-789.012 - OTHER_TWO_VALUES_MEAN); |
| |
| /** |
| * Helper class for testing with non-finite values. {@link #ALL_MANY_VALUES} gives a number |
| * instances with many combinations of finite and non-finite values. All have {@link |
| * #MANY_VALUES_COUNT} values. If all the values are finite then the mean is {@link |
| * #MANY_VALUES_MEAN} and the sum-of-squares-of-deltas is {@link |
| * #MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS}. The smallest and largest finite values are always |
| * {@link #MANY_VALUES_MIN} and {@link #MANY_VALUES_MAX}, although setting non-finite values will |
| * change the true min and max. |
| */ |
| static class ManyValues { |
| |
| private final ImmutableList<Double> values; |
| |
| ManyValues(double[] values) { |
| this.values = ImmutableList.copyOf(Doubles.asList(values)); |
| } |
| |
| ImmutableList<Double> asIterable() { |
| return values; |
| } |
| |
| double[] asArray() { |
| return Doubles.toArray(values); |
| } |
| |
| boolean hasAnyPositiveInfinity() { |
| return Iterables.any(values, Predicates.equalTo(POSITIVE_INFINITY)); |
| } |
| |
| boolean hasAnyNegativeInfinity() { |
| return Iterables.any(values, Predicates.equalTo(NEGATIVE_INFINITY)); |
| } |
| |
| boolean hasAnyNaN() { |
| return Iterables.any(values, Predicates.equalTo(NaN)); |
| } |
| |
| boolean hasAnyNonFinite() { |
| return hasAnyPositiveInfinity() || hasAnyNegativeInfinity() || hasAnyNaN(); |
| } |
| |
| @Override |
| public String toString() { |
| return values.toString(); |
| } |
| |
| private static ImmutableList<ManyValues> createAll() { |
| ImmutableList.Builder<ManyValues> builder = ImmutableList.builder(); |
| double[] values = new double[5]; |
| for (double first : ImmutableList.of(1.1, POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN)) { |
| values[0] = first; |
| values[1] = -44.44; |
| for (double third : ImmutableList.of(33.33, POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN)) { |
| values[2] = third; |
| values[3] = 555.555; |
| for (double fifth : ImmutableList.of(-2.2, POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN)) { |
| values[4] = fifth; |
| builder.add(new ManyValues(values)); |
| } |
| } |
| } |
| return builder.build(); |
| } |
| } |
| |
| static final ImmutableList<ManyValues> ALL_MANY_VALUES = ManyValues.createAll(); |
| |
| static final ImmutableList<Double> MANY_VALUES = |
| ImmutableList.of(1.1, -44.44, 33.33, 555.555, -2.2); |
| static final int MANY_VALUES_COUNT = 5; |
| static final double MANY_VALUES_MEAN = (1.1 - 44.44 + 33.33 + 555.555 - 2.2) / 5; |
| static final double MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS = |
| (1.1 - MANY_VALUES_MEAN) * (1.1 - MANY_VALUES_MEAN) |
| + (-44.44 - MANY_VALUES_MEAN) * (-44.44 - MANY_VALUES_MEAN) |
| + (33.33 - MANY_VALUES_MEAN) * (33.33 - MANY_VALUES_MEAN) |
| + (555.555 - MANY_VALUES_MEAN) * (555.555 - MANY_VALUES_MEAN) |
| + (-2.2 - MANY_VALUES_MEAN) * (-2.2 - MANY_VALUES_MEAN); |
| static final double MANY_VALUES_MAX = 555.555; |
| static final double MANY_VALUES_MIN = -44.44; |
| |
| // Doubles which will overflow if summed: |
| static final double[] LARGE_VALUES = {Double.MAX_VALUE, Double.MAX_VALUE / 2.0}; |
| static final double LARGE_VALUES_MEAN = 0.75 * Double.MAX_VALUE; |
| |
| static final ImmutableList<Double> OTHER_MANY_VALUES = |
| ImmutableList.of(1.11, -2.22, 33.3333, -44.4444, 555.555555); |
| static final int OTHER_MANY_VALUES_COUNT = 5; |
| static final double OTHER_MANY_VALUES_MEAN = (1.11 - 2.22 + 33.3333 - 44.4444 + 555.555555) / 5; |
| |
| static final double MANY_VALUES_SUM_OF_PRODUCTS_OF_DELTAS = |
| (1.1 - MANY_VALUES_MEAN) * (1.11 - OTHER_MANY_VALUES_MEAN) |
| + (-44.44 - MANY_VALUES_MEAN) * (-2.22 - OTHER_MANY_VALUES_MEAN) |
| + (33.33 - MANY_VALUES_MEAN) * (33.3333 - OTHER_MANY_VALUES_MEAN) |
| + (555.555 - MANY_VALUES_MEAN) * (-44.4444 - OTHER_MANY_VALUES_MEAN) |
| + (-2.2 - MANY_VALUES_MEAN) * (555.555555 - OTHER_MANY_VALUES_MEAN); |
| |
| static final ImmutableList<Integer> INTEGER_MANY_VALUES = |
| ImmutableList.of(11, -22, 3333, -4444, 555555); |
| static final int INTEGER_MANY_VALUES_COUNT = 5; |
| static final double INTEGER_MANY_VALUES_MEAN = (11.0 - 22.0 + 3333.0 - 4444.0 + 555555.0) / 5; |
| static final double INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS = |
| (11.0 - INTEGER_MANY_VALUES_MEAN) * (11.0 - INTEGER_MANY_VALUES_MEAN) |
| + (-22.0 - INTEGER_MANY_VALUES_MEAN) * (-22.0 - INTEGER_MANY_VALUES_MEAN) |
| + (3333.0 - INTEGER_MANY_VALUES_MEAN) * (3333.0 - INTEGER_MANY_VALUES_MEAN) |
| + (-4444.0 - INTEGER_MANY_VALUES_MEAN) * (-4444.0 - INTEGER_MANY_VALUES_MEAN) |
| + (555555.0 - INTEGER_MANY_VALUES_MEAN) * (555555.0 - INTEGER_MANY_VALUES_MEAN); |
| static final double INTEGER_MANY_VALUES_MAX = 555555.0; |
| static final double INTEGER_MANY_VALUES_MIN = -4444.0; |
| |
| // Integers which will overflow if summed (using integer arithmetic): |
| static final int[] LARGE_INTEGER_VALUES = {Integer.MAX_VALUE, Integer.MAX_VALUE / 2}; |
| static final double LARGE_INTEGER_VALUES_MEAN = |
| BigInteger.valueOf(Integer.MAX_VALUE) |
| .multiply(BigInteger.valueOf(3L)) |
| .divide(BigInteger.valueOf(4L)) |
| .doubleValue(); |
| static final double LARGE_INTEGER_VALUES_POPULATION_VARIANCE = |
| BigInteger.valueOf(Integer.MAX_VALUE) |
| .multiply(BigInteger.valueOf(Integer.MAX_VALUE)) |
| .divide(BigInteger.valueOf(16L)) |
| .doubleValue(); |
| |
| static final ImmutableList<Long> LONG_MANY_VALUES = |
| ImmutableList.of(1111L, -2222L, 33333333L, -44444444L, 5555555555L); |
| static final int LONG_MANY_VALUES_COUNT = 5; |
| static final double LONG_MANY_VALUES_MEAN = |
| (1111.0 - 2222.0 + 33333333.0 - 44444444.0 + 5555555555.0) / 5; |
| static final double LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS = |
| (1111.0 - LONG_MANY_VALUES_MEAN) * (1111.0 - LONG_MANY_VALUES_MEAN) |
| + (-2222.0 - LONG_MANY_VALUES_MEAN) * (-2222.0 - LONG_MANY_VALUES_MEAN) |
| + (33333333.0 - LONG_MANY_VALUES_MEAN) * (33333333.0 - LONG_MANY_VALUES_MEAN) |
| + (-44444444.0 - LONG_MANY_VALUES_MEAN) * (-44444444.0 - LONG_MANY_VALUES_MEAN) |
| + (5555555555.0 - LONG_MANY_VALUES_MEAN) * (5555555555.0 - LONG_MANY_VALUES_MEAN); |
| static final double LONG_MANY_VALUES_MAX = 5555555555.0; |
| static final double LONG_MANY_VALUES_MIN = -44444444.0; |
| |
| // Longs which will overflow if summed (using long arithmetic): |
| static final long[] LARGE_LONG_VALUES = {Long.MAX_VALUE, Long.MAX_VALUE / 2}; |
| static final double LARGE_LONG_VALUES_MEAN = |
| BigInteger.valueOf(Long.MAX_VALUE) |
| .multiply(BigInteger.valueOf(3L)) |
| .divide(BigInteger.valueOf(4L)) |
| .doubleValue(); |
| static final double LARGE_LONG_VALUES_POPULATION_VARIANCE = |
| BigInteger.valueOf(Long.MAX_VALUE) |
| .multiply(BigInteger.valueOf(Long.MAX_VALUE)) |
| .divide(BigInteger.valueOf(16L)) |
| .doubleValue(); |
| |
| // Stats instances: |
| |
| static final Stats EMPTY_STATS_VARARGS = Stats.of(); |
| static final Stats EMPTY_STATS_ITERABLE = Stats.of(ImmutableList.<Double>of()); |
| static final Stats ONE_VALUE_STATS = Stats.of(ONE_VALUE); |
| static final Stats OTHER_ONE_VALUE_STATS = Stats.of(OTHER_ONE_VALUE); |
| static final Stats TWO_VALUES_STATS = Stats.of(TWO_VALUES); |
| static final Stats OTHER_TWO_VALUES_STATS = Stats.of(OTHER_TWO_VALUES); |
| 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 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 = |
| Stats.of(Ints.toArray(INTEGER_MANY_VALUES)); |
| 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 LARGE_LONG_VALUES_STATS = Stats.of(LARGE_LONG_VALUES); |
| |
| static { |
| StatsAccumulator accumulator = new StatsAccumulator(); |
| accumulator.addAll(MANY_VALUES); |
| MANY_VALUES_STATS_SNAPSHOT = accumulator.snapshot(); |
| accumulator.add(999.999); // should do nothing to the snapshot |
| } |
| |
| static { |
| StatsAccumulator accumulator = new StatsAccumulator(); |
| accumulator.addAll(LONG_MANY_VALUES); |
| LONG_MANY_VALUES_STATS_SNAPSHOT = accumulator.snapshot(); |
| } |
| |
| static final ImmutableList<Stats> ALL_STATS = |
| ImmutableList.of( |
| EMPTY_STATS_VARARGS, |
| EMPTY_STATS_ITERABLE, |
| ONE_VALUE_STATS, |
| OTHER_ONE_VALUE_STATS, |
| TWO_VALUES_STATS, |
| OTHER_TWO_VALUES_STATS, |
| MANY_VALUES_STATS_VARARGS, |
| MANY_VALUES_STATS_ITERABLE, |
| MANY_VALUES_STATS_ITERATOR, |
| MANY_VALUES_STATS_SNAPSHOT, |
| LARGE_VALUES_STATS, |
| OTHER_MANY_VALUES_STATS, |
| INTEGER_MANY_VALUES_STATS_VARARGS, |
| INTEGER_MANY_VALUES_STATS_ITERABLE, |
| LARGE_INTEGER_VALUES_STATS, |
| LONG_MANY_VALUES_STATS_ITERATOR, |
| LONG_MANY_VALUES_STATS_SNAPSHOT, |
| LARGE_LONG_VALUES_STATS); |
| |
| // PairedStats instances: |
| |
| static final PairedStats EMPTY_PAIRED_STATS = |
| createPairedStatsOf(ImmutableList.<Double>of(), ImmutableList.<Double>of()); |
| static final PairedStats ONE_VALUE_PAIRED_STATS = |
| 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 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 { |
| PairedStatsAccumulator accumulator = |
| createFilledPairedStatsAccumulator(MANY_VALUES, OTHER_MANY_VALUES); |
| MANY_VALUES_PAIRED_STATS = accumulator.snapshot(); |
| accumulator.add(99.99, 9999.9999); // should do nothing to the snapshot |
| } |
| |
| static { |
| PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); |
| for (double x : MANY_VALUES) { |
| accumulator.add(x, OTHER_ONE_VALUE); |
| } |
| HORIZONTAL_VALUES_PAIRED_STATS = accumulator.snapshot(); |
| } |
| |
| static { |
| PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); |
| for (double y : OTHER_MANY_VALUES) { |
| accumulator.add(ONE_VALUE, y); |
| } |
| VERTICAL_VALUES_PAIRED_STATS = accumulator.snapshot(); |
| } |
| |
| static { |
| 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(); |
| } |
| |
| static final ImmutableList<PairedStats> ALL_PAIRED_STATS = |
| ImmutableList.of( |
| EMPTY_PAIRED_STATS, |
| ONE_VALUE_PAIRED_STATS, |
| TWO_VALUES_PAIRED_STATS, |
| MANY_VALUES_PAIRED_STATS, |
| DUPLICATE_MANY_VALUES_PAIRED_STATS, |
| HORIZONTAL_VALUES_PAIRED_STATS, |
| VERTICAL_VALUES_PAIRED_STATS, |
| CONSTANT_VALUES_PAIRED_STATS); |
| |
| // Helper methods: |
| |
| static void assertStatsApproxEqual(Stats expectedStats, Stats actualStats) { |
| assertThat(actualStats.count()).isEqualTo(expectedStats.count()); |
| if (expectedStats.count() == 0) { |
| try { |
| actualStats.mean(); |
| fail("Expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| try { |
| actualStats.populationVariance(); |
| fail("Expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| try { |
| actualStats.min(); |
| fail("Expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| try { |
| actualStats.max(); |
| fail("Expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| } else if (expectedStats.count() == 1) { |
| assertThat(actualStats.mean()).isWithin(ALLOWED_ERROR).of(expectedStats.mean()); |
| assertThat(actualStats.populationVariance()).isWithin(0.0).of(0.0); |
| assertThat(actualStats.min()).isWithin(ALLOWED_ERROR).of(expectedStats.min()); |
| assertThat(actualStats.max()).isWithin(ALLOWED_ERROR).of(expectedStats.max()); |
| } else { |
| assertThat(actualStats.mean()).isWithin(ALLOWED_ERROR).of(expectedStats.mean()); |
| assertThat(actualStats.populationVariance()) |
| .isWithin(ALLOWED_ERROR) |
| .of(expectedStats.populationVariance()); |
| assertThat(actualStats.min()).isWithin(ALLOWED_ERROR).of(expectedStats.min()); |
| assertThat(actualStats.max()).isWithin(ALLOWED_ERROR).of(expectedStats.max()); |
| } |
| } |
| |
| /** |
| * Asserts that {@code transformation} is diagonal (i.e. neither horizontal or vertical) and |
| * passes through both {@code (x1, y1)} and {@code (x1 + xDelta, y1 + yDelta)}. Includes |
| * assertions about all the public instance methods of {@link LinearTransformation} (on both |
| * {@code transformation} and its inverse). Since the transformation is expected to be diagonal, |
| * neither {@code xDelta} nor {@code yDelta} may be zero. |
| */ |
| static void assertDiagonalLinearTransformation( |
| LinearTransformation transformation, double x1, double y1, double xDelta, double yDelta) { |
| checkArgument(xDelta != 0.0); |
| checkArgument(yDelta != 0.0); |
| assertThat(transformation.isHorizontal()).isFalse(); |
| assertThat(transformation.isVertical()).isFalse(); |
| assertThat(transformation.inverse().isHorizontal()).isFalse(); |
| assertThat(transformation.inverse().isVertical()).isFalse(); |
| assertThat(transformation.transform(x1)).isWithin(ALLOWED_ERROR).of(y1); |
| assertThat(transformation.transform(x1 + xDelta)).isWithin(ALLOWED_ERROR).of(y1 + yDelta); |
| assertThat(transformation.inverse().transform(y1)).isWithin(ALLOWED_ERROR).of(x1); |
| assertThat(transformation.inverse().transform(y1 + yDelta)) |
| .isWithin(ALLOWED_ERROR) |
| .of(x1 + xDelta); |
| assertThat(transformation.slope()).isWithin(ALLOWED_ERROR).of(yDelta / xDelta); |
| assertThat(transformation.inverse().slope()).isWithin(ALLOWED_ERROR).of(xDelta / yDelta); |
| assertThat(transformation.inverse()).isSameAs(transformation.inverse()); |
| assertThat(transformation.inverse().inverse()).isSameAs(transformation); |
| } |
| |
| /** |
| * Asserts that {@code transformation} is horizontal with the given value of {@code y}. Includes |
| * assertions about all the public instance methods of {@link LinearTransformation}, including an |
| * assertion that {@link LinearTransformation#transform} and {@link LinearTransformation#slope} on |
| * its inverse throws as expected. |
| */ |
| static void assertHorizontalLinearTransformation(LinearTransformation transformation, double y) { |
| assertThat(transformation.isHorizontal()).isTrue(); |
| assertThat(transformation.isVertical()).isFalse(); |
| assertThat(transformation.inverse().isHorizontal()).isFalse(); |
| assertThat(transformation.inverse().isVertical()).isTrue(); |
| assertThat(transformation.transform(-1.0)).isWithin(ALLOWED_ERROR).of(y); |
| assertThat(transformation.transform(1.0)).isWithin(ALLOWED_ERROR).of(y); |
| try { |
| transformation.inverse().transform(0.0); |
| fail("Expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| assertThat(transformation.slope()).isWithin(ALLOWED_ERROR).of(0.0); |
| try { |
| transformation.inverse().slope(); |
| fail("Expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| assertThat(transformation.inverse()).isSameAs(transformation.inverse()); |
| assertThat(transformation.inverse().inverse()).isSameAs(transformation); |
| } |
| |
| /** |
| * Asserts that {@code transformation} is vertical with the given value of {@code x}. Includes |
| * assertions about all the public instance methods of {@link LinearTransformation}, including |
| * assertions that {@link LinearTransformation#slope} and {@link LinearTransformation#transform} |
| * throw as expected. |
| */ |
| static void assertVerticalLinearTransformation(LinearTransformation transformation, double x) { |
| assertThat(transformation.isHorizontal()).isFalse(); |
| assertThat(transformation.isVertical()).isTrue(); |
| assertThat(transformation.inverse().isHorizontal()).isTrue(); |
| assertThat(transformation.inverse().isVertical()).isFalse(); |
| try { |
| transformation.transform(0.0); |
| fail("Expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| assertThat(transformation.inverse().transform(-1.0)).isWithin(ALLOWED_ERROR).of(x); |
| assertThat(transformation.inverse().transform(1.0)).isWithin(ALLOWED_ERROR).of(x); |
| try { |
| transformation.slope(); |
| fail("Expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| assertThat(transformation.inverse().slope()).isWithin(ALLOWED_ERROR).of(0.0); |
| assertThat(transformation.inverse()).isSameAs(transformation.inverse()); |
| assertThat(transformation.inverse().inverse()).isSameAs(transformation); |
| } |
| |
| /** |
| * Asserts that {@code transformation} behaves as expected for {@link |
| * LinearTransformation#forNaN}. |
| */ |
| static void assertLinearTransformationNaN(LinearTransformation transformation) { |
| assertThat(transformation.isHorizontal()).isFalse(); |
| assertThat(transformation.isVertical()).isFalse(); |
| assertThat(transformation.slope()).isNaN(); |
| assertThat(transformation.transform(0.0)).isNaN(); |
| assertThat(transformation.inverse()).isSameAs(transformation); |
| } |
| |
| /** |
| * Creates a {@link PairedStats} from with the given lists of {@code x} and {@code y} values, |
| * which must be of the same size. |
| */ |
| static PairedStats createPairedStatsOf(List<Double> xValues, List<Double> yValues) { |
| return createFilledPairedStatsAccumulator(xValues, yValues).snapshot(); |
| } |
| |
| /** |
| * Creates a {@link PairedStatsAccumulator} filled with the given lists of {@code x} and {@code y} |
| * values, which must be of the same size. |
| */ |
| static PairedStatsAccumulator createFilledPairedStatsAccumulator( |
| List<Double> xValues, List<Double> yValues) { |
| checkArgument(xValues.size() == yValues.size()); |
| PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); |
| for (int index = 0; index < xValues.size(); index++) { |
| accumulator.add(xValues.get(index), yValues.get(index)); |
| } |
| return accumulator; |
| } |
| |
| /** |
| * Creates a {@link PairedStatsAccumulator} filled with the given lists of {@code x} and {@code y} |
| * values, which must be of the same size, added in groups of {@code partitionSize} using {@link |
| * PairedStatsAccumulator#addAll(PairedStats)}. |
| */ |
| static PairedStatsAccumulator createPartitionedFilledPairedStatsAccumulator( |
| List<Double> xValues, List<Double> yValues, int partitionSize) { |
| checkArgument(xValues.size() == yValues.size()); |
| checkArgument(partitionSize > 0); |
| PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); |
| List<List<Double>> xPartitions = Lists.partition(xValues, partitionSize); |
| List<List<Double>> yPartitions = Lists.partition(yValues, partitionSize); |
| for (int index = 0; index < xPartitions.size(); index++) { |
| accumulator.addAll(createPairedStatsOf(xPartitions.get(index), yPartitions.get(index))); |
| } |
| return accumulator; |
| } |
| |
| private StatsTesting() {} |
| } |