Precision.java

  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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */

  21. package org.hipparchus.util;

  22. import java.math.BigDecimal;
  23. import java.math.RoundingMode;

  24. import org.hipparchus.exception.LocalizedCoreFormats;
  25. import org.hipparchus.exception.MathRuntimeException;
  26. import org.hipparchus.exception.MathIllegalArgumentException;

  27. /**
  28.  * Utilities for comparing numbers.
  29.  */
  30. public class Precision {
  31.     /**
  32.      * Largest double-precision floating-point number such that
  33.      * {@code 1 + EPSILON} is numerically equal to 1. This value is an upper
  34.      * bound on the relative error due to rounding real numbers to double
  35.      * precision floating-point numbers.
  36.      * <p>
  37.      * In IEEE 754 arithmetic, this is 2<sup>-53</sup>.
  38.      *
  39.      * @see <a href="http://en.wikipedia.org/wiki/Machine_epsilon">Machine epsilon</a>
  40.      */
  41.     public static final double EPSILON;

  42.     /**
  43.      * Safe minimum, such that {@code 1 / SAFE_MIN} does not overflow.
  44.      * <br>
  45.      * In IEEE 754 arithmetic, this is also the smallest normalized
  46.      * number 2<sup>-1022</sup>.
  47.      */
  48.     public static final double SAFE_MIN;

  49.     /** Exponent offset in IEEE754 representation. */
  50.     private static final long EXPONENT_OFFSET = 1023l;

  51.     /** Offset to order signed double numbers lexicographically. */
  52.     private static final long SGN_MASK = 0x8000000000000000L;
  53.     /** Offset to order signed double numbers lexicographically. */
  54.     private static final int SGN_MASK_FLOAT = 0x80000000;
  55.     /** Positive zero. */
  56.     private static final double POSITIVE_ZERO = 0d;
  57.     /** Positive zero bits. */
  58.     private static final long POSITIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(+0.0);
  59.     /** Negative zero bits. */
  60.     private static final long NEGATIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(-0.0);
  61.     /** Positive zero bits. */
  62.     private static final int POSITIVE_ZERO_FLOAT_BITS   = Float.floatToRawIntBits(+0.0f);
  63.     /** Negative zero bits. */
  64.     private static final int NEGATIVE_ZERO_FLOAT_BITS   = Float.floatToRawIntBits(-0.0f);
  65.     /** Mask used to extract exponent from double bits. */
  66.     private static final long MASK_DOUBLE_EXPONENT = 0x7ff0000000000000L;
  67.     /** Mask used to extract mantissa from double bits. */
  68.     private static final long MASK_DOUBLE_MANTISSA = 0x000fffffffffffffL;
  69.     /** Mask used to add implicit high order bit for normalized double. */
  70.     private static final long IMPLICIT_DOUBLE_HIGH_BIT = 0x0010000000000000L;
  71.     /** Mask used to extract exponent from float bits. */
  72.     private static final int MASK_FLOAT_EXPONENT = 0x7f800000;
  73.     /** Mask used to extract mantissa from float bits. */
  74.     private static final int MASK_FLOAT_MANTISSA = 0x007fffff;
  75.     /** Mask used to add implicit high order bit for normalized float. */
  76.     private static final int IMPLICIT_FLOAT_HIGH_BIT = 0x00800000;

  77.     static {
  78.         /*
  79.          *  This was previously expressed as = 0x1.0p-53;
  80.          *  However, OpenJDK (Sparc Solaris) cannot handle such small
  81.          *  constants: MATH-721
  82.          */
  83.         EPSILON = Double.longBitsToDouble((EXPONENT_OFFSET - 53l) << 52);

  84.         /*
  85.          * This was previously expressed as = 0x1.0p-1022;
  86.          * However, OpenJDK (Sparc Solaris) cannot handle such small
  87.          * constants: MATH-721
  88.          */
  89.         SAFE_MIN = Double.longBitsToDouble((EXPONENT_OFFSET - 1022l) << 52);
  90.     }

  91.     /**
  92.      * Private constructor.
  93.      */
  94.     private Precision() {}

  95.     /**
  96.      * Compares two numbers given some amount of allowed error.
  97.      *
  98.      * @param x the first number
  99.      * @param y the second number
  100.      * @param eps the amount of error to allow when checking for equality
  101.      * @return <ul><li>0 if  {@link #equals(double, double, double) equals(x, y, eps)}</li>
  102.      *       <li>&lt; 0 if !{@link #equals(double, double, double) equals(x, y, eps)} &amp;&amp; x &lt; y</li>
  103.      *       <li>&gt; 0 if !{@link #equals(double, double, double) equals(x, y, eps)} &amp;&amp; x &gt; y or
  104.      *       either argument is NaN</li></ul>
  105.      */
  106.     public static int compareTo(double x, double y, double eps) {
  107.         if (equals(x, y, eps)) {
  108.             return 0;
  109.         } else if (x < y) {
  110.             return -1;
  111.         }
  112.         return 1;
  113.     }

  114.     /**
  115.      * Compares two numbers given some amount of allowed error.
  116.      * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
  117.      * (or fewer) floating point numbers between them, i.e. two adjacent floating
  118.      * point numbers are considered equal.
  119.      * Adapted from <a
  120.      * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
  121.      * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN.
  122.      *
  123.      * @param x first value
  124.      * @param y second value
  125.      * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
  126.      * values between {@code x} and {@code y}.
  127.      * @return <ul><li>0 if  {@link #equals(double, double, int) equals(x, y, maxUlps)}</li>
  128.      *       <li>&lt; 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)} &amp;&amp; x &lt; y</li>
  129.      *       <li>&gt; 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)} &amp;&amp; x &gt; y
  130.      *       or either argument is NaN</li></ul>
  131.      */
  132.     public static int compareTo(final double x, final double y, final int maxUlps) {
  133.         if (equals(x, y, maxUlps)) {
  134.             return 0;
  135.         } else if (x < y) {
  136.             return -1;
  137.         }
  138.         return 1;
  139.     }

  140.     /**
  141.      * Returns true iff they are equal as defined by
  142.      * {@link #equals(float,float,int) equals(x, y, 1)}.
  143.      *
  144.      * @param x first value
  145.      * @param y second value
  146.      * @return {@code true} if the values are equal.
  147.      */
  148.     public static boolean equals(float x, float y) {
  149.         return equals(x, y, 1);
  150.     }

  151.     /**
  152.      * Returns true if both arguments are NaN or they are
  153.      * equal as defined by {@link #equals(float,float) equals(x, y, 1)}.
  154.      *
  155.      * @param x first value
  156.      * @param y second value
  157.      * @return {@code true} if the values are equal or both are NaN.
  158.      */
  159.     public static boolean equalsIncludingNaN(float x, float y) {
  160.         return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, 1);
  161.     }

  162.     /**
  163.      * Returns true if the arguments are equal or within the range of allowed
  164.      * error (inclusive).  Returns {@code false} if either of the arguments
  165.      * is NaN.
  166.      *
  167.      * @param x first value
  168.      * @param y second value
  169.      * @param eps the amount of absolute error to allow.
  170.      * @return {@code true} if the values are equal or within range of each other.
  171.      */
  172.     public static boolean equals(float x, float y, float eps) {
  173.         return equals(x, y, 1) || FastMath.abs(y - x) <= eps;
  174.     }

  175.     /**
  176.      * Returns true if the arguments are both NaN, are equal, or are within the range
  177.      * of allowed error (inclusive).
  178.      *
  179.      * @param x first value
  180.      * @param y second value
  181.      * @param eps the amount of absolute error to allow.
  182.      * @return {@code true} if the values are equal or within range of each other,
  183.      * or both are NaN.
  184.      */
  185.     public static boolean equalsIncludingNaN(float x, float y, float eps) {
  186.         return equalsIncludingNaN(x, y) || (FastMath.abs(y - x) <= eps);
  187.     }

  188.     /**
  189.      * Returns true if the arguments are equal or within the range of allowed
  190.      * error (inclusive).
  191.      * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
  192.      * (or fewer) floating point numbers between them, i.e. two adjacent floating
  193.      * point numbers are considered equal.
  194.      * Adapted from <a
  195.      * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
  196.      * Bruce Dawson</a>.  Returns {@code false} if either of the arguments is NaN.
  197.      *
  198.      * @param x first value
  199.      * @param y second value
  200.      * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
  201.      * values between {@code x} and {@code y}.
  202.      * @return {@code true} if there are fewer than {@code maxUlps} floating
  203.      * point values between {@code x} and {@code y}.
  204.      */
  205.     public static boolean equals(final float x, final float y, final int maxUlps) {

  206.         final int xInt = Float.floatToRawIntBits(x);
  207.         final int yInt = Float.floatToRawIntBits(y);

  208.         final boolean isEqual;
  209.         if (((xInt ^ yInt) & SGN_MASK_FLOAT) == 0) {
  210.             // number have same sign, there is no risk of overflow
  211.             isEqual = FastMath.abs(xInt - yInt) <= maxUlps;
  212.         } else {
  213.             // number have opposite signs, take care of overflow
  214.             final int deltaPlus;
  215.             final int deltaMinus;
  216.             if (xInt < yInt) {
  217.                 deltaPlus  = yInt - POSITIVE_ZERO_FLOAT_BITS;
  218.                 deltaMinus = xInt - NEGATIVE_ZERO_FLOAT_BITS;
  219.             } else {
  220.                 deltaPlus  = xInt - POSITIVE_ZERO_FLOAT_BITS;
  221.                 deltaMinus = yInt - NEGATIVE_ZERO_FLOAT_BITS;
  222.             }

  223.             if (deltaPlus > maxUlps) {
  224.                 isEqual = false;
  225.             } else {
  226.                 isEqual = deltaMinus <= (maxUlps - deltaPlus);
  227.             }

  228.         }

  229.         return isEqual && !Float.isNaN(x) && !Float.isNaN(y);

  230.     }

  231.     /**
  232.      * Returns true if the arguments are both NaN or if they are equal as defined
  233.      * by {@link #equals(float,float,int) equals(x, y, maxUlps)}.
  234.      *
  235.      * @param x first value
  236.      * @param y second value
  237.      * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
  238.      * values between {@code x} and {@code y}.
  239.      * @return {@code true} if both arguments are NaN or if there are less than
  240.      * {@code maxUlps} floating point values between {@code x} and {@code y}.
  241.      */
  242.     public static boolean equalsIncludingNaN(float x, float y, int maxUlps) {
  243.         return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, maxUlps);
  244.     }

  245.     /**
  246.      * Returns true iff they are equal as defined by
  247.      * {@link #equals(double,double,int) equals(x, y, 1)}.
  248.      *
  249.      * @param x first value
  250.      * @param y second value
  251.      * @return {@code true} if the values are equal.
  252.      */
  253.     public static boolean equals(double x, double y) {
  254.         return equals(x, y, 1);
  255.     }

  256.     /**
  257.      * Returns true if the arguments are both NaN or they are
  258.      * equal as defined by {@link #equals(double,double) equals(x, y, 1)}.
  259.      *
  260.      * @param x first value
  261.      * @param y second value
  262.      * @return {@code true} if the values are equal or both are NaN.
  263.      */
  264.     public static boolean equalsIncludingNaN(double x, double y) {
  265.         return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, 1);
  266.     }

  267.     /**
  268.      * Returns {@code true} if there is no double value strictly between the
  269.      * arguments or the difference between them is within the range of allowed
  270.      * error (inclusive). Returns {@code false} if either of the arguments
  271.      * is NaN.
  272.      *
  273.      * @param x First value.
  274.      * @param y Second value.
  275.      * @param eps Amount of allowed absolute error.
  276.      * @return {@code true} if the values are two adjacent floating point
  277.      * numbers or they are within range of each other.
  278.      */
  279.     public static boolean equals(double x, double y, double eps) {
  280.         return equals(x, y, 1) || FastMath.abs(y - x) <= eps;
  281.     }

  282.     /**
  283.      * Returns {@code true} if there is no double value strictly between the
  284.      * arguments or the relative difference between them is less than or equal
  285.      * to the given tolerance. Returns {@code false} if either of the arguments
  286.      * is NaN.
  287.      *
  288.      * @param x First value.
  289.      * @param y Second value.
  290.      * @param eps Amount of allowed relative error.
  291.      * @return {@code true} if the values are two adjacent floating point
  292.      * numbers or they are within range of each other.
  293.      */
  294.     public static boolean equalsWithRelativeTolerance(double x, double y, double eps) {
  295.         if (equals(x, y, 1)) {
  296.             return true;
  297.         }

  298.         final double absoluteMax = FastMath.max(FastMath.abs(x), FastMath.abs(y));
  299.         final double relativeDifference = FastMath.abs((x - y) / absoluteMax);

  300.         return relativeDifference <= eps;
  301.     }

  302.     /**
  303.      * Returns true if the arguments are both NaN, are equal or are within the range
  304.      * of allowed error (inclusive).
  305.      *
  306.      * @param x first value
  307.      * @param y second value
  308.      * @param eps the amount of absolute error to allow.
  309.      * @return {@code true} if the values are equal or within range of each other,
  310.      * or both are NaN.
  311.      */
  312.     public static boolean equalsIncludingNaN(double x, double y, double eps) {
  313.         return equalsIncludingNaN(x, y) || (FastMath.abs(y - x) <= eps);
  314.     }

  315.     /**
  316.      * Returns true if the arguments are equal or within the range of allowed
  317.      * error (inclusive).
  318.      * <p>
  319.      * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
  320.      * (or fewer) floating point numbers between them, i.e. two adjacent
  321.      * floating point numbers are considered equal.
  322.      * </p>
  323.      * <p>
  324.      * Adapted from <a
  325.      * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
  326.      * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN.
  327.      * </p>
  328.      *
  329.      * @param x first value
  330.      * @param y second value
  331.      * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
  332.      * values between {@code x} and {@code y}.
  333.      * @return {@code true} if there are fewer than {@code maxUlps} floating
  334.      * point values between {@code x} and {@code y}.
  335.      */
  336.     public static boolean equals(final double x, final double y, final int maxUlps) {

  337.         final long xInt = Double.doubleToRawLongBits(x);
  338.         final long yInt = Double.doubleToRawLongBits(y);

  339.         final boolean isEqual;
  340.         if (((xInt ^ yInt) & SGN_MASK) == 0l) {
  341.             // number have same sign, there is no risk of overflow
  342.             isEqual = FastMath.abs(xInt - yInt) <= maxUlps;
  343.         } else {
  344.             // number have opposite signs, take care of overflow
  345.             final long deltaPlus;
  346.             final long deltaMinus;
  347.             if (xInt < yInt) {
  348.                 deltaPlus  = yInt - POSITIVE_ZERO_DOUBLE_BITS;
  349.                 deltaMinus = xInt - NEGATIVE_ZERO_DOUBLE_BITS;
  350.             } else {
  351.                 deltaPlus  = xInt - POSITIVE_ZERO_DOUBLE_BITS;
  352.                 deltaMinus = yInt - NEGATIVE_ZERO_DOUBLE_BITS;
  353.             }

  354.             if (deltaPlus > maxUlps) {
  355.                 isEqual = false;
  356.             } else {
  357.                 isEqual = deltaMinus <= (maxUlps - deltaPlus);
  358.             }

  359.         }

  360.         return isEqual && !Double.isNaN(x) && !Double.isNaN(y);

  361.     }

  362.     /**
  363.      * Returns true if both arguments are NaN or if they are equal as defined
  364.      * by {@link #equals(double,double,int) equals(x, y, maxUlps)}.
  365.      *
  366.      * @param x first value
  367.      * @param y second value
  368.      * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
  369.      * values between {@code x} and {@code y}.
  370.      * @return {@code true} if both arguments are NaN or if there are less than
  371.      * {@code maxUlps} floating point values between {@code x} and {@code y}.
  372.      */
  373.     public static boolean equalsIncludingNaN(double x, double y, int maxUlps) {
  374.         return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, maxUlps);
  375.     }

  376.     /**
  377.      * Rounds the given value to the specified number of decimal places.
  378.      * The value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method.
  379.      *
  380.      * @param x Value to round.
  381.      * @param scale Number of digits to the right of the decimal point.
  382.      * @return the rounded value.
  383.      */
  384.     public static double round(double x, int scale) {
  385.         return round(x, scale, RoundingMode.HALF_UP);
  386.     }

  387.     /**
  388.      * Rounds the given value to the specified number of decimal places.
  389.      * The value is rounded using the given method which is any method defined
  390.      * in {@link BigDecimal}.
  391.      * If {@code x} is infinite or {@code NaN}, then the value of {@code x} is
  392.      * returned unchanged, regardless of the other parameters.
  393.      *
  394.      * @param x Value to round.
  395.      * @param scale Number of digits to the right of the decimal point.
  396.      * @param roundingMethod Rounding method as defined in {@link BigDecimal}.
  397.      * @return the rounded value.
  398.      * @throws ArithmeticException if {@code roundingMethod == ROUND_UNNECESSARY}
  399.      * and the specified scaling operation would require rounding.
  400.      * @throws IllegalArgumentException if {@code roundingMethod} does not
  401.      * represent a valid rounding mode.
  402.      */
  403.     public static double round(double x, int scale, RoundingMode roundingMethod) {
  404.         try {
  405.             final double rounded = (new BigDecimal(Double.toString(x))
  406.                    .setScale(scale, roundingMethod))
  407.                    .doubleValue();
  408.             // MATH-1089: negative values rounded to zero should result in negative zero
  409.             return rounded == POSITIVE_ZERO ? POSITIVE_ZERO * x : rounded;
  410.         } catch (NumberFormatException ex) {
  411.             if (Double.isInfinite(x)) {
  412.                 return x;
  413.             } else {
  414.                 return Double.NaN;
  415.             }
  416.         }
  417.     }

  418.     /**
  419.      * Rounds the given value to the specified number of decimal places.
  420.      * The value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method.
  421.      *
  422.      * @param x Value to round.
  423.      * @param scale Number of digits to the right of the decimal point.
  424.      * @return the rounded value.
  425.      */
  426.     public static float round(float x, int scale) {
  427.         return round(x, scale, RoundingMode.HALF_UP);
  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.      *
  434.      * @param x Value to round.
  435.      * @param scale Number of digits to the right of the decimal point.
  436.      * @param roundingMethod Rounding method as defined in {@link BigDecimal}.
  437.      * @return the rounded value.
  438.      * @throws MathRuntimeException if an exact operation is required but result is not exact
  439.      * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding method.
  440.      */
  441.     public static float round(float x, int scale, RoundingMode roundingMethod)
  442.         throws MathRuntimeException, MathIllegalArgumentException {
  443.         final float sign = FastMath.copySign(1f, x);
  444.         final float factor = (float) FastMath.pow(10.0f, scale) * sign;
  445.         return (float) roundUnscaled(x * factor, sign, roundingMethod) / factor;
  446.     }

  447.     /**
  448.      * Rounds the given non-negative value to the "nearest" integer. Nearest is
  449.      * determined by the rounding method specified. Rounding methods are defined
  450.      * in {@link BigDecimal}.
  451.      *
  452.      * @param unscaled Value to round.
  453.      * @param sign Sign of the original, scaled value.
  454.      * @param roundingMethod Rounding method, as defined in {@link BigDecimal}.
  455.      * @return the rounded value.
  456.      * @throws MathRuntimeException if an exact operation is required but result is not exact
  457.      * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding method.
  458.      */
  459.     private static double roundUnscaled(double unscaled,
  460.                                         double sign,
  461.                                         RoundingMode roundingMethod)
  462.         throws MathRuntimeException, MathIllegalArgumentException {
  463.         switch (roundingMethod) {
  464.         case CEILING :
  465.             if (sign == -1) {
  466.                 unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY));
  467.             } else {
  468.                 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY));
  469.             }
  470.             break;
  471.         case DOWN :
  472.             unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY));
  473.             break;
  474.         case FLOOR :
  475.             if (sign == -1) {
  476.                 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY));
  477.             } else {
  478.                 unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY));
  479.             }
  480.             break;
  481.         case HALF_DOWN : {
  482.             unscaled = FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY);
  483.             double fraction = unscaled - FastMath.floor(unscaled);
  484.             if (fraction > 0.5) {
  485.                 unscaled = FastMath.ceil(unscaled);
  486.             } else {
  487.                 unscaled = FastMath.floor(unscaled);
  488.             }
  489.             break;
  490.         }
  491.         case HALF_EVEN : {
  492.             double fraction = unscaled - FastMath.floor(unscaled);
  493.             if (fraction > 0.5) {
  494.                 unscaled = FastMath.ceil(unscaled);
  495.             } else if (fraction < 0.5) {
  496.                 unscaled = FastMath.floor(unscaled);
  497.             } else {
  498.                 // The following equality test is intentional and needed for rounding purposes
  499.                 if (FastMath.floor(unscaled) / 2.0 == FastMath.floor(FastMath.floor(unscaled) / 2.0)) { // even
  500.                     unscaled = FastMath.floor(unscaled);
  501.                 } else { // odd
  502.                     unscaled = FastMath.ceil(unscaled);
  503.                 }
  504.             }
  505.             break;
  506.         }
  507.         case HALF_UP : {
  508.             unscaled = FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY);
  509.             double fraction = unscaled - FastMath.floor(unscaled);
  510.             if (fraction >= 0.5) {
  511.                 unscaled = FastMath.ceil(unscaled);
  512.             } else {
  513.                 unscaled = FastMath.floor(unscaled);
  514.             }
  515.             break;
  516.         }
  517.         case UNNECESSARY :
  518.             if (unscaled != FastMath.floor(unscaled)) {
  519.                 throw new MathRuntimeException(LocalizedCoreFormats.ARITHMETIC_EXCEPTION);
  520.             }
  521.             break;
  522.         case UP :
  523.             // do not round if the discarded fraction is equal to zero
  524.             if (unscaled != FastMath.floor(unscaled)) {
  525.                 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY));
  526.             }
  527.             break;
  528.         default :
  529.             // this should nerver happen
  530.             throw MathRuntimeException.createInternalError();
  531.         }
  532.         return unscaled;
  533.     }

  534.     /** Check is x is a mathematical integer.
  535.      * @param x number to check
  536.      * @return true if x is a mathematical integer
  537.      * @since 1.7
  538.      */
  539.     public static boolean isMathematicalInteger(final double x) {
  540.         final long bits   = Double.doubleToRawLongBits(x);
  541.         final int  rawExp = (int) ((bits & MASK_DOUBLE_EXPONENT) >> 52);
  542.         if (rawExp == 2047) {
  543.             // NaN or infinite
  544.             return false;
  545.         } else {
  546.             // a double that may have a fractional part
  547.             final long rawMantissa    = bits & MASK_DOUBLE_MANTISSA;
  548.             final long fullMantissa   = rawExp > 0 ? (IMPLICIT_DOUBLE_HIGH_BIT | rawMantissa) : rawMantissa;
  549.             final long fractionalMask = (IMPLICIT_DOUBLE_HIGH_BIT | MASK_DOUBLE_MANTISSA) >> FastMath.min(53, FastMath.max(0, rawExp - 1022));
  550.             return (fullMantissa & fractionalMask) == 0l;
  551.         }
  552.     }

  553.     /** Check is x is a mathematical integer.
  554.      * @param x number to check
  555.      * @return true if x is a mathematical integer
  556.      * @since 1.7
  557.      */
  558.     public static boolean isMathematicalInteger(final float x) {
  559.         final int bits   = Float.floatToRawIntBits(x);
  560.         final int rawExp = (bits & MASK_FLOAT_EXPONENT) >> 23;
  561.         if (rawExp == 255) {
  562.             // NaN or infinite
  563.             return false;
  564.         } else {
  565.             // a float that may have a fractional part
  566.             final int rawMantissa    = bits & MASK_FLOAT_MANTISSA;
  567.             final int fullMantissa   = rawExp > 0 ? (IMPLICIT_FLOAT_HIGH_BIT | rawMantissa) : rawMantissa;
  568.             final int fractionalMask = (IMPLICIT_FLOAT_HIGH_BIT | MASK_FLOAT_MANTISSA) >> FastMath.min(24, FastMath.max(0, rawExp - 126));
  569.             return (fullMantissa & fractionalMask) == 0;
  570.         }
  571.     }

  572.     /**
  573.      * Computes a number {@code delta} close to {@code originalDelta} with
  574.      * the property that <pre><code>
  575.      *   x + delta - x
  576.      * </code></pre>
  577.      * is exactly machine-representable.
  578.      * This is useful when computing numerical derivatives, in order to reduce
  579.      * roundoff errors.
  580.      *
  581.      * @param x Value.
  582.      * @param originalDelta Offset value.
  583.      * @return a number {@code delta} so that {@code x + delta} and {@code x}
  584.      * differ by a representable floating number.
  585.      */
  586.     public static double representableDelta(double x,
  587.                                             double originalDelta) {
  588.         return x + originalDelta - x;
  589.     }
  590. }