alpar@7: /* -*- C++ -*-
alpar@7:  *
alpar@7:  * This file is a part of LEMON, a generic C++ optimization library
alpar@7:  *
alpar@7:  * Copyright (C) 2003-2007
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: ///\todo It should be in a module like "Basic tools"
alpar@7: 
alpar@7: 
alpar@7: namespace lemon {
alpar@7: 
alpar@7:   /// \addtogroup misc
alpar@7:   /// @{
alpar@7:   
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:   ///
alpar@7:   ///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@7:   ///This is an abstract class, it should be specialized for all numerical
alpar@7:   ///data types. These specialized classes like \ref Tolerance\<double\>
alpar@7:   ///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:   ///\sa Tolerance<int>
kpeter@16: #if defined __GNUC__ && !defined __STRICT_ANSI__  
alpar@7:   ///\sa Tolerance<long long int>
kpeter@16: #endif
alpar@7:   ///\sa Tolerance<unsigned int>
kpeter@16: #if defined __GNUC__ && !defined __STRICT_ANSI__  
alpar@7:   ///\sa Tolerance<unsigned long long int>
kpeter@16: #endif
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
alpar@7:     ///The concept is that these bool functions return with \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@7:     static bool less(Value a,Value b) {return false;}
alpar@7:     ///Returns \c true if \c a is \e surely different from \c b
alpar@7:     static bool different(Value a,Value b) {return false;}
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     static bool positive(Value a) {return false;}
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     static bool negative(Value a) {return false;}
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
alpar@7:     static bool nonZero(Value a) {return false;}
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns the zero value.
alpar@7:     static Value zero() {return T();}
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@7:   ///Float specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Float specialization of \ref 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) {}
alpar@7:     ///Constructor setting the epsilon tolerance.
alpar@7:     Tolerance(float e) : _epsilon(e) {}
alpar@7: 
alpar@7:     ///Return the epsilon value.
alpar@7:     Value epsilon() const {return _epsilon;}
alpar@7:     ///Set the epsilon value.
alpar@7:     void epsilon(Value e) {_epsilon=e;}
alpar@7: 
alpar@7:     ///Return the default epsilon value.
alpar@7:     static Value defaultEpsilon() {return def_epsilon;}
alpar@7:     ///Set the default epsilon value.
alpar@7:     static void defaultEpsilon(Value e) {def_epsilon=e;}
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See class 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:   ///Double specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Double specialization of \ref 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) {}
alpar@7:     ///Constructor setting the epsilon tolerance.
alpar@7:     Tolerance(double e) : _epsilon(e) {}
alpar@7: 
alpar@7:     ///Return the epsilon value.
alpar@7:     Value epsilon() const {return _epsilon;}
alpar@7:     ///Set the epsilon value.
alpar@7:     void epsilon(Value e) {_epsilon=e;}
alpar@7: 
alpar@7:     ///Return the default epsilon value.
alpar@7:     static Value defaultEpsilon() {return def_epsilon;}
alpar@7:     ///Set the default epsilon value.
alpar@7:     static void defaultEpsilon(Value e) {def_epsilon=e;}
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See class 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:   ///Long double specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Long double specialization of \ref 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) {}
alpar@7:     ///Constructor setting the epsilon tolerance.
alpar@7:     Tolerance(long double e) : _epsilon(e) {}
alpar@7: 
alpar@7:     ///Return the epsilon value.
alpar@7:     Value epsilon() const {return _epsilon;}
alpar@7:     ///Set the epsilon value.
alpar@7:     void epsilon(Value e) {_epsilon=e;}
alpar@7: 
alpar@7:     ///Return the default epsilon value.
alpar@7:     static Value defaultEpsilon() {return def_epsilon;}
alpar@7:     ///Set the default epsilon value.
alpar@7:     static void defaultEpsilon(Value e) {def_epsilon=e;}
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See class 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:   ///Integer specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Integer specialization of \ref Tolerance.
alpar@7:   ///\sa Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<int>
alpar@7:   {
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef int Value;
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See \ref 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:     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@7:     static bool different(Value a,Value b) { return a!=b; }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     static bool positive(Value a) { return 0<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     static bool negative(Value a) { return 0>a; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     static bool nonZero(Value a) { return a!=0; }
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns zero
alpar@7:     static Value zero() {return 0;}
alpar@7:   };
alpar@7: 
alpar@7:   ///Unsigned integer specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Unsigned integer specialization of \ref Tolerance.
alpar@7:   ///\sa Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<unsigned int>
alpar@7:   {
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef unsigned int Value;
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See \ref 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:     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@7:     static bool different(Value a,Value b) { return a!=b; }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     static bool positive(Value a) { return 0<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     static bool negative(Value) { return false; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     static bool nonZero(Value a) { return a!=0; }
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:   ///Long integer specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Long integer specialization of \ref Tolerance.
alpar@7:   ///\sa Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<long int>
alpar@7:   {
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef long int Value;
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See \ref 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:     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@7:     static bool different(Value a,Value b) { return a!=b; }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     static bool positive(Value a) { return 0<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     static bool negative(Value a) { return 0>a; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     static bool nonZero(Value a) { return a!=0;}
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns zero
alpar@7:     static Value zero() {return 0;}
alpar@7:   };
alpar@7: 
alpar@7:   ///Unsigned long integer specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Unsigned long integer specialization of \ref Tolerance.
alpar@7:   ///\sa Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<unsigned long int>
alpar@7:   {
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef unsigned long int Value;
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See \ref 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:     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@7:     static bool different(Value a,Value b) { return a!=b; }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     static bool positive(Value a) { return 0<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     static bool negative(Value) { return false; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     static bool nonZero(Value a) { return a!=0;}
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns zero
alpar@7:     static Value zero() {return 0;}
alpar@7:   };
alpar@7: 
alpar@7: #if defined __GNUC__ && !defined __STRICT_ANSI__
alpar@7: 
alpar@7:   ///Long long integer specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Long long integer specialization of \ref Tolerance.
alpar@7:   ///\warning This class (more exactly, type <tt>long long</tt>)
alpar@7:   ///is not ansi compatible.
alpar@7:   ///\sa Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<long long int>
alpar@7:   {
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef long long int Value;
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See \ref 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:     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@7:     static bool different(Value a,Value b) { return a!=b; }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     static bool positive(Value a) { return 0<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     static bool negative(Value a) { return 0>a; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     static bool nonZero(Value a) { return a!=0;}
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns zero
alpar@7:     static Value zero() {return 0;}
alpar@7:   };
alpar@7: 
alpar@7:   ///Unsigned long long integer specialization of \ref Tolerance.
alpar@7: 
alpar@7:   ///Unsigned long long integer specialization of \ref Tolerance.
alpar@7:   ///\warning This class (more exactly, type <tt>unsigned long long</tt>)
alpar@7:   ///is not ansi compatible.
alpar@7:   ///\sa Tolerance
alpar@7:   template<>
alpar@7:   class Tolerance<unsigned long long int>
alpar@7:   {
alpar@7:   public:
alpar@7:     ///\e
alpar@7:     typedef unsigned long long int Value;
alpar@7: 
alpar@7:     ///\name Comparisons
alpar@7:     ///See \ref 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:     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@7:     static bool different(Value a,Value b) { return a!=b; }
alpar@7:     ///Returns \c true if \c a is \e surely positive
alpar@7:     static bool positive(Value a) { return 0<a; }
alpar@7:     ///Returns \c true if \c a is \e surely negative
alpar@7:     static bool negative(Value) { return false; }
alpar@7:     ///Returns \c true if \c a is \e surely non-zero
kpeter@16:     static bool nonZero(Value a) { return a!=0;}
alpar@7: 
alpar@7:     ///@}
alpar@7: 
alpar@7:     ///Returns zero
alpar@7:     static Value zero() {return 0;}
alpar@7:   };
alpar@7: 
alpar@7: #endif
alpar@7: 
alpar@7:   /// @}
alpar@7: 
alpar@7: } //namespace lemon
alpar@7: 
alpar@7: #endif //LEMON_TOLERANCE_H