refactor: compile-time performance optimizations for expression templates

This commit is contained in:
Mateusz Pusz
2024-06-12 14:18:51 +02:00
parent 18b16c51a0
commit ba0ba44dd9

View File

@@ -362,7 +362,7 @@ template<typename NumList, typename DenList, typename OneType, template<typename
using simple = expr_simplify<num_list, den_list, Pred>; using simple = expr_simplify<num_list, den_list, Pred>;
// the usage of `std::identity` below helps to resolve an using alias identifier to the actual // the usage of `std::identity` below helps to resolve an using alias identifier to the actual
// type identifier in the clang compile-time errors // type identifier in the clang compile-time errors
return std::identity{}(expr_make_spec_impl<typename simple::num, typename simple::den, OneType, To>()); return std::identity{}(decltype(expr_make_spec_impl<typename simple::num, typename simple::den, OneType, To>()){});
} }
/** /**
@@ -384,19 +384,19 @@ template<template<typename...> typename To, typename OneType, template<typename,
return Lhs{}; return Lhs{};
} else if constexpr (is_specialization_of<Lhs, To> && is_specialization_of<Rhs, 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 Lhs::_num_, typename Rhs::_num_, Pred>, return decltype(get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, typename Rhs::_num_, Pred>,
type_list_merge_sorted<typename Lhs::_den_, typename Rhs::_den_, Pred>, OneType, type_list_merge_sorted<typename Lhs::_den_, typename Rhs::_den_, Pred>,
Pred, To>(); OneType, Pred, To>()){};
} else if constexpr (is_specialization_of<Lhs, To>) { } else if constexpr (is_specialization_of<Lhs, To>) {
return get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, type_list<Rhs>, Pred>, return decltype(get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, type_list<Rhs>, Pred>,
typename Lhs::_den_, OneType, Pred, To>(); typename Lhs::_den_, OneType, Pred, To>()){};
} else if constexpr (is_specialization_of<Rhs, To>) { } else if constexpr (is_specialization_of<Rhs, To>) {
return get_optimized_expression<type_list_merge_sorted<typename Rhs::_num_, type_list<Lhs>, Pred>, return decltype(get_optimized_expression<type_list_merge_sorted<typename Rhs::_num_, type_list<Lhs>, Pred>,
typename Rhs::_den_, 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<Lhs>, type_list<Rhs>, Pred>, type_list<>, OneType, return decltype(get_optimized_expression<type_list_merge_sorted<type_list<Lhs>, type_list<Rhs>, Pred>, type_list<>,
Pred, To>(); OneType, Pred, To>()){};
} }
} }
@@ -418,18 +418,19 @@ template<template<typename...> typename To, typename OneType, template<typename,
} else if constexpr (is_same_v<Rhs, OneType>) { } else if constexpr (is_same_v<Rhs, OneType>) {
return lhs; return lhs;
} else if constexpr (is_same_v<Lhs, OneType>) { } else if constexpr (is_same_v<Lhs, OneType>) {
return expr_divide<To, OneType, Pred>(To<>{}, rhs); return decltype(expr_divide<To, OneType, Pred>(To<>{}, rhs)){};
} else if constexpr (is_specialization_of<Lhs, To> && is_specialization_of<Rhs, To>) { } else if constexpr (is_specialization_of<Lhs, To> && is_specialization_of<Rhs, To>) {
// two derived entities // two derived entities
return get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, typename Rhs::_den_, Pred>, return decltype(get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, typename Rhs::_den_, Pred>,
type_list_merge_sorted<typename Lhs::_den_, typename Rhs::_num_, Pred>, OneType, type_list_merge_sorted<typename Lhs::_den_, typename Rhs::_num_, Pred>,
Pred, To>(); OneType, Pred, To>()){};
} else if constexpr (is_specialization_of<Lhs, To>) { } else if constexpr (is_specialization_of<Lhs, To>) {
return get_optimized_expression< return decltype(get_optimized_expression<typename Lhs::_num_,
typename Lhs::_num_, type_list_merge_sorted<typename Lhs::_den_, type_list<Rhs>, Pred>, OneType, Pred, To>(); type_list_merge_sorted<typename Lhs::_den_, type_list<Rhs>, Pred>, OneType,
Pred, To>()){};
} else if constexpr (is_specialization_of<Rhs, To>) { } else if constexpr (is_specialization_of<Rhs, To>) {
return get_optimized_expression<type_list_merge_sorted<typename Rhs::_den_, type_list<Lhs>, Pred>, return decltype(get_optimized_expression<type_list_merge_sorted<typename Rhs::_den_, type_list<Lhs>, Pred>,
typename Rhs::_num_, OneType, Pred, To>(); typename Rhs::_num_, OneType, Pred, To>()){};
} else { } else {
// two named entities // two named entities
return To<Lhs, per<Rhs>>{}; return To<Lhs, per<Rhs>>{};
@@ -449,7 +450,7 @@ template<template<typename...> typename To, typename OneType, typename T>
if constexpr (is_specialization_of<T, To>) if constexpr (is_specialization_of<T, To>)
// the usage of `std::identity` below helps to resolve an using alias identifier to the actual // the usage of `std::identity` below helps to resolve an using alias identifier to the actual
// type identifier in the clang compile-time errors // type identifier in the clang compile-time errors
return std::identity{}(expr_make_spec_impl<typename T::_den_, typename T::_num_, OneType, To>()); return std::identity{}(decltype(expr_make_spec_impl<typename T::_den_, typename T::_num_, OneType, To>()){});
else else
return To<OneType, per<T>>{}; return To<OneType, per<T>>{};
} }
@@ -460,8 +461,9 @@ template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To
requires detail::non_zero<Den> requires detail::non_zero<Den>
[[nodiscard]] consteval auto expr_pow_impl(type_list<Nums...>, type_list<Dens...>) [[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}>...>, return decltype(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>(); type_list<power_or_T<Dens, ratio{Num, Den}>...>, OneType, Pred,
To>()){};
} }
@@ -480,7 +482,7 @@ template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To
requires detail::non_zero<Den> requires detail::non_zero<Den>
[[nodiscard]] consteval auto expr_pow(T) [[nodiscard]] consteval auto expr_pow(T)
{ {
return expr_pow_impl<Num, Den, To, OneType, Pred>(typename T::_num_{}, typename T::_den_{}); return decltype(expr_pow_impl<Num, Den, To, OneType, Pred>(typename T::_num_{}, typename T::_den_{})){};
} }
@@ -527,7 +529,7 @@ template<typename T>
template<typename T, auto... Ints> template<typename T, auto... Ints>
[[nodiscard]] consteval auto map_power(power<T, Ints...>) [[nodiscard]] consteval auto map_power(power<T, Ints...>)
{ {
return pow<Ints...>(T{}); return decltype(pow<Ints...>(T{})){};
} }
template<template<typename> typename Proj, template<typename...> typename To, typename OneType, template<template<typename> typename Proj, template<typename...> typename To, typename OneType,
@@ -555,7 +557,7 @@ template<template<typename> typename Proj, template<typename...> typename To, ty
if constexpr (type_list_size<typename T::_num_> + type_list_size<typename T::_den_> == 0) if constexpr (type_list_size<typename T::_num_> + type_list_size<typename T::_den_> == 0)
return OneType{}; return OneType{};
else else
return expr_map_impl<Proj, To, OneType, Pred>(typename T::_num_{}, typename T::_den_{}); return decltype(expr_map_impl<Proj, To, OneType, Pred>(typename T::_num_{}, typename T::_den_{})){};
} }
} // namespace detail } // namespace detail