// Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. #ifndef CoinFloatEqual_H #define CoinFloatEqual_H #include # #include #include "CoinFinite.hpp" /*! \file CoinFloatEqual.hpp \brief Function objects for testing equality of real numbers. Two objects are provided; one tests for equality to an absolute tolerance, one to a scaled tolerance. The tests will handle IEEE floating point, but note that infinity == infinity. Mathematicians are rolling in their graves, but this matches the behaviour for the common practice of using DBL_MAX (numeric_limits::max(), or similar large finite number) as infinity.

Example usage: @verbatim double d1 = 3.14159 ; double d2 = d1 ; double d3 = d1+.0001 ; CoinAbsFltEq eq1 ; CoinAbsFltEq eq2(.001) ; assert( eq1(d1,d2) ) ; assert( !eq1(d1,d3) ) ; assert( eq2(d1,d3) ) ; @endverbatim CoinRelFltEq follows the same pattern. */ /*! \brief Equality to an absolute tolerance Operands are considered equal if their difference is within an epsilon ; the test does not consider the relative magnitude of the operands. */ class CoinAbsFltEq { public: //! Compare function inline bool operator() (const double f1, const double f2) const { if (CoinIsnan(f1) || CoinIsnan(f2)) return false ; if (f1 == f2) return true ; return (fabs(f1-f2) < epsilon_) ; } /*! \name Constructors and destructors */ //@{ //! Default constructor CoinAbsFltEq () : epsilon_(1.e-10) {} //! Alternate constructor with epsilon as a parameter CoinAbsFltEq (const double epsilon) : epsilon_(epsilon) {} //! Destructor virtual ~CoinAbsFltEq () {} //! Copy constructor CoinAbsFltEq (const CoinAbsFltEq& src) : epsilon_(src.epsilon_) {} //! Assignment CoinAbsFltEq& operator= (const CoinAbsFltEq& rhs) { if (this != &rhs) epsilon_ = rhs.epsilon_ ; return (*this) ; } //@} private: /*! \name Private member data */ //@{ //! Equality tolerance. double epsilon_ ; //@} } ; /*! \brief Equality to a scaled tolerance Operands are considered equal if their difference is within a scaled epsilon calculated as epsilon_*(1+max(|f1|,|f2|)). */ class CoinRelFltEq { public: //! Compare function inline bool operator() (const double f1, const double f2) const { if (CoinIsnan(f1) || CoinIsnan(f2)) return false ; if (f1 == f2) return true ; if (!CoinFinite(f1) || !CoinFinite(f2)) return false ; double tol = (fabs(f1)>fabs(f2))?fabs(f1):fabs(f2) ; return (fabs(f1-f2) <= epsilon_*(1+tol)) ; } /*! \name Constructors and destructors */ //@{ //! Default constructor #ifndef COIN_FLOAT CoinRelFltEq () : epsilon_(1.e-10) {} #else CoinRelFltEq () : epsilon_(1.e-6) {} ; // as float #endif //! Alternate constructor with epsilon as a parameter CoinRelFltEq (const double epsilon) : epsilon_(epsilon) {} //! Destructor virtual ~CoinRelFltEq () {} //! Copy constructor CoinRelFltEq (const CoinRelFltEq & src) : epsilon_(src.epsilon_) {} //! Assignment CoinRelFltEq& operator= (const CoinRelFltEq& rhs) { if (this != &rhs) epsilon_ = rhs.epsilon_ ; return (*this) ; } //@} private: /*! \name Private member data */ //@{ //! Base equality tolerance double epsilon_ ; //@} } ; #endif