comparison.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #ifndef UAVCAN_UTIL_COMPARISON_HPP_INCLUDED
6 #define UAVCAN_UTIL_COMPARISON_HPP_INCLUDED
7 
10 
11 namespace uavcan
12 {
16 template <typename T>
18 inline bool areFloatsExactlyEqual(const T& left, const T& right)
19 {
20  return (left <= right) && (left >= right);
21 }
22 
29 template <typename T>
31 inline bool areFloatsClose(T a, T b, const T& absolute_epsilon, const T& relative_epsilon)
32 {
33  // NAN
34  if (isNaN(a) || isNaN(b))
35  {
36  return false;
37  }
38 
39  // Infinity
40  if (isInfinity(a) || isInfinity(b))
41  {
42  return areFloatsExactlyEqual(a, b);
43  }
44 
45  // Close numbers near zero
46  const T diff = std::fabs(a - b);
47  if (diff <= absolute_epsilon)
48  {
49  return true;
50  }
51 
52  // General case
53  a = std::fabs(a);
54  b = std::fabs(b);
55  const T largest = (b > a) ? b : a;
56  return (diff <= largest * relative_epsilon);
57 }
58 
63 namespace are_close_impl_
64 {
65 
66 struct Applicable { char foo[1]; };
67 struct NotApplicable { long long foo[16]; };
68 
69 template <typename This, typename Rhs>
71 {
72  template <typename U, typename R, bool (U::*)(const R&) const> struct ConstRef { };
73  template <typename U, typename R, bool (U::*)(R) const> struct ByValue { };
74 
75  template <typename U, typename R> static Applicable test(ConstRef<U, R, &U::isClose>*);
76  template <typename U, typename R> static Applicable test(ByValue<U, R, &U::isClose>*);
77 
78  template <typename U, typename R> static NotApplicable test(...);
79 
80  enum { Result = sizeof(test<This, Rhs>(UAVCAN_NULLPTR)) };
81 };
82 
84 template <typename L, typename R>
86 inline bool areCloseImplFirst(const L& left, const R& right, IntToType<sizeof(Applicable)>)
87 {
88  return left.isClose(right);
89 }
90 
92 template <typename L, typename R>
94 inline bool areCloseImplSecond(const L& left, const R& right, IntToType<sizeof(Applicable)>)
95 {
96  return right.isClose(left);
97 }
98 
100 template <typename L, typename R>
102 inline bool areCloseImplSecond(const L& left, const R& right, IntToType<sizeof(NotApplicable)>)
103 {
104  return left == right;
105 }
106 
108 template <typename L, typename R>
110 inline bool areCloseImplFirst(const L& left, const R& right, IntToType<sizeof(NotApplicable)>)
111 {
112  return are_close_impl_::areCloseImplSecond(left, right,
114 }
115 
116 } // namespace are_close_impl_
117 
156 template <typename L, typename R>
158 inline bool areClose(const L& left, const R& right)
159 {
160  return are_close_impl_::areCloseImplFirst(left, right,
162 }
163 
164 /*
165  * Float comparison specializations
166  */
167 template <>
169 inline bool areClose<float, float>(const float& left, const float& right)
170 {
171  return areFloatsClose(left, right, NumericTraits<float>::epsilon(),
173 }
174 
175 template <>
177 inline bool areClose<double, double>(const double& left, const double& right)
178 {
179  return areFloatsClose(left, right, NumericTraits<double>::epsilon(),
181 }
182 
183 template <>
185 inline bool areClose<long double, long double>(const long double& left, const long double& right)
186 {
187  return areFloatsClose(left, right, NumericTraits<long double>::epsilon(),
188  NumericTraits<long double>::epsilon() * FloatComparisonEpsilonMult);
189 }
190 
191 /*
192  * Mixed floating type comparison - coercing larger type to smaller type
193  */
194 template <>
196 inline bool areClose<float, double>(const float& left, const double& right)
197 {
198  return areClose(left, static_cast<float>(right));
199 }
200 
201 template <>
203 inline bool areClose<double, float>(const double& left, const float& right)
204 {
205  return areClose(static_cast<float>(left), right);
206 }
207 
208 template <>
210 inline bool areClose<float, long double>(const float& left, const long double& right)
211 {
212  return areClose(left, static_cast<float>(right));
213 }
214 
215 template <>
217 inline bool areClose<long double, float>(const long double& left, const float& right)
218 {
219  return areClose(static_cast<float>(left), right);
220 }
221 
222 template <>
224 inline bool areClose<double, long double>(const double& left, const long double& right)
225 {
226  return areClose(left, static_cast<double>(right));
227 }
228 
229 template <>
231 inline bool areClose<long double, double>(const long double& left, const double& right)
232 {
233  return areClose(static_cast<double>(left), right);
234 }
235 
241 template <typename T>
243 inline bool isCloseToZero(const T& x)
244 {
245  return x == 0;
246 }
247 
248 template <>
250 inline bool isCloseToZero<float>(const float& x)
251 {
252  return areClose(x, static_cast<float>(0.0F));
253 }
254 
255 template <>
257 inline bool isCloseToZero<double>(const double& x)
258 {
259  return areClose(x, static_cast<double>(0.0));
260 }
261 
262 template <>
264 inline bool isCloseToZero<long double>(const long double& x)
265 {
266  return areClose(x, static_cast<long double>(0.0L));
267 }
268 
269 }
270 
271 #endif // UAVCAN_UTIL_COMPARISON_HPP_INCLUDED
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::FloatComparisonEpsilonMult
static const unsigned FloatComparisonEpsilonMult
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:262
templates.hpp
uavcan::are_close_impl_::HasIsCloseMethod::ConstRef
Definition: comparison.hpp:72
uavcan::isNaN
bool isNaN(T arg)
Definition: templates.hpp:501
uavcan::NumericTraits< double >::epsilon
static double epsilon()
Definition: templates.hpp:473
uavcan::are_close_impl_::areCloseImplSecond
UAVCAN_EXPORT bool areCloseImplSecond(const L &left, const R &right, IntToType< sizeof(Applicable)>)
Second stage: bool R::isClose(L)
Definition: comparison.hpp:94
uavcan::areFloatsExactlyEqual
UAVCAN_EXPORT bool areFloatsExactlyEqual(const T &left, const T &right)
Definition: comparison.hpp:18
uavcan::areClose< double, double >
UAVCAN_EXPORT bool areClose< double, double >(const double &left, const double &right)
Definition: comparison.hpp:177
uavcan::areClose< float, float >
UAVCAN_EXPORT bool areClose< float, float >(const float &left, const float &right)
Definition: comparison.hpp:169
uavcan::isInfinity
bool isInfinity(T arg)
Definition: templates.hpp:517
uavcan::areClose< float, double >
UAVCAN_EXPORT bool areClose< float, double >(const float &left, const double &right)
Definition: comparison.hpp:196
uavcan::areClose< double, long double >
UAVCAN_EXPORT bool areClose< double, long double >(const double &left, const long double &right)
Definition: comparison.hpp:224
uavcan::are_close_impl_::HasIsCloseMethod::test
static Applicable test(ConstRef< U, R, &U::isClose > *)
uavcan::areClose
UAVCAN_EXPORT bool areClose(const L &left, const R &right)
Definition: comparison.hpp:158
uavcan::IntToType
Definition: templates.hpp:134
uavcan::NumericTraits< float >::epsilon
static float epsilon()
Definition: templates.hpp:461
uavcan::are_close_impl_::Applicable::foo
char foo[1]
Definition: comparison.hpp:66
uavcan::areClose< double, float >
UAVCAN_EXPORT bool areClose< double, float >(const double &left, const float &right)
Definition: comparison.hpp:203
uavcan::areClose< float, long double >
UAVCAN_EXPORT bool areClose< float, long double >(const float &left, const long double &right)
Definition: comparison.hpp:210
UAVCAN_EXPORT
#define UAVCAN_EXPORT
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:108
uavcan::areClose< long double, long double >
UAVCAN_EXPORT bool areClose< long double, long double >(const long double &left, const long double &right)
Definition: comparison.hpp:185
uavcan::isCloseToZero< double >
UAVCAN_EXPORT bool isCloseToZero< double >(const double &x)
Definition: comparison.hpp:257
build_config.hpp
uavcan::are_close_impl_::areCloseImplFirst
UAVCAN_EXPORT bool areCloseImplFirst(const L &left, const R &right, IntToType< sizeof(Applicable)>)
First stage: bool L::isClose(R)
Definition: comparison.hpp:86
uavcan::isCloseToZero< float >
UAVCAN_EXPORT bool isCloseToZero< float >(const float &x)
Definition: comparison.hpp:250
uavcan::areClose< long double, double >
UAVCAN_EXPORT bool areClose< long double, double >(const long double &left, const double &right)
Definition: comparison.hpp:231
uavcan::areClose< long double, float >
UAVCAN_EXPORT bool areClose< long double, float >(const long double &left, const float &right)
Definition: comparison.hpp:217
uavcan::areFloatsClose
UAVCAN_EXPORT bool areFloatsClose(T a, T b, const T &absolute_epsilon, const T &relative_epsilon)
Definition: comparison.hpp:31
uavcan::are_close_impl_::NotApplicable::foo
long long foo[16]
Definition: comparison.hpp:67
uavcan::isCloseToZero< long double >
UAVCAN_EXPORT bool isCloseToZero< long double >(const long double &x)
Definition: comparison.hpp:264
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::are_close_impl_::HasIsCloseMethod::ByValue
Definition: comparison.hpp:73
uavcan::isCloseToZero
UAVCAN_EXPORT bool isCloseToZero(const T &x)
Definition: comparison.hpp:243
uavcan::are_close_impl_::Applicable
Definition: comparison.hpp:66
uavcan::are_close_impl_::HasIsCloseMethod::Result
@ Result
Definition: comparison.hpp:80
uavcan::are_close_impl_::HasIsCloseMethod
Definition: comparison.hpp:70
pyuavcan_v0.driver.timestamp_estimator.x
x
Definition: timestamp_estimator.py:221
uavcan::are_close_impl_::NotApplicable
Definition: comparison.hpp:67


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02