1 /* $Id: CoinFloatEqual.hpp 2083 2019-01-06 19:38:09Z unxusr $ */ 2 // Copyright (C) 2000, International Business Machines 3 // Corporation and others. All Rights Reserved. 4 // This code is licensed under the terms of the Eclipse Public License (EPL). 5 6 #ifndef CoinFloatEqual_H 7 #define CoinFloatEqual_H 8 9 #include <algorithm> 10 #include <cmath> 11 12 #include "CoinFinite.hpp" 13 14 /*! \file CoinFloatEqual.hpp 15 \brief Function objects for testing equality of real numbers. 16 17 Two objects are provided; one tests for equality to an absolute tolerance, 18 one to a scaled tolerance. The tests will handle IEEE floating point, but 19 note that infinity == infinity. Mathematicians are rolling in their graves, 20 but this matches the behaviour for the common practice of using 21 <code>DBL_MAX</code> (<code>numeric_limits<double>::max()</code>, or similar 22 large finite number) as infinity. 23 24 <p> 25 Example usage: 26 @verbatim 27 double d1 = 3.14159 ; 28 double d2 = d1 ; 29 double d3 = d1+.0001 ; 30 31 CoinAbsFltEq eq1 ; 32 CoinAbsFltEq eq2(.001) ; 33 34 assert( eq1(d1,d2) ) ; 35 assert( !eq1(d1,d3) ) ; 36 assert( eq2(d1,d3) ) ; 37 @endverbatim 38 CoinRelFltEq follows the same pattern. */ 39 40 /*! \brief Equality to an absolute tolerance 41 42 Operands are considered equal if their difference is within an epsilon ; 43 the test does not consider the relative magnitude of the operands. 44 */ 45 46 class CoinAbsFltEq { 47 public: 48 //! Compare function 49 operator ()(const double f1,const double f2) const50 inline bool operator()(const double f1, const double f2) const 51 52 { 53 if (CoinIsnan(f1) || CoinIsnan(f2)) 54 return false; 55 if (f1 == f2) 56 return true; 57 return (fabs(f1 - f2) < epsilon_); 58 } 59 60 /*! \name Constructors and destructors */ 61 //@{ 62 63 /*! \brief Default constructor 64 65 Default tolerance is 1.0e-10. 66 */ 67 CoinAbsFltEq()68 CoinAbsFltEq() 69 : epsilon_(1.e-10) 70 { 71 } 72 73 //! Alternate constructor with epsilon as a parameter 74 CoinAbsFltEq(const double epsilon)75 CoinAbsFltEq(const double epsilon) 76 : epsilon_(epsilon) 77 { 78 } 79 80 //! Destructor 81 ~CoinAbsFltEq()82 virtual ~CoinAbsFltEq() {} 83 84 //! Copy constructor 85 CoinAbsFltEq(const CoinAbsFltEq & src)86 CoinAbsFltEq(const CoinAbsFltEq &src) 87 : epsilon_(src.epsilon_) 88 { 89 } 90 91 //! Assignment 92 operator =(const CoinAbsFltEq & rhs)93 CoinAbsFltEq &operator=(const CoinAbsFltEq &rhs) 94 95 { 96 if (this != &rhs) 97 epsilon_ = rhs.epsilon_; 98 return (*this); 99 } 100 101 //@} 102 103 private: 104 /*! \name Private member data */ 105 //@{ 106 107 //! Equality tolerance. 108 109 double epsilon_; 110 111 //@} 112 }; 113 114 /*! \brief Equality to a scaled tolerance 115 116 Operands are considered equal if their difference is within a scaled 117 epsilon calculated as epsilon_*(1+CoinMax(|f1|,|f2|)). 118 */ 119 120 class CoinRelFltEq { 121 public: 122 //! Compare function 123 operator ()(const double f1,const double f2) const124 inline bool operator()(const double f1, const double f2) const 125 126 { 127 if (CoinIsnan(f1) || CoinIsnan(f2)) 128 return false; 129 if (f1 == f2) 130 return true; 131 if (!CoinFinite(f1) || !CoinFinite(f2)) 132 return false; 133 134 double tol = (fabs(f1) > fabs(f2)) ? fabs(f1) : fabs(f2); 135 136 return (fabs(f1 - f2) <= epsilon_ * (1 + tol)); 137 } 138 139 /*! \name Constructors and destructors */ 140 //@{ 141 142 #ifndef COIN_FLOAT 143 /*! Default constructor 144 145 Default tolerance is 1.0e-10. 146 */ CoinRelFltEq()147 CoinRelFltEq() 148 : epsilon_(1.e-10) 149 { 150 } 151 #else 152 /*! Default constructor 153 154 Default tolerance is 1.0e-6. 155 */ CoinRelFltEq()156 CoinRelFltEq() 157 : epsilon_(1.e-6) {}; // as float 158 #endif 159 160 //! Alternate constructor with epsilon as a parameter 161 CoinRelFltEq(const double epsilon)162 CoinRelFltEq(const double epsilon) 163 : epsilon_(epsilon) 164 { 165 } 166 167 //! Destructor 168 ~CoinRelFltEq()169 virtual ~CoinRelFltEq() {} 170 171 //! Copy constructor 172 CoinRelFltEq(const CoinRelFltEq & src)173 CoinRelFltEq(const CoinRelFltEq &src) 174 : epsilon_(src.epsilon_) 175 { 176 } 177 178 //! Assignment 179 operator =(const CoinRelFltEq & rhs)180 CoinRelFltEq &operator=(const CoinRelFltEq &rhs) 181 182 { 183 if (this != &rhs) 184 epsilon_ = rhs.epsilon_; 185 return (*this); 186 } 187 188 //@} 189 190 private: 191 /*! \name Private member data */ 192 //@{ 193 194 //! Base equality tolerance 195 196 double epsilon_; 197 198 //@} 199 }; 200 201 #endif 202 203 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 204 */ 205