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