USRP Hardware Driver and USRP Manual  Version: 3.11.0.HEAD-0-gdca39145
UHD and USRP Manual
math.hpp
Go to the documentation of this file.
1 //
2 // Copyright 2014-2015 Ettus Research LLC
3 //
4 // SPDX-License-Identifier: GPL-3.0
5 //
6 
7 #ifndef INCLUDED_UHD_UTILS_MATH_HPP
8 #define INCLUDED_UHD_UTILS_MATH_HPP
9 
10 #include <cmath>
11 #include <uhd/config.hpp>
12 #include <stdint.h>
13 #include <boost/numeric/conversion/bounds.hpp>
14 
15 namespace uhd {
16 
21 namespace math {
22 
39  static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
40  static const double DOUBLE_PRECISION_EPSILON = 2.22e-16;
41 
42 namespace fp_compare {
43 
57  template<typename float_t> class fp_compare_epsilon {
58  public:
59  UHD_INLINE fp_compare_epsilon(float_t value);
60  UHD_INLINE fp_compare_epsilon(float_t value, float_t epsilon);
63  UHD_INLINE void operator=(const fp_compare_epsilon& copy);
64 
65  float_t _value;
66  float_t _epsilon;
67  };
68 
69  /* A Note on Floating Point Equality with Epsilons
70  *
71  * There are obviously a lot of strategies for defining floating point
72  * equality, and in the end it all comes down to the domain at hand. UHD's
73  * floating-point-with-epsilon comparison algorithm is based on the method
74  * presented in Knuth's "The Art of Computer Science" called "very close
75  * with tolerance epsilon".
76  *
77  * [(|u - v| / |u|) <= e] && [(|u - v| / |v|) <= e]
78  *
79  * UHD's modification to this algorithm is using the denominator's epsilon
80  * value (since each float_t object has its own epsilon) for each
81  * comparison.
82  */
83 
84  template<typename float_t> UHD_INLINE
86  template<typename float_t> UHD_INLINE
88  template<typename float_t> UHD_INLINE
89  bool operator<(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
90  template<typename float_t> UHD_INLINE
91  bool operator<=(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
92  template<typename float_t> UHD_INLINE
94  template<typename float_t> UHD_INLINE
96 
97  /* If these operators are used with floats, we rely on type promotion to
98  * double. */
99  template<typename float_t> UHD_INLINE
100  bool operator==(fp_compare_epsilon<float_t> lhs, double rhs);
101  template<typename float_t> UHD_INLINE
102  bool operator!=(fp_compare_epsilon<float_t> lhs, double rhs);
103  template<typename float_t> UHD_INLINE
104  bool operator<(fp_compare_epsilon<float_t> lhs, double rhs);
105  template<typename float_t> UHD_INLINE
106  bool operator<=(fp_compare_epsilon<float_t> lhs, double rhs);
107  template<typename float_t> UHD_INLINE
108  bool operator>(fp_compare_epsilon<float_t> lhs, double rhs);
109  template<typename float_t> UHD_INLINE
110  bool operator>=(fp_compare_epsilon<float_t> lhs, double rhs);
111 
112  template<typename float_t> UHD_INLINE
113  bool operator==(double lhs, fp_compare_epsilon<float_t> rhs);
114  template<typename float_t> UHD_INLINE
115  bool operator!=(double lhs, fp_compare_epsilon<float_t> rhs);
116  template<typename float_t> UHD_INLINE
117  bool operator<(double lhs, fp_compare_epsilon<float_t> rhs);
118  template<typename float_t> UHD_INLINE
119  bool operator<=(double lhs, fp_compare_epsilon<float_t> rhs);
120  template<typename float_t> UHD_INLINE
121  bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
122  template<typename float_t> UHD_INLINE
123  bool operator>=(double lhs, fp_compare_epsilon<float_t> rhs);
124 
125 } // namespace fp_compare
126 
127 
134  static const float SINGLE_PRECISION_DELTA = 1e-3f;
135  static const double DOUBLE_PRECISION_DELTA = 1e-5;
136 
138  static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
139 
140 
141 namespace fp_compare {
142 
156  template<typename float_t> class fp_compare_delta {
157  public:
158  UHD_INLINE fp_compare_delta(float_t value);
159  UHD_INLINE fp_compare_delta(float_t value, float_t delta);
160  UHD_INLINE fp_compare_delta(const fp_compare_delta<float_t>& copy);
161  UHD_INLINE ~fp_compare_delta();
162  UHD_INLINE void operator=(const fp_compare_delta& copy);
163 
164  float_t _value;
165  float_t _delta;
166  };
167 
168  template<typename float_t> UHD_INLINE
170  template<typename float_t> UHD_INLINE
172  template<typename float_t> UHD_INLINE
173  bool operator<(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
174  template<typename float_t> UHD_INLINE
175  bool operator<=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
176  template<typename float_t> UHD_INLINE
178  template<typename float_t> UHD_INLINE
180 
181  /* If these operators are used with floats, we rely on type promotion to
182  * double. */
183  template<typename float_t> UHD_INLINE
184  bool operator==(fp_compare_delta<float_t> lhs, double rhs);
185  template<typename float_t> UHD_INLINE
186  bool operator!=(fp_compare_delta<float_t> lhs, double rhs);
187  template<typename float_t> UHD_INLINE
188  bool operator<(fp_compare_delta<float_t> lhs, double rhs);
189  template<typename float_t> UHD_INLINE
190  bool operator<=(fp_compare_delta<float_t> lhs, double rhs);
191  template<typename float_t> UHD_INLINE
192  bool operator>(fp_compare_delta<float_t> lhs, double rhs);
193  template<typename float_t> UHD_INLINE
194  bool operator>=(fp_compare_delta<float_t> lhs, double rhs);
195 
196  template<typename float_t> UHD_INLINE
197  bool operator==(double lhs, fp_compare_delta<float_t> rhs);
198  template<typename float_t> UHD_INLINE
199  bool operator!=(double lhs, fp_compare_delta<float_t> rhs);
200  template<typename float_t> UHD_INLINE
201  bool operator<(double lhs, fp_compare_delta<float_t> rhs);
202  template<typename float_t> UHD_INLINE
203  bool operator<=(double lhs, fp_compare_delta<float_t> rhs);
204  template<typename float_t> UHD_INLINE
205  bool operator>(double lhs, fp_compare_delta<float_t> rhs);
206  template<typename float_t> UHD_INLINE
207  bool operator>=(double lhs, fp_compare_delta<float_t> rhs);
208 
209 } // namespace fp_compare
210 
211  UHD_INLINE bool frequencies_are_equal(double lhs, double rhs) {
212  return(fp_compare::fp_compare_delta<double>(lhs, FREQ_COMPARISON_DELTA_HZ)
213  == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ));
214  }
215 
217  template <typename float_t> UHD_INLINE
218  float_t log2(float_t x)
219  {
220  // C++11 defines std::log2(), when that's universally supported
221  // we can switch over.
222  return std::log(x) / std::log(float_t(2));
223  }
224 
225 
226 } // namespace math
227 } // namespace uhd
228 
231 
232 #endif /* INCLUDED_UHD_UTILS_MATH_HPP */
UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
Definition: math.hpp:211
float_t _value
Definition: math.hpp:164
UHD_INLINE float_t log2(float_t x)
Portable log2()
Definition: math.hpp:218
UHD_INLINE bool operator>=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:86
UHD_INLINE bool operator>(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:80
UHD_INLINE bool operator!=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:64
float_t _delta
Definition: math.hpp:165
float_t _epsilon
Definition: math.hpp:66
Definition: build_info.hpp:14
#define UHD_INLINE
Definition: config.h:52
UHD_INLINE ~fp_compare_epsilon()
Definition: fp_compare_epsilon.ipp:43
float_t _value
Definition: math.hpp:65
UHD_INLINE void operator=(const fp_compare_epsilon &copy)
Definition: fp_compare_epsilon.ipp:47
UHD_INLINE fp_compare_epsilon(float_t value)
UHD_INLINE bool operator==(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:58