lib: Replace uhd::math::gcd,lcm with std::gcd,lcm

This became possible with the new dependency on C++17, which added std::
gcm() and std::lcm(). The standard library has some advantages over our
version (e.g., constexpr) but most importantly, it allows us to remove
the (version dependent!) Boost dependency in math.hpp.

This breaks the public API: `uhd::math::{gcd,lcm}` were defined in the
public header uhd/utils/math.hpp.
This commit is contained in:
Martin Braun 2024-10-17 16:19:37 +02:00 committed by joerg.hofrichter@emerson.com
parent a0a3c3a856
commit 3909512623
11 changed files with 30 additions and 58 deletions

View File

@ -1,6 +1,14 @@
Change Log for Releases
==============================
## 004.next
* API Changes
- `uhd::math::gcd` and `uhd::math::lcm` are removed from the public
headers. Use `std::gcd` and `std::lcm` instead if C++17 is available,
or `boost::math::gcd` and `boost::math::lcm` if not.
## 004.008.000.000
* Highlights / Main Changes
- Addition of rfnoc_modtool and further improvements to RFNoC Image Builder

View File

@ -8,17 +8,7 @@
#pragma once
#include <uhd/config.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/version.hpp>
#include <cmath>
#if BOOST_VERSION >= 106700
# include <boost/integer/common_factor.hpp>
// "bmint" for "boost math integer"
namespace _bmint = boost::integer;
#else
# include <boost/math/common_factor.hpp>
namespace _bmint = boost::math;
#endif
namespace uhd {
@ -272,22 +262,6 @@ inline double lin_to_dB(const double val)
}
//! Portable version of lcm() across Boost versions
template <typename IntegerType>
inline IntegerType lcm(IntegerType x, IntegerType y)
{
// Note: _bmint is defined conditionally at the top of the file
return _bmint::lcm<IntegerType>(x, y);
}
//! Portable version of gcd() across Boost versions
template <typename IntegerType>
inline IntegerType gcd(IntegerType x, IntegerType y)
{
// Note: _bmint is defined conditionally at the top of the file
return _bmint::gcd<IntegerType>(x, y);
}
//! Returns the sign of x
//
// Note: This is equivalent to the Boost.Math version, but without the

View File

