1 /* 2 * Copyright (C) 2011 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.math.MathTesting.ALL_DOUBLE_CANDIDATES; 20 import static com.google.common.math.MathTesting.ALL_ROUNDING_MODES; 21 import static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES; 22 import static com.google.common.math.MathTesting.DOUBLE_CANDIDATES_EXCEPT_NAN; 23 import static com.google.common.math.MathTesting.FINITE_DOUBLE_CANDIDATES; 24 import static com.google.common.math.MathTesting.FRACTIONAL_DOUBLE_CANDIDATES; 25 import static com.google.common.math.MathTesting.INFINITIES; 26 import static com.google.common.math.MathTesting.INTEGRAL_DOUBLE_CANDIDATES; 27 import static com.google.common.math.MathTesting.NEGATIVE_INTEGER_CANDIDATES; 28 import static com.google.common.math.MathTesting.POSITIVE_FINITE_DOUBLE_CANDIDATES; 29 import static java.math.RoundingMode.CEILING; 30 import static java.math.RoundingMode.DOWN; 31 import static java.math.RoundingMode.FLOOR; 32 import static java.math.RoundingMode.HALF_DOWN; 33 import static java.math.RoundingMode.HALF_EVEN; 34 import static java.math.RoundingMode.HALF_UP; 35 import static java.math.RoundingMode.UNNECESSARY; 36 import static java.math.RoundingMode.UP; 37 import static java.util.Arrays.asList; 38 39 import com.google.common.annotations.GwtCompatible; 40 import com.google.common.annotations.GwtIncompatible; 41 import com.google.common.collect.ImmutableList; 42 import com.google.common.collect.Iterables; 43 import com.google.common.primitives.Doubles; 44 import com.google.common.testing.NullPointerTester; 45 46 import junit.framework.TestCase; 47 48 import java.math.BigDecimal; 49 import java.math.BigInteger; 50 import java.math.RoundingMode; 51 import java.util.Arrays; 52 import java.util.List; 53 54 /** 55 * Tests for {@code DoubleMath}. 56 * 57 * @author Louis Wasserman 58 */ 59 @GwtCompatible(emulated = true) 60 public class DoubleMathTest extends TestCase { 61 62 private static final BigDecimal MAX_INT_AS_BIG_DECIMAL = BigDecimal.valueOf(Integer.MAX_VALUE); 63 private static final BigDecimal MIN_INT_AS_BIG_DECIMAL = BigDecimal.valueOf(Integer.MIN_VALUE); 64 65 private static final BigDecimal MAX_LONG_AS_BIG_DECIMAL = BigDecimal.valueOf(Long.MAX_VALUE); 66 private static final BigDecimal MIN_LONG_AS_BIG_DECIMAL = BigDecimal.valueOf(Long.MIN_VALUE); 67 68 public void testConstantsMaxFactorial() { 69 BigInteger maxDoubleValue = BigDecimal.valueOf(Double.MAX_VALUE).toBigInteger(); 70 assertTrue(BigIntegerMath.factorial(DoubleMath.MAX_FACTORIAL).compareTo(maxDoubleValue) <= 0); 71 assertTrue( 72 BigIntegerMath.factorial(DoubleMath.MAX_FACTORIAL + 1).compareTo(maxDoubleValue) > 0); 73 } 74 75 public void testConstantsEverySixteenthFactorial() { 76 for (int i = 0, n = 0; n <= DoubleMath.MAX_FACTORIAL; i++, n += 16) { 77 assertEquals( 78 BigIntegerMath.factorial(n).doubleValue(), DoubleMath.everySixteenthFactorial[i]); 79 } 80 } 81 82 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)") 83 public void testRoundIntegralDoubleToInt() { 84 for (double d : INTEGRAL_DOUBLE_CANDIDATES) { 85 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 86 BigDecimal expected = new BigDecimal(d).setScale(0, mode); 87 boolean isInBounds = expected.compareTo(MAX_INT_AS_BIG_DECIMAL) <= 0 88 & expected.compareTo(MIN_INT_AS_BIG_DECIMAL) >= 0; 89 90 try { 91 assertEquals(expected.intValue(), DoubleMath.roundToInt(d, mode)); 92 assertTrue(isInBounds); 93 } catch (ArithmeticException e) { 94 assertFalse(isInBounds); 95 } 96 } 97 } 98 } 99 100 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)") 101 public void testRoundFractionalDoubleToInt() { 102 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) { 103 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 104 BigDecimal expected = new BigDecimal(d).setScale(0, mode); 105 boolean isInBounds = expected.compareTo(MAX_INT_AS_BIG_DECIMAL) <= 0 106 & expected.compareTo(MIN_INT_AS_BIG_DECIMAL) >= 0; 107 108 try { 109 assertEquals(expected.intValue(), DoubleMath.roundToInt(d, mode)); 110 assertTrue(isInBounds); 111 } catch (ArithmeticException e) { 112 assertFalse(isInBounds); 113 } 114 } 115 } 116 } 117 118 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)") 119 public void testRoundExactIntegralDoubleToInt() { 120 for (double d : INTEGRAL_DOUBLE_CANDIDATES) { 121 BigDecimal expected = new BigDecimal(d).setScale(0, UNNECESSARY); 122 boolean isInBounds = expected.compareTo(MAX_INT_AS_BIG_DECIMAL) <= 0 123 & expected.compareTo(MIN_INT_AS_BIG_DECIMAL) >= 0; 124 125 try { 126 assertEquals(expected.intValue(), DoubleMath.roundToInt(d, UNNECESSARY)); 127 assertTrue(isInBounds); 128 } catch (ArithmeticException e) { 129 assertFalse(isInBounds); 130 } 131 } 132 } 133 134 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)") 135 public void testRoundExactFractionalDoubleToIntFails() { 136 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) { 137 try { 138 DoubleMath.roundToInt(d, UNNECESSARY); 139 fail("Expected ArithmeticException"); 140 } catch (ArithmeticException expected) {} 141 } 142 } 143 144 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)") 145 public void testRoundNaNToIntAlwaysFails() { 146 for (RoundingMode mode : ALL_ROUNDING_MODES) { 147 try { 148 DoubleMath.roundToInt(Double.NaN, mode); 149 fail("Expected ArithmeticException"); 150 } catch (ArithmeticException expected) {} 151 } 152 } 153 154 @GwtIncompatible("DoubleMath.roundToInt(double, RoundingMode)") 155 public void testRoundInfiniteToIntAlwaysFails() { 156 for (RoundingMode mode : ALL_ROUNDING_MODES) { 157 try { 158 DoubleMath.roundToInt(Double.POSITIVE_INFINITY, mode); 159 fail("Expected ArithmeticException"); 160 } catch (ArithmeticException expected) {} 161 try { 162 DoubleMath.roundToInt(Double.NEGATIVE_INFINITY, mode); 163 fail("Expected ArithmeticException"); 164 } catch (ArithmeticException expected) {} 165 } 166 } 167 168 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)") 169 public void testRoundIntegralDoubleToLong() { 170 for (double d : INTEGRAL_DOUBLE_CANDIDATES) { 171 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 172 BigDecimal expected = new BigDecimal(d).setScale(0, mode); 173 boolean isInBounds = expected.compareTo(MAX_LONG_AS_BIG_DECIMAL) <= 0 174 & expected.compareTo(MIN_LONG_AS_BIG_DECIMAL) >= 0; 175 176 try { 177 assertEquals(expected.longValue(), DoubleMath.roundToLong(d, mode)); 178 assertTrue(isInBounds); 179 } catch (ArithmeticException e) { 180 assertFalse(isInBounds); 181 } 182 } 183 } 184 } 185 186 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)") 187 public void testRoundFractionalDoubleToLong() { 188 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) { 189 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 190 BigDecimal expected = new BigDecimal(d).setScale(0, mode); 191 boolean isInBounds = expected.compareTo(MAX_LONG_AS_BIG_DECIMAL) <= 0 192 & expected.compareTo(MIN_LONG_AS_BIG_DECIMAL) >= 0; 193 194 try { 195 assertEquals(expected.longValue(), DoubleMath.roundToLong(d, mode)); 196 assertTrue(isInBounds); 197 } catch (ArithmeticException e) { 198 assertFalse(isInBounds); 199 } 200 } 201 } 202 } 203 204 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)") 205 public void testRoundExactIntegralDoubleToLong() { 206 for (double d : INTEGRAL_DOUBLE_CANDIDATES) { 207 // every mode except UNNECESSARY 208 BigDecimal expected = new BigDecimal(d).setScale(0, UNNECESSARY); 209 boolean isInBounds = expected.compareTo(MAX_LONG_AS_BIG_DECIMAL) <= 0 210 & expected.compareTo(MIN_LONG_AS_BIG_DECIMAL) >= 0; 211 212 try { 213 assertEquals(expected.longValue(), DoubleMath.roundToLong(d, UNNECESSARY)); 214 assertTrue(isInBounds); 215 } catch (ArithmeticException e) { 216 assertFalse(isInBounds); 217 } 218 } 219 } 220 221 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)") 222 public void testRoundExactFractionalDoubleToLongFails() { 223 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) { 224 try { 225 DoubleMath.roundToLong(d, UNNECESSARY); 226 fail("Expected ArithmeticException"); 227 } catch (ArithmeticException expected) {} 228 } 229 } 230 231 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)") 232 public void testRoundNaNToLongAlwaysFails() { 233 for (RoundingMode mode : ALL_ROUNDING_MODES) { 234 try { 235 DoubleMath.roundToLong(Double.NaN, mode); 236 fail("Expected ArithmeticException"); 237 } catch (ArithmeticException expected) {} 238 } 239 } 240 241 @GwtIncompatible("DoubleMath.roundToLong(double, RoundingMode)") 242 public void testRoundInfiniteToLongAlwaysFails() { 243 for (RoundingMode mode : ALL_ROUNDING_MODES) { 244 try { 245 DoubleMath.roundToLong(Double.POSITIVE_INFINITY, mode); 246 fail("Expected ArithmeticException"); 247 } catch (ArithmeticException expected) {} 248 try { 249 DoubleMath.roundToLong(Double.NEGATIVE_INFINITY, mode); 250 fail("Expected ArithmeticException"); 251 } catch (ArithmeticException expected) {} 252 } 253 } 254 255 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)") 256 public void testRoundIntegralDoubleToBigInteger() { 257 for (double d : INTEGRAL_DOUBLE_CANDIDATES) { 258 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 259 BigDecimal expected = new BigDecimal(d).setScale(0, mode); 260 assertEquals(expected.toBigInteger(), DoubleMath.roundToBigInteger(d, mode)); 261 } 262 } 263 } 264 265 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)") 266 public void testRoundFractionalDoubleToBigInteger() { 267 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) { 268 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) { 269 BigDecimal expected = new BigDecimal(d).setScale(0, mode); 270 assertEquals(expected.toBigInteger(), DoubleMath.roundToBigInteger(d, mode)); 271 } 272 } 273 } 274 275 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)") 276 public void testRoundExactIntegralDoubleToBigInteger() { 277 for (double d : INTEGRAL_DOUBLE_CANDIDATES) { 278 BigDecimal expected = new BigDecimal(d).setScale(0, UNNECESSARY); 279 assertEquals(expected.toBigInteger(), DoubleMath.roundToBigInteger(d, UNNECESSARY)); 280 } 281 } 282 283 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)") 284 public void testRoundExactFractionalDoubleToBigIntegerFails() { 285 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) { 286 try { 287 DoubleMath.roundToBigInteger(d, UNNECESSARY); 288 fail("Expected ArithmeticException"); 289 } catch (ArithmeticException expected) {} 290 } 291 } 292 293 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)") 294 public void testRoundNaNToBigIntegerAlwaysFails() { 295 for (RoundingMode mode : ALL_ROUNDING_MODES) { 296 try { 297 DoubleMath.roundToBigInteger(Double.NaN, mode); 298 fail("Expected ArithmeticException"); 299 } catch (ArithmeticException expected) {} 300 } 301 } 302 303 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)") 304 public void testRoundInfiniteToBigIntegerAlwaysFails() { 305 for (RoundingMode mode : ALL_ROUNDING_MODES) { 306 try { 307 DoubleMath.roundToBigInteger(Double.POSITIVE_INFINITY, mode); 308 fail("Expected ArithmeticException"); 309 } catch (ArithmeticException expected) {} 310 try { 311 DoubleMath.roundToBigInteger(Double.NEGATIVE_INFINITY, mode); 312 fail("Expected ArithmeticException"); 313 } catch (ArithmeticException expected) {} 314 } 315 } 316 317 @GwtIncompatible("DoubleMath.roundToBigInteger(double, RoundingMode)") 318 public void testRoundLog2Floor() { 319 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 320 int log2 = DoubleMath.log2(d, FLOOR); 321 assertTrue(StrictMath.pow(2.0, log2) <= d); 322 assertTrue(StrictMath.pow(2.0, log2 + 1) > d); 323 } 324 } 325 326 @GwtIncompatible("DoubleMath.log2(double, RoundingMode), StrictMath") 327 public void testRoundLog2Ceiling() { 328 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 329 int log2 = DoubleMath.log2(d, CEILING); 330 assertTrue(StrictMath.pow(2.0, log2) >= d); 331 double z = StrictMath.pow(2.0, log2 - 1); 332 assertTrue(z < d); 333 } 334 } 335 336 @GwtIncompatible("DoubleMath.log2(double, RoundingMode), StrictMath") 337 public void testRoundLog2Down() { 338 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 339 int log2 = DoubleMath.log2(d, DOWN); 340 if (d >= 1.0) { 341 assertTrue(log2 >= 0); 342 assertTrue(StrictMath.pow(2.0, log2) <= d); 343 assertTrue(StrictMath.pow(2.0, log2 + 1) > d); 344 } else { 345 assertTrue(log2 <= 0); 346 assertTrue(StrictMath.pow(2.0, log2) >= d); 347 assertTrue(StrictMath.pow(2.0, log2 - 1) < d); 348 } 349 } 350 } 351 352 @GwtIncompatible("DoubleMath.log2(double, RoundingMode), StrictMath") 353 public void testRoundLog2Up() { 354 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 355 int log2 = DoubleMath.log2(d, UP); 356 if (d >= 1.0) { 357 assertTrue(log2 >= 0); 358 assertTrue(StrictMath.pow(2.0, log2) >= d); 359 assertTrue(StrictMath.pow(2.0, log2 - 1) < d); 360 } else { 361 assertTrue(log2 <= 0); 362 assertTrue(StrictMath.pow(2.0, log2) <= d); 363 assertTrue(StrictMath.pow(2.0, log2 + 1) > d); 364 } 365 } 366 } 367 368 @GwtIncompatible("DoubleMath.log2(double, RoundingMode)") 369 public void testRoundLog2Half() { 370 // We don't expect perfect rounding accuracy. 371 for (int exp : asList(-1022, -50, -1, 0, 1, 2, 3, 4, 100, 1022, 1023)) { 372 for (RoundingMode mode : asList(HALF_EVEN, HALF_UP, HALF_DOWN)) { 373 double x = Math.scalb(Math.sqrt(2) + 0.001, exp); 374 double y = Math.scalb(Math.sqrt(2) - 0.001, exp); 375 if (exp < 0) { 376 assertEquals(exp + 1, DoubleMath.log2(x, mode)); 377 assertEquals(exp, DoubleMath.log2(y, mode)); 378 } else { 379 assertEquals(exp + 1, DoubleMath.log2(x, mode)); 380 assertEquals(exp, DoubleMath.log2(y, mode)); 381 } 382 } 383 } 384 } 385 386 @GwtIncompatible("DoubleMath.log2(double, RoundingMode)") 387 public void testRoundLog2Exact() { 388 for (double x : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 389 boolean isPowerOfTwo = StrictMath.pow(2.0, DoubleMath.log2(x, FLOOR)) == x; 390 try { 391 int log2 = DoubleMath.log2(x, UNNECESSARY); 392 assertEquals(x, Math.scalb(1.0, log2)); 393 assertTrue(isPowerOfTwo); 394 } catch (ArithmeticException e) { 395 assertFalse(isPowerOfTwo); 396 } 397 } 398 } 399 400 @GwtIncompatible("DoubleMath.log2(double, RoundingMode)") 401 public void testRoundLog2ThrowsOnZerosInfinitiesAndNaN() { 402 for (RoundingMode mode : ALL_ROUNDING_MODES) { 403 for (double d : 404 asList(0.0, -0.0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN)) { 405 try { 406 DoubleMath.log2(d, mode); 407 fail("Expected IllegalArgumentException"); 408 } catch (IllegalArgumentException expected) {} 409 } 410 } 411 } 412 413 @GwtIncompatible("DoubleMath.log2(double, RoundingMode)") 414 public void testRoundLog2ThrowsOnNegative() { 415 for (RoundingMode mode : ALL_ROUNDING_MODES) { 416 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 417 try { 418 DoubleMath.log2(-d, mode); 419 fail("Expected IllegalArgumentException"); 420 } catch (IllegalArgumentException expected) {} 421 } 422 } 423 } 424 425 @GwtIncompatible("DoubleMath.isPowerOfTwo, DoubleMath.log2(double, RoundingMode), StrictMath") 426 public void testIsPowerOfTwoYes() { 427 for (int i = -1074; i <= 1023; i++) { 428 assertTrue(DoubleMath.isPowerOfTwo(StrictMath.pow(2.0, i))); 429 } 430 } 431 432 @GwtIncompatible("DoubleMath.isPowerOfTwo, DoubleMath.log2(double, RoundingMode), StrictMath") 433 public void testIsPowerOfTwo() { 434 for (double x : ALL_DOUBLE_CANDIDATES) { 435 boolean expected = x > 0 && !Double.isInfinite(x) && !Double.isNaN(x) 436 && StrictMath.pow(2.0, DoubleMath.log2(x, FLOOR)) == x; 437 assertEquals(expected, DoubleMath.isPowerOfTwo(x)); 438 } 439 } 440 441 @GwtIncompatible("#trueLog2, Math.ulp") 442 public void testLog2Accuracy() { 443 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 444 double dmLog2 = DoubleMath.log2(d); 445 double trueLog2 = trueLog2(d); 446 assertTrue(Math.abs(dmLog2 - trueLog2) <= Math.ulp(trueLog2)); 447 } 448 } 449 450 public void testLog2SemiMonotonic() { 451 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 452 assertTrue(DoubleMath.log2(d + 0.01) >= DoubleMath.log2(d)); 453 } 454 } 455 456 public void testLog2Negative() { 457 for (double d : POSITIVE_FINITE_DOUBLE_CANDIDATES) { 458 assertTrue(Double.isNaN(DoubleMath.log2(-d))); 459 } 460 } 461 462 public void testLog2Zero() { 463 assertEquals(Double.NEGATIVE_INFINITY, DoubleMath.log2(0.0)); 464 assertEquals(Double.NEGATIVE_INFINITY, DoubleMath.log2(-0.0)); 465 } 466 467 public void testLog2NaNInfinity() { 468 assertEquals(Double.POSITIVE_INFINITY, DoubleMath.log2(Double.POSITIVE_INFINITY)); 469 assertTrue(Double.isNaN(DoubleMath.log2(Double.NEGATIVE_INFINITY))); 470 assertTrue(Double.isNaN(DoubleMath.log2(Double.NaN))); 471 } 472 473 @GwtIncompatible("StrictMath") 474 private strictfp double trueLog2(double d) { 475 double trueLog2 = StrictMath.log(d) / StrictMath.log(2); 476 // increment until it's >= the true value 477 while (StrictMath.pow(2.0, trueLog2) < d) { 478 trueLog2 = StrictMath.nextUp(trueLog2); 479 } 480 // decrement until it's <= the true value 481 while (StrictMath.pow(2.0, trueLog2) > d) { 482 trueLog2 = StrictMath.nextAfter(trueLog2, Double.NEGATIVE_INFINITY); 483 } 484 if (StrictMath.abs(StrictMath.pow(2.0, trueLog2) - d) 485 > StrictMath.abs(StrictMath.pow(2.0, StrictMath.nextUp(trueLog2)) - d)) { 486 trueLog2 = StrictMath.nextUp(trueLog2); 487 } 488 return trueLog2; 489 } 490 491 @GwtIncompatible("DoubleMath.isMathematicalInteger") 492 public void testIsMathematicalIntegerIntegral() { 493 for (double d : INTEGRAL_DOUBLE_CANDIDATES) { 494 assertTrue(DoubleMath.isMathematicalInteger(d)); 495 } 496 } 497 498 @GwtIncompatible("DoubleMath.isMathematicalInteger") 499 public void testIsMathematicalIntegerFractional() { 500 for (double d : FRACTIONAL_DOUBLE_CANDIDATES) { 501 assertFalse(DoubleMath.isMathematicalInteger(d)); 502 } 503 } 504 505 @GwtIncompatible("DoubleMath.isMathematicalInteger") 506 public void testIsMathematicalIntegerNotFinite() { 507 for (double d : 508 Arrays.asList(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN)) { 509 assertFalse(DoubleMath.isMathematicalInteger(d)); 510 } 511 } 512 513 @GwtIncompatible("Math.ulp") 514 public void testFactorial() { 515 for (int i = 0; i <= DoubleMath.MAX_FACTORIAL; i++) { 516 double actual = BigIntegerMath.factorial(i).doubleValue(); 517 double result = DoubleMath.factorial(i); 518 assertEquals(actual, result, Math.ulp(actual)); 519 } 520 } 521 522 public void testFactorialTooHigh() { 523 assertEquals(Double.POSITIVE_INFINITY, DoubleMath.factorial(DoubleMath.MAX_FACTORIAL + 1)); 524 assertEquals(Double.POSITIVE_INFINITY, DoubleMath.factorial(DoubleMath.MAX_FACTORIAL + 20)); 525 } 526 527 public void testFactorialNegative() { 528 for (int n : NEGATIVE_INTEGER_CANDIDATES) { 529 try { 530 DoubleMath.factorial(n); 531 fail("Expected IllegalArgumentException"); 532 } catch (IllegalArgumentException expected) {} 533 } 534 } 535 536 private static final ImmutableList<Double> FINITE_TOLERANCE_CANDIDATES = 537 ImmutableList.of(-0.0, 0.0, 1.0, 100.0, 10000.0, Double.MAX_VALUE); 538 539 private static final Iterable<Double> TOLERANCE_CANDIDATES = 540 Iterables.concat(FINITE_TOLERANCE_CANDIDATES, ImmutableList.of(Double.POSITIVE_INFINITY)); 541 542 private static final List<Double> BAD_TOLERANCE_CANDIDATES = 543 Doubles.asList(-Double.MIN_VALUE, -Double.MIN_NORMAL, -1, -20, Double.NaN, 544 Double.NEGATIVE_INFINITY, -0.001); 545 546 public void testFuzzyEqualsFinite() { 547 for (double a : FINITE_DOUBLE_CANDIDATES) { 548 for (double b : FINITE_DOUBLE_CANDIDATES) { 549 for (double tolerance : FINITE_TOLERANCE_CANDIDATES) { 550 assertEquals( 551 Math.abs(a - b) <= tolerance, 552 DoubleMath.fuzzyEquals(a, b, tolerance)); 553 } 554 } 555 } 556 } 557 558 public void testFuzzyInfiniteVersusFiniteWithFiniteTolerance() { 559 for (double inf : INFINITIES) { 560 for (double a : FINITE_DOUBLE_CANDIDATES) { 561 for (double tolerance : FINITE_TOLERANCE_CANDIDATES) { 562 assertFalse(DoubleMath.fuzzyEquals(a, inf, tolerance)); 563 assertFalse(DoubleMath.fuzzyEquals(inf, a, tolerance)); 564 } 565 } 566 } 567 } 568 569 public void testFuzzyInfiniteVersusInfiniteWithFiniteTolerance() { 570 for (double inf : INFINITIES) { 571 for (double tolerance : FINITE_TOLERANCE_CANDIDATES) { 572 assertTrue(DoubleMath.fuzzyEquals(inf, inf, tolerance)); 573 assertFalse(DoubleMath.fuzzyEquals(inf, -inf, tolerance)); 574 } 575 } 576 } 577 578 public void testFuzzyEqualsInfiniteTolerance() { 579 for (double a : DOUBLE_CANDIDATES_EXCEPT_NAN) { 580 for (double b : DOUBLE_CANDIDATES_EXCEPT_NAN) { 581 assertTrue(DoubleMath.fuzzyEquals(a, b, Double.POSITIVE_INFINITY)); 582 } 583 } 584 } 585 586 public void testFuzzyEqualsOneNaN() { 587 for (double a : DOUBLE_CANDIDATES_EXCEPT_NAN) { 588 for (double tolerance : TOLERANCE_CANDIDATES) { 589 assertFalse(DoubleMath.fuzzyEquals(a, Double.NaN, tolerance)); 590 assertFalse(DoubleMath.fuzzyEquals(Double.NaN, a, tolerance)); 591 } 592 } 593 } 594 595 public void testFuzzyEqualsTwoNaNs() { 596 for (double tolerance : TOLERANCE_CANDIDATES) { 597 assertTrue(DoubleMath.fuzzyEquals(Double.NaN, Double.NaN, tolerance)); 598 } 599 } 600 601 public void testFuzzyEqualsZeroTolerance() { 602 // make sure we test -0 tolerance 603 for (double zero : Doubles.asList(0.0, -0.0)) { 604 for (double a : ALL_DOUBLE_CANDIDATES) { 605 for (double b : ALL_DOUBLE_CANDIDATES) { 606 assertEquals(a == b || (Double.isNaN(a) && Double.isNaN(b)), 607 DoubleMath.fuzzyEquals(a, b, zero)); 608 } 609 } 610 } 611 } 612 613 public void testFuzzyEqualsBadTolerance() { 614 for (double tolerance : BAD_TOLERANCE_CANDIDATES) { 615 try { 616 DoubleMath.fuzzyEquals(1, 2, tolerance); 617 fail("Expected IllegalArgumentException"); 618 } catch (IllegalArgumentException expected) { 619 // success 620 } 621 } 622 } 623 624 public void testFuzzyCompare() { 625 for (double a : ALL_DOUBLE_CANDIDATES) { 626 for (double b : ALL_DOUBLE_CANDIDATES) { 627 for (double tolerance : TOLERANCE_CANDIDATES) { 628 int expected = DoubleMath.fuzzyEquals(a, b, tolerance) ? 0 : Double.compare(a, b); 629 int actual = DoubleMath.fuzzyCompare(a, b, tolerance); 630 assertEquals(Integer.signum(expected), Integer.signum(actual)); 631 } 632 } 633 } 634 } 635 636 public void testFuzzyCompareBadTolerance() { 637 for (double tolerance : BAD_TOLERANCE_CANDIDATES) { 638 try { 639 DoubleMath.fuzzyCompare(1, 2, tolerance); 640 fail("Expected IllegalArgumentException"); 641 } catch (IllegalArgumentException expected) { 642 // success 643 } 644 } 645 } 646 647 @GwtIncompatible("DoubleMath.mean") 648 public void testMean_doubleVarargs() { 649 assertEquals(-1.375, DoubleMath.mean(1.1, -2.2, 4.4, -8.8), 1.0e-10); 650 assertEquals(1.1, DoubleMath.mean(1.1), 1.0e-10); 651 try { 652 DoubleMath.mean(Double.NaN); 653 fail("Expected IllegalArgumentException"); 654 } catch (IllegalArgumentException expected) { 655 } 656 try { 657 DoubleMath.mean(Double.POSITIVE_INFINITY); 658 fail("Expected IllegalArgumentException"); 659 } catch (IllegalArgumentException expected) { 660 } 661 } 662 663 @GwtIncompatible("DoubleMath.mean") 664 public void testMean_intVarargs() { 665 assertEquals(-13.75, DoubleMath.mean(11, -22, 44, -88), 1.0e-10); 666 assertEquals(11.0, DoubleMath.mean(11), 1.0e-10); 667 } 668 669 @GwtIncompatible("DoubleMath.mean") 670 public void testMean_longVarargs() { 671 assertEquals(-13.75, DoubleMath.mean(11L, -22L, 44L, -88L), 1.0e-10); 672 assertEquals(11.0, DoubleMath.mean(11L), 1.0e-10); 673 } 674 675 @GwtIncompatible("DoubleMath.mean") 676 public void testMean_emptyVarargs() { 677 try { 678 DoubleMath.mean(); 679 fail("Expected IllegalArgumentException"); 680 } catch (IllegalArgumentException expected) { 681 } 682 } 683 684 @GwtIncompatible("DoubleMath.mean") 685 public void testMean_doubleIterable() { 686 assertEquals(-1.375, DoubleMath.mean(ImmutableList.of(1.1, -2.2, 4.4, -8.8)), 1.0e-10); 687 assertEquals(1.1, DoubleMath.mean(ImmutableList.of(1.1)), 1.0e-10); 688 try { 689 DoubleMath.mean(ImmutableList.<Double>of()); 690 fail("Expected IllegalArgumentException"); 691 } catch (IllegalArgumentException expected) { 692 } 693 try { 694 DoubleMath.mean(ImmutableList.of(Double.NaN)); 695 fail("Expected IllegalArgumentException"); 696 } catch (IllegalArgumentException expected) { 697 } 698 try { 699 DoubleMath.mean(ImmutableList.of(Double.POSITIVE_INFINITY)); 700 fail("Expected IllegalArgumentException"); 701 } catch (IllegalArgumentException expected) { 702 } 703 } 704 705 @GwtIncompatible("DoubleMath.mean") 706 public void testMean_intIterable() { 707 assertEquals(-13.75, DoubleMath.mean(ImmutableList.of(11, -22, 44, -88)), 1.0e-10); 708 assertEquals(11, DoubleMath.mean(ImmutableList.of(11)), 1.0e-10); 709 try { 710 DoubleMath.mean(ImmutableList.<Integer>of()); 711 fail("Expected IllegalArgumentException"); 712 } catch (IllegalArgumentException expected) { 713 } 714 } 715 716 @GwtIncompatible("DoubleMath.mean") 717 public void testMean_longIterable() { 718 assertEquals(-13.75, DoubleMath.mean(ImmutableList.of(11L, -22L, 44L, -88L)), 1.0e-10); 719 assertEquals(11, DoubleMath.mean(ImmutableList.of(11L)), 1.0e-10); 720 try { 721 DoubleMath.mean(ImmutableList.<Long>of()); 722 fail("Expected IllegalArgumentException"); 723 } catch (IllegalArgumentException expected) { 724 } 725 } 726 727 @GwtIncompatible("DoubleMath.mean") 728 public void testMean_intIterator() { 729 assertEquals(-13.75, DoubleMath.mean(ImmutableList.of(11, -22, 44, -88).iterator()), 1.0e-10); 730 assertEquals(11, DoubleMath.mean(ImmutableList.of(11).iterator()), 1.0e-10); 731 try { 732 DoubleMath.mean(ImmutableList.<Integer>of().iterator()); 733 fail("Expected IllegalArgumentException"); 734 } catch (IllegalArgumentException expected) { 735 } 736 } 737 738 @GwtIncompatible("DoubleMath.mean") 739 public void testMean_longIterator() { 740 assertEquals(-13.75, DoubleMath.mean(ImmutableList.of(11L, -22L, 44L, -88L).iterator()), 741 1.0e-10); 742 assertEquals(11, DoubleMath.mean(ImmutableList.of(11L).iterator()), 1.0e-10); 743 try { 744 DoubleMath.mean(ImmutableList.<Long>of().iterator()); 745 fail("Expected IllegalArgumentException"); 746 } catch (IllegalArgumentException expected) { 747 } 748 } 749 750 @GwtIncompatible("NullPointerTester") 751 public void testNullPointers() { 752 NullPointerTester tester = new NullPointerTester(); 753 tester.setDefault(double.class, 3.0); 754 tester.testAllPublicStaticMethods(DoubleMath.class); 755 } 756 } 757