fix: pow() fixed for quantity specs and units

This commit is contained in:
Mateusz Pusz
2023-06-13 09:14:01 +03:00
parent 211bd61895
commit de4fefde3f
2 changed files with 23 additions and 11 deletions

View File

@@ -545,9 +545,9 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
// `2 * one * (2 * one)` should compare to `4 * one` // `2 * one * (2 * one)` should compare to `4 * one`
// `2 * rad * (2 * rad)` should compare to `4 * rad^2` // `2 * rad * (2 * rad)` should compare to `4 * rad^2`
// all are dimensionless quantities :-( // all are dimensionless quantities :-(
if constexpr (q == dimensionless) if constexpr (Num == 0 || q == dimensionless)
return q; return dimensionless;
else if constexpr (Num == 1 && Den == 1) else if constexpr (ratio{Num, Den} == 1)
return q; return q;
else if constexpr (detail::IntermediateDerivedQuantitySpec<Q>) else if constexpr (detail::IntermediateDerivedQuantitySpec<Q>)
return detail::clone_kind_of<Q{}>( return detail::clone_kind_of<Q{}>(

View File

@@ -501,6 +501,16 @@ template<typename... Expr1, typename... Expr2>
canonical_lhs.mag == canonical_rhs.mag; canonical_lhs.mag == canonical_rhs.mag;
} }
namespace detail {
template<typename T>
inline constexpr bool is_specialization_of_derived_unit = false;
template<typename... Expr>
inline constexpr bool is_specialization_of_derived_unit<derived_unit<Expr...>> = true;
} // namespace detail
/** /**
* @brief Computes the value of a unit raised to the `Num/Den` power * @brief Computes the value of a unit raised to the `Num/Den` power
* *
@@ -514,16 +524,18 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
requires detail::non_zero<Den> requires detail::non_zero<Den>
[[nodiscard]] consteval Unit auto pow(U u) [[nodiscard]] consteval Unit auto pow(U u)
{ {
if constexpr (requires { U::symbol; }) { if constexpr (Num == 0 || is_same_v<U, struct one>)
if constexpr (Den == 1) return one;
return derived_unit<power<U, Num>>{}; else if constexpr (ratio{Num, Den} == 1)
else return u;
return derived_unit<power<U, Num, Den>>{}; else if constexpr (detail::is_specialization_of_scaled_unit<U>)
} else if constexpr (detail::is_specialization_of_scaled_unit<U>) {
return scaled_unit<pow<Num, Den>(U::mag), std::remove_const_t<decltype(pow<Num, Den>(U::reference_unit))>>{}; return scaled_unit<pow<Num, Den>(U::mag), std::remove_const_t<decltype(pow<Num, Den>(U::reference_unit))>>{};
} else { else if constexpr (detail::is_specialization_of_derived_unit<U>)
return detail::expr_pow<Num, Den, derived_unit, struct one, detail::type_list_of_unit_less>(u); return detail::expr_pow<Num, Den, derived_unit, struct one, detail::type_list_of_unit_less>(u);
} else if constexpr (Den == 1)
return derived_unit<power<U, Num>>{};
else
return derived_unit<power<U, Num, Den>>{};
} }
/** /**