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 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 // TODO(cpovirk): Convince myself that this larger error makes sense. 44 static final double ALLOWED_ERROR = isAndroid() ? .25 : 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 of 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 // Stats instances: 216 217 static final Stats EMPTY_STATS_VARARGS = Stats.of(); 218 static final Stats EMPTY_STATS_ITERABLE = Stats.of(ImmutableList.<Double>of()); 219 static final Stats ONE_VALUE_STATS = Stats.of(ONE_VALUE); 220 static final Stats OTHER_ONE_VALUE_STATS = Stats.of(OTHER_ONE_VALUE); 221 static final Stats TWO_VALUES_STATS = Stats.of(TWO_VALUES); 222 static final Stats OTHER_TWO_VALUES_STATS = Stats.of(OTHER_TWO_VALUES); 223 static final Stats MANY_VALUES_STATS_VARARGS = Stats.of(1.1, -44.44, 33.33, 555.555, -2.2); 224 static final Stats MANY_VALUES_STATS_ITERABLE = Stats.of(MANY_VALUES); 225 static final Stats MANY_VALUES_STATS_ITERATOR = Stats.of(MANY_VALUES.iterator()); 226 static final Stats MANY_VALUES_STATS_SNAPSHOT = buildManyValuesStatsSnapshot(); 227 static final Stats LARGE_VALUES_STATS = Stats.of(LARGE_VALUES); 228 static final Stats OTHER_MANY_VALUES_STATS = Stats.of(OTHER_MANY_VALUES); 229 static final Stats INTEGER_MANY_VALUES_STATS_VARARGS = 230 Stats.of(Ints.toArray(INTEGER_MANY_VALUES)); 231 static final Stats INTEGER_MANY_VALUES_STATS_ITERABLE = Stats.of(INTEGER_MANY_VALUES); 232 static final Stats LARGE_INTEGER_VALUES_STATS = Stats.of(LARGE_INTEGER_VALUES); 233 static final Stats LONG_MANY_VALUES_STATS_ITERATOR = Stats.of(LONG_MANY_VALUES.iterator()); 234 static final Stats LONG_MANY_VALUES_STATS_SNAPSHOT = buildLongManyValuesStatsSnapshot(); 235 static final Stats LARGE_LONG_VALUES_STATS = Stats.of(LARGE_LONG_VALUES); 236 buildManyValuesStatsSnapshot()237 private static Stats buildManyValuesStatsSnapshot() { 238 StatsAccumulator accumulator = new StatsAccumulator(); 239 accumulator.addAll(MANY_VALUES); 240 Stats stats = accumulator.snapshot(); 241 accumulator.add(999.999); // should do nothing to the snapshot 242 return stats; 243 } 244 buildLongManyValuesStatsSnapshot()245 private static Stats buildLongManyValuesStatsSnapshot() { 246 StatsAccumulator accumulator = new StatsAccumulator(); 247 accumulator.addAll(LONG_MANY_VALUES); 248 return accumulator.snapshot(); 249 } 250 251 static final ImmutableList<Stats> ALL_STATS = 252 ImmutableList.of( 253 EMPTY_STATS_VARARGS, 254 EMPTY_STATS_ITERABLE, 255 ONE_VALUE_STATS, 256 OTHER_ONE_VALUE_STATS, 257 TWO_VALUES_STATS, 258 OTHER_TWO_VALUES_STATS, 259 MANY_VALUES_STATS_VARARGS, 260 MANY_VALUES_STATS_ITERABLE, 261 MANY_VALUES_STATS_ITERATOR, 262 MANY_VALUES_STATS_SNAPSHOT, 263 LARGE_VALUES_STATS, 264 OTHER_MANY_VALUES_STATS, 265 INTEGER_MANY_VALUES_STATS_VARARGS, 266 INTEGER_MANY_VALUES_STATS_ITERABLE, 267 LARGE_INTEGER_VALUES_STATS, 268 LONG_MANY_VALUES_STATS_ITERATOR, 269 LONG_MANY_VALUES_STATS_SNAPSHOT, 270 LARGE_LONG_VALUES_STATS); 271 272 // PairedStats instances: 273 274 static final PairedStats EMPTY_PAIRED_STATS = 275 createPairedStatsOf(ImmutableList.<Double>of(), ImmutableList.<Double>of()); 276 static final PairedStats ONE_VALUE_PAIRED_STATS = 277 createPairedStatsOf(ImmutableList.of(ONE_VALUE), ImmutableList.of(OTHER_ONE_VALUE)); 278 static final PairedStats TWO_VALUES_PAIRED_STATS = 279 createPairedStatsOf(TWO_VALUES, OTHER_TWO_VALUES); 280 static final PairedStats MANY_VALUES_PAIRED_STATS = buildManyValuesPairedStats(); 281 static final PairedStats DUPLICATE_MANY_VALUES_PAIRED_STATS = 282 createPairedStatsOf(MANY_VALUES, OTHER_MANY_VALUES); 283 static final PairedStats HORIZONTAL_VALUES_PAIRED_STATS = buildHorizontalValuesPairedStats(); 284 static final PairedStats VERTICAL_VALUES_PAIRED_STATS = buildVerticalValuesPairedStats(); 285 static final PairedStats CONSTANT_VALUES_PAIRED_STATS = buildConstantValuesPairedStats(); 286 buildManyValuesPairedStats()287 private static PairedStats buildManyValuesPairedStats() { 288 PairedStatsAccumulator accumulator = 289 createFilledPairedStatsAccumulator(MANY_VALUES, OTHER_MANY_VALUES); 290 PairedStats stats = accumulator.snapshot(); 291 accumulator.add(99.99, 9999.9999); // should do nothing to the snapshot 292 return stats; 293 } 294 buildHorizontalValuesPairedStats()295 private static PairedStats buildHorizontalValuesPairedStats() { 296 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 297 for (double x : MANY_VALUES) { 298 accumulator.add(x, OTHER_ONE_VALUE); 299 } 300 return accumulator.snapshot(); 301 } 302 buildVerticalValuesPairedStats()303 private static PairedStats buildVerticalValuesPairedStats() { 304 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 305 for (double y : OTHER_MANY_VALUES) { 306 accumulator.add(ONE_VALUE, y); 307 } 308 return accumulator.snapshot(); 309 } 310 buildConstantValuesPairedStats()311 private static PairedStats buildConstantValuesPairedStats() { 312 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 313 for (int i = 0; i < MANY_VALUES_COUNT; ++i) { 314 accumulator.add(ONE_VALUE, OTHER_ONE_VALUE); 315 } 316 return accumulator.snapshot(); 317 } 318 319 static final ImmutableList<PairedStats> ALL_PAIRED_STATS = 320 ImmutableList.of( 321 EMPTY_PAIRED_STATS, 322 ONE_VALUE_PAIRED_STATS, 323 TWO_VALUES_PAIRED_STATS, 324 MANY_VALUES_PAIRED_STATS, 325 DUPLICATE_MANY_VALUES_PAIRED_STATS, 326 HORIZONTAL_VALUES_PAIRED_STATS, 327 VERTICAL_VALUES_PAIRED_STATS, 328 CONSTANT_VALUES_PAIRED_STATS); 329 330 // Helper methods: 331 assertStatsApproxEqual(Stats expectedStats, Stats actualStats)332 static void assertStatsApproxEqual(Stats expectedStats, Stats actualStats) { 333 assertThat(actualStats.count()).isEqualTo(expectedStats.count()); 334 if (expectedStats.count() == 0) { 335 try { 336 actualStats.mean(); 337 fail("Expected IllegalStateException"); 338 } catch (IllegalStateException expected) { 339 } 340 try { 341 actualStats.populationVariance(); 342 fail("Expected IllegalStateException"); 343 } catch (IllegalStateException expected) { 344 } 345 try { 346 actualStats.min(); 347 fail("Expected IllegalStateException"); 348 } catch (IllegalStateException expected) { 349 } 350 try { 351 actualStats.max(); 352 fail("Expected IllegalStateException"); 353 } catch (IllegalStateException expected) { 354 } 355 } else if (expectedStats.count() == 1) { 356 assertThat(actualStats.mean()).isWithin(ALLOWED_ERROR).of(expectedStats.mean()); 357 assertThat(actualStats.populationVariance()).isEqualTo(0.0); 358 assertThat(actualStats.min()).isWithin(ALLOWED_ERROR).of(expectedStats.min()); 359 assertThat(actualStats.max()).isWithin(ALLOWED_ERROR).of(expectedStats.max()); 360 } else { 361 assertThat(actualStats.mean()).isWithin(ALLOWED_ERROR).of(expectedStats.mean()); 362 assertThat(actualStats.populationVariance()) 363 .isWithin(ALLOWED_ERROR) 364 .of(expectedStats.populationVariance()); 365 assertThat(actualStats.min()).isWithin(ALLOWED_ERROR).of(expectedStats.min()); 366 assertThat(actualStats.max()).isWithin(ALLOWED_ERROR).of(expectedStats.max()); 367 } 368 } 369 370 /** 371 * Asserts that {@code transformation} is diagonal (i.e. neither horizontal nor vertical) and 372 * passes through both {@code (x1, y1)} and {@code (x1 + xDelta, y1 + yDelta)}. Includes 373 * assertions about all the public instance methods of {@link LinearTransformation} (on both 374 * {@code transformation} and its inverse). Since the transformation is expected to be diagonal, 375 * neither {@code xDelta} nor {@code yDelta} may be zero. 376 */ assertDiagonalLinearTransformation( LinearTransformation transformation, double x1, double y1, double xDelta, double yDelta)377 static void assertDiagonalLinearTransformation( 378 LinearTransformation transformation, double x1, double y1, double xDelta, double yDelta) { 379 checkArgument(xDelta != 0.0); 380 checkArgument(yDelta != 0.0); 381 assertThat(transformation.isHorizontal()).isFalse(); 382 assertThat(transformation.isVertical()).isFalse(); 383 assertThat(transformation.inverse().isHorizontal()).isFalse(); 384 assertThat(transformation.inverse().isVertical()).isFalse(); 385 assertThat(transformation.transform(x1)).isWithin(ALLOWED_ERROR).of(y1); 386 assertThat(transformation.transform(x1 + xDelta)).isWithin(ALLOWED_ERROR).of(y1 + yDelta); 387 assertThat(transformation.inverse().transform(y1)).isWithin(ALLOWED_ERROR).of(x1); 388 assertThat(transformation.inverse().transform(y1 + yDelta)) 389 .isWithin(ALLOWED_ERROR) 390 .of(x1 + xDelta); 391 assertThat(transformation.slope()).isWithin(ALLOWED_ERROR).of(yDelta / xDelta); 392 assertThat(transformation.inverse().slope()).isWithin(ALLOWED_ERROR).of(xDelta / yDelta); 393 assertThat(transformation.inverse()).isSameInstanceAs(transformation.inverse()); 394 assertThat(transformation.inverse().inverse()).isSameInstanceAs(transformation); 395 } 396 397 /** 398 * Asserts that {@code transformation} is horizontal with the given value of {@code y}. Includes 399 * assertions about all the public instance methods of {@link LinearTransformation}, including an 400 * assertion that {@link LinearTransformation#transform} and {@link LinearTransformation#slope} on 401 * its inverse throws as expected. 402 */ assertHorizontalLinearTransformation(LinearTransformation transformation, double y)403 static void assertHorizontalLinearTransformation(LinearTransformation transformation, double y) { 404 assertThat(transformation.isHorizontal()).isTrue(); 405 assertThat(transformation.isVertical()).isFalse(); 406 assertThat(transformation.inverse().isHorizontal()).isFalse(); 407 assertThat(transformation.inverse().isVertical()).isTrue(); 408 assertThat(transformation.transform(-1.0)).isWithin(ALLOWED_ERROR).of(y); 409 assertThat(transformation.transform(1.0)).isWithin(ALLOWED_ERROR).of(y); 410 try { 411 transformation.inverse().transform(0.0); 412 fail("Expected IllegalStateException"); 413 } catch (IllegalStateException expected) { 414 } 415 assertThat(transformation.slope()).isWithin(ALLOWED_ERROR).of(0.0); 416 try { 417 transformation.inverse().slope(); 418 fail("Expected IllegalStateException"); 419 } catch (IllegalStateException expected) { 420 } 421 assertThat(transformation.inverse()).isSameInstanceAs(transformation.inverse()); 422 assertThat(transformation.inverse().inverse()).isSameInstanceAs(transformation); 423 } 424 425 /** 426 * Asserts that {@code transformation} is vertical with the given value of {@code x}. Includes 427 * assertions about all the public instance methods of {@link LinearTransformation}, including 428 * assertions that {@link LinearTransformation#slope} and {@link LinearTransformation#transform} 429 * throw as expected. 430 */ assertVerticalLinearTransformation(LinearTransformation transformation, double x)431 static void assertVerticalLinearTransformation(LinearTransformation transformation, double x) { 432 assertThat(transformation.isHorizontal()).isFalse(); 433 assertThat(transformation.isVertical()).isTrue(); 434 assertThat(transformation.inverse().isHorizontal()).isTrue(); 435 assertThat(transformation.inverse().isVertical()).isFalse(); 436 try { 437 transformation.transform(0.0); 438 fail("Expected IllegalStateException"); 439 } catch (IllegalStateException expected) { 440 } 441 assertThat(transformation.inverse().transform(-1.0)).isWithin(ALLOWED_ERROR).of(x); 442 assertThat(transformation.inverse().transform(1.0)).isWithin(ALLOWED_ERROR).of(x); 443 try { 444 transformation.slope(); 445 fail("Expected IllegalStateException"); 446 } catch (IllegalStateException expected) { 447 } 448 assertThat(transformation.inverse().slope()).isWithin(ALLOWED_ERROR).of(0.0); 449 assertThat(transformation.inverse()).isSameInstanceAs(transformation.inverse()); 450 assertThat(transformation.inverse().inverse()).isSameInstanceAs(transformation); 451 } 452 453 /** 454 * Asserts that {@code transformation} behaves as expected for {@link 455 * LinearTransformation#forNaN}. 456 */ assertLinearTransformationNaN(LinearTransformation transformation)457 static void assertLinearTransformationNaN(LinearTransformation transformation) { 458 assertThat(transformation.isHorizontal()).isFalse(); 459 assertThat(transformation.isVertical()).isFalse(); 460 assertThat(transformation.slope()).isNaN(); 461 assertThat(transformation.transform(0.0)).isNaN(); 462 assertThat(transformation.inverse()).isSameInstanceAs(transformation); 463 } 464 465 /** 466 * Creates a {@link PairedStats} from with the given lists of {@code x} and {@code y} values, 467 * which must be of the same size. 468 */ createPairedStatsOf(List<Double> xValues, List<Double> yValues)469 static PairedStats createPairedStatsOf(List<Double> xValues, List<Double> yValues) { 470 return createFilledPairedStatsAccumulator(xValues, yValues).snapshot(); 471 } 472 473 /** 474 * Creates a {@link PairedStatsAccumulator} filled with the given lists of {@code x} and {@code y} 475 * values, which must be of the same size. 476 */ createFilledPairedStatsAccumulator( List<Double> xValues, List<Double> yValues)477 static PairedStatsAccumulator createFilledPairedStatsAccumulator( 478 List<Double> xValues, List<Double> yValues) { 479 checkArgument(xValues.size() == yValues.size()); 480 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 481 for (int index = 0; index < xValues.size(); index++) { 482 accumulator.add(xValues.get(index), yValues.get(index)); 483 } 484 return accumulator; 485 } 486 487 /** 488 * Creates a {@link PairedStatsAccumulator} filled with the given lists of {@code x} and {@code y} 489 * values, which must be of the same size, added in groups of {@code partitionSize} using {@link 490 * PairedStatsAccumulator#addAll(PairedStats)}. 491 */ createPartitionedFilledPairedStatsAccumulator( List<Double> xValues, List<Double> yValues, int partitionSize)492 static PairedStatsAccumulator createPartitionedFilledPairedStatsAccumulator( 493 List<Double> xValues, List<Double> yValues, int partitionSize) { 494 checkArgument(xValues.size() == yValues.size()); 495 checkArgument(partitionSize > 0); 496 PairedStatsAccumulator accumulator = new PairedStatsAccumulator(); 497 List<List<Double>> xPartitions = Lists.partition(xValues, partitionSize); 498 List<List<Double>> yPartitions = Lists.partition(yValues, partitionSize); 499 for (int index = 0; index < xPartitions.size(); index++) { 500 accumulator.addAll(createPairedStatsOf(xPartitions.get(index), yPartitions.get(index))); 501 } 502 return accumulator; 503 } 504 isAndroid()505 private static boolean isAndroid() { 506 return checkNotNull(System.getProperty("java.runtime.name", "")).contains("Android"); 507 } 508 StatsTesting()509 private StatsTesting() {} 510 } 511