USRP Hardware Driver and USRP Manual  Version: 4.9.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 <cmath>
12 
13 
14 namespace uhd {
15 
20 namespace math {
21 
22 static const double PI = 3.14159265358979323846;
23 
40 static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
41 static const double DOUBLE_PRECISION_EPSILON = 2.22e-16;
42 
44 //
45 // Note that this is a UHD/USRP-specific constant. In UHD, frequencies are on
46 // the order of 1e9 (GHz) or below. We will declare frequencies as equal if they
47 // are within a millihertz. For the purpose of
48 // comparing frequencies, we "lose" 9 decimal places for the integer
49 // component of the frequency, so we choose this epsilon value for floating
50 // point comparison of frequencies.
51 static constexpr double FREQ_COMPARE_EPSILON = 1e-12;
52 
53 namespace fp_compare {
54 
68 template <typename float_t>
70 {
71 public:
72  UHD_INLINE fp_compare_epsilon(float_t value);
73  UHD_INLINE fp_compare_epsilon(float_t value, float_t epsilon);
76  UHD_INLINE void operator=(const fp_compare_epsilon& copy);
77 
78  float_t _value;
79  float_t _epsilon;
80 };
81 
82 /* A Note on Floating Point Equality with Epsilons
83  *
84  * There are obviously a lot of strategies for defining floating point
85  * equality, and in the end it all comes down to the domain at hand. UHD's
86  * floating-point-with-epsilon comparison algorithm is based on the method
87  * presented in Knuth's "The Art of Computer Science" called "close enough
88  * with tolerance epsilon".
89  *
90  * [(|u - v| / |u|) <= e] || [(|u - v| / |v|) <= e]
91  *
92  * UHD's modification to this algorithm is using the denominator's epsilon
93  * value (since each float_t object has its own epsilon) for each
94  * comparison.
95  */
96 
97 template <typename float_t>
100 template <typename float_t>
103 template <typename float_t>
104 UHD_INLINE bool operator<(
106 template <typename float_t>
109 template <typename float_t>
110 UHD_INLINE bool operator>(
112 template <typename float_t>
115 
116 /* If these operators are used with floats, we rely on type promotion to
117  * double. */
118 template <typename float_t>
120 template <typename float_t>
122 template <typename float_t>
123 UHD_INLINE bool operator<(fp_compare_epsilon<float_t> lhs, double rhs);
124 template <typename float_t>
126 template <typename float_t>
127 UHD_INLINE bool operator>(fp_compare_epsilon<float_t> lhs, double rhs);
128 template <typename float_t>
130 
131 template <typename float_t>
133 template <typename float_t>
135 template <typename float_t>
136 UHD_INLINE bool operator<(double lhs, fp_compare_epsilon<float_t> rhs);
137 template <typename float_t>
139 template <typename float_t>
140 UHD_INLINE bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
141 template <typename float_t>
143 
146 {
147 public:
149  : fp_compare_epsilon<double>(value, FREQ_COMPARE_EPSILON)
150  {
151  }
152 
154  : fp_compare_epsilon<double>(copy)
155  {
156  }
157 };
158 
159 
160 } // namespace fp_compare
161 
162 
169 static const float SINGLE_PRECISION_DELTA = 1e-3f;
170 static const double DOUBLE_PRECISION_DELTA = 1e-5;
171 
173 static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
174 
175 
176 namespace fp_compare {
177 
191 template <typename float_t>
193 {
194 public:
195  UHD_INLINE fp_compare_delta(float_t value);
196  UHD_INLINE fp_compare_delta(float_t value, float_t delta);
199  UHD_INLINE void operator=(const fp_compare_delta& copy);
200 
201  float_t _value;
202  float_t _delta;
203 };
204 
205 template <typename float_t>
207 template <typename float_t>
209 template <typename float_t>
211 template <typename float_t>
213 template <typename float_t>
215 template <typename float_t>
217 
218 /* If these operators are used with floats, we rely on type promotion to
219  * double. */
220 template <typename float_t>
221 UHD_INLINE bool operator==(fp_compare_delta<float_t> lhs, double rhs);
222 template <typename float_t>
223 UHD_INLINE bool operator!=(fp_compare_delta<float_t> lhs, double rhs);
224 template <typename float_t>
225 UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, double rhs);
226 template <typename float_t>
227 UHD_INLINE bool operator<=(fp_compare_delta<float_t> lhs, double rhs);
228 template <typename float_t>
229 UHD_INLINE bool operator>(fp_compare_delta<float_t> lhs, double rhs);
230 template <typename float_t>
231 UHD_INLINE bool operator>=(fp_compare_delta<float_t> lhs, double rhs);
232 
233 template <typename float_t>
234 UHD_INLINE bool operator==(double lhs, fp_compare_delta<float_t> rhs);
235 template <typename float_t>
236 UHD_INLINE bool operator!=(double lhs, fp_compare_delta<float_t> rhs);
237 template <typename float_t>
238 UHD_INLINE bool operator<(double lhs, fp_compare_delta<float_t> rhs);
239 template <typename float_t>
240 UHD_INLINE bool operator<=(double lhs, fp_compare_delta<float_t> rhs);
241 template <typename float_t>
242 UHD_INLINE bool operator>(double lhs, fp_compare_delta<float_t> rhs);
243 template <typename float_t>
244 UHD_INLINE bool operator>=(double lhs, fp_compare_delta<float_t> rhs);
245 
246 } // namespace fp_compare
247 
248 UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
249 {
250  return (fp_compare::fp_compare_delta<double>(lhs, FREQ_COMPARISON_DELTA_HZ)
251  == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ));
252 }
253 
254 inline double dB_to_lin(const double dB_val)
255 {
256  return std::pow(10, (dB_val) / 10.0);
257 }
258 
259 inline double lin_to_dB(const double val)
260 {
261  return 10 * std::log10(val);
262 }
263 
264 
266 //
267 // Note: This is equivalent to the Boost.Math version, but without the
268 // dependency.
269 //
270 // Returns +1 for positive arguments, -1 for negative arguments, and 0 if x is
271 // zero.
272 template <typename T>
273 inline constexpr int sign(T x)
274 {
275  // Note: If T is unsigned, then this will compile with a warning. Should
276  // we need that, expand the template logic.
277  return (T(0) < x) - (x < T(0));
278 }
279 
281 // Nyquist zone.
282 //
283 // Examples:
284 // - Just above the sampling rate:
285 // wrap_frequency(250e6, 200e6) == 50e6
286 // - Just outside the Nyquist zone:
287 // wrap_frequency(120e6, 200e6) == -80e6
288 // - Also works for negative frequencies:
289 // wrap_frequency(-250e6, 200e6) == -50e6
290 inline double wrap_frequency(const double requested_freq, const double rate)
291 {
292  double freq = std::fmod(requested_freq, rate);
293  if (std::abs(freq) > rate / 2.0)
294  freq -= uhd::math::sign(freq) * rate;
295  return freq;
296 }
297 
298 } // namespace math
299 } // namespace uhd
300 
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::lin_to_dB
double lin_to_dB(const double val)
Definition: math.hpp:259
uhd::math::frequencies_are_equal
UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
Definition: math.hpp:248
uhd::math::fp_compare::freq_compare_epsilon
An alias for fp_compare_epsilon, but with defaults for frequencies.
Definition: math.hpp:145
uhd::math::fp_compare::fp_compare_epsilon::_epsilon
float_t _epsilon
Definition: math.hpp:79
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:273
uhd::math::fp_compare::fp_compare_delta::_value
float_t _value
Definition: math.hpp:201
uhd::math::fp_compare::freq_compare_epsilon::freq_compare_epsilon
UHD_INLINE freq_compare_epsilon(const freq_compare_epsilon &copy)
Definition: math.hpp:153
uhd::math::fp_compare::fp_compare_delta::_delta
float_t _delta
Definition: math.hpp:202
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::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:148
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:290
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:78
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:192
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:254
uhd::math::fp_compare::fp_compare_epsilon
Definition: math.hpp:69
fp_compare_epsilon.ipp