1 | /* $Id: CoinFloatEqual.hpp 1448 2011-06-19 15:34:41Z stefan $ */ |
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 | { |
48 | public: |
49 | |
50 | //! Compare function |
51 | |
52 | inline bool operator() (const double f1, const double f2) const |
53 | |
54 | { if (CoinIsnan(f1) || CoinIsnan(f2)) return false ; |
55 | if (f1 == f2) return true ; |
56 | return (fabs(f1-f2) < epsilon_) ; } |
57 | |
58 | /*! \name Constructors and destructors */ |
59 | //@{ |
60 | |
61 | /*! \brief Default constructor |
62 | |
63 | Default tolerance is 1.0e-10. |
64 | */ |
65 | |
66 | CoinAbsFltEq () : epsilon_(1.e-10) {} |
67 | |
68 | //! Alternate constructor with epsilon as a parameter |
69 | |
70 | CoinAbsFltEq (const double epsilon) : epsilon_(epsilon) {} |
71 | |
72 | //! Destructor |
73 | |
74 | virtual ~CoinAbsFltEq () {} |
75 | |
76 | //! Copy constructor |
77 | |
78 | CoinAbsFltEq (const CoinAbsFltEq& src) : epsilon_(src.epsilon_) {} |
79 | |
80 | //! Assignment |
81 | |
82 | CoinAbsFltEq& operator= (const CoinAbsFltEq& rhs) |
83 | |
84 | { if (this != &rhs) epsilon_ = rhs.epsilon_ ; |
85 | return (*this) ; } |
86 | |
87 | //@} |
88 | |
89 | private: |
90 | |
91 | /*! \name Private member data */ |
92 | //@{ |
93 | |
94 | //! Equality tolerance. |
95 | |
96 | double epsilon_ ; |
97 | |
98 | //@} |
99 | |
100 | } ; |
101 | |
102 | |
103 | |
104 | /*! \brief Equality to a scaled tolerance |
105 | |
106 | Operands are considered equal if their difference is within a scaled |
107 | epsilon calculated as epsilon_*(1+CoinMax(|f1|,|f2|)). |
108 | */ |
109 | |
110 | class CoinRelFltEq |
111 | { |
112 | public: |
113 | |
114 | //! Compare function |
115 | |
116 | inline bool operator() (const double f1, const double f2) const |
117 | |
118 | { if (CoinIsnan(f1) || CoinIsnan(f2)) return false ; |
119 | if (f1 == f2) return true ; |
120 | if (!CoinFinite(f1) || !CoinFinite(f2)) return false ; |
121 | |
122 | double tol = (fabs(f1)>fabs(f2))?fabs(f1):fabs(f2) ; |
123 | |
124 | return (fabs(f1-f2) <= epsilon_*(1+tol)) ; } |
125 | |
126 | /*! \name Constructors and destructors */ |
127 | //@{ |
128 | |
129 | #ifndef COIN_FLOAT |
130 | /*! Default constructor |
131 | |
132 | Default tolerance is 1.0e-10. |
133 | */ |
134 | CoinRelFltEq () : epsilon_(1.e-10) {} |
135 | #else |
136 | /*! Default constructor |
137 | |
138 | Default tolerance is 1.0e-6. |
139 | */ |
140 | CoinRelFltEq () : epsilon_(1.e-6) {} ; // as float |
141 | #endif |
142 | |
143 | //! Alternate constructor with epsilon as a parameter |
144 | |
145 | CoinRelFltEq (const double epsilon) : epsilon_(epsilon) {} |
146 | |
147 | //! Destructor |
148 | |
149 | virtual ~CoinRelFltEq () {} |
150 | |
151 | //! Copy constructor |
152 | |
153 | CoinRelFltEq (const CoinRelFltEq & src) : epsilon_(src.epsilon_) {} |
154 | |
155 | //! Assignment |
156 | |
157 | CoinRelFltEq& operator= (const CoinRelFltEq& rhs) |
158 | |
159 | { if (this != &rhs) epsilon_ = rhs.epsilon_ ; |
160 | return (*this) ; } |
161 | |
162 | //@} |
163 | |
164 | private: |
165 | |
166 | /*! \name Private member data */ |
167 | //@{ |
168 | |
169 | //! Base equality tolerance |
170 | |
171 | double epsilon_ ; |
172 | |
173 | //@} |
174 | |
175 | } ; |
176 | |
177 | #endif |
178 | |