summaryrefslogtreecommitdiff
path: root/thirdparty/linux/include/coin1/CoinFloatEqual.hpp
blob: d5edfffa803d3b2ceda853e3c5e878cddd765893 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/* $Id: CoinFloatEqual.hpp 1416 2011-04-17 09:57:29Z stefan $ */
// Copyright (C) 2000, International Business Machines
// Corporation and others.  All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).

#ifndef CoinFloatEqual_H
#define CoinFloatEqual_H

#include <algorithm>
#include <cmath>

#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
  <code>DBL_MAX</code> (<code>numeric_limits<double>::max()</code>, or similar
  large finite number) as infinity.

  <p>
  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 */
  //@{

  /*! \brief Default constructor

    Default tolerance is 1.0e-10.
  */

  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+CoinMax(|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 */
  //@{

#ifndef COIN_FLOAT
  /*! Default constructor

    Default tolerance is 1.0e-10.
  */
  CoinRelFltEq () : epsilon_(1.e-10) {} 
#else
  /*! Default constructor

    Default tolerance is 1.0e-6.
  */
  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