forked from mpusz/mp-units
Factor out logic into pairwise_all()
helper
We could move this somewhere more generic if we want.
This commit is contained in:
@@ -186,20 +186,25 @@ struct is_base_power<base_power<B, E>>
|
||||
template<typename T>
|
||||
struct is_magnitude: std::false_type {};
|
||||
|
||||
// Check whether a tuple of (possibly heterogeneously typed) values are strictly increasing.
|
||||
template<typename... Ts>
|
||||
constexpr bool strictly_increasing(const std::tuple<Ts...> &ts) {
|
||||
template<typename Predicate, typename... Ts>
|
||||
constexpr bool pairwise_all(const std::tuple<Ts...> &ts, const Predicate &pred) {
|
||||
// Carefully handle different sizes, avoiding unsigned integer underflow.
|
||||
constexpr auto num_comparisons = [](auto num_elements) {
|
||||
return (num_elements > 1) ? (num_elements - 1) : 0;
|
||||
}(sizeof...(Ts));
|
||||
|
||||
// Compare zero or more pairs of neighbours as needed.
|
||||
return [&ts]<std::size_t... Is>(std::integer_sequence<std::size_t, Is...>) {
|
||||
return ((std::get<Is>(ts) < std::get<Is + 1>(ts)) && ...);
|
||||
return [&ts, &pred]<std::size_t... Is>(std::integer_sequence<std::size_t, Is...>) {
|
||||
return (pred(std::get<Is>(ts), std::get<Is + 1>(ts)) && ...);
|
||||
}(std::make_index_sequence<num_comparisons>());
|
||||
}
|
||||
|
||||
// Check whether a tuple of (possibly heterogeneously typed) values are strictly increasing.
|
||||
template<typename... Ts>
|
||||
constexpr bool strictly_increasing(const std::tuple<Ts...> &ts) {
|
||||
return pairwise_all(ts, std::less{});
|
||||
}
|
||||
|
||||
// To be a valid magnitude, one must be a magnitude<...> of BasePowers with nonzero exponents, sorted by increasing base
|
||||
// value.
|
||||
template<BasePower... Bs>
|
||||
|
@@ -374,6 +374,30 @@ TEST_CASE("is_prime detects primes")
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("pairwise_all evaluates all pairs")
|
||||
{
|
||||
SECTION("always true for empty tuples")
|
||||
{
|
||||
CHECK(pairwise_all(std::make_tuple(), [](auto a, auto b){ return true; }));
|
||||
CHECK(pairwise_all(std::make_tuple(), [](auto a, auto b){ return false; }));
|
||||
}
|
||||
|
||||
SECTION("always true for single-element tuples")
|
||||
{
|
||||
CHECK(pairwise_all(std::make_tuple(1), [](auto a, auto b){ return true; }));
|
||||
CHECK(pairwise_all(std::make_tuple(3.14), [](auto a, auto b){ return false; }));
|
||||
CHECK(pairwise_all(std::make_tuple('x'), [](auto a, auto b){ return true; }));
|
||||
}
|
||||
|
||||
SECTION("true for longer tuples iff true for all neighbouring pairs")
|
||||
{
|
||||
CHECK(pairwise_all(std::make_tuple(1, 1.5), std::less{}));
|
||||
CHECK(pairwise_all(std::make_tuple(1, 1.5, 2), std::less{}));
|
||||
CHECK(!pairwise_all(std::make_tuple(1, 2.0, 2), std::less{}));
|
||||
CHECK(!pairwise_all(std::make_tuple(1, 2.5, 2), std::less{}));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace units::mag
|
||||
|
Reference in New Issue
Block a user