1 /* 2 * Copyright (C) 2013 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.math; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 import static com.google.common.truth.Truth.assertThat; 21 import static java.lang.Double.NEGATIVE_INFINITY; 22 import static java.lang.Double.NaN; 23 import static java.lang.Double.POSITIVE_INFINITY; 24 import static org.junit.Assert.fail; 25 26 import com.google.common.base.Predicates; 27 import com.google.common.collect.ImmutableList; 28 import com.google.common.collect.Iterables; 29 import com.google.common.collect.Lists; 30 import com.google.common.primitives.Doubles; 31 import com.google.common.primitives.Ints; 32 import java.math.BigInteger; 33 import java.util.List; 34 35 /** 36 * Inputs, expected outputs, and helper methods for tests of {@link StatsAccumulator}, {@link 37 * Stats}, {@link PairedStatsAccumulator}, and {@link PairedStats}. 38 * 39 * @author Pete Gillin 40 */ 41 class StatsTesting { 42 43 static final double ALLOWED_ERROR = 1e-10; 44 45 // Inputs and their statistics: 46 47 static final double ONE_VALUE = 12.34; 48 49 static final double OTHER_ONE_VALUE = -56.78; 50 51 static final ImmutableList<Double> TWO_VALUES = ImmutableList.of(12.34, -56.78); 52 static final double TWO_VALUES_MEAN = (12.34 - 56.78) / 2; 53 static final double TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS = 54 (12.34 - TWO_VALUES_MEAN) * (12.34 - TWO_VALUES_MEAN) 55 + (-56.78 - TWO_VALUES_MEAN) * (-56.78 - TWO_VALUES_MEAN); 56 static final double TWO_VALUES_MAX = 12.34; 57 static final double TWO_VALUES_MIN = -56.78; 58 59 static final ImmutableList<Double> OTHER_TWO_VALUES = ImmutableList.of(123.456, -789.012); 60 static final double OTHER_TWO_VALUES_MEAN = (123.456 - 789.012) / 2; 61 static final double TWO_VALUES_SUM_OF_PRODUCTS_OF_DELTAS = 62 (12.34 - TWO_VALUES_MEAN) * (123.456 - OTHER_TWO_VALUES_MEAN) 63 + (-56.78 - TWO_VALUES_MEAN) * (-789.012 - OTHER_TWO_VALUES_MEAN); 64 65 /** 66 * Helper class for testing with non-finite values. {@link #ALL_MANY_VALUES} gives a number 67 * instances with many combinations of finite and non-finite values. All have {@link 68 * #MANY_VALUES_COUNT} values. If all the values are finite then the mean is {@link 69 * #MANY_VALUES_MEAN} and the sum-of-squares-of-deltas is {@link 70 * #MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS}. The smallest and largest finite values are always 71 * {@link #MANY_VALUES_MIN} and {@link #MANY_VALUES_MAX}, although setting non-finite values will 72 * change the true min and max. 73 */ 74 static class ManyValues { 75 76 private final ImmutableList<Double> values; 77 ManyValues(double[] values)78 ManyValues(double[] values) { 79 this.values = ImmutableList.copyOf(Doubles.asList(values)); 80 } 81 asIterable()82 ImmutableList<Double> asIterable() { 83 return values; 84 } 85 asArray()86 double[] asArray() { 87 return Doubles.toArray(values); 88 } 89 hasAnyPositiveInfinity()90 boolean hasAnyPositiveInfinity() { 91 return Iterables.any(values, Predicates.equalTo(POSITIVE_INFINITY)); 92 } 93 hasAnyNegativeInfinity()94 boolean hasAnyNegativeInfinity() { 95 return Iterables.any(values, Predicates.equalTo(NEGATIVE_INFINITY)); 96 } 97 hasAnyNaN()98 boolean hasAnyNaN() { 99 return Iterables.any(values, Predicates.equalTo(NaN)); 100 } 101 hasAnyNonFinite()102 boolean hasAnyNonFinite() { 103 return hasAnyPositiveInfinity() || hasAnyNegativeInfinity() || hasAnyNaN(); 104 } 105 106 @Override toString()107 public String toString() { 108 return values.toString(); 109 } 110 createAll()111 private static ImmutableList<ManyValues> createAll() { 112 ImmutableList.Builder<ManyValues> builder = ImmutableList.builder(); 113 double[] values = new double[5]; 114 for (double first : ImmutableList.of(1.1, POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN)) { 115 values[0] = first; 116 values[1] = -44.44; 117 for (double third : ImmutableList.of(33.33, POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN)) { 118 values[2] = third; 119 values[3] = 555.555; 120 for (double fifth : ImmutableList.of(-2.2, POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN)) { 121 values[4] = fifth; 122 builder.add(new ManyValues(values)); 123 } 124 } 125 } 126 return builder.build(); 127 } 128 } 129 130 static final ImmutableList<ManyValues> ALL_MANY_VALUES = ManyValues.createAll(); 131 132 static final ImmutableList<Double> MANY_VALUES = 133 ImmutableList.of(1.1, -44.44, 33.33, 555.555, -2.2); 134 static final int MANY_VALUES_COUNT = 5; 135 static final double MANY_VALUES_MEAN = (1.1 - 44.44 + 33.33 + 555.555 - 2.2) / 5; 136 static final double MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS = 137 (1.1 - MANY_VALUES_MEAN) * (1.1 - MANY_VALUES_MEAN) 138 + (-44.44 - MANY_VALUES_MEAN) * (-44.44 - MANY_VALUES_MEAN) 139 + (33.33 - MANY_VALUES_MEAN) * (33.33 - MANY_VALUES_MEAN) 140 + (555.555 - MANY_VALUES_MEAN) * (555.555 - MANY_VALUES_MEAN) 141 + (-2.2 - MANY_VALUES_MEAN) * (-2.2 - MANY_VALUES_MEAN); 142 static final double MANY_VALUES_MAX = 555.555; 143 static final double MANY_VALUES_MIN = -44.44; 144 145 // Doubles which will overflow if summed: 146 static final double[] LARGE_VALUES = {Double.MAX_VALUE, Double.MAX_VALUE / 2.0}; 147 static final double LARGE_VALUES_MEAN = 0.75 * Double.MAX_VALUE; 148 149 static final ImmutableList<Double> OTHER_MANY_VALUES = 150 ImmutableList.of(1.11, -2.22, 33.3333, -44.4444, 555.555555); 151 static final int OTHER_MANY_VALUES_COUNT = 5; 152 static final double OTHER_MANY_VALUES_MEAN = (1.11 - 2.22 + 33.3333 - 44.4444 + 555.555555) / 5; 153 154 static final double MANY_VALUES_SUM_OF_PRODUCTS_OF_DELTAS = 155 (1.1 - MANY_VALUES_MEAN) * (1.11 - OTHER_MANY_VALUES_MEAN) 156 + (-44.44 - MANY_VALUES_MEAN) * (-2.22 - OTHER_MANY_VALUES_MEAN) 157 + (33.33 - MANY_VALUES_MEAN) * (33.3333 - OTHER_MANY_VALUES_MEAN) 158 + (555.555 - MANY_VALUES_MEAN) * (-44.4444 - OTHER_MANY_VALUES_MEAN) 159 + (-2.2 - MANY_VALUES_MEAN) * (555.555555 - OTHER_MANY_VALUES_MEAN); 160 161 static final ImmutableList<Integer> INTEGER_MANY_VALUES = 162 ImmutableList.of(11, -22, 3333, -4444, 555555); 163 static final int INTEGER_MANY_VALUES_COUNT = 5; 164 static final double INTEGER_MANY_VALUES_MEAN = (11.0 - 22.0 + 3333.0 - 4444.0 + 555555.0) / 5; 165 static final double INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS = 166 (11.0 - INTEGER_MANY_VALUES_MEAN) * (11.0 - INTEGER_MANY_VALUES_MEAN) 167 + (-22.0 - INTEGER_MANY_VALUES_MEAN) * (-22.0 - INTEGER_MANY_VALUES_MEAN) 168 + (3333.0 - INTEGER_MANY_VALUES_MEAN) * (3333.0 - INTEGER_MANY_VALUES_MEAN) 169 + (-4444.0 - INTEGER_MANY_VALUES_MEAN) * (-4444.0 - INTEGER_MANY_VALUES_MEAN) 170 + (555555.0 - INTEGER_MANY_VALUES_MEAN) * (555555.0 - INTEGER_MANY_VALUES_MEAN); 171 static final double INTEGER_MANY_VALUES_MAX = 555555.0; 172 static final double INTEGER_MANY_VALUES_MIN = -4444.0; 173 174 // Integers which will overflow if summed (using integer arithmetic): 175 static final int[] LARGE_INTEGER_VALUES = {Integer.MAX_VALUE, Integer.MAX_VALUE / 2}; 176 static final double LARGE_INTEGER_VALUES_MEAN = 177 BigInteger.valueOf(Integer.MAX_VALUE) 178 .multiply(BigInteger.valueOf(3L)) 179 .divide(BigInteger.valueOf(4L)) 180 .doubleValue(); 181 static final double LARGE_INTEGER_VALUES_POPULATION_VARIANCE = 182 BigInteger.valueOf(Integer.MAX_VALUE) 183 .multiply(BigInteger.valueOf(Integer.MAX_VALUE)) 184 .divide(BigInteger.valueOf(16L)) 185 .doubleValue(); 186 187 static final ImmutableList<Long> LONG_MANY_VALUES = 188 ImmutableList.of(1111L, -2222L, 33333333L, -44444444L, 5555555555L); 189 static final int LONG_MANY_VALUES_COUNT = 5; 190 static final double LONG_MANY_VALUES_MEAN = 191 (1111.0 - 2222.0 + 33333333.0 - 44444444.0 + 5555555555.0) / 5; 192 static final double LONG_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS = 193 (1111.0 - LONG_MANY_VALUES_MEAN) * (1111.0 - LONG_MANY_VALUES_MEAN) 194 + (-2222.0 - LONG_MANY_VALUES_MEAN) * (-2222.0 - LONG_MANY_VALUES_MEAN) 195 + (33333333.0 - LONG_MANY_VALUES_MEAN) * (33333333.0 - LONG_MANY_VALUES_MEAN) 196 + (-44444444.0 - LONG_MANY_VALUES_MEAN) * (-44444444.0 - LONG_MANY_VALUES_MEAN) 197 + (5555555555.0 - LONG_MANY_VALUES_MEAN) * (5555555555.0 - LONG_MANY_VALUES_MEAN); 198 static final double LONG_MANY_VALUES_MAX = 5555555555.0; 199 static final double LONG_MANY_VALUES_MIN = -44444444.0; 200 201 // Longs which will overflow if summed (using long arithmetic): 202 static final long[] LARGE_LONG_VALUES = {Long.MAX_VALUE, Long.MAX_VALUE / 2}; 203 static final double LARGE_LONG_VALUES_MEAN = 204 BigInteger.valueOf(Long.MAX_VALUE) 205 .multiply(BigInteger.valueOf(3L)) 206 .divide(BigInteger.valueOf(4L)) 207 .doubleValue(); 208 static final double LARGE_LONG_VALUES_POPULATION_VARIANCE = 209 BigInteger.valueOf(Long.MAX_VALUE) 210 .multiply(BigInteger.valueOf(Long.MAX_VALUE)) 211 .divide(BigInteger.valueOf(16L)) 212 .doubleValue(); 213 214 // Stats instances: 215 216 static final Stats EMPTY_STATS_VARARGS = Stats.of(); 217 static final Stats EMPTY_STATS_ITERABLE = Stats.of(ImmutableList.<Double>of()); 218 static final Stats ONE_VALUE_STATS = Stats.of(ONE_VALUE); 219 static final Stats OTHER_ONE_VALUE_STATS = Stats.of(OTHER_ONE_VALUE); 220 static final Stats TWO_VALUES_STATS = Stats.of(TWO_VALUES); 221 static final Stats OTHER_TWO_VALUES_STATS = Stats.of(OTHER_TWO_VALUES); 222 static final Stats MANY_VALUES_STATS_VARARGS = Stats.of(1.1, -44.44, 33.33, 555.555, -2.2); 223 static final Stats MANY_VALUES_STATS_ITERABLE = Stats.of(MANY_VALUES); 224 static final Stats MANY_VALUES_STATS_ITERATOR = Stats.of(MANY_VALUES.iterator()); 225 static final Stats MANY_VALUES_STATS_SNAPSHOT = buildManyValuesStatsSnapshot(); 226 static final Stats LARGE_VALUES_STATS = Stats.of(LARGE_VALUES); 227 static final Stats OTHER_MANY_VALUES_STATS = Stats.of(OTHER_MANY_VALUES); 228 static final Stats INTEGER_MANY_VALUES_STATS_VARARGS = 229 Stats.of(Ints.toArray(INTEGER_MANY_VALUES)); 230 static final Stats INTEGER_MANY_VALUES_STATS_ITERABLE = Stats.of(INTEGER_MANY_VALUES); 231 static final Stats LARGE_INTEGER_VALUES_STATS = Stats.of(LARGE_INTEGER_VALUES); 232 static final Stats LONG_MANY_VALUES_STATS_ITERATOR = Stats.of(LONG_MANY_VALUES.iterator()); 233 static final Stats LONG_MANY_VALUES_STATS_SNAPSHOT = buildLongManyValuesStatsSnapshot(); 234 static final Stats LARGE_LONG_VALUES_STATS = Stats.of(LARGE_LONG_VALUES); 235 buildManyValuesStatsSnapshot()236 private static Stats buildManyValuesStatsSnapshot() { 237 StatsAccumulator accumulator = new StatsAccumulator(); 238 accumulator.addAll(MANY_VALUES); 239 Stats stats = accumulator.snapshot(); 240 accumulator.add(999.999); // should do nothing to the snapshot 241 return stats; 242 } 243 buildLongManyValuesStatsSnapshot()244 private static Stats buildLongManyValuesStatsSnapshot() { 245 StatsAccumulator accumulator = new StatsAccumulator(); 246 accumulator.addAll(LONG_MANY_VALUES); 247 return accumulator.snapshot(); 248 } 249 250 static final ImmutableList<Stats> ALL_STATS = 251 ImmutableList.of( 252 EMPTY_STATS_VARARGS, 253 EMPTY_STATS_ITERABLE, 254 ONE_VALUE_STATS, 255 OTHER_ONE_VALUE_STATS, 256 TWO_VALUES_STATS, 257 OTHER_TWO_VALUES_STATS, 258 MANY_VALUES_STATS_VARARGS, 259 MANY_VALUES_STATS_ITERABLE, 260 MANY_VALUES_STATS_ITERATOR, 261 MANY_VALUES_STATS_SNAPSHOT, 262 LARGE_VALUES_STATS, 263 OTHER_MANY_VALUES_STATS, 264 INTEGER_MANY_VALUES_STATS_VARARGS, 265 INTEGER_MANY_VALUES_STATS_ITERABLE, 266 LARGE_INTEGER_VALUES_STATS, 267 LONG_MANY_VALUES_STATS_ITERATOR, 268 LONG_MANY_VALUES_STATS_SNAPSHOT, 269 LARGE_LONG_VALUES_STATS); 270 271 // PairedStats instances: 272 273 static final PairedStats EMPTY_PAIRED_STATS = 274 createPairedStatsOf(ImmutableList.<Double>of(), ImmutableList.<Double>of()); 275 static final PairedStats ONE_VALUE_PAIRED_STATS = 276 createPairedStatsOf(ImmutableList.of(ONE_VALUE), ImmutableList.of(OTHER_ONE_VALUE)); 277 static final PairedStats TWO_VALUES_PAIRED_STATS = 278 createPairedStatsOf(TWO_VALUES, OTHER_TWO_VALUES); 279 static final PairedStats MANY_VALUES_PAIRED_STATS = buildManyValuesPairedStats(); 280 static final PairedStats DUPLICATE_MANY_VALUES_PAIRED_STATS = 281 createPairedStatsOf(MANY_VALUES, OTHER_MANY_VALUES); 282 static final PairedStats HORIZONTAL_VALUES_PAIRED_STATS = buildHorizontalValuesPairedStats(); 283 static final PairedStats VERTICAL_VALUES_PAIRED_STATS = buildVerticalValuesPairedStats(); 284 static final PairedStats CONSTANT_VALUES_PAIRED_STATS = buildConstantValuesPairedStats(); 285 buildManyValuesPairedStats()286 private static PairedStats buildManyValuesPairedStats() { 287 PairedStatsAccumulator accumulator = 288 createFilledPairedStatsAccumulator(MANY_VALUES, OTHER_MANY_VALUES); 289 PairedStats stats = accumulator.snapshot(); 290 accumulator.add(99.99, 9999.9999); // should do nothing to the snapshot 291 return stats; 292 } 293 buildHorizontalValuesPairedStats()294 private static PairedStats buildHorizontalValuesPairedStats() { 295 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 296 for (double x : MANY_VALUES) { 297 accumulator.add(x, OTHER_ONE_VALUE); 298 } 299 return accumulator.snapshot(); 300 } 301 buildVerticalValuesPairedStats()302 private static PairedStats buildVerticalValuesPairedStats() { 303 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 304 for (double y : OTHER_MANY_VALUES) { 305 accumulator.add(ONE_VALUE, y); 306 } 307 return accumulator.snapshot(); 308 } 309 buildConstantValuesPairedStats()310 private static PairedStats buildConstantValuesPairedStats() { 311 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 312 for (int i = 0; i < MANY_VALUES_COUNT; ++i) { 313 accumulator.add(ONE_VALUE, OTHER_ONE_VALUE); 314 } 315 return accumulator.snapshot(); 316 } 317 318 static final ImmutableList<PairedStats> ALL_PAIRED_STATS = 319 ImmutableList.of( 320 EMPTY_PAIRED_STATS, 321 ONE_VALUE_PAIRED_STATS, 322 TWO_VALUES_PAIRED_STATS, 323 MANY_VALUES_PAIRED_STATS, 324 DUPLICATE_MANY_VALUES_PAIRED_STATS, 325 HORIZONTAL_VALUES_PAIRED_STATS, 326 VERTICAL_VALUES_PAIRED_STATS, 327 CONSTANT_VALUES_PAIRED_STATS); 328 329 // Helper methods: 330 assertStatsApproxEqual(Stats expectedStats, Stats actualStats)331 static void assertStatsApproxEqual(Stats expectedStats, Stats actualStats) { 332 assertThat(actualStats.count()).isEqualTo(expectedStats.count()); 333 if (expectedStats.count() == 0) { 334 try { 335 actualStats.mean(); 336 fail("Expected IllegalStateException"); 337 } catch (IllegalStateException expected) { 338 } 339 try { 340 actualStats.populationVariance(); 341 fail("Expected IllegalStateException"); 342 } catch (IllegalStateException expected) { 343 } 344 try { 345 actualStats.min(); 346 fail("Expected IllegalStateException"); 347 } catch (IllegalStateException expected) { 348 } 349 try { 350 actualStats.max(); 351 fail("Expected IllegalStateException"); 352 } catch (IllegalStateException expected) { 353 } 354 } else if (expectedStats.count() == 1) { 355 assertThat(actualStats.mean()).isWithin(ALLOWED_ERROR).of(expectedStats.mean()); 356 assertThat(actualStats.populationVariance()).isWithin(0.0).of(0.0); 357 assertThat(actualStats.min()).isWithin(ALLOWED_ERROR).of(expectedStats.min()); 358 assertThat(actualStats.max()).isWithin(ALLOWED_ERROR).of(expectedStats.max()); 359 } else { 360 assertThat(actualStats.mean()).isWithin(ALLOWED_ERROR).of(expectedStats.mean()); 361 assertThat(actualStats.populationVariance()) 362 .isWithin(ALLOWED_ERROR) 363 .of(expectedStats.populationVariance()); 364 assertThat(actualStats.min()).isWithin(ALLOWED_ERROR).of(expectedStats.min()); 365 assertThat(actualStats.max()).isWithin(ALLOWED_ERROR).of(expectedStats.max()); 366 } 367 } 368 369 /** 370 * Asserts that {@code transformation} is diagonal (i.e. neither horizontal or vertical) and 371 * passes through both {@code (x1, y1)} and {@code (x1 + xDelta, y1 + yDelta)}. Includes 372 * assertions about all the public instance methods of {@link LinearTransformation} (on both 373 * {@code transformation} and its inverse). Since the transformation is expected to be diagonal, 374 * neither {@code xDelta} nor {@code yDelta} may be zero. 375 */ assertDiagonalLinearTransformation( LinearTransformation transformation, double x1, double y1, double xDelta, double yDelta)376 static void assertDiagonalLinearTransformation( 377 LinearTransformation transformation, double x1, double y1, double xDelta, double yDelta) { 378 checkArgument(xDelta != 0.0); 379 checkArgument(yDelta != 0.0); 380 assertThat(transformation.isHorizontal()).isFalse(); 381 assertThat(transformation.isVertical()).isFalse(); 382 assertThat(transformation.inverse().isHorizontal()).isFalse(); 383 assertThat(transformation.inverse().isVertical()).isFalse(); 384 assertThat(transformation.transform(x1)).isWithin(ALLOWED_ERROR).of(y1); 385 assertThat(transformation.transform(x1 + xDelta)).isWithin(ALLOWED_ERROR).of(y1 + yDelta); 386 assertThat(transformation.inverse().transform(y1)).isWithin(ALLOWED_ERROR).of(x1); 387 assertThat(transformation.inverse().transform(y1 + yDelta)) 388 .isWithin(ALLOWED_ERROR) 389 .of(x1 + xDelta); 390 assertThat(transformation.slope()).isWithin(ALLOWED_ERROR).of(yDelta / xDelta); 391 assertThat(transformation.inverse().slope()).isWithin(ALLOWED_ERROR).of(xDelta / yDelta); 392 assertThat(transformation.inverse()).isSameInstanceAs(transformation.inverse()); 393 assertThat(transformation.inverse().inverse()).isSameInstanceAs(transformation); 394 } 395 396 /** 397 * Asserts that {@code transformation} is horizontal with the given value of {@code y}. Includes 398 * assertions about all the public instance methods of {@link LinearTransformation}, including an 399 * assertion that {@link LinearTransformation#transform} and {@link LinearTransformation#slope} on 400 * its inverse throws as expected. 401 */ assertHorizontalLinearTransformation(LinearTransformation transformation, double y)402 static void assertHorizontalLinearTransformation(LinearTransformation transformation, double y) { 403 assertThat(transformation.isHorizontal()).isTrue(); 404 assertThat(transformation.isVertical()).isFalse(); 405 assertThat(transformation.inverse().isHorizontal()).isFalse(); 406 assertThat(transformation.inverse().isVertical()).isTrue(); 407 assertThat(transformation.transform(-1.0)).isWithin(ALLOWED_ERROR).of(y); 408 assertThat(transformation.transform(1.0)).isWithin(ALLOWED_ERROR).of(y); 409 try { 410 transformation.inverse().transform(0.0); 411 fail("Expected IllegalStateException"); 412 } catch (IllegalStateException expected) { 413 } 414 assertThat(transformation.slope()).isWithin(ALLOWED_ERROR).of(0.0); 415 try { 416 transformation.inverse().slope(); 417 fail("Expected IllegalStateException"); 418 } catch (IllegalStateException expected) { 419 } 420 assertThat(transformation.inverse()).isSameInstanceAs(transformation.inverse()); 421 assertThat(transformation.inverse().inverse()).isSameInstanceAs(transformation); 422 } 423 424 /** 425 * Asserts that {@code transformation} is vertical with the given value of {@code x}. Includes 426 * assertions about all the public instance methods of {@link LinearTransformation}, including 427 * assertions that {@link LinearTransformation#slope} and {@link LinearTransformation#transform} 428 * throw as expected. 429 */ assertVerticalLinearTransformation(LinearTransformation transformation, double x)430 static void assertVerticalLinearTransformation(LinearTransformation transformation, double x) { 431 assertThat(transformation.isHorizontal()).isFalse(); 432 assertThat(transformation.isVertical()).isTrue(); 433 assertThat(transformation.inverse().isHorizontal()).isTrue(); 434 assertThat(transformation.inverse().isVertical()).isFalse(); 435 try { 436 transformation.transform(0.0); 437 fail("Expected IllegalStateException"); 438 } catch (IllegalStateException expected) { 439 } 440 assertThat(transformation.inverse().transform(-1.0)).isWithin(ALLOWED_ERROR).of(x); 441 assertThat(transformation.inverse().transform(1.0)).isWithin(ALLOWED_ERROR).of(x); 442 try { 443 transformation.slope(); 444 fail("Expected IllegalStateException"); 445 } catch (IllegalStateException expected) { 446 } 447 assertThat(transformation.inverse().slope()).isWithin(ALLOWED_ERROR).of(0.0); 448 assertThat(transformation.inverse()).isSameInstanceAs(transformation.inverse()); 449 assertThat(transformation.inverse().inverse()).isSameInstanceAs(transformation); 450 } 451 452 /** 453 * Asserts that {@code transformation} behaves as expected for {@link 454 * LinearTransformation#forNaN}. 455 */ assertLinearTransformationNaN(LinearTransformation transformation)456 static void assertLinearTransformationNaN(LinearTransformation transformation) { 457 assertThat(transformation.isHorizontal()).isFalse(); 458 assertThat(transformation.isVertical()).isFalse(); 459 assertThat(transformation.slope()).isNaN(); 460 assertThat(transformation.transform(0.0)).isNaN(); 461 assertThat(transformation.inverse()).isSameInstanceAs(transformation); 462 } 463 464 /** 465 * Creates a {@link PairedStats} from with the given lists of {@code x} and {@code y} values, 466 * which must be of the same size. 467 */ createPairedStatsOf(List<Double> xValues, List<Double> yValues)468 static PairedStats createPairedStatsOf(List<Double> xValues, List<Double> yValues) { 469 return createFilledPairedStatsAccumulator(xValues, yValues).snapshot(); 470 } 471 472 /** 473 * Creates a {@link PairedStatsAccumulator} filled with the given lists of {@code x} and {@code y} 474 * values, which must be of the same size. 475 */ createFilledPairedStatsAccumulator( List<Double> xValues, List<Double> yValues)476 static PairedStatsAccumulator createFilledPairedStatsAccumulator( 477 List<Double> xValues, List<Double> yValues) { 478 checkArgument(xValues.size() == yValues.size()); 479 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 480 for (int index = 0; index < xValues.size(); index++) { 481 accumulator.add(xValues.get(index), yValues.get(index)); 482 } 483 return accumulator; 484 } 485 486 /** 487 * Creates a {@link PairedStatsAccumulator} filled with the given lists of {@code x} and {@code y} 488 * values, which must be of the same size, added in groups of {@code partitionSize} using {@link 489 * PairedStatsAccumulator#addAll(PairedStats)}. 490 */ createPartitionedFilledPairedStatsAccumulator( List<Double> xValues, List<Double> yValues, int partitionSize)491 static PairedStatsAccumulator createPartitionedFilledPairedStatsAccumulator( 492 List<Double> xValues, List<Double> yValues, int partitionSize) { 493 checkArgument(xValues.size() == yValues.size()); 494 checkArgument(partitionSize > 0); 495 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 496 List<List<Double>> xPartitions = Lists.partition(xValues, partitionSize); 497 List<List<Double>> yPartitions = Lists.partition(yValues, partitionSize); 498 for (int index = 0; index < xPartitions.size(); index++) { 499 accumulator.addAll(createPairedStatsOf(xPartitions.get(index), yPartitions.get(index))); 500 } 501 return accumulator; 502 } 503 StatsTesting()504 private StatsTesting() {} 505 } 506