Stratax 0.2.0
Loading...
Searching...
No Matches
Bitwise.hpp
1#pragma once
2
3#include <stratax/core/Concepts.hpp>
5
6#include <functional>
7
14template<Array A>
16void require_same_bitwise_shape(const A& lhs, const A& rhs)
17{
18 stratax::core::validation::require_same_shape(
19 lhs,
20 rhs,
21 "Bitwise operands must have the same shape.");
22}
23
34template<Array A, typename Op>
36A binary_bitwise_op(const A& lhs, const A& rhs, Op op)
37{
38 require_same_bitwise_shape(lhs, rhs);
39
40 A result(lhs.shape());
41
42 auto out = result.begin();
43 auto it_lhs = lhs.begin();
44 auto it_rhs = rhs.begin();
45
46 for (; it_lhs != lhs.end(); ++it_lhs, ++it_rhs, ++out)
47 {
48 *out = static_cast<typename A::value_type>(op(*it_lhs, *it_rhs));
49 }
50
51 return result;
52}
53
62template<Array A, Integer Scalar, typename Op>
64A binary_scalar_bitwise_op(const A& lhs, const Scalar& rhs, Op op)
65{
66 A result(lhs.shape());
67
68 auto out = result.begin();
69 for (auto it = lhs.begin(); it != lhs.end(); ++it, ++out)
70 {
71 *out = static_cast<typename A::value_type>(op(*it, rhs));
72 }
73
74 return result;
75}
76
85template<Integer Scalar, Array A, typename Op>
87A binary_scalar_bitwise_op(const Scalar& lhs, const A& rhs, Op op)
88{
89 A result(rhs.shape());
90
91 auto out = result.begin();
92 for (auto it = rhs.begin(); it != rhs.end(); ++it, ++out)
93 {
94 *out = static_cast<typename A::value_type>(op(lhs, *it));
95 }
96
97 return result;
98}
99
100// Unary
101
108template<Array A>
110A operator~(const A& value)
111{
112 A result(value.shape());
113
114 auto out = result.begin();
115 for (auto it = value.begin(); it != value.end(); ++it, ++out)
116 {
117 *out = static_cast<typename A::value_type>(std::bit_not<>{}(*it));
118 }
119
120 return result;
121}
122
123// Array-array
124
132template<Array A>
134A operator&(const A& lhs, const A& rhs)
135{
136 return binary_bitwise_op(lhs, rhs, std::bit_and<>{});
137}
138
146template<Array A>
148A operator|(const A& lhs, const A& rhs)
149{
150 return binary_bitwise_op(lhs, rhs, std::bit_or<>{});
151}
152
160template<Array A>
162A operator^(const A& lhs, const A& rhs)
163{
164 return binary_bitwise_op(lhs, rhs, std::bit_xor<>{});
165}
166
174template<Array A>
176A operator<<(const A& lhs, const A& rhs)
177{
178 return binary_bitwise_op(lhs, rhs, [](auto left, auto right) { return left << right; });
179}
180
188template<Array A>
190A operator>>(const A& lhs, const A& rhs)
191{
192 return binary_bitwise_op(lhs, rhs, [](auto left, auto right) { return left >> right; });
193}
194
195// Array-scalar
196
204template<Array A, Integer Scalar>
206A operator&(const A& lhs, const Scalar& rhs)
207{
208 return binary_scalar_bitwise_op(lhs, rhs, std::bit_and<>{});
209}
210
218template<Array A, Integer Scalar>
220A operator|(const A& lhs, const Scalar& rhs)
221{
222 return binary_scalar_bitwise_op(lhs, rhs, std::bit_or<>{});
223}
224
232template<Array A, Integer Scalar>
234A operator^(const A& lhs, const Scalar& rhs)
235{
236 return binary_scalar_bitwise_op(lhs, rhs, std::bit_xor<>{});
237}
238
246template<Array A, Integer Scalar>
248A operator<<(const A& lhs, const Scalar& rhs)
249{
250 return binary_scalar_bitwise_op(lhs, rhs, [](auto left, auto right) { return left << right; });
251}
252
260template<Array A, Integer Scalar>
262A operator>>(const A& lhs, const Scalar& rhs)
263{
264 return binary_scalar_bitwise_op(lhs, rhs, [](auto left, auto right) { return left >> right; });
265}
266
267// Scalar-array (reverse)
268
276template<Integer Scalar, Array A>
278A operator&(const Scalar& lhs, const A& rhs)
279{
280 return binary_scalar_bitwise_op(lhs, rhs, std::bit_and<>{});
281}
282
290template<Integer Scalar, Array A>
292A operator|(const Scalar& lhs, const A& rhs)
293{
294 return binary_scalar_bitwise_op(lhs, rhs, std::bit_or<>{});
295}
296
304template<Integer Scalar, Array A>
306A operator^(const Scalar& lhs, const A& rhs)
307{
308 return binary_scalar_bitwise_op(lhs, rhs, std::bit_xor<>{});
309}
310
318template<Integer Scalar, Array A>
320A operator<<(const Scalar& lhs, const A& rhs)
321{
322 return binary_scalar_bitwise_op(lhs, rhs, [](auto left, auto right) { return left << right; });
323}
324
332template<Integer Scalar, Array A>
334A operator>>(const Scalar& lhs, const A& rhs)
335{
336 return binary_scalar_bitwise_op(lhs, rhs, [](auto left, auto right) { return left >> right; });
337}
338
339// In-place array-array
340
348template<Array A>
350A& operator&=(A& lhs, const A& rhs)
351{
352 lhs = lhs & rhs;
353 return lhs;
354}
355
363template<Array A>
365A& operator|=(A& lhs, const A& rhs)
366{
367 lhs = lhs | rhs;
368 return lhs;
369}
370
378template<Array A>
380A& operator^=(A& lhs, const A& rhs)
381{
382 lhs = lhs ^ rhs;
383 return lhs;
384}
385
393template<Array A>
395A& operator<<=(A& lhs, const A& rhs)
396{
397 lhs = lhs << rhs;
398 return lhs;
399}
400
408template<Array A>
410A& operator>>=(A& lhs, const A& rhs)
411{
412 lhs = lhs >> rhs;
413 return lhs;
414}
415
416// In-place array-scalar
417
425template<Array A, Integer Scalar>
427A& operator&=(A& lhs, const Scalar& rhs)
428{
429 lhs = lhs & rhs;
430 return lhs;
431}
432
440template<Array A, Integer Scalar>
442A& operator|=(A& lhs, const Scalar& rhs)
443{
444 lhs = lhs | rhs;
445 return lhs;
446}
447
455template<Array A, Integer Scalar>
457A& operator^=(A& lhs, const Scalar& rhs)
458{
459 lhs = lhs ^ rhs;
460 return lhs;
461}
462
470template<Array A, Integer Scalar>
472A& operator<<=(A& lhs, const Scalar& rhs)
473{
474 lhs = lhs << rhs;
475 return lhs;
476}
477
485template<Array A, Integer Scalar>
487A& operator>>=(A& lhs, const Scalar& rhs)
488{
489 lhs = lhs >> rhs;
490 return lhs;
491}
Shared runtime validation helpers.
Alias for Stratax-supported integer types.
Definition Concepts.hpp:69
Alias for any scalar type accepted by Stratax numeric containers.
Definition Concepts.hpp:162