USRP Hardware Driver and USRP Manual  Version: 4.1.0.0-264-g3e5e4eb06 UHD and USRP Manual
math.hpp
Go to the documentation of this file.
1 //
2 // Copyright 2014-2015 Ettus Research LLC
3 // Copyright 2018 Ettus Research, a National Instruments Company
4 //
6 //
7
8 #pragma once
9
10 #include <uhd/config.hpp>
11 #include <uhd/exception.hpp>
12 #include <stdint.h>
13 #include <boost/numeric/conversion/bounds.hpp>
14 #include <cmath>
15 #if BOOST_VERSION >= 106700
16 # include <boost/integer/common_factor.hpp>
17 // "bmint" for "boost math integer"
18 namespace _bmint = boost::integer;
19 #else
20 # include <boost/math/common_factor.hpp>
21 namespace _bmint = boost::math;
22 #endif
23
24
25 namespace uhd {
26
31 namespace math {
32
33 static const double PI = 3.14159265358979323846;
34
51 static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
52 static const double DOUBLE_PRECISION_EPSILON = 2.22e-16;
53
54 namespace fp_compare {
55
69 template <typename float_t>
71 {
72 public:
73  UHD_INLINE fp_compare_epsilon(float_t value);
74  UHD_INLINE fp_compare_epsilon(float_t value, float_t epsilon);
77  UHD_INLINE void operator=(const fp_compare_epsilon& copy);
78
79  float_t _value;
80  float_t _epsilon;
81 };
82
83 /* A Note on Floating Point Equality with Epsilons
84  *
85  * There are obviously a lot of strategies for defining floating point
86  * equality, and in the end it all comes down to the domain at hand. UHD's
87  * floating-point-with-epsilon comparison algorithm is based on the method
88  * presented in Knuth's "The Art of Computer Science" called "very close
89  * with tolerance epsilon".
90  *
91  * [(|u - v| / |u|) <= e] && [(|u - v| / |v|) <= e]
92  *
93  * UHD's modification to this algorithm is using the denominator's epsilon
94  * value (since each float_t object has its own epsilon) for each
95  * comparison.
96  */
97
98 template <typename float_t>
101 template <typename float_t>
104 template <typename float_t>
105 UHD_INLINE bool operator<(
107 template <typename float_t>
110 template <typename float_t>
111 UHD_INLINE bool operator>(
113 template <typename float_t>
116
117 /* If these operators are used with floats, we rely on type promotion to
118  * double. */
119 template <typename float_t>
121 template <typename float_t>
123 template <typename float_t>
124 UHD_INLINE bool operator<(fp_compare_epsilon<float_t> lhs, double rhs);
125 template <typename float_t>
126 UHD_INLINE bool operator<=(fp_compare_epsilon<float_t> lhs, double rhs);
127 template <typename float_t>
128 UHD_INLINE bool operator>(fp_compare_epsilon<float_t> lhs, double rhs);
129 template <typename float_t>
131
132 template <typename float_t>
134 template <typename float_t>
136 template <typename float_t>
137 UHD_INLINE bool operator<(double lhs, fp_compare_epsilon<float_t> rhs);
138 template <typename float_t>
139 UHD_INLINE bool operator<=(double lhs, fp_compare_epsilon<float_t> rhs);
140 template <typename float_t>
141 UHD_INLINE bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
142 template <typename float_t>
144
145 } // namespace fp_compare
146
147
154 static const float SINGLE_PRECISION_DELTA = 1e-3f;
155 static const double DOUBLE_PRECISION_DELTA = 1e-5;
156
158 static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
159
160
161 namespace fp_compare {
162
176 template <typename float_t>
178 {
179 public:
180  UHD_INLINE fp_compare_delta(float_t value);
181  UHD_INLINE fp_compare_delta(float_t value, float_t delta);
182  UHD_INLINE fp_compare_delta(const fp_compare_delta<float_t>& copy);
183  UHD_INLINE ~fp_compare_delta();
184  UHD_INLINE void operator=(const fp_compare_delta& copy);
185
186  float_t _value;
187  float_t _delta;
188 };
189
190 template <typename float_t>
192 template <typename float_t>
194 template <typename float_t>
195 UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
196 template <typename float_t>
197 UHD_INLINE bool operator<=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
198 template <typename float_t>
200 template <typename float_t>
202
203 /* If these operators are used with floats, we rely on type promotion to
204  * double. */
205 template <typename float_t>
206 UHD_INLINE bool operator==(fp_compare_delta<float_t> lhs, double rhs);
207 template <typename float_t>
208 UHD_INLINE bool operator!=(fp_compare_delta<float_t> lhs, double rhs);
209 template <typename float_t>
210 UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, double rhs);
211 template <typename float_t>
212 UHD_INLINE bool operator<=(fp_compare_delta<float_t> lhs, double rhs);
213 template <typename float_t>
214 UHD_INLINE bool operator>(fp_compare_delta<float_t> lhs, double rhs);
215 template <typename float_t>
216 UHD_INLINE bool operator>=(fp_compare_delta<float_t> lhs, double rhs);
217
218 template <typename float_t>
219 UHD_INLINE bool operator==(double lhs, fp_compare_delta<float_t> rhs);
220 template <typename float_t>
221 UHD_INLINE bool operator!=(double lhs, fp_compare_delta<float_t> rhs);
222 template <typename float_t>
223 UHD_INLINE bool operator<(double lhs, fp_compare_delta<float_t> rhs);
224 template <typename float_t>
225 UHD_INLINE bool operator<=(double lhs, fp_compare_delta<float_t> rhs);
226 template <typename float_t>
227 UHD_INLINE bool operator>(double lhs, fp_compare_delta<float_t> rhs);
228 template <typename float_t>
229 UHD_INLINE bool operator>=(double lhs, fp_compare_delta<float_t> rhs);
230
231 } // namespace fp_compare
232
233 UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
234 {
235  return (fp_compare::fp_compare_delta<double>(lhs, FREQ_COMPARISON_DELTA_HZ)
236  == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ));
237 }
238
239 inline double dB_to_lin(const double dB_val)
240 {
241  return std::pow(10, (dB_val) / 10.0);
242 }
243
244 inline double lin_to_dB(const double val)
245 {
246  return 10 * std::log10(val);
247 }
248
249
251 template <typename IntegerType>
252 inline IntegerType lcm(IntegerType x, IntegerType y)
253 {
254  // Note: _bmint is defined conditionally at the top of the file
255  return _bmint::lcm<IntegerType>(x, y);
256 }
257
259 template <typename IntegerType>
260 inline IntegerType gcd(IntegerType x, IntegerType y)
261 {
262  // Note: _bmint is defined conditionally at the top of the file
263  return _bmint::gcd<IntegerType>(x, y);
264 }
265
267 //
268 // Note: This is equivalent to the Boost.Math version, but without the
269 // dependency.
270 //
271 // Returns +1 for positive arguments, -1 for negative arguments, and 0 if x is
272 // zero.
273 template <typename T>
274 inline constexpr int sign(T x)
275 {
276  // Note: If T is unsigned, then this will compile with a warning. Should
277  // we need that, expand the template logic.
278  return (T(0) < x) - (x < T(0));
279 }
280
282 // Nyquist zone.
283 //
284 // Examples:
285 // - Just above the sampling rate:
286 // wrap_frequency(250e6, 200e6) == 50e6
287 // - Just outside the Nyquist zone:
288 // wrap_frequency(120e6, 200e6) == -80e6
289 // - Also works for negative frequencies:
290 // wrap_frequency(-250e6, 200e6) == -50e6
291 inline double wrap_frequency(const double requested_freq, const double rate)
292 {
293  double freq = std::fmod(requested_freq, rate);
294  if (std::abs(freq) > rate / 2.0)
295  freq -= uhd::math::sign(freq) * rate;
296  return freq;
297 }
298
299 } // namespace math
300 } // namespace uhd
301
UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
Definition: math.hpp:233
UHD_INLINE bool operator<=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:75
float_t _value
Definition: math.hpp:186
UHD_INLINE bool operator>=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:86
IntegerType gcd(IntegerType x, IntegerType y)
Portable version of gcd() across Boost versions.
Definition: math.hpp:260
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
double wrap_frequency(const double requested_freq, const double rate)
Return a wrapped frequency that is the equivalent frequency in the first.
Definition: math.hpp:291
float_t _delta
Definition: math.hpp:187
float_t _epsilon
Definition: math.hpp:80
Definition: build_info.hpp:12
UHD_INLINE bool operator<(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:69
#define UHD_INLINE
Definition: config.h:55
double dB_to_lin(const double dB_val)
Definition: math.hpp:239
UHD_INLINE ~fp_compare_epsilon()
Definition: fp_compare_epsilon.ipp:43
constexpr int sign(T x)
Returns the sign of x.
Definition: math.hpp:274
float_t _value
Definition: math.hpp:79
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
double lin_to_dB(const double val)
Definition: math.hpp:244
IntegerType lcm(IntegerType x, IntegerType y)
Portable version of lcm() across Boost versions.
Definition: math.hpp:252