xref: /llvm-project/libcxx/test/std/experimental/simd/simd.reference/reference_arith_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 PlusAssign {
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 MinusAssign {
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 MultipliesAssign {
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 DividesAssign {
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 ModulusAssign {
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 template <typename T, typename SimdAbi, typename Op, typename OpAssign>
63 struct SimdReferenceOperatorHelper {
64   template <class U>
65   void operator()() const {
66     ex::simd<T, SimdAbi> origin_simd(static_cast<T>(3));
67     static_assert(noexcept(OpAssign{}(origin_simd[0], static_cast<U>(2))));
68     OpAssign{}(origin_simd[0], static_cast<U>(2));
69     assert((T)origin_simd[0] == (T)Op{}(static_cast<T>(3), static_cast<T>(std::forward<U>(2))));
70   }
71 };
72 
73 template <class T, std::size_t>
74 struct CheckReferenceArithOperators {
75   template <class SimdAbi>
76   void operator()() {
77     types::for_each(simd_test_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::plus<>, PlusAssign>());
78     types::for_each(simd_test_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::minus<>, MinusAssign>());
79     types::for_each(simd_test_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::multiplies<>, MultipliesAssign>());
80     types::for_each(simd_test_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::divides<>, DividesAssign>());
81   }
82 };
83 
84 template <class T, std::size_t>
85 struct CheckReferenceModOperators {
86   template <class SimdAbi>
87   void operator()() {
88     types::for_each(
89         simd_test_integer_types(), SimdReferenceOperatorHelper<T, SimdAbi, std::modulus<>, ModulusAssign>());
90   }
91 };
92 
93 int main(int, char**) {
94   test_all_simd_abi<CheckReferenceArithOperators>();
95   types::for_each(types::integer_types(), TestAllSimdAbiFunctor<CheckReferenceModOperators>());
96   return 0;
97 }
98