3#include <stratax/core/dtypes/Concepts.hpp>
4#include <stratax/ops/Broadcasting.hpp>
11namespace stratax::core::bitwise_detail {
24template<
typename Value, Integral Count>
25constexpr bool valid_shift_count(
const Count& count)
noexcept
27 if constexpr (std::is_signed_v<std::remove_cvref_t<Count>>)
35 using value_type = std::remove_cvref_t<Value>;
37 return static_cast<std::uintmax_t
>(count) <
38 sizeof(value_type) * CHAR_BIT;
50template<
typename Value, Integral Count>
51void require_valid_shift_count(
const Count& count)
53 if (!valid_shift_count<Value>(count))
67template<Array A, Integral Count,
typename Op>
74 using value_type =
typename A::value_type;
76 require_valid_shift_count<value_type>(rhs);
79 stratax::core::rebind_array_t<A, value_type>;
81 result_type result(lhs.shape());
83 auto out = result.begin();
85 for (
auto it = lhs.begin(); it != lhs.end(); ++it, ++out)
87 *out =
static_cast<value_type
>(
104template<Array L, Array R,
typename Op>
114 using value_type =
typename L::value_type;
117 stratax::core::promote_array_t<
122 const auto result_shape =
123 broadcasted_shape(lhs.shape(), rhs.shape());
125 result_type result(result_shape);
127 for (std::size_t i = 0; i < result.size(); ++i)
129 const std::size_t lhs_index =
130 stratax::core::broadcast_detail::flat_operand_index(
135 const std::size_t rhs_index =
136 stratax::core::broadcast_detail::flat_operand_index(
141 const auto count = rhs[rhs_index];
143 require_valid_shift_count<value_type>(count);
145 result[i] =
static_cast<value_type
>(
146 op(lhs[lhs_index], count));
160template<Integral Scalar, Array A,
typename Op>
162auto scalar_shift_array_op(
167 using value_type = std::remove_cvref_t<Scalar>;
170 stratax::core::rebind_array_t<
174 result_type result(rhs.shape());
176 auto out = result.begin();
178 for (
auto it = rhs.begin(); it != rhs.end(); ++it, ++out)
180 require_valid_shift_count<value_type>(*it);
182 *out =
static_cast<value_type
>(
198template<Array L, Array R,
typename Op>
203L& compound_bitwise_op(
208 const auto result_shape =
209 broadcasted_shape(lhs.shape(), rhs.shape());
211 if (result_shape != lhs.shape())
214 "In-place broadcasting cannot change the left operand's shape.");
217 for (std::size_t i = 0; i < lhs.size(); ++i)
219 const std::size_t rhs_index =
220 stratax::core::broadcast_detail::flat_operand_index(
225 lhs[i] =
static_cast<typename L::value_type
>(
226 op(lhs[i], rhs[rhs_index]));
239template<Array A, Integral Scalar,
typename Op>
241A& compound_scalar_bitwise_op(
246 for (std::size_t i = 0; i < lhs.size(); ++i)
248 lhs[i] =
static_cast<typename A::value_type
>(
269template<Array L, Array R,
typename Op>
279 const auto result_shape =
280 broadcasted_shape(lhs.shape(), rhs.shape());
282 if (result_shape != lhs.shape())
285 "In-place broadcasting cannot change the left operand's shape.");
288 using value_type =
typename L::value_type;
290 for (std::size_t i = 0; i < lhs.size(); ++i)
292 const std::size_t rhs_index =
293 stratax::core::broadcast_detail::flat_operand_index(
298 require_valid_shift_count<value_type>(rhs[rhs_index]);
301 for (std::size_t i = 0; i < lhs.size(); ++i)
303 const std::size_t rhs_index =
304 stratax::core::broadcast_detail::flat_operand_index(
309 const auto count = rhs[rhs_index];
311 lhs[i] =
static_cast<value_type
>(
336template<Array L, Array R,
typename Op>
341auto binary_bitwise_op(
346 using result_value_type =
347 stratax::core::promote_t<
348 typename L::value_type,
349 typename R::value_type>;
351 return stratax::core::broadcasted_op<result_value_type>(
370template<Array A, Integral Scalar,
typename Op>
371auto binary_scalar_bitwise_op(
373 const Scalar& scalar,
376 using result_value_type =
377 promote_t<typename A::value_type, Scalar>;
380 rebind_array_t<A, result_value_type>;
382 result_type result(arr.shape());
384 for (std::size_t i = 0; i < arr.size(); ++i)
386 result[i] =
static_cast<result_value_type
>(
406template<Integral Scalar, Array A,
typename Op>
407auto binary_scalar_bitwise_op(
408 const Scalar& scalar,
412 using result_value_type =
413 promote_t<Scalar, typename A::value_type>;
416 rebind_array_t<A, result_value_type>;
418 result_type result(arr.shape());
420 for (std::size_t i = 0; i < arr.size(); ++i)
422 result[i] =
static_cast<result_value_type
>(
435template<Array A, Integral Count,
typename Op>
437A& compound_scalar_shift_op(
442 using value_type =
typename A::value_type;
444 require_valid_shift_count<value_type>(rhs);
446 for (std::size_t i = 0; i < lhs.size(); ++i)
448 lhs[i] =
static_cast<value_type
>(
467A operator~(
const A& value)
469 A result(value.shape());
471 auto out = result.begin();
472 for (
auto it = value.begin(); it != value.end(); ++it, ++out)
474 *out =
static_cast<typename A::value_type
>(std::bit_not<>{}(*it));
483template<Array L, Array R>
488auto operator&(
const L& lhs,
const R& rhs)
490 return stratax::core::bitwise_detail::binary_bitwise_op(
491 lhs, rhs, std::bit_and<>{});
495template<Array L, Array R>
500auto operator|(
const L& lhs,
const R& rhs)
502 return stratax::core::bitwise_detail::binary_bitwise_op(
503 lhs, rhs, std::bit_or<>{});
507template<Array L, Array R>
512auto operator^(
const L& lhs,
const R& rhs)
514 return stratax::core::bitwise_detail::binary_bitwise_op(
515 lhs, rhs, std::bit_xor<>{});
519template<Array L, Array R>
524auto operator<<(
const L& lhs,
const R& rhs)
526 return stratax::core::bitwise_detail::shift_array_op(
529 [](
auto value,
auto count)
531 return value << count;
536template<Array L, Array R>
541auto operator>>(
const L& lhs,
const R& rhs)
543 return stratax::core::bitwise_detail::shift_array_op(
546 [](
auto value,
auto count)
548 return value >> count;
555template<Array A, Integral Scalar>
557auto operator&(
const A& lhs,
const Scalar& rhs)
559 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
560 lhs, rhs, std::bit_and<>{});
564template<Array A, Integral Scalar>
566auto operator|(
const A& lhs,
const Scalar& rhs)
568 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
569 lhs, rhs, std::bit_or<>{});
573template<Array A, Integral Scalar>
575auto operator^(
const A& lhs,
const Scalar& rhs)
577 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
578 lhs, rhs, std::bit_xor<>{});
582template<Array A, Integral Scalar>
584auto operator<<(
const A& lhs,
const Scalar& rhs)
586 return stratax::core::bitwise_detail::shift_scalar_op(
589 [](
auto value,
auto count)
591 return value << count;
596template<Array A, Integral Scalar>
598auto operator>>(
const A& lhs,
const Scalar& rhs)
600 return stratax::core::bitwise_detail::shift_scalar_op(
603 [](
auto value,
auto count)
605 return value >> count;
613template<Integral Scalar, Array A>
615auto operator&(
const Scalar& lhs,
const A& rhs)
617 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
618 lhs, rhs, std::bit_and<>{});
623template<Integral Scalar, Array A>
625auto operator|(
const Scalar& lhs,
const A& rhs)
627 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
628 lhs, rhs, std::bit_or<>{});
632template<Integral Scalar, Array A>
634auto operator^(
const Scalar& lhs,
const A& rhs)
636 return stratax::core::bitwise_detail::binary_scalar_bitwise_op(
637 lhs, rhs, std::bit_xor<>{});
640template<Integral Scalar, Array A>
642auto operator<<(
const Scalar& lhs,
const A& rhs)
644 return stratax::core::bitwise_detail::scalar_shift_array_op(
647 [](
auto value,
auto count)
649 return value << count;
653template<Integral Scalar, Array A>
655auto operator>>(
const Scalar& lhs,
const A& rhs)
657 return stratax::core::bitwise_detail::scalar_shift_array_op(
660 [](
auto value,
auto count)
662 return value >> count;
669template<Array L, Array R>
674L&
operator&=(L& lhs,
const R& rhs)
676 return stratax::core::bitwise_detail::compound_bitwise_op(
677 lhs, rhs, std::bit_and<>{});
681template<Array L, Array R>
686L&
operator|=(L& lhs,
const R& rhs)
688 return stratax::core::bitwise_detail::compound_bitwise_op(
689 lhs, rhs, std::bit_or<>{});
693template<Array L, Array R>
698L&
operator^=(L& lhs,
const R& rhs)
700 return stratax::core::bitwise_detail::compound_bitwise_op(
701 lhs, rhs, std::bit_xor<>{});
705template<Array L, Array R>
710L&
operator<<=(L& lhs,
const R& rhs)
712 return stratax::core::bitwise_detail::compound_shift_op(
715 [](
auto value,
auto count) {
716 return value << count;
721template<Array L, Array R>
726L&
operator>>=(L& lhs,
const R& rhs)
728 return stratax::core::bitwise_detail::compound_shift_op(
731 [](
auto value,
auto count) {
732 return value >> count;
738template<Array A, Integral Scalar>
740A& operator&=(A& lhs,
const Scalar& rhs)
742 return stratax::core::bitwise_detail::compound_scalar_bitwise_op(
743 lhs, rhs, std::bit_and<>{});
746template<Array A, Integral Scalar>
748A& operator|=(A& lhs,
const Scalar& rhs)
750 return stratax::core::bitwise_detail::compound_scalar_bitwise_op(
751 lhs, rhs, std::bit_or<>{});
754template<Array A, Integral Scalar>
756A& operator^=(A& lhs,
const Scalar& rhs)
758 return stratax::core::bitwise_detail::compound_scalar_bitwise_op(
759 lhs, rhs, std::bit_xor<>{});
762template<Array A, Integral Scalar>
764A& operator<<=(A& lhs,
const Scalar& rhs)
766 return stratax::core::bitwise_detail::compound_scalar_shift_op(
769 [](
auto value,
auto count)
771 return value << count;
775template<Array A, Integral Scalar>
777A& operator>>=(A& lhs,
const Scalar& rhs)
779 return stratax::core::bitwise_detail::compound_scalar_shift_op(
782 [](
auto value,
auto count)
784 return value >> count;