feat: power<Num, Den>() support added for dimensions and units

This commit is contained in:
Mateusz Pusz committed 2022-10-23 10:47:12 +02:00
1 parent 9bfe75ebf6
commit e7bebac2a7
5 files changed
+124 -6

No files matched your search

@@ -112,13 +112,17 @@ inline constexpr bool is_specialization_of_power<power<F, Ints...>> = true;
template<typename T, ratio R>
consteval auto power_or_T_impl()
{
if constexpr (R.den == 1) {
if constexpr (R.num == 1)
return T{};
else
return power<T, R.num>{};
if constexpr (is_specialization_of_power<T>) {
return power_or_T_impl<typename T::factor, T::exponent * R>();
} else {
return power<T, R.num, R.den>{};
if constexpr (R.den == 1) {
if constexpr (R.num == 1)
return T{};
else
return power<T, R.num>{};
} else {
return power<T, R.num, R.den>{};
}
}
};
@@ -437,6 +441,32 @@ template<template<typename...> typename To, typename OneType, typename T>
return To<OneType, per<T>>{};
}
template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To, typename OneType,
template<typename, typename> typename Pred, typename... Nums, typename... Dens>
requires detail::non_zero<Den>
[[nodiscard]] consteval auto expr_pow_impl(type_list<Nums...>, type_list<Dens...>)
{
return detail::get_optimized_expression<type_list<power_or_T<Nums, ratio{Num, Den}>...>,
type_list<power_or_T<Dens, ratio{Num, Den}>...>, OneType, Pred, To>();
}
/**
* @brief Computes the value of an expression raised to the `Num/Den` power
*
* @tparam Num Exponent numerator
* @tparam Den Exponent denominator
* @tparam T Expression being the base of the operation
*/
template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To, typename OneType,
template<typename, typename> typename Pred, typename T>
requires detail::non_zero<Den>
[[nodiscard]] consteval auto expr_pow(T)
{
return expr_pow_impl<Num, Den, To, OneType, Pred>(typename T::_num_{}, typename T::_den_{});
}
} // namespace detail
} // namespace units
+22
View File
@@ -285,6 +285,28 @@ template<Dimension D1, Dimension D2>
return std::derived_from<D1, D2> || std::derived_from<D2, D1>;
}
/**
* @brief Computes the value of a dimension raised to the `Num/Den` power
*
* @tparam Num Exponent numerator
* @tparam Den Exponent denominator
* @param d Dimension being the base of the operation
*
* @return Dimension The result of computation
*/
template<std::intmax_t Num, std::intmax_t Den = 1, Dimension D>
requires detail::non_zero<Den>
[[nodiscard]] consteval Dimension auto pow(D d)
{
if constexpr (BaseDimension<D>) {
if constexpr (Den == 1)
return derived_dimension<power<D, Num>>{};
else
return derived_dimension<power<D, Num, Den>>{};
} else
return detail::expr_pow<Num, Den, derived_dimension, struct one_dim, detail::type_list_of_base_dimension_less>(d);
}
// TODO consider adding the support for text output of the dimensional equation
} // namespace units
+27
View File
@@ -471,6 +471,33 @@ template<Unit Lhs, Unit Rhs>
return is_same_v<decltype(canonical_lhs.reference_unit), decltype(canonical_rhs.reference_unit)>;
}
/**
* @brief Computes the value of a unit raised to the `Num/Den` power
*
* @tparam Num Exponent numerator
* @tparam Den Exponent denominator
* @param u Unit being the base of the operation
*
* @return Unit The result of computation
*/
template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
requires detail::non_zero<Den>
[[nodiscard]] consteval Unit auto pow(U u)
{
if constexpr (requires { U::symbol; }) {
if constexpr (Den == 1)
return derived_unit<power<U, Num>>{};
else
return derived_unit<power<U, Num, Den>>{};
} else if constexpr (detail::is_specialization_of_scaled_unit<U>) {
return scaled_unit<pow<ratio{Num, Den}>(U::mag), std::remove_const_t<decltype(pow<Num, Den>(U::reference_unit))>>{};
} else {
return detail::expr_pow<Num, Den, derived_unit, struct one, detail::type_list_of_unit_less>(u);
}
}
// Helper variable templates to create common powers
template<Unit auto U>
inline constexpr decltype(U * U) square;