mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-09 23:24:27 +02:00
refactor: expression template operations now take function parameters
This commit is contained in:
@@ -250,17 +250,17 @@ struct expr_simplify<type_list<power<T, Ints1...>, NRest...>, type_list<power<T,
|
|||||||
|
|
||||||
|
|
||||||
// expr_less
|
// expr_less
|
||||||
template<typename T1, typename T2, template<typename, typename> typename Pred>
|
template<typename Lhs, typename Rhs, template<typename, typename> typename Pred>
|
||||||
struct expr_less_impl : Pred<T1, T2> {};
|
struct expr_less_impl : Pred<Lhs, Rhs> {};
|
||||||
|
|
||||||
template<typename T1, int... Ints1, typename T2, int... Ints2, template<typename, typename> typename Pred>
|
template<typename Lhs, int... Ints1, typename Rhs, int... Ints2, template<typename, typename> typename Pred>
|
||||||
struct expr_less_impl<power<T1, Ints1...>, power<T2, Ints2...>, Pred> : Pred<T1, T2> {};
|
struct expr_less_impl<power<Lhs, Ints1...>, power<Rhs, Ints2...>, Pred> : Pred<Lhs, Rhs> {};
|
||||||
|
|
||||||
template<typename T1, int... Ints, typename T2, template<typename, typename> typename Pred>
|
template<typename Lhs, int... Ints, typename Rhs, template<typename, typename> typename Pred>
|
||||||
struct expr_less_impl<power<T1, Ints...>, T2, Pred> : Pred<T1, T2> {};
|
struct expr_less_impl<power<Lhs, Ints...>, Rhs, Pred> : Pred<Lhs, Rhs> {};
|
||||||
|
|
||||||
template<typename T1, typename T2, int... Ints, template<typename, typename> typename Pred>
|
template<typename Lhs, typename Rhs, int... Ints, template<typename, typename> typename Pred>
|
||||||
struct expr_less_impl<T1, power<T2, Ints...>, Pred> : Pred<T1, T2> {};
|
struct expr_less_impl<Lhs, power<Rhs, Ints...>, Pred> : Pred<Lhs, Rhs> {};
|
||||||
|
|
||||||
template<typename T, int... Ints, template<typename, typename> typename Pred>
|
template<typename T, int... Ints, template<typename, typename> typename Pred>
|
||||||
struct expr_less_impl<T, power<T, Ints...>, Pred> : std::true_type {};
|
struct expr_less_impl<T, power<T, Ints...>, Pred> : std::true_type {};
|
||||||
@@ -271,8 +271,8 @@ struct expr_less_impl<T, power<T, Ints...>, Pred> : std::true_type {};
|
|||||||
* Algorithm accounts not only for explicit types but also for the case when they
|
* Algorithm accounts not only for explicit types but also for the case when they
|
||||||
* are wrapped within `power<T, Num, Den>`.
|
* are wrapped within `power<T, Num, Den>`.
|
||||||
*/
|
*/
|
||||||
template<typename T1, typename T2, template<typename, typename> typename Pred>
|
template<typename Lhs, typename Rhs, template<typename, typename> typename Pred>
|
||||||
using expr_less = expr_less_impl<T1, T2, Pred>;
|
using expr_less = expr_less_impl<Lhs, Rhs, Pred>;
|
||||||
|
|
||||||
|
|
||||||
// expr_fractions
|
// expr_fractions
|
||||||
@@ -355,34 +355,34 @@ template<typename NumList, typename DenList, typename OneType, template<typename
|
|||||||
/**
|
/**
|
||||||
* @brief Multiplies two sorted expression template specs
|
* @brief Multiplies two sorted expression template specs
|
||||||
*
|
*
|
||||||
* @tparam T1 lhs of the operation
|
* @tparam To destination type list to put the result to
|
||||||
* @tparam T2 rhs of the operation
|
|
||||||
* @tparam OneType type that represents the value `1`
|
* @tparam OneType type that represents the value `1`
|
||||||
* @tparam Pred binary less then predicate
|
* @tparam Pred binary less then predicate
|
||||||
* @tparam To destination type list to put the result to
|
* @tparam Lhs lhs of the operation
|
||||||
|
* @tparam Rhs rhs of the operation
|
||||||
*/
|
*/
|
||||||
template<typename T1, typename T2, typename OneType, template<typename, typename> typename Pred,
|
template<template<typename...> typename To, typename OneType, template<typename, typename> typename Pred, typename Lhs,
|
||||||
template<typename...> typename To>
|
typename Rhs>
|
||||||
[[nodiscard]] consteval auto expr_multiply()
|
[[nodiscard]] consteval auto expr_multiply(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<T1, OneType>) {
|
if constexpr (is_same_v<Lhs, OneType>) {
|
||||||
return T2{};
|
return Rhs{};
|
||||||
} else if constexpr (is_same_v<T2, OneType>) {
|
} else if constexpr (is_same_v<Rhs, OneType>) {
|
||||||
return T1{};
|
return Lhs{};
|
||||||
} else if constexpr (is_specialization_of<T1, To> && is_specialization_of<T2, To>) {
|
} else if constexpr (is_specialization_of<Lhs, To> && is_specialization_of<Rhs, To>) {
|
||||||
// two derived dimensions
|
// two derived dimensions
|
||||||
return get_optimized_expression<type_list_merge_sorted<typename T1::_num_, typename T2::_num_, Pred>,
|
return get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, typename Rhs::_num_, Pred>,
|
||||||
type_list_merge_sorted<typename T1::_den_, typename T2::_den_, Pred>, OneType, Pred,
|
type_list_merge_sorted<typename Lhs::_den_, typename Rhs::_den_, Pred>, OneType,
|
||||||
To>();
|
Pred, To>();
|
||||||
} else if constexpr (is_specialization_of<T1, To>) {
|
} else if constexpr (is_specialization_of<Lhs, To>) {
|
||||||
return get_optimized_expression<type_list_merge_sorted<typename T1::_num_, type_list<T2>, Pred>, typename T1::_den_,
|
return get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, type_list<Rhs>, Pred>,
|
||||||
OneType, Pred, To>();
|
typename Lhs::_den_, OneType, Pred, To>();
|
||||||
} else if constexpr (is_specialization_of<T2, To>) {
|
} else if constexpr (is_specialization_of<Rhs, To>) {
|
||||||
return get_optimized_expression<type_list_merge_sorted<typename T2::_num_, type_list<T1>, Pred>, typename T2::_den_,
|
return get_optimized_expression<type_list_merge_sorted<typename Rhs::_num_, type_list<Lhs>, Pred>,
|
||||||
OneType, Pred, To>();
|
typename Rhs::_den_, OneType, Pred, To>();
|
||||||
} else {
|
} else {
|
||||||
// two base dimensions
|
// two base dimensions
|
||||||
return get_optimized_expression<type_list_merge_sorted<type_list<T1>, type_list<T2>, Pred>, type_list<>, OneType,
|
return get_optimized_expression<type_list_merge_sorted<type_list<Lhs>, type_list<Rhs>, Pred>, type_list<>, OneType,
|
||||||
Pred, To>();
|
Pred, To>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,34 +390,34 @@ template<typename T1, typename T2, typename OneType, template<typename, typename
|
|||||||
/**
|
/**
|
||||||
* @brief Divides two sorted expression template specs
|
* @brief Divides two sorted expression template specs
|
||||||
*
|
*
|
||||||
* @tparam T1 lhs of the operation
|
* @tparam To destination type list to put the result to
|
||||||
* @tparam T2 rhs of the operation
|
|
||||||
* @tparam OneType type that represents the value `1`
|
* @tparam OneType type that represents the value `1`
|
||||||
* @tparam Pred binary less then predicate
|
* @tparam Pred binary less then predicate
|
||||||
* @tparam To destination type list to put the result to
|
* @tparam Lhs lhs of the operation
|
||||||
|
* @tparam Rhs rhs of the operation
|
||||||
*/
|
*/
|
||||||
template<typename T1, typename T2, typename OneType, template<typename, typename> typename Pred,
|
template<template<typename...> typename To, typename OneType, template<typename, typename> typename Pred, typename Lhs,
|
||||||
template<typename...> typename To>
|
typename Rhs>
|
||||||
[[nodiscard]] consteval auto expr_divide()
|
[[nodiscard]] consteval auto expr_divide(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<T1, T2>) {
|
if constexpr (is_same_v<Lhs, Rhs>) {
|
||||||
return OneType{};
|
return OneType{};
|
||||||
} else if constexpr (is_same_v<T2, OneType>) {
|
} else if constexpr (is_same_v<Rhs, OneType>) {
|
||||||
return T1{};
|
return Lhs{};
|
||||||
} else if constexpr (is_specialization_of<T1, To> && is_specialization_of<T2, To>) {
|
} else if constexpr (is_specialization_of<Lhs, To> && is_specialization_of<Rhs, To>) {
|
||||||
// two derived dimensions
|
// two derived dimensions
|
||||||
return get_optimized_expression<type_list_merge_sorted<typename T1::_num_, typename T2::_den_, Pred>,
|
return get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, typename Rhs::_den_, Pred>,
|
||||||
type_list_merge_sorted<typename T1::_den_, typename T2::_num_, Pred>, OneType, Pred,
|
type_list_merge_sorted<typename Lhs::_den_, typename Rhs::_num_, Pred>, OneType,
|
||||||
To>();
|
Pred, To>();
|
||||||
} else if constexpr (is_specialization_of<T1, To>) {
|
} else if constexpr (is_specialization_of<Lhs, To>) {
|
||||||
return get_optimized_expression<typename T1::_num_, type_list_merge_sorted<typename T1::_den_, type_list<T2>, Pred>,
|
return get_optimized_expression<
|
||||||
OneType, Pred, To>();
|
typename Lhs::_num_, type_list_merge_sorted<typename Lhs::_den_, type_list<Rhs>, Pred>, OneType, Pred, To>();
|
||||||
} else if constexpr (is_specialization_of<T2, To>) {
|
} else if constexpr (is_specialization_of<Rhs, To>) {
|
||||||
return get_optimized_expression<type_list_merge_sorted<typename T2::_den_, type_list<T1>, Pred>, typename T2::_num_,
|
return get_optimized_expression<type_list_merge_sorted<typename Rhs::_den_, type_list<Lhs>, Pred>,
|
||||||
OneType, Pred, To>();
|
typename Rhs::_num_, OneType, Pred, To>();
|
||||||
} else {
|
} else {
|
||||||
// two base dimensions
|
// two base dimensions
|
||||||
return To<T1, per<T2>>{};
|
return To<Lhs, per<Rhs>>{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,8 +428,8 @@ template<typename T1, typename T2, typename OneType, template<typename, typename
|
|||||||
* @tparam OneType type that represents the value `1`
|
* @tparam OneType type that represents the value `1`
|
||||||
* @tparam To destination type list to put the result to
|
* @tparam To destination type list to put the result to
|
||||||
*/
|
*/
|
||||||
template<typename T, typename OneType, template<typename...> typename To>
|
template<template<typename...> typename To, typename OneType, typename T>
|
||||||
[[nodiscard]] consteval auto expr_invert()
|
[[nodiscard]] consteval auto expr_invert(T)
|
||||||
{
|
{
|
||||||
if constexpr (is_specialization_of<T, To>)
|
if constexpr (is_specialization_of<T, To>)
|
||||||
return expr_make_spec<typename T::_den_, typename T::_num_, OneType, To>{};
|
return expr_make_spec<typename T::_den_, typename T::_num_, OneType, To>{};
|
||||||
|
@@ -109,8 +109,8 @@ concept Dimension = BaseDimension<T> || DerivedDimension<T>;
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<BaseDimension D1, BaseDimension D2>
|
template<BaseDimension Lhs, BaseDimension Rhs>
|
||||||
struct base_dimension_less : std::bool_constant<(D1::symbol < D2::symbol)> {};
|
struct base_dimension_less : std::bool_constant<(Lhs::symbol < Rhs::symbol)> {};
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
using type_list_of_base_dimension_less = expr_less<T1, T2, base_dimension_less>;
|
using type_list_of_base_dimension_less = expr_less<T1, T2, base_dimension_less>;
|
||||||
@@ -249,34 +249,34 @@ using dim_type = dim_type_impl<T>::type;
|
|||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension Lhs, Dimension Rhs>
|
||||||
[[nodiscard]] consteval Dimension auto operator*(D1, D2)
|
[[nodiscard]] consteval Dimension auto operator*(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
return detail::expr_multiply<detail::dim_type<D1>, detail::dim_type<D2>, struct one_dim,
|
return detail::expr_multiply<derived_dimension, struct one_dim, detail::type_list_of_base_dimension_less>(
|
||||||
detail::type_list_of_base_dimension_less, derived_dimension>();
|
detail::dim_type<Lhs>{}, detail::dim_type<Rhs>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension Lhs, Dimension Rhs>
|
||||||
[[nodiscard]] consteval Dimension auto operator/(D1, D2)
|
[[nodiscard]] consteval Dimension auto operator/(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
return detail::expr_divide<detail::dim_type<D1>, detail::dim_type<D2>, struct one_dim,
|
return detail::expr_divide<derived_dimension, struct one_dim, detail::type_list_of_base_dimension_less>(
|
||||||
detail::type_list_of_base_dimension_less, derived_dimension>();
|
detail::dim_type<Lhs>{}, detail::dim_type<Rhs>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Dimension D>
|
template<Dimension D>
|
||||||
[[nodiscard]] consteval Dimension auto operator/(int value, D)
|
[[nodiscard]] consteval Dimension auto operator/(int value, D)
|
||||||
{
|
{
|
||||||
gsl_Assert(value == 1);
|
gsl_Assert(value == 1);
|
||||||
return detail::expr_invert<detail::dim_type<D>, struct one_dim, derived_dimension>();
|
return detail::expr_invert<derived_dimension, struct one_dim>(detail::dim_type<D>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Dimension D>
|
template<Dimension D>
|
||||||
[[nodiscard]] consteval Dimension auto operator/(D, int) = delete;
|
[[nodiscard]] consteval Dimension auto operator/(D, int) = delete;
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension Lhs, Dimension Rhs>
|
||||||
[[nodiscard]] consteval bool operator==(D1, D2)
|
[[nodiscard]] consteval bool operator==(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
return is_same_v<D1, D2>;
|
return is_same_v<Lhs, Rhs>;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
|
Reference in New Issue
Block a user