alpar@209: /* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@7:  *
alpar@209:  * This file is a part of LEMON, a generic C++ optimization library.
alpar@7:  *
alpar@440:  * Copyright (C) 2003-2009
alpar@7:  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@7:  * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@7:  *
alpar@7:  * Permission to use, modify and distribute this software is granted
alpar@7:  * provided that this copyright notice appears in all copies. For
alpar@7:  * precise terms see the accompanying LICENSE file.
alpar@7:  *
alpar@7:  * This software is provided "AS IS" with no warranty of any kind,
alpar@7:  * express or implied, and with no claim as to its suitability for any
alpar@7:  * purpose.
alpar@7:  *
alpar@7:  */
alpar@7: 
alpar@7: #ifndef LEMON_TOLERANCE_H
alpar@7: #define LEMON_TOLERANCE_H
alpar@7: 
alpar@7: ///\ingroup misc
alpar@7: ///\file
alpar@7: ///\brief A basic tool to handle the anomalies of calculation with
alpar@7: ///floating point numbers.
alpar@7: ///
alpar@7: 
alpar@7: namespace lemon {
alpar@7: 
alpar@7:   /// \addtogroup misc
alpar@7:   /// @{
alpar@209: 
alpar@7:   ///\brief A class to provide a basic way to
alpar@7:   ///handle the comparison of numbers that are obtained
alpar@7:   ///as a result of a probably inexact computation.
alpar@7:   ///
kpeter@49:   ///\ref Tolerance is a class to provide a basic way to
alpar@7:   ///handle the comparison of numbers that are obtained
alpar@7:   ///as a result of a probably inexact computation.
alpar@7:   ///
alpar@486:   ///The general implementation is suitable only if the data type is exact,
alpar@486:   ///like the integer types, otherwise a specialized version must be
alpar@486:   ///implemented. These specialized classes like
kpeter@72:   ///Tolerance<double> may offer additional tuning parameters.
alpar@7:   ///
alpar@7:   ///\sa Tolerance<float>
alpar@7:   ///\sa Tolerance<double>
alpar@7:   ///\sa Tolerance<long double>
alpar@7: 
alpar@7:   template<class T>
alpar@7:   class Tolerance
alpar@7:   {
alpar@7:   public:
alpar@7:     typedef T Value;
alpar@7: 
alpar@7:     ///\name Comparisons
kpeter@49:     ///The concept is that these bool functions return \c true only if
alpar@7:     ///the related comparisons hold even if some numerical error appeared
alpar@7:     ///during the computations.
alpar@7: 
alpar@7:     ///@{
alpar@7: 
alpar@7:     ///Returns \c true if \c a is \e surely strictly less than \c b
alpar@486:     static bool less(Value a,Value b) {return a<b;}
alpar@7:     ///Returns \c true if \c a is \e surely different from \c b
alpar@486:     static bool different(Value a,Value b) {return a!=b;}
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@486:     static bool positive(Value a) {return static_cast<Value>(0) < a;}
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@486:     static bool negative(Value a) {return a < static_cast<Value>(0);}
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
alpar@486:     static bool nonZero(Value a) {return a != static_cast<Value>(0);}
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns the zero value.
alpar@486:     static Value zero() {return static_cast<Value>(0);}
alpar@7: 
alpar@7:     //   static bool finite(Value a) {}
alpar@7:     //   static Value big() {}
alpar@7:     //   static Value negativeBig() {}
alpar@7:   };
alpar@7: 
alpar@7: 
alpar@42:   ///Float specialization of Tolerance.
alpar@7: 
alpar@42:   ///Float specialization of Tolerance.
alpar@7:   ///\sa Tolerance
alpar@7:   ///\relates Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<float>
alpar@7:   {
alpar@7:     static float def_epsilon;
alpar@7:     float _epsilon;
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef float Value;
alpar@7: 
alpar@7:     ///Constructor setting the epsilon tolerance to the default value.
alpar@7:     Tolerance() : _epsilon(def_epsilon) {}
kpeter@49:     ///Constructor setting the epsilon tolerance to the given value.
alpar@7:     Tolerance(float e) : _epsilon(e) {}
alpar@7: 
kpeter@49:     ///Returns the epsilon value.
alpar@7:     Value epsilon() const {return _epsilon;}
kpeter@49:     ///Sets the epsilon value.
alpar@7:     void epsilon(Value e) {_epsilon=e;}
alpar@7: 
kpeter@49:     ///Returns the default epsilon value.
alpar@7:     static Value defaultEpsilon() {return def_epsilon;}
kpeter@49:     ///Sets the default epsilon value.
alpar@7:     static void defaultEpsilon(Value e) {def_epsilon=e;}
alpar@7: 
alpar@7:     ///\name Comparisons
kpeter@72:     ///See \ref lemon::Tolerance "Tolerance" for more details.
alpar@7: 
alpar@7:     ///@{
alpar@7: 
alpar@7:     ///Returns \c true if \c a is \e surely strictly less than \c b
alpar@7:     bool less(Value a,Value b) const {return a+_epsilon<b;}
alpar@7:     ///Returns \c true if \c a is \e surely different from \c b
alpar@7:     bool different(Value a,Value b) const { return less(a,b)||less(b,a); }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     bool positive(Value a) const { return _epsilon<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     bool negative(Value a) const { return -_epsilon>a; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     bool nonZero(Value a) const { return positive(a)||negative(a); }
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns zero
alpar@7:     static Value zero() {return 0;}
alpar@7:   };
alpar@7: 
alpar@42:   ///Double specialization of Tolerance.
alpar@7: 
alpar@42:   ///Double specialization of Tolerance.
alpar@7:   ///\sa Tolerance
alpar@7:   ///\relates Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<double>
alpar@7:   {
alpar@7:     static double def_epsilon;
alpar@7:     double _epsilon;
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef double Value;
alpar@7: 
alpar@7:     ///Constructor setting the epsilon tolerance to the default value.
alpar@7:     Tolerance() : _epsilon(def_epsilon) {}
kpeter@49:     ///Constructor setting the epsilon tolerance to the given value.
alpar@7:     Tolerance(double e) : _epsilon(e) {}
alpar@7: 
kpeter@49:     ///Returns the epsilon value.
alpar@7:     Value epsilon() const {return _epsilon;}
kpeter@49:     ///Sets the epsilon value.
alpar@7:     void epsilon(Value e) {_epsilon=e;}
alpar@7: 
kpeter@49:     ///Returns the default epsilon value.
alpar@7:     static Value defaultEpsilon() {return def_epsilon;}
kpeter@49:     ///Sets the default epsilon value.
alpar@7:     static void defaultEpsilon(Value e) {def_epsilon=e;}
alpar@7: 
alpar@7:     ///\name Comparisons
kpeter@72:     ///See \ref lemon::Tolerance "Tolerance" for more details.
alpar@7: 
alpar@7:     ///@{
alpar@7: 
alpar@7:     ///Returns \c true if \c a is \e surely strictly less than \c b
alpar@7:     bool less(Value a,Value b) const {return a+_epsilon<b;}
alpar@7:     ///Returns \c true if \c a is \e surely different from \c b
alpar@7:     bool different(Value a,Value b) const { return less(a,b)||less(b,a); }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     bool positive(Value a) const { return _epsilon<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     bool negative(Value a) const { return -_epsilon>a; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     bool nonZero(Value a) const { return positive(a)||negative(a); }
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns zero
alpar@7:     static Value zero() {return 0;}
alpar@7:   };
alpar@7: 
alpar@42:   ///Long double specialization of Tolerance.
alpar@7: 
alpar@42:   ///Long double specialization of Tolerance.
alpar@7:   ///\sa Tolerance
alpar@7:   ///\relates Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<long double>
alpar@7:   {
alpar@7:     static long double def_epsilon;
alpar@7:     long double _epsilon;
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef long double Value;
alpar@7: 
alpar@7:     ///Constructor setting the epsilon tolerance to the default value.
alpar@7:     Tolerance() : _epsilon(def_epsilon) {}
kpeter@49:     ///Constructor setting the epsilon tolerance to the given value.
alpar@7:     Tolerance(long double e) : _epsilon(e) {}
alpar@7: 
kpeter@49:     ///Returns the epsilon value.
alpar@7:     Value epsilon() const {return _epsilon;}
kpeter@49:     ///Sets the epsilon value.
alpar@7:     void epsilon(Value e) {_epsilon=e;}
alpar@7: 
kpeter@49:     ///Returns the default epsilon value.
alpar@7:     static Value defaultEpsilon() {return def_epsilon;}
kpeter@49:     ///Sets the default epsilon value.
alpar@7:     static void defaultEpsilon(Value e) {def_epsilon=e;}
alpar@7: 
alpar@7:     ///\name Comparisons
kpeter@72:     ///See \ref lemon::Tolerance "Tolerance" for more details.
alpar@7: 
alpar@7:     ///@{
alpar@7: 
alpar@7:     ///Returns \c true if \c a is \e surely strictly less than \c b
alpar@7:     bool less(Value a,Value b) const {return a+_epsilon<b;}
alpar@7:     ///Returns \c true if \c a is \e surely different from \c b
alpar@7:     bool different(Value a,Value b) const { return less(a,b)||less(b,a); }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     bool positive(Value a) const { return _epsilon<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     bool negative(Value a) const { return -_epsilon>a; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     bool nonZero(Value a) const { return positive(a)||negative(a); }
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns zero
alpar@7:     static Value zero() {return 0;}
alpar@7:   };
alpar@7: 
alpar@7:   /// @}
alpar@7: 
alpar@7: } //namespace lemon
alpar@7: 
alpar@7: #endif //LEMON_TOLERANCE_H