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