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