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

org.jgrasstools.gears.utils.math.NumericsUtilities Maven / Gradle / Ivy

/*
 * JGrass - Free Open Source Java GIS http://www.jgrass.org 
 * (C) HydroloGIS - www.hydrologis.com 
 * 
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Library General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option) any
 * later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Library General Public License
 * along with this library; if not, write to the Free Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.jgrasstools.gears.utils.math;

import static java.lang.Math.*;
import static java.lang.Float.*;
import static java.lang.Double.*;

/**
 * Class to help out with numeric issues, mostly due to floating point usage.
 * 
 * 

* Since the floating point representation keeps a constant relative precision, * comparison is done using relative error. *

*

* Be aware of the fact that the methods *

    *
  • {@link #dEq(double, double)}
  • *
  • {@link #fEq(float, float)}
  • *
* can be used in the case of "simple" numerical * comparison, while in the case of particular values that are generated through * iterations the user/developer should consider to supply an epsilon value * derived from the knowledge of the domain of the current problem * and use the methods *
    *
  • {@link #dEq(double, double, double)}
  • *
  • {@link #fEq(float, float, float)}
  • *
*

* * @author Andrea Antonello (www.hydrologis.com) */ public class NumericsUtilities { /** * The machine epsilon for double values. */ private static double MACHINE_D_EPSILON; /** * The machine epsilon for float values. */ private static float MACHINE_F_EPSILON; // calculate the machine epsilon static { float fTmp = 0.5f; double dTmp = 0.5d; while( 1 + fTmp > 1 ) fTmp = fTmp / 2; while( 1 + dTmp > 1 ) dTmp = dTmp / 2; MACHINE_D_EPSILON = dTmp; MACHINE_F_EPSILON = fTmp; } /** * The double tolerance used for comparisons. */ private final static double D_TOLERANCE = MACHINE_D_EPSILON * 10d; /** * The float tolerance used for comparisons. */ private final static float F_TOLERANCE = MACHINE_F_EPSILON * 10f; /** * Getter for the calculated machine double epsilon. * * @return the machine epsilon for double values. */ public static double getMachineDEpsilon() { return MACHINE_D_EPSILON; } /** * Getter for the calculated machine float epsilon. * * @return the machine epsilon for float values. */ public static float machineFEpsilon() { return MACHINE_F_EPSILON; } /** * Returns true if two doubles are considered equal based on a tolerance of {@value #D_TOLERANCE}. * *

Note that two {@link Double#NaN} are seen as equal and return true.

* * @param a double to compare. * @param b double to compare. * @return true if two doubles are considered equal. */ public static boolean dEq( double a, double b ) { if (isNaN(a) && isNaN(b)) { return true; } double diffAbs = abs(a - b); return a == b ? true : diffAbs < D_TOLERANCE ? true : diffAbs / max(abs(a), abs(b)) < D_TOLERANCE; } /** * Returns true if two doubles are considered equal based on an supplied epsilon. * *

Note that two {@link Double#NaN} are seen as equal and return true.

* * @param a double to compare. * @param b double to compare. * @return true if two doubles are considered equal. */ public static boolean dEq( double a, double b, double epsilon ) { if (isNaN(a) && isNaN(b)) { return true; } double diffAbs = abs(a - b); return a == b ? true : diffAbs < epsilon ? true : diffAbs / max(abs(a), abs(b)) < epsilon; } /** * Returns true if two floats are considered equal based on a tolerance of {@value #F_TOLERANCE}. * *

Note that two {@link Float#NaN} are seen as equal and return true.

* * @param a float to compare. * @param b float to compare. * @return true if two floats are considered equal. */ public static boolean fEq( float a, float b ) { if (isNaN(a) && isNaN(b)) { return true; } float diffAbs = abs(a - b); return a == b ? true : diffAbs < F_TOLERANCE ? true : diffAbs / max(abs(a), abs(b)) < F_TOLERANCE; } /** * Returns true if two floats are considered equal based on an supplied epsilon. * *

Note that two {@link Float#NaN} are seen as equal and return true.

* * @param a float to compare. * @param b float to compare. * @return true if two float are considered equal. */ public static boolean fEq( float a, float b, float epsilon ) { if (isNaN(a) && isNaN(b)) { return true; } float diffAbs = abs(a - b); return a == b ? true : diffAbs < epsilon ? true : diffAbs / max(abs(a), abs(b)) < epsilon; } /** * Checks if a string is a number (currently Double, Float, Integer). * * @param value the string to check. * @param adaptee the class to check against. If null, the more permissive {@link Double} will be used. * @return the number or null, if the parsing fails. */ public static T isNumber( String value, Class adaptee ) { if (value == null) { return null; } if (adaptee == null || adaptee.isAssignableFrom(Double.class)) { try { Double parsed = Double.parseDouble(value); return adaptee.cast(parsed); } catch (Exception e) { return null; } } else if (adaptee.isAssignableFrom(Float.class)) { try { Float parsed = Float.parseFloat(value); return adaptee.cast(parsed); } catch (Exception e) { return null; } } else if (adaptee.isAssignableFrom(Integer.class)) { try { Integer parsed = Integer.parseInt(value); return adaptee.cast(parsed); } catch (Exception e) { try { // try also double and convert by truncating Integer parsed = (int) Double.parseDouble(value); return adaptee.cast(parsed); } catch (Exception ex) { return null; } } } else { throw new IllegalArgumentException(); } } /** * Calculates the hypothenuse as of the Pythagorean theorem. * * @param d1 the length of the first leg. * @param d2 the length of the second leg. * @return the length of the hypothenuse. */ public static double pythagoras( double d1, double d2 ) { return sqrt(pow(d1, 2.0) + pow(d2, 2.0)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy