All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.openhft.chronicle.hash.impl.util.math.Precision Maven / Gradle / Ivy

There is a newer version: 3.26ea4
Show newest version
/*
 * Copyright 2012-2018 Chronicle Map Contributors
 * Copyright 2001-2015 The Apache Software Foundation
 * Copyright 2010-2012 CS Systèmes d'Information
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.openhft.chronicle.hash.impl.util.math;

class Precision {

    /**
     * Offset to order signed double numbers lexicographically.
     */
    private static final long SGN_MASK = 0x8000000000000000L;
    /**
     * Positive zero bits.
     */
    private static final long POSITIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(+0.0);
    /**
     * Negative zero bits.
     */
    private static final long NEGATIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(-0.0);

    /**
     * Returns {@code true} if there is no double value strictly between the
     * arguments or the difference between them is within the range of allowed
     * error (inclusive).
     *
     * @param x   First value.
     * @param y   Second value.
     * @param eps Amount of allowed absolute error.
     * @return {@code true} if the values are two adjacent floating point
     * numbers or they are within range of each other.
     */
    public static boolean isEquals(double x, double y, double eps) {
        return isEquals(x, y, 1) || Math.abs(y - x) <= eps;
    }

    /**
     * Returns true if both arguments are equal or within the range of allowed
     * error (inclusive).
     * 

* Two float numbers are considered equal if there are {@code (maxUlps - 1)} * (or fewer) floating point numbers between them, i.e. two adjacent * floating point numbers are considered equal. *

*

* Adapted from * Bruce Dawson *

* * @param x first value * @param y second value * @param maxUlps {@code (maxUlps - 1)} is the number of floating point * values between {@code x} and {@code y}. * @return {@code true} if there are fewer than {@code maxUlps} floating * point values between {@code x} and {@code y}. */ public static boolean isEquals(final double x, final double y, final int maxUlps) { final long xInt = Double.doubleToRawLongBits(x); final long yInt = Double.doubleToRawLongBits(y); final boolean isEqual; if (((xInt ^ yInt) & SGN_MASK) == 0L) { // number have same sign, there is no risk of overflow isEqual = Math.abs(xInt - yInt) <= maxUlps; } else { // number have opposite signs, take care of overflow final long deltaPlus; final long deltaMinus; if (xInt < yInt) { deltaPlus = yInt - POSITIVE_ZERO_DOUBLE_BITS; deltaMinus = xInt - NEGATIVE_ZERO_DOUBLE_BITS; } else { deltaPlus = xInt - POSITIVE_ZERO_DOUBLE_BITS; deltaMinus = yInt - NEGATIVE_ZERO_DOUBLE_BITS; } if (deltaPlus > maxUlps) { isEqual = false; } else { isEqual = deltaMinus <= (maxUlps - deltaPlus); } } return isEqual && !Double.isNaN(x) && !Double.isNaN(y); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy