Go to the documentation of this file.00001
00011
00012
00013
00014
00015 #ifndef ECL_MATH_FUZZY_HPP_
00016 #define ECL_MATH_FUZZY_HPP_
00017
00018
00019
00020
00021
00022
00023 #include <cmath>
00024 #include <cstdlib>
00025 #include <algorithm>
00026 #include <ecl/type_traits/numeric_limits.hpp>
00027
00028
00029
00030
00031
00032 namespace ecl {
00036 namespace implementations {
00037
00038
00039
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
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
00086 if ( ecl::numeric_limits<OtherScalar>::is_integer ) {
00087 return x == y;
00088 } else {
00089
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
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
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 }
00132
00136
00137
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 }
00179
00180 #endif