fix: clang compilation workarounds added for magnitudes

This commit is contained in:
Mateusz Pusz
2023-08-24 19:21:17 +02:00
parent 9f1a42bc7f
commit 1bc6fdece9

View File

@@ -107,7 +107,7 @@ concept Magnitude = detail::is_magnitude<T>;
/** /**
* @brief A basis vector in our magnitude representation, raised to some rational power. * @brief A basis vector in our magnitude representation, raised to some rational power.
* *
* The public API is that there is a `power` member variable (of type `ratio`), and a `get_base()` member function (of * The public API is that there is a `power` member variable (of type `ratio`), and a `get_base_value()` member function (of
* type either `std::intmax_t` or `long double`, as appropriate), for any specialization. * type either `std::intmax_t` or `long double`, as appropriate), for any specialization.
* *
* These types exist to be used as NTTPs for the variadic `magnitude<...>` template. We represent a magnitude (which is * These types exist to be used as NTTPs for the variadic `magnitude<...>` template. We represent a magnitude (which is
@@ -185,6 +185,14 @@ template<MagnitudeSpec Element>
[[nodiscard]] consteval auto get_base(Element element) [[nodiscard]] consteval auto get_base(Element element)
{ {
if constexpr (detail::is_specialization_of_power_v<Element>) return Element::base; if constexpr (detail::is_specialization_of_power_v<Element>) return Element::base;
else
return element;
}
template<MagnitudeSpec Element>
[[nodiscard]] consteval auto get_base_value(Element element)
{
if constexpr (detail::is_specialization_of_power_v<Element>) return get_base_value(Element::base);
#if MP_UNITS_COMP_CLANG #if MP_UNITS_COMP_CLANG
else if constexpr (is_specialization_of<Element, mag_value>) else if constexpr (is_specialization_of<Element, mag_value>)
return element.value; return element.value;
@@ -234,15 +242,13 @@ template<auto V>
template<PowerVBase auto V, ratio R> template<PowerVBase auto V, ratio R>
[[nodiscard]] consteval auto power_v_or_T() [[nodiscard]] consteval auto power_v_or_T()
{ {
constexpr auto shortT = shorten_T<V>();
if constexpr (R.den == 1) { if constexpr (R.den == 1) {
if constexpr (R.num == 1) if constexpr (R.num == 1)
return shortT; return shorten_T<V>();
else else
return power_v<shortT, R.num>{}; return power_v<shorten_T<V>(), R.num>{};
} else { } else {
return power_v<shortT, R.num, R.den>{}; return power_v<shorten_T<V>(), R.num, R.den>{};
} }
} }
@@ -319,7 +325,7 @@ template<typename T>
} }
auto power = exp.num; auto power = exp.num;
return int_power(static_cast<widen_t<T>>(get_base(el)), power); return int_power(static_cast<widen_t<T>>(get_base_value(el)), power);
} }
// A converter for the value member variable of magnitude (below). // A converter for the value member variable of magnitude (below).
@@ -382,13 +388,13 @@ namespace detail {
// if (get_exponent(element) == 0) { // if (get_exponent(element) == 0) {
// return false; // return false;
// } // }
// if constexpr (std::integral<decltype(get_base(element))>) { // if constexpr (std::integral<decltype(get_base_value(element))>) {
// // Some prime numbers are so big, that we can't check their primality without exhausting limits on constexpr // // Some prime numbers are so big, that we can't check their primality without exhausting limits on constexpr
// steps // steps
// // and/or iterations. We can still _perform_ the factorization for these by using the `known_first_factor` // // and/or iterations. We can still _perform_ the factorization for these by using the `known_first_factor`
// // workaround. However, we can't _check_ that they are prime, because this workaround depends on the input being // // workaround. However, we can't _check_ that they are prime, because this workaround depends on the input being
// // usable in a constexpr expression. This is true for `prime_factorization` (below), where the input `N` is a // // usable in a constexpr expression. This is true for `prime_factorization` (below), where the input `N` is a
// // template parameter, but is not true for our case, where the input `bp.get_base()` is a function parameter. // // template parameter, but is not true for our case, where the input `bp.get_base_value()` is a function parameter.
// (See // (See
// // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1045r1.html for some background reading on this // // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1045r1.html for some background reading on this
// // distinction.) // // distinction.)
@@ -575,13 +581,13 @@ namespace detail {
consteval bool less(MagnitudeSpec auto lhs, MagnitudeSpec auto rhs) consteval bool less(MagnitudeSpec auto lhs, MagnitudeSpec auto rhs)
{ {
using lhs_base_t = decltype(get_base(lhs)); using lhs_base_t = decltype(get_base_value(lhs));
using rhs_base_t = decltype(get_base(rhs)); using rhs_base_t = decltype(get_base_value(rhs));
if constexpr (is_named_magnitude<lhs_base_t> && is_named_magnitude<rhs_base_t>) if constexpr (is_named_magnitude<lhs_base_t> && is_named_magnitude<rhs_base_t>)
return type_name<lhs_base_t>() < type_name<rhs_base_t>(); return type_name<lhs_base_t>() < type_name<rhs_base_t>();
else if constexpr (!is_named_magnitude<lhs_base_t> && !is_named_magnitude<rhs_base_t>) else if constexpr (!is_named_magnitude<lhs_base_t> && !is_named_magnitude<rhs_base_t>)
return get_base(lhs) < get_base(rhs); return get_base_value(lhs) < get_base_value(rhs);
else else
return is_named_magnitude<lhs_base_t>; return is_named_magnitude<lhs_base_t>;
} }
@@ -731,10 +737,10 @@ template<auto H1, auto... T1, auto H2, auto... T2>
{ {
using detail::remove_positive_power; using detail::remove_positive_power;
if constexpr (detail::get_base(H1) < detail::get_base(H2)) { if constexpr (detail::get_base_value(H1) < detail::get_base_value(H2)) {
// When H1 has the smaller base, prepend to result from recursion. // When H1 has the smaller base, prepend to result from recursion.
return remove_positive_power(magnitude<H1>{}) * common_magnitude(magnitude<T1...>{}, magnitude<H2, T2...>{}); return remove_positive_power(magnitude<H1>{}) * common_magnitude(magnitude<T1...>{}, magnitude<H2, T2...>{});
} else if constexpr (detail::get_base(H2) < detail::get_base(H1)) { } else if constexpr (detail::get_base_value(H2) < detail::get_base_value(H1)) {
// When H2 has the smaller base, prepend to result from recursion. // When H2 has the smaller base, prepend to result from recursion.
return remove_positive_power(magnitude<H2>{}) * common_magnitude(magnitude<H1, T1...>{}, magnitude<T2...>{}); return remove_positive_power(magnitude<H2>{}) * common_magnitude(magnitude<H1, T1...>{}, magnitude<T2...>{});
} else { } else {
@@ -751,7 +757,7 @@ template<auto H1, auto... T1, auto H2, auto... T2>
template<auto... Ms> template<auto... Ms>
[[nodiscard]] consteval auto common_magnitude_type_impl(magnitude<Ms...>) [[nodiscard]] consteval auto common_magnitude_type_impl(magnitude<Ms...>)
{ {
return (... * decltype(get_base(Ms)){}) * std::intmax_t{}; return (... * decltype(get_base_value(Ms)){}) * std::intmax_t{};
} }
// Returns the most precise type to express the magnitude factor // Returns the most precise type to express the magnitude factor
@@ -828,7 +834,7 @@ namespace detail {
template<typename T, auto... Ms> template<typename T, auto... Ms>
[[nodiscard]] consteval ratio get_power(T base, magnitude<Ms...>) [[nodiscard]] consteval ratio get_power(T base, magnitude<Ms...>)
{ {
return ((get_base(Ms) == base ? get_exponent(Ms) : ratio{0}) + ... + ratio{0}); return ((get_base_value(Ms) == base ? get_exponent(Ms) : ratio{0}) + ... + ratio{0});
} }
[[nodiscard]] consteval std::intmax_t integer_part(ratio r) { return r.num / r.den; } [[nodiscard]] consteval std::intmax_t integer_part(ratio r) { return r.num / r.den; }