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\ alpar@7: ///may offer additional tuning parameters. alpar@7: /// alpar@7: ///\sa Tolerance alpar@7: ///\sa Tolerance alpar@7: ///\sa Tolerance alpar@7: ///\sa Tolerance alpar@7: ///\sa Tolerance alpar@7: ///\sa Tolerance alpar@7: ///\sa Tolerance alpar@7: alpar@7: template 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 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+_epsilona; } alpar@7: ///Returns \c true if \c a is \e surely non-zero alpar@7: 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 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+_epsilona; } alpar@7: ///Returns \c true if \c a is \e surely non-zero alpar@7: 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 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+_epsilona; } alpar@7: ///Returns \c true if \c a is \e surely non-zero alpar@7: 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 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 aa; } alpar@7: ///Returns \c true if \c a is \e surely non-zero alpar@7: 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 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 alpar@7: class Tolerance 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 aa; } alpar@7: ///Returns \c true if \c a is \e surely non-zero alpar@7: 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 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 along long) alpar@7: ///is not ansi compatible. alpar@7: ///\sa Tolerance alpar@7: template<> alpar@7: class Tolerance 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 aa; } alpar@7: ///Returns \c true if \c a is \e surely non-zero alpar@7: 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 unsigned long long) alpar@7: ///is not ansi compatible. alpar@7: ///\sa Tolerance alpar@7: template<> alpar@7: class Tolerance 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