USRP Hardware Driver and USRP Manual Version: 4.2.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"
18namespace _bmint = boost::integer;
19#else
20# include <boost/math/common_factor.hpp>
21namespace _bmint = boost::math;
22#endif
23
24
25namespace uhd {
26
31namespace math {
32
33static const double PI = 3.14159265358979323846;
34
51static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
52static 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.
62static constexpr double FREQ_COMPARE_EPSILON = 1e-12;
63
64namespace fp_compare {
65
79template <typename float_t>
81{
82public:
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
108template <typename float_t>
111template <typename float_t>
114template <typename float_t>
117template <typename float_t>
120template <typename float_t>
123template <typename float_t>
126
127/* If these operators are used with floats, we rely on type promotion to
128 * double. */
129template <typename float_t>
131template <typename float_t>
133template <typename float_t>
135template <typename float_t>
137template <typename float_t>
139template <typename float_t>
141
142template <typename float_t>
144template <typename float_t>
146template <typename float_t>
148template <typename float_t>
150template <typename float_t>
152template <typename float_t>
154
157{
158public:
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
180static const float SINGLE_PRECISION_DELTA = 1e-3f;
181static const double DOUBLE_PRECISION_DELTA = 1e-5;
182
184static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
185
186
187namespace fp_compare {
188
202template <typename float_t>
204{
205public:
207 UHD_INLINE fp_compare_delta(float_t value, float_t delta);
210 UHD_INLINE void operator=(const fp_compare_delta& copy);
211
212 float_t _value;
213 float_t _delta;
214};
215
216template <typename float_t>
218template <typename float_t>
220template <typename float_t>
222template <typename float_t>
224template <typename float_t>
226template <typename float_t>
228
229/* If these operators are used with floats, we rely on type promotion to
230 * double. */
231template <typename float_t>
233template <typename float_t>
235template <typename float_t>
237template <typename float_t>
239template <typename float_t>
241template <typename float_t>
243
244template <typename float_t>
246template <typename float_t>
248template <typename float_t>
250template <typename float_t>
252template <typename float_t>
254template <typename float_t>
256
257} // namespace fp_compare
258
259UHD_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
265inline double dB_to_lin(const double dB_val)
266{
267 return std::pow(10, (dB_val) / 10.0);
268}
269
270inline double lin_to_dB(const double val)
271{
272 return 10 * std::log10(val);
273}
274
275
277template <typename IntegerType>
278inline 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
285template <typename IntegerType>
286inline 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.
299template <typename T>
300inline 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
317inline 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 fp_compare_delta(float_t value)
float_t _delta
Definition: math.hpp:213
UHD_INLINE void operator=(const fp_compare_delta &copy)
Definition: fp_compare_delta.ipp:52
UHD_INLINE ~fp_compare_delta()
Definition: fp_compare_delta.ipp:48
float_t _value
Definition: math.hpp:212
float_t _epsilon
Definition: math.hpp:90
UHD_INLINE ~fp_compare_epsilon()
Definition: fp_compare_epsilon.ipp:44
UHD_INLINE void operator=(const fp_compare_epsilon &copy)
Definition: fp_compare_epsilon.ipp:48
float_t _value
Definition: math.hpp:89
UHD_INLINE fp_compare_epsilon(float_t value)
An alias for fp_compare_epsilon, but with defaults for frequencies.
Definition: math.hpp:157
UHD_INLINE freq_compare_epsilon(const freq_compare_epsilon &copy)
Definition: math.hpp:164
UHD_INLINE freq_compare_epsilon(double value)
Definition: math.hpp:159
#define UHD_INLINE
Definition: config.h:65
UHD_INLINE bool operator!=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:64
UHD_INLINE bool operator<=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:75
UHD_INLINE bool operator==(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:58
UHD_INLINE bool operator<(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:69
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:86
IntegerType lcm(IntegerType x, IntegerType y)
Portable version of lcm() across Boost versions.
Definition: math.hpp:278
UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
Definition: math.hpp:259
double dB_to_lin(const double dB_val)
Definition: math.hpp:265
constexpr int sign(T x)
Returns the sign of x.
Definition: math.hpp:300
IntegerType gcd(IntegerType x, IntegerType y)
Portable version of gcd() across Boost versions.
Definition: math.hpp:286
double lin_to_dB(const double val)
Definition: math.hpp:270
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
Definition: build_info.hpp:12