001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.numbers.core;
019
020import java.math.BigDecimal;
021import java.math.RoundingMode;
022
023/**
024 * Utilities for comparing numbers.
025 */
026public final class Precision {
027    /**
028     * <p>
029     * Largest double-precision floating-point number such that
030     * {@code 1 + EPSILON} is numerically equal to 1. This value is an upper
031     * bound on the relative error due to rounding real numbers to double
032     * precision floating-point numbers.
033     * </p>
034     * <p>
035     * In IEEE 754 arithmetic, this is 2<sup>-53</sup>.
036     * </p>
037     *
038     * @see <a href="http://en.wikipedia.org/wiki/Machine_epsilon">Machine epsilon</a>
039     */
040    public static final double EPSILON;
041
042    /**
043     * Safe minimum, such that {@code 1 / SAFE_MIN} does not overflow.
044     * In IEEE 754 arithmetic, this is also the smallest normalized
045     * number 2<sup>-1022</sup>.
046     */
047    public static final double SAFE_MIN;
048
049    /** Exponent offset in IEEE754 representation. */
050    private static final long EXPONENT_OFFSET = 1023L;
051
052    /** Offset to order signed double numbers lexicographically. */
053    private static final long SGN_MASK = 0x8000000000000000L;
054    /** Offset to order signed double numbers lexicographically. */
055    private static final int SGN_MASK_FLOAT = 0x80000000;
056    /** Positive zero. */
057    private static final double POSITIVE_ZERO = 0d;
058    /** Positive zero bits. */
059    private static final long POSITIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(+0.0);
060    /** Negative zero bits. */
061    private static final long NEGATIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(-0.0);
062    /** Positive zero bits. */
063    private static final int POSITIVE_ZERO_FLOAT_BITS = Float.floatToRawIntBits(+0.0f);
064    /** Negative zero bits. */
065    private static final int NEGATIVE_ZERO_FLOAT_BITS = Float.floatToRawIntBits(-0.0f);
066
067    static {
068        /*
069         *  This was previously expressed as = 0x1.0p-53
070         *  However, OpenJDK (Sparc Solaris) cannot handle such small
071         *  constants: MATH-721
072         */
073        EPSILON = Double.longBitsToDouble((EXPONENT_OFFSET - 53L) << 52);
074
075        /*
076         * This was previously expressed as = 0x1.0p-1022
077         * However, OpenJDK (Sparc Solaris) cannot handle such small
078         * constants: MATH-721
079         */
080        SAFE_MIN = Double.longBitsToDouble((EXPONENT_OFFSET - 1022L) << 52);
081    }
082
083    /**
084     * Private constructor.
085     */
086    private Precision() {}
087
088    /**
089     * Compares two numbers given some amount of allowed error.
090     * The returned value is
091     * <ul>
092     *  <li>
093     *   0 if  {@link #equals(double,double,double) equals(x, y, eps)},
094     *  </li>
095     *  <li>
096     *   negative if !{@link #equals(double,double,double) equals(x, y, eps)} and {@code x < y},
097     *  </li>
098     *  <li>
099     *   positive if !{@link #equals(double,double,double) equals(x, y, eps)} and {@code x > y} or
100     *   either argument is {@code NaN}.
101     *  </li>
102     * </ul>
103     *
104     * @param x First value.
105     * @param y Second value.
106     * @param eps Allowed error when checking for equality.
107     * @return 0 if the value are considered equal, -1 if the first is smaller than
108     * the second, 1 is the first is larger than the second.
109     */
110    public static int compareTo(double x, double y, double eps) {
111        if (equals(x, y, eps)) {
112            return 0;
113        } else if (x < y) {
114            return -1;
115        }
116        return 1;
117    }
118
119    /**
120     * Compares two numbers given some amount of allowed error.
121     * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
122     * (or fewer) floating point numbers between them, i.e. two adjacent floating
123     * point numbers are considered equal.
124     * Adapted from
125     * <a href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
126     * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN.
127     * The returned value is
128     * <ul>
129     *  <li>
130     *   zero if {@link #equals(double,double,int) equals(x, y, maxUlps)},
131     *  </li>
132     *  <li>
133     *   negative if !{@link #equals(double,double,int) equals(x, y, maxUlps)} and {@code x < y},
134     *  </li>
135     *  <li>
136     *   positive if !{@link #equals(double,double,int) equals(x, y, maxUlps)} and {@code x > y}
137     *       or either argument is {@code NaN}.
138     *  </li>
139     * </ul>
140     *
141     * @param x First value.
142     * @param y Second value.
143     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
144     * values between {@code x} and {@code y}.
145     * @return 0 if the value are considered equal, -1 if the first is smaller than
146     * the second, 1 is the first is larger than the second.
147     */
148    public static int compareTo(final double x, final double y, final int maxUlps) {
149        if (equals(x, y, maxUlps)) {
150            return 0;
151        } else if (x < y) {
152            return -1;
153        }
154        return 1;
155    }
156
157    /**
158     * Returns true iff they are equal as defined by
159     * {@link #equals(float,float,int) equals(x, y, 1)}.
160     *
161     * @param x first value
162     * @param y second value
163     * @return {@code true} if the values are equal.
164     */
165    public static boolean equals(float x, float y) {
166        return equals(x, y, 1);
167    }
168
169    /**
170     * Returns true if both arguments are NaN or they are
171     * equal as defined by {@link #equals(float,float) equals(x, y, 1)}.
172     *
173     * @param x first value
174     * @param y second value
175     * @return {@code true} if the values are equal or both are NaN.
176     */
177    public static boolean equalsIncludingNaN(float x, float y) {
178        final boolean xIsNan = Float.isNaN(x);
179        final boolean yIsNan = Float.isNaN(y);
180        return xIsNan || yIsNan ?
181            !(xIsNan ^ yIsNan) :
182            equals(x, y, 1);
183    }
184
185    /**
186     * Returns true if the arguments are equal or within the range of allowed
187     * error (inclusive).  Returns {@code false} if either of the arguments
188     * is NaN.
189     *
190     * @param x first value
191     * @param y second value
192     * @param eps the amount of absolute error to allow.
193     * @return {@code true} if the values are equal or within range of each other.
194     */
195    public static boolean equals(float x, float y, float eps) {
196        return equals(x, y, 1) || Math.abs(y - x) <= eps;
197    }
198
199    /**
200     * Returns true if the arguments are both NaN, are equal, or are within the range
201     * of allowed error (inclusive).
202     *
203     * @param x first value
204     * @param y second value
205     * @param eps the amount of absolute error to allow.
206     * @return {@code true} if the values are equal or within range of each other,
207     * or both are NaN.
208     */
209    public static boolean equalsIncludingNaN(float x, float y, float eps) {
210        return equalsIncludingNaN(x, y) || (Math.abs(y - x) <= eps);
211    }
212
213    /**
214     * Returns true if the arguments are equal or within the range of allowed
215     * error (inclusive).
216     * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
217     * (or fewer) floating point numbers between them, i.e. two adjacent floating
218     * point numbers are considered equal.
219     * Adapted from <a
220     * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
221     * Bruce Dawson</a>.  Returns {@code false} if either of the arguments is NaN.
222     *
223     * @param x first value
224     * @param y second value
225     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
226     * values between {@code x} and {@code y}.
227     * @return {@code true} if there are fewer than {@code maxUlps} floating
228     * point values between {@code x} and {@code y}.
229     */
230    public static boolean equals(final float x, final float y, final int maxUlps) {
231
232        final int xInt = Float.floatToRawIntBits(x);
233        final int yInt = Float.floatToRawIntBits(y);
234
235        final boolean isEqual;
236        if (((xInt ^ yInt) & SGN_MASK_FLOAT) == 0) {
237            // number have same sign, there is no risk of overflow
238            isEqual = Math.abs(xInt - yInt) <= maxUlps;
239        } else {
240            // number have opposite signs, take care of overflow
241            final int deltaPlus;
242            final int deltaMinus;
243            if (xInt < yInt) {
244                deltaPlus  = yInt - POSITIVE_ZERO_FLOAT_BITS;
245                deltaMinus = xInt - NEGATIVE_ZERO_FLOAT_BITS;
246            } else {
247                deltaPlus  = xInt - POSITIVE_ZERO_FLOAT_BITS;
248                deltaMinus = yInt - NEGATIVE_ZERO_FLOAT_BITS;
249            }
250
251            if (deltaPlus > maxUlps) {
252                isEqual = false;
253            } else {
254                isEqual = deltaMinus <= (maxUlps - deltaPlus);
255            }
256
257        }
258
259        return isEqual && !Float.isNaN(x) && !Float.isNaN(y);
260
261    }
262
263    /**
264     * Returns true if the arguments are both NaN or if they are equal as defined
265     * by {@link #equals(float,float,int) equals(x, y, maxUlps)}.
266     *
267     * @param x first value
268     * @param y second value
269     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
270     * values between {@code x} and {@code y}.
271     * @return {@code true} if both arguments are NaN or if there are less than
272     * {@code maxUlps} floating point values between {@code x} and {@code y}.
273     */
274    public static boolean equalsIncludingNaN(float x, float y, int maxUlps) {
275        final boolean xIsNan = Float.isNaN(x);
276        final boolean yIsNan = Float.isNaN(y);
277        return xIsNan || yIsNan ?
278            !(xIsNan ^ yIsNan) :
279            equals(x, y, maxUlps);
280    }
281
282    /**
283     * Returns true iff they are equal as defined by
284     * {@link #equals(double,double,int) equals(x, y, 1)}.
285     *
286     * @param x first value
287     * @param y second value
288     * @return {@code true} if the values are equal.
289     */
290    public static boolean equals(double x, double y) {
291        return equals(x, y, 1);
292    }
293
294    /**
295     * Returns true if the arguments are both NaN or they are
296     * equal as defined by {@link #equals(double,double) equals(x, y, 1)}.
297     *
298     * @param x first value
299     * @param y second value
300     * @return {@code true} if the values are equal or both are NaN.
301     */
302    public static boolean equalsIncludingNaN(double x, double y) {
303        final boolean xIsNan = Double.isNaN(x);
304        final boolean yIsNan = Double.isNaN(y);
305        return xIsNan || yIsNan ?
306            !(xIsNan ^ yIsNan) :
307            equals(x, y, 1);
308    }
309
310    /**
311     * Returns {@code true} if there is no double value strictly between the
312     * arguments or the difference between them is within the range of allowed
313     * error (inclusive). Returns {@code false} if either of the arguments
314     * is NaN.
315     *
316     * @param x First value.
317     * @param y Second value.
318     * @param eps Amount of allowed absolute error.
319     * @return {@code true} if the values are two adjacent floating point
320     * numbers or they are within range of each other.
321     */
322    public static boolean equals(double x, double y, double eps) {
323        return equals(x, y, 1) || Math.abs(y - x) <= eps;
324    }
325
326    /**
327     * Returns {@code true} if there is no double value strictly between the
328     * arguments or the relative difference between them is less than or equal
329     * to the given tolerance. Returns {@code false} if either of the arguments
330     * is NaN.
331     *
332     * @param x First value.
333     * @param y Second value.
334     * @param eps Amount of allowed relative error.
335     * @return {@code true} if the values are two adjacent floating point
336     * numbers or they are within range of each other.
337     */
338    public static boolean equalsWithRelativeTolerance(double x, double y, double eps) {
339        if (equals(x, y, 1)) {
340            return true;
341        }
342
343        final double absoluteMax = Math.max(Math.abs(x), Math.abs(y));
344        final double relativeDifference = Math.abs((x - y) / absoluteMax);
345
346        return relativeDifference <= eps;
347    }
348
349    /**
350     * Returns true if the arguments are both NaN, are equal or are within the range
351     * of allowed error (inclusive).
352     *
353     * @param x first value
354     * @param y second value
355     * @param eps the amount of absolute error to allow.
356     * @return {@code true} if the values are equal or within range of each other,
357     * or both are NaN.
358     */
359    public static boolean equalsIncludingNaN(double x, double y, double eps) {
360        return equalsIncludingNaN(x, y) || (Math.abs(y - x) <= eps);
361    }
362
363    /**
364     * Returns true if the arguments are equal or within the range of allowed
365     * error (inclusive).
366     * <p>
367     * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
368     * (or fewer) floating point numbers between them, i.e. two adjacent
369     * floating point numbers are considered equal.
370     * </p>
371     * <p>
372     * Adapted from <a
373     * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
374     * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN.
375     * </p>
376     *
377     * @param x first value
378     * @param y second value
379     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
380     * values between {@code x} and {@code y}.
381     * @return {@code true} if there are fewer than {@code maxUlps} floating
382     * point values between {@code x} and {@code y}.
383     */
384    public static boolean equals(final double x, final double y, final int maxUlps) {
385
386        final long xInt = Double.doubleToRawLongBits(x);
387        final long yInt = Double.doubleToRawLongBits(y);
388
389        final boolean isEqual;
390        if (((xInt ^ yInt) & SGN_MASK) == 0L) {
391            // number have same sign, there is no risk of overflow
392            isEqual = Math.abs(xInt - yInt) <= maxUlps;
393        } else {
394            // number have opposite signs, take care of overflow
395            final long deltaPlus;
396            final long deltaMinus;
397            if (xInt < yInt) {
398                deltaPlus  = yInt - POSITIVE_ZERO_DOUBLE_BITS;
399                deltaMinus = xInt - NEGATIVE_ZERO_DOUBLE_BITS;
400            } else {
401                deltaPlus  = xInt - POSITIVE_ZERO_DOUBLE_BITS;
402                deltaMinus = yInt - NEGATIVE_ZERO_DOUBLE_BITS;
403            }
404
405            if (deltaPlus > maxUlps) {
406                isEqual = false;
407            } else {
408                isEqual = deltaMinus <= (maxUlps - deltaPlus);
409            }
410
411        }
412
413        return isEqual && !Double.isNaN(x) && !Double.isNaN(y);
414
415    }
416
417    /**
418     * Returns true if both arguments are NaN or if they are equal as defined
419     * by {@link #equals(double,double,int) equals(x, y, maxUlps)}.
420     *
421     * @param x first value
422     * @param y second value
423     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
424     * values between {@code x} and {@code y}.
425     * @return {@code true} if both arguments are NaN or if there are less than
426     * {@code maxUlps} floating point values between {@code x} and {@code y}.
427     */
428    public static boolean equalsIncludingNaN(double x, double y, int maxUlps) {
429        final boolean xIsNan = Double.isNaN(x);
430        final boolean yIsNan = Double.isNaN(y);
431        return xIsNan || yIsNan ?
432            !(xIsNan ^ yIsNan) :
433            equals(x, y, maxUlps);
434    }
435
436    /**
437     * Rounds the given value to the specified number of decimal places.
438     * The value is rounded using the {@link RoundingMode#HALF_UP} method.
439     *
440     * @param x Value to round.
441     * @param scale Number of digits to the right of the decimal point.
442     * @return the rounded value.
443     */
444    public static double round(double x, int scale) {
445        return round(x, scale, RoundingMode.HALF_UP);
446    }
447
448    /**
449     * Rounds the given value to the specified number of decimal places.
450     * The value is rounded using the given method which is any method defined
451     * in {@link BigDecimal}.
452     * If {@code x} is infinite or {@code NaN}, then the value of {@code x} is
453     * returned unchanged, regardless of the other parameters.
454     *
455     * @param x Value to round.
456     * @param scale Number of digits to the right of the decimal point.
457     * @param roundingMethod Rounding method as defined in {@link BigDecimal}.
458     * @return the rounded value.
459     * @throws ArithmeticException if {@code roundingMethod} is
460     * {@link RoundingMode#UNNECESSARY} and the specified scaling operation
461     * would require rounding.
462     */
463    public static double round(double x,
464                               int scale,
465                               RoundingMode roundingMethod) {
466        try {
467            final double rounded = (new BigDecimal(Double.toString(x))
468                   .setScale(scale, roundingMethod))
469                   .doubleValue();
470            // MATH-1089: negative values rounded to zero should result in negative zero
471            return rounded == POSITIVE_ZERO ? POSITIVE_ZERO * x : rounded;
472        } catch (NumberFormatException ex) {
473            if (Double.isInfinite(x)) {
474                return x;
475            }
476            return Double.NaN;
477        }
478    }
479
480    /**
481     * Computes a number {@code delta} close to {@code originalDelta} with
482     * the property that <pre><code>
483     *   x + delta - x
484     * </code></pre>
485     * is exactly machine-representable.
486     * This is useful when computing numerical derivatives, in order to reduce
487     * roundoff errors.
488     *
489     * @param x Value.
490     * @param originalDelta Offset value.
491     * @return a number {@code delta} so that {@code x + delta} and {@code x}
492     * differ by a representable floating number.
493     */
494    public static double representableDelta(double x,
495                                            double originalDelta) {
496        return x + originalDelta - x;
497    }
498}