Loading...
Searching...
No Matches
math.hpp
Go to the documentation of this file.
//
// Copyright 2014-2015 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#pragma once
#include <uhd/config.hpp>
#include <cmath>
namespace uhd {
namespace math {
static const double PI = 3.14159265358979323846;
static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
static const double DOUBLE_PRECISION_EPSILON = 2.22e-16;
//
// Note that this is a UHD/USRP-specific constant. In UHD, frequencies are on
// the order of 1e9 (GHz) or below. We will declare frequencies as equal if they
// are within a millihertz. For the purpose of
// comparing frequencies, we "lose" 9 decimal places for the integer
// component of the frequency, so we choose this epsilon value for floating
// point comparison of frequencies.
static constexpr double FREQ_COMPARE_EPSILON = 1e-12;
namespace fp_compare {
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 "close enough
* 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 freq_compare_epsilon : public fp_compare_epsilon<double>
{
public:
UHD_INLINE freq_compare_epsilon(double value)
: fp_compare_epsilon<double>(value, FREQ_COMPARE_EPSILON)
{
}
UHD_INLINE freq_compare_epsilon(const freq_compare_epsilon& copy)
: fp_compare_epsilon<double>(copy)
{
}
};
} // namespace fp_compare
static const float SINGLE_PRECISION_DELTA = 1e-3f;
static const double DOUBLE_PRECISION_DELTA = 1e-5;
static const double FREQ_COMPARISON_DELTA_HZ = 0.1;
namespace fp_compare {
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));
}
inline double dB_to_lin(const double dB_val)
{
return std::pow(10, (dB_val) / 10.0);
}
inline double lin_to_dB(const double val)
{
return 10 * std::log10(val);
}
//
// Note: This is equivalent to the Boost.Math version, but without the
// dependency.
//
// Returns +1 for positive arguments, -1 for negative arguments, and 0 if x is
// zero.
template <typename T>
inline constexpr int sign(T x)
{
// Note: If T is unsigned, then this will compile with a warning. Should
// we need that, expand the template logic.
return (T(0) < x) - (x < T(0));
}
// Nyquist zone.
//
// Examples:
// - Just above the sampling rate:
// wrap_frequency(250e6, 200e6) == 50e6
// - Just outside the Nyquist zone:
// wrap_frequency(120e6, 200e6) == -80e6
// - Also works for negative frequencies:
// wrap_frequency(-250e6, 200e6) == -50e6
inline double wrap_frequency(const double requested_freq, const double rate)
{
double freq = std::fmod(requested_freq, rate);
if (std::abs(freq) > rate / 2.0)
freq -= uhd::math::sign(freq) * rate;
return freq;
}
} // namespace math
} // namespace uhd
#include <uhd/utils/fp_compare_delta.ipp>
#include <uhd/utils/fp_compare_epsilon.ipp>
uhd::math::fp_compare::fp_compare_delta
Definition math.hpp:193
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:202
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:201
uhd::math::fp_compare::fp_compare_epsilon
Definition math.hpp:70
uhd::math::fp_compare::fp_compare_epsilon::_epsilon
float_t _epsilon
Definition math.hpp:79
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:78
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:153
uhd::math::fp_compare::freq_compare_epsilon::freq_compare_epsilon
UHD_INLINE freq_compare_epsilon(double value)
Definition math.hpp:148
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::frequencies_are_equal
UHD_INLINE bool frequencies_are_equal(double lhs, double rhs)
Definition math.hpp:248
uhd::math::dB_to_lin
double dB_to_lin(const double dB_val)
Definition math.hpp:254
uhd::math::sign
constexpr int sign(T x)
Returns the sign of x.
Definition math.hpp:273
uhd::math::lin_to_dB
double lin_to_dB(const double val)
Definition math.hpp:259
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
Definition build_info.hpp:12