@ -19,6 +19,7 @@
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <utility>
#include <vector>
@ -421,7 +422,7 @@ inline double adf535x_impl<adf5355_regs_t>::_set_frequency(
// The data sheet recommends reducing FRAC2 and MOD2 to the lowest possible values
const uint16_t frac2 = static_cast<uint16_t>(
std::min(ceil(residue * mod2), static_cast<double>(ADF5355_MAX_FRAC2)));
const auto gcd = uhd::math::gcd(static_cast<int>(frac2), static_cast<int>(mod2));
const auto gcd = std::gcd(static_cast<int>(frac2), static_cast<int>(mod2));
// FRAC2 and MOD2 are 14-bit numbers
const uint16_t FRAC2 = (frac2 == 0) ? 0 : frac2 / gcd;
const uint16_t MOD2 = (frac2 == 0) ? 2 : mod2 / gcd;
@ -563,7 +564,7 @@ inline double adf535x_impl<adf5356_regs_t>::_set_frequency(
// The data sheet recommends reducing FRAC2 and MOD2 to the lowest possible values
const uint32_t frac2 = static_cast<uint32_t>(
std::min(ceil(residue * mod2), static_cast<double>(ADF5356_MAX_FRAC2)));
const auto gcd = uhd::math::gcd(static_cast<int>(frac2), static_cast<int>(mod2));
const auto gcd = std::gcd(static_cast<int>(frac2), static_cast<int>(mod2));
// FRAC2 and MOD2 are 28-bit numbers
const uint32_t FRAC2 = (frac2 == 0) ? 0 : frac2 / gcd;
const uint32_t MOD2 = (frac2 == 0) ? 2 : mod2 / gcd;

View File

@ -9,10 +9,10 @@
#include <uhd/rfnoc/multichan_register_iface.hpp>
#include <uhd/rfnoc/register_iface.hpp>
#include <uhd/utils/log.hpp>
#include <uhd/utils/math.hpp>
#include <uhdlib/rfnoc/radio_control_impl.hpp>
#include <uhdlib/utils/compat_check.hpp>
#include <map>
#include <numeric>
#include <tuple>
using namespace uhd::rfnoc;
@ -173,7 +173,7 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
{&_atomic_item_size_in.back()},
[this, chan, &ais_in = _atomic_item_size_in.back()]() {
RFNOC_LOG_TRACE("Calling resolver for atomic_item_size in@" << chan);
ais_in = uhd::math::lcm<size_t>(ais_in, get_atomic_item_size());
ais_in = std::lcm<size_t>(ais_in, get_atomic_item_size());
ais_in = std::min<size_t>(
ais_in, get_mtu({res_source_info::INPUT_EDGE, chan}));
if ((ais_in % get_atomic_item_size()) > 0) {
@ -186,7 +186,7 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
{&_atomic_item_size_out.back()},
[this, chan, &ais_out = _atomic_item_size_out.back()]() {
RFNOC_LOG_TRACE("Calling resolver for atomic_item_size out@" << chan);
ais_out = uhd::math::lcm<size_t>(ais_out, get_atomic_item_size());
ais_out = std::lcm<size_t>(ais_out, get_atomic_item_size());
ais_out = std::min<size_t>(
ais_out, get_mtu({res_source_info::OUTPUT_EDGE, chan}));
if ((ais_out % get_atomic_item_size()) > 0) {

View File

@ -13,9 +13,9 @@
#include <uhd/rfnoc/replay_block_control.hpp>
#include <uhd/transport/bounded_buffer.hpp>
#include <uhd/types/stream_cmd.hpp>
#include <uhd/utils/math.hpp>
#include <uhdlib/utils/compat_check.hpp>
#include <uhdlib/utils/narrow.hpp>
#include <numeric>
#include <string>
using namespace uhd::rfnoc;
@ -535,7 +535,7 @@ private:
get_mtu_prop_ref({res_source_info::INPUT_EDGE, port})},
{&_atomic_item_size_in.back()},
[this, port, &ais_in = _atomic_item_size_in.back()]() {
ais_in = uhd::math::lcm<size_t>(ais_in, get_word_size());
ais_in = std::lcm<size_t>(ais_in, get_word_size());
ais_in = std::min<size_t>(
ais_in, get_mtu({res_source_info::INPUT_EDGE, port}));
if (ais_in.get() % get_word_size() > 0) {
@ -598,7 +598,7 @@ private:
get_mtu_prop_ref({res_source_info::OUTPUT_EDGE, port})},
{&_atomic_item_size_out.back()},
[this, port, &ais_out = _atomic_item_size_out.back()]() {
ais_out = uhd::math::lcm<size_t>(ais_out, get_word_size());
ais_out = std::lcm<size_t>(ais_out, get_word_size());
ais_out = std::min<size_t>(
ais_out, get_mtu({res_source_info::OUTPUT_EDGE, port}));
if (ais_out.get() % get_word_size() > 0) {
@ -679,8 +679,8 @@ private:
// - Configured item size (e.g., sample size)
const uint32_t item_size = get_play_item_size(port);
const uint32_t atomic_item_size = _atomic_item_size_out.at(port).get();
const uint32_t min_chunk = uhd::math::lcm<uint32_t>(
uhd::math::lcm<uint32_t>(item_size, atomic_item_size), _word_size);
const uint32_t min_chunk = std::lcm<uint32_t>(
std::lcm<uint32_t>(item_size, atomic_item_size), _word_size);
if (new_pyld_size % min_chunk != 0) {
const uint32_t coerced_size = new_pyld_size - (new_pyld_size % min_chunk);

View File

@ -5,14 +5,13 @@
//
#include <uhd/rfnoc/defaults.hpp>
#include <uhd/utils/math.hpp>
#include <uhdlib/rfnoc/node_accessor.hpp>
#include <uhdlib/rfnoc/rfnoc_rx_streamer.hpp>
#include <atomic>
#include <numeric>
#include <thread>
using namespace std::chrono_literals;
;
using namespace uhd;
using namespace uhd::rfnoc;
@ -267,7 +266,7 @@ void rfnoc_rx_streamer::_register_props(const size_t chan, const std::string& ot
if (ais.is_valid()) {
const size_t bpi = convert::get_bytes_per_item(type.get());
const size_t spp = this->rx_streamer_impl::get_max_num_samps();
const size_t spp_multiple = uhd::math::lcm<size_t>(ais.get(), bpi) / bpi;
const size_t spp_multiple = std::lcm<size_t>(ais.get(), bpi) / bpi;
if (spp < spp_multiple) {
RFNOC_LOG_ERROR("Cannot resolve spp! Must be a multiple of "
<< spp_multiple << " but max value is " << spp);

View File

@ -5,10 +5,10 @@
//
#include <uhd/rfnoc/defaults.hpp>
#include <uhd/utils/math.hpp>
#include <uhdlib/rfnoc/node_accessor.hpp>
#include <uhdlib/rfnoc/rfnoc_tx_streamer.hpp>
#include <atomic>
#include <numeric>
using namespace uhd;
using namespace uhd::rfnoc;
@ -266,7 +266,7 @@ void rfnoc_tx_streamer::_register_props(const size_t chan, const std::string& ot
if (ais.is_valid()) {
const size_t bpi = convert::get_bytes_per_item(type.get());
const size_t spp = this->tx_streamer_impl::get_max_num_samps();
const size_t spp_multiple = uhd::math::lcm<size_t>(ais.get(), bpi) / bpi;
const size_t spp_multiple = std::lcm<size_t>(ais.get(), bpi) / bpi;
if (spp < spp_multiple) {
RFNOC_LOG_ERROR("Cannot resolve spp! Must be a multiple of "
<< spp_multiple << " but max value is " << spp);

View File

@ -5,9 +5,9 @@
//
#include <uhd/exception.hpp>
#include <uhd/utils/math.hpp>
#include <uhd/utils/safe_call.hpp>
#include <uhdlib/rfnoc/rfnoc_tx_streamer_replay_buffered.hpp>
#include <numeric>
using namespace uhd;
using namespace uhd::rfnoc;
@ -66,7 +66,7 @@ size_t rfnoc_tx_streamer_replay_buffered::send(const buffs_type& buffs,
throw uhd::runtime_error(
"[multi_usrp] Number of samples for send() call must be a "
"multiple of "
+ std::to_string(uhd::math::lcm<uint64_t>(
+ std::to_string(std::lcm<uint64_t>(
replay->get_word_size(), uint64_t(_bytes_per_otw_item)))
+ " for DRAM alignment");
}

View File

@ -11,13 +11,13 @@
#include <uhd/exception.hpp>
#include <uhd/utils/assert_has.hpp>
#include <uhd/utils/log.hpp>
#include <uhd/utils/math.hpp>
#include <uhd/utils/safe_call.hpp>
#include <uhdlib/utils/narrow.hpp>
#include <stdint.h>
#include <boost/format.hpp>
#include <algorithm>
#include <chrono>
#include <numeric>
#include <thread>
#include <utility>
@ -125,8 +125,7 @@ static clock_settings_type get_clock_settings(double rate)
const uint64_t out_rate = uint64_t(rate);
const uint64_t ref_rate = uint64_t(cs.get_ref_rate());
const size_t gcd =
uhd::narrow_cast<size_t>((uhd::math::gcd<size_t>(ref_rate, out_rate)));
const size_t gcd = uhd::narrow_cast<size_t>((std::gcd<size_t>(ref_rate, out_rate)));
for (size_t i = 1; i <= 100; i++) {
const size_t X = size_t(i * ref_rate / gcd);
@ -316,7 +315,7 @@ public:
const double ref_rate = REFERENCE_INPUT_RATE * 2;
// bypass prescaler such that N = B
long gcd = uhd::math::gcd(long(ref_rate), long(rate));
long gcd = std::gcd(long(ref_rate), long(rate));
_ad9522_regs.set_r_counter(int(ref_rate / gcd));
_ad9522_regs.a_counter = 0;
_ad9522_regs.set_b_counter(int(rate / gcd));

View File

@ -14,6 +14,7 @@
#include <uhdlib/usrp/common/validate_subdev_spec.hpp>
#include <functional>
#include <memory>
#include <numeric>
#include <set>
using namespace uhd;
@ -110,7 +111,7 @@ void b200_impl::set_auto_tick_rate(
}
// Clean up floating point rounding errors if they crept in
this_dsp_rate = std::min(max_tick_rate, this_dsp_rate);
lcm_rate = uhd::math::lcm<uint32_t>(
lcm_rate = std::lcm<uint32_t>(
lcm_rate, static_cast<uint32_t>(floor(this_dsp_rate + 0.5)));
}
}

View File

@ -8,16 +8,6 @@
#include <uhd/utils/math.hpp>
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(test_lcm)
{
BOOST_CHECK_EQUAL(uhd::math::lcm<int>(2, 3), 6);
}
BOOST_AUTO_TEST_CASE(test_gcd)
{
BOOST_CHECK_EQUAL(uhd::math::gcd<int>(6, 15), 3);
}
BOOST_AUTO_TEST_CASE(test_sign)
{
BOOST_CHECK_EQUAL(uhd::math::sign(2.3), +1);