From c30f62e7f5cfa6b8202b729fb40203917f8c1760 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Thu, 4 Jul 2024 22:57:49 +0100 Subject: [PATCH] docs: 2.2.0 release announcement updated to point to 2.2.1 --- docs/blog/posts/2.2.0-released.md | 6 +- .../include/mp-units/framework/dimension.h | 11 +- .../mp-units/framework/expression_template.h | 223 ++++++++++-------- .../mp-units/framework/quantity_spec.h | 13 +- src/core/include/mp-units/framework/unit.h | 6 +- 5 files changed, 143 insertions(+), 116 deletions(-) diff --git a/docs/blog/posts/2.2.0-released.md b/docs/blog/posts/2.2.0-released.md index bd30c471..451a1f53 100644 --- a/docs/blog/posts/2.2.0-released.md +++ b/docs/blog/posts/2.2.0-released.md @@ -9,14 +9,14 @@ categories: # mp-units 2.2.0 released! **A new product version can be obtained from -[GitHub](https://github.com/mpusz/mp-units/releases/tag/v2.2.0) and -[Conan](https://conan.io/center/recipes/mp-units?version=2.2.0).** +[GitHub](https://github.com/mpusz/mp-units/releases/tag/v2.2.1) and +[Conan](https://conan.io/center/recipes/mp-units?version=2.2.1).** Among other features, this release provides long-awaited support for C++20 modules, redesigns and enhances text output formatting, and greatly simplifies quantity point usage. This post describes those and a few other smaller interesting improvements, while a much longer list of the most significant changes introduced by the new version can be found in our -[Release Notes](../../release_notes.md#2.2.0). +[Release Notes](../../release_notes.md#2.2.1). diff --git a/src/core/include/mp-units/framework/dimension.h b/src/core/include/mp-units/framework/dimension.h index cbd3609d..eed17936 100644 --- a/src/core/include/mp-units/framework/dimension.h +++ b/src/core/include/mp-units/framework/dimension.h @@ -160,15 +160,15 @@ struct is_dimension_one : std::true_type {}; MP_UNITS_EXPORT template [[nodiscard]] consteval Dimension auto operator*(Lhs, Rhs) { - return detail::expr_multiply( + return detail::expr_multiply( Lhs{}, Rhs{}); } MP_UNITS_EXPORT template [[nodiscard]] consteval Dimension auto operator/(Lhs, Rhs) { - return detail::expr_divide(Lhs{}, - Rhs{}); + return detail::expr_divide( + Lhs{}, Rhs{}); } namespace detail { @@ -213,8 +213,8 @@ template else return derived_dimension>{}; } else - return detail::expr_pow(d); + return detail::expr_pow(d); } /** @@ -235,7 +235,6 @@ template */ [[nodiscard]] consteval Dimension auto cbrt(Dimension auto d) { return pow<1, 3>(d); } - struct dimension_symbol_formatting { text_encoding encoding = text_encoding::default_encoding; }; diff --git a/src/core/include/mp-units/framework/expression_template.h b/src/core/include/mp-units/framework/expression_template.h index 0e1c0dc2..45b77ff3 100644 --- a/src/core/include/mp-units/framework/expression_template.h +++ b/src/core/include/mp-units/framework/expression_template.h @@ -199,80 +199,6 @@ template using expr_consolidate = MP_UNITS_TYPENAME expr_consolidate_impl::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 Pred> -struct expr_simplify; - -// when one of the lists is empty there is nothing to do -template typename Pred> - requires(type_list_size == 0) || (type_list_size == 0) -struct expr_simplify { - using num = NumList; - using den = DenList; -}; - -// in case when front elements are different progress to the next element -template typename Pred> -struct expr_simplify, type_list, Pred> { - using impl = conditional::value, expr_simplify, type_list, Pred>, - expr_simplify, type_list, Pred>>; - using num = conditional::value, type_list_push_front, typename impl::num>; - using den = conditional::value, typename impl::den, type_list_push_front>; -}; - -// in case two elements are of the same power such element gets omitted -template typename Pred> -struct expr_simplify, type_list, Pred> : - expr_simplify, type_list, Pred> {}; - -template -struct expr_simplify_power { - static constexpr ratio r = Num - Den; - using type = power_or_T; - using num = conditional<(r > 0), type_list, type_list<>>; - using den = conditional<(r < 0), type_list, type_list<>>; -}; - -// in case there are different powers for the same element simplify the power -template typename Pred> -struct expr_simplify, NRest...>, type_list, Pred> { - using impl = expr_simplify, type_list, Pred>; - using type = expr_simplify_power::exponent, ratio{1}>; - using num = type_list_join; - using den = type_list_join; -}; - -// in case there are different powers for the same element simplify the power -template typename Pred> -struct expr_simplify, type_list, DRest...>, Pred> { - using impl = expr_simplify, type_list, Pred>; - using type = expr_simplify_power::exponent>; - using num = type_list_join; - using den = type_list_join; -}; - -// in case there are different powers for the same element simplify the power -template typename Pred> - requires(!std::same_as, power>) -struct expr_simplify, NRest...>, type_list, DRest...>, Pred> { - using impl = expr_simplify, type_list, Pred>; - using type = expr_simplify_power::exponent, power::exponent>; - using num = type_list_join; - using den = type_list_join; -}; - - // expr_less template typename Pred> struct expr_less_impl : Pred, expr_type> {}; @@ -328,9 +254,9 @@ template typename OneType, typename List> template typename OneType, typename... Ts> struct expr_fractions : decltype(expr_fractions_impl>()) {}; -// expr_make_spec +// make_expr template typename To> -[[nodiscard]] consteval auto expr_make_spec_impl() +[[nodiscard]] consteval auto make_expr() { constexpr std::size_t num = type_list_size; constexpr std::size_t den = type_list_size; @@ -350,19 +276,110 @@ template typename Pred> +struct expr_simplify_impl; + +// when one of the lists is empty there is nothing to do +template typename Pred> + requires(type_list_size == 0) || (type_list_size == 0) +struct expr_simplify_impl { + using num = NumList; + using den = DenList; +}; + +// in case when front elements are different progress to the next element +template typename Pred> +struct expr_simplify_impl, type_list, Pred> { + using impl = + conditional::value, expr_simplify_impl, type_list, Pred>, + expr_simplify_impl, type_list, Pred>>; + using num = conditional::value, type_list_push_front, typename impl::num>; + using den = conditional::value, typename impl::den, type_list_push_front>; +}; + +// in case two elements are of the same power such element gets omitted +template typename Pred> +struct expr_simplify_impl, type_list, Pred> : + expr_simplify_impl, type_list, Pred> {}; + +template +struct expr_simplify_power { + static constexpr ratio r = Num - Den; + using type = power_or_T; + using num = conditional<(r > 0), type_list, type_list<>>; + using den = conditional<(r < 0), type_list, type_list<>>; +}; + +// in case there are different powers for the same element simplify the power +template typename Pred> +struct expr_simplify_impl, NRest...>, type_list, Pred> { + using impl = expr_simplify_impl, type_list, Pred>; + using type = expr_simplify_power::exponent, ratio{1}>; + using num = type_list_join; + using den = type_list_join; +}; + +// in case there are different powers for the same element simplify the power +template typename Pred> +struct expr_simplify_impl, type_list, DRest...>, Pred> { + using impl = expr_simplify_impl, type_list, Pred>; + using type = expr_simplify_power::exponent>; + using num = type_list_join; + using den = type_list_join; +}; + +// in case there are different powers for the same element simplify the power +template typename Pred> + requires(!std::same_as, power>) +struct expr_simplify_impl, NRest...>, type_list, DRest...>, Pred> { + using impl = expr_simplify_impl, type_list, Pred>; + using type = expr_simplify_power::exponent, power::exponent>; + using num = type_list_join; + using den = type_list_join; +}; + +template typename To, typename OneType, template typename Pred, typename T> +[[nodiscard]] consteval auto expr_simplify(T) +{ + if constexpr (is_specialization_of) { + using simple = expr_simplify_impl; + // 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()); + } else + return T{}; +} + /** * @brief Creates an expression template spec based on provided numerator and denominator parts */ template typename Pred, - template typename To> + bool Simplify, template typename To> [[nodiscard]] consteval auto get_optimized_expression() { using num_list = expr_consolidate; using den_list = expr_consolidate; - using simple = expr_simplify; - // 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{}(expr_make_spec_impl()); + if constexpr (Simplify) { + using simple = expr_simplify_impl; + // 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()); + } 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()); } /** @@ -371,11 +388,12 @@ template typename To, typename OneType, template typename Pred, typename Lhs, - typename Rhs> +template typename To, typename OneType, template typename Pred, bool Simplify, + typename Lhs, typename Rhs> [[nodiscard]] consteval auto expr_multiply(Lhs, Rhs) { if constexpr (is_same_v) { @@ -386,17 +404,17 @@ template typename To, typename OneType, template, type_list_merge_sorted, OneType, - Pred, To>(); + Pred, Simplify, To>(); } else if constexpr (is_specialization_of) { return get_optimized_expression, Pred>, - typename Lhs::_den_, OneType, Pred, To>(); + typename Lhs::_den_, OneType, Pred, Simplify, To>(); } else if constexpr (is_specialization_of) { return get_optimized_expression, Pred>, - typename Rhs::_den_, OneType, Pred, To>(); + typename Rhs::_den_, OneType, Pred, Simplify, To>(); } else { // two base dimensions return get_optimized_expression, type_list, Pred>, type_list<>, OneType, - Pred, To>(); + Pred, Simplify, To>(); } } @@ -406,11 +424,12 @@ template typename To, typename OneType, template typename To, typename OneType, template typename Pred, typename Lhs, - typename Rhs> +template typename To, typename OneType, template typename Pred, bool Simplify, + typename Lhs, typename Rhs> [[nodiscard]] consteval auto expr_divide(Lhs lhs, Rhs rhs) { if constexpr (is_same_v) { @@ -418,18 +437,19 @@ template typename To, typename OneType, template) { return lhs; } else if constexpr (is_same_v) { - return expr_divide(To<>{}, rhs); + return expr_divide(To<>{}, rhs); } else if constexpr (is_specialization_of && is_specialization_of) { // two derived entities return get_optimized_expression, type_list_merge_sorted, OneType, - Pred, To>(); + Pred, Simplify, To>(); } else if constexpr (is_specialization_of) { - return get_optimized_expression< - typename Lhs::_num_, type_list_merge_sorted, Pred>, OneType, Pred, To>(); + return get_optimized_expression, Pred>, OneType, Pred, + Simplify, To>(); } else if constexpr (is_specialization_of) { return get_optimized_expression, Pred>, - typename Rhs::_num_, OneType, Pred, To>(); + typename Rhs::_num_, OneType, Pred, Simplify, To>(); } else { // two named entities return To>{}; @@ -442,26 +462,28 @@ template typename To, typename OneType, template typename To, typename OneType, typename T> +template typename To, typename OneType, bool Simplify, typename T> [[nodiscard]] consteval auto expr_invert(T) { if constexpr (is_specialization_of) // 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{}(expr_make_spec_impl()); + return std::identity{}(make_expr()); else return To>{}; } template typename To, typename OneType, - template typename Pred, typename... Nums, typename... Dens> + template typename Pred, bool Simplify, typename... Nums, typename... Dens> requires detail::non_zero [[nodiscard]] consteval auto expr_pow_impl(type_list, type_list) { return detail::get_optimized_expression...>, - type_list...>, OneType, Pred, To>(); + type_list...>, OneType, Pred, Simplify, + To>(); } @@ -473,14 +495,15 @@ template typename To * @tparam To destination type list to put the result to * @tparam OneType type that represents the value `1` * @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 */ template typename To, typename OneType, - template typename Pred, typename T> + template typename Pred, bool Simplify, typename T> requires detail::non_zero [[nodiscard]] consteval auto expr_pow(T) { - return expr_pow_impl(typename T::_num_{}, typename T::_den_{}); + return expr_pow_impl(typename T::_num_{}, typename T::_den_{}); } diff --git a/src/core/include/mp-units/framework/quantity_spec.h b/src/core/include/mp-units/framework/quantity_spec.h index 3c24b88c..458592e3 100644 --- a/src/core/include/mp-units/framework/quantity_spec.h +++ b/src/core/include/mp-units/framework/quantity_spec.h @@ -552,7 +552,7 @@ template [[nodiscard]] consteval QuantitySpec auto operator*(Lhs lhs, Rhs rhs) { return detail::clone_kind_of( - detail::expr_multiply( + detail::expr_multiply( detail::remove_kind(lhs), detail::remove_kind(rhs))); } @@ -560,10 +560,15 @@ template [[nodiscard]] consteval QuantitySpec auto operator/(Lhs lhs, Rhs rhs) { return detail::clone_kind_of( - detail::expr_divide( + detail::expr_divide( detail::remove_kind(lhs), detail::remove_kind(rhs))); } +[[nodiscard]] consteval QuantitySpec auto simplify(QuantitySpec auto q) +{ + return detail::expr_simplify(q); +} + template [[nodiscard]] consteval bool operator==(Lhs, Rhs) { @@ -592,8 +597,8 @@ template return q; else if constexpr (detail::DerivedQuantitySpec) return detail::clone_kind_of( - detail::expr_pow( - detail::remove_kind(q))); + detail::expr_pow(detail::remove_kind(q))); else if constexpr (Den == 1) return detail::clone_kind_of(derived_quantity_spec>{}); else diff --git a/src/core/include/mp-units/framework/unit.h b/src/core/include/mp-units/framework/unit.h index f32f4b40..af0ed993 100644 --- a/src/core/include/mp-units/framework/unit.h +++ b/src/core/include/mp-units/framework/unit.h @@ -481,7 +481,7 @@ template else if constexpr (detail::is_specialization_of_scaled_unit) return Rhs::mag * (lhs * Rhs::reference_unit); else - return detail::expr_multiply(lhs, rhs); + return detail::expr_multiply(lhs, rhs); } /** @@ -499,7 +499,7 @@ template else if constexpr (detail::is_specialization_of_scaled_unit) return mag<1> / Rhs::mag * (lhs / Rhs::reference_unit); else - return detail::expr_divide(lhs, rhs); + return detail::expr_divide(lhs, rhs); } [[nodiscard]] MP_UNITS_CONSTEVAL Unit auto inverse(Unit auto u) { return one / u; } @@ -559,7 +559,7 @@ template else if constexpr (detail::is_specialization_of_scaled_unit) return scaled_unit(U::mag), decltype(pow(U::reference_unit))>{}; else if constexpr (detail::is_specialization_of_derived_unit) - return detail::expr_pow(u); + return detail::expr_pow(u); else if constexpr (Den == 1) return derived_unit>{}; else