4#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_COMBINE_KINDS_HPP_
5#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_COMBINE_KINDS_HPP_
7#include "arene/base/constraints/constraints.hpp"
8#include "arene/base/stdlib_choice/cstddef.hpp"
9#include "arene/base/stdlib_choice/cstdint.hpp"
10#include "arene/base/stdlib_choice/enable_if.hpp"
11#include "arene/base/stdlib_choice/integral_constant.hpp"
12#include "arene/base/stdlib_choice/is_same.hpp"
13#include "arene/base/type_info/type_name_string.hpp"
14#include "arene/base/type_list/apply_all.hpp"
15#include "arene/base/type_list/sort.hpp"
16#include "arene/base/type_list/type_list.hpp"
17#include "arene/base/type_traits/all_of.hpp"
18#include "arene/base/type_traits/conditional.hpp"
19#include "arene/base/type_traits/is_instantiation_of.hpp"
20#include "arene/base/units/base_kind_set.hpp"
21#include "arene/base/units/detail/is_bipartite_match.hpp"
22#include "arene/base/units/detail/missing.hpp"
23#include "arene/base/units/detail/sum.hpp"
24#include "arene/base/units/explicit_base_set.hpp"
25#include "arene/base/units/is_base_quantity_kind.hpp"
26#include "arene/base/units/is_kind_with_exponent.hpp"
27#include "arene/base/units/is_quantity_kind.hpp"
28#include "arene/base/units/is_unit.hpp"
29#include "arene/base/units/kind_with_exponent_fwd.hpp"
30#include "arene/base/units/quantity_kind.hpp"
31#include "arene/base/units/quantity_unit.hpp"
32#include "arene/base/units/scaled_unit.hpp"
33#include "arene/base/units/unit_kind.hpp"
38namespace combine_kinds_detail {
42template <
typename Kind>
43class unpack_unit_exponent_helper {
51template <
typename Kind>
52class unpack_unit_exponent_helper<units_detail::quantity_kind_with_exponent<Kind, 1, 0>> {
60template <
typename Kind>
61using unpack_unit_exponent_t =
typename unpack_unit_exponent_helper<Kind>::type;
65template <
typename CombinedKind,
typename = constraints<>>
66class combine_kind_base_helper {
69 using type = quantity_kind<CombinedKind>;
74template <
typename... BaseKinds>
75class combined_quantity_kind :
public combine_kind_base_helper<combined_quantity_kind<BaseKinds...>>::type {
76 static_assert(all_of_v<is_quantity_kind_v<BaseKinds>...>,
"All combined elements must be valid quantity kinds");
81 using is_implicit =
void;
86template <
typename Kind>
87class normalize_for_combining_helper {
90 using type = units_detail::quantity_kind_with_exponent<Kind, 1, 0>;
100template <
typename Kind>
101using normalize_for_combining_t =
typename normalize_for_combining_helper<Kind>::type;
107template <
typename Kind, units_detail::exponent_t PositiveExponent, units_detail::exponent_t NegativeExponent>
108class normalize_for_combining_helper<
109 units_detail::quantity_kind_with_exponent<Kind, PositiveExponent, NegativeExponent>> {
112 using type = units_detail::quantity_kind_with_exponent<Kind, PositiveExponent, NegativeExponent>;
123template <
typename BaseUnit,
typename Scale>
124class normalize_for_combining_helper<scaled_unit_detail::scaled_unit_impl<BaseUnit, Scale>> {
127 using type = units_detail::quantity_kind_with_exponent<
128 units_detail::explicit_base_barrier<scaled_unit_detail::scaled_unit_impl<BaseUnit, Scale>>,
135template <
typename... Kinds>
136class normalize_for_combining_helper<combined_quantity_kind<Kinds...>> {
139 using type = combined_quantity_kind<normalize_for_combining_t<Kinds>...>;
146template <
typename LhsKind,
typename RhsKind>
147class kind_sorts_before {
152 static constexpr bool value{type_name_v<LhsKind> < type_name_v<RhsKind>};
168 units_detail::exponent_t LhsPositiveExponent,
169 units_detail::exponent_t LhsNegativeExponent,
171 units_detail::exponent_t RhsPositiveExponent,
172 units_detail::exponent_t RhsNegativeExponent>
173class kind_sorts_before<
174 units_detail::quantity_kind_with_exponent<LhsKind, LhsPositiveExponent, LhsNegativeExponent>,
175 units_detail::quantity_kind_with_exponent<RhsKind, RhsPositiveExponent, RhsNegativeExponent>> {
180 static constexpr bool value{
181 (type_name_v<LhsKind> < type_name_v<RhsKind>) ||
182 ((type_name_v<LhsKind> == type_name_v<RhsKind>)&&(
183 (LhsPositiveExponent < RhsPositiveExponent) ||
184 ((LhsPositiveExponent == RhsPositiveExponent) && (LhsNegativeExponent < RhsNegativeExponent))
193template <
typename Kind>
194class canonicalize_post_combining {
202template <
typename... Kinds>
203class canonicalize_post_combining<combined_quantity_kind<Kinds...>> {
206 using type = combined_quantity_kind<
typename canonicalize_post_combining<Kinds>::type...>;
211template <
typename Kind>
212class canonicalize_post_combining<combined_quantity_kind<Kind>> :
public canonicalize_post_combining<Kind> {};
215template <
typename Kind, units_detail::exponent_t PositiveExponent, units_detail::exponent_t NegativeExponent>
216class canonicalize_post_combining<units_detail::quantity_kind_with_exponent<Kind, PositiveExponent, NegativeExponent>> {
219 using type = conditional_t<
220 (PositiveExponent == 1 && NegativeExponent == 0),
221 typename canonicalize_post_combining<Kind>::type,
222 units_detail::quantity_kind_with_exponent<
223 typename canonicalize_post_combining<Kind>::type,
232template <
typename Kind>
233class canonicalize_post_combining<units_detail::explicit_base_barrier<Kind>> {
242template <
typename... Kinds>
243class internal_combine_kinds {
245 struct explicit_base_set_union {
249 static constexpr auto value = units_detail::set_union(units_detail::explicit_base_set<Kinds>...);
256 using type = type_lists::apply_all_t<
258 units_detail::as_list_of_kinds_with_exponents_t<explicit_base_set_union>,
259 combine_kinds_detail::kind_sorts_before>,
260 combined_quantity_kind>;
266template <
typename... Kinds>
267using internal_combine_kinds_t =
typename internal_combine_kinds<Kinds...>::type;
273template <
typename...
Kinds>
281namespace units_detail {
287template <
typename... BaseKinds, exponent_t PositiveExponent, exponent_t NegativeExponent>
288class kind_with_exponent_helper<
289 combine_kinds_detail::combined_quantity_kind<BaseKinds...>,
294 constraints<std::enable_if_t<!(PositiveExponent == 1 && NegativeExponent == 0)>>> {
298 combine_kinds_t<
typename kind_with_exponent_helper<BaseKinds, PositiveExponent, NegativeExponent>::type...>;
303namespace combine_kinds_detail {
309template <
typename... BaseKinds>
310class combine_kind_base_helper<
311 combined_quantity_kind<BaseKinds...>,
312 constraints<std::enable_if_t<all_of_v<is_unit_v<BaseKinds>...>>>> {
315 using type = quantity_unit<
316 combined_quantity_kind<BaseKinds...>,
317 combine_kinds_t<unit_kind_t<BaseKinds>...>>;
328 using type = units_detail::quantity_kind_with_exponent<Kind, 1, 0>;
337template <
class Kind, units_detail::exponent_t Positive, units_detail::exponent_t Negative>
338class with_exponent<units_detail::quantity_kind_with_exponent<Kind, Positive, Negative>> {
341 using type = units_detail::quantity_kind_with_exponent<Kind, Positive, Negative>;
346template <
typename Kind>
347using with_exponent_t =
typename with_exponent<Kind>::type;
351enum class polarity : std::uint8_t {
363template <polarity Sign,
class KindWithExponent>
364struct polarity_wrapper;
372template <
typename Kind, units_detail::exponent_t Positive, units_detail::exponent_t Negative>
373struct polarity_wrapper<polarity::negative, units_detail::quantity_kind_with_exponent<Kind, Positive, Negative>> {
375 static constexpr auto sign = polarity::negative;
378 static constexpr std::size_t count{Negative};
381 using quantity_kind_type = Kind;
390template <
typename Kind, units_detail::exponent_t Positive, units_detail::exponent_t Negative>
391struct polarity_wrapper<polarity::zero, units_detail::quantity_kind_with_exponent<Kind, Positive, Negative>> {
393 static constexpr auto sign = polarity::zero;
398 static constexpr std::size_t count{((Positive == 0) && (Negative == 0)) ? 1U : 0U};
401 using quantity_kind_type = Kind;
410template <
typename Kind, units_detail::exponent_t Positive, units_detail::exponent_t Negative>
411struct polarity_wrapper<polarity::positive, units_detail::quantity_kind_with_exponent<Kind, Positive, Negative>> {
413 static constexpr auto sign = polarity::positive;
416 static constexpr std::size_t count{Positive};
419 using quantity_kind_type = Kind;
429template <
typename Source,
typename Sink>
430using is_kind_sink = std::integral_constant<
432 ((Source::sign == Sink::sign) &&
433 (std::is_same<
typename Source::quantity_kind_type,
typename Sink::quantity_kind_type>::value ||
434 is_base_quantity_kind_of_v<
typename Sink::quantity_kind_type,
typename Source::quantity_kind_type>))>;
442template <polarity Sign,
typename Sources,
typename Sinks>
443extern constexpr auto has_pairwise_match_v = units_detail::missing{};
450template <
typename... Ts>
451class error_if_duplicate_types : Ts... {};
457template <polarity Sign,
typename... Sources,
typename... Sinks>
458extern constexpr bool has_pairwise_match_v<
460 type_list<Sources...>,
463 (error_if_duplicate_types<
typename Sources::quantity_kind_type...>{},
true) &&
464 (error_if_duplicate_types<
typename Sinks::quantity_kind_type...>{},
true) &&
465 (units_detail::sum({polarity_wrapper<Sign, with_exponent_t<Sources>>::count...}) ==
466 units_detail::sum({polarity_wrapper<Sign, with_exponent_t<Sinks>>::count...})) &&
467 units_detail::is_bipartite_match_v<
468 type_list<polarity_wrapper<Sign, with_exponent_t<Sources>>...>,
469 type_list<polarity_wrapper<Sign, with_exponent_t<Sinks>>...>,
475namespace is_base_quantity_kind_detail {
485template <
typename... BaseKinds,
typename... CheckKinds>
486extern constexpr bool is_base_quantity_kind_of_v<
487 combine_kinds_detail::combined_quantity_kind<BaseKinds...>,
488 combine_kinds_detail::combined_quantity_kind<CheckKinds...>,
492 combine_kinds_detail::combined_quantity_kind<BaseKinds...>,
493 combine_kinds_detail::combined_quantity_kind<CheckKinds...>>::value>>>
495 combine_kinds_detail::has_pairwise_match_v<
496 combine_kinds_detail::polarity::negative,
497 type_list<CheckKinds...>,
498 type_list<BaseKinds...>>
499 && combine_kinds_detail::has_pairwise_match_v<
500 combine_kinds_detail::polarity::zero,
501 type_list<CheckKinds...>,
502 type_list<BaseKinds...>>
503 && combine_kinds_detail::has_pairwise_match_v<
504 combine_kinds_detail::polarity::positive,
505 type_list<CheckKinds...>,
506 type_list<BaseKinds...>>
520 typename... CheckKinds>
521extern constexpr bool is_base_quantity_kind_of_v<
523 combine_kinds_detail::combined_quantity_kind<CheckKinds...>,
526 !is_instantiation_of_v<
528 combine_kinds_detail::combined_quantity_kind>>>>
530 is_base_quantity_kind_of_v<
531 combine_kinds_detail::combined_quantity_kind<BaseKind>,
532 combine_kinds_detail::combined_quantity_kind<CheckKinds...>>
544template <
typename... BaseKinds,
typename CheckKind>
545extern constexpr bool is_base_quantity_kind_of_v<
546 combine_kinds_detail::combined_quantity_kind<BaseKinds...>,
549 std::enable_if_t<units_detail::is_kind_with_exponent_v<CheckKind>>,
551 !is_base_quantity_kind_of_v<
552 combine_kinds_detail::combined_quantity_kind<BaseKinds...>,
553 typename CheckKind::parent_quantity_kind_type>>
556 is_base_quantity_kind_of_v<
557 combine_kinds_detail::combined_quantity_kind<BaseKinds...>,
558 combine_kinds_detail::combined_quantity_kind<CheckKind>>
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10