xref: /llvm-project/libcxx/test/std/experimental/simd/simd.reference/reference_bitwise_operators.pass.cpp (revision 09e3a360581dc36d0820d3fb6da9bd7cfed87b5d)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 
11 // <experimental/simd>
12 //
13 // [simd.reference]
14 // template<class U> reference|=(U&& x) && noexcept;
15 // template<class U> reference&=(U&& x) && noexcept;
16 // template<class U> reference^=(U&& x) && noexcept;
17 // template<class U> reference<<=(U&& x) && noexcept;
18 // template<class U> reference>>=(U&& x) && noexcept;
19 
20 #include <experimental/simd>
21 #include <functional>
22 
23 #include "../test_utils.h"
24 
25 namespace ex = std::experimental::parallelism_v2;
26 
27 struct AndAssign {
28   template <typename T, typename U>
29   void operator()(T&& lhs, const U& rhs) const noexcept {
30     std::forward<T>(lhs) &= rhs;
31   }
32 };
33 
34 struct OrAssign {
35   template <typename T, typename U>
36   void operator()(T&& lhs, const U& rhs) const noexcept {
37     std::forward<T>(lhs) |= rhs;
38   }
39 };
40 
41 struct XorAssign {
42   template <typename T, typename U>
43   void operator()(T&& lhs, const U& rhs) const noexcept {
44     std::forward<T>(lhs) ^= rhs;
45   }
46 };
47 
48 struct LeftShiftAssign {
49   template <typename T, typename U>
50   void operator()(T&& lhs, const U& rhs) const noexcept {
51     std::forward<T>(lhs) <<= rhs;
52   }
53 };
54 
55 struct RightShiftAssign {
56   template <typename T, typename U>
57   void operator()(T&& lhs, const U& rhs) const noexcept {
58     std::forward<T>(lhs) >>= rhs;
59   }
60 };
61 
62 struct LeftShift {
63   template <typename T, typename U>
64   T operator()(const T& lhs, const U& rhs) const noexcept {
65     return lhs << rhs;
66   }
67 };
68 
69 struct RightShift {
70   template <typename T, typename U>
71   T operator()(const T& lhs, const U& rhs) const noexcept {
72     return lhs >> rhs;
73   }
74 };
75 
76 template <typename T, typename SimdAbi, typename Op, typename OpAssign>
77 struct SimdReferenceOperatorHelper {
78   template <class U>
79   void operator()() const {
80     ex::simd<T, SimdAbi> origin_simd(static_cast<T>(3));
81     static_assert(noexcept(OpAssign{}(origin_simd[0], static_cast<U>(2))));
82     OpAssign{}(origin_simd[0], static_cast<U>(2));
83     assert((T)origin_simd[0] == (T)Op{}(static_cast<T>(3), static_cast<T>(std::forward<U>(2))));
84   }
85 };
86 
87 template <typename T, typename SimdAbi, typename Op, typename OpAssign>
88 struct MaskReferenceOperatorHelper {
89   template <class U>
90   void operator()() const {
91     ex::simd_mask<T, SimdAbi> origin_mask(true);
92     static_assert(noexcept(OpAssign{}(origin_mask[0], static_cast<U>(false))));
93     OpAssign{}(origin_mask[0], static_cast<U>(false));
94     assert((bool)origin_mask[0] == (bool)Op{}(true, static_cast<bool>(std::forward<U>(false))));
95   }
96 };
97 
98 template <class T, std::size_t>
99 struct CheckReferenceBitwiseOperators {
100   template <class SimdAbi>
101   void operator()() {
102     types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::bit_and<>, AndAssign>());
103     types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::bit_or<>, OrAssign>());
104     types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::bit_xor<>, XorAssign>());
105     types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelper<T, SimdAbi, LeftShift, LeftShiftAssign>());
106     types::for_each(simd_test_integer_types(), SimdReferenceOperatorHelper<T, SimdAbi, RightShift, RightShiftAssign>());
107 
108     types::for_each(simd_test_integer_types(), MaskReferenceOperatorHelper<T, SimdAbi, std::bit_and<>, AndAssign>());
109     types::for_each(simd_test_integer_types(), MaskReferenceOperatorHelper<T, SimdAbi, std::bit_or<>, OrAssign>());
110     types::for_each(simd_test_integer_types(), MaskReferenceOperatorHelper<T, SimdAbi, std::bit_xor<>, XorAssign>());
111   }
112 };
113 
114 int main(int, char**) {
115   types::for_each(types::integer_types(), TestAllSimdAbiFunctor<CheckReferenceBitwiseOperators>());
116   return 0;
117 }
118