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