USRP Hardware Driver and USRP Manual  Version: 3.11.0.HEAD-0-g13c32cef
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 #ifndef INCLUDED_UHD_UTILS_MATH_HPP
9 #define INCLUDED_UHD_UTILS_MATH_HPP
10 
11 #include <cmath>
12 #include <uhd/config.hpp>
13 #include <stdint.h>
14 #include <boost/numeric/conversion/bounds.hpp>
15 
16 namespace uhd {
17 
22 namespace math {
23 
40  static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
41  static const double DOUBLE_PRECISION_EPSILON = 2.22e-16;
42 
43 namespace fp_compare {
44 
58  template<typename float_t> class fp_compare_epsilon {
59  public:
60  UHD_INLINE fp_compare_epsilon(float_t value);
61  UHD_INLINE fp_compare_epsilon(float_t value, float_t epsilon);
64  UHD_INLINE void operator=(const fp_compare_epsilon& copy);
65 
66  float_t _value;
67  float_t _epsilon;
68  };
69 
70  /* A Note on Floating Point Equality with Epsilons
71  *
72  * There are obviously a lot of strategies for defining floating point
73  * equality, and in the end it all comes down to the domain at hand. UHD's
74  * floating-point-with-epsilon comparison algorithm is based on the method
75  * presented in Knuth's "The Art of Computer Science" called "very close
76  * with tolerance epsilon".
77  *
78  * [(|u - v| / |u|) <= e] && [(|u - v| / |v|) <= e]
79  *
80  * UHD's modification to this algorithm is using the denominator's epsilon
81  * value (since each float_t object has its own epsilon) for each
82  * comparison.
83  */
84 
85  template<typename float_t> UHD_INLINE
87  template<typename float_t> UHD_INLINE
89  template<typename float_t> UHD_INLINE
90  bool operator<(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
91  template<typename float_t> UHD_INLINE
92  bool operator<=(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
93  template<typename float_t> UHD_INLINE
95  template<typename float_t> UHD_INLINE
97 
98  /* If these operators are used with floats, we rely on type promotion to
99  * double. */
100  template<typename float_t> UHD_INLINE
101  bool operator==(fp_compare_epsilon<float_t> lhs, double rhs);
102  template<typename float_t> UHD_INLINE
103  bool operator!=(fp_compare_epsilon<float_t> lhs, double rhs);
104  template<typename float_t> UHD_INLINE
105  bool operator<(fp_compare_epsilon<float_t> lhs, double rhs);
106  template<typename float_t> UHD_INLINE
107  bool operator<=(fp_compare_epsilon<float_t> lhs, double rhs);
108  template<typename float_t> UHD_INLINE
109  bool operator>(fp_compare_epsilon<float_t> lhs, double rhs);
110  template<typename float_t> UHD_INLINE
111  bool operator>=(fp_compare_epsilon<float_t> lhs, double rhs);
112 
113  template<typename float_t> UHD_INLINE
114  bool operator==(double lhs, fp_compare_epsilon<float_t> rhs);
115  template<typename float_t> UHD_INLINE
116  bool operator!=(double lhs, fp_compare_epsilon<float_t> rhs);
117  template<typename float_t> UHD_INLINE
118  bool operator<(double lhs, fp_compare_epsilon<float_t> rhs);
119  template<typename float_t> UHD_INLINE
120  bool operator<=(double lhs, fp_compare_epsilon<float_t> rhs);
121  template<typename float_t> UHD_INLINE
122  bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
123  template<typename float_t> UHD_INLINE
124  bool operator>=(double lhs, fp_compare_epsilon<float_t> rhs);
125 
126 } // namespace fp_compare
127 
128 
135  static const float SINGLE_PRECISION_DELTA = 1e-3f;
136  static const double DOUBLE_PRECISION_DELTA = 1e-5;
137 
139  static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
140 
141 
142 namespace fp_compare {
143 
157  template<typename float_t> class fp_compare_delta {
158  public:
159  UHD_INLINE fp_compare_delta(float_t value);
160  UHD_INLINE fp_compare_delta(float_t value, float_t delta);
161  UHD_INLINE fp_compare_delta(const fp_compare_delta<float_t>& copy);
162  UHD_INLINE ~fp_compare_delta();
163  UHD_INLINE void operator=(const fp_compare_delta& copy);
164 
165  float_t _value;
166  float_t _delta;
167  };
168 
169  template<typename float_t> UHD_INLINE
171  template<typename float_t> UHD_INLINE
173  template<typename float_t> UHD_INLINE
174  bool operator<(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
175  template<typename float_t> UHD_INLINE
176  bool operator<=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
177  template<typename float_t> UHD_INLINE
179  template<typename float_t> UHD_INLINE
181 
182  /* If these operators are used with floats, we rely on type promotion to
183  * double. */
184  template<typename float_t> UHD_INLINE
185  bool operator==(fp_compare_delta<float_t> lhs, double rhs);
186  template<typename float_t> UHD_INLINE
187  bool operator!=(fp_compare_delta<float_t> lhs, double rhs);
188  template<typename float_t> UHD_INLINE
189  bool operator<(fp_compare_delta<float_t> lhs, double rhs);
190  template<typename float_t> UHD_INLINE
191  bool operator<=(fp_compare_delta<float_t> lhs, double rhs);
192  template<typename float_t> UHD_INLINE
193  bool operator>(fp_compare_delta<float_t> lhs, double rhs);
194  template<typename float_t> UHD_INLINE
195  bool operator>=(fp_compare_delta<float_t> lhs, double rhs);
196 
197  template<typename float_t> UHD_INLINE
198  bool operator==(double lhs, fp_compare_delta<float_t> rhs);
199  template<typename float_t> UHD_INLINE
200  bool operator!=(double lhs, fp_compare_delta<float_t> rhs);
201  template<typename float_t> UHD_INLINE
202  bool operator<(double lhs, fp_compare_delta<float_t> rhs);
203  template<typename float_t> UHD_INLINE
204  bool operator<=(double lhs, fp_compare_delta<float_t> rhs);
205  template<typename float_t> UHD_INLINE
206  bool operator>(double lhs, fp_compare_delta<float_t> rhs);
207  template<typename float_t> UHD_INLINE
208  bool operator>=(double lhs, fp_compare_delta<float_t> rhs);
209 
210 } // namespace fp_compare
211 
212  UHD_INLINE bool frequencies_are_equal(double lhs, double rhs) {
213  return(fp_compare::fp_compare_delta<double>(lhs, FREQ_COMPARISON_DELTA_HZ)
214  == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ));
215  }
216 
218  template <typename float_t> UHD_INLINE
219  float_t log2(float_t x)
220  {
221  // C++11 defines std::log2(), when that's universally supported
222  // we can switch over.
223  return std::log(x) / std::log(float_t(2));
224  }
225 
226 
227 } // namespace math
228 } // namespace uhd
229 
232 
233 #endif /* INCLUDED_UHD_UTILS_MATH_HPP */
UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
Definition: math.hpp:212
float_t _value
Definition: math.hpp:165
UHD_INLINE float_t log2(float_t x)
Portable log2()
Definition: math.hpp:219
UHD_INLINE bool operator>=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:87
UHD_INLINE bool operator>(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:81
UHD_INLINE bool operator!=(fp_compare_delta< float_t > lhs, fp_compare_delta< float_t > rhs)
Definition: fp_compare_delta.ipp:65
float_t _delta
Definition: math.hpp:166
float_t _epsilon
Definition: math.hpp:67
Definition: build_info.hpp:14
#define UHD_INLINE
Definition: config.h:53
UHD_INLINE ~fp_compare_epsilon()
Definition: fp_compare_epsilon.ipp:44
float_t _value
Definition: math.hpp:66
UHD_INLINE void operator=(const fp_compare_epsilon &copy)
Definition: fp_compare_epsilon.ipp:48
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:59