1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * This is not the original file distributed by the Apache Software Foundation 20 * It has been modified by the Hipparchus project 21 */ 22 23 package org.hipparchus.util; 24 25 import java.math.BigDecimal; 26 import java.math.RoundingMode; 27 28 import org.hipparchus.exception.LocalizedCoreFormats; 29 import org.hipparchus.exception.MathRuntimeException; 30 import org.hipparchus.exception.MathIllegalArgumentException; 31 32 /** 33 * Utilities for comparing numbers. 34 */ 35 public class Precision { 36 /** 37 * Largest double-precision floating-point number such that 38 * {@code 1 + EPSILON} is numerically equal to 1. This value is an upper 39 * bound on the relative error due to rounding real numbers to double 40 * precision floating-point numbers. 41 * <p> 42 * In IEEE 754 arithmetic, this is 2<sup>-53</sup>. 43 * 44 * @see <a href="http://en.wikipedia.org/wiki/Machine_epsilon">Machine epsilon</a> 45 */ 46 public static final double EPSILON; 47 48 /** 49 * Safe minimum, such that {@code 1 / SAFE_MIN} does not overflow. 50 * <br> 51 * In IEEE 754 arithmetic, this is also the smallest normalized 52 * number 2<sup>-1022</sup>. 53 */ 54 public static final double SAFE_MIN; 55 56 /** Exponent offset in IEEE754 representation. */ 57 private static final long EXPONENT_OFFSET = 1023l; 58 59 /** Offset to order signed double numbers lexicographically. */ 60 private static final long SGN_MASK = 0x8000000000000000L; 61 /** Offset to order signed double numbers lexicographically. */ 62 private static final int SGN_MASK_FLOAT = 0x80000000; 63 /** Positive zero. */ 64 private static final double POSITIVE_ZERO = 0d; 65 /** Positive zero bits. */ 66 private static final long POSITIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(+0.0); 67 /** Negative zero bits. */ 68 private static final long NEGATIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(-0.0); 69 /** Positive zero bits. */ 70 private static final int POSITIVE_ZERO_FLOAT_BITS = Float.floatToRawIntBits(+0.0f); 71 /** Negative zero bits. */ 72 private static final int NEGATIVE_ZERO_FLOAT_BITS = Float.floatToRawIntBits(-0.0f); 73 /** Mask used to extract exponent from double bits. */ 74 private static final long MASK_DOUBLE_EXPONENT = 0x7ff0000000000000L; 75 /** Mask used to extract mantissa from double bits. */ 76 private static final long MASK_DOUBLE_MANTISSA = 0x000fffffffffffffL; 77 /** Mask used to add implicit high order bit for normalized double. */ 78 private static final long IMPLICIT_DOUBLE_HIGH_BIT = 0x0010000000000000L; 79 /** Mask used to extract exponent from float bits. */ 80 private static final int MASK_FLOAT_EXPONENT = 0x7f800000; 81 /** Mask used to extract mantissa from float bits. */ 82 private static final int MASK_FLOAT_MANTISSA = 0x007fffff; 83 /** Mask used to add implicit high order bit for normalized float. */ 84 private static final int IMPLICIT_FLOAT_HIGH_BIT = 0x00800000; 85 86 static { 87 /* 88 * This was previously expressed as = 0x1.0p-53; 89 * However, OpenJDK (Sparc Solaris) cannot handle such small 90 * constants: MATH-721 91 */ 92 EPSILON = Double.longBitsToDouble((EXPONENT_OFFSET - 53l) << 52); 93 94 /* 95 * This was previously expressed as = 0x1.0p-1022; 96 * However, OpenJDK (Sparc Solaris) cannot handle such small 97 * constants: MATH-721 98 */ 99 SAFE_MIN = Double.longBitsToDouble((EXPONENT_OFFSET - 1022l) << 52); 100 } 101 102 /** 103 * Private constructor. 104 */ 105 private Precision() {} 106 107 /** 108 * Compares two numbers given some amount of allowed error. 109 * 110 * @param x the first number 111 * @param y the second number 112 * @param eps the amount of error to allow when checking for equality 113 * @return <ul><li>0 if {@link #equals(double, double, double) equals(x, y, eps)}</li> 114 * <li>< 0 if !{@link #equals(double, double, double) equals(x, y, eps)} && x < y</li> 115 * <li>> 0 if !{@link #equals(double, double, double) equals(x, y, eps)} && x > y or 116 * either argument is NaN</li></ul> 117 */ 118 public static int compareTo(double x, double y, double eps) { 119 if (equals(x, y, eps)) { 120 return 0; 121 } else if (x < y) { 122 return -1; 123 } 124 return 1; 125 } 126 127 /** 128 * Compares two numbers given some amount of allowed error. 129 * Two float numbers are considered equal if there are {@code (maxUlps - 1)} 130 * (or fewer) floating point numbers between them, i.e. two adjacent floating 131 * point numbers are considered equal. 132 * Adapted from <a 133 * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/"> 134 * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN. 135 * 136 * @param x first value 137 * @param y second value 138 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point 139 * values between {@code x} and {@code y}. 140 * @return <ul><li>0 if {@link #equals(double, double, int) equals(x, y, maxUlps)}</li> 141 * <li>< 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)} && x < y</li> 142 * <li>> 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)} && x > y 143 * or either argument is NaN</li></ul> 144 */ 145 public static int compareTo(final double x, final double y, final int maxUlps) { 146 if (equals(x, y, maxUlps)) { 147 return 0; 148 } else if (x < y) { 149 return -1; 150 } 151 return 1; 152 } 153 154 /** 155 * Returns true iff they are equal as defined by 156 * {@link #equals(float,float,int) equals(x, y, 1)}. 157 * 158 * @param x first value 159 * @param y second value 160 * @return {@code true} if the values are equal. 161 */ 162 public static boolean equals(float x, float y) { 163 return equals(x, y, 1); 164 } 165 166 /** 167 * Returns true if both arguments are NaN or they are 168 * equal as defined by {@link #equals(float,float) equals(x, y, 1)}. 169 * 170 * @param x first value 171 * @param y second value 172 * @return {@code true} if the values are equal or both are NaN. 173 */ 174 public static boolean equalsIncludingNaN(float x, float y) { 175 return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, 1); 176 } 177 178 /** 179 * Returns true if the arguments are equal or within the range of allowed 180 * error (inclusive). Returns {@code false} if either of the arguments 181 * is NaN. 182 * 183 * @param x first value 184 * @param y second value 185 * @param eps the amount of absolute error to allow. 186 * @return {@code true} if the values are equal or within range of each other. 187 */ 188 public static boolean equals(float x, float y, float eps) { 189 return equals(x, y, 1) || FastMath.abs(y - x) <= eps; 190 } 191 192 /** 193 * Returns true if the arguments are both NaN, are equal, or are within the range 194 * of allowed error (inclusive). 195 * 196 * @param x first value 197 * @param y second value 198 * @param eps the amount of absolute error to allow. 199 * @return {@code true} if the values are equal or within range of each other, 200 * or both are NaN. 201 */ 202 public static boolean equalsIncludingNaN(float x, float y, float eps) { 203 return equalsIncludingNaN(x, y) || (FastMath.abs(y - x) <= eps); 204 } 205 206 /** 207 * Returns true if the arguments are equal or within the range of allowed 208 * error (inclusive). 209 * Two float numbers are considered equal if there are {@code (maxUlps - 1)} 210 * (or fewer) floating point numbers between them, i.e. two adjacent floating 211 * point numbers are considered equal. 212 * Adapted from <a 213 * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/"> 214 * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN. 215 * 216 * @param x first value 217 * @param y second value 218 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point 219 * values between {@code x} and {@code y}. 220 * @return {@code true} if there are fewer than {@code maxUlps} floating 221 * point values between {@code x} and {@code y}. 222 */ 223 public static boolean equals(final float x, final float y, final int maxUlps) { 224 225 final int xInt = Float.floatToRawIntBits(x); 226 final int yInt = Float.floatToRawIntBits(y); 227 228 final boolean isEqual; 229 if (((xInt ^ yInt) & SGN_MASK_FLOAT) == 0) { 230 // number have same sign, there is no risk of overflow 231 isEqual = FastMath.abs(xInt - yInt) <= maxUlps; 232 } else { 233 // number have opposite signs, take care of overflow 234 final int deltaPlus; 235 final int deltaMinus; 236 if (xInt < yInt) { 237 deltaPlus = yInt - POSITIVE_ZERO_FLOAT_BITS; 238 deltaMinus = xInt - NEGATIVE_ZERO_FLOAT_BITS; 239 } else { 240 deltaPlus = xInt - POSITIVE_ZERO_FLOAT_BITS; 241 deltaMinus = yInt - NEGATIVE_ZERO_FLOAT_BITS; 242 } 243 244 if (deltaPlus > maxUlps) { 245 isEqual = false; 246 } else { 247 isEqual = deltaMinus <= (maxUlps - deltaPlus); 248 } 249 250 } 251 252 return isEqual && !Float.isNaN(x) && !Float.isNaN(y); 253 254 } 255 256 /** 257 * Returns true if the arguments are both NaN or if they are equal as defined 258 * by {@link #equals(float,float,int) equals(x, y, maxUlps)}. 259 * 260 * @param x first value 261 * @param y second value 262 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point 263 * values between {@code x} and {@code y}. 264 * @return {@code true} if both arguments are NaN or if there are less than 265 * {@code maxUlps} floating point values between {@code x} and {@code y}. 266 */ 267 public static boolean equalsIncludingNaN(float x, float y, int maxUlps) { 268 return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, maxUlps); 269 } 270 271 /** 272 * Returns true iff they are equal as defined by 273 * {@link #equals(double,double,int) equals(x, y, 1)}. 274 * 275 * @param x first value 276 * @param y second value 277 * @return {@code true} if the values are equal. 278 */ 279 public static boolean equals(double x, double y) { 280 return equals(x, y, 1); 281 } 282 283 /** 284 * Returns true if the arguments are both NaN or they are 285 * equal as defined by {@link #equals(double,double) equals(x, y, 1)}. 286 * 287 * @param x first value 288 * @param y second value 289 * @return {@code true} if the values are equal or both are NaN. 290 */ 291 public static boolean equalsIncludingNaN(double x, double y) { 292 return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, 1); 293 } 294 295 /** 296 * Returns {@code true} if there is no double value strictly between the 297 * arguments or the difference between them is within the range of allowed 298 * error (inclusive). Returns {@code false} if either of the arguments 299 * is NaN. 300 * 301 * @param x First value. 302 * @param y Second value. 303 * @param eps Amount of allowed absolute error. 304 * @return {@code true} if the values are two adjacent floating point 305 * numbers or they are within range of each other. 306 */ 307 public static boolean equals(double x, double y, double eps) { 308 return equals(x, y, 1) || FastMath.abs(y - x) <= eps; 309 } 310 311 /** 312 * Returns {@code true} if there is no double value strictly between the 313 * arguments or the relative difference between them is less than or equal 314 * to the given tolerance. Returns {@code false} if either of the arguments 315 * is NaN. 316 * 317 * @param x First value. 318 * @param y Second value. 319 * @param eps Amount of allowed relative error. 320 * @return {@code true} if the values are two adjacent floating point 321 * numbers or they are within range of each other. 322 */ 323 public static boolean equalsWithRelativeTolerance(double x, double y, double eps) { 324 if (equals(x, y, 1)) { 325 return true; 326 } 327 328 final double absoluteMax = FastMath.max(FastMath.abs(x), FastMath.abs(y)); 329 final double relativeDifference = FastMath.abs((x - y) / absoluteMax); 330 331 return relativeDifference <= eps; 332 } 333 334 /** 335 * Returns true if the arguments are both NaN, are equal or are within the range 336 * of allowed error (inclusive). 337 * 338 * @param x first value 339 * @param y second value 340 * @param eps the amount of absolute error to allow. 341 * @return {@code true} if the values are equal or within range of each other, 342 * or both are NaN. 343 */ 344 public static boolean equalsIncludingNaN(double x, double y, double eps) { 345 return equalsIncludingNaN(x, y) || (FastMath.abs(y - x) <= eps); 346 } 347 348 /** 349 * Returns true if the arguments are equal or within the range of allowed 350 * error (inclusive). 351 * <p> 352 * Two float numbers are considered equal if there are {@code (maxUlps - 1)} 353 * (or fewer) floating point numbers between them, i.e. two adjacent 354 * floating point numbers are considered equal. 355 * </p> 356 * <p> 357 * Adapted from <a 358 * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/"> 359 * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN. 360 * </p> 361 * 362 * @param x first value 363 * @param y second value 364 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point 365 * values between {@code x} and {@code y}. 366 * @return {@code true} if there are fewer than {@code maxUlps} floating 367 * point values between {@code x} and {@code y}. 368 */ 369 public static boolean equals(final double x, final double y, final int maxUlps) { 370 371 final long xInt = Double.doubleToRawLongBits(x); 372 final long yInt = Double.doubleToRawLongBits(y); 373 374 final boolean isEqual; 375 if (((xInt ^ yInt) & SGN_MASK) == 0l) { 376 // number have same sign, there is no risk of overflow 377 isEqual = FastMath.abs(xInt - yInt) <= maxUlps; 378 } else { 379 // number have opposite signs, take care of overflow 380 final long deltaPlus; 381 final long deltaMinus; 382 if (xInt < yInt) { 383 deltaPlus = yInt - POSITIVE_ZERO_DOUBLE_BITS; 384 deltaMinus = xInt - NEGATIVE_ZERO_DOUBLE_BITS; 385 } else { 386 deltaPlus = xInt - POSITIVE_ZERO_DOUBLE_BITS; 387 deltaMinus = yInt - NEGATIVE_ZERO_DOUBLE_BITS; 388 } 389 390 if (deltaPlus > maxUlps) { 391 isEqual = false; 392 } else { 393 isEqual = deltaMinus <= (maxUlps - deltaPlus); 394 } 395 396 } 397 398 return isEqual && !Double.isNaN(x) && !Double.isNaN(y); 399 400 } 401 402 /** 403 * Returns true if both arguments are NaN or if they are equal as defined 404 * by {@link #equals(double,double,int) equals(x, y, maxUlps)}. 405 * 406 * @param x first value 407 * @param y second value 408 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point 409 * values between {@code x} and {@code y}. 410 * @return {@code true} if both arguments are NaN or if there are less than 411 * {@code maxUlps} floating point values between {@code x} and {@code y}. 412 */ 413 public static boolean equalsIncludingNaN(double x, double y, int maxUlps) { 414 return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, maxUlps); 415 } 416 417 /** 418 * Rounds the given value to the specified number of decimal places. 419 * The value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method. 420 * 421 * @param x Value to round. 422 * @param scale Number of digits to the right of the decimal point. 423 * @return the rounded value. 424 */ 425 public static double round(double x, int scale) { 426 return round(x, scale, RoundingMode.HALF_UP); 427 } 428 429 /** 430 * Rounds the given value to the specified number of decimal places. 431 * The value is rounded using the given method which is any method defined 432 * in {@link BigDecimal}. 433 * If {@code x} is infinite or {@code NaN}, then the value of {@code x} is 434 * returned unchanged, regardless of the other parameters. 435 * 436 * @param x Value to round. 437 * @param scale Number of digits to the right of the decimal point. 438 * @param roundingMethod Rounding method as defined in {@link BigDecimal}. 439 * @return the rounded value. 440 * @throws ArithmeticException if {@code roundingMethod == ROUND_UNNECESSARY} 441 * and the specified scaling operation would require rounding. 442 * @throws IllegalArgumentException if {@code roundingMethod} does not 443 * represent a valid rounding mode. 444 */ 445 public static double round(double x, int scale, RoundingMode roundingMethod) { 446 try { 447 final double rounded = (new BigDecimal(Double.toString(x)) 448 .setScale(scale, roundingMethod)) 449 .doubleValue(); 450 // MATH-1089: negative values rounded to zero should result in negative zero 451 return rounded == POSITIVE_ZERO ? POSITIVE_ZERO * x : rounded; 452 } catch (NumberFormatException ex) { 453 if (Double.isInfinite(x)) { 454 return x; 455 } else { 456 return Double.NaN; 457 } 458 } 459 } 460 461 /** 462 * Rounds the given value to the specified number of decimal places. 463 * The value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method. 464 * 465 * @param x Value to round. 466 * @param scale Number of digits to the right of the decimal point. 467 * @return the rounded value. 468 */ 469 public static float round(float x, int scale) { 470 return round(x, scale, RoundingMode.HALF_UP); 471 } 472 473 /** 474 * Rounds the given value to the specified number of decimal places. 475 * The value is rounded using the given method which is any method defined 476 * in {@link BigDecimal}. 477 * 478 * @param x Value to round. 479 * @param scale Number of digits to the right of the decimal point. 480 * @param roundingMethod Rounding method as defined in {@link BigDecimal}. 481 * @return the rounded value. 482 * @throws MathRuntimeException if an exact operation is required but result is not exact 483 * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding method. 484 */ 485 public static float round(float x, int scale, RoundingMode roundingMethod) 486 throws MathRuntimeException, MathIllegalArgumentException { 487 final float sign = FastMath.copySign(1f, x); 488 final float factor = (float) FastMath.pow(10.0f, scale) * sign; 489 return (float) roundUnscaled(x * factor, sign, roundingMethod) / factor; 490 } 491 492 /** 493 * Rounds the given non-negative value to the "nearest" integer. Nearest is 494 * determined by the rounding method specified. Rounding methods are defined 495 * in {@link BigDecimal}. 496 * 497 * @param unscaled Value to round. 498 * @param sign Sign of the original, scaled value. 499 * @param roundingMethod Rounding method, as defined in {@link BigDecimal}. 500 * @return the rounded value. 501 * @throws MathRuntimeException if an exact operation is required but result is not exact 502 * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding method. 503 */ 504 private static double roundUnscaled(double unscaled, 505 double sign, 506 RoundingMode roundingMethod) 507 throws MathRuntimeException, MathIllegalArgumentException { 508 switch (roundingMethod) { 509 case CEILING : 510 if (sign == -1) { 511 unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); 512 } else { 513 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); 514 } 515 break; 516 case DOWN : 517 unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); 518 break; 519 case FLOOR : 520 if (sign == -1) { 521 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); 522 } else { 523 unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); 524 } 525 break; 526 case HALF_DOWN : { 527 unscaled = FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY); 528 double fraction = unscaled - FastMath.floor(unscaled); 529 if (fraction > 0.5) { 530 unscaled = FastMath.ceil(unscaled); 531 } else { 532 unscaled = FastMath.floor(unscaled); 533 } 534 break; 535 } 536 case HALF_EVEN : { 537 double fraction = unscaled - FastMath.floor(unscaled); 538 if (fraction > 0.5) { 539 unscaled = FastMath.ceil(unscaled); 540 } else if (fraction < 0.5) { 541 unscaled = FastMath.floor(unscaled); 542 } else { 543 // The following equality test is intentional and needed for rounding purposes 544 if (FastMath.floor(unscaled) / 2.0 == FastMath.floor(FastMath.floor(unscaled) / 2.0)) { // even 545 unscaled = FastMath.floor(unscaled); 546 } else { // odd 547 unscaled = FastMath.ceil(unscaled); 548 } 549 } 550 break; 551 } 552 case HALF_UP : { 553 unscaled = FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY); 554 double fraction = unscaled - FastMath.floor(unscaled); 555 if (fraction >= 0.5) { 556 unscaled = FastMath.ceil(unscaled); 557 } else { 558 unscaled = FastMath.floor(unscaled); 559 } 560 break; 561 } 562 case UNNECESSARY : 563 if (unscaled != FastMath.floor(unscaled)) { 564 throw new MathRuntimeException(LocalizedCoreFormats.ARITHMETIC_EXCEPTION); 565 } 566 break; 567 case UP : 568 // do not round if the discarded fraction is equal to zero 569 if (unscaled != FastMath.floor(unscaled)) { 570 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); 571 } 572 break; 573 default : 574 // this should nerver happen 575 throw MathRuntimeException.createInternalError(); 576 } 577 return unscaled; 578 } 579 580 /** Check is x is a mathematical integer. 581 * @param x number to check 582 * @return true if x is a mathematical integer 583 * @since 1.7 584 */ 585 public static boolean isMathematicalInteger(final double x) { 586 final long bits = Double.doubleToRawLongBits(x); 587 final int rawExp = (int) ((bits & MASK_DOUBLE_EXPONENT) >> 52); 588 if (rawExp == 2047) { 589 // NaN or infinite 590 return false; 591 } else { 592 // a double that may have a fractional part 593 final long rawMantissa = bits & MASK_DOUBLE_MANTISSA; 594 final long fullMantissa = rawExp > 0 ? (IMPLICIT_DOUBLE_HIGH_BIT | rawMantissa) : rawMantissa; 595 final long fractionalMask = (IMPLICIT_DOUBLE_HIGH_BIT | MASK_DOUBLE_MANTISSA) >> FastMath.min(53, FastMath.max(0, rawExp - 1022)); 596 return (fullMantissa & fractionalMask) == 0l; 597 } 598 } 599 600 /** Check is x is a mathematical integer. 601 * @param x number to check 602 * @return true if x is a mathematical integer 603 * @since 1.7 604 */ 605 public static boolean isMathematicalInteger(final float x) { 606 final int bits = Float.floatToRawIntBits(x); 607 final int rawExp = (int) ((bits & MASK_FLOAT_EXPONENT) >> 23); 608 if (rawExp == 255) { 609 // NaN or infinite 610 return false; 611 } else { 612 // a float that may have a fractional part 613 final int rawMantissa = bits & MASK_FLOAT_MANTISSA; 614 final int fullMantissa = rawExp > 0 ? (IMPLICIT_FLOAT_HIGH_BIT | rawMantissa) : rawMantissa; 615 final int fractionalMask = (IMPLICIT_FLOAT_HIGH_BIT | MASK_FLOAT_MANTISSA) >> FastMath.min(24, FastMath.max(0, rawExp - 126)); 616 return (fullMantissa & fractionalMask) == 0; 617 } 618 } 619 620 /** 621 * Computes a number {@code delta} close to {@code originalDelta} with 622 * the property that <pre><code> 623 * x + delta - x 624 * </code></pre> 625 * is exactly machine-representable. 626 * This is useful when computing numerical derivatives, in order to reduce 627 * roundoff errors. 628 * 629 * @param x Value. 630 * @param originalDelta Offset value. 631 * @return a number {@code delta} so that {@code x + delta} and {@code x} 632 * differ by a representable floating number. 633 */ 634 public static double representableDelta(double x, 635 double originalDelta) { 636 return x + originalDelta - x; 637 } 638 }