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