summaryrefslogtreecommitdiff
path: root/c++/unit_reduction.hpp
blob: df02a4dd53876df0905b99c30e8ddf19dfc45a53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#pragma once

#include <cstdint>
#include <type_traits>

namespace kel {
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;
};
}