diff options
Diffstat (limited to 'src/unit_reduction.h')
-rw-r--r-- | src/unit_reduction.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/unit_reduction.h b/src/unit_reduction.h new file mode 100644 index 0000000..d9060d2 --- /dev/null +++ b/src/unit_reduction.h @@ -0,0 +1,133 @@ +#pragma once + +#include <cstdint> +#include <type_traits> + +namespace kelun { +template<typename... T> +constexpr bool is_always_false = false; + +template<typename UnitType, int64_t Exponent> +struct unit_component; + +template<typename StorageT, typename... T> +class unit; + +namespace impl { + +template<typename T, typename U> +class unit_matching; + +template<typename... T> +class unit_redux_list { + static_assert(sizeof...(T) == 0, "Template type not supported"); + + using reduced_typed = unit_redux_list<>; +}; + +template<typename T0, int64_t E0, typename... TL, int64_t... EL> +struct unit_redux_list<unit_component<T0,E0>, unit_component<TL,EL>...> { + using reduced_type = typename unit_matching<unit_redux_list<unit_component<T0,E0>, unit_component<TL,EL>...>, unit_redux_list<>>::type; +}; + +template<typename T, typename U, typename V> +class unit_matching_reduce { +public: + static_assert(is_always_false<T, U, V>, "Template type not supported"); +}; + +template<typename T, int64_t E, typename T0, int64_t E0, typename... TL, int64_t... EL, typename... TR, int64_t... ER> +class unit_matching_reduce<unit_component<T,E>, unit_redux_list<unit_component<T0,E0>,unit_component<TL,EL>...>, unit_redux_list<unit_component<TR,ER>...>> { +public: + static constexpr bool is_same = std::is_same_v<T,T0>; + + using match_reduce_type = typename std::conditional<is_same, unit_component<T,E+E0>, unit_component<T,E>>::type; + using match_reduce_unit_redux_list = typename std::conditional<is_same, unit_redux_list<unit_component<TR,ER>...>, unit_redux_list<unit_component<TR,ER>..., unit_component<T0,E0>>>::type; + + using value_type = typename unit_matching_reduce<match_reduce_type, unit_redux_list<unit_component<TL,EL>...>, match_reduce_unit_redux_list>::value_type; + using unit_redux_list_type = typename unit_matching_reduce<match_reduce_type, unit_redux_list<unit_component<TL,EL>...>, match_reduce_unit_redux_list>::unit_redux_list_type; + + static constexpr int64_t value_num = unit_matching_reduce<match_reduce_type, unit_redux_list<unit_component<TL,EL>...>, match_reduce_unit_redux_list>::value_num; +}; + +template<typename T, int64_t E, typename... TR, int64_t... ER> +class unit_matching_reduce<unit_component<T,E>, unit_redux_list<>, unit_redux_list<unit_component<TR,ER>...>> { +public: + using value_type = unit_component<T,E>; + using unit_redux_list_type = unit_redux_list<unit_component<TR,ER>...>; + + static constexpr int64_t value_num = E; +}; + +template<typename T, typename U> +class unit_matching { + static_assert(is_always_false<T, U>, "Template type not supported"); +}; + +template<typename... T, int64_t... E> +class unit_matching<unit_redux_list<>,unit_redux_list<unit_component<T,E>...>> { +public: + using type = unit_redux_list<unit_component<T,E>...>; + +}; + +template<typename T0, int64_t E0, typename... TL, int64_t... EL, typename... TR, int64_t... ER> +class unit_matching<unit_redux_list<unit_component<T0,E0>,unit_component<TL,EL>...>, unit_redux_list<unit_component<TR,ER>...>> { +public: + using reduced_value_type = typename unit_matching_reduce<unit_component<T0,E0>, unit_redux_list<unit_component<TL,EL>...>, unit_redux_list<>>::value_type; + using reduced_unit_redux_list_type = typename unit_matching_reduce<unit_component<T0,E0>, unit_redux_list<unit_component<TL,EL>...>, unit_redux_list<>>::unit_redux_list_type; + + static constexpr int64_t reduced_value_num = unit_matching_reduce<unit_component<T0,E0>, unit_redux_list<unit_component<TL,EL>...>, unit_redux_list<>>::value_num; + using reduced_result_unit_redux_list = typename std::conditional<reduced_value_num == 0, unit_redux_list<unit_component<TR,ER>...>, unit_redux_list<unit_component<TR,ER>...,reduced_value_type>>::type; + + using type = typename unit_matching<reduced_unit_redux_list_type, reduced_result_unit_redux_list>::type; +}; + +template<typename List, typename StorageT> +class unit_matching_add_storage { +public: + static_assert(is_always_false<List,StorageT>, "Template type not supported"); +}; + +template<typename StorageT, typename... UnitTypes, int64_t... UnitExponents> +class unit_matching_add_storage<unit_redux_list<unit_component<UnitTypes,UnitExponents>...>, StorageT> { +public: + using type = unit<StorageT, unit_component<UnitTypes,UnitExponents>...>; +}; + +} + +template<typename StorageT, typename... T> +class unit_reduction { + static_assert(is_always_false<StorageT,T...>, "Template type not supported"); +}; + +template<typename StorageT, typename... UnitT, int64_t... UnitE> +class unit_reduction<StorageT, unit_component<UnitT, UnitE>...> { +public: + using list_type = typename impl::unit_matching<impl::unit_redux_list<unit_component<UnitT, UnitE>...>, impl::unit_redux_list<>>::type; + using type = typename impl::unit_matching_add_storage<list_type, StorageT>::type; +}; + +template<typename StorageT, typename... T> +class unit_invert { + static_assert(is_always_false<StorageT, T...>, "Template type not supported"); +}; + +template<typename StorageT, typename... UnitT, int64_t... UnitE> +class unit_invert<StorageT, unit_component<UnitT, UnitE>...> { +public: + using type = unit<StorageT, unit_component<UnitT, -UnitE>...>; +}; + +template<typename T, typename U> +class unit_multiplication{ + static_assert(is_always_false<T, U>, "Template type not supported"); +}; + +template<typename StorageT, typename... UnitT, int64_t... UnitE, typename... UnitRhsT, int64_t... UnitRhsE> +class unit_multiplication<unit<StorageT, unit_component<UnitT,UnitE>...>, unit<StorageT, unit_component<UnitRhsT, UnitRhsE>...>> { +public: + using type = typename unit_reduction<StorageT, unit_component<UnitT,UnitE>..., unit_component<UnitRhsT, UnitRhsE>...>::type; +}; +} |