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 = (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 }