mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-02 11:54:27 +02:00
fix: most of the previous commit reverted (accidentaly too many files with changes were included)
This commit is contained in:
@@ -160,15 +160,15 @@ struct is_dimension_one<struct dimension_one> : std::true_type {};
|
|||||||
MP_UNITS_EXPORT template<Dimension Lhs, Dimension Rhs>
|
MP_UNITS_EXPORT template<Dimension Lhs, Dimension Rhs>
|
||||||
[[nodiscard]] consteval Dimension auto operator*(Lhs, Rhs)
|
[[nodiscard]] consteval Dimension auto operator*(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
return detail::expr_multiply<derived_dimension, struct dimension_one, detail::type_list_of_base_dimension_less, true>(
|
return detail::expr_multiply<derived_dimension, struct dimension_one, detail::type_list_of_base_dimension_less>(
|
||||||
Lhs{}, Rhs{});
|
Lhs{}, Rhs{});
|
||||||
}
|
}
|
||||||
|
|
||||||
MP_UNITS_EXPORT template<Dimension Lhs, Dimension Rhs>
|
MP_UNITS_EXPORT template<Dimension Lhs, Dimension Rhs>
|
||||||
[[nodiscard]] consteval Dimension auto operator/(Lhs, Rhs)
|
[[nodiscard]] consteval Dimension auto operator/(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
return detail::expr_divide<derived_dimension, struct dimension_one, detail::type_list_of_base_dimension_less, true>(
|
return detail::expr_divide<derived_dimension, struct dimension_one, detail::type_list_of_base_dimension_less>(Lhs{},
|
||||||
Lhs{}, Rhs{});
|
Rhs{});
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -213,8 +213,8 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Dimension D>
|
|||||||
else
|
else
|
||||||
return derived_dimension<power<D, Num, Den>>{};
|
return derived_dimension<power<D, Num, Den>>{};
|
||||||
} else
|
} else
|
||||||
return detail::expr_pow<Num, Den, derived_dimension, struct dimension_one, detail::type_list_of_base_dimension_less,
|
return detail::expr_pow<Num, Den, derived_dimension, struct dimension_one,
|
||||||
true>(d);
|
detail::type_list_of_base_dimension_less>(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -235,6 +235,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Dimension D>
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] consteval Dimension auto cbrt(Dimension auto d) { return pow<1, 3>(d); }
|
[[nodiscard]] consteval Dimension auto cbrt(Dimension auto d) { return pow<1, 3>(d); }
|
||||||
|
|
||||||
|
|
||||||
struct dimension_symbol_formatting {
|
struct dimension_symbol_formatting {
|
||||||
text_encoding encoding = text_encoding::default_encoding;
|
text_encoding encoding = text_encoding::default_encoding;
|
||||||
};
|
};
|
||||||
|
@@ -199,6 +199,80 @@ template<typename List>
|
|||||||
using expr_consolidate = MP_UNITS_TYPENAME expr_consolidate_impl<List>::type;
|
using expr_consolidate = MP_UNITS_TYPENAME expr_consolidate_impl<List>::type;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Simplifies the expression template
|
||||||
|
*
|
||||||
|
* Analyzes provided numerator and denominator type lists and simplifies elements with the same type.
|
||||||
|
* If the same power exists in both list, this elements gets omitted. Otherwise, the power of its
|
||||||
|
* exponent gets subtracted according to numerator and denominator elements powers.
|
||||||
|
*
|
||||||
|
* @tparam NumList type list for expression numerator
|
||||||
|
* @tparam DenList type list for expression denominator
|
||||||
|
* @tparam Pred predicate to be used for elements comparisons
|
||||||
|
*/
|
||||||
|
template<typename NumList, typename DenList, template<typename, typename> typename Pred>
|
||||||
|
struct expr_simplify;
|
||||||
|
|
||||||
|
// when one of the lists is empty there is nothing to do
|
||||||
|
template<typename NumList, typename DenList, template<typename, typename> typename Pred>
|
||||||
|
requires(type_list_size<NumList> == 0) || (type_list_size<DenList> == 0)
|
||||||
|
struct expr_simplify<NumList, DenList, Pred> {
|
||||||
|
using num = NumList;
|
||||||
|
using den = DenList;
|
||||||
|
};
|
||||||
|
|
||||||
|
// in case when front elements are different progress to the next element
|
||||||
|
template<typename Num, typename... NRest, typename Den, typename... DRest, template<typename, typename> typename Pred>
|
||||||
|
struct expr_simplify<type_list<Num, NRest...>, type_list<Den, DRest...>, Pred> {
|
||||||
|
using impl = conditional<Pred<Num, Den>::value, expr_simplify<type_list<NRest...>, type_list<Den, DRest...>, Pred>,
|
||||||
|
expr_simplify<type_list<Num, NRest...>, type_list<DRest...>, Pred>>;
|
||||||
|
using num = conditional<Pred<Num, Den>::value, type_list_push_front<typename impl::num, Num>, typename impl::num>;
|
||||||
|
using den = conditional<Pred<Num, Den>::value, typename impl::den, type_list_push_front<typename impl::den, Den>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// in case two elements are of the same power such element gets omitted
|
||||||
|
template<typename T, typename... NRest, typename... DRest, template<typename, typename> typename Pred>
|
||||||
|
struct expr_simplify<type_list<T, NRest...>, type_list<T, DRest...>, Pred> :
|
||||||
|
expr_simplify<type_list<NRest...>, type_list<DRest...>, Pred> {};
|
||||||
|
|
||||||
|
template<typename T, ratio Num, ratio Den>
|
||||||
|
struct expr_simplify_power {
|
||||||
|
static constexpr ratio r = Num - Den;
|
||||||
|
using type = power_or_T<T, ratio{abs(r.num), r.den}>;
|
||||||
|
using num = conditional<(r > 0), type_list<type>, type_list<>>;
|
||||||
|
using den = conditional<(r < 0), type_list<type>, type_list<>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// in case there are different powers for the same element simplify the power
|
||||||
|
template<typename T, typename... NRest, int... Ints, typename... DRest, template<typename, typename> typename Pred>
|
||||||
|
struct expr_simplify<type_list<power<T, Ints...>, NRest...>, type_list<T, DRest...>, Pred> {
|
||||||
|
using impl = expr_simplify<type_list<NRest...>, type_list<DRest...>, Pred>;
|
||||||
|
using type = expr_simplify_power<T, power<T, Ints...>::exponent, ratio{1}>;
|
||||||
|
using num = type_list_join<typename type::num, typename impl::num>;
|
||||||
|
using den = type_list_join<typename type::den, typename impl::den>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// in case there are different powers for the same element simplify the power
|
||||||
|
template<typename T, typename... NRest, typename... DRest, int... Ints, template<typename, typename> typename Pred>
|
||||||
|
struct expr_simplify<type_list<T, NRest...>, type_list<power<T, Ints...>, DRest...>, Pred> {
|
||||||
|
using impl = expr_simplify<type_list<NRest...>, type_list<DRest...>, Pred>;
|
||||||
|
using type = expr_simplify_power<T, ratio{1}, power<T, Ints...>::exponent>;
|
||||||
|
using num = type_list_join<typename type::num, typename impl::num>;
|
||||||
|
using den = type_list_join<typename type::den, typename impl::den>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// in case there are different powers for the same element simplify the power
|
||||||
|
template<typename T, typename... NRest, int... Ints1, typename... DRest, int... Ints2,
|
||||||
|
template<typename, typename> typename Pred>
|
||||||
|
requires(!std::same_as<power<T, Ints1...>, power<T, Ints2...>>)
|
||||||
|
struct expr_simplify<type_list<power<T, Ints1...>, NRest...>, type_list<power<T, Ints2...>, DRest...>, Pred> {
|
||||||
|
using impl = expr_simplify<type_list<NRest...>, type_list<DRest...>, Pred>;
|
||||||
|
using type = expr_simplify_power<T, power<T, Ints1...>::exponent, power<T, Ints2...>::exponent>;
|
||||||
|
using num = type_list_join<typename type::num, typename impl::num>;
|
||||||
|
using den = type_list_join<typename type::den, typename impl::den>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// expr_less
|
// expr_less
|
||||||
template<typename Lhs, typename Rhs, template<typename, typename, auto...> typename Pred>
|
template<typename Lhs, typename Rhs, template<typename, typename, auto...> typename Pred>
|
||||||
struct expr_less_impl : Pred<expr_type<Lhs>, expr_type<Rhs>> {};
|
struct expr_less_impl : Pred<expr_type<Lhs>, expr_type<Rhs>> {};
|
||||||
@@ -254,9 +328,9 @@ template<template<typename> typename OneType, typename List>
|
|||||||
template<template<typename> typename OneType, typename... Ts>
|
template<template<typename> typename OneType, typename... Ts>
|
||||||
struct expr_fractions : decltype(expr_fractions_impl<OneType, type_list<Ts...>>()) {};
|
struct expr_fractions : decltype(expr_fractions_impl<OneType, type_list<Ts...>>()) {};
|
||||||
|
|
||||||
// make_expr
|
// expr_make_spec
|
||||||
template<typename NumList, typename DenList, typename OneType, template<typename...> typename To>
|
template<typename NumList, typename DenList, typename OneType, template<typename...> typename To>
|
||||||
[[nodiscard]] consteval auto make_expr()
|
[[nodiscard]] consteval auto expr_make_spec_impl()
|
||||||
{
|
{
|
||||||
constexpr std::size_t num = type_list_size<NumList>;
|
constexpr std::size_t num = type_list_size<NumList>;
|
||||||
constexpr std::size_t den = type_list_size<DenList>;
|
constexpr std::size_t den = type_list_size<DenList>;
|
||||||
@@ -276,110 +350,19 @@ template<typename NumList, typename DenList, typename OneType, template<typename
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Simplifies the expression template
|
|
||||||
*
|
|
||||||
* Analyzes provided numerator and denominator type lists and simplifies elements with the same type.
|
|
||||||
* If the same power exists in both list, this elements gets omitted. Otherwise, the power of its
|
|
||||||
* exponent gets subtracted according to numerator and denominator elements powers.
|
|
||||||
*
|
|
||||||
* @tparam NumList type list for expression numerator
|
|
||||||
* @tparam DenList type list for expression denominator
|
|
||||||
* @tparam Pred predicate to be used for elements comparisons
|
|
||||||
*/
|
|
||||||
template<typename NumList, typename DenList, template<typename, typename> typename Pred>
|
|
||||||
struct expr_simplify_impl;
|
|
||||||
|
|
||||||
// when one of the lists is empty there is nothing to do
|
|
||||||
template<typename NumList, typename DenList, template<typename, typename> typename Pred>
|
|
||||||
requires(type_list_size<NumList> == 0) || (type_list_size<DenList> == 0)
|
|
||||||
struct expr_simplify_impl<NumList, DenList, Pred> {
|
|
||||||
using num = NumList;
|
|
||||||
using den = DenList;
|
|
||||||
};
|
|
||||||
|
|
||||||
// in case when front elements are different progress to the next element
|
|
||||||
template<typename Num, typename... NRest, typename Den, typename... DRest, template<typename, typename> typename Pred>
|
|
||||||
struct expr_simplify_impl<type_list<Num, NRest...>, type_list<Den, DRest...>, Pred> {
|
|
||||||
using impl =
|
|
||||||
conditional<Pred<Num, Den>::value, expr_simplify_impl<type_list<NRest...>, type_list<Den, DRest...>, Pred>,
|
|
||||||
expr_simplify_impl<type_list<Num, NRest...>, type_list<DRest...>, Pred>>;
|
|
||||||
using num = conditional<Pred<Num, Den>::value, type_list_push_front<typename impl::num, Num>, typename impl::num>;
|
|
||||||
using den = conditional<Pred<Num, Den>::value, typename impl::den, type_list_push_front<typename impl::den, Den>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// in case two elements are of the same power such element gets omitted
|
|
||||||
template<typename T, typename... NRest, typename... DRest, template<typename, typename> typename Pred>
|
|
||||||
struct expr_simplify_impl<type_list<T, NRest...>, type_list<T, DRest...>, Pred> :
|
|
||||||
expr_simplify_impl<type_list<NRest...>, type_list<DRest...>, Pred> {};
|
|
||||||
|
|
||||||
template<typename T, ratio Num, ratio Den>
|
|
||||||
struct expr_simplify_power {
|
|
||||||
static constexpr ratio r = Num - Den;
|
|
||||||
using type = power_or_T<T, ratio{abs(r.num), r.den}>;
|
|
||||||
using num = conditional<(r > 0), type_list<type>, type_list<>>;
|
|
||||||
using den = conditional<(r < 0), type_list<type>, type_list<>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// in case there are different powers for the same element simplify the power
|
|
||||||
template<typename T, typename... NRest, int... Ints, typename... DRest, template<typename, typename> typename Pred>
|
|
||||||
struct expr_simplify_impl<type_list<power<T, Ints...>, NRest...>, type_list<T, DRest...>, Pred> {
|
|
||||||
using impl = expr_simplify_impl<type_list<NRest...>, type_list<DRest...>, Pred>;
|
|
||||||
using type = expr_simplify_power<T, power<T, Ints...>::exponent, ratio{1}>;
|
|
||||||
using num = type_list_join<typename type::num, typename impl::num>;
|
|
||||||
using den = type_list_join<typename type::den, typename impl::den>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// in case there are different powers for the same element simplify the power
|
|
||||||
template<typename T, typename... NRest, typename... DRest, int... Ints, template<typename, typename> typename Pred>
|
|
||||||
struct expr_simplify_impl<type_list<T, NRest...>, type_list<power<T, Ints...>, DRest...>, Pred> {
|
|
||||||
using impl = expr_simplify_impl<type_list<NRest...>, type_list<DRest...>, Pred>;
|
|
||||||
using type = expr_simplify_power<T, ratio{1}, power<T, Ints...>::exponent>;
|
|
||||||
using num = type_list_join<typename type::num, typename impl::num>;
|
|
||||||
using den = type_list_join<typename type::den, typename impl::den>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// in case there are different powers for the same element simplify the power
|
|
||||||
template<typename T, typename... NRest, int... Ints1, typename... DRest, int... Ints2,
|
|
||||||
template<typename, typename> typename Pred>
|
|
||||||
requires(!std::same_as<power<T, Ints1...>, power<T, Ints2...>>)
|
|
||||||
struct expr_simplify_impl<type_list<power<T, Ints1...>, NRest...>, type_list<power<T, Ints2...>, DRest...>, Pred> {
|
|
||||||
using impl = expr_simplify_impl<type_list<NRest...>, type_list<DRest...>, Pred>;
|
|
||||||
using type = expr_simplify_power<T, power<T, Ints1...>::exponent, power<T, Ints2...>::exponent>;
|
|
||||||
using num = type_list_join<typename type::num, typename impl::num>;
|
|
||||||
using den = type_list_join<typename type::den, typename impl::den>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename...> typename To, typename OneType, template<typename, typename> typename Pred, typename T>
|
|
||||||
[[nodiscard]] consteval auto expr_simplify(T)
|
|
||||||
{
|
|
||||||
if constexpr (is_specialization_of<T, To>) {
|
|
||||||
using simple = expr_simplify_impl<typename T::_num_, typename T::_den_, Pred>;
|
|
||||||
// the usage of `std::identity` below helps to resolve an using alias identifier to the actual
|
|
||||||
// type identifier in the clang compile-time errors
|
|
||||||
return std::identity{}(make_expr<typename simple::num, typename simple::den, OneType, To>());
|
|
||||||
} else
|
|
||||||
return T{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates an expression template spec based on provided numerator and denominator parts
|
* @brief Creates an expression template spec based on provided numerator and denominator parts
|
||||||
*/
|
*/
|
||||||
template<typename NumList, typename DenList, typename OneType, template<typename, typename> typename Pred,
|
template<typename NumList, typename DenList, typename OneType, template<typename, typename> typename Pred,
|
||||||
bool Simplify, template<typename...> typename To>
|
template<typename...> typename To>
|
||||||
[[nodiscard]] consteval auto get_optimized_expression()
|
[[nodiscard]] consteval auto get_optimized_expression()
|
||||||
{
|
{
|
||||||
using num_list = expr_consolidate<NumList>;
|
using num_list = expr_consolidate<NumList>;
|
||||||
using den_list = expr_consolidate<DenList>;
|
using den_list = expr_consolidate<DenList>;
|
||||||
if constexpr (Simplify) {
|
using simple = expr_simplify<num_list, den_list, Pred>;
|
||||||
using simple = expr_simplify_impl<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{}(make_expr<typename simple::num, typename simple::den, OneType, To>());
|
|
||||||
} else
|
|
||||||
// the usage of `std::identity` below helps to resolve an using alias identifier to the actual
|
|
||||||
// type identifier in the clang compile-time errors
|
|
||||||
return std::identity{}(make_expr<num_list, den_list, OneType, To>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -388,12 +371,11 @@ template<typename NumList, typename DenList, typename OneType, template<typename
|
|||||||
* @tparam To destination type list to put the result to
|
* @tparam To destination type list to put the result to
|
||||||
* @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 Simplify specifies whether the resulting expression should be immediately simplified
|
|
||||||
* @tparam Lhs lhs of the operation
|
* @tparam Lhs lhs of the operation
|
||||||
* @tparam Rhs rhs of the operation
|
* @tparam Rhs rhs of the operation
|
||||||
*/
|
*/
|
||||||
template<template<typename...> typename To, typename OneType, template<typename, typename> typename Pred, bool Simplify,
|
template<template<typename...> typename To, typename OneType, template<typename, typename> typename Pred, typename Lhs,
|
||||||
typename Lhs, typename Rhs>
|
typename Rhs>
|
||||||
[[nodiscard]] consteval auto expr_multiply(Lhs, Rhs)
|
[[nodiscard]] consteval auto expr_multiply(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<Lhs, OneType>) {
|
if constexpr (is_same_v<Lhs, OneType>) {
|
||||||
@@ -404,17 +386,17 @@ template<template<typename...> typename To, typename OneType, template<typename,
|
|||||||
// two derived dimensions
|
// two derived dimensions
|
||||||
return get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, typename Rhs::_num_, Pred>,
|
return 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>, OneType,
|
||||||
Pred, Simplify, To>();
|
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 get_optimized_expression<type_list_merge_sorted<typename Lhs::_num_, type_list<Rhs>, Pred>,
|
||||||
typename Lhs::_den_, OneType, Pred, Simplify, 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 get_optimized_expression<type_list_merge_sorted<typename Rhs::_num_, type_list<Lhs>, Pred>,
|
||||||
typename Rhs::_den_, OneType, Pred, Simplify, 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 get_optimized_expression<type_list_merge_sorted<type_list<Lhs>, type_list<Rhs>, Pred>, type_list<>, OneType,
|
||||||
Pred, Simplify, To>();
|
Pred, To>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,12 +406,11 @@ template<template<typename...> typename To, typename OneType, template<typename,
|
|||||||
* @tparam To destination type list to put the result to
|
* @tparam To destination type list to put the result to
|
||||||
* @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 Simplify specifies whether the resulting expression should be immediately simplified
|
|
||||||
* @tparam Lhs lhs of the operation
|
* @tparam Lhs lhs of the operation
|
||||||
* @tparam Rhs rhs of the operation
|
* @tparam Rhs rhs of the operation
|
||||||
*/
|
*/
|
||||||
template<template<typename...> typename To, typename OneType, template<typename, typename> typename Pred, bool Simplify,
|
template<template<typename...> typename To, typename OneType, template<typename, typename> typename Pred, typename Lhs,
|
||||||
typename Lhs, typename Rhs>
|
typename Rhs>
|
||||||
[[nodiscard]] consteval auto expr_divide(Lhs lhs, Rhs rhs)
|
[[nodiscard]] consteval auto expr_divide(Lhs lhs, Rhs rhs)
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<Lhs, Rhs>) {
|
if constexpr (is_same_v<Lhs, Rhs>) {
|
||||||
@@ -437,19 +418,18 @@ 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, Simplify>(To<>{}, rhs);
|
return 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 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>, OneType,
|
||||||
Pred, Simplify, To>();
|
Pred, To>();
|
||||||
} else if constexpr (is_specialization_of<Lhs, To>) {
|
} else if constexpr (is_specialization_of<Lhs, To>) {
|
||||||
return get_optimized_expression<typename Lhs::_num_,
|
return get_optimized_expression<
|
||||||
type_list_merge_sorted<typename Lhs::_den_, type_list<Rhs>, Pred>, OneType, Pred,
|
typename Lhs::_num_, type_list_merge_sorted<typename Lhs::_den_, type_list<Rhs>, Pred>, OneType, Pred, To>();
|
||||||
Simplify, 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 get_optimized_expression<type_list_merge_sorted<typename Rhs::_den_, type_list<Lhs>, Pred>,
|
||||||
typename Rhs::_num_, OneType, Pred, Simplify, 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>>{};
|
||||||
@@ -462,28 +442,26 @@ template<template<typename...> typename To, typename OneType, template<typename,
|
|||||||
* @tparam T expression template spec to invert
|
* @tparam T expression template spec to invert
|
||||||
* @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
|
||||||
* @tparam Simplify specifies whether the resulting expression should be immediately simplified
|
|
||||||
*/
|
*/
|
||||||
template<template<typename...> typename To, typename OneType, bool Simplify, typename T>
|
template<template<typename...> typename To, typename OneType, typename T>
|
||||||
[[nodiscard]] consteval auto expr_invert(T)
|
[[nodiscard]] consteval auto expr_invert(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{}(make_expr<typename T::_den_, typename T::_num_, OneType, Simplify, To>());
|
return std::identity{}(expr_make_spec_impl<typename T::_den_, typename T::_num_, OneType, To>());
|
||||||
else
|
else
|
||||||
return To<OneType, per<T>>{};
|
return To<OneType, per<T>>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To, typename OneType,
|
template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To, typename OneType,
|
||||||
template<typename, typename> typename Pred, bool Simplify, typename... Nums, typename... Dens>
|
template<typename, typename> typename Pred, typename... Nums, typename... Dens>
|
||||||
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 detail::get_optimized_expression<type_list<power_or_T<Nums, ratio{Num, Den}>...>,
|
||||||
type_list<power_or_T<Dens, ratio{Num, Den}>...>, OneType, Pred, Simplify,
|
type_list<power_or_T<Dens, ratio{Num, Den}>...>, OneType, Pred, To>();
|
||||||
To>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -495,15 +473,14 @@ template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To
|
|||||||
* @tparam To destination type list to put the result to
|
* @tparam To destination type list to put the result to
|
||||||
* @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 Simplify specifies whether the resulting expression should be immediately simplified
|
|
||||||
* @tparam T Expression being the base of the operation
|
* @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<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To, typename OneType,
|
||||||
template<typename, typename> typename Pred, bool Simplify, typename T>
|
template<typename, typename> typename Pred, typename T>
|
||||||
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, Simplify>(typename T::_num_{}, typename T::_den_{});
|
return expr_pow_impl<Num, Den, To, OneType, Pred>(typename T::_num_{}, typename T::_den_{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -552,7 +552,7 @@ template<QuantitySpec Lhs, QuantitySpec Rhs>
|
|||||||
[[nodiscard]] consteval QuantitySpec auto operator*(Lhs lhs, Rhs rhs)
|
[[nodiscard]] consteval QuantitySpec auto operator*(Lhs lhs, Rhs rhs)
|
||||||
{
|
{
|
||||||
return detail::clone_kind_of<Lhs{}, Rhs{}>(
|
return detail::clone_kind_of<Lhs{}, Rhs{}>(
|
||||||
detail::expr_multiply<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less, false>(
|
detail::expr_multiply<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||||
detail::remove_kind(lhs), detail::remove_kind(rhs)));
|
detail::remove_kind(lhs), detail::remove_kind(rhs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,15 +560,10 @@ template<QuantitySpec Lhs, QuantitySpec Rhs>
|
|||||||
[[nodiscard]] consteval QuantitySpec auto operator/(Lhs lhs, Rhs rhs)
|
[[nodiscard]] consteval QuantitySpec auto operator/(Lhs lhs, Rhs rhs)
|
||||||
{
|
{
|
||||||
return detail::clone_kind_of<Lhs{}, Rhs{}>(
|
return detail::clone_kind_of<Lhs{}, Rhs{}>(
|
||||||
detail::expr_divide<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less, false>(
|
detail::expr_divide<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||||
detail::remove_kind(lhs), detail::remove_kind(rhs)));
|
detail::remove_kind(lhs), detail::remove_kind(rhs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] consteval QuantitySpec auto simplify(QuantitySpec auto q)
|
|
||||||
{
|
|
||||||
return detail::expr_simplify<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
||||||
[[nodiscard]] consteval bool operator==(Lhs, Rhs)
|
[[nodiscard]] consteval bool operator==(Lhs, Rhs)
|
||||||
{
|
{
|
||||||
@@ -597,8 +592,8 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
|
|||||||
return q;
|
return q;
|
||||||
else if constexpr (detail::DerivedQuantitySpec<Q>)
|
else if constexpr (detail::DerivedQuantitySpec<Q>)
|
||||||
return detail::clone_kind_of<Q{}>(
|
return detail::clone_kind_of<Q{}>(
|
||||||
detail::expr_pow<Num, Den, derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less,
|
detail::expr_pow<Num, Den, derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||||
false>(detail::remove_kind(q)));
|
detail::remove_kind(q)));
|
||||||
else if constexpr (Den == 1)
|
else if constexpr (Den == 1)
|
||||||
return detail::clone_kind_of<Q{}>(derived_quantity_spec<power<decltype(detail::remove_kind(Q{})), Num>>{});
|
return detail::clone_kind_of<Q{}>(derived_quantity_spec<power<decltype(detail::remove_kind(Q{})), Num>>{});
|
||||||
else
|
else
|
||||||
|
@@ -481,7 +481,7 @@ template<Unit Lhs, Unit Rhs>
|
|||||||
else if constexpr (detail::is_specialization_of_scaled_unit<Rhs>)
|
else if constexpr (detail::is_specialization_of_scaled_unit<Rhs>)
|
||||||
return Rhs::mag * (lhs * Rhs::reference_unit);
|
return Rhs::mag * (lhs * Rhs::reference_unit);
|
||||||
else
|
else
|
||||||
return detail::expr_multiply<derived_unit, struct one, detail::type_list_of_unit_less, false>(lhs, rhs);
|
return detail::expr_multiply<derived_unit, struct one, detail::type_list_of_unit_less>(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -499,7 +499,7 @@ template<Unit Lhs, Unit Rhs>
|
|||||||
else if constexpr (detail::is_specialization_of_scaled_unit<Rhs>)
|
else if constexpr (detail::is_specialization_of_scaled_unit<Rhs>)
|
||||||
return mag<1> / Rhs::mag * (lhs / Rhs::reference_unit);
|
return mag<1> / Rhs::mag * (lhs / Rhs::reference_unit);
|
||||||
else
|
else
|
||||||
return detail::expr_divide<derived_unit, struct one, detail::type_list_of_unit_less, false>(lhs, rhs);
|
return detail::expr_divide<derived_unit, struct one, detail::type_list_of_unit_less>(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto inverse(Unit auto u) { return one / u; }
|
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto inverse(Unit auto u) { return one / u; }
|
||||||
@@ -559,7 +559,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
|
|||||||
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), decltype(pow<Num, Den>(U::reference_unit))>{};
|
return scaled_unit<pow<Num, Den>(U::mag), decltype(pow<Num, Den>(U::reference_unit))>{};
|
||||||
else if constexpr (detail::is_specialization_of_derived_unit<U>)
|
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, false>(u);
|
return detail::expr_pow<Num, Den, derived_unit, struct one, detail::type_list_of_unit_less>(u);
|
||||||
else if constexpr (Den == 1)
|
else if constexpr (Den == 1)
|
||||||
return derived_unit<power<U, Num>>{};
|
return derived_unit<power<U, Num>>{};
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user