Stratax 0.3.1
Loading...
Searching...
No Matches
Promotion.hpp
1#pragma once
2
3#include <concepts>
4#include <cstddef>
5#include <type_traits>
6
7#include <stratax/core/dtypes/DTypeTraits.hpp>
8
9namespace stratax::core {
10
20template<typename L, typename R>
21struct Promote;
22
26template<typename T>
27requires requires
28{
29 typename DTypeTraits<T>::type;
31}
32struct Promote<T, T>
33{
34 using type = T;
35};
36
40template<typename L, typename R>
41requires (
42 DTypeTraits<L>::kind == DTypeKind::SignedInteger &&
43 DTypeTraits<R>::kind == DTypeKind::SignedInteger
44)
46{
47 using type = std::conditional_t<
49 L,
50 R
51 >;
52};
53
57template<typename L, typename R>
58requires (
59 DTypeTraits<L>::kind == DTypeKind::UnsignedInteger &&
60 DTypeTraits<R>::kind == DTypeKind::UnsignedInteger
61)
62struct Promote<L, R>
63{
64 using type = std::conditional_t<
66 L,
67 R
68 >;
69};
70
78template<typename L, typename R>
79requires (
80 (DTypeTraits<L>::kind == DTypeKind::SignedInteger &&
81 DTypeTraits<R>::kind == DTypeKind::UnsignedInteger) ||
82 (DTypeTraits<L>::kind == DTypeKind::UnsignedInteger &&
83 DTypeTraits<R>::kind == DTypeKind::SignedInteger)
84)
85struct Promote<L, R>
86{
87private:
88 using signed_type = std::conditional_t<
89 DTypeTraits<L>::kind == DTypeKind::SignedInteger,
90 L,
91 R
92 >;
93
94 using unsigned_type = std::conditional_t<
95 DTypeTraits<L>::kind == DTypeKind::UnsignedInteger,
96 L,
97 R
98 >;
99
100 static constexpr std::size_t signed_bits =
101 DTypeTraits<signed_type>::bits;
102
103 static constexpr std::size_t unsigned_bits =
104 DTypeTraits<unsigned_type>::bits;
105
106 /*
107 * An N-bit unsigned integer requires N+1 bits in a signed
108 * representation to preserve its complete range.
109 */
110 static constexpr std::size_t required_bits =
111 signed_bits > unsigned_bits
112 ? signed_bits
113 : unsigned_bits + 1;
114
115public:
116 using type = std::conditional_t<
117 (required_bits <= 8),
118 dtype::int8,
119 std::conditional_t<
120 (required_bits <= 16),
121 dtype::int16,
122 std::conditional_t<
123 (required_bits <= 32),
124 dtype::int32,
125 std::conditional_t<
126 (required_bits <= 64),
127 dtype::int64,
128 dtype::float64
129 >
130 >
131 >
132 >;
133};
134
142template<typename L, typename R>
143requires (
144 (
145 (DTypeTraits<L>::kind == DTypeKind::SignedInteger ||
146 DTypeTraits<L>::kind == DTypeKind::UnsignedInteger) &&
147 DTypeTraits<R>::kind == DTypeKind::Floating
148 ) ||
149 (
150 DTypeTraits<L>::kind == DTypeKind::Floating &&
151 (DTypeTraits<R>::kind == DTypeKind::SignedInteger ||
152 DTypeTraits<R>::kind == DTypeKind::UnsignedInteger)
153 )
154)
155struct Promote<L, R>
156{
157private:
158 using integer_type = std::conditional_t<
159 DTypeTraits<L>::kind == DTypeKind::SignedInteger ||
160 DTypeTraits<L>::kind == DTypeKind::UnsignedInteger,
161 L,
162 R
163 >;
164
165 using floating_type = std::conditional_t<
166 DTypeTraits<L>::kind == DTypeKind::Floating,
167 L,
168 R
169 >;
170
171 static constexpr int integer_digits =
172 DTypeTraits<integer_type>::digits;
173
174 static constexpr int floating_digits =
175 DTypeTraits<floating_type>::digits;
176
177public:
178 using type = std::conditional_t<
179 (integer_digits <= floating_digits),
180 floating_type,
181 std::conditional_t<
182 std::same_as<floating_type, dtype::float32>,
183 dtype::float64,
184 floating_type
185 >
186 >;
187};
188
193template<typename L, typename R>
194requires (
195 DTypeTraits<L>::kind == DTypeKind::Floating &&
196 DTypeTraits<R>::kind == DTypeKind::Floating
197)
198struct Promote<L, R>
199{
200 using type = std::conditional_t<
201 (DTypeTraits<L>::rank >= DTypeTraits<R>::rank),
202 L,
203 R
204 >;
205};
206
210template<typename L, typename R>
211requires (
212 DTypeTraits<L>::kind == DTypeKind::Complex &&
213 DTypeTraits<R>::kind == DTypeKind::Complex
214)
215struct Promote<L, R>
216{
217private:
218 using left_component =
219 complex_component_t<L>;
220
221 using right_component =
222 complex_component_t<R>;
223
224 using promoted_component =
225 typename Promote<left_component, right_component>::type;
226
227public:
228 using type =
229 complex_from_real_t<promoted_component>;
230};
231
239template<typename L, typename R>
240requires (
241 (
242 (DTypeTraits<L>::kind == DTypeKind::SignedInteger ||
243 DTypeTraits<L>::kind == DTypeKind::UnsignedInteger ||
244 DTypeTraits<L>::kind == DTypeKind::Floating) &&
245 DTypeTraits<R>::kind == DTypeKind::Complex
246 ) ||
247 (
248 DTypeTraits<L>::kind == DTypeKind::Complex &&
249 (DTypeTraits<R>::kind == DTypeKind::SignedInteger ||
250 DTypeTraits<R>::kind == DTypeKind::UnsignedInteger ||
251 DTypeTraits<R>::kind == DTypeKind::Floating)
252 )
253)
254struct Promote<L, R>
255{
256private:
257 using real_type = std::conditional_t<
258 DTypeTraits<L>::kind == DTypeKind::Complex,
259 R,
260 L
261 >;
262
263 using complex_type = std::conditional_t<
264 DTypeTraits<L>::kind == DTypeKind::Complex,
265 L,
266 R
267 >;
268
269 using component_type =
270 complex_component_t<complex_type>;
271
272 using promoted_component =
273 typename Promote<real_type, component_type>::type;
274
275public:
276 using type =
277 complex_from_real_t<promoted_component>;
278};
279
285template<typename L, typename R>
286using promote_t = typename Promote<
287 std::remove_cvref_t<L>,
288 std::remove_cvref_t<R>
289>::type;
290
291} // namespace stratax::core
Provides compile-time metadata for a supported Stratax dtype.
Determines the promoted dtype for two Stratax dtypes.
Definition Promotion.hpp:21