MathUtils.java
01 /*
02  * Java GPX Library (jpx-3.1.0).
03  * Copyright (c) 2016-2023 Franz Wilhelmstötter
04  *
05  * Licensed under the Apache License, Version 2.0 (the "License");
06  * you may not use this file except in compliance with the License.
07  * You may obtain a copy of the License at
08  *
09  *      http://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  * Author:
18  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
19  */
20 package io.jenetics.jpx.geom;
21 
22 import static java.lang.Double.doubleToRawLongBits;
23 
24 /**
25  * Mathematical helper functions.
26  *
27  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
28  @version 2.1
29  @since 2.1
30  */
31 final class MathUtils {
32 
33     private static final long POSITIVE_ZERO_BITS = doubleToRawLongBits(+0.0);
34     private static final long NEGATIVE_ZERO_BITS = doubleToRawLongBits(-0.0);
35 
36     private MathUtils() {
37     }
38 
39     /**
40      * Returns {@code true} if the given {@code double} values are equal within
41      * the range of allowed ULP error (inclusive). The values are considered
42      * equal if there are maximal {@code (ulps - 1)} {@code double} values
43      * between them.
44      *
45      @param x first value to compare
46      @param y second value to compare
47      @param ulps the maximal ULP distance (epsilon)
48      @return {@code true} if there are fewer than {@code ulps}values between
49      *         {@code x} and {@code y}, {@code false} otherwise
50      */
51     static boolean equal(final double x, final double y, final int ulps) {
52         long a = doubleToRawLongBits(x);
53         long b = doubleToRawLongBits(y);
54         if (a < b) {
55             final long t = a; a = b; b = t;
56         }
57 
58         final boolean equal;
59         if ((a ^ b0) { // a and b have opposite sign.
60             final long diffPositive = a - POSITIVE_ZERO_BITS;
61             final long diffNegative = b - NEGATIVE_ZERO_BITS;
62             equal = diffPositive <= ulps && diffNegative <= (ulps - diffPositive);
63         else {         // a and b have same sign.
64             equal = a - b <= ulps;
65         }
66 
67         return equal && !Double.isNaN(x&& !Double.isNaN(y);
68     }
69 
70 }