1#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_SCALED_UNIT_HPP_
2#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_SCALED_UNIT_HPP_
6#include "arene/base/constraints/constraints.hpp"
7#include "arene/base/math/float_properties.hpp"
8#include "arene/base/stdlib_choice/cstdint.hpp"
9#include "arene/base/stdlib_choice/enable_if.hpp"
10#include "arene/base/stdlib_choice/initializer_list.hpp"
11#include "arene/base/stdlib_choice/is_floating_point.hpp"
12#include "arene/base/stdlib_choice/ratio.hpp"
13#include "arene/base/type_info/type_name_string.hpp"
14#include "arene/base/type_list/index_of.hpp"
15#include "arene/base/type_list/remove_nth.hpp"
16#include "arene/base/type_list/sort.hpp"
17#include "arene/base/type_traits/is_one_of.hpp"
18#include "arene/base/units/is_unit.hpp"
19#include "arene/base/units/quantity_unit.hpp"
24namespace scaled_unit_detail {
28template <
typename Type>
29extern constexpr bool is_ratio_v =
false;
34template <std::intmax_t Numerator, std::intmax_t Denominator>
35extern constexpr bool is_ratio_v<std::ratio<Numerator, Denominator>> =
true;
39template <
typename Type,
typename = constraints<>>
40extern constexpr bool is_identity_ratio_v =
false;
44template <
typename Type>
45extern constexpr bool is_identity_ratio_v<Type, constraints<std::enable_if_t<is_ratio_v<Type>>>> =
46 (Type::num == Type::den);
51template <
typename Type,
typename = constraints<>>
52extern constexpr bool is_floating_point_wrapper_scale_v =
false;
57template <
typename Type>
58extern constexpr bool is_floating_point_wrapper_scale_v<
61 std::enable_if_t<std::is_floating_point<
decltype(Type::value)>::value>,
62 std::enable_if_t<isnormal(Type::value)>>> =
true;
66template <
typename Type>
67extern constexpr bool is_valid_scale_v = is_floating_point_wrapper_scale_v<Type> || is_ratio_v<Type>;
71template <
typename Type>
72class inverse_unit_scale {
76 static constexpr double value{1. / Type::value};
82template <
typename Type,
typename = constraints<>>
83class inverse_unit_scale_helper {
84 static_assert(is_floating_point_wrapper_scale_v<Type>,
"The type being inverted must be a floating point wrapper");
88 using type = inverse_unit_scale<Type>;
94template <
typename BaseUnit,
typename Scale>
95class scaled_unit_impl :
public quantity_unit<scaled_unit_impl<BaseUnit, Scale>,
typename BaseUnit::unit_kind_type> {
98 using scale_factor = Scale;
101 using is_implicit =
void;
108template <
typename BaseUnit,
typename Scale,
typename = constraints<>>
109class scaled_unit_helper {
110 static_assert(is_unit_v<BaseUnit>,
"The supplied BaseUnit must be a valid quantity unit");
111 static_assert(is_valid_scale_v<Scale>,
"The scale factor must be a ratio or a class wrapping a floating point scale");
115 using type = scaled_unit_impl<BaseUnit, Scale>;
128template <
typename Type>
131namespace scaled_unit_detail {
137template <
typename Type, constraints<std::enable_if_t<std::is_floating_point<
decltype(Type::value)>::value>> =
nullptr>
138constexpr auto scale_value()
noexcept ->
double {
146template <
typename Type, constraints<std::enable_if_t<is_ratio_v<Type>>> =
nullptr>
147constexpr auto scale_value()
noexcept ->
double {
148 return static_cast<
double>(Type::num) /
static_cast<
double>(Type::den);
154inline constexpr auto combined_scale_value(std::initializer_list<
double> values)
noexcept ->
double {
156 for (
auto const elem : values) {
165template <
typename... Scales>
166class combined_scales {
170 static constexpr double value{combined_scale_value({scale_value<Scales>()...})};
178template <
typename Scales>
179class canonicalize_scale {
189class canonicalize_scale<combined_scales<>> {
192 using type = std::ratio<1, 1>;
199template <
typename Scale>
200class canonicalize_scale<combined_scales<Scale>> {
213template <
typename LhsScale,
typename RhsScale>
214class scale_sorts_before {
219 static constexpr bool value{
220 !is_ratio_v<RhsScale> && (is_ratio_v<LhsScale> || (type_name_v<LhsScale> < type_name_v<RhsScale>))
232template <
typename... Scales>
233class canonicalize_scale<combined_scales<Scales...>> {
236 using type = type_lists::sort_t<combined_scales<Scales...>, scale_sorts_before>;
242template <
typename Scale1,
typename Scale2,
typename = constraints<>>
243class combine_scales_helper {
246 using type = combined_scales<Scale1, Scale2>;
252template <
typename Scale1,
typename Scale2>
253using combine_scales_t =
typename canonicalize_scale<
typename combine_scales_helper<Scale1, Scale2>::type>::type;
260template <
typename Scale1,
typename Scale2>
261class combine_scales_helper<
264 constraints<std::enable_if_t<is_ratio_v<Scale1>>, std::enable_if_t<is_ratio_v<Scale2>>>> {
267 using type = std::ratio_multiply<Scale1, Scale2>;
276template <
typename Scale1,
typename Scale2>
277class combine_scales_helper<
280 constraints<std::enable_if_t<!is_ratio_v<Scale1>>, std::enable_if_t<is_ratio_v<Scale2>>>> {
283 using type = combine_scales_t<Scale2, Scale1>;
291template <
typename... Scales1,
typename Scale2>
292class combine_scales_helper<
293 combined_scales<Scales1...>,
296 std::enable_if_t<!is_ratio_v<Scale2>>,
297 std::enable_if_t<!is_one_of_v<inverse_unit_scale_t<Scale2>, Scales1...>>>> {
300 using type = combined_scales<Scales1..., Scale2>;
308template <
typename... Scales1,
typename Scale2>
309class combine_scales_helper<
310 combined_scales<Scales1...>,
313 std::enable_if_t<!is_ratio_v<Scale2>>,
314 std::enable_if_t<is_one_of_v<inverse_unit_scale_t<Scale2>, Scales1...>>>> {
317 using type = type_lists::remove_nth_t<
318 combined_scales<Scales1...>,
319 type_lists::index_of_v<combined_scales<Scales1...>, inverse_unit_scale_t<Scale2>>>;
328template <
typename Scale1,
typename FirstScale2,
typename... OtherScales2>
329class combine_scales_helper<
331 combined_scales<FirstScale2, OtherScales2...>,
333 std::enable_if_t<is_ratio_v<Scale1>>,
334 std::enable_if_t<!is_identity_ratio_v<Scale1>>,
335 std::enable_if_t<!is_ratio_v<FirstScale2>>>> {
338 using type = combined_scales<Scale1, FirstScale2, OtherScales2...>;
347template <
typename Scale1,
typename FirstScale2,
typename... OtherScales2>
348class combine_scales_helper<
350 combined_scales<FirstScale2, OtherScales2...>,
351 constraints<std::enable_if_t<is_ratio_v<Scale1>>, std::enable_if_t<is_ratio_v<FirstScale2>>>> {
354 using type = combine_scales_t<std::ratio_multiply<Scale1, FirstScale2>, combined_scales<OtherScales2...>>;
362template <
typename Scale1,
typename... Scales2>
363class combine_scales_helper<
365 combined_scales<Scales2...>,
366 constraints<std::enable_if_t<is_identity_ratio_v<Scale1>>>> {
369 using type = combined_scales<Scales2...>;
376template <
typename BaseUnit,
typename BaseScale,
typename Scale>
377class scaled_unit_helper<
378 scaled_unit_impl<BaseUnit, BaseScale>,
380 constraints<std::enable_if_t<!is_identity_ratio_v<Scale>>>> {
381 static_assert(is_valid_scale_v<Scale>,
"The scale factor must be a ratio or a class wrapping a floating point scale");
385 using type = scaled_unit<BaseUnit, combine_scales_t<BaseScale, Scale>>;
393template <
typename BaseUnit,
typename Scale>
394class scaled_unit_helper<BaseUnit, Scale, constraints<std::enable_if_t<is_identity_ratio_v<Scale>>>> {
395 static_assert(is_unit_v<BaseUnit>,
"The supplied BaseUnit must be a valid quantity unit");
396 static_assert(is_valid_scale_v<Scale>,
"The scale factor must be a ratio or a class wrapping a floating point scale");
400 using type = BaseUnit;
405template <
typename Type>
406class inverse_unit_scale_helper<Type, constraints<std::enable_if_t<is_ratio_v<Type>>>> {
409 using type = std::ratio<Type::den, Type::num>;
414template <
typename Type>
415class inverse_unit_scale_helper<inverse_unit_scale<Type>> {
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10