fuzzy.hpp
Go to the documentation of this file.
00001 
00011 /*****************************************************************************
00012 ** Ifdefs
00013 *****************************************************************************/
00014 
00015 #ifndef ECL_MATH_FUZZY_HPP_
00016 #define ECL_MATH_FUZZY_HPP_
00017 
00018 /*****************************************************************************
00019 ** Includes
00020 *****************************************************************************/
00021 
00022 //#include "num_traits.hpp"
00023 #include <cmath> // floating point std::abs
00024 #include <cstdlib> // integral std::abs
00025 #include <algorithm> // std::min, std::max
00026 #include <ecl/type_traits/numeric_limits.hpp>
00027 
00028 /*****************************************************************************
00029 ** Namespaces
00030 *****************************************************************************/
00031 
00032 namespace ecl {
00036 namespace implementations {
00037 
00038 /****************************************************************************
00039 * Implementation of fuzzy comparisons                                       *
00040 ****************************************************************************/
00041 
00047 template<typename Scalar,
00048          bool IsInteger>
00049 struct scalar_fuzzy_default_impl {};
00050 
00056 template<typename Scalar>
00057 struct scalar_fuzzy_default_impl<Scalar, false>
00058 {
00059         typedef typename ecl::numeric_limits<Scalar>::Precision Precision;
00060 
00061         template<typename OtherScalar>
00062         static inline bool isApprox(const Scalar& x, const OtherScalar& y, const Precision& prec) {
00063                 // casting just in case y is an integer type.
00064                 return std::abs(x - static_cast<Scalar>(y)) <= std::min( std::abs(x),  std::abs(static_cast<Scalar>(y))) * prec;
00065         }
00066 
00067         template<typename OtherScalar>
00068         static inline bool isApproxOrLessThan(const Scalar& x, const OtherScalar& y, const Precision& prec) {
00069                 return x <= y || isApprox(x, y, prec);
00070         }
00071 };
00072 
00078 template<typename Scalar>
00079 struct scalar_fuzzy_default_impl<Scalar, true> {
00080 
00081         typedef typename ecl::numeric_limits<Scalar>::Precision Precision;
00082 
00083         template<typename OtherScalar>
00084         static inline bool isApprox(const Scalar& x, const OtherScalar& y, const Precision& prec) {
00085                 // this will trigger if default argument is used (dummy precision for integers == 0)
00086                 if ( ecl::numeric_limits<OtherScalar>::is_integer ) {
00087                         return x == y;
00088                 } else {
00089                         // only get here if its not complex, so OtherScalar has to be a floating type
00090                         typename ecl::numeric_limits<OtherScalar>::Precision precision;
00091                         if ( prec == 0.0 ) {
00092                                 precision = ecl::numeric_limits<OtherScalar>::dummy_precision;
00093                         } else {
00094                                 precision = static_cast<OtherScalar>(prec);
00095                         }
00096                         return std::abs(static_cast<OtherScalar>(x) - y) <= std::min( std::abs(static_cast<OtherScalar>(x)),  std::abs(y)) * precision;
00097                 }
00098         }
00099         template<typename OtherScalar>
00100         static inline bool isApproxOrLessThan(const Scalar& x, const OtherScalar& y, const Precision&) {
00101                 return x <= y;
00102         }
00103 };
00104 
00106 // * @brief Fuzzy math implementation for complex numbers.
00107 // *
00108 // * Specialisation of fuzzy math functions for complex numbers.
00109 // *
00110 // * @tparam Scalar : autoselected by numeric traits as always being complex.
00111 // */
00112 //template<typename Scalar>
00113 //struct scalar_fuzzy_default_impl<Scalar, true, false> {
00114 //      typedef typename ecl::NumTraits<Scalar>::Precision Precision;
00115 //
00116 //      static inline bool isApprox(const Scalar& x, const Scalar& y, const Precision& prec) {
00117 //              return ei_abs2(x - y) <= std::min(ei_abs2(x), ei_abs2(y)) * prec * prec;
00118 //      }
00119 //};
00120 
00128 template<typename Scalar>
00129 struct scalar_fuzzy_impl : implementations::scalar_fuzzy_default_impl<Scalar, numeric_limits<Scalar>::is_integer> {};
00130 
00131 } // implementations
00132 
00136 /*****************************************************************************
00137 ** Direct Interfaces
00138 *****************************************************************************/
00139 
00153 template<typename Scalar, typename OtherScalar>
00154 inline bool isApprox(const Scalar& x, const OtherScalar& y, typename numeric_limits<Scalar>::Precision precision = numeric_limits<Scalar>::dummy_precision) {
00155         return implementations::scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
00156 }
00157 
00171 template<typename Scalar, typename OtherScalar>
00172 inline bool isApproxOrLessThan(const Scalar& x, const OtherScalar& y, typename numeric_limits<Scalar>::Precision precision = numeric_limits<Scalar>::dummy_precision) {
00173         return implementations::scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
00174 }
00175 
00176 
00177 
00178 } // namespace ecl
00179 
00180 #endif /* ECL_MATH_FUZZY_HPP_ */


ecl_math
Author(s): Daniel Stonier
autogenerated on Thu Jun 6 2019 21:17:37