aboutsummaryrefslogtreecommitdiffstats
path: root/host/include/uhd/utils/math.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/include/uhd/utils/math.hpp')
-rw-r--r--host/include/uhd/utils/math.hpp380
1 files changed, 194 insertions, 186 deletions
diff --git a/host/include/uhd/utils/math.hpp b/host/include/uhd/utils/math.hpp
index b0e7dd145..e9f8efb57 100644
--- a/host/include/uhd/utils/math.hpp
+++ b/host/include/uhd/utils/math.hpp
@@ -8,10 +8,10 @@
#ifndef INCLUDED_UHD_UTILS_MATH_HPP
#define INCLUDED_UHD_UTILS_MATH_HPP
-#include <cmath>
#include <uhd/config.hpp>
#include <stdint.h>
#include <boost/numeric/conversion/bounds.hpp>
+#include <cmath>
namespace uhd {
@@ -21,213 +21,221 @@ namespace uhd {
*/
namespace math {
- /*!
- * Define epsilon values for floating point comparisons.
- *
- * There are a lot of different sources for epsilon values that we could use
- * for this. For single-precision (f32), most machines will report an
- * epsilon of 1.192e-7, and for double-precision (f64) most machines will
- * report an epsilon of 2.220e-16. The issue is that these are not always
- * appropriate, depending on the scale of the operands and how they have
- * been rounded in previous calculations. The values defined here are
- * defaults, but should be overridden for calculations depending on the
- * application.
- *
- * If a particular comparison is operating using very small or very large
- * values, a custom epsilon should be defined for those computations. This
- * use-case is provided for in the `fp_compare_epsilon` class constructor.
- */
- static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
- static const double DOUBLE_PRECISION_EPSILON = 2.22e-16;
+/*!
+ * Define epsilon values for floating point comparisons.
+ *
+ * There are a lot of different sources for epsilon values that we could use
+ * for this. For single-precision (f32), most machines will report an
+ * epsilon of 1.192e-7, and for double-precision (f64) most machines will
+ * report an epsilon of 2.220e-16. The issue is that these are not always
+ * appropriate, depending on the scale of the operands and how they have
+ * been rounded in previous calculations. The values defined here are
+ * defaults, but should be overridden for calculations depending on the
+ * application.
+ *
+ * If a particular comparison is operating using very small or very large
+ * values, a custom epsilon should be defined for those computations. This
+ * use-case is provided for in the `fp_compare_epsilon` class constructor.
+ */
+static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
+static const double DOUBLE_PRECISION_EPSILON = 2.22e-16;
namespace fp_compare {
- /*!
- * Class for floating-point comparisons using an epsilon.
- *
- * At construction, you can specify the epsilon to use for the comparisons.
- * This class, combined with the operators under it, allow for
- * epsilon-comparisons of floats. An example is:
- *
- * // Compare floats 'x' and 'y'.
- * bool x_equals_y = (fp_compare_epsilon<float>(x) == y);
- *
- * // Compare doubles 'x' and 'y'.
- * bool x_equals_y = (fp_compare_epsilon<double>(x) == y);
- */
- template<typename float_t> class fp_compare_epsilon {
- public:
- UHD_INLINE fp_compare_epsilon(float_t value);
- UHD_INLINE fp_compare_epsilon(float_t value, float_t epsilon);
- UHD_INLINE fp_compare_epsilon(const fp_compare_epsilon<float_t>& copy);
- UHD_INLINE ~fp_compare_epsilon();
- UHD_INLINE void operator=(const fp_compare_epsilon& copy);
-
- float_t _value;
- float_t _epsilon;
- };
-
- /* A Note on Floating Point Equality with Epsilons
- *
- * There are obviously a lot of strategies for defining floating point
- * equality, and in the end it all comes down to the domain at hand. UHD's
- * floating-point-with-epsilon comparison algorithm is based on the method
- * presented in Knuth's "The Art of Computer Science" called "very close
- * with tolerance epsilon".
- *
- * [(|u - v| / |u|) <= e] && [(|u - v| / |v|) <= e]
- *
- * UHD's modification to this algorithm is using the denominator's epsilon
- * value (since each float_t object has its own epsilon) for each
- * comparison.
- */
-
- template<typename float_t> UHD_INLINE
- bool operator==(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator!=(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator<(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator<=(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator>(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator>=(fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
-
- /* If these operators are used with floats, we rely on type promotion to
- * double. */
- template<typename float_t> UHD_INLINE
- bool operator==(fp_compare_epsilon<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator!=(fp_compare_epsilon<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator<(fp_compare_epsilon<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator<=(fp_compare_epsilon<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator>(fp_compare_epsilon<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator>=(fp_compare_epsilon<float_t> lhs, double rhs);
-
- template<typename float_t> UHD_INLINE
- bool operator==(double lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator!=(double lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator<(double lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator<=(double lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator>=(double lhs, fp_compare_epsilon<float_t> rhs);
+/*!
+ * Class for floating-point comparisons using an epsilon.
+ *
+ * At construction, you can specify the epsilon to use for the comparisons.
+ * This class, combined with the operators under it, allow for
+ * epsilon-comparisons of floats. An example is:
+ *
+ * // Compare floats 'x' and 'y'.
+ * bool x_equals_y = (fp_compare_epsilon<float>(x) == y);
+ *
+ * // Compare doubles 'x' and 'y'.
+ * bool x_equals_y = (fp_compare_epsilon<double>(x) == y);
+ */
+template <typename float_t> class fp_compare_epsilon
+{
+public:
+ UHD_INLINE fp_compare_epsilon(float_t value);
+ UHD_INLINE fp_compare_epsilon(float_t value, float_t epsilon);
+ UHD_INLINE fp_compare_epsilon(const fp_compare_epsilon<float_t>& copy);
+ UHD_INLINE ~fp_compare_epsilon();
+ UHD_INLINE void operator=(const fp_compare_epsilon& copy);
+
+ float_t _value;
+ float_t _epsilon;
+};
+
+/* A Note on Floating Point Equality with Epsilons
+ *
+ * There are obviously a lot of strategies for defining floating point
+ * equality, and in the end it all comes down to the domain at hand. UHD's
+ * floating-point-with-epsilon comparison algorithm is based on the method
+ * presented in Knuth's "The Art of Computer Science" called "very close
+ * with tolerance epsilon".
+ *
+ * [(|u - v| / |u|) <= e] && [(|u - v| / |v|) <= e]
+ *
+ * UHD's modification to this algorithm is using the denominator's epsilon
+ * value (since each float_t object has its own epsilon) for each
+ * comparison.
+ */
+
+template <typename float_t>
+UHD_INLINE bool operator==(
+ fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator!=(
+ fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator<(
+ fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator<=(
+ fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator>(
+ fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator>=(
+ fp_compare_epsilon<float_t> lhs, fp_compare_epsilon<float_t> rhs);
+
+/* If these operators are used with floats, we rely on type promotion to
+ * double. */
+template <typename float_t>
+UHD_INLINE bool operator==(fp_compare_epsilon<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator!=(fp_compare_epsilon<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator<(fp_compare_epsilon<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator<=(fp_compare_epsilon<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator>(fp_compare_epsilon<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator>=(fp_compare_epsilon<float_t> lhs, double rhs);
+
+template <typename float_t>
+UHD_INLINE bool operator==(double lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator!=(double lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator<(double lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator<=(double lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator>=(double lhs, fp_compare_epsilon<float_t> rhs);
} // namespace fp_compare
- /*!
- * Define delta values for floating point comparisons.
- *
- * These are the default deltas used by the 'fp_compare_delta' class for
- * single and double-precision floating point comparisons.
- */
- static const float SINGLE_PRECISION_DELTA = 1e-3f;
- static const double DOUBLE_PRECISION_DELTA = 1e-5;
+/*!
+ * Define delta values for floating point comparisons.
+ *
+ * These are the default deltas used by the 'fp_compare_delta' class for
+ * single and double-precision floating point comparisons.
+ */
+static const float SINGLE_PRECISION_DELTA = 1e-3f;
+static const double DOUBLE_PRECISION_DELTA = 1e-5;
- /*! Floating-point delta to use for frequency comparisons. */
- static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
+/*! Floating-point delta to use for frequency comparisons. */
+static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
namespace fp_compare {
/*!
- * Class for floating-point comparisons using a delta.
- *
- * At construction, you can specify the delta to use for the comparisons.
- * This class, combined with the operators under it, allow for
- * delta-comparisons of floats. An example is:
- *
- * // Compare floats 'x' and 'y'.
- * bool x_equals_y = (fp_compare_delta<float>(x) == y);
- *
- * // Compare doubles 'x' and 'y'.
- * bool x_equals_y = (fp_compare_delta<double>(x) == y);
- */
- template<typename float_t> class fp_compare_delta {
- public:
- UHD_INLINE fp_compare_delta(float_t value);
- UHD_INLINE fp_compare_delta(float_t value, float_t delta);
- UHD_INLINE fp_compare_delta(const fp_compare_delta<float_t>& copy);
- UHD_INLINE ~fp_compare_delta();
- UHD_INLINE void operator=(const fp_compare_delta& copy);
-
- float_t _value;
- float_t _delta;
- };
-
- template<typename float_t> UHD_INLINE
- bool operator==(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator!=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator<(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator<=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator>(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator>=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
-
- /* If these operators are used with floats, we rely on type promotion to
- * double. */
- template<typename float_t> UHD_INLINE
- bool operator==(fp_compare_delta<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator!=(fp_compare_delta<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator<(fp_compare_delta<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator<=(fp_compare_delta<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator>(fp_compare_delta<float_t> lhs, double rhs);
- template<typename float_t> UHD_INLINE
- bool operator>=(fp_compare_delta<float_t> lhs, double rhs);
-
- template<typename float_t> UHD_INLINE
- bool operator==(double lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator!=(double lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator<(double lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator<=(double lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator>(double lhs, fp_compare_delta<float_t> rhs);
- template<typename float_t> UHD_INLINE
- bool operator>=(double lhs, fp_compare_delta<float_t> rhs);
+ * Class for floating-point comparisons using a delta.
+ *
+ * At construction, you can specify the delta to use for the comparisons.
+ * This class, combined with the operators under it, allow for
+ * delta-comparisons of floats. An example is:
+ *
+ * // Compare floats 'x' and 'y'.
+ * bool x_equals_y = (fp_compare_delta<float>(x) == y);
+ *
+ * // Compare doubles 'x' and 'y'.
+ * bool x_equals_y = (fp_compare_delta<double>(x) == y);
+ */
+template <typename float_t> class fp_compare_delta
+{
+public:
+ UHD_INLINE fp_compare_delta(float_t value);
+ UHD_INLINE fp_compare_delta(float_t value, float_t delta);
+ UHD_INLINE fp_compare_delta(const fp_compare_delta<float_t>& copy);
+ UHD_INLINE ~fp_compare_delta();
+ UHD_INLINE void operator=(const fp_compare_delta& copy);
+
+ float_t _value;
+ float_t _delta;
+};
+
+template <typename float_t>
+UHD_INLINE bool operator==(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator!=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator<=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator>(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator>=(fp_compare_delta<float_t> lhs, fp_compare_delta<float_t> rhs);
+
+/* If these operators are used with floats, we rely on type promotion to
+ * double. */
+template <typename float_t>
+UHD_INLINE bool operator==(fp_compare_delta<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator!=(fp_compare_delta<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator<=(fp_compare_delta<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator>(fp_compare_delta<float_t> lhs, double rhs);
+template <typename float_t>
+UHD_INLINE bool operator>=(fp_compare_delta<float_t> lhs, double rhs);
+
+template <typename float_t>
+UHD_INLINE bool operator==(double lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator!=(double lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator<(double lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator<=(double lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator>(double lhs, fp_compare_delta<float_t> rhs);
+template <typename float_t>
+UHD_INLINE bool operator>=(double lhs, fp_compare_delta<float_t> rhs);
} // namespace fp_compare
- UHD_INLINE bool frequencies_are_equal(double lhs, double rhs) {
- return(fp_compare::fp_compare_delta<double>(lhs, FREQ_COMPARISON_DELTA_HZ)
- == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ));
- }
+UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
+{
+ return (fp_compare::fp_compare_delta<double>(lhs, FREQ_COMPARISON_DELTA_HZ)
+ == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ));
+}
- //! Portable log2()
- template <typename float_t> UHD_INLINE
- float_t log2(float_t x)
- {
- // C++11 defines std::log2(), when that's universally supported
- // we can switch over.
- return std::log(x) / std::log(float_t(2));
- }
+//! Portable log2()
+template <typename float_t> UHD_INLINE float_t log2(float_t x)
+{
+ // C++11 defines std::log2(), when that's universally supported
+ // we can switch over.
+ return std::log(x) / std::log(float_t(2));
+}
} // namespace math
} // namespace uhd
-#include <uhd/utils/fp_compare_epsilon.ipp>
#include <uhd/utils/fp_compare_delta.ipp>
+#include <uhd/utils/fp_compare_epsilon.ipp>
#endif /* INCLUDED_UHD_UTILS_MATH_HPP */