Stratax 0.4.0rc1
Loading...
Searching...
No Matches
Bitwise.hpp
Go to the documentation of this file.
1
12#pragma once
13
18
19#include <functional>
20#include <type_traits>
21
22namespace stratax::core::bitwise_detail {
23
32template<Array A, Integral Count, typename Op>
35 const A& lhs,
36 const Count& rhs,
37 Op op)
38{
39 using value_type = typename A::value_type;
40
41 validation::require_valid_shift_count<value_type>(rhs);
42
43 using result_type =
45
46 result_type result(lhs.shape());
47
48 auto out = result.begin();
49
50 for (auto it = lhs.begin(); it != lhs.end(); ++it, ++out)
51 {
52 *out = static_cast<value_type>(
53 op(*it, rhs));
54 }
55
56 return result;
57}
58
69template<Array L, Array R, typename Op>
70requires (
73)
75 const L& lhs,
76 const R& rhs,
77 Op op)
78{
79 using value_type = typename L::value_type;
80
81 using result_type =
83 L,
84 R,
85 value_type>;
86
87 const auto result_shape =
88 stratax::core::broadcast_detail::array_result_shape(lhs, rhs);
89
90 result_type result(result_shape);
91
92 for (std::size_t i = 0; i < result.size(); ++i)
93 {
94 const std::size_t lhs_index =
95 stratax::core::broadcast_detail::flat_operand_index(
96 i,
97 result_shape,
98 lhs.shape());
99
100 const std::size_t rhs_index =
101 stratax::core::broadcast_detail::flat_operand_index(
102 i,
103 result_shape,
104 rhs.shape());
105
106 const auto count = rhs[rhs_index];
107
108 validation::require_valid_shift_count<value_type>(count);
109
110 result[i] = static_cast<value_type>(
111 op(lhs[lhs_index], count));
112 }
113
114 return result;
115}
116
125template<Integral Scalar, Array A, typename Op>
128 const Scalar& lhs,
129 const A& rhs,
130 Op op)
131{
132 using value_type = std::remove_cvref_t<Scalar>;
133
134 using result_type =
136 A,
137 value_type>;
138
139 result_type result(rhs.shape());
140
141 auto out = result.begin();
142
143 for (auto it = rhs.begin(); it != rhs.end(); ++it, ++out)
144 {
145 validation::require_valid_shift_count<value_type>(*it);
146
147 *out = static_cast<value_type>(
148 op(lhs, *it));
149 }
150
151 return result;
152}
153
165template<Array L, Array R, typename Op>
166requires (
169)
171 L& lhs,
172 const R& rhs,
173 Op op)
174{
175 const auto result_shape =
176 stratax::core::broadcast_detail::array_result_shape(lhs, rhs);
177
178 if (result_shape != lhs.shape())
179 {
181 "In-place broadcasting cannot change the left operand's shape.");
182 }
183
184 constexpr bool stage = !compound_detail::owns_storage<L> ||
185 !compound_detail::owns_storage<R>;
186 return compound_detail::write_results<stage>(lhs, [&](std::size_t i)
187 {
188 const auto rhs_index = broadcast_detail::flat_operand_index(
189 i, lhs.shape(), rhs.shape());
190 return op(lhs[i], rhs[rhs_index]);
191 });
192}
193
203template<Array A, Integral Scalar, typename Op>
206 A& lhs,
207 const Scalar& rhs,
208 Op op)
209{
210 const Scalar scalar = rhs;
211 return compound_detail::write_results<
212 !compound_detail::owns_storage<A>>(lhs, [&](std::size_t i)
213 {
214 return op(lhs[i], scalar);
215 });
216}
217
234template<Array L, Array R, typename Op>
235requires (
238)
240 L& lhs,
241 const R& rhs,
242 Op op)
243{
244 const auto result_shape =
245 stratax::core::broadcast_detail::array_result_shape(lhs, rhs);
246
247 if (result_shape != lhs.shape())
248 {
250 "In-place broadcasting cannot change the left operand's shape.");
251 }
252
253 using value_type = typename L::value_type;
254
255 for (std::size_t i = 0; i < lhs.size(); ++i)
256 {
257 const std::size_t rhs_index =
258 stratax::core::broadcast_detail::flat_operand_index(
259 i,
260 lhs.shape(),
261 rhs.shape());
262
263 validation::require_valid_shift_count<value_type>(rhs[rhs_index]);
264 }
265
266 constexpr bool stage = !compound_detail::owns_storage<L> ||
267 !compound_detail::owns_storage<R>;
268 return compound_detail::write_results<stage>(lhs, [&](std::size_t i)
269 {
270 const auto rhs_index = broadcast_detail::flat_operand_index(
271 i, lhs.shape(), rhs.shape());
272 return op(lhs[i], rhs[rhs_index]);
273 });
274}
275
294template<Array L, Array R, typename Op>
295requires (
298)
300 const L& lhs,
301 const R& rhs,
302 Op op)
303{
304 using result_value_type =
306 typename L::value_type,
307 typename R::value_type>;
308
309 return stratax::core::broadcasted_op<result_value_type>(
310 lhs,
311 rhs,
312 op);
313}
314
328template<Array A, Integral Scalar, typename Op>
330 const A& arr,
331 const Scalar& scalar,
332 Op op)
333{
334 using result_value_type =
336
337 using result_type =
339
340 result_type result(arr.shape());
341
342 for (std::size_t i = 0; i < arr.size(); ++i)
343 {
344 result[i] = static_cast<result_value_type>(
345 op(arr[i], scalar));
346 }
347
348 return result;
349}
350
364template<Integral Scalar, Array A, typename Op>
366 const Scalar& scalar,
367 const A& arr,
368 Op op)
369{
370 using result_value_type =
372
373 using result_type =
375
376 result_type result(arr.shape());
377
378 for (std::size_t i = 0; i < arr.size(); ++i)
379 {
380 result[i] = static_cast<result_value_type>(
381 op(scalar, arr[i]));
382 }
383
384 return result;
385}
386
395template<Array A, Integral Count, typename Op>
398 A& lhs,
399 const Count& rhs,
400 Op op)
401{
402 const Count scalar = rhs;
403 validation::require_valid_shift_count<typename A::value_type>(scalar);
404 return compound_detail::write_results<
405 !compound_detail::owns_storage<A>>(lhs, [&](std::size_t i)
406 {
407 return op(lhs[i], scalar);
408 });
409}
410
411} // namespace stratax::core::bitwise_detail
412
413// Unary
414
421template<Array A>
423A operator~(const A& value)
424{
425 A result(value.shape());
426
427 auto out = result.begin();
428 for (auto it = value.begin(); it != value.end(); ++it, ++out)
429 {
430 *out = static_cast<typename A::value_type>(std::bit_not<>{}(*it));
431 }
432
433 return result;
434}
435
436// Array-array
437
439template<Array L, Array R>
440requires (
443)
444auto operator&(const L& lhs, const R& rhs)
445{
446 return stratax::core::bitwise_detail::binary_bitwise_op(
447 lhs, rhs, std::bit_and<>{});
448}
449
451template<Array L, Array R>
452requires (
455)
456auto operator|(const L& lhs, const R& rhs)
457{
458 return stratax::core::bitwise_detail::binary_bitwise_op(
459 lhs, rhs, std::bit_or<>{});
460}
461
463template<Array L, Array R>
464requires (
467)
468auto operator^(const L& lhs, const R& rhs)
469{
470 return stratax::core::bitwise_detail::binary_bitwise_op(
471 lhs, rhs, std::bit_xor<>{});
472}
473
475template<Array L, Array R>
476requires (
479)
480auto operator<<(const L& lhs, const R& rhs)
481{
482 return stratax::core::bitwise_detail::shift_array_op(
483 lhs,
484 rhs,
485 [](auto value, auto count)
486 {
487 return value << count;
488 });
489}
490
492template<Array L, Array R>
493requires (
496)
497auto operator>>(const L& lhs, const R& rhs)
498{
499 return stratax::core::bitwise_detail::shift_array_op(
500 lhs,
501 rhs,
502 [](auto value, auto count)
503 {
504 return value >> count;
505 });
506}
507
508// Array-scalar
509
511template<Array A, Integral Scalar>
513auto operator&(const A& lhs, const Scalar& rhs)
514{
515 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
516 lhs, rhs, std::bit_and<>{});
517}
518
520template<Array A, Integral Scalar>
522auto operator|(const A& lhs, const Scalar& rhs)
523{
524 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
525 lhs, rhs, std::bit_or<>{});
526}
527
529template<Array A, Integral Scalar>
531auto operator^(const A& lhs, const Scalar& rhs)
532{
533 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
534 lhs, rhs, std::bit_xor<>{});
535}
536
538template<Array A, Integral Scalar>
540auto operator<<(const A& lhs, const Scalar& rhs)
541{
542 return stratax::core::bitwise_detail::shift_scalar_op(
543 lhs,
544 rhs,
545 [](auto value, auto count)
546 {
547 return value << count;
548 });
549}
550
552template<Array A, Integral Scalar>
554auto operator>>(const A& lhs, const Scalar& rhs)
555{
556 return stratax::core::bitwise_detail::shift_scalar_op(
557 lhs,
558 rhs,
559 [](auto value, auto count)
560 {
561 return value >> count;
562 });
563}
564
565// Scalar-array (reverse)
566
568template<Integral Scalar, Array A>
570auto operator&(const Scalar& lhs, const A& rhs)
571{
572 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
573 lhs, rhs, std::bit_and<>{});
574}
575
577template<Integral Scalar, Array A>
579auto operator|(const Scalar& lhs, const A& rhs)
580{
581 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
582 lhs, rhs, std::bit_or<>{});
583}
584
586template<Integral Scalar, Array A>
588auto operator^(const Scalar& lhs, const A& rhs)
589{
590 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
591 lhs, rhs, std::bit_xor<>{});
592}
593
595template<Integral Scalar, Array A>
597auto operator<<(const Scalar& lhs, const A& rhs)
598{
599 return stratax::core::bitwise_detail::scalar_shift_array_op(
600 lhs,
601 rhs,
602 [](auto value, auto count)
603 {
604 return value << count;
605 });
606}
607
609template<Integral Scalar, Array A>
611auto operator>>(const Scalar& lhs, const A& rhs)
612{
613 return stratax::core::bitwise_detail::scalar_shift_array_op(
614 lhs,
615 rhs,
616 [](auto value, auto count)
617 {
618 return value >> count;
619 });
620}
621
622// In-place array-array
623
625template<Array L, Array R>
626requires (
629)
630L& operator&=(L& lhs, const R& rhs)
631{
632 return stratax::core::bitwise_detail::compound_bitwise_op(
633 lhs, rhs, std::bit_and<>{});
634}
635
637template<Array L, Array R>
638requires (
641)
642L& operator|=(L& lhs, const R& rhs)
643{
644 return stratax::core::bitwise_detail::compound_bitwise_op(
645 lhs, rhs, std::bit_or<>{});
646}
647
649template<Array L, Array R>
650requires (
653)
654L& operator^=(L& lhs, const R& rhs)
655{
656 return stratax::core::bitwise_detail::compound_bitwise_op(
657 lhs, rhs, std::bit_xor<>{});
658}
659
661template<Array L, Array R>
662requires (
665)
666L& operator<<=(L& lhs, const R& rhs)
667{
668 return stratax::core::bitwise_detail::compound_shift_op(
669 lhs,
670 rhs,
671 [](auto value, auto count) {
672 return value << count;
673 });
674}
675
677template<Array L, Array R>
678requires (
681)
682L& operator>>=(L& lhs, const R& rhs)
683{
684 return stratax::core::bitwise_detail::compound_shift_op(
685 lhs,
686 rhs,
687 [](auto value, auto count) {
688 return value >> count;
689 });
690}
691
692// In-place array-scalar
693
695template<Array A, Integral Scalar>
697A& operator&=(A& lhs, const Scalar& rhs)
698{
699 return stratax::core::bitwise_detail::compound_scalar_bitwise_op(
700 lhs, rhs, std::bit_and<>{});
701}
702
704template<Array A, Integral Scalar>
706A& operator|=(A& lhs, const Scalar& rhs)
707{
708 return stratax::core::bitwise_detail::compound_scalar_bitwise_op(
709 lhs, rhs, std::bit_or<>{});
710}
711
713template<Array A, Integral Scalar>
715A& operator^=(A& lhs, const Scalar& rhs)
716{
717 return stratax::core::bitwise_detail::compound_scalar_bitwise_op(
718 lhs, rhs, std::bit_xor<>{});
719}
720
722template<Array A, Integral Scalar>
724A& operator<<=(A& lhs, const Scalar& rhs)
725{
726 return stratax::core::bitwise_detail::compound_scalar_shift_op(
727 lhs,
728 rhs,
729 [](auto value, auto count)
730 {
731 return value << count;
732 });
733}
734
736template<Array A, Integral Scalar>
738A& operator>>=(A& lhs, const Scalar& rhs)
739{
740 return stratax::core::bitwise_detail::compound_scalar_shift_op(
741 lhs,
742 rhs,
743 [](auto value, auto count)
744 {
745 return value >> count;
746 });
747}
typename PromoteArray< std::remove_cvref_t< L >, std::remove_cvref_t< R >, std::remove_cvref_t< T > >::type promote_array_t
Convenience alias for the promoted array container type.
typename RebindArray< std::remove_cvref_t< A >, std::remove_cvref_t< T > >::type rebind_array_t
Convenience alias for rebinding an array to a new value type.
auto operator<<(const L &lhs, const R &rhs)
Left-shifts broadcasted left values by corresponding right counts.
Definition Bitwise.hpp:480
auto operator>>(const L &lhs, const R &rhs)
Right-shifts broadcasted left values by corresponding right counts.
Definition Bitwise.hpp:497
L & operator>>=(L &lhs, const R &rhs)
Applies broadcasted right-shift assignment after validating every count.
Definition Bitwise.hpp:682
auto operator^(const L &lhs, const R &rhs)
Computes the broadcasted element-wise bitwise XOR.
Definition Bitwise.hpp:468
auto operator&(const L &lhs, const R &rhs)
Computes the broadcasted element-wise bitwise AND.
Definition Bitwise.hpp:444
auto shift_scalar_op(const A &lhs, const Count &rhs, Op op)
Applies a validated scalar shift to every array element.
Definition Bitwise.hpp:34
auto shift_array_op(const L &lhs, const R &rhs, Op op)
Applies broadcasted per-element shift counts to an array.
Definition Bitwise.hpp:74
A & compound_scalar_bitwise_op(A &lhs, const Scalar &rhs, Op op)
Applies a scalar bitwise operation to lhs in place.
Definition Bitwise.hpp:205
auto scalar_shift_array_op(const Scalar &lhs, const A &rhs, Op op)
Shifts a scalar by every count stored in an array.
Definition Bitwise.hpp:127
L & operator|=(L &lhs, const R &rhs)
Applies broadcasted bitwise OR assignment.
Definition Bitwise.hpp:642
L & compound_bitwise_op(L &lhs, const R &rhs, Op op)
Applies a broadcasted bitwise operation to lhs in place.
Definition Bitwise.hpp:170
L & compound_shift_op(L &lhs, const R &rhs, Op op)
Applies validated broadcasted shift counts to lhs in place.
Definition Bitwise.hpp:239
auto binary_bitwise_op(const L &lhs, const R &rhs, Op op)
Applies a bitwise callable to two broadcast-compatible integer arrays.
Definition Bitwise.hpp:299
A operator~(const A &value)
Applies bitwise NOT to each element of an integer array.
Definition Bitwise.hpp:423
L & operator&=(L &lhs, const R &rhs)
Applies broadcasted bitwise AND assignment.
Definition Bitwise.hpp:630
L & operator^=(L &lhs, const R &rhs)
Applies broadcasted bitwise XOR assignment.
Definition Bitwise.hpp:654
auto binary_scalar_bitwise_op(const A &arr, const Scalar &scalar, Op op)
Applies a callable to every integer array element and a right scalar.
Definition Bitwise.hpp:329
L & operator<<=(L &lhs, const R &rhs)
Applies broadcasted left-shift assignment after validating every count.
Definition Bitwise.hpp:666
auto operator|(const L &lhs, const R &rhs)
Computes the broadcasted element-wise bitwise OR.
Definition Bitwise.hpp:456
A & compound_scalar_shift_op(A &lhs, const Count &rhs, Op op)
Applies a validated scalar shift to an array in place.
Definition Bitwise.hpp:397
Trailing-axis shape compatibility and element projection.
Internal result staging for compound operations on aliased arrays.
Dtype and array interface concepts.
Shared validation for division operands and integral shift counts.
typename Promote< std::remove_cvref_t< L >, std::remove_cvref_t< R > >::type promote_t
Convenience alias for the promoted dtype of two types.
Operands cannot broadcast to the requested result.
Supported integer dtype, excluding bool.
Definition Concepts.hpp:62