refactor: V2 design update

This commit is contained in:
Mateusz Pusz committed 2022-10-06 23:43:01 +01:00
1 parent 4411b8ea6d
commit 4a49bdda05
146 files changed
+3076 -13622

No files matched your search

+145 -41
View File
@@ -75,6 +75,12 @@ namespace detail {
template<Magnitude auto M, typename U>
void to_base_scaled_unit(const volatile scaled_unit<M, U>*);
template<typename T>
inline constexpr bool is_specialization_of_scaled_unit = false;
template<Magnitude auto M, typename U>
inline constexpr bool is_specialization_of_scaled_unit<scaled_unit<M, U>> = true;
} // namespace detail
/**
@@ -98,14 +104,106 @@ concept NamedUnit = Unit<T> && detail::is_named<T>;
template<Unit auto U1, Unit auto U2>
struct same_unit_reference : is_same<typename decltype(U1)::reference, typename decltype(U2)::reference> {};
namespace detail {
template<Unit U1, Unit U2>
struct unit_less : std::bool_constant<type_name<U1>() < type_name<U2>()> {};
template<typename T1, typename T2>
using type_list_of_unit_less = expr_less<T1, T2, unit_less>;
/**
* @brief Unpacks the list of potentially derived dimensions to a list containing only base dimensions
*
* @tparam Es Exponents of potentially derived dimensions
*/
// template<typename NumList, typename DenList>
// struct unit_extract;
// template<>
// struct unit_extract<type_list<>, type_list<>> {
// using num = type_list<>;
// using den = type_list<>;
// };
// template<typename T, typename... NRest, typename... Dens>
// requires BaseUnit<T> || BaseUnit<typename T::factor>
// struct unit_extract<type_list<T, NRest...>, type_list<Dens...>> {
// using impl = unit_extract<type_list<NRest...>, type_list<Dens...>>;
// using num = type_list_push_front<typename impl::num, T>;
// using den = TYPENAME impl::den;
// };
// template<typename T, typename... DRest>
// requires BaseUnit<T> || BaseUnit<typename T::factor>
// struct unit_extract<type_list<>, type_list<T, DRest...>> {
// using impl = unit_extract<type_list<>, type_list<DRest...>>;
// using num = TYPENAME impl::num;
// using den = type_list_push_front<typename impl::den, T>;
// };
// template<DerivedUnit T, typename... NRest, typename... Dens>
// struct unit_extract<type_list<T, NRest...>, type_list<Dens...>> :
// unit_extract<type_list_push_back<typename T::normalized_num, NRest...>,
// type_list_push_back<typename T::normalized_den, Dens...>> {};
// template<DerivedUnit T, int... Ints, typename... NRest, typename... Dens>
// struct unit_extract<type_list<power<T, Ints...>, NRest...>, type_list<Dens...>> :
// unit_extract<type_list_push_back<typename expr_power<typename T::normalized_num, power<T, Ints...>::num,
// power<T, Ints...>::den>::type,
// NRest...>,
// type_list_push_back<typename expr_power<typename T::normalized_den, power<T, Ints...>::num,
// power<T, Ints...>::den>::type,
// Dens...>> {};
// template<DerivedUnit T, typename... DRest>
// struct unit_extract<type_list<>, type_list<T, DRest...>> :
// unit_extract<typename T::normalized_den, type_list_push_back<typename T::normalized_num, DRest...>> {};
// template<DerivedUnit T, int... Ints, typename... DRest>
// struct unit_extract<type_list<>, type_list<power<T, Ints...>, DRest...>> :
// unit_extract<typename expr_power<typename T::normalized_den, power<T, Ints...>::num, power<T,
// Ints...>::den>::type,
// type_list_push_back<typename expr_power<typename T::normalized_num, power<T, Ints...>::num,
// power<T, Ints...>::den>::type,
// DRest...>> {};
/**
* @brief Converts user provided derived dimension specification into a valid units::normalized_dimension definition
*
* User provided definition of a derived dimension may contain the same base dimension repeated more than once on the
* list possibly hidden in other derived units provided by the user. The process here should:
* 1. Extract derived dimensions into exponents of base dimensions.
* 2. Sort the exponents so the same dimensions are placed next to each other.
* 3. Consolidate contiguous range of exponents of the same base dimensions to a one (or possibly zero) exponent for
* this base dimension.
*/
template<typename OneTypeBase, typename... Us>
struct normalized_unit : detail::expr_fractions<OneTypeBase, Us...> {
// private:
// using base = detail::expr_fractions<OneTypeBase, Us...>;
// using extracted = unit_extract<typename base::num, typename base::den>;
// using num_list = expr_consolidate<type_list_sort<typename extracted::num, type_list_of_unit_less>>;
// using den_list = expr_consolidate<type_list_sort<typename extracted::den, type_list_of_unit_less>>;
// using simple = expr_simplify<num_list, den_list, type_list_of_unit_less>;
// public:
// using normalized_num = TYPENAME simple::num;
// using normalized_den = TYPENAME simple::den;
};
} // namespace detail
// TODO add checking for `per` and power elements as well
template<typename T>
concept UnitSpec = Unit<T> || is_specialization_of<T, per> || detail::is_specialization_of_power<T>;
// User should not instantiate this type!!!
// It should not be exported from the module
template<UnitSpec... Us>
struct derived_unit : detail::expr_fractions<derived_unit<>, Us...>, scaled_unit<mag<1>, derived_unit<Us...>> {};
// : detail::normalized_dimension<derived_dimension<>, Ds...> {};
struct derived_unit : detail::normalized_unit<derived_unit<>, Us...>, scaled_unit<mag<1>, derived_unit<Us...>> {
static constexpr bool is_base = false;
};
/**
* @brief Unit one
@@ -129,28 +227,13 @@ struct named_unit;
template<basic_symbol_text Symbol>
struct named_unit<Symbol> : scaled_unit<mag<1>, named_unit<Symbol>> {
static constexpr auto symbol = Symbol;
static constexpr bool is_base = true;
};
template<basic_symbol_text Symbol, auto U>
requires is_specialization_of<std::remove_const_t<decltype(U)>, derived_unit>
template<basic_symbol_text Symbol, Unit auto U>
struct named_unit<Symbol, U> : decltype(U) {
static constexpr auto symbol = Symbol;
};
/**
* @brief A named scaled unit
*
* Defines a new named unit that is a scaled version of another unit.
* A named unit may be composed with a prefix to create a prefixed_unit.
*
* @tparam Symbol a short text representation of the unit
* @tparam M the Magnitude by which to scale U
* @tparam U a reference unit to scale
*/
template<basic_symbol_text Symbol, Magnitude auto M, Unit auto U>
struct named_scaled_unit : scaled_unit<M* decltype(U)::mag, typename decltype(U)::reference> {
static constexpr auto symbol = Symbol;
static constexpr bool is_base = decltype(U)::is_base;
};
/**
@@ -164,15 +247,12 @@ struct named_scaled_unit : scaled_unit<M* decltype(U)::mag, typename decltype(U)
* @tparam P prefix to be appied to the reference unit
* @tparam U reference unit
*/
// template<typename Child, Prefix P, NamedUnit U>
// requires detail::can_be_prefixed<U>
// struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::mag * U::mag, typename U::reference>> {
// static constexpr auto symbol = P::symbol + U::symbol;
// };
template<basic_symbol_text Symbol, Magnitude auto M, NamedUnit auto U>
struct prefixed_unit : scaled_unit<M* decltype(U)::mag, typename decltype(U)::reference> {};
// requires detail::can_be_prefixed<U>
struct prefixed_unit : scaled_unit<M* decltype(U)::mag, typename decltype(U)::reference> {
// static constexpr auto symbol = symbol + decltype(U)::symbol;
static constexpr bool is_base = decltype(U)::is_base;
};
/**
* @brief A coherent unit of a derived quantity
@@ -187,11 +267,11 @@ struct prefixed_unit : scaled_unit<M* decltype(U)::mag, typename decltype(U)::re
namespace detail {
template<basic_symbol_text Symbol>
void is_named_impl(const volatile named_unit<Symbol>*);
template<basic_symbol_text Symbol, auto... Args>
void is_named_impl(const volatile named_unit<Symbol, Args...>*);
template<basic_symbol_text Symbol, Magnitude auto M, auto U>
void is_named_impl(const volatile named_scaled_unit<Symbol, M, U>*);
template<basic_symbol_text Symbol, Magnitude auto M, NamedUnit auto U>
void is_named_impl(const volatile prefixed_unit<Symbol, M, U>*);
template<Unit U>
inline constexpr bool is_named<U> = requires(U * u) { is_named_impl(u); };
@@ -211,15 +291,20 @@ inline constexpr bool is_named<U> = requires(U * u) { is_named_impl(u); };
// template<Magnitude auto M, typename U>
// inline constexpr bool can_be_prefixed<scaled_unit<M, U>> = can_be_prefixed<typename U::reference>;
template<Unit U1, Unit U2>
struct unit_less : std::bool_constant<type_name<U1>() < type_name<U2>()> {};
template<typename T1, typename T2>
using type_list_of_unit_less = expr_less<T1, T2, unit_less>;
} // namespace detail
template<Magnitude M, Unit U>
[[nodiscard]] consteval Unit auto operator*(M mag, U)
{
return scaled_unit<mag, U>{};
}
template<Magnitude M1, Magnitude auto M2, typename U>
[[nodiscard]] consteval Unit auto operator*(M1 mag, scaled_unit<M2, U>)
{
return scaled_unit<mag * M2, U>{};
}
template<Unit U1, Unit U2>
[[nodiscard]] consteval Unit auto operator*(U1, U2)
{
@@ -242,9 +327,16 @@ template<Unit U>
template<Unit U1, Unit U2>
[[nodiscard]] consteval bool operator==(U1, U2)
{
return false;
return is_same_v<U1, U2>;
}
template<Unit U1, Unit U2>
[[nodiscard]] consteval bool equivalent(U1, U2)
{
return true; // TODO implement this
}
// template<BaseDimension D1, BaseDimension D2>
// constexpr bool operator==(D1, D2)
// {
@@ -274,4 +366,16 @@ template<Unit U1, Unit U2>
// std::is_same_v<typename D1::normalized_den, typename D2::normalized_den>;
// }
template<Unit U>
struct square_ : decltype(U{} * U{}) {};
template<Unit auto U>
inline constexpr square_<std::remove_const_t<decltype(U)>> square;
template<Unit U>
struct cubic_ : decltype(U{} * U{} * U{}) {};
template<Unit auto U>
inline constexpr cubic_<std::remove_const_t<decltype(U)>> cubic;
} // namespace units