1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2003, 2004, 2005, 2007 StatPro Italia srl
5 
6  This file is part of QuantLib, a free-software/open-source library
7  for financial quantitative analysts and developers - http://quantlib.org/
8 
9  QuantLib is free software: you can redistribute it and/or modify it
10  under the terms of the QuantLib license.  You should have received a
11  copy of the license along with this program; if not, please email
12  <quantlib-dev@lists.sf.net>. The license is also available online at
13  <http://quantlib.org/license.shtml>.
14 
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the license for more details.
18 */
19 
20 /*! \file comparison.hpp
21     \brief floating-point comparisons
22 */
23 
24 #ifndef quantlib_comparison_hpp
25 #define quantlib_comparison_hpp
26 
27 #include <ql/types.hpp>
28 #include <ql/shared_ptr.hpp>
29 
30 namespace QuantLib {
31 
32     /*! Follows somewhat the advice of Knuth on checking for floating-point
33         equality. The closeness relationship is:
34         \f[
35         \mathrm{close}(x,y,n) \equiv |x-y| \leq \varepsilon |x|
36                               \wedge |x-y| \leq \varepsilon |y|
37         \f]
38         where \f$ \varepsilon \f$ is \f$ n \f$ times the machine accuracy;
39         \f$ n \f$ equals 42 if not given.
40     */
41     bool close(Real x, Real y);
42     bool close(Real x, Real y, Size n);
43 
44     /*! Follows somewhat the advice of Knuth on checking for floating-point
45         equality. The closeness relationship is:
46         \f[
47         \mathrm{close}(x,y,n) \equiv |x-y| \leq \varepsilon |x|
48                                 \vee |x-y| \leq \varepsilon |y|
49         \f]
50         where \f$ \varepsilon \f$ is \f$ n \f$ times the machine accuracy;
51         \f$ n \f$ equals 42 if not given.
52     */
53     bool close_enough(Real x, Real y);
54     bool close_enough(Real x, Real y, Size n);
55 
56 
57     // inline definitions
58 
close(Real x,Real y)59     inline bool close(Real x, Real y) {
60         return close(x,y,42);
61     }
62 
close(Real x,Real y,Size n)63     inline bool close(Real x, Real y, Size n) {
64         // Deals with +infinity and -infinity representations etc.
65         if (x == y)
66             return true;
67 
68         Real diff = std::fabs(x-y), tolerance = n * QL_EPSILON;
69 
70         if (x * y == 0.0) // x or y = 0.0
71             return diff < (tolerance * tolerance);
72 
73         return diff <= tolerance*std::fabs(x) &&
74                diff <= tolerance*std::fabs(y);
75     }
76 
close_enough(Real x,Real y)77     inline bool close_enough(Real x, Real y) {
78         return close_enough(x,y,42);
79     }
80 
close_enough(Real x,Real y,Size n)81     inline bool close_enough(Real x, Real y, Size n) {
82         // Deals with +infinity and -infinity representations etc.
83         if (x == y)
84             return true;
85 
86         Real diff = std::fabs(x-y), tolerance = n * QL_EPSILON;
87 
88         if (x * y == 0.0) // x or y = 0.0
89             return diff < (tolerance * tolerance);
90 
91         return diff <= tolerance*std::fabs(x) ||
92                diff <= tolerance*std::fabs(y);
93     }
94 
95 
96 
97     //! compare two objects by date
98     /*! There is no generic implementation of this struct.
99         Template specializations will have to be defined for
100         each needed type (see CashFlow for an example.)
101     */
102     template <class T> struct earlier_than;
103 
104     /* partial specialization for shared pointers, forwarding to their
105        pointees. */
106     template <class T>
107     struct earlier_than<ext::shared_ptr<T> > {
108         typedef ext::shared_ptr<T> first_argument_type;
109         typedef ext::shared_ptr<T> second_argument_type;
110         typedef bool result_type;
111 
operator ()QuantLib::earlier_than112         bool operator()(const ext::shared_ptr<T>& x,
113                         const ext::shared_ptr<T>& y) const {
114             return earlier_than<T>()(*x,*y);
115         }
116     };
117 
118 }
119 
120 
121 #endif
122