Loading [MathJax]/extensions/tex2jax.js
USRP Hardware Driver and USRP Manual  Version: 4.8.0.0
UHD and USRP Manual
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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"
17 namespace _bmint = boost::integer;
18 #else
19 # include <boost/math/common_factor.hpp>
20 namespace _bmint = boost::math;
21 #endif
22 
23 
24 namespace uhd {
25 
30 namespace math {
31 
32 static const double PI = 3.14159265358979323846;
33 
50 static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
51 static 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.
61 static constexpr double FREQ_COMPARE_EPSILON = 1e-12;
62 
63 namespace fp_compare {
64 
78 template <typename float_t>
80 {
81 public:
82  UHD_INLINE fp_compare_epsilon(float_t value);
83  UHD_INLINE fp_compare_epsilon(float_t value, float_t 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 
107 template <typename float_t>
110 template <typename float_t>
113 template <typename float_t>
114 UHD_INLINE bool operator<(
116 template <typename float_t>
119 template <typename float_t>
120 UHD_INLINE bool operator>(
122 template <typename float_t>
125 
126 /* If these operators are used with floats, we rely on type promotion to
127  * double. */
128 template <typename float_t>
130 template <typename float_t>
132 template <typename float_t>
133 UHD_INLINE bool operator<(fp_compare_epsilon<float_t> lhs, double rhs);
134 template <typename float_t>
136 template <typename float_t>
137 UHD_INLINE bool operator>(fp_compare_epsilon<float_t> lhs, double rhs);
138 template <typename float_t>
140 
141 template <typename float_t>
143 template <typename float_t>
145 template <typename float_t>
146 UHD_INLINE bool operator<(double lhs, fp_compare_epsilon<float_t> rhs);
147 template <typename float_t>
149 template <typename float_t>
150 UHD_INLINE bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
151 template <typename float_t>
153 
156 {
157 public:
159  : fp_compare_epsilon<double>(value, FREQ_COMPARE_EPSILON)
160  {
161  }
162 
164  : fp_compare_epsilon<double>(copy)
165  {
166  }
167 };
168 
169 
170 } // namespace fp_compare
171 
172 
179 static const float SINGLE_PRECISION_DELTA = 1e-3f;
180 static const double DOUBLE_PRECISION_DELTA = 1e-5;
181 
183 static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
184 
185 
186 namespace fp_compare {
187 
201 template <typename float_t>
203 {
204 public:
205  UHD_INLINE fp_compare_delta(float_t value);
206  UHD_INLINE fp_compare_delta(float_t value, float_t delta);
209  UHD_INLINE void operator=(const fp_compare_delta& copy);
210 
211  float_t _value;
212  float_t _delta;
213 };
214 
215 template <typename float_t>
217 template <typename float_t>
219 template <typename float_t>
221 template <typename float_t>
223 template <typename float_t>
225 template <typename float_t>
227 
228 /* If these operators are used with floats, we rely on type promotion to
229  * double. */
230 template <typename float_t>
231 UHD_INLINE bool operator==(fp_compare_delta<float_t> lhs, double rhs);
232 template <typename float_t>
233 UHD_INLINE bool operator!=(fp_compare_delta<float_t> lhs, double rhs);
234 template <typename float_t>
235 UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, double rhs);
236 template <typename float_t>
237 UHD_INLINE bool operator<=(fp_compare_delta<float_t> lhs, double rhs);
238 template <typename float_t>
239 UHD_INLINE bool operator>(fp_compare_delta<float_t> lhs, double rhs);
240 template <typename float_t>
241 UHD_INLINE bool operator>=(fp_compare_delta<float_t> lhs, double rhs);
242 
243 template <typename float_t>
244 UHD_INLINE bool operator==(double lhs, fp_compare_delta<float_t> rhs);
245 template <typename float_t>
246 UHD_INLINE bool operator!=(double lhs, fp_compare_delta<float_t> rhs);
247 template <typename float_t>
248 UHD_INLINE bool operator<(double lhs, fp_compare_delta<float_t> rhs);
249 template <typename float_t>
250 UHD_INLINE bool operator<=(double lhs, fp_compare_delta<float_t> rhs);
251 template <typename float_t>
252 UHD_INLINE bool operator>(double lhs, fp_compare_delta<float_t> rhs);
253 template <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 
276 template <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 
284 template <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.
298 template <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 
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
config.hpp
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::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::frequencies_are_equal
UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
Definition: math.hpp:258
uhd::math::fp_compare::freq_compare_epsilon
An alias for fp_compare_epsilon, but with defaults for frequencies.
Definition: math.hpp:155
uhd::math::fp_compare::fp_compare_epsilon::_epsilon
float_t _epsilon
Definition: math.hpp:89
UHD_INLINE
#define UHD_INLINE
Definition: config.h:65
uhd::math::sign
constexpr int sign(T x)
Returns the sign of x.
Definition: math.hpp:299
uhd::math::fp_compare::fp_compare_delta::_value
float_t _value
Definition: math.hpp:211
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::fp_compare_delta::_delta
float_t _delta
Definition: math.hpp:212
uhd
Definition: build_info.hpp:12
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:77
uhd::math::lcm
IntegerType lcm(IntegerType x, IntegerType y)
Portable version of lcm() across Boost versions.
Definition: math.hpp:277
uhd::math::fp_compare::fp_compare_epsilon::fp_compare_epsilon
UHD_INLINE fp_compare_epsilon(float_t value)
uhd::math::fp_compare::fp_compare_delta::fp_compare_delta
UHD_INLINE fp_compare_delta(float_t value)
uhd::math::fp_compare::freq_compare_epsilon::freq_compare_epsilon
UHD_INLINE freq_compare_epsilon(double value)
Definition: math.hpp:158
fp_compare_delta.ipp
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::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::fp_compare_epsilon::_value
float_t _value
Definition: math.hpp:88
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_delta::operator=
UHD_INLINE void operator=(const fp_compare_delta &copy)
Definition: fp_compare_delta.ipp:56
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_delta::~fp_compare_delta
UHD_INLINE ~fp_compare_delta()
Definition: fp_compare_delta.ipp:51
uhd::math::fp_compare::fp_compare_delta
Definition: math.hpp:202
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::dB_to_lin
double dB_to_lin(const double dB_val)
Definition: math.hpp:264
uhd::math::fp_compare::fp_compare_epsilon
Definition: math.hpp:79
fp_compare_epsilon.ipp