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// Older versions of clang may encounter a backend error (see 0295c2ad):
12// Pass-by-value arguments with alignment greater than register width are not supported.
13// XFAIL: target=powerpc{{.*}}-ibm-{{.*}} && clang-18
14
15// This test crashes AppleClang 15 but not later versions.
16// UNSUPPORTED: apple-clang-15
17
18// FIXME: The following issue occurs on Windows to Armv7 Ubuntu Linux:
19// Assertion failed: N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type"
20// XFAIL: target=armv7-unknown-linux-gnueabihf
21
22// <experimental/simd>
23//
24// [simd.class]
25// simd& operator++() noexcept;
26// simd operator++(int) noexcept;
27// simd& operator--() noexcept;
28// simd operator--(int) noexcept;
29// mask_type operator!() const noexcept;
30// simd operator~() const noexcept;
31// simd operator+() const noexcept;
32// simd operator-() const noexcept;
33
34#include "../test_utils.h"
35#include <experimental/simd>
36
37namespace ex = std::experimental::parallelism_v2;
38
39template <class T, std::size_t>
40struct CheckSimdPrefixIncrementOperator {
41 template <class SimdAbi>
42 void operator()() {
43 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
44 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
45 static_assert(noexcept(++origin_simd));
46 std::array<T, array_size> expected_return_value, expected_value;
47 for (size_t i = 0; i < array_size; ++i) {
48 expected_return_value[i] = static_cast<T>(i) + 1;
49 expected_value[i] = static_cast<T>(i) + 1;
50 }
51 assert_simd_values_equal<array_size>(++origin_simd, expected_return_value);
52 assert_simd_values_equal<array_size>(origin_simd, expected_value);
53 }
54};
55
56template <class T, std::size_t>
57struct CheckSimdPostfixIncrementOperator {
58 template <class SimdAbi>
59 void operator()() {
60 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
61 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
62 static_assert(noexcept(origin_simd++));
63 std::array<T, array_size> expected_return_value, expected_value;
64 for (size_t i = 0; i < array_size; ++i) {
65 expected_return_value[i] = static_cast<T>(i);
66 expected_value[i] = static_cast<T>(i) + 1;
67 }
68 assert_simd_values_equal<array_size>(origin_simd++, expected_return_value);
69 assert_simd_values_equal<array_size>(origin_simd, expected_value);
70 }
71};
72
73template <class T, std::size_t>
74struct CheckSimdPrefixDecrementOperator {
75 template <class SimdAbi>
76 void operator()() {
77 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
78 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
79 static_assert(noexcept(--origin_simd));
80 std::array<T, array_size> expected_return_value, expected_value;
81 for (size_t i = 0; i < array_size; ++i) {
82 expected_return_value[i] = static_cast<T>(i) - 1;
83 expected_value[i] = static_cast<T>(i) - 1;
84 }
85 assert_simd_values_equal<array_size>(--origin_simd, expected_return_value);
86 assert_simd_values_equal<array_size>(origin_simd, expected_value);
87 }
88};
89
90template <class T, std::size_t>
91struct CheckSimdPostfixDecrementOperator {
92 template <class SimdAbi>
93 void operator()() {
94 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
95 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
96 static_assert(noexcept(origin_simd--));
97 std::array<T, array_size> expected_return_value, expected_value;
98 for (size_t i = 0; i < array_size; ++i) {
99 expected_return_value[i] = static_cast<T>(i);
100 expected_value[i] = static_cast<T>(i) - 1;
101 }
102 assert_simd_values_equal<array_size>(origin_simd--, expected_return_value);
103 assert_simd_values_equal<array_size>(origin_simd, expected_value);
104 }
105};
106
107template <class T, std::size_t>
108struct CheckSimdNegationOperator {
109 template <class SimdAbi>
110 void operator()() {
111 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
112 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
113 static_assert(noexcept(!origin_simd));
114 std::array<bool, array_size> expected_value;
115 for (size_t i = 0; i < array_size; ++i)
116 expected_value[i] = !static_cast<bool>(i);
117 assert_simd_mask_values_equal<array_size>(!origin_simd, expected_value);
118 }
119};
120
121template <class T, std::size_t>
122struct CheckSimdBitwiseNotOperator {
123 template <class SimdAbi>
124 void operator()() {
125 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
126 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
127 static_assert(noexcept(~origin_simd));
128 std::array<T, array_size> expected_value;
129 for (size_t i = 0; i < array_size; ++i)
130 expected_value[i] = ~static_cast<T>(i);
131 assert_simd_values_equal<array_size>(~origin_simd, expected_value);
132 }
133};
134
135template <class T, std::size_t>
136struct CheckSimdPositiveSignOperator {
137 template <class SimdAbi>
138 void operator()() {
139 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
140 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
141 static_assert(noexcept(+origin_simd));
142 std::array<T, array_size> expected_value;
143 for (size_t i = 0; i < array_size; ++i)
144 expected_value[i] = +static_cast<T>(i);
145 assert_simd_values_equal<array_size>(+origin_simd, expected_value);
146 }
147};
148
149template <class T, std::size_t>
150struct CheckSimdNegativeSignOperator {
151 template <class SimdAbi>
152 void operator()() {
153 constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>;
154 ex::simd<T, SimdAbi> origin_simd([](T i) { return i; });
155 static_assert(noexcept(-origin_simd));
156 std::array<T, array_size> expected_value;
157 for (size_t i = 0; i < array_size; ++i)
158 expected_value[i] = -static_cast<T>(i);
159 assert_simd_values_equal<array_size>(-origin_simd, expected_value);
160 }
161};
162
163template <class T, class SimdAbi = ex::simd_abi::compatible<T>, class = void>
164struct has_bitwise_not_op : std::false_type {};
165
166template <class T, class SimdAbi>
167struct has_bitwise_not_op<T, SimdAbi, std::void_t<decltype(~std::declval<ex::simd<T, SimdAbi>>())>> : std::true_type {};
168
169template <class T, std::size_t>
170struct CheckSimdBitwiseNotTraits {
171 template <class SimdAbi>
172 void operator()() {
173 // This function shall not participate in overload resolution unless
174 // T is an integral type.
175 if constexpr (std::is_integral_v<T>)
176 static_assert(has_bitwise_not_op<T, SimdAbi>::value);
177 // T is not an integral type.
178 else
179 static_assert(!has_bitwise_not_op<T, SimdAbi>::value);
180 }
181};
182
183int main(int, char**) {
184 test_all_simd_abi<CheckSimdPrefixIncrementOperator>();
185 test_all_simd_abi<CheckSimdPostfixIncrementOperator>();
186 test_all_simd_abi<CheckSimdPrefixDecrementOperator>();
187 test_all_simd_abi<CheckSimdPostfixDecrementOperator>();
188 test_all_simd_abi<CheckSimdNegationOperator>();
189 types::for_each(types::integer_types(), TestAllSimdAbiFunctor<CheckSimdBitwiseNotOperator>());
190 test_all_simd_abi<CheckSimdPositiveSignOperator>();
191 test_all_simd_abi<CheckSimdNegativeSignOperator>();
192 test_all_simd_abi<CheckSimdBitwiseNotTraits>();
193 return 0;
194}
195

source code of libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp