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 ^ b) < 0) { // 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 }
|