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

toolgood.algorithm.mathNet.Precision Maven / Gradle / Ivy

package toolgood.algorithm.mathNet;

public class Precision {
    /// 
    /// Standard epsilon, the maximum relative precision of IEEE 754
    /// double-precision floating numbers (64 bit).
    /// According to the definition of Prof. Demmel and used in LAPACK and Scilab.
    /// 
    public final static double DoublePrecision = Math.pow(2, -53);

    /// 
    /// Standard epsilon, the maximum relative precision of IEEE 754
    /// double-precision floating numbers (64 bit).
    /// According to the definition of Prof. Higham and used in the ISO C standard
    /// and MATLAB.
    /// 
    public final static double PositiveDoublePrecision = 2 * DoublePrecision;

    /// 
    /// Value representing 10 * 2^(-53) = 1.11022302462516E-15
    /// 
   final static double DefaultDoubleAccuracy = DoublePrecision * 10;

    public static double Increment(double value) {
        return Increment(value, -1);
    }

    /// 
    /// Increments a floating point number to the next bigger number representable
    /// by the data type.
    /// 
    /// The value which needs to be incremented.
    /// How many times the number should be incremented.
    /// 
    /// The incrementation step length depends on the provided value.
    /// Increment(double.MaxValue) will return positive infinity.
    /// 
    /// The next larger floating point value.
    public static double Increment(double value, int count) {
        if (Double.isInfinite(value) || Double.isNaN(value) || count == 0) {
            return value;
        }

        // Translate the bit pattern of the double to an integer.
        // Note that this leads to:
        // double > 0 --> long > 0, growing as the double value grows
        // double < 0 --> long < 0, increasing in absolute magnitude as the double
        // gets closer to zero!
        // i.e. 0 - double.epsilon will give the largest long value!
        long intValue = (long)value;
        // long intValue = BitConverter.DoubleToInt64Bits(value);
        if (intValue < 0) {
            intValue -= count;
        } else {
            intValue += count;
        }

        // Note that long.MinValue has the same bit pattern as -0.0.
        if (intValue == Long.MIN_VALUE) {
            return 0;
        }
        return intValue;
        // Note that not all long values can be translated into double values. There's a
        // whole bunch of them
        // which return weird values like infinity and NaN
        // return BitConverter.Int64BitsToDouble(intValue);
    }

    /// 
    /// Evaluates the minimum distance to the next distinguishable number near the
    /// argument value.
    /// 
    /// The value used to determine the minimum
    /// distance.
    /// 
    /// Relative Epsilon (positive double or NaN).
    /// 
    /// Evaluates the negative epsilon. The more common positive
    /// epsilon is equal to two times this negative epsilon.
    ///// 
    public static double EpsilonOf(double value) {
        if (Double.isInfinite(value) || Double.isNaN(value)) {
            return Double.NaN;
        }

        long signed64 = (long)value;
        // long signed64 = BitConverter.DoubleToInt64Bits(value);
        if (signed64 == 0) {
            signed64++;
            return signed64 - value;
            // return BitConverter.Int64BitsToDouble(signed64) - value;
        }
        if (signed64-- < 0) {
            return  signed64 - value;
            // return BitConverter.Int64BitsToDouble(signed64) - value;
        }
        return value -  signed64;
        // return value - BitConverter.Int64BitsToDouble(signed64);
    }

    /// 
    /// Evaluates the minimum distance to the next distinguishable number near the
    /// argument value.
    /// 
    /// The value used to determine the minimum
    /// distance.
    /// Relative Epsilon (positive double or NaN)
    /// Evaluates the positive epsilon. See also 
    ///// 
    public static double PositiveEpsilonOf(double value) {
        return 2 * EpsilonOf(value);
    }

    public static boolean AlmostEqualNormRelative(double a, double b, double diff, double maximumError) {
        // If A or B are infinity (positive or negative) then
        // only return true if they are exactly equal to each other -
        // that is, if they are both infinities of the same sign.
        if (Double.isInfinite(a) || Double.isInfinite(b)) {
            return a == b;
        }

        // If A or B are a NAN, return false. NANs are equal to nothing,
        // not even themselves.
        if (Double.isNaN(a) || Double.isNaN(b)) {
            return false;
        }

        // If one is almost zero, fall back to absolute equality
        if (Math.abs(a) < DoublePrecision || Math.abs(b) < DoublePrecision) {
            return Math.abs(diff) < maximumError;
        }

        if ((a == 0 && Math.abs(b) < maximumError) || (b == 0 && Math.abs(a) < maximumError)) {
            return true;
        }

        return Math.abs(diff) < maximumError * Math.max(Math.abs(a), Math.abs(b));
    }

    public static boolean AlmostEqualRelative(double a, double b) {
        return AlmostEqualNormRelative(a, b, a - b, DefaultDoubleAccuracy);
    }

    public static boolean AlmostEqual(double a, double b) {
        return AlmostEqualNorm(a, b, a - b, DefaultDoubleAccuracy);
    }

    public static boolean AlmostEqualNorm(double a, double b, double diff, double maximumAbsoluteError) {
        // If A or B are infinity (positive or negative) then
        // only return true if they are exactly equal to each other -
        // that is, if they are both infinities of the same sign.
        if (Double.isInfinite(a) || Double.isInfinite(b)) {
            return a == b;
        }

        // If A or B are a NAN, return false. NANs are equal to nothing,
        // not even themselves.
        if (Double.isNaN(a) || Double.isNaN(b)) {
            return false;
        }

        return Math.abs(diff) < maximumAbsoluteError;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy