/** * Copyright 2010-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ package com.jogamp.math; /** * Basic Double math utility functions. */ public final class DoubleUtil { // // Scalar Ops // @SuppressWarnings("unused") private static void calculateMachineEpsilonDouble() { final long t0; double machEps = 1.0; int i=0; do { machEps /= 2.0; i++; } while (1.0 + (machEps / 2.0) != 1.0); machEpsilon = machEps; } private static volatile boolean machEpsilonAvail = false; private static double machEpsilon = 0f; /** * Return computed machine Epsilon value. *
* The machine Epsilon value is computed once. *
* @see #EPSILON */ public static double getMachineEpsilon() { if( !machEpsilonAvail ) { synchronized(DoubleUtil.class) { if( !machEpsilonAvail ) { machEpsilonAvail = true; calculateMachineEpsilonDouble(); } } } return machEpsilon; } public static final double E = 2.7182818284590452354; /** The value PI, i.e. 180 degrees in radians. */ public static final double PI = 3.14159265358979323846; /** The value 2PI, i.e. 360 degrees in radians. */ public static final double TWO_PI = 2.0 * PI; /** The value PI/2, i.e. 90 degrees in radians. */ public static final double HALF_PI = PI / 2.0; /** The value PI/4, i.e. 45 degrees in radians. */ public static final double QUARTER_PI = PI / 4.0; /** The value PI^2. */ public final static double SQUARED_PI = PI * PI; /** Converts arc-degree to radians */ public static double adegToRad(final double arc_degree) { return arc_degree * PI / 180.0; } /** Converts radians to arc-degree */ public static double radToADeg(final double rad) { return rad * 180.0 / PI; } /** * Epsilon for floating point {@value}, as once computed via {@link #getMachineEpsilon()} on an AMD-64 CPU. ** Definition of machine epsilon guarantees that: *
* 1.0 + EPSILON != 1.0 ** In other words: machEps is the maximum relative error of the chosen rounding procedure. * *
* A number can be considered zero if it is in the range (or in the set): *
* MaybeZeroSet e ]-machEps .. machEps[ (exclusive) ** While comparing floating point values, machEps allows to clip the relative error: *
* boolean isZero = afloat < EPSILON; * boolean isNotZero = afloat >= EPSILON; * * boolean isEqual = abs(bfloat - afloat) < EPSILON; * boolean isNotEqual = abs(bfloat - afloat) >= EPSILON; ** * @see #isEqual(float, float, float) * @see #isZero(float, float) */ public static final double EPSILON = 2.220446049250313E-16; /** * Inversion Epsilon, used with equals method to determine if two inverted matrices are close enough to be considered equal. *
* Using {@value}, which is ~100 times {@link DoubleUtil#EPSILON}. *
*/ public static final double INV_DEVIANCE = 1.0E-8f; // EPSILON == 1.1920929E-7f; double ALLOWED_DEVIANCE: 1.0E-8f /** * Return true if both values are equal w/o regarding an epsilon. ** Implementation considers following corner cases: *
* {@code epsilon} is allowed to be {@code 0}. *
** Implementation considers following corner cases: *
* Implementation considers following corner cases: *
* Implementation does not consider corner cases like {@link #isEqual(float, float, float)}. *
* @see #EPSILON */ public static boolean isEqual2(final double a, final double b) { return Math.abs(a - b) < EPSILON; } /** * Returns true if both values are equal w/o regarding an epsilon. ** Implementation considers following corner cases: *
* {@code epsilon} is allowed to be {@code 0}. *
** Implementation considers following corner cases: *
* {@code epsilon} is allowed to be {@code 0}. *
** return 0 == epsilon && 0 == a || 0 != epsilon && Math.abs(a) < epsilon ** @param a value to test * @param epsilon optional positive epsilon value, maybe {@code 0} * @see #EPSILON */ public static boolean isZero(final double a, final double epsilon) { return 0 == epsilon && a == 0 || 0 != epsilon && Math.abs(a) < epsilon; } /** * Returns true if value is zero, i.e. it's absolute value < {@link #EPSILON}. * @see #EPSILON */ public static boolean isZero(final double a) { return Math.abs(a) < EPSILON; } }