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
46class 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
110class 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
164private:
165
166 /*! \name Private member data */
167 //@{
168
169 //! Base equality tolerance
170
171 double epsilon_ ;
172
173 //@}
174
175} ;
176
177#endif
178