USRP Hardware Driver and USRP Manual: math.hpp Source File

| USRP Hardware Driver and USRP Manual Version: 4.8.0.makepkg-0-g308126a4 UHD and USRP Manual |

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