USRP Hardware Driver and USRP Manual  Version: 4.7.0.0
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 //
5 // SPDX-License-Identifier: GPL-3.0-or-later
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 
55 //
56 // Note that this is a UHD/USRP-specific constant. In UHD, frequencies are on
57 // the order of 1e9 (GHz) or below. We will declare frequencies as equal if they
58 // are within a millihertz. For the purpose of
59 // comparing frequencies, we "lose" 9 decimal places for the integer
60 // component of the frequency, so we choose this epsilon value for floating
61 // point comparison of frequencies.
62 static constexpr double FREQ_COMPARE_EPSILON = 1e-12;
63 
64 namespace fp_compare {
65 
79 template <typename float_t>
81 {
82 public:
83  UHD_INLINE fp_compare_epsilon(float_t value);
84  UHD_INLINE fp_compare_epsilon(float_t value, float_t epsilon);
87  UHD_INLINE void operator=(const fp_compare_epsilon& copy);
88 
89  float_t _value;
90  float_t _epsilon;
91 };
92 
93 /* A Note on Floating Point Equality with Epsilons
94  *
95  * There are obviously a lot of strategies for defining floating point
96  * equality, and in the end it all comes down to the domain at hand. UHD's
97  * floating-point-with-epsilon comparison algorithm is based on the method
98  * presented in Knuth's "The Art of Computer Science" called "close enough
99  * with tolerance epsilon".
100  *
101  * [(|u - v| / |u|) <= e] || [(|u - v| / |v|) <= e]
102  *
103  * UHD's modification to this algorithm is using the denominator's epsilon
104  * value (since each float_t object has its own epsilon) for each
105  * comparison.
106  */
107 
108 template <typename float_t>
111 template <typename float_t>
114 template <typename float_t>
115 UHD_INLINE bool operator<(
117 template <typename float_t>
120 template <typename float_t>
121 UHD_INLINE bool operator>(
123 template <typename float_t>
126 
127 /* If these operators are used with floats, we rely on type promotion to
128  * double. */
129 template <typename float_t>
131 template <typename float_t>
133 template <typename float_t>
134 UHD_INLINE bool operator<(fp_compare_epsilon<float_t> lhs, double rhs);
135 template <typename float_t>
136 UHD_INLINE bool operator<=(fp_compare_epsilon<float_t> lhs, double rhs);
137 template <typename float_t>
138 UHD_INLINE bool operator>(fp_compare_epsilon<float_t> lhs, double rhs);
139 template <typename float_t>
141 
142 template <typename float_t>
144 template <typename float_t>
146 template <typename float_t>
147 UHD_INLINE bool operator<(double lhs, fp_compare_epsilon<float_t> rhs);
148 template <typename float_t>
149 UHD_INLINE bool operator<=(double lhs, fp_compare_epsilon<float_t> rhs);
150 template <typename float_t>
151 UHD_INLINE bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
152 template <typename float_t>
154 
157 {
158 public:
160  : fp_compare_epsilon<double>(value, FREQ_COMPARE_EPSILON)
161  {
162  }
163 
165  : fp_compare_epsilon<double>(copy)
166  {
167  }
168 };
169 
170 
171 } // namespace fp_compare
172 
173 
180 static const float SINGLE_PRECISION_DELTA = 1e-3f;
181 static const double DOUBLE_PRECISION_DELTA = 1e-5;
182 
184 static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
185 
186 
187 namespace fp_compare {
188 
202 template <typename float_t>
204 {
205 public:
206  UHD_INLINE fp_compare_delta(float_t value);
207  UHD_INLINE fp_compare_delta(float_t value, float_t delta);
208  UHD_INLINE fp_compare_delta(const fp_compare_delta<float_t>& copy);
209  UHD_INLINE ~fp_compare_delta();
210  UHD_INLINE void operator=(const fp_compare_delta& copy);
211 
212  float_t _value;
213  float_t _delta;
214 };
215 
216 template <typename float_t>
218 template <typename float_t>
220 template <typename float_t>
221 UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
222 template <typename float_t>
223 UHD_INLINE bool operator<=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
224 template <typename float_t>
226 template <typename float_t>
228 
229 /* If these operators are used with floats, we rely on type promotion to
230  * double. */
231 template <typename float_t>
232 UHD_INLINE bool operator==(fp_compare_delta<float_t> lhs, double rhs);
233 template <typename float_t>
234 UHD_INLINE bool operator!=(fp_compare_delta<float_t> lhs, double rhs);
235 template <typename float_t>
236 UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, double rhs);
237 template <typename float_t>
238 UHD_INLINE bool operator<=(fp_compare_delta<float_t> lhs, double rhs);
239 template <typename float_t>
240 UHD_INLINE bool operator>(fp_compare_delta<float_t> lhs, double rhs);
241 template <typename float_t>
242 UHD_INLINE bool operator>=(fp_compare_delta<float_t> lhs, double rhs);
243 
244 template <typename float_t>
245 UHD_INLINE bool operator==(double lhs, fp_compare_delta<float_t> rhs);
246 template <typename float_t>
247 UHD_INLINE bool operator!=(double lhs, fp_compare_delta<float_t> rhs);
248 template <typename float_t>
249 UHD_INLINE bool operator<(double lhs, fp_compare_delta<float_t> rhs);
250 template <typename float_t>
251 UHD_INLINE bool operator<=(double lhs, fp_compare_delta<float_t> rhs);
252 template <typename float_t>
253 UHD_INLINE bool operator>(double lhs, fp_compare_delta<float_t> rhs);
254 template <typename float_t>
255 UHD_INLINE bool operator>=(double lhs, fp_compare_delta<float_t> rhs);
256 
257 } // namespace fp_compare
258 
259 UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
260 {
261  return (fp_compare::fp_compare_delta<double>(lhs, FREQ_COMPARISON_DELTA_HZ)
262  == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ));
263 }
264 
265 inline double dB_to_lin(const double dB_val)
266 {
267  return std::pow(10, (dB_val) / 10.0);
268 }
269 
270 inline double lin_to_dB(const double val)
271 {
272  return 10 * std::log10(val);
273 }
274 
275 
277 template <typename IntegerType>
278 inline IntegerType lcm(IntegerType x, IntegerType y)
279 {
280  // Note: _bmint is defined conditionally at the top of the file
281  return _bmint::lcm<IntegerType>(x, y);
282 }
283 
285 template <typename IntegerType>
286 inline IntegerType gcd(IntegerType x, IntegerType y)
287 {
288  // Note: _bmint is defined conditionally at the top of the file
289  return _bmint::gcd<IntegerType>(x, y);
290 }
291 
293 //
294 // Note: This is equivalent to the Boost.Math version, but without the
295 // dependency.
296 //
297 // Returns +1 for positive arguments, -1 for negative arguments, and 0 if x is
298 // zero.
299 template <typename T>
300 inline constexpr int sign(T x)
301 {
302  // Note: If T is unsigned, then this will compile with a warning. Should
303  // we need that, expand the template logic.
304  return (T(0) < x) - (x < T(0));
305 }
306 
308 // Nyquist zone.
309 //
310 // Examples:
311 // - Just above the sampling rate:
312 // wrap_frequency(250e6, 200e6) == 50e6
313 // - Just outside the Nyquist zone:
314 // wrap_frequency(120e6, 200e6) == -80e6
315 // - Also works for negative frequencies:
316 // wrap_frequency(-250e6, 200e6) == -50e6
317 inline double wrap_frequency(const double requested_freq, const double rate)
318 {
319  double freq = std::fmod(requested_freq, rate);
320  if (std::abs(freq) > rate / 2.0)
321  freq -= uhd::math::sign(freq) * rate;
322  return freq;
323 }
324 
325 } // namespace math
326 } // namespace uhd
327 
UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
Definition: math.hpp:259
UHD_INLINE bool operator<=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:84
float_t _value
Definition: math.hpp:212
UHD_INLINE freq_compare_epsilon(const freq_compare_epsilon &copy)
Definition: math.hpp:164
UHD_INLINE bool operator>=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:97
IntegerType gcd(IntegerType x, IntegerType y)
Portable version of gcd() across Boost versions.
Definition: math.hpp:286
UHD_INLINE bool operator>(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:90
UHD_INLINE bool operator!=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:71
An alias for fp_compare_epsilon, but with defaults for frequencies.
Definition: math.hpp:156
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:317
float_t _delta
Definition: math.hpp:213
float_t _epsilon
Definition: math.hpp:90
UHD_INLINE freq_compare_epsilon(double value)
Definition: math.hpp:159
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:77
#define UHD_INLINE
Definition: config.h:65
double dB_to_lin(const double dB_val)
Definition: math.hpp:265
UHD_INLINE ~fp_compare_epsilon()
Definition: fp_compare_epsilon.ipp:46
constexpr int sign(T x)
Returns the sign of x.
Definition: math.hpp:300
float_t _value
Definition: math.hpp:89
UHD_INLINE void operator=(const fp_compare_epsilon &copy)
Definition: fp_compare_epsilon.ipp:51
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:64
double lin_to_dB(const double val)
Definition: math.hpp:270
IntegerType lcm(IntegerType x, IntegerType y)
Portable version of lcm() across Boost versions.
Definition: math.hpp:278