simd revision 1.1 1 1.1 joerg // -*- C++ -*-
2 1.1 joerg //===------------------------------- simd ---------------------------------===//
3 1.1 joerg //
4 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 1.1 joerg // See https://llvm.org/LICENSE.txt for license information.
6 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 1.1 joerg //
8 1.1 joerg //===----------------------------------------------------------------------===//
9 1.1 joerg #ifndef _LIBCPP_EXPERIMENTAL_SIMD
10 1.1 joerg #define _LIBCPP_EXPERIMENTAL_SIMD
11 1.1 joerg
12 1.1 joerg /*
13 1.1 joerg experimental/simd synopsis
14 1.1 joerg
15 1.1 joerg namespace std::experimental {
16 1.1 joerg
17 1.1 joerg inline namespace parallelism_v2 {
18 1.1 joerg
19 1.1 joerg namespace simd_abi {
20 1.1 joerg
21 1.1 joerg struct scalar {};
22 1.1 joerg template <int N> struct fixed_size {};
23 1.1 joerg template <typename T> inline constexpr int max_fixed_size = implementation-defined;
24 1.1 joerg template <typename T> using compatible = implementation-defined;
25 1.1 joerg template <typename T> using native = implementation-defined;
26 1.1 joerg
27 1.1 joerg } // simd_abi
28 1.1 joerg
29 1.1 joerg struct element_aligned_tag {};
30 1.1 joerg struct vector_aligned_tag {};
31 1.1 joerg template <size_t> struct overaligned_tag {};
32 1.1 joerg inline constexpr element_aligned_tag element_aligned{};
33 1.1 joerg inline constexpr vector_aligned_tag vector_aligned{};
34 1.1 joerg template <size_t N> inline constexpr overaligned_tag<N> overaligned{};
35 1.1 joerg
36 1.1 joerg // traits [simd.traits]
37 1.1 joerg template <class T> struct is_abi_tag;
38 1.1 joerg template <class T> inline constexpr bool is_abi_tag_v = is_abi_tag<T>::value;
39 1.1 joerg
40 1.1 joerg template <class T> struct is_simd;
41 1.1 joerg template <class T> inline constexpr bool is_simd_v = is_simd<T>::value;
42 1.1 joerg
43 1.1 joerg template <class T> struct is_simd_mask;
44 1.1 joerg template <class T> inline constexpr bool is_simd_mask_v = is_simd_mask<T>::value;
45 1.1 joerg
46 1.1 joerg template <class T> struct is_simd_flag_type;
47 1.1 joerg template <class T> inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<T>::value;
48 1.1 joerg
49 1.1 joerg template <class T, size_t N> struct abi_for_size { using type = see below; };
50 1.1 joerg template <class T, size_t N> using abi_for_size_t = typename abi_for_size<T, N>::type;
51 1.1 joerg
52 1.1 joerg template <class T, class Abi = simd_abi::compatible<T>> struct simd_size;
53 1.1 joerg template <class T, class Abi = simd_abi::compatible<T>>
54 1.1 joerg inline constexpr size_t simd_size_v = simd_size<T, Abi>::value;
55 1.1 joerg
56 1.1 joerg template <class T, class U = typename T::value_type> struct memory_alignment;
57 1.1 joerg template <class T, class U = typename T::value_type>
58 1.1 joerg inline constexpr size_t memory_alignment_v = memory_alignment<T, U>::value;
59 1.1 joerg
60 1.1 joerg // class template simd [simd.class]
61 1.1 joerg template <class T, class Abi = simd_abi::compatible<T>> class simd;
62 1.1 joerg template <class T> using native_simd = simd<T, simd_abi::native<T>>;
63 1.1 joerg template <class T, int N> using fixed_size_simd = simd<T, simd_abi::fixed_size<N>>;
64 1.1 joerg
65 1.1 joerg // class template simd_mask [simd.mask.class]
66 1.1 joerg template <class T, class Abi = simd_abi::compatible<T>> class simd_mask;
67 1.1 joerg template <class T> using native_simd_mask = simd_mask<T, simd_abi::native<T>>;
68 1.1 joerg template <class T, int N> using fixed_size_simd_mask = simd_mask<T, simd_abi::fixed_size<N>>;
69 1.1 joerg
70 1.1 joerg // casts [simd.casts]
71 1.1 joerg template <class T, class U, class Abi> see below simd_cast(const simd<U, Abi>&);
72 1.1 joerg template <class T, class U, class Abi> see below static_simd_cast(const simd<U, Abi>&);
73 1.1 joerg
74 1.1 joerg template <class T, class Abi>
75 1.1 joerg fixed_size_simd<T, simd_size_v<T, Abi>> to_fixed_size(const simd<T, Abi>&) noexcept;
76 1.1 joerg template <class T, class Abi>
77 1.1 joerg fixed_size_simd_mask<T, simd_size_v<T, Abi>> to_fixed_size(const simd_mask<T, Abi>&) noexcept;
78 1.1 joerg template <class T, size_t N> native_simd<T> to_native(const fixed_size_simd<T, N>&) noexcept;
79 1.1 joerg template <class T, size_t N>
80 1.1 joerg native_simd_mask<T> to_native(const fixed_size_simd_mask<T, N>> &) noexcept;
81 1.1 joerg template <class T, size_t N> simd<T> to_compatible(const fixed_size_simd<T, N>&) noexcept;
82 1.1 joerg template <class T, size_t N> simd_mask<T> to_compatible(const fixed_size_simd_mask<T, N>&) noexcept;
83 1.1 joerg
84 1.1 joerg template <size_t... Sizes, class T, class Abi>
85 1.1 joerg tuple<simd<T, abi_for_size_t<Sizes>>...> split(const simd<T, Abi>&);
86 1.1 joerg template <size_t... Sizes, class T, class Abi>
87 1.1 joerg tuple<simd_mask<T, abi_for_size_t<Sizes>>...> split(const simd_mask<T, Abi>&);
88 1.1 joerg template <class V, class Abi>
89 1.1 joerg array<V, simd_size_v<typename V::value_type, Abi> / V::size()> split(
90 1.1 joerg const simd<typename V::value_type, Abi>&);
91 1.1 joerg template <class V, class Abi>
92 1.1 joerg array<V, simd_size_v<typename V::value_type, Abi> / V::size()> split(
93 1.1 joerg const simd_mask<typename V::value_type, Abi>&);
94 1.1 joerg
95 1.1 joerg template <class T, class... Abis>
96 1.1 joerg simd<T, abi_for_size_t<T, (simd_size_v<T, Abis> + ...)>> concat(const simd<T, Abis>&...);
97 1.1 joerg template <class T, class... Abis>
98 1.1 joerg simd_mask<T, abi_for_size_t<T, (simd_size_v<T, Abis> + ...)>> concat(const simd_mask<T, Abis>&...);
99 1.1 joerg
100 1.1 joerg // reductions [simd.mask.reductions]
101 1.1 joerg template <class T, class Abi> bool all_of(const simd_mask<T, Abi>&) noexcept;
102 1.1 joerg template <class T, class Abi> bool any_of(const simd_mask<T, Abi>&) noexcept;
103 1.1 joerg template <class T, class Abi> bool none_of(const simd_mask<T, Abi>&) noexcept;
104 1.1 joerg template <class T, class Abi> bool some_of(const simd_mask<T, Abi>&) noexcept;
105 1.1 joerg template <class T, class Abi> int popcount(const simd_mask<T, Abi>&) noexcept;
106 1.1 joerg template <class T, class Abi> int find_first_set(const simd_mask<T, Abi>&);
107 1.1 joerg template <class T, class Abi> int find_last_set(const simd_mask<T, Abi>&);
108 1.1 joerg
109 1.1 joerg bool all_of(see below) noexcept;
110 1.1 joerg bool any_of(see below) noexcept;
111 1.1 joerg bool none_of(see below) noexcept;
112 1.1 joerg bool some_of(see below) noexcept;
113 1.1 joerg int popcount(see below) noexcept;
114 1.1 joerg int find_first_set(see below) noexcept;
115 1.1 joerg int find_last_set(see below) noexcept;
116 1.1 joerg
117 1.1 joerg // masked assignment [simd.whereexpr]
118 1.1 joerg template <class M, class T> class const_where_expression;
119 1.1 joerg template <class M, class T> class where_expression;
120 1.1 joerg
121 1.1 joerg // masked assignment [simd.mask.where]
122 1.1 joerg template <class T> struct nodeduce { using type = T; }; // exposition only
123 1.1 joerg
124 1.1 joerg template <class T> using nodeduce_t = typename nodeduce<T>::type; // exposition only
125 1.1 joerg
126 1.1 joerg template <class T, class Abi>
127 1.1 joerg where_expression<simd_mask<T, Abi>, simd<T, Abi>>
128 1.1 joerg where(const typename simd<T, Abi>::mask_type&, simd<T, Abi>&) noexcept;
129 1.1 joerg
130 1.1 joerg template <class T, class Abi>
131 1.1 joerg const_where_expression<simd_mask<T, Abi>, const simd<T, Abi>>
132 1.1 joerg where(const typename simd<T, Abi>::mask_type&, const simd<T, Abi>&) noexcept;
133 1.1 joerg
134 1.1 joerg template <class T, class Abi>
135 1.1 joerg where_expression<simd_mask<T, Abi>, simd_mask<T, Abi>>
136 1.1 joerg where(const nodeduce_t<simd_mask<T, Abi>>&, simd_mask<T, Abi>&) noexcept;
137 1.1 joerg
138 1.1 joerg template <class T, class Abi>
139 1.1 joerg const_where_expression<simd_mask<T, Abi>, const simd_mask<T, Abi>>
140 1.1 joerg where(const nodeduce_t<simd_mask<T, Abi>>&, const simd_mask<T, Abi>&) noexcept;
141 1.1 joerg
142 1.1 joerg template <class T> where_expression<bool, T> where(see below k, T& d) noexcept;
143 1.1 joerg
144 1.1 joerg template <class T>
145 1.1 joerg const_where_expression<bool, const T> where(see below k, const T& d) noexcept;
146 1.1 joerg
147 1.1 joerg // reductions [simd.reductions]
148 1.1 joerg template <class T, class Abi, class BinaryOperation = std::plus<>>
149 1.1 joerg T reduce(const simd<T, Abi>&, BinaryOperation = BinaryOperation());
150 1.1 joerg
151 1.1 joerg template <class M, class V, class BinaryOperation>
152 1.1 joerg typename V::value_type reduce(const const_where_expression<M, V>& x,
153 1.1 joerg typename V::value_type neutral_element, BinaryOperation binary_op);
154 1.1 joerg
155 1.1 joerg template <class M, class V>
156 1.1 joerg typename V::value_type reduce(const const_where_expression<M, V>& x, plus<> binary_op = plus<>());
157 1.1 joerg
158 1.1 joerg template <class M, class V>
159 1.1 joerg typename V::value_type reduce(const const_where_expression<M, V>& x, multiplies<> binary_op);
160 1.1 joerg
161 1.1 joerg template <class M, class V>
162 1.1 joerg typename V::value_type reduce(const const_where_expression<M, V>& x, bit_and<> binary_op);
163 1.1 joerg
164 1.1 joerg template <class M, class V>
165 1.1 joerg typename V::value_type reduce(const const_where_expression<M, V>& x, bit_or<> binary_op);
166 1.1 joerg
167 1.1 joerg template <class M, class V>
168 1.1 joerg typename V::value_type reduce(const const_where_expression<M, V>& x, bit_xor<> binary_op);
169 1.1 joerg
170 1.1 joerg template <class T, class Abi> T hmin(const simd<T, Abi>&);
171 1.1 joerg template <class M, class V> T hmin(const const_where_expression<M, V>&);
172 1.1 joerg template <class T, class Abi> T hmax(const simd<T, Abi>&);
173 1.1 joerg template <class M, class V> T hmax(const const_where_expression<M, V>&);
174 1.1 joerg
175 1.1 joerg // algorithms [simd.alg]
176 1.1 joerg template <class T, class Abi> simd<T, Abi> min(const simd<T, Abi>&, const simd<T, Abi>&) noexcept;
177 1.1 joerg
178 1.1 joerg template <class T, class Abi> simd<T, Abi> max(const simd<T, Abi>&, const simd<T, Abi>&) noexcept;
179 1.1 joerg
180 1.1 joerg template <class T, class Abi>
181 1.1 joerg std::pair<simd<T, Abi>, simd<T, Abi>> minmax(const simd<T, Abi>&, const simd<T, Abi>&) noexcept;
182 1.1 joerg
183 1.1 joerg template <class T, class Abi>
184 1.1 joerg simd<T, Abi> clamp(const simd<T, Abi>& v, const simd<T, Abi>& lo, const simd<T, Abi>& hi);
185 1.1 joerg
186 1.1 joerg // [simd.whereexpr]
187 1.1 joerg template <class M, class T>
188 1.1 joerg class const_where_expression {
189 1.1 joerg const M& mask; // exposition only
190 1.1 joerg T& data; // exposition only
191 1.1 joerg public:
192 1.1 joerg const_where_expression(const const_where_expression&) = delete;
193 1.1 joerg const_where_expression& operator=(const const_where_expression&) = delete;
194 1.1 joerg remove_const_t<T> operator-() const &&;
195 1.1 joerg template <class U, class Flags> void copy_to(U* mem, Flags f) const &&;
196 1.1 joerg };
197 1.1 joerg
198 1.1 joerg template <class M, class T>
199 1.1 joerg class where_expression : public const_where_expression<M, T> {
200 1.1 joerg public:
201 1.1 joerg where_expression(const where_expression&) = delete;
202 1.1 joerg where_expression& operator=(const where_expression&) = delete;
203 1.1 joerg template <class U> void operator=(U&& x);
204 1.1 joerg template <class U> void operator+=(U&& x);
205 1.1 joerg template <class U> void operator-=(U&& x);
206 1.1 joerg template <class U> void operator*=(U&& x);
207 1.1 joerg template <class U> void operator/=(U&& x);
208 1.1 joerg template <class U> void operator%=(U&& x);
209 1.1 joerg template <class U> void operator&=(U&& x);
210 1.1 joerg template <class U> void operator|=(U&& x);
211 1.1 joerg template <class U> void operator^=(U&& x);
212 1.1 joerg template <class U> void operator<<=(U&& x);
213 1.1 joerg template <class U> void operator>>=(U&& x);
214 1.1 joerg void operator++();
215 1.1 joerg void operator++(int);
216 1.1 joerg void operator--();
217 1.1 joerg void operator--(int);
218 1.1 joerg template <class U, class Flags> void copy_from(const U* mem, Flags);
219 1.1 joerg };
220 1.1 joerg
221 1.1 joerg // [simd.class]
222 1.1 joerg template <class T, class Abi> class simd {
223 1.1 joerg public:
224 1.1 joerg using value_type = T;
225 1.1 joerg using reference = see below;
226 1.1 joerg using mask_type = simd_mask<T, Abi>;
227 1.1 joerg
228 1.1 joerg using abi_type = Abi;
229 1.1 joerg static constexpr size_t size() noexcept;
230 1.1 joerg simd() = default;
231 1.1 joerg
232 1.1 joerg // implicit type conversion constructor
233 1.1 joerg template <class U> simd(const simd<U, simd_abi::fixed_size<size()>>&);
234 1.1 joerg
235 1.1 joerg // implicit broadcast constructor (see below for constraints)
236 1.1 joerg template <class U> simd(U&& value);
237 1.1 joerg
238 1.1 joerg // generator constructor (see below for constraints)
239 1.1 joerg template <class G> explicit simd(G&& gen);
240 1.1 joerg
241 1.1 joerg // load constructor
242 1.1 joerg template <class U, class Flags> simd(const U* mem, Flags f);
243 1.1 joerg
244 1.1 joerg // loads [simd.load]
245 1.1 joerg template <class U, class Flags> void copy_from(const U* mem, Flags f);
246 1.1 joerg
247 1.1 joerg // stores [simd.store]
248 1.1 joerg template <class U, class Flags> void copy_to(U* mem, Flags f) const;
249 1.1 joerg
250 1.1 joerg // scalar access [simd.subscr]
251 1.1 joerg reference operator[](size_t);
252 1.1 joerg value_type operator[](size_t) const;
253 1.1 joerg
254 1.1 joerg // unary operators [simd.unary]
255 1.1 joerg simd& operator++();
256 1.1 joerg simd operator++(int);
257 1.1 joerg simd& operator--();
258 1.1 joerg simd operator--(int);
259 1.1 joerg mask_type operator!() const;
260 1.1 joerg simd operator~() const; // see below
261 1.1 joerg simd operator+() const;
262 1.1 joerg simd operator-() const;
263 1.1 joerg
264 1.1 joerg // binary operators [simd.binary]
265 1.1 joerg friend simd operator+ (const simd&, const simd&);
266 1.1 joerg friend simd operator- (const simd&, const simd&);
267 1.1 joerg friend simd operator* (const simd&, const simd&);
268 1.1 joerg friend simd operator/ (const simd&, const simd&);
269 1.1 joerg friend simd operator% (const simd&, const simd&);
270 1.1 joerg friend simd operator& (const simd&, const simd&);
271 1.1 joerg friend simd operator| (const simd&, const simd&);
272 1.1 joerg friend simd operator^ (const simd&, const simd&);
273 1.1 joerg friend simd operator<<(const simd&, const simd&);
274 1.1 joerg friend simd operator>>(const simd&, const simd&);
275 1.1 joerg friend simd operator<<(const simd&, int);
276 1.1 joerg friend simd operator>>(const simd&, int);
277 1.1 joerg
278 1.1 joerg // compound assignment [simd.cassign]
279 1.1 joerg friend simd& operator+= (simd&, const simd&);
280 1.1 joerg friend simd& operator-= (simd&, const simd&);
281 1.1 joerg friend simd& operator*= (simd&, const simd&);
282 1.1 joerg friend simd& operator/= (simd&, const simd&);
283 1.1 joerg friend simd& operator%= (simd&, const simd&);
284 1.1 joerg
285 1.1 joerg friend simd& operator&= (simd&, const simd&);
286 1.1 joerg friend simd& operator|= (simd&, const simd&);
287 1.1 joerg friend simd& operator^= (simd&, const simd&);
288 1.1 joerg friend simd& operator<<=(simd&, const simd&);
289 1.1 joerg friend simd& operator>>=(simd&, const simd&);
290 1.1 joerg friend simd& operator<<=(simd&, int);
291 1.1 joerg friend simd& operator>>=(simd&, int);
292 1.1 joerg
293 1.1 joerg // compares [simd.comparison]
294 1.1 joerg friend mask_type operator==(const simd&, const simd&);
295 1.1 joerg friend mask_type operator!=(const simd&, const simd&);
296 1.1 joerg friend mask_type operator>=(const simd&, const simd&);
297 1.1 joerg friend mask_type operator<=(const simd&, const simd&);
298 1.1 joerg friend mask_type operator> (const simd&, const simd&);
299 1.1 joerg friend mask_type operator< (const simd&, const simd&);
300 1.1 joerg };
301 1.1 joerg
302 1.1 joerg // [simd.math]
303 1.1 joerg template <class Abi> using scharv = simd<signed char, Abi>; // exposition only
304 1.1 joerg template <class Abi> using shortv = simd<short, Abi>; // exposition only
305 1.1 joerg template <class Abi> using intv = simd<int, Abi>; // exposition only
306 1.1 joerg template <class Abi> using longv = simd<long int, Abi>; // exposition only
307 1.1 joerg template <class Abi> using llongv = simd<long long int, Abi>; // exposition only
308 1.1 joerg template <class Abi> using floatv = simd<float, Abi>; // exposition only
309 1.1 joerg template <class Abi> using doublev = simd<double, Abi>; // exposition only
310 1.1 joerg template <class Abi> using ldoublev = simd<long double, Abi>; // exposition only
311 1.1 joerg template <class T, class V> using samesize = fixed_size_simd<T, V::size()>; // exposition only
312 1.1 joerg
313 1.1 joerg template <class Abi> floatv<Abi> acos(floatv<Abi> x);
314 1.1 joerg template <class Abi> doublev<Abi> acos(doublev<Abi> x);
315 1.1 joerg template <class Abi> ldoublev<Abi> acos(ldoublev<Abi> x);
316 1.1 joerg
317 1.1 joerg template <class Abi> floatv<Abi> asin(floatv<Abi> x);
318 1.1 joerg template <class Abi> doublev<Abi> asin(doublev<Abi> x);
319 1.1 joerg template <class Abi> ldoublev<Abi> asin(ldoublev<Abi> x);
320 1.1 joerg
321 1.1 joerg template <class Abi> floatv<Abi> atan(floatv<Abi> x);
322 1.1 joerg template <class Abi> doublev<Abi> atan(doublev<Abi> x);
323 1.1 joerg template <class Abi> ldoublev<Abi> atan(ldoublev<Abi> x);
324 1.1 joerg
325 1.1 joerg template <class Abi> floatv<Abi> atan2(floatv<Abi> y, floatv<Abi> x);
326 1.1 joerg template <class Abi> doublev<Abi> atan2(doublev<Abi> y, doublev<Abi> x);
327 1.1 joerg template <class Abi> ldoublev<Abi> atan2(ldoublev<Abi> y, ldoublev<Abi> x);
328 1.1 joerg
329 1.1 joerg template <class Abi> floatv<Abi> cos(floatv<Abi> x);
330 1.1 joerg template <class Abi> doublev<Abi> cos(doublev<Abi> x);
331 1.1 joerg template <class Abi> ldoublev<Abi> cos(ldoublev<Abi> x);
332 1.1 joerg
333 1.1 joerg template <class Abi> floatv<Abi> sin(floatv<Abi> x);
334 1.1 joerg template <class Abi> doublev<Abi> sin(doublev<Abi> x);
335 1.1 joerg template <class Abi> ldoublev<Abi> sin(ldoublev<Abi> x);
336 1.1 joerg
337 1.1 joerg template <class Abi> floatv<Abi> tan(floatv<Abi> x);
338 1.1 joerg template <class Abi> doublev<Abi> tan(doublev<Abi> x);
339 1.1 joerg template <class Abi> ldoublev<Abi> tan(ldoublev<Abi> x);
340 1.1 joerg
341 1.1 joerg template <class Abi> floatv<Abi> acosh(floatv<Abi> x);
342 1.1 joerg template <class Abi> doublev<Abi> acosh(doublev<Abi> x);
343 1.1 joerg template <class Abi> ldoublev<Abi> acosh(ldoublev<Abi> x);
344 1.1 joerg
345 1.1 joerg template <class Abi> floatv<Abi> asinh(floatv<Abi> x);
346 1.1 joerg template <class Abi> doublev<Abi> asinh(doublev<Abi> x);
347 1.1 joerg template <class Abi> ldoublev<Abi> asinh(ldoublev<Abi> x);
348 1.1 joerg
349 1.1 joerg template <class Abi> floatv<Abi> atanh(floatv<Abi> x);
350 1.1 joerg template <class Abi> doublev<Abi> atanh(doublev<Abi> x);
351 1.1 joerg template <class Abi> ldoublev<Abi> atanh(ldoublev<Abi> x);
352 1.1 joerg
353 1.1 joerg template <class Abi> floatv<Abi> cosh(floatv<Abi> x);
354 1.1 joerg template <class Abi> doublev<Abi> cosh(doublev<Abi> x);
355 1.1 joerg template <class Abi> ldoublev<Abi> cosh(ldoublev<Abi> x);
356 1.1 joerg
357 1.1 joerg template <class Abi> floatv<Abi> sinh(floatv<Abi> x);
358 1.1 joerg template <class Abi> doublev<Abi> sinh(doublev<Abi> x);
359 1.1 joerg template <class Abi> ldoublev<Abi> sinh(ldoublev<Abi> x);
360 1.1 joerg
361 1.1 joerg template <class Abi> floatv<Abi> tanh(floatv<Abi> x);
362 1.1 joerg template <class Abi> doublev<Abi> tanh(doublev<Abi> x);
363 1.1 joerg template <class Abi> ldoublev<Abi> tanh(ldoublev<Abi> x);
364 1.1 joerg
365 1.1 joerg template <class Abi> floatv<Abi> exp(floatv<Abi> x);
366 1.1 joerg template <class Abi> doublev<Abi> exp(doublev<Abi> x);
367 1.1 joerg template <class Abi> ldoublev<Abi> exp(ldoublev<Abi> x);
368 1.1 joerg
369 1.1 joerg template <class Abi> floatv<Abi> exp2(floatv<Abi> x);
370 1.1 joerg template <class Abi> doublev<Abi> exp2(doublev<Abi> x);
371 1.1 joerg template <class Abi> ldoublev<Abi> exp2(ldoublev<Abi> x);
372 1.1 joerg
373 1.1 joerg template <class Abi> floatv<Abi> expm1(floatv<Abi> x);
374 1.1 joerg template <class Abi> doublev<Abi> expm1(doublev<Abi> x);
375 1.1 joerg template <class Abi> ldoublev<Abi> expm1(ldoublev<Abi> x);
376 1.1 joerg
377 1.1 joerg template <class Abi> floatv<Abi> frexp(floatv<Abi> value, samesize<int, floatv<Abi>>* exp);
378 1.1 joerg template <class Abi> doublev<Abi> frexp(doublev<Abi> value, samesize<int, doublev<Abi>>* exp);
379 1.1 joerg template <class Abi> ldoublev<Abi> frexp(ldoublev<Abi> value, samesize<int, ldoublev<Abi>>* exp);
380 1.1 joerg
381 1.1 joerg template <class Abi> samesize<int, floatv<Abi>> ilogb(floatv<Abi> x);
382 1.1 joerg template <class Abi> samesize<int, doublev<Abi>> ilogb(doublev<Abi> x);
383 1.1 joerg template <class Abi> samesize<int, ldoublev<Abi>> ilogb(ldoublev<Abi> x);
384 1.1 joerg
385 1.1 joerg template <class Abi> floatv<Abi> ldexp(floatv<Abi> x, samesize<int, floatv<Abi>> exp);
386 1.1 joerg template <class Abi> doublev<Abi> ldexp(doublev<Abi> x, samesize<int, doublev<Abi>> exp);
387 1.1 joerg template <class Abi> ldoublev<Abi> ldexp(ldoublev<Abi> x, samesize<int, ldoublev<Abi>> exp);
388 1.1 joerg
389 1.1 joerg template <class Abi> floatv<Abi> log(floatv<Abi> x);
390 1.1 joerg template <class Abi> doublev<Abi> log(doublev<Abi> x);
391 1.1 joerg template <class Abi> ldoublev<Abi> log(ldoublev<Abi> x);
392 1.1 joerg
393 1.1 joerg template <class Abi> floatv<Abi> log10(floatv<Abi> x);
394 1.1 joerg template <class Abi> doublev<Abi> log10(doublev<Abi> x);
395 1.1 joerg template <class Abi> ldoublev<Abi> log10(ldoublev<Abi> x);
396 1.1 joerg
397 1.1 joerg template <class Abi> floatv<Abi> log1p(floatv<Abi> x);
398 1.1 joerg template <class Abi> doublev<Abi> log1p(doublev<Abi> x);
399 1.1 joerg template <class Abi> ldoublev<Abi> log1p(ldoublev<Abi> x);
400 1.1 joerg
401 1.1 joerg template <class Abi> floatv<Abi> log2(floatv<Abi> x);
402 1.1 joerg template <class Abi> doublev<Abi> log2(doublev<Abi> x);
403 1.1 joerg template <class Abi> ldoublev<Abi> log2(ldoublev<Abi> x);
404 1.1 joerg
405 1.1 joerg template <class Abi> floatv<Abi> logb(floatv<Abi> x);
406 1.1 joerg template <class Abi> doublev<Abi> logb(doublev<Abi> x);
407 1.1 joerg template <class Abi> ldoublev<Abi> logb(ldoublev<Abi> x);
408 1.1 joerg
409 1.1 joerg template <class Abi> floatv<Abi> modf(floatv<Abi> value, floatv<Abi>* iptr);
410 1.1 joerg template <class Abi> doublev<Abi> modf(doublev<Abi> value, doublev<Abi>* iptr);
411 1.1 joerg template <class Abi> ldoublev<Abi> modf(ldoublev<Abi> value, ldoublev<Abi>* iptr);
412 1.1 joerg
413 1.1 joerg template <class Abi> floatv<Abi> scalbn(floatv<Abi> x, samesize<int, floatv<Abi>> n);
414 1.1 joerg template <class Abi> doublev<Abi> scalbn(doublev<Abi> x, samesize<int, doublev<Abi>> n);
415 1.1 joerg template <class Abi> ldoublev<Abi> scalbn(ldoublev<Abi> x, samesize<int, ldoublev<Abi>> n);
416 1.1 joerg template <class Abi> floatv<Abi> scalbln(floatv<Abi> x, samesize<long int, floatv<Abi>> n);
417 1.1 joerg template <class Abi> doublev<Abi> scalbln(doublev<Abi> x, samesize<long int, doublev<Abi>> n);
418 1.1 joerg template <class Abi> ldoublev<Abi> scalbln(ldoublev<Abi> x, samesize<long int, ldoublev<Abi>> n);
419 1.1 joerg
420 1.1 joerg template <class Abi> floatv<Abi> cbrt(floatv<Abi> x);
421 1.1 joerg template <class Abi> doublev<Abi> cbrt(doublev<Abi> x);
422 1.1 joerg template <class Abi> ldoublev<Abi> cbrt(ldoublev<Abi> x);
423 1.1 joerg
424 1.1 joerg template <class Abi> scharv<Abi> abs(scharv<Abi> j);
425 1.1 joerg template <class Abi> shortv<Abi> abs(shortv<Abi> j);
426 1.1 joerg template <class Abi> intv<Abi> abs(intv<Abi> j);
427 1.1 joerg template <class Abi> longv<Abi> abs(longv<Abi> j);
428 1.1 joerg template <class Abi> llongv<Abi> abs(llongv<Abi> j);
429 1.1 joerg template <class Abi> floatv<Abi> abs(floatv<Abi> j);
430 1.1 joerg template <class Abi> doublev<Abi> abs(doublev<Abi> j);
431 1.1 joerg template <class Abi> ldoublev<Abi> abs(ldoublev<Abi> j);
432 1.1 joerg
433 1.1 joerg template <class Abi> floatv<Abi> hypot(floatv<Abi> x, floatv<Abi> y);
434 1.1 joerg template <class Abi> doublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y);
435 1.1 joerg template <class Abi> ldoublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y);
436 1.1 joerg template <class Abi> floatv<Abi> hypot(floatv<Abi> x, floatv<Abi> y, floatv<Abi> z);
437 1.1 joerg template <class Abi> doublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y, doublev<Abi> z);
438 1.1 joerg template <class Abi> ldoublev<Abi> hypot(ldoublev<Abi> x, ldoublev<Abi> y, ldoublev<Abi> z);
439 1.1 joerg
440 1.1 joerg template <class Abi> floatv<Abi> pow(floatv<Abi> x, floatv<Abi> y);
441 1.1 joerg template <class Abi> doublev<Abi> pow(doublev<Abi> x, doublev<Abi> y);
442 1.1 joerg template <class Abi> ldoublev<Abi> pow(ldoublev<Abi> x, ldoublev<Abi> y);
443 1.1 joerg
444 1.1 joerg template <class Abi> floatv<Abi> sqrt(floatv<Abi> x);
445 1.1 joerg template <class Abi> doublev<Abi> sqrt(doublev<Abi> x);
446 1.1 joerg template <class Abi> ldoublev<Abi> sqrt(ldoublev<Abi> x);
447 1.1 joerg
448 1.1 joerg template <class Abi> floatv<Abi> erf(floatv<Abi> x);
449 1.1 joerg template <class Abi> doublev<Abi> erf(doublev<Abi> x);
450 1.1 joerg template <class Abi> ldoublev<Abi> erf(ldoublev<Abi> x);
451 1.1 joerg template <class Abi> floatv<Abi> erfc(floatv<Abi> x);
452 1.1 joerg template <class Abi> doublev<Abi> erfc(doublev<Abi> x);
453 1.1 joerg template <class Abi> ldoublev<Abi> erfc(ldoublev<Abi> x);
454 1.1 joerg
455 1.1 joerg template <class Abi> floatv<Abi> lgamma(floatv<Abi> x);
456 1.1 joerg template <class Abi> doublev<Abi> lgamma(doublev<Abi> x);
457 1.1 joerg template <class Abi> ldoublev<Abi> lgamma(ldoublev<Abi> x);
458 1.1 joerg
459 1.1 joerg template <class Abi> floatv<Abi> tgamma(floatv<Abi> x);
460 1.1 joerg template <class Abi> doublev<Abi> tgamma(doublev<Abi> x);
461 1.1 joerg template <class Abi> ldoublev<Abi> tgamma(ldoublev<Abi> x);
462 1.1 joerg
463 1.1 joerg template <class Abi> floatv<Abi> ceil(floatv<Abi> x);
464 1.1 joerg template <class Abi> doublev<Abi> ceil(doublev<Abi> x);
465 1.1 joerg template <class Abi> ldoublev<Abi> ceil(ldoublev<Abi> x);
466 1.1 joerg
467 1.1 joerg template <class Abi> floatv<Abi> floor(floatv<Abi> x);
468 1.1 joerg template <class Abi> doublev<Abi> floor(doublev<Abi> x);
469 1.1 joerg template <class Abi> ldoublev<Abi> floor(ldoublev<Abi> x);
470 1.1 joerg
471 1.1 joerg template <class Abi> floatv<Abi> nearbyint(floatv<Abi> x);
472 1.1 joerg template <class Abi> doublev<Abi> nearbyint(doublev<Abi> x);
473 1.1 joerg template <class Abi> ldoublev<Abi> nearbyint(ldoublev<Abi> x);
474 1.1 joerg
475 1.1 joerg template <class Abi> floatv<Abi> rint(floatv<Abi> x);
476 1.1 joerg template <class Abi> doublev<Abi> rint(doublev<Abi> x);
477 1.1 joerg template <class Abi> ldoublev<Abi> rint(ldoublev<Abi> x);
478 1.1 joerg
479 1.1 joerg template <class Abi> samesize<long int, floatv<Abi>> lrint(floatv<Abi> x);
480 1.1 joerg template <class Abi> samesize<long int, doublev<Abi>> lrint(doublev<Abi> x);
481 1.1 joerg template <class Abi> samesize<long int, ldoublev<Abi>> lrint(ldoublev<Abi> x);
482 1.1 joerg template <class Abi> samesize<long long int, floatv<Abi>> llrint(floatv<Abi> x);
483 1.1 joerg template <class Abi> samesize<long long int, doublev<Abi>> llrint(doublev<Abi> x);
484 1.1 joerg template <class Abi> samesize<long long int, ldoublev<Abi>> llrint(ldoublev<Abi> x);
485 1.1 joerg
486 1.1 joerg template <class Abi> floatv<Abi> round(floatv<Abi> x);
487 1.1 joerg template <class Abi> doublev<Abi> round(doublev<Abi> x);
488 1.1 joerg template <class Abi> ldoublev<Abi> round(ldoublev<Abi> x);
489 1.1 joerg template <class Abi> samesize<long int, floatv<Abi>> lround(floatv<Abi> x);
490 1.1 joerg template <class Abi> samesize<long int, doublev<Abi>> lround(doublev<Abi> x);
491 1.1 joerg template <class Abi> samesize<long int, ldoublev<Abi>> lround(ldoublev<Abi> x);
492 1.1 joerg template <class Abi> samesize<long long int, floatv<Abi>> llround(floatv<Abi> x);
493 1.1 joerg template <class Abi> samesize<long long int, doublev<Abi>> llround(doublev<Abi> x);
494 1.1 joerg template <class Abi> samesize<long long int, ldoublev<Abi>> llround(ldoublev<Abi> x);
495 1.1 joerg
496 1.1 joerg template <class Abi> floatv<Abi> trunc(floatv<Abi> x);
497 1.1 joerg template <class Abi> doublev<Abi> trunc(doublev<Abi> x);
498 1.1 joerg template <class Abi> ldoublev<Abi> trunc(ldoublev<Abi> x);
499 1.1 joerg
500 1.1 joerg template <class Abi> floatv<Abi> fmod(floatv<Abi> x, floatv<Abi> y);
501 1.1 joerg template <class Abi> doublev<Abi> fmod(doublev<Abi> x, doublev<Abi> y);
502 1.1 joerg template <class Abi> ldoublev<Abi> fmod(ldoublev<Abi> x, ldoublev<Abi> y);
503 1.1 joerg
504 1.1 joerg template <class Abi> floatv<Abi> remainder(floatv<Abi> x, floatv<Abi> y);
505 1.1 joerg template <class Abi> doublev<Abi> remainder(doublev<Abi> x, doublev<Abi> y);
506 1.1 joerg template <class Abi> ldoublev<Abi> remainder(ldoublev<Abi> x, ldoublev<Abi> y);
507 1.1 joerg
508 1.1 joerg template <class Abi> floatv<Abi> remquo(floatv<Abi> x, floatv<Abi> y, samesize<int, floatv<Abi>>* quo);
509 1.1 joerg template <class Abi> doublev<Abi> remquo(doublev<Abi> x, doublev<Abi> y, samesize<int, doublev<Abi>>* quo);
510 1.1 joerg template <class Abi> ldoublev<Abi> remquo(ldoublev<Abi> x, ldoublev<Abi> y, samesize<int, ldoublev<Abi>>* quo);
511 1.1 joerg
512 1.1 joerg template <class Abi> floatv<Abi> copysign(floatv<Abi> x, floatv<Abi> y);
513 1.1 joerg template <class Abi> doublev<Abi> copysign(doublev<Abi> x, doublev<Abi> y);
514 1.1 joerg template <class Abi> ldoublev<Abi> copysign(ldoublev<Abi> x, ldoublev<Abi> y);
515 1.1 joerg
516 1.1 joerg template <class Abi> doublev<Abi> nan(const char* tagp);
517 1.1 joerg template <class Abi> floatv<Abi> nanf(const char* tagp);
518 1.1 joerg template <class Abi> ldoublev<Abi> nanl(const char* tagp);
519 1.1 joerg
520 1.1 joerg template <class Abi> floatv<Abi> nextafter(floatv<Abi> x, floatv<Abi> y);
521 1.1 joerg template <class Abi> doublev<Abi> nextafter(doublev<Abi> x, doublev<Abi> y);
522 1.1 joerg template <class Abi> ldoublev<Abi> nextafter(ldoublev<Abi> x, ldoublev<Abi> y);
523 1.1 joerg
524 1.1 joerg template <class Abi> floatv<Abi> nexttoward(floatv<Abi> x, ldoublev<Abi> y);
525 1.1 joerg template <class Abi> doublev<Abi> nexttoward(doublev<Abi> x, ldoublev<Abi> y);
526 1.1 joerg template <class Abi> ldoublev<Abi> nexttoward(ldoublev<Abi> x, ldoublev<Abi> y);
527 1.1 joerg
528 1.1 joerg template <class Abi> floatv<Abi> fdim(floatv<Abi> x, floatv<Abi> y);
529 1.1 joerg template <class Abi> doublev<Abi> fdim(doublev<Abi> x, doublev<Abi> y);
530 1.1 joerg template <class Abi> ldoublev<Abi> fdim(ldoublev<Abi> x, ldoublev<Abi> y);
531 1.1 joerg
532 1.1 joerg template <class Abi> floatv<Abi> fmax(floatv<Abi> x, floatv<Abi> y);
533 1.1 joerg template <class Abi> doublev<Abi> fmax(doublev<Abi> x, doublev<Abi> y);
534 1.1 joerg template <class Abi> ldoublev<Abi> fmax(ldoublev<Abi> x, ldoublev<Abi> y);
535 1.1 joerg
536 1.1 joerg template <class Abi> floatv<Abi> fmin(floatv<Abi> x, floatv<Abi> y);
537 1.1 joerg template <class Abi> doublev<Abi> fmin(doublev<Abi> x, doublev<Abi> y);
538 1.1 joerg template <class Abi> ldoublev<Abi> fmin(ldoublev<Abi> x, ldoublev<Abi> y);
539 1.1 joerg
540 1.1 joerg template <class Abi> floatv<Abi> fma(floatv<Abi> x, floatv<Abi> y, floatv<Abi> z);
541 1.1 joerg template <class Abi> doublev<Abi> fma(doublev<Abi> x, doublev<Abi> y, doublev<Abi> z);
542 1.1 joerg template <class Abi> ldoublev<Abi> fma(ldoublev<Abi> x, ldoublev<Abi> y, ldoublev<Abi> z);
543 1.1 joerg
544 1.1 joerg template <class Abi> samesize<int, floatv<Abi>> fpclassify(floatv<Abi> x);
545 1.1 joerg template <class Abi> samesize<int, doublev<Abi>> fpclassify(doublev<Abi> x);
546 1.1 joerg template <class Abi> samesize<int, ldoublev<Abi>> fpclassify(ldoublev<Abi> x);
547 1.1 joerg
548 1.1 joerg template <class Abi> simd_mask<float, Abi> isfinite(floatv<Abi> x);
549 1.1 joerg template <class Abi> simd_mask<double, Abi> isfinite(doublev<Abi> x);
550 1.1 joerg template <class Abi> simd_mask<long double, Abi> isfinite(ldoublev<Abi> x);
551 1.1 joerg
552 1.1 joerg template <class Abi> simd_mask<float, Abi> isinf(floatv<Abi> x);
553 1.1 joerg template <class Abi> simd_mask<double, Abi> isinf(doublev<Abi> x);
554 1.1 joerg template <class Abi> simd_mask<long double, Abi> isinf(ldoublev<Abi> x);
555 1.1 joerg
556 1.1 joerg template <class Abi> simd_mask<float, Abi> isnan(floatv<Abi> x);
557 1.1 joerg template <class Abi> simd_mask<double, Abi> isnan(doublev<Abi> x);
558 1.1 joerg template <class Abi> simd_mask<long double, Abi> isnan(ldoublev<Abi> x);
559 1.1 joerg
560 1.1 joerg template <class Abi> simd_mask<float, Abi> isnormal(floatv<Abi> x);
561 1.1 joerg template <class Abi> simd_mask<double, Abi> isnormal(doublev<Abi> x);
562 1.1 joerg template <class Abi> simd_mask<long double, Abi> isnormal(ldoublev<Abi> x);
563 1.1 joerg
564 1.1 joerg template <class Abi> simd_mask<float, Abi> signbit(floatv<Abi> x);
565 1.1 joerg template <class Abi> simd_mask<double, Abi> signbit(doublev<Abi> x);
566 1.1 joerg template <class Abi> simd_mask<long double, Abi> signbit(ldoublev<Abi> x);
567 1.1 joerg
568 1.1 joerg template <class Abi> simd_mask<float, Abi> isgreater(floatv<Abi> x, floatv<Abi> y);
569 1.1 joerg template <class Abi> simd_mask<double, Abi> isgreater(doublev<Abi> x, doublev<Abi> y);
570 1.1 joerg template <class Abi> simd_mask<long double, Abi> isgreater(ldoublev<Abi> x, ldoublev<Abi> y);
571 1.1 joerg
572 1.1 joerg template <class Abi> simd_mask<float, Abi> isgreaterequal(floatv<Abi> x, floatv<Abi> y);
573 1.1 joerg template <class Abi> simd_mask<double, Abi> isgreaterequal(doublev<Abi> x, doublev<Abi> y);
574 1.1 joerg template <class Abi> simd_mask<long double, Abi> isgreaterequal(ldoublev<Abi> x, ldoublev<Abi> y);
575 1.1 joerg
576 1.1 joerg template <class Abi> simd_mask<float, Abi> isless(floatv<Abi> x, floatv<Abi> y);
577 1.1 joerg template <class Abi> simd_mask<double, Abi> isless(doublev<Abi> x, doublev<Abi> y);
578 1.1 joerg template <class Abi> simd_mask<long double, Abi> isless(ldoublev<Abi> x, ldoublev<Abi> y);
579 1.1 joerg
580 1.1 joerg template <class Abi> simd_mask<float, Abi> islessequal(floatv<Abi> x, floatv<Abi> y);
581 1.1 joerg template <class Abi> simd_mask<double, Abi> islessequal(doublev<Abi> x, doublev<Abi> y);
582 1.1 joerg template <class Abi> simd_mask<long double, Abi> islessequal(ldoublev<Abi> x, ldoublev<Abi> y);
583 1.1 joerg
584 1.1 joerg template <class Abi> simd_mask<float, Abi> islessgreater(floatv<Abi> x, floatv<Abi> y);
585 1.1 joerg template <class Abi> simd_mask<double, Abi> islessgreater(doublev<Abi> x, doublev<Abi> y);
586 1.1 joerg template <class Abi> simd_mask<long double, Abi> islessgreater(ldoublev<Abi> x, ldoublev<Abi> y);
587 1.1 joerg
588 1.1 joerg template <class Abi> simd_mask<float, Abi> isunordered(floatv<Abi> x, floatv<Abi> y);
589 1.1 joerg template <class Abi> simd_mask<double, Abi> isunordered(doublev<Abi> x, doublev<Abi> y);
590 1.1 joerg template <class Abi> simd_mask<long double, Abi> isunordered(ldoublev<Abi> x, ldoublev<Abi> y);
591 1.1 joerg
592 1.1 joerg template <class V> struct simd_div_t { V quot, rem; };
593 1.1 joerg template <class Abi> simd_div_t<scharv<Abi>> div(scharv<Abi> numer, scharv<Abi> denom);
594 1.1 joerg template <class Abi> simd_div_t<shortv<Abi>> div(shortv<Abi> numer, shortv<Abi> denom);
595 1.1 joerg template <class Abi> simd_div_t<intv<Abi>> div(intv<Abi> numer, intv<Abi> denom);
596 1.1 joerg template <class Abi> simd_div_t<longv<Abi>> div(longv<Abi> numer, longv<Abi> denom);
597 1.1 joerg template <class Abi> simd_div_t<llongv<Abi>> div(llongv<Abi> numer, llongv<Abi> denom);
598 1.1 joerg
599 1.1 joerg // [simd.mask.class]
600 1.1 joerg template <class T, class Abi>
601 1.1 joerg class simd_mask {
602 1.1 joerg public:
603 1.1 joerg using value_type = bool;
604 1.1 joerg using reference = see below;
605 1.1 joerg using simd_type = simd<T, Abi>;
606 1.1 joerg using abi_type = Abi;
607 1.1 joerg static constexpr size_t size() noexcept;
608 1.1 joerg simd_mask() = default;
609 1.1 joerg
610 1.1 joerg // broadcast constructor
611 1.1 joerg explicit simd_mask(value_type) noexcept;
612 1.1 joerg
613 1.1 joerg // implicit type conversion constructor
614 1.1 joerg template <class U> simd_mask(const simd_mask<U, simd_abi::fixed_size<size()>>&) noexcept;
615 1.1 joerg
616 1.1 joerg // load constructor
617 1.1 joerg template <class Flags> simd_mask(const value_type* mem, Flags);
618 1.1 joerg
619 1.1 joerg // loads [simd.mask.copy]
620 1.1 joerg template <class Flags> void copy_from(const value_type* mem, Flags);
621 1.1 joerg template <class Flags> void copy_to(value_type* mem, Flags) const;
622 1.1 joerg
623 1.1 joerg // scalar access [simd.mask.subscr]
624 1.1 joerg reference operator[](size_t);
625 1.1 joerg value_type operator[](size_t) const;
626 1.1 joerg
627 1.1 joerg // unary operators [simd.mask.unary]
628 1.1 joerg simd_mask operator!() const noexcept;
629 1.1 joerg
630 1.1 joerg // simd_mask binary operators [simd.mask.binary]
631 1.1 joerg friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept;
632 1.1 joerg friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept;
633 1.1 joerg friend simd_mask operator& (const simd_mask&, const simd_mask&) noexcept;
634 1.1 joerg friend simd_mask operator| (const simd_mask&, const simd_mask&) noexcept;
635 1.1 joerg friend simd_mask operator^ (const simd_mask&, const simd_mask&) noexcept;
636 1.1 joerg
637 1.1 joerg // simd_mask compound assignment [simd.mask.cassign]
638 1.1 joerg friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept;
639 1.1 joerg friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept;
640 1.1 joerg friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept;
641 1.1 joerg
642 1.1 joerg // simd_mask compares [simd.mask.comparison]
643 1.1 joerg friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept;
644 1.1 joerg friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept;
645 1.1 joerg };
646 1.1 joerg
647 1.1 joerg } // parallelism_v2
648 1.1 joerg } // std::experimental
649 1.1 joerg
650 1.1 joerg */
651 1.1 joerg
652 1.1 joerg #include <experimental/__config>
653 1.1 joerg #include <algorithm>
654 1.1 joerg #include <array>
655 1.1 joerg #include <cstddef>
656 1.1 joerg #include <functional>
657 1.1 joerg
658 1.1 joerg #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
659 1.1 joerg #pragma GCC system_header
660 1.1 joerg #endif
661 1.1 joerg
662 1.1 joerg _LIBCPP_PUSH_MACROS
663 1.1 joerg #include <__undef_macros>
664 1.1 joerg
665 1.1 joerg _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD
666 1.1 joerg
667 1.1 joerg #if _LIBCPP_STD_VER >= 17
668 1.1 joerg
669 1.1 joerg enum class _StorageKind {
670 1.1 joerg _Scalar,
671 1.1 joerg _Array,
672 1.1 joerg _VecExt,
673 1.1 joerg };
674 1.1 joerg
675 1.1 joerg template <_StorageKind __kind, int _Np>
676 1.1 joerg struct __simd_abi {};
677 1.1 joerg
678 1.1 joerg template <class _Tp, class _Abi>
679 1.1 joerg class __simd_storage {};
680 1.1 joerg
681 1.1 joerg template <class _Tp, int __num_element>
682 1.1 joerg class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> {
683 1.1 joerg std::array<_Tp, __num_element> __storage_;
684 1.1 joerg
685 1.1 joerg template <class, class>
686 1.1 joerg friend struct simd;
687 1.1 joerg
688 1.1 joerg template <class, class>
689 1.1 joerg friend struct simd_mask;
690 1.1 joerg
691 1.1 joerg public:
692 1.1 joerg _Tp __get(size_t __index) const noexcept { return __storage_[__index]; };
693 1.1 joerg void __set(size_t __index, _Tp __val) noexcept {
694 1.1 joerg __storage_[__index] = __val;
695 1.1 joerg }
696 1.1 joerg };
697 1.1 joerg
698 1.1 joerg template <class _Tp>
699 1.1 joerg class __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> {
700 1.1 joerg _Tp __storage_;
701 1.1 joerg
702 1.1 joerg template <class, class>
703 1.1 joerg friend struct simd;
704 1.1 joerg
705 1.1 joerg template <class, class>
706 1.1 joerg friend struct simd_mask;
707 1.1 joerg
708 1.1 joerg public:
709 1.1 joerg _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; };
710 1.1 joerg void __set(size_t __index, _Tp __val) noexcept {
711 1.1 joerg (&__storage_)[__index] = __val;
712 1.1 joerg }
713 1.1 joerg };
714 1.1 joerg
715 1.1 joerg #ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION
716 1.1 joerg
717 1.1 joerg constexpr size_t __floor_pow_of_2(size_t __val) {
718 1.1 joerg return ((__val - 1) & __val) == 0 ? __val
719 1.1 joerg : __floor_pow_of_2((__val - 1) & __val);
720 1.1 joerg }
721 1.1 joerg
722 1.1 joerg constexpr size_t __ceil_pow_of_2(size_t __val) {
723 1.1 joerg return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1;
724 1.1 joerg }
725 1.1 joerg
726 1.1 joerg template <class _Tp, size_t __bytes>
727 1.1 joerg struct __vec_ext_traits {
728 1.1 joerg #if !defined(_LIBCPP_COMPILER_CLANG_BASED)
729 1.1 joerg typedef _Tp type __attribute__((vector_size(__ceil_pow_of_2(__bytes))));
730 1.1 joerg #endif
731 1.1 joerg };
732 1.1 joerg
733 1.1 joerg #if defined(_LIBCPP_COMPILER_CLANG_BASED)
734 1.1 joerg #define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \
735 1.1 joerg template <> \
736 1.1 joerg struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \
737 1.1 joerg using type = \
738 1.1 joerg _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \
739 1.1 joerg }
740 1.1 joerg
741 1.1 joerg #define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \
742 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \
743 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \
744 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \
745 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \
746 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \
747 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \
748 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \
749 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \
750 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \
751 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \
752 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \
753 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \
754 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \
755 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \
756 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \
757 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \
758 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \
759 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \
760 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \
761 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \
762 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \
763 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \
764 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \
765 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \
766 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \
767 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \
768 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \
769 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \
770 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \
771 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \
772 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \
773 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32);
774 1.1 joerg
775 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(char);
776 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(char16_t);
777 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(char32_t);
778 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(wchar_t);
779 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(signed char);
780 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(signed short);
781 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(signed int);
782 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(signed long);
783 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(signed long long);
784 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned char);
785 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned short);
786 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned int);
787 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long);
788 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long long);
789 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(float);
790 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(double);
791 1.1 joerg _LIBCPP_SPECIALIZE_VEC_EXT_32(long double);
792 1.1 joerg
793 1.1 joerg #undef _LIBCPP_SPECIALIZE_VEC_EXT_32
794 1.1 joerg #undef _LIBCPP_SPECIALIZE_VEC_EXT
795 1.1 joerg #endif
796 1.1 joerg
797 1.1 joerg template <class _Tp, int __num_element>
798 1.1 joerg class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> {
799 1.1 joerg using _StorageType =
800 1.1 joerg typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type;
801 1.1 joerg
802 1.1 joerg _StorageType __storage_;
803 1.1 joerg
804 1.1 joerg template <class, class>
805 1.1 joerg friend struct simd;
806 1.1 joerg
807 1.1 joerg template <class, class>
808 1.1 joerg friend struct simd_mask;
809 1.1 joerg
810 1.1 joerg public:
811 1.1 joerg _Tp __get(size_t __index) const noexcept { return __storage_[__index]; };
812 1.1 joerg void __set(size_t __index, _Tp __val) noexcept {
813 1.1 joerg __storage_[__index] = __val;
814 1.1 joerg }
815 1.1 joerg };
816 1.1 joerg
817 1.1 joerg #endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION
818 1.1 joerg
819 1.1 joerg template <class _Vp, class _Tp, class _Abi>
820 1.1 joerg class __simd_reference {
821 1.1 joerg static_assert(std::is_same<_Vp, _Tp>::value, "");
822 1.1 joerg
823 1.1 joerg template <class, class>
824 1.1 joerg friend struct simd;
825 1.1 joerg
826 1.1 joerg template <class, class>
827 1.1 joerg friend struct simd_mask;
828 1.1 joerg
829 1.1 joerg __simd_storage<_Tp, _Abi>* __ptr_;
830 1.1 joerg size_t __index_;
831 1.1 joerg
832 1.1 joerg __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index)
833 1.1 joerg : __ptr_(__ptr), __index_(__index) {}
834 1.1 joerg
835 1.1 joerg __simd_reference(const __simd_reference&) = default;
836 1.1 joerg
837 1.1 joerg public:
838 1.1 joerg __simd_reference() = delete;
839 1.1 joerg __simd_reference& operator=(const __simd_reference&) = delete;
840 1.1 joerg
841 1.1 joerg operator _Vp() const { return __ptr_->__get(__index_); }
842 1.1 joerg
843 1.1 joerg __simd_reference operator=(_Vp __value) && {
844 1.1 joerg __ptr_->__set(__index_, __value);
845 1.1 joerg return *this;
846 1.1 joerg }
847 1.1 joerg
848 1.1 joerg __simd_reference operator++() && {
849 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) + 1;
850 1.1 joerg }
851 1.1 joerg
852 1.1 joerg _Vp operator++(int) && {
853 1.1 joerg auto __val = __ptr_->__get(__index_);
854 1.1 joerg __ptr_->__set(__index_, __val + 1);
855 1.1 joerg return __val;
856 1.1 joerg }
857 1.1 joerg
858 1.1 joerg __simd_reference operator--() && {
859 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) - 1;
860 1.1 joerg }
861 1.1 joerg
862 1.1 joerg _Vp operator--(int) && {
863 1.1 joerg auto __val = __ptr_->__get(__index_);
864 1.1 joerg __ptr_->__set(__index_, __val - 1);
865 1.1 joerg return __val;
866 1.1 joerg }
867 1.1 joerg
868 1.1 joerg __simd_reference operator+=(_Vp __value) && {
869 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) + __value;
870 1.1 joerg }
871 1.1 joerg
872 1.1 joerg __simd_reference operator-=(_Vp __value) && {
873 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) - __value;
874 1.1 joerg }
875 1.1 joerg
876 1.1 joerg __simd_reference operator*=(_Vp __value) && {
877 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) * __value;
878 1.1 joerg }
879 1.1 joerg
880 1.1 joerg __simd_reference operator/=(_Vp __value) && {
881 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) / __value;
882 1.1 joerg }
883 1.1 joerg
884 1.1 joerg __simd_reference operator%=(_Vp __value) && {
885 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) % __value;
886 1.1 joerg }
887 1.1 joerg
888 1.1 joerg __simd_reference operator>>=(_Vp __value) && {
889 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) >> __value;
890 1.1 joerg }
891 1.1 joerg
892 1.1 joerg __simd_reference operator<<=(_Vp __value) && {
893 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) << __value;
894 1.1 joerg }
895 1.1 joerg
896 1.1 joerg __simd_reference operator&=(_Vp __value) && {
897 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) & __value;
898 1.1 joerg }
899 1.1 joerg
900 1.1 joerg __simd_reference operator|=(_Vp __value) && {
901 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) | __value;
902 1.1 joerg }
903 1.1 joerg
904 1.1 joerg __simd_reference operator^=(_Vp __value) && {
905 1.1 joerg return std::move(*this) = __ptr_->__get(__index_) ^ __value;
906 1.1 joerg }
907 1.1 joerg };
908 1.1 joerg
909 1.1 joerg template <class _To, class _From>
910 1.1 joerg constexpr decltype(_To{std::declval<_From>()}, true)
911 1.1 joerg __is_non_narrowing_convertible_impl(_From) {
912 1.1 joerg return true;
913 1.1 joerg }
914 1.1 joerg
915 1.1 joerg template <class _To>
916 1.1 joerg constexpr bool __is_non_narrowing_convertible_impl(...) {
917 1.1 joerg return false;
918 1.1 joerg }
919 1.1 joerg
920 1.1 joerg template <class _From, class _To>
921 1.1 joerg constexpr typename std::enable_if<std::is_arithmetic<_To>::value &&
922 1.1 joerg std::is_arithmetic<_From>::value,
923 1.1 joerg bool>::type
924 1.1 joerg __is_non_narrowing_arithmetic_convertible() {
925 1.1 joerg return __is_non_narrowing_convertible_impl<_To>(_From{});
926 1.1 joerg }
927 1.1 joerg
928 1.1 joerg template <class _From, class _To>
929 1.1 joerg constexpr typename std::enable_if<!(std::is_arithmetic<_To>::value &&
930 1.1 joerg std::is_arithmetic<_From>::value),
931 1.1 joerg bool>::type
932 1.1 joerg __is_non_narrowing_arithmetic_convertible() {
933 1.1 joerg return false;
934 1.1 joerg }
935 1.1 joerg
936 1.1 joerg template <class _Tp>
937 1.1 joerg constexpr _Tp __variadic_sum() {
938 1.1 joerg return _Tp{};
939 1.1 joerg }
940 1.1 joerg
941 1.1 joerg template <class _Tp, class _Up, class... _Args>
942 1.1 joerg constexpr _Tp __variadic_sum(_Up __first, _Args... __rest) {
943 1.1 joerg return static_cast<_Tp>(__first) + __variadic_sum<_Tp>(__rest...);
944 1.1 joerg }
945 1.1 joerg
946 1.1 joerg template <class _Tp>
947 1.1 joerg struct __nodeduce {
948 1.1 joerg using type = _Tp;
949 1.1 joerg };
950 1.1 joerg
951 1.1 joerg template <class _Tp>
952 1.1 joerg constexpr bool __vectorizable() {
953 1.1 joerg return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value &&
954 1.1 joerg !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value;
955 1.1 joerg }
956 1.1 joerg
957 1.1 joerg _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD
958 1.1 joerg _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD_ABI
959 1.1 joerg
960 1.1 joerg using scalar = __simd_abi<_StorageKind::_Scalar, 1>;
961 1.1 joerg
962 1.1 joerg template <int _Np>
963 1.1 joerg using fixed_size = __simd_abi<_StorageKind::_Array, _Np>;
964 1.1 joerg
965 1.1 joerg template <class _Tp>
966 1.1 joerg _LIBCPP_INLINE_VAR constexpr size_t max_fixed_size = 32;
967 1.1 joerg
968 1.1 joerg template <class _Tp>
969 1.1 joerg using compatible = fixed_size<16 / sizeof(_Tp)>;
970 1.1 joerg
971 1.1 joerg #ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION
972 1.1 joerg template <class _Tp>
973 1.1 joerg using native = __simd_abi<_StorageKind::_VecExt,
974 1.1 joerg _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>;
975 1.1 joerg #else
976 1.1 joerg template <class _Tp>
977 1.1 joerg using native =
978 1.1 joerg fixed_size<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>;
979 1.1 joerg #endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION
980 1.1 joerg
981 1.1 joerg _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI
982 1.1 joerg _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD
983 1.1 joerg
984 1.1 joerg template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
985 1.1 joerg class simd;
986 1.1 joerg template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
987 1.1 joerg class simd_mask;
988 1.1 joerg
989 1.1 joerg struct element_aligned_tag {};
990 1.1 joerg struct vector_aligned_tag {};
991 1.1 joerg template <size_t>
992 1.1 joerg struct overaligned_tag {};
993 1.1 joerg _LIBCPP_INLINE_VAR constexpr element_aligned_tag element_aligned{};
994 1.1 joerg _LIBCPP_INLINE_VAR constexpr vector_aligned_tag vector_aligned{};
995 1.1 joerg template <size_t _Np>
996 1.1 joerg _LIBCPP_INLINE_VAR constexpr overaligned_tag<_Np> overaligned{};
997 1.1 joerg
998 1.1 joerg // traits [simd.traits]
999 1.1 joerg template <class _Tp>
1000 1.1 joerg struct is_abi_tag : std::integral_constant<bool, false> {};
1001 1.1 joerg
1002 1.1 joerg template <_StorageKind __kind, int _Np>
1003 1.1 joerg struct is_abi_tag<__simd_abi<__kind, _Np>>
1004 1.1 joerg : std::integral_constant<bool, true> {};
1005 1.1 joerg
1006 1.1 joerg template <class _Tp>
1007 1.1 joerg struct is_simd : std::integral_constant<bool, false> {};
1008 1.1 joerg
1009 1.1 joerg template <class _Tp, class _Abi>
1010 1.1 joerg struct is_simd<simd<_Tp, _Abi>> : std::integral_constant<bool, true> {};
1011 1.1 joerg
1012 1.1 joerg template <class _Tp>
1013 1.1 joerg struct is_simd_mask : std::integral_constant<bool, false> {};
1014 1.1 joerg
1015 1.1 joerg template <class _Tp, class _Abi>
1016 1.1 joerg struct is_simd_mask<simd_mask<_Tp, _Abi>> : std::integral_constant<bool, true> {
1017 1.1 joerg };
1018 1.1 joerg
1019 1.1 joerg template <class _Tp>
1020 1.1 joerg struct is_simd_flag_type : std::integral_constant<bool, false> {};
1021 1.1 joerg
1022 1.1 joerg template <>
1023 1.1 joerg struct is_simd_flag_type<element_aligned_tag>
1024 1.1 joerg : std::integral_constant<bool, true> {};
1025 1.1 joerg
1026 1.1 joerg template <>
1027 1.1 joerg struct is_simd_flag_type<vector_aligned_tag>
1028 1.1 joerg : std::integral_constant<bool, true> {};
1029 1.1 joerg
1030 1.1 joerg template <size_t _Align>
1031 1.1 joerg struct is_simd_flag_type<overaligned_tag<_Align>>
1032 1.1 joerg : std::integral_constant<bool, true> {};
1033 1.1 joerg
1034 1.1 joerg template <class _Tp>
1035 1.1 joerg _LIBCPP_INLINE_VAR constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value;
1036 1.1 joerg template <class _Tp>
1037 1.1 joerg _LIBCPP_INLINE_VAR constexpr bool is_simd_v = is_simd<_Tp>::value;
1038 1.1 joerg template <class _Tp>
1039 1.1 joerg _LIBCPP_INLINE_VAR constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value;
1040 1.1 joerg template <class _Tp>
1041 1.1 joerg _LIBCPP_INLINE_VAR constexpr bool is_simd_flag_type_v =
1042 1.1 joerg is_simd_flag_type<_Tp>::value;
1043 1.1 joerg template <class _Tp, size_t _Np>
1044 1.1 joerg struct abi_for_size {
1045 1.1 joerg using type = simd_abi::fixed_size<_Np>;
1046 1.1 joerg };
1047 1.1 joerg template <class _Tp, size_t _Np>
1048 1.1 joerg using abi_for_size_t = typename abi_for_size<_Tp, _Np>::type;
1049 1.1 joerg
1050 1.1 joerg template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
1051 1.1 joerg struct simd_size;
1052 1.1 joerg
1053 1.1 joerg template <class _Tp, _StorageKind __kind, int _Np>
1054 1.1 joerg struct simd_size<_Tp, __simd_abi<__kind, _Np>>
1055 1.1 joerg : std::integral_constant<size_t, _Np> {
1056 1.1 joerg static_assert(
1057 1.1 joerg std::is_arithmetic<_Tp>::value &&
1058 1.1 joerg !std::is_same<typename std::remove_const<_Tp>::type, bool>::value,
1059 1.1 joerg "Element type should be vectorizable");
1060 1.1 joerg };
1061 1.1 joerg
1062 1.1 joerg // TODO: implement it.
1063 1.1 joerg template <class _Tp, class _Up = typename _Tp::value_type>
1064 1.1 joerg struct memory_alignment;
1065 1.1 joerg
1066 1.1 joerg template <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
1067 1.1 joerg _LIBCPP_INLINE_VAR constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value;
1068 1.1 joerg
1069 1.1 joerg template <class _Tp, class _Up = typename _Tp::value_type>
1070 1.1 joerg _LIBCPP_INLINE_VAR constexpr size_t memory_alignment_v =
1071 1.1 joerg memory_alignment<_Tp, _Up>::value;
1072 1.1 joerg
1073 1.1 joerg // class template simd [simd.class]
1074 1.1 joerg template <class _Tp>
1075 1.1 joerg using native_simd = simd<_Tp, simd_abi::native<_Tp>>;
1076 1.1 joerg template <class _Tp, int _Np>
1077 1.1 joerg using fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>;
1078 1.1 joerg
1079 1.1 joerg // class template simd_mask [simd.mask.class]
1080 1.1 joerg template <class _Tp>
1081 1.1 joerg using native_simd_mask = simd_mask<_Tp, simd_abi::native<_Tp>>;
1082 1.1 joerg
1083 1.1 joerg template <class _Tp, int _Np>
1084 1.1 joerg using fixed_size_simd_mask = simd_mask<_Tp, simd_abi::fixed_size<_Np>>;
1085 1.1 joerg
1086 1.1 joerg // casts [simd.casts]
1087 1.1 joerg template <class _Tp>
1088 1.1 joerg struct __static_simd_cast_traits {
1089 1.1 joerg template <class _Up, class _Abi>
1090 1.1 joerg static simd<_Tp, _Abi> __apply(const simd<_Up, _Abi>& __v);
1091 1.1 joerg };
1092 1.1 joerg
1093 1.1 joerg template <class _Tp, class _NewAbi>
1094 1.1 joerg struct __static_simd_cast_traits<simd<_Tp, _NewAbi>> {
1095 1.1 joerg template <class _Up, class _Abi>
1096 1.1 joerg static typename std::enable_if<simd<_Up, _Abi>::size() ==
1097 1.1 joerg simd<_Tp, _NewAbi>::size(),
1098 1.1 joerg simd<_Tp, _NewAbi>>::type
1099 1.1 joerg __apply(const simd<_Up, _Abi>& __v);
1100 1.1 joerg };
1101 1.1 joerg
1102 1.1 joerg template <class _Tp>
1103 1.1 joerg struct __simd_cast_traits {
1104 1.1 joerg template <class _Up, class _Abi>
1105 1.1 joerg static typename std::enable_if<
1106 1.1 joerg __is_non_narrowing_arithmetic_convertible<_Up, _Tp>(),
1107 1.1 joerg simd<_Tp, _Abi>>::type
1108 1.1 joerg __apply(const simd<_Up, _Abi>& __v);
1109 1.1 joerg };
1110 1.1 joerg
1111 1.1 joerg template <class _Tp, class _NewAbi>
1112 1.1 joerg struct __simd_cast_traits<simd<_Tp, _NewAbi>> {
1113 1.1 joerg template <class _Up, class _Abi>
1114 1.1 joerg static typename std::enable_if<
1115 1.1 joerg __is_non_narrowing_arithmetic_convertible<_Up, _Tp>() &&
1116 1.1 joerg simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(),
1117 1.1 joerg simd<_Tp, _NewAbi>>::type
1118 1.1 joerg __apply(const simd<_Up, _Abi>& __v);
1119 1.1 joerg };
1120 1.1 joerg
1121 1.1 joerg template <class _Tp, class _Up, class _Abi>
1122 1.1 joerg auto simd_cast(const simd<_Up, _Abi>& __v)
1123 1.1 joerg -> decltype(__simd_cast_traits<_Tp>::__apply(__v)) {
1124 1.1 joerg return __simd_cast_traits<_Tp>::__apply(__v);
1125 1.1 joerg }
1126 1.1 joerg
1127 1.1 joerg template <class _Tp, class _Up, class _Abi>
1128 1.1 joerg auto static_simd_cast(const simd<_Up, _Abi>& __v)
1129 1.1 joerg -> decltype(__static_simd_cast_traits<_Tp>::__apply(__v)) {
1130 1.1 joerg return __static_simd_cast_traits<_Tp>::__apply(__v);
1131 1.1 joerg }
1132 1.1 joerg
1133 1.1 joerg template <class _Tp, class _Abi>
1134 1.1 joerg fixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value>
1135 1.1 joerg to_fixed_size(const simd<_Tp, _Abi>&) noexcept;
1136 1.1 joerg
1137 1.1 joerg template <class _Tp, class _Abi>
1138 1.1 joerg fixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value>
1139 1.1 joerg to_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept;
1140 1.1 joerg
1141 1.1 joerg template <class _Tp, size_t _Np>
1142 1.1 joerg native_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept;
1143 1.1 joerg
1144 1.1 joerg template <class _Tp, size_t _Np>
1145 1.1 joerg native_simd_mask<_Tp> to_native(const fixed_size_simd_mask<_Tp, _Np>&) noexcept;
1146 1.1 joerg
1147 1.1 joerg template <class _Tp, size_t _Np>
1148 1.1 joerg simd<_Tp> to_compatible(const fixed_size_simd<_Tp, _Np>&) noexcept;
1149 1.1 joerg
1150 1.1 joerg template <class _Tp, size_t _Np>
1151 1.1 joerg simd_mask<_Tp> to_compatible(const fixed_size_simd_mask<_Tp, _Np>&) noexcept;
1152 1.1 joerg
1153 1.1 joerg template <size_t... __sizes, class _Tp, class _Abi>
1154 1.1 joerg tuple<simd<_Tp, abi_for_size_t<_Tp, __sizes>>...> split(const simd<_Tp, _Abi>&);
1155 1.1 joerg
1156 1.1 joerg template <size_t... __sizes, class _Tp, class _Abi>
1157 1.1 joerg tuple<simd_mask<_Tp, abi_for_size_t<_Tp, __sizes>>...>
1158 1.1 joerg split(const simd_mask<_Tp, _Abi>&);
1159 1.1 joerg
1160 1.1 joerg template <class _SimdType, class _Abi>
1161 1.1 joerg array<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value /
1162 1.1 joerg _SimdType::size()>
1163 1.1 joerg split(const simd<typename _SimdType::value_type, _Abi>&);
1164 1.1 joerg
1165 1.1 joerg template <class _SimdType, class _Abi>
1166 1.1 joerg array<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value /
1167 1.1 joerg _SimdType::size()>
1168 1.1 joerg split(const simd_mask<typename _SimdType::value_type, _Abi>&);
1169 1.1 joerg
1170 1.1 joerg template <class _Tp, class... _Abis>
1171 1.1 joerg simd<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>>
1172 1.1 joerg concat(const simd<_Tp, _Abis>&...);
1173 1.1 joerg
1174 1.1 joerg template <class _Tp, class... _Abis>
1175 1.1 joerg simd_mask<_Tp,
1176 1.1 joerg abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>>
1177 1.1 joerg concat(const simd_mask<_Tp, _Abis>&...);
1178 1.1 joerg
1179 1.1 joerg // reductions [simd.mask.reductions]
1180 1.1 joerg template <class _Tp, class _Abi>
1181 1.1 joerg bool all_of(const simd_mask<_Tp, _Abi>&) noexcept;
1182 1.1 joerg template <class _Tp, class _Abi>
1183 1.1 joerg bool any_of(const simd_mask<_Tp, _Abi>&) noexcept;
1184 1.1 joerg template <class _Tp, class _Abi>
1185 1.1 joerg bool none_of(const simd_mask<_Tp, _Abi>&) noexcept;
1186 1.1 joerg template <class _Tp, class _Abi>
1187 1.1 joerg bool some_of(const simd_mask<_Tp, _Abi>&) noexcept;
1188 1.1 joerg template <class _Tp, class _Abi>
1189 1.1 joerg int popcount(const simd_mask<_Tp, _Abi>&) noexcept;
1190 1.1 joerg template <class _Tp, class _Abi>
1191 1.1 joerg int find_first_set(const simd_mask<_Tp, _Abi>&);
1192 1.1 joerg template <class _Tp, class _Abi>
1193 1.1 joerg int find_last_set(const simd_mask<_Tp, _Abi>&);
1194 1.1 joerg bool all_of(bool) noexcept;
1195 1.1 joerg bool any_of(bool) noexcept;
1196 1.1 joerg bool none_of(bool) noexcept;
1197 1.1 joerg bool some_of(bool) noexcept;
1198 1.1 joerg int popcount(bool) noexcept;
1199 1.1 joerg int find_first_set(bool) noexcept;
1200 1.1 joerg int find_last_set(bool) noexcept;
1201 1.1 joerg
1202 1.1 joerg // masked assignment [simd.whereexpr]
1203 1.1 joerg template <class _MaskType, class _Tp>
1204 1.1 joerg class const_where_expression;
1205 1.1 joerg template <class _MaskType, class _Tp>
1206 1.1 joerg class where_expression;
1207 1.1 joerg
1208 1.1 joerg // masked assignment [simd.mask.where]
1209 1.1 joerg template <class _Tp, class _Abi>
1210 1.1 joerg where_expression<simd_mask<_Tp, _Abi>, simd<_Tp, _Abi>>
1211 1.1 joerg where(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept;
1212 1.1 joerg
1213 1.1 joerg template <class _Tp, class _Abi>
1214 1.1 joerg const_where_expression<simd_mask<_Tp, _Abi>, const simd<_Tp, _Abi>>
1215 1.1 joerg where(const typename simd<_Tp, _Abi>::mask_type&,
1216 1.1 joerg const simd<_Tp, _Abi>&) noexcept;
1217 1.1 joerg
1218 1.1 joerg template <class _Tp, class _Abi>
1219 1.1 joerg where_expression<simd_mask<_Tp, _Abi>, simd_mask<_Tp, _Abi>>
1220 1.1 joerg where(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&,
1221 1.1 joerg simd_mask<_Tp, _Abi>&) noexcept;
1222 1.1 joerg
1223 1.1 joerg template <class _Tp, class _Abi>
1224 1.1 joerg const_where_expression<simd_mask<_Tp, _Abi>, const simd_mask<_Tp, _Abi>>
1225 1.1 joerg where(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&,
1226 1.1 joerg const simd_mask<_Tp, _Abi>&) noexcept;
1227 1.1 joerg
1228 1.1 joerg template <class _Tp>
1229 1.1 joerg where_expression<bool, _Tp> where(bool, _Tp&) noexcept;
1230 1.1 joerg
1231 1.1 joerg template <class _Tp>
1232 1.1 joerg const_where_expression<bool, const _Tp> where(bool, const _Tp&) noexcept;
1233 1.1 joerg
1234 1.1 joerg // reductions [simd.reductions]
1235 1.1 joerg template <class _Tp, class _Abi, class _BinaryOp = std::plus<_Tp>>
1236 1.1 joerg _Tp reduce(const simd<_Tp, _Abi>&, _BinaryOp = _BinaryOp());
1237 1.1 joerg
1238 1.1 joerg template <class _MaskType, class _SimdType, class _BinaryOp>
1239 1.1 joerg typename _SimdType::value_type
1240 1.1 joerg reduce(const const_where_expression<_MaskType, _SimdType>&,
1241 1.1 joerg typename _SimdType::value_type neutral_element, _BinaryOp binary_op);
1242 1.1 joerg
1243 1.1 joerg template <class _MaskType, class _SimdType>
1244 1.1 joerg typename _SimdType::value_type
1245 1.1 joerg reduce(const const_where_expression<_MaskType, _SimdType>&,
1246 1.1 joerg plus<typename _SimdType::value_type> binary_op = {});
1247 1.1 joerg
1248 1.1 joerg template <class _MaskType, class _SimdType>
1249 1.1 joerg typename _SimdType::value_type
1250 1.1 joerg reduce(const const_where_expression<_MaskType, _SimdType>&,
1251 1.1 joerg multiplies<typename _SimdType::value_type> binary_op);
1252 1.1 joerg
1253 1.1 joerg template <class _MaskType, class _SimdType>
1254 1.1 joerg typename _SimdType::value_type
1255 1.1 joerg reduce(const const_where_expression<_MaskType, _SimdType>&,
1256 1.1 joerg bit_and<typename _SimdType::value_type> binary_op);
1257 1.1 joerg
1258 1.1 joerg template <class _MaskType, class _SimdType>
1259 1.1 joerg typename _SimdType::value_type
1260 1.1 joerg reduce(const const_where_expression<_MaskType, _SimdType>&,
1261 1.1 joerg bit_or<typename _SimdType::value_type> binary_op);
1262 1.1 joerg
1263 1.1 joerg template <class _MaskType, class _SimdType>
1264 1.1 joerg typename _SimdType::value_type
1265 1.1 joerg reduce(const const_where_expression<_MaskType, _SimdType>&,
1266 1.1 joerg bit_xor<typename _SimdType::value_type> binary_op);
1267 1.1 joerg
1268 1.1 joerg template <class _Tp, class _Abi>
1269 1.1 joerg _Tp hmin(const simd<_Tp, _Abi>&);
1270 1.1 joerg template <class _MaskType, class _SimdType>
1271 1.1 joerg typename _SimdType::value_type
1272 1.1 joerg hmin(const const_where_expression<_MaskType, _SimdType>&);
1273 1.1 joerg template <class _Tp, class _Abi>
1274 1.1 joerg _Tp hmax(const simd<_Tp, _Abi>&);
1275 1.1 joerg template <class _MaskType, class _SimdType>
1276 1.1 joerg typename _SimdType::value_type
1277 1.1 joerg hmax(const const_where_expression<_MaskType, _SimdType>&);
1278 1.1 joerg
1279 1.1 joerg // algorithms [simd.alg]
1280 1.1 joerg template <class _Tp, class _Abi>
1281 1.1 joerg simd<_Tp, _Abi> min(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
1282 1.1 joerg
1283 1.1 joerg template <class _Tp, class _Abi>
1284 1.1 joerg simd<_Tp, _Abi> max(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
1285 1.1 joerg
1286 1.1 joerg template <class _Tp, class _Abi>
1287 1.1 joerg std::pair<simd<_Tp, _Abi>, simd<_Tp, _Abi>>
1288 1.1 joerg minmax(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
1289 1.1 joerg
1290 1.1 joerg template <class _Tp, class _Abi>
1291 1.1 joerg simd<_Tp, _Abi> clamp(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&,
1292 1.1 joerg const simd<_Tp, _Abi>&);
1293 1.1 joerg
1294 1.1 joerg // [simd.whereexpr]
1295 1.1 joerg // TODO implement where expressions.
1296 1.1 joerg template <class _MaskType, class _Tp>
1297 1.1 joerg class const_where_expression {
1298 1.1 joerg public:
1299 1.1 joerg const_where_expression(const const_where_expression&) = delete;
1300 1.1 joerg const_where_expression& operator=(const const_where_expression&) = delete;
1301 1.1 joerg typename remove_const<_Tp>::type operator-() const&&;
1302 1.1 joerg template <class _Up, class _Flags>
1303 1.1 joerg void copy_to(_Up*, _Flags) const&&;
1304 1.1 joerg };
1305 1.1 joerg
1306 1.1 joerg template <class _MaskType, class _Tp>
1307 1.1 joerg class where_expression : public const_where_expression<_MaskType, _Tp> {
1308 1.1 joerg public:
1309 1.1 joerg where_expression(const where_expression&) = delete;
1310 1.1 joerg where_expression& operator=(const where_expression&) = delete;
1311 1.1 joerg template <class _Up>
1312 1.1 joerg void operator=(_Up&&);
1313 1.1 joerg template <class _Up>
1314 1.1 joerg void operator+=(_Up&&);
1315 1.1 joerg template <class _Up>
1316 1.1 joerg void operator-=(_Up&&);
1317 1.1 joerg template <class _Up>
1318 1.1 joerg void operator*=(_Up&&);
1319 1.1 joerg template <class _Up>
1320 1.1 joerg void operator/=(_Up&&);
1321 1.1 joerg template <class _Up>
1322 1.1 joerg void operator%=(_Up&&);
1323 1.1 joerg template <class _Up>
1324 1.1 joerg void operator&=(_Up&&);
1325 1.1 joerg template <class _Up>
1326 1.1 joerg void operator|=(_Up&&);
1327 1.1 joerg template <class _Up>
1328 1.1 joerg void operator^=(_Up&&);
1329 1.1 joerg template <class _Up>
1330 1.1 joerg void operator<<=(_Up&&);
1331 1.1 joerg template <class _Up>
1332 1.1 joerg void operator>>=(_Up&&);
1333 1.1 joerg void operator++();
1334 1.1 joerg void operator++(int);
1335 1.1 joerg void operator--();
1336 1.1 joerg void operator--(int);
1337 1.1 joerg template <class _Up, class _Flags>
1338 1.1 joerg void copy_from(const _Up*, _Flags);
1339 1.1 joerg };
1340 1.1 joerg
1341 1.1 joerg // [simd.class]
1342 1.1 joerg // TODO: implement simd
1343 1.1 joerg template <class _Tp, class _Abi>
1344 1.1 joerg class simd {
1345 1.1 joerg public:
1346 1.1 joerg using value_type = _Tp;
1347 1.1 joerg using reference = __simd_reference<_Tp, _Tp, _Abi>;
1348 1.1 joerg using mask_type = simd_mask<_Tp, _Abi>;
1349 1.1 joerg using abi_type = _Abi;
1350 1.1 joerg
1351 1.1 joerg simd() = default;
1352 1.1 joerg simd(const simd&) = default;
1353 1.1 joerg simd& operator=(const simd&) = default;
1354 1.1 joerg
1355 1.1 joerg static constexpr size_t size() noexcept {
1356 1.1 joerg return simd_size<_Tp, _Abi>::value;
1357 1.1 joerg }
1358 1.1 joerg
1359 1.1 joerg private:
1360 1.1 joerg __simd_storage<_Tp, _Abi> __s_;
1361 1.1 joerg
1362 1.1 joerg template <class _Up>
1363 1.1 joerg static constexpr bool __can_broadcast() {
1364 1.1 joerg return (std::is_arithmetic<_Up>::value &&
1365 1.1 joerg __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) ||
1366 1.1 joerg (!std::is_arithmetic<_Up>::value &&
1367 1.1 joerg std::is_convertible<_Up, _Tp>::value) ||
1368 1.1 joerg std::is_same<typename std::remove_const<_Up>::type, int>::value ||
1369 1.1 joerg (std::is_same<typename std::remove_const<_Up>::type,
1370 1.1 joerg unsigned int>::value &&
1371 1.1 joerg std::is_unsigned<_Tp>::value);
1372 1.1 joerg }
1373 1.1 joerg
1374 1.1 joerg template <class _Generator, size_t... __indicies>
1375 1.1 joerg static constexpr decltype(
1376 1.1 joerg std::forward_as_tuple(std::declval<_Generator>()(
1377 1.1 joerg std::integral_constant<size_t, __indicies>())...),
1378 1.1 joerg bool())
1379 1.1 joerg __can_generate(std::index_sequence<__indicies...>) {
1380 1.1 joerg return !__variadic_sum<bool>(
1381 1.1 joerg !__can_broadcast<decltype(std::declval<_Generator>()(
1382 1.1 joerg std::integral_constant<size_t, __indicies>()))>()...);
1383 1.1 joerg }
1384 1.1 joerg
1385 1.1 joerg template <class _Generator>
1386 1.1 joerg static bool __can_generate(...) {
1387 1.1 joerg return false;
1388 1.1 joerg }
1389 1.1 joerg
1390 1.1 joerg template <class _Generator, size_t... __indicies>
1391 1.1 joerg void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) {
1392 1.1 joerg int __not_used[]{((*this)[__indicies] =
1393 1.1 joerg __g(std::integral_constant<size_t, __indicies>()),
1394 1.1 joerg 0)...};
1395 1.1 joerg (void)__not_used;
1396 1.1 joerg }
1397 1.1 joerg
1398 1.1 joerg public:
1399 1.1 joerg // implicit type conversion constructor
1400 1.1 joerg template <class _Up,
1401 1.1 joerg class = typename std::enable_if<
1402 1.1 joerg std::is_same<_Abi, simd_abi::fixed_size<size()>>::value &&
1403 1.1 joerg __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()>::type>
1404 1.1 joerg simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) {
1405 1.1 joerg for (size_t __i = 0; __i < size(); __i++) {
1406 1.1 joerg (*this)[__i] = static_cast<_Tp>(__v[__i]);
1407 1.1 joerg }
1408 1.1 joerg }
1409 1.1 joerg
1410 1.1 joerg // implicit broadcast constructor
1411 1.1 joerg template <class _Up,
1412 1.1 joerg class = typename std::enable_if<__can_broadcast<_Up>()>::type>
1413 1.1 joerg simd(_Up&& __rv) {
1414 1.1 joerg auto __v = static_cast<_Tp>(__rv);
1415 1.1 joerg for (size_t __i = 0; __i < size(); __i++) {
1416 1.1 joerg (*this)[__i] = __v;
1417 1.1 joerg }
1418 1.1 joerg }
1419 1.1 joerg
1420 1.1 joerg // generator constructor
1421 1.1 joerg template <class _Generator,
1422 1.1 joerg int = typename std::enable_if<
1423 1.1 joerg __can_generate<_Generator>(std::make_index_sequence<size()>()),
1424 1.1 joerg int>::type()>
1425 1.1 joerg explicit simd(_Generator&& __g) {
1426 1.1 joerg __generator_init(std::forward<_Generator>(__g),
1427 1.1 joerg std::make_index_sequence<size()>());
1428 1.1 joerg }
1429 1.1 joerg
1430 1.1 joerg // load constructor
1431 1.1 joerg template <
1432 1.1 joerg class _Up, class _Flags,
1433 1.1 joerg class = typename std::enable_if<__vectorizable<_Up>()>::type,
1434 1.1 joerg class = typename std::enable_if<is_simd_flag_type<_Flags>::value>::type>
1435 1.1 joerg simd(const _Up* __buffer, _Flags) {
1436 1.1 joerg // TODO: optimize for overaligned flags
1437 1.1 joerg for (size_t __i = 0; __i < size(); __i++) {
1438 1.1 joerg (*this)[__i] = static_cast<_Tp>(__buffer[__i]);
1439 1.1 joerg }
1440 1.1 joerg }
1441 1.1 joerg
1442 1.1 joerg // loads [simd.load]
1443 1.1 joerg template <class _Up, class _Flags>
1444 1.1 joerg typename std::enable_if<__vectorizable<_Up>() &&
1445 1.1 joerg is_simd_flag_type<_Flags>::value>::type
1446 1.1 joerg copy_from(const _Up* __buffer, _Flags) {
1447 1.1 joerg *this = simd(__buffer, _Flags());
1448 1.1 joerg }
1449 1.1 joerg
1450 1.1 joerg // stores [simd.store]
1451 1.1 joerg template <class _Up, class _Flags>
1452 1.1 joerg typename std::enable_if<__vectorizable<_Up>() &&
1453 1.1 joerg is_simd_flag_type<_Flags>::value>::type
1454 1.1 joerg copy_to(_Up* __buffer, _Flags) const {
1455 1.1 joerg // TODO: optimize for overaligned flags
1456 1.1 joerg for (size_t __i = 0; __i < size(); __i++) {
1457 1.1 joerg __buffer[__i] = static_cast<_Up>((*this)[__i]);
1458 1.1 joerg }
1459 1.1 joerg }
1460 1.1 joerg
1461 1.1 joerg // scalar access [simd.subscr]
1462 1.1 joerg reference operator[](size_t __i) { return reference(&__s_, __i); }
1463 1.1 joerg
1464 1.1 joerg value_type operator[](size_t __i) const { return __s_.__get(__i); }
1465 1.1 joerg
1466 1.1 joerg // unary operators [simd.unary]
1467 1.1 joerg simd& operator++();
1468 1.1 joerg simd operator++(int);
1469 1.1 joerg simd& operator--();
1470 1.1 joerg simd operator--(int);
1471 1.1 joerg mask_type operator!() const;
1472 1.1 joerg simd operator~() const;
1473 1.1 joerg simd operator+() const;
1474 1.1 joerg simd operator-() const;
1475 1.1 joerg
1476 1.1 joerg // binary operators [simd.binary]
1477 1.1 joerg friend simd operator+(const simd&, const simd&);
1478 1.1 joerg friend simd operator-(const simd&, const simd&);
1479 1.1 joerg friend simd operator*(const simd&, const simd&);
1480 1.1 joerg friend simd operator/(const simd&, const simd&);
1481 1.1 joerg friend simd operator%(const simd&, const simd&);
1482 1.1 joerg friend simd operator&(const simd&, const simd&);
1483 1.1 joerg friend simd operator|(const simd&, const simd&);
1484 1.1 joerg friend simd operator^(const simd&, const simd&);
1485 1.1 joerg friend simd operator<<(const simd&, const simd&);
1486 1.1 joerg friend simd operator>>(const simd&, const simd&);
1487 1.1 joerg friend simd operator<<(const simd&, int);
1488 1.1 joerg friend simd operator>>(const simd&, int);
1489 1.1 joerg
1490 1.1 joerg // compound assignment [simd.cassign]
1491 1.1 joerg friend simd& operator+=(simd&, const simd&);
1492 1.1 joerg friend simd& operator-=(simd&, const simd&);
1493 1.1 joerg friend simd& operator*=(simd&, const simd&);
1494 1.1 joerg friend simd& operator/=(simd&, const simd&);
1495 1.1 joerg friend simd& operator%=(simd&, const simd&);
1496 1.1 joerg
1497 1.1 joerg friend simd& operator&=(simd&, const simd&);
1498 1.1 joerg friend simd& operator|=(simd&, const simd&);
1499 1.1 joerg friend simd& operator^=(simd&, const simd&);
1500 1.1 joerg friend simd& operator<<=(simd&, const simd&);
1501 1.1 joerg friend simd& operator>>=(simd&, const simd&);
1502 1.1 joerg friend simd& operator<<=(simd&, int);
1503 1.1 joerg friend simd& operator>>=(simd&, int);
1504 1.1 joerg
1505 1.1 joerg // compares [simd.comparison]
1506 1.1 joerg friend mask_type operator==(const simd&, const simd&);
1507 1.1 joerg friend mask_type operator!=(const simd&, const simd&);
1508 1.1 joerg friend mask_type operator>=(const simd&, const simd&);
1509 1.1 joerg friend mask_type operator<=(const simd&, const simd&);
1510 1.1 joerg friend mask_type operator>(const simd&, const simd&);
1511 1.1 joerg friend mask_type operator<(const simd&, const simd&);
1512 1.1 joerg };
1513 1.1 joerg
1514 1.1 joerg // [simd.mask.class]
1515 1.1 joerg template <class _Tp, class _Abi>
1516 1.1 joerg // TODO: implement simd_mask
1517 1.1 joerg class simd_mask {
1518 1.1 joerg public:
1519 1.1 joerg using value_type = bool;
1520 1.1 joerg // TODO: this is strawman implementation. Turn it into a proxy type.
1521 1.1 joerg using reference = bool&;
1522 1.1 joerg using simd_type = simd<_Tp, _Abi>;
1523 1.1 joerg using abi_type = _Abi;
1524 1.1 joerg static constexpr size_t size() noexcept;
1525 1.1 joerg simd_mask() = default;
1526 1.1 joerg
1527 1.1 joerg // broadcast constructor
1528 1.1 joerg explicit simd_mask(value_type) noexcept;
1529 1.1 joerg
1530 1.1 joerg // implicit type conversion constructor
1531 1.1 joerg template <class _Up>
1532 1.1 joerg simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>&) noexcept;
1533 1.1 joerg
1534 1.1 joerg // load constructor
1535 1.1 joerg template <class _Flags>
1536 1.1 joerg simd_mask(const value_type*, _Flags);
1537 1.1 joerg
1538 1.1 joerg // loads [simd.mask.copy]
1539 1.1 joerg template <class _Flags>
1540 1.1 joerg void copy_from(const value_type*, _Flags);
1541 1.1 joerg template <class _Flags>
1542 1.1 joerg void copy_to(value_type*, _Flags) const;
1543 1.1 joerg
1544 1.1 joerg // scalar access [simd.mask.subscr]
1545 1.1 joerg reference operator[](size_t);
1546 1.1 joerg value_type operator[](size_t) const;
1547 1.1 joerg
1548 1.1 joerg // unary operators [simd.mask.unary]
1549 1.1 joerg simd_mask operator!() const noexcept;
1550 1.1 joerg
1551 1.1 joerg // simd_mask binary operators [simd.mask.binary]
1552 1.1 joerg friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept;
1553 1.1 joerg friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept;
1554 1.1 joerg friend simd_mask operator&(const simd_mask&, const simd_mask&)noexcept;
1555 1.1 joerg friend simd_mask operator|(const simd_mask&, const simd_mask&) noexcept;
1556 1.1 joerg friend simd_mask operator^(const simd_mask&, const simd_mask&) noexcept;
1557 1.1 joerg
1558 1.1 joerg // simd_mask compound assignment [simd.mask.cassign]
1559 1.1 joerg friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept;
1560 1.1 joerg friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept;
1561 1.1 joerg friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept;
1562 1.1 joerg
1563 1.1 joerg // simd_mask compares [simd.mask.comparison]
1564 1.1 joerg friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept;
1565 1.1 joerg friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept;
1566 1.1 joerg };
1567 1.1 joerg
1568 1.1 joerg #endif // _LIBCPP_STD_VER >= 17
1569 1.1 joerg
1570 1.1 joerg _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD
1571 1.1 joerg
1572 1.1 joerg _LIBCPP_POP_MACROS
1573 1.1 joerg
1574 1.1 joerg #endif /* _LIBCPP_EXPERIMENTAL_SIMD */
1575