From 6218a709ae1eb78b03c4f6bfb247781a8bd699d8 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Mon, 21 Mar 2022 18:13:47 +0100 Subject: [PATCH] refactor: `first_factor_maybe()` replaced with `get_first_of()` --- .../units/bits/{external => }/algorithm.h | 43 ++++++++++++++----- .../units/bits/external/fixed_string.h | 2 +- src/core/include/units/bits/prime.h | 29 ++++--------- 3 files changed, 42 insertions(+), 32 deletions(-) rename src/core/include/units/bits/{external => }/algorithm.h (66%) diff --git a/src/core/include/units/bits/external/algorithm.h b/src/core/include/units/bits/algorithm.h similarity index 66% rename from src/core/include/units/bits/external/algorithm.h rename to src/core/include/units/bits/algorithm.h index 830f8cc5..762bb7bc 100644 --- a/src/core/include/units/bits/external/algorithm.h +++ b/src/core/include/units/bits/algorithm.h @@ -24,9 +24,41 @@ #include // IWYU pragma: keep #include +#include namespace units::detail { +// TODO refactor two below functions with std::ranges when moved to modules + + +/** + * @brief Returns the first successful value obtained from applying the function object to the elements of a given + * range, if any. + * + * @tparam InputIt must meet the requirements of LegacyInputIterator + * @tparam UnaryFunction must meet the requirements of MoveConstructible + * @param first the beginning of the range of elements to examine + * @param last the end of the range of elements to examine + * @param f function object, to be applied to the result of dereferencing every iterator in the range + * @return std::invoke_result_t> + */ +template +constexpr std::invoke_result_t> get_first_of(InputIt first, InputIt last, + UnaryFunction f) +{ + for (; first != last; ++first) + if (auto opt = f(*first)) return *opt; + return {}; +} + +template +constexpr auto get_first_of(const Rng& rng, UnaryFunction f) +{ + using std::begin, std::end; + return get_first_of(begin(rng), end(rng), f); +} + +// TODO remove all the below and use std when moved to modules template constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) { @@ -38,17 +70,6 @@ constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) return true; } -template -constexpr InputIt find_if(InputIt first, InputIt last, UnaryPredicate p) -{ - for (; first != last; ++first) { - if (p(*first)) { - return first; - } - } - return last; -} - template constexpr auto lexicographical_compare_three_way(I1 f1, I1 l1, I2 f2, I2 l2, Cmp comp) -> decltype(comp(*f1, *f2)) { diff --git a/src/core/include/units/bits/external/fixed_string.h b/src/core/include/units/bits/external/fixed_string.h index 732a30c7..25a7369a 100644 --- a/src/core/include/units/bits/external/fixed_string.h +++ b/src/core/include/units/bits/external/fixed_string.h @@ -24,7 +24,7 @@ #include // IWYU pragma: keep // TODO use when moved to C++20 modules (parsing takes too long for each translation unit) -#include +#include // IWYU pragma: begin_exports #include diff --git a/src/core/include/units/bits/prime.h b/src/core/include/units/bits/prime.h index eb77e503..49b74a10 100644 --- a/src/core/include/units/bits/prime.h +++ b/src/core/include/units/bits/prime.h @@ -22,6 +22,7 @@ #pragma once +#include #include #include #include @@ -55,23 +56,6 @@ constexpr std::optional first_factor_maybe(std::size_t n, std::size return std::nullopt; } -// TODO refactor two below functions with std::ranges when moved to modules -template -constexpr std::optional first_factor_maybe(InputIt first, InputIt last, std::size_t n, - std::size_t offset = 0) -{ - for (; first != last; ++first) - if (const auto k = first_factor_maybe(n, *first + offset)) return *k; - return {}; -} - -template -constexpr std::optional first_factor_maybe(const Rng& rng, std::size_t n, std::size_t offset = 0) -{ - using std::begin, std::end; - return first_factor_maybe(begin(rng), end(rng), n, offset); -} - template constexpr std::array first_n_primes() { @@ -153,11 +137,16 @@ struct wheel_factorizer { static constexpr std::size_t find_first_factor(std::size_t n) { - if (const auto k = first_factor_maybe(basis, n)) return *k; - if (const auto k = first_factor_maybe(std::next(begin(coprimes_in_first_wheel)), end(coprimes_in_first_wheel), n)) + if (const auto k = detail::get_first_of(basis, [&](auto p) { return first_factor_maybe(n, p); })) return *k; + + if (const auto k = detail::get_first_of(std::next(begin(coprimes_in_first_wheel)), end(coprimes_in_first_wheel), + [&](auto p) { return first_factor_maybe(n, p); })) return *k; + for (std::size_t wheel = wheel_size; wheel < n; wheel += wheel_size) - if (const auto k = first_factor_maybe(coprimes_in_first_wheel, n, wheel)) return *k; + if (const auto k = + detail::get_first_of(coprimes_in_first_wheel, [&](auto p) { return first_factor_maybe(n, wheel + p); })) + return *k; return n; }