mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-03 20:34:26 +02:00
refactor: explode
and get_complexity
compile-time performance improved
This commit is contained in:
@@ -551,17 +551,17 @@ MP_UNITS_EXPORT_BEGIN
|
|||||||
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
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{}>(decltype(detail::expr_multiply<derived_quantity_spec, struct dimensionless,
|
||||||
detail::expr_multiply<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
detail::type_list_of_quantity_spec_less>(
|
||||||
detail::remove_kind(lhs), detail::remove_kind(rhs)));
|
detail::remove_kind(lhs), detail::remove_kind(rhs))){});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
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>(
|
decltype(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))){});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
||||||
@@ -570,7 +570,7 @@ template<QuantitySpec Lhs, QuantitySpec Rhs>
|
|||||||
return is_same_v<Lhs, Rhs>;
|
return is_same_v<Lhs, Rhs>;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] consteval QuantitySpec auto inverse(QuantitySpec auto q) { return dimensionless / q; }
|
[[nodiscard]] consteval QuantitySpec auto inverse(QuantitySpec auto q) { return decltype(dimensionless / q){}; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -592,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>(
|
decltype(detail::expr_pow<Num, Den, derived_quantity_spec, struct dimensionless,
|
||||||
detail::remove_kind(q)));
|
detail::type_list_of_quantity_spec_less>(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
|
||||||
@@ -608,7 +608,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
|
|||||||
*
|
*
|
||||||
* @return QuantitySpec The result of computation
|
* @return QuantitySpec The result of computation
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] consteval QuantitySpec auto sqrt(QuantitySpec auto q) { return pow<1, 2>(q); }
|
[[nodiscard]] consteval QuantitySpec auto sqrt(QuantitySpec auto q) { return decltype(pow<1, 2>(q)){}; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -618,44 +618,43 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
|
|||||||
*
|
*
|
||||||
* @return QuantitySpec The result of computation
|
* @return QuantitySpec The result of computation
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] consteval QuantitySpec auto cbrt(QuantitySpec auto q) { return pow<1, 3>(q); }
|
[[nodiscard]] consteval QuantitySpec auto cbrt(QuantitySpec auto q) { return decltype(pow<1, 3>(q)){}; }
|
||||||
|
|
||||||
MP_UNITS_EXPORT_END
|
MP_UNITS_EXPORT_END
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
enum class specs_convertible_result : std::int8_t { no, cast, explicit_conversion, yes };
|
|
||||||
|
|
||||||
template<QuantitySpec Q>
|
template<QuantitySpec Q>
|
||||||
[[nodiscard]] consteval int get_complexity(Q);
|
[[nodiscard]] consteval auto get_complexity(Q);
|
||||||
|
|
||||||
template<typename... Ts>
|
template<typename... Ts>
|
||||||
[[nodiscard]] consteval int get_complexity(type_list<Ts...>)
|
[[nodiscard]] consteval auto get_complexity(type_list<Ts...>)
|
||||||
{
|
{
|
||||||
return (0 + ... + get_complexity(Ts{}));
|
return std::integral_constant<int, (0 + ... + decltype(get_complexity(Ts{}))::value)>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantitySpec Q, int... Ints>
|
template<QuantitySpec Q, int... Ints>
|
||||||
[[nodiscard]] consteval int get_complexity(power<Q, Ints...>)
|
[[nodiscard]] consteval auto get_complexity(power<Q, Ints...>)
|
||||||
{
|
{
|
||||||
return get_complexity(Q{});
|
return decltype(get_complexity(Q{})){};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q>
|
template<typename Q>
|
||||||
[[nodiscard]] consteval int get_complexity(kind_of_<Q>)
|
[[nodiscard]] consteval auto get_complexity(kind_of_<Q>)
|
||||||
{
|
{
|
||||||
return get_complexity(Q{});
|
return decltype(get_complexity(Q{})){};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantitySpec Q>
|
template<QuantitySpec Q>
|
||||||
[[nodiscard]] consteval int get_complexity(Q)
|
[[nodiscard]] consteval auto get_complexity(Q)
|
||||||
{
|
{
|
||||||
if constexpr (detail::DerivedQuantitySpec<Q>)
|
if constexpr (detail::DerivedQuantitySpec<Q>)
|
||||||
return get_complexity(typename Q::_num_{}) + get_complexity(typename Q::_den_{});
|
return std::integral_constant<int, decltype(get_complexity(typename Q::_num_{}))::value +
|
||||||
|
decltype(get_complexity(typename Q::_den_{}))::value>{};
|
||||||
else if constexpr (requires { Q::_equation_; })
|
else if constexpr (requires { Q::_equation_; })
|
||||||
return 1 + get_complexity(Q::_equation_);
|
return std::integral_constant<int, 1 + decltype(get_complexity(Q::_equation_))::value>{};
|
||||||
else
|
else
|
||||||
return 1;
|
return std::integral_constant<int, 1>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
// dimension_one is always the last one
|
// dimension_one is always the last one
|
||||||
@@ -672,8 +671,8 @@ template<Dimension D1, Dimension D2>
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<QuantitySpec Lhs, QuantitySpec Rhs, bool lhs_eq = requires { Lhs::_equation_; },
|
template<QuantitySpec Lhs, QuantitySpec Rhs, bool lhs_eq = requires { Lhs::_equation_; },
|
||||||
bool rhs_eq = requires { Rhs::_equation_; }, ratio lhs_compl = get_complexity(Lhs{}),
|
bool rhs_eq = requires { Rhs::_equation_; }, ratio lhs_compl = decltype(get_complexity(Lhs{}))::value,
|
||||||
ratio rhs_compl = get_complexity(Rhs{})>
|
ratio rhs_compl = decltype(get_complexity(Rhs{}))::value>
|
||||||
struct ingredients_less :
|
struct ingredients_less :
|
||||||
std::bool_constant<(lhs_compl > rhs_compl) ||
|
std::bool_constant<(lhs_compl > rhs_compl) ||
|
||||||
(lhs_compl == rhs_compl && ingredients_dimension_less(Lhs::dimension, Rhs::dimension)) ||
|
(lhs_compl == rhs_compl && ingredients_dimension_less(Lhs::dimension, Rhs::dimension)) ||
|
||||||
@@ -693,25 +692,21 @@ template<QuantitySpec Q>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantitySpec Q>
|
enum class specs_convertible_result : std::int8_t { no, cast, explicit_conversion, yes };
|
||||||
|
|
||||||
|
template<QuantitySpec auto Q, specs_convertible_result Result>
|
||||||
struct explode_to_equation_result {
|
struct explode_to_equation_result {
|
||||||
Q equation;
|
static constexpr QuantitySpec auto equation = Q;
|
||||||
specs_convertible_result result;
|
static constexpr specs_convertible_result result = Result;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if MP_UNITS_COMP_CLANG
|
|
||||||
|
|
||||||
template<QuantitySpec Q>
|
|
||||||
explode_to_equation_result(Q, specs_convertible_result) -> explode_to_equation_result<Q>;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<QuantitySpec Q>
|
template<QuantitySpec Q>
|
||||||
requires requires { Q::_equation_; }
|
requires requires { Q::_equation_; }
|
||||||
[[nodiscard]] consteval auto explode_to_equation(Q q)
|
[[nodiscard]] consteval auto explode_to_equation(Q q)
|
||||||
{
|
{
|
||||||
return explode_to_equation_result{
|
return explode_to_equation_result<Q::_equation_,
|
||||||
Q::_equation_, defines_equation(q) ? specs_convertible_result::yes : specs_convertible_result::explicit_conversion};
|
(defines_equation(q) ? specs_convertible_result::yes
|
||||||
|
: specs_convertible_result::explicit_conversion)>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantitySpec Q, int... Ints>
|
template<QuantitySpec Q, int... Ints>
|
||||||
@@ -719,30 +714,23 @@ template<QuantitySpec Q, int... Ints>
|
|||||||
[[nodiscard]] consteval auto explode_to_equation(power<Q, Ints...>)
|
[[nodiscard]] consteval auto explode_to_equation(power<Q, Ints...>)
|
||||||
{
|
{
|
||||||
constexpr ratio exp = power<Q, Ints...>::exponent;
|
constexpr ratio exp = power<Q, Ints...>::exponent;
|
||||||
return explode_to_equation_result{
|
return explode_to_equation_result<decltype(pow<exp.num, exp.den>(Q::_equation_)){},
|
||||||
pow<exp.num, exp.den>(Q::_equation_),
|
(defines_equation(Q{}) ? specs_convertible_result::yes
|
||||||
defines_equation(Q{}) ? specs_convertible_result::yes : specs_convertible_result::explicit_conversion};
|
: specs_convertible_result::explicit_conversion)>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantitySpec Q>
|
template<QuantitySpec auto Q, specs_convertible_result Result = specs_convertible_result::yes>
|
||||||
struct explode_result {
|
struct explode_result {
|
||||||
Q quantity;
|
static constexpr QuantitySpec auto quantity = Q;
|
||||||
specs_convertible_result result = specs_convertible_result::yes;
|
static constexpr specs_convertible_result result = Result;
|
||||||
|
|
||||||
template<typename T>
|
template<auto T, specs_convertible_result Res>
|
||||||
[[nodiscard]] consteval explode_result common_convertibility_with(explode_to_equation_result<T> res) const
|
[[nodiscard]] static consteval auto common_convertibility_with(explode_to_equation_result<T, Res> res)
|
||||||
{
|
{
|
||||||
return {quantity, min(result, res.result)};
|
return explode_result<quantity, min(result, res.result)>{};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if MP_UNITS_COMP_CLANG
|
|
||||||
|
|
||||||
template<QuantitySpec Q>
|
|
||||||
explode_result(Q) -> explode_result<Q>;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<int Complexity, DerivedQuantitySpec Q>
|
template<int Complexity, DerivedQuantitySpec Q>
|
||||||
[[nodiscard]] consteval auto explode(Q q);
|
[[nodiscard]] consteval auto explode(Q q);
|
||||||
|
|
||||||
@@ -752,24 +740,25 @@ template<int Complexity, NamedQuantitySpec Q>
|
|||||||
template<int Complexity, QuantitySpec Q, typename Num, typename... Nums, typename Den, typename... Dens>
|
template<int Complexity, QuantitySpec Q, typename Num, typename... Nums, typename Den, typename... Dens>
|
||||||
[[nodiscard]] consteval auto explode(Q, type_list<Num, Nums...>, type_list<Den, Dens...>)
|
[[nodiscard]] consteval auto explode(Q, type_list<Num, Nums...>, type_list<Den, Dens...>)
|
||||||
{
|
{
|
||||||
constexpr auto n = get_complexity(Num{});
|
constexpr auto n = decltype(get_complexity(Num{}))::value;
|
||||||
constexpr auto d = get_complexity(Den{});
|
constexpr auto d = decltype(get_complexity(Den{}))::value;
|
||||||
constexpr auto max_compl = n > d ? n : d;
|
constexpr auto max_compl = n > d ? n : d;
|
||||||
|
|
||||||
if constexpr (max_compl == Complexity || ((n >= d && !requires { explode_to_equation(Num{}); }) ||
|
if constexpr (max_compl == Complexity || ((n >= d && !requires { explode_to_equation(Num{}); }) ||
|
||||||
(n < d && !requires { explode_to_equation(Den{}); })))
|
(n < d && !requires { explode_to_equation(Den{}); })))
|
||||||
return explode_result{(map_power(Num{}) * ... * map_power(Nums{})) / (map_power(Den{}) * ... * map_power(Dens{}))};
|
return explode_result<decltype(decltype((map_power(Num{}) * ... * map_power(Nums{}))){} /
|
||||||
|
decltype((map_power(Den{}) * ... * map_power(Dens{}))){}){}>{};
|
||||||
else {
|
else {
|
||||||
if constexpr (n >= d) {
|
if constexpr (n >= d) {
|
||||||
constexpr auto res = explode_to_equation(Num{});
|
constexpr auto res = decltype(explode_to_equation(Num{})){};
|
||||||
return explode<Complexity>((res.equation * ... * map_power(Nums{})) /
|
return decltype(explode<Complexity>(
|
||||||
(map_power(Den{}) * ... * map_power(Dens{})))
|
decltype(decltype((res.equation * ... * map_power(Nums{}))){} /
|
||||||
.common_convertibility_with(res);
|
decltype((map_power(Den{}) * ... * map_power(Dens{}))){}){}))::common_convertibility_with(res);
|
||||||
} else {
|
} else {
|
||||||
constexpr auto res = explode_to_equation(Den{});
|
constexpr auto res = explode_to_equation(Den{});
|
||||||
return explode<Complexity>((map_power(Num{}) * ... * map_power(Nums{})) /
|
return decltype(explode<Complexity>(
|
||||||
(res.equation * ... * map_power(Dens{})))
|
decltype(decltype((map_power(Num{}) * ... * map_power(Nums{}))){} /
|
||||||
.common_convertibility_with(res);
|
decltype((res.equation * ... * map_power(Dens{}))){}){}))::common_convertibility_with(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -777,54 +766,56 @@ template<int Complexity, QuantitySpec Q, typename Num, typename... Nums, typenam
|
|||||||
template<int Complexity, QuantitySpec Q, typename Num, typename... Nums>
|
template<int Complexity, QuantitySpec Q, typename Num, typename... Nums>
|
||||||
[[nodiscard]] consteval auto explode(Q, type_list<Num, Nums...>, type_list<>)
|
[[nodiscard]] consteval auto explode(Q, type_list<Num, Nums...>, type_list<>)
|
||||||
{
|
{
|
||||||
constexpr auto n = get_complexity(Num{});
|
constexpr auto n = decltype(get_complexity(Num{}))::value;
|
||||||
if constexpr (n == Complexity || !requires { explode_to_equation(Num{}); })
|
if constexpr (n == Complexity || !requires { explode_to_equation(Num{}); })
|
||||||
return explode_result{(map_power(Num{}) * ... * map_power(Nums{}))};
|
return explode_result<decltype((map_power(Num{}) * ... * map_power(Nums{}))){}>{};
|
||||||
else {
|
else {
|
||||||
constexpr auto res = explode_to_equation(Num{});
|
constexpr auto res = decltype(explode_to_equation(Num{})){};
|
||||||
return explode<Complexity>((res.equation * ... * map_power(Nums{}))).common_convertibility_with(res);
|
return decltype(explode<Complexity>(
|
||||||
|
decltype((res.equation * ... * map_power(Nums{}))){}))::common_convertibility_with(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int Complexity, QuantitySpec Q, typename Den, typename... Dens>
|
template<int Complexity, QuantitySpec Q, typename Den, typename... Dens>
|
||||||
[[nodiscard]] consteval auto explode(Q, type_list<>, type_list<Den, Dens...>)
|
[[nodiscard]] consteval auto explode(Q, type_list<>, type_list<Den, Dens...>)
|
||||||
{
|
{
|
||||||
constexpr auto d = get_complexity(Den{});
|
constexpr auto d = decltype(get_complexity(Den{}))::value;
|
||||||
if constexpr (d == Complexity || !requires { explode_to_equation(Den{}); })
|
if constexpr (d == Complexity || !requires { explode_to_equation(Den{}); })
|
||||||
return explode_result{dimensionless / (map_power(Den{}) * ... * map_power(Dens{}))};
|
return explode_result<decltype(dimensionless / decltype((map_power(Den{}) * ... * map_power(Dens{}))){}){}>{};
|
||||||
else {
|
else {
|
||||||
constexpr auto res = explode_to_equation(Den{});
|
constexpr auto res = decltype(explode_to_equation(Den{})){};
|
||||||
return explode<Complexity>(dimensionless / (res.equation * ... * map_power(Dens{})))
|
return decltype(explode<Complexity>(
|
||||||
.common_convertibility_with(res);
|
decltype(dimensionless /
|
||||||
|
decltype((res.equation * ... * map_power(Dens{}))){}){}))::common_convertibility_with(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int Complexity, QuantitySpec Q>
|
template<int Complexity, QuantitySpec Q>
|
||||||
[[nodiscard]] consteval auto explode(Q, type_list<>, type_list<>)
|
[[nodiscard]] consteval auto explode(Q, type_list<>, type_list<>)
|
||||||
{
|
{
|
||||||
return explode_result{dimensionless};
|
return explode_result<dimensionless>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int Complexity, DerivedQuantitySpec Q>
|
template<int Complexity, DerivedQuantitySpec Q>
|
||||||
[[nodiscard]] consteval auto explode(Q q)
|
[[nodiscard]] consteval auto explode(Q q)
|
||||||
{
|
{
|
||||||
constexpr auto c = get_complexity(Q{});
|
constexpr auto c = decltype(get_complexity(Q{}))::value;
|
||||||
if constexpr (c > Complexity)
|
if constexpr (c > Complexity)
|
||||||
return explode<Complexity>(q, type_list_sort<typename Q::_num_, type_list_of_ingredients_less>{},
|
return decltype(explode<Complexity>(q, type_list_sort<typename Q::_num_, type_list_of_ingredients_less>{},
|
||||||
type_list_sort<typename Q::_den_, type_list_of_ingredients_less>{});
|
type_list_sort<typename Q::_den_, type_list_of_ingredients_less>{})){};
|
||||||
else
|
else
|
||||||
return explode_result{q};
|
return explode_result<Q{}>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int Complexity, NamedQuantitySpec Q>
|
template<int Complexity, NamedQuantitySpec Q>
|
||||||
[[nodiscard]] consteval auto explode(Q q)
|
[[nodiscard]] consteval auto explode(Q)
|
||||||
{
|
{
|
||||||
constexpr auto c = get_complexity(Q{});
|
constexpr auto c = decltype(get_complexity(Q{}))::value;
|
||||||
if constexpr (c > Complexity && requires { Q::_equation_; }) {
|
if constexpr (c > Complexity && requires { Q::_equation_; }) {
|
||||||
constexpr auto res = explode_to_equation(Q{});
|
constexpr auto res = decltype(explode_to_equation(Q{})){};
|
||||||
return explode<Complexity>(res.equation).common_convertibility_with(res);
|
return decltype(explode<Complexity>(res.equation))::common_convertibility_with(res);
|
||||||
} else
|
} else
|
||||||
return explode_result{q};
|
return explode_result<Q{}>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename NumFrom, typename... NumsFrom, typename DenFrom, typename... DensFrom, typename NumTo,
|
template<typename NumFrom, typename... NumsFrom, typename DenFrom, typename... DensFrom, typename NumTo,
|
||||||
@@ -916,8 +907,8 @@ extract_results(bool, From = {}, To = {}, prepend_rest = {}, Elem = {}) -> extra
|
|||||||
template<typename From, typename To>
|
template<typename From, typename To>
|
||||||
[[nodiscard]] consteval auto extract_convertible_quantities(From, To)
|
[[nodiscard]] consteval auto extract_convertible_quantities(From, To)
|
||||||
{
|
{
|
||||||
constexpr auto qfrom = map_power(From{});
|
constexpr auto qfrom = decltype(map_power(From{})){};
|
||||||
constexpr auto qto = map_power(To{});
|
constexpr auto qto = decltype(map_power(To{})){};
|
||||||
if constexpr (qfrom.dimension == qto.dimension) {
|
if constexpr (qfrom.dimension == qto.dimension) {
|
||||||
if constexpr (is_specialization_of_power<From> && is_specialization_of_power<To>) {
|
if constexpr (is_specialization_of_power<From> && is_specialization_of_power<To>) {
|
||||||
constexpr auto cr = common_ratio(From::exponent, To::exponent);
|
constexpr auto cr = common_ratio(From::exponent, To::exponent);
|
||||||
@@ -1023,10 +1014,10 @@ template<typename NumFrom, typename... NumsFrom, typename DenFrom, typename... D
|
|||||||
return process_extracted<process_entities::to, extT>(num_from, den_from, type_list<NumsTo...>{},
|
return process_extracted<process_entities::to, extT>(num_from, den_from, type_list<NumsTo...>{},
|
||||||
type_list<DensTo...>{});
|
type_list<DensTo...>{});
|
||||||
else {
|
else {
|
||||||
constexpr auto num_from_compl = get_complexity(NumFrom{});
|
constexpr auto num_from_compl = decltype(get_complexity(NumFrom{}))::value;
|
||||||
constexpr auto den_from_compl = get_complexity(DenFrom{});
|
constexpr auto den_from_compl = decltype(get_complexity(DenFrom{}))::value;
|
||||||
constexpr auto num_to_compl = get_complexity(NumTo{});
|
constexpr auto num_to_compl = decltype(get_complexity(NumTo{}))::value;
|
||||||
constexpr auto den_to_compl = get_complexity(DenTo{});
|
constexpr auto den_to_compl = decltype(get_complexity(DenTo{}))::value;
|
||||||
constexpr auto max_compl = max({num_from_compl, num_to_compl, den_from_compl, den_to_compl});
|
constexpr auto max_compl = max({num_from_compl, num_to_compl, den_from_compl, den_to_compl});
|
||||||
if constexpr (max_compl > 1) {
|
if constexpr (max_compl > 1) {
|
||||||
if constexpr (num_from_compl == max_compl) {
|
if constexpr (num_from_compl == max_compl) {
|
||||||
@@ -1070,9 +1061,9 @@ template<typename DenFrom, typename... DensFrom, typename NumTo, typename... Num
|
|||||||
return process_extracted<process_entities::to, extT>(num_from, den_from, type_list<NumsTo...>{},
|
return process_extracted<process_entities::to, extT>(num_from, den_from, type_list<NumsTo...>{},
|
||||||
type_list<DensTo...>{});
|
type_list<DensTo...>{});
|
||||||
else {
|
else {
|
||||||
constexpr auto den_from_compl = get_complexity(DenFrom{});
|
constexpr auto den_from_compl = decltype(get_complexity(DenFrom{}))::value;
|
||||||
constexpr auto num_to_compl = get_complexity(NumTo{});
|
constexpr auto num_to_compl = decltype(get_complexity(NumTo{}))::value;
|
||||||
constexpr auto den_to_compl = get_complexity(DenTo{});
|
constexpr auto den_to_compl = decltype(get_complexity(DenTo{}))::value;
|
||||||
constexpr auto max_compl = max({num_to_compl, den_from_compl, den_to_compl});
|
constexpr auto max_compl = max({num_to_compl, den_from_compl, den_to_compl});
|
||||||
if constexpr (max_compl > 1) {
|
if constexpr (max_compl > 1) {
|
||||||
if constexpr (den_from_compl == max_compl) {
|
if constexpr (den_from_compl == max_compl) {
|
||||||
@@ -1109,9 +1100,9 @@ template<typename NumFrom, typename... NumsFrom, typename NumTo, typename... Num
|
|||||||
return process_extracted<process_entities::to, extT>(num_from, den_from, type_list<NumsTo...>{},
|
return process_extracted<process_entities::to, extT>(num_from, den_from, type_list<NumsTo...>{},
|
||||||
type_list<DensTo...>{});
|
type_list<DensTo...>{});
|
||||||
else {
|
else {
|
||||||
constexpr auto num_from_compl = get_complexity(NumFrom{});
|
constexpr auto num_from_compl = decltype(get_complexity(NumFrom{}))::value;
|
||||||
constexpr auto num_to_compl = get_complexity(NumTo{});
|
constexpr auto num_to_compl = decltype(get_complexity(NumTo{}))::value;
|
||||||
constexpr auto den_to_compl = get_complexity(DenTo{});
|
constexpr auto den_to_compl = decltype(get_complexity(DenTo{}))::value;
|
||||||
constexpr auto max_compl = max({num_from_compl, num_to_compl, den_to_compl});
|
constexpr auto max_compl = max({num_from_compl, num_to_compl, den_to_compl});
|
||||||
if constexpr (max_compl > 1) {
|
if constexpr (max_compl > 1) {
|
||||||
if constexpr (num_from_compl == max_compl) {
|
if constexpr (num_from_compl == max_compl) {
|
||||||
@@ -1149,9 +1140,9 @@ template<typename NumFrom, typename... NumsFrom, typename DenFrom, typename... D
|
|||||||
return process_extracted<process_entities::from, extF>(type_list<NumsFrom...>{}, type_list<DensFrom...>{}, num_to,
|
return process_extracted<process_entities::from, extF>(type_list<NumsFrom...>{}, type_list<DensFrom...>{}, num_to,
|
||||||
den_to);
|
den_to);
|
||||||
else {
|
else {
|
||||||
constexpr auto num_from_compl = get_complexity(NumFrom{});
|
constexpr auto num_from_compl = decltype(get_complexity(NumFrom{}))::value;
|
||||||
constexpr auto den_from_compl = get_complexity(DenFrom{});
|
constexpr auto den_from_compl = decltype(get_complexity(DenFrom{}))::value;
|
||||||
constexpr auto den_to_compl = get_complexity(DenTo{});
|
constexpr auto den_to_compl = decltype(get_complexity(DenTo{}))::value;
|
||||||
constexpr auto max_compl = max({num_from_compl, den_from_compl, den_to_compl});
|
constexpr auto max_compl = max({num_from_compl, den_from_compl, den_to_compl});
|
||||||
if constexpr (max_compl > 1) {
|
if constexpr (max_compl > 1) {
|
||||||
if constexpr (num_from_compl == max_compl) {
|
if constexpr (num_from_compl == max_compl) {
|
||||||
@@ -1189,9 +1180,9 @@ template<typename NumFrom, typename... NumsFrom, typename DenFrom, typename... D
|
|||||||
return process_extracted<process_entities::from, extF>(type_list<NumsFrom...>{}, type_list<DensFrom...>{}, num_to,
|
return process_extracted<process_entities::from, extF>(type_list<NumsFrom...>{}, type_list<DensFrom...>{}, num_to,
|
||||||
den_to);
|
den_to);
|
||||||
else {
|
else {
|
||||||
constexpr auto num_from_compl = get_complexity(NumFrom{});
|
constexpr auto num_from_compl = decltype(get_complexity(NumFrom{}))::value;
|
||||||
constexpr auto den_from_compl = get_complexity(DenFrom{});
|
constexpr auto den_from_compl = decltype(get_complexity(DenFrom{}))::value;
|
||||||
constexpr auto num_to_compl = get_complexity(NumTo{});
|
constexpr auto num_to_compl = decltype(get_complexity(NumTo{}))::value;
|
||||||
constexpr auto max_compl = max({num_from_compl, num_to_compl, den_from_compl});
|
constexpr auto max_compl = max({num_from_compl, num_to_compl, den_from_compl});
|
||||||
if constexpr (max_compl > 1) {
|
if constexpr (max_compl > 1) {
|
||||||
if constexpr (num_from_compl == max_compl) {
|
if constexpr (num_from_compl == max_compl) {
|
||||||
@@ -1225,8 +1216,8 @@ template<typename NumFrom, typename... NumsFrom, typename NumTo, typename... Num
|
|||||||
return process_extracted<process_entities::numerators, ext>(type_list<NumsFrom...>{}, den_from,
|
return process_extracted<process_entities::numerators, ext>(type_list<NumsFrom...>{}, den_from,
|
||||||
type_list<NumsTo...>{}, den_to);
|
type_list<NumsTo...>{}, den_to);
|
||||||
} else {
|
} else {
|
||||||
constexpr auto num_from_compl = get_complexity(NumFrom{});
|
constexpr auto num_from_compl = decltype(get_complexity(NumFrom{}))::value;
|
||||||
constexpr auto num_to_compl = get_complexity(NumTo{});
|
constexpr auto num_to_compl = decltype(get_complexity(NumTo{}))::value;
|
||||||
constexpr auto max_compl = max(num_from_compl, num_to_compl);
|
constexpr auto max_compl = max(num_from_compl, num_to_compl);
|
||||||
if constexpr (max_compl > 1) {
|
if constexpr (max_compl > 1) {
|
||||||
if constexpr (num_from_compl == max_compl) {
|
if constexpr (num_from_compl == max_compl) {
|
||||||
@@ -1253,8 +1244,8 @@ template<typename DenFrom, typename... DensFrom, typename DenTo, typename... Den
|
|||||||
return process_extracted<process_entities::denominators, ext>(num_from, type_list<DensFrom...>{}, num_to,
|
return process_extracted<process_entities::denominators, ext>(num_from, type_list<DensFrom...>{}, num_to,
|
||||||
type_list<DensTo...>{});
|
type_list<DensTo...>{});
|
||||||
else {
|
else {
|
||||||
constexpr auto den_from_compl = get_complexity(DenFrom{});
|
constexpr auto den_from_compl = decltype(get_complexity(DenFrom{}))::value;
|
||||||
constexpr auto den_to_compl = get_complexity(DenTo{});
|
constexpr auto den_to_compl = decltype(get_complexity(DenTo{}))::value;
|
||||||
constexpr auto max_compl = max(den_from_compl, den_to_compl);
|
constexpr auto max_compl = max(den_from_compl, den_to_compl);
|
||||||
if constexpr (max_compl > 1) {
|
if constexpr (max_compl > 1) {
|
||||||
if constexpr (den_from_compl == max_compl) {
|
if constexpr (den_from_compl == max_compl) {
|
||||||
@@ -1371,14 +1362,14 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
return res == no ? no : yes;
|
return res == no ? no : yes;
|
||||||
};
|
};
|
||||||
if constexpr ((NamedQuantitySpec<decltype(from_kind)> && NamedQuantitySpec<decltype(to_kind)>) ||
|
if constexpr ((NamedQuantitySpec<decltype(from_kind)> && NamedQuantitySpec<decltype(to_kind)>) ||
|
||||||
get_complexity(from_kind) == get_complexity(to_kind))
|
decltype(get_complexity(from_kind))::value == decltype(get_complexity(to_kind))::value)
|
||||||
return convertible_impl(from_kind, to_kind);
|
return convertible_impl(from_kind, to_kind);
|
||||||
else if constexpr (get_complexity(from_kind) > get_complexity(to_kind))
|
else if constexpr (decltype(get_complexity(from_kind))::value > decltype(get_complexity(to_kind))::value)
|
||||||
return exploded_kind_result(
|
return exploded_kind_result(convertible_impl(
|
||||||
convertible_impl(get_kind_tree_root(explode<get_complexity(to_kind)>(from_kind).quantity), to_kind));
|
get_kind_tree_root(explode<decltype(get_complexity(to_kind))::value>(from_kind).quantity), to_kind));
|
||||||
else
|
else
|
||||||
return exploded_kind_result(
|
return exploded_kind_result(convertible_impl(
|
||||||
convertible_impl(from_kind, get_kind_tree_root(explode<get_complexity(from_kind)>(to_kind).quantity)));
|
from_kind, get_kind_tree_root(explode<decltype(get_complexity(from_kind))::value>(to_kind).quantity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<NamedQuantitySpec From, NamedQuantitySpec To>
|
template<NamedQuantitySpec From, NamedQuantitySpec To>
|
||||||
@@ -1393,11 +1384,11 @@ template<NamedQuantitySpec From, NamedQuantitySpec To>
|
|||||||
return no;
|
return no;
|
||||||
} else if constexpr (get_kind(From{}) != get_kind(To{}))
|
} else if constexpr (get_kind(From{}) != get_kind(To{}))
|
||||||
return no;
|
return no;
|
||||||
else if constexpr (get_complexity(From{}) != get_complexity(To{})) {
|
else if constexpr (decltype(get_complexity(From{}))::value != decltype(get_complexity(To{}))::value) {
|
||||||
if constexpr (get_complexity(From{}) > get_complexity(To{}))
|
if constexpr (decltype(get_complexity(From{}))::value > decltype(get_complexity(To{}))::value)
|
||||||
return convertible_impl(explode<get_complexity(to)>(from).quantity, to);
|
return convertible_impl(explode<decltype(get_complexity(to))::value>(from).quantity, to);
|
||||||
else {
|
else {
|
||||||
auto res = explode<get_complexity(from)>(to);
|
auto res = explode<decltype(get_complexity(from))::value>(to);
|
||||||
return min(res.result, convertible_impl(from, res.quantity));
|
return min(res.result, convertible_impl(from, res.quantity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1422,7 +1413,7 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
} else if constexpr (DerivedQuantitySpec<From> && DerivedQuantitySpec<To>) {
|
} else if constexpr (DerivedQuantitySpec<From> && DerivedQuantitySpec<To>) {
|
||||||
return are_ingredients_convertible(from, to);
|
return are_ingredients_convertible(from, to);
|
||||||
} else if constexpr (DerivedQuantitySpec<From>) {
|
} else if constexpr (DerivedQuantitySpec<From>) {
|
||||||
auto res = explode<get_complexity(to)>(from);
|
auto res = explode<decltype(get_complexity(to))::value>(from);
|
||||||
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
||||||
return convertible_impl(res.quantity, to);
|
return convertible_impl(res.quantity, to);
|
||||||
else if constexpr (requires { to._equation_; }) {
|
else if constexpr (requires { to._equation_; }) {
|
||||||
@@ -1431,7 +1422,7 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
} else
|
} else
|
||||||
return are_ingredients_convertible(from, to);
|
return are_ingredients_convertible(from, to);
|
||||||
} else if constexpr (DerivedQuantitySpec<To>) {
|
} else if constexpr (DerivedQuantitySpec<To>) {
|
||||||
auto res = explode<get_complexity(from)>(to);
|
auto res = explode<decltype(get_complexity(from))::value>(to);
|
||||||
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
||||||
return min(res.result, convertible_impl(from, res.quantity));
|
return min(res.result, convertible_impl(from, res.quantity));
|
||||||
else if constexpr (requires { from._equation_; })
|
else if constexpr (requires { from._equation_; })
|
||||||
@@ -1508,8 +1499,8 @@ template<QuantitySpec Q>
|
|||||||
} else if constexpr (requires { Q::_parent_; }) {
|
} else if constexpr (requires { Q::_parent_; }) {
|
||||||
return get_kind_tree_root(Q::_parent_);
|
return get_kind_tree_root(Q::_parent_);
|
||||||
} else if constexpr (detail::DerivedQuantitySpec<Q>) {
|
} else if constexpr (detail::DerivedQuantitySpec<Q>) {
|
||||||
return detail::expr_map<detail::to_kind, derived_quantity_spec, struct dimensionless,
|
return decltype(detail::expr_map<detail::to_kind, derived_quantity_spec, struct dimensionless,
|
||||||
detail::type_list_of_quantity_spec_less>(q);
|
detail::type_list_of_quantity_spec_less>(q)){};
|
||||||
} else {
|
} else {
|
||||||
// root quantity
|
// root quantity
|
||||||
return q;
|
return q;
|
||||||
|
Reference in New Issue
Block a user