dune-common 2.12-git
Loading...
Searching...
No Matches
stdsimd.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3#ifndef DUNE_COMMON_SIMD_STDSIMD_HH
4#define DUNE_COMMON_SIMD_STDSIMD_HH
5
11#include <dune-common-config.hh> // DUNE_HAVE_CXX_EXPERIMENTAL_SIMD
12
13#if DUNE_HAVE_CXX_EXPERIMENTAL_SIMD
14
15#include <cstddef>
16#include <type_traits>
17#include <utility>
18
19#include <experimental/simd>
20
23#include <dune/common/simd/defaults.hh> // for anyFalse()
27
76namespace Dune {
77 namespace Simd {
78
79 namespace StdSimdImpl {
80
81 namespace stdx = std::experimental;
82
84 template<class V>
85 struct IsMask : std::bool_constant<stdx::is_simd_mask_v<V> > {};
86
88 template<class V>
89 struct IsVector
90 : std::bool_constant<stdx::is_simd_v<V> || stdx::is_simd_mask_v<V> >
91 {};
92
94 template<class T>
96 : std::bool_constant<std::is_arithmetic<T>::value &&
97 !std::is_same<T, bool>::value> {};
98
100 template<class V, class = void>
101 struct VectorType { using type = V; };
102
103 template<class M>
104 struct VectorType<M, std::enable_if_t<IsMask<M>::value> >
105 {
106 using type = typename M::simd_type;
107 };
108
110
122 template<class Proxy, class ValueType>
124 {
125 using value_type = ValueType;
126
127#define DUNE_SIMD_STDSIMD_BINARY(OP) \
128 template<class T, class Abi> \
129 friend auto operator OP(const stdx::simd<T, Abi> &l, Proxy&& r) \
130 -> decltype(l OP std::declval<value_type>()) \
131 { \
132 return l OP value_type(r); \
133 } \
134 template<class T, class Abi> \
135 friend auto operator OP(Proxy&& l, const stdx::simd<T, Abi> &r) \
136 -> decltype(std::declval<value_type>() OP r) \
137 { \
138 return value_type(l) OP r; \
139 }
140
157#undef DUNE_SIMD_STDSIMD_BINARY
158
159#define DUNE_SIMD_STDSIMD_ASSIGN(OP) \
160 template<class T, class Abi> \
161 friend auto operator OP(stdx::simd<T, Abi> &l, Proxy&& r) \
162 -> decltype(l OP std::declval<value_type>()) \
163 { \
164 return l OP value_type(r); \
165 }
166
177#undef DUNE_SIMD_STDSIMD_ASSIGN
178 };
179
181 template<class V>
182 using Proxy = Impl::ValueProxy<V, ProxyOperations>;
183
184 } // namespace StdSimdImpl
185
186 namespace Overloads {
187
194
197 template<class V>
198 struct ScalarType<V,
199 std::enable_if_t<StdSimdImpl::IsVector<V>::value> >
200 {
201 using type = typename V::value_type;
202 };
203
205
212 template<class V>
213 struct RebindType<Simd::Scalar<V>, V,
214 std::enable_if_t<StdSimdImpl::IsVector<V>::value> >
215 {
216 using type = V;
217 };
218
220
226 template<class V>
227 struct RebindType<bool, V,
228 std::enable_if_t<StdSimdImpl::IsVector<V>::value &&
229 !StdSimdImpl::IsMask<V>::value> >
230 {
231 using type = typename V::mask_type;
232 };
233
235
241 template<class M>
242 struct RebindType<Scalar<typename M::simd_type>, M,
243 std::enable_if_t<StdSimdImpl::IsMask<M>::value> >
244 {
245 using type = typename M::simd_type;
246 };
247
249
259 template<class S, class V>
260 struct RebindType<S, V,
261 std::enable_if_t<
262 StdSimdImpl::IsVector<V>::value &&
263 StdSimdImpl::IsVectorizable<S>::value &&
264 !std::is_same<
265 S, Scalar<typename StdSimdImpl::VectorType<V>::type>
266 >::value> >
267 {
268 using type = std::experimental::rebind_simd_t<
270 };
271
273
280 template<class S, class V>
281 struct RebindType<S, V,
282 std::enable_if_t<
283 StdSimdImpl::IsVector<V>::value &&
284 !StdSimdImpl::IsVectorizable<S>::value &&
285 !std::is_same<S, bool>::value &&
286 !std::is_same<S, Scalar<V> >::value> >
287 {
289 };
290
292
295 template<class V>
296 struct LaneCount<V,
297 std::enable_if_t<StdSimdImpl::IsVector<V>::value> >
298 : public index_constant<V::size()>
299 { };
300
302 template<class V>
304 std::size_t l, V &v)
305 {
306 return { l, v };
307 }
308
310 template<class V>
312 std::size_t l, const V &v)
313 {
314 return v[l];
315 }
316
318 template<class V,
321 std::size_t l, V &&v)
322 {
323 return std::as_const(v)[l];
324 }
325
327 template<class V>
329 const Mask<V> &mask, const V &ifTrue, const V &ifFalse)
330 {
331 V result = ifFalse;
332 std::experimental::where(mask, result) = ifTrue;
333 return result;
334 }
335
337 template<class V>
340 const V &v1, const V &v2)
341 {
342 return std::experimental::max(v1, v2);
343 }
344
346 template<class M>
348 const M &m1, const M &m2)
349 {
350 return m1 || m2;
351 }
352
354 template<class V>
357 const V &v1, const V &v2)
358 {
359 return std::experimental::min(v1, v2);
360 }
361
363 template<class M>
365 const M &m1, const M &m2)
366 {
367 return m1 && m2;
368 }
369
371 template<class M>
373 {
374 return std::experimental::any_of(mask);
375 }
376
378 template<class M>
380 {
381 return std::experimental::all_of(mask);
382 }
383
384 // anyFalse() is handled by defaults.hh
385
387 template<class M>
389 {
390 return std::experimental::none_of(mask);
391 }
392
394 template<class V>
397 const V &v)
398 {
399 return std::experimental::hmax(v);
400 }
401
403 template<class M>
405 {
406 return std::experimental::any_of(mask);
407 }
408
410 template<class V>
413 const V &v)
414 {
415 return std::experimental::hmin(v);
416 }
417
419 template<class M>
421 {
422 return std::experimental::all_of(mask);
423 }
424
426 template<class S1, class V2>
427 auto maskAnd(ADLTag<5, std::is_same<Mask<S1>, bool>::value &&
429 const S1 &s1, const V2 &v2)
430 {
431 return Simd::Mask<V2>(Simd::mask(s1)) && Simd::mask(v2);
432 }
433
435 template<class V1, class S2>
437 std::is_same<Mask<S2>, bool>::value>,
438 const V1 &v1, const S2 &s2)
439 {
440 return Simd::mask(v1) && Simd::Mask<V1>(Simd::mask(s2));
441 }
442
444 template<class S1, class V2>
445 auto maskOr(ADLTag<5, std::is_same<Mask<S1>, bool>::value &&
447 const S1 &s1, const V2 &v2)
448 {
449 return Simd::Mask<V2>(Simd::mask(s1)) || Simd::mask(v2);
450 }
451
453 template<class V1, class S2>
455 std::is_same<Mask<S2>, bool>::value>,
456 const V1 &v1, const S2 &s2)
457 {
458 return Simd::mask(v1) || Simd::Mask<V1>(Simd::mask(s2));
459 }
460
462
463 } // namespace Overloads
464
465 } // namespace Simd
466
467 /*
468 * Specialize IsNumber for std::experimental::simd to be able to use it as a
469 * scalar in DenseMatrix etc.
470 */
471 template<class T, class Abi>
472 struct IsNumber<std::experimental::simd<T, Abi> >
473 : public std::integral_constant<bool, IsNumber<T>::value> {
474 };
475
476} // namespace Dune
477
478#endif // DUNE_HAVE_CXX_EXPERIMENTAL_SIMD
479
480#endif // DUNE_COMMON_SIMD_STDSIMD_HH
A proxy for lanes of SIMD types with operator[]
#define DUNE_SIMD_STDSIMD_ASSIGN(OP)
Definition stdsimd.hh:159
Basic definitions for SIMD Implementations.
Default implementations for SIMD Implementations.
Traits for type conversions and type information.
auto mask(const V &v)
Convert to mask, analogue of bool(s) for scalars.
Definition simd/interface.hh:502
Rebind< bool, V > Mask
Mask type type of some SIMD type.
Definition simd/interface.hh:289
typename Overloads::ScalarType< std::decay_t< V > >::type Scalar
Element type of some SIMD type.
Definition simd/interface.hh:235
Mask< V > mask(ADLTag< 0, std::is_same< V, Mask< V > >::value >, const V &v)
implements Simd::mask()
Definition defaults.hh:153
bool allFalse(ADLTag< 0 >, const Mask &mask)
implements Simd::allFalse()
Definition defaults.hh:124
bool allTrue(ADLTag< 0 >, const Mask &mask)
implements Simd::allTrue()
Definition defaults.hh:104
auto maskAnd(ADLTag< 0 >, const V1 &v1, const V2 &v2)
implements Simd::maskAnd()
Definition defaults.hh:177
auto maskOr(ADLTag< 0 >, const V1 &v1, const V2 &v2)
implements Simd::maskOr()
Definition defaults.hh:170
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition defaults.hh:89
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition defaults.hh:81
STL namespace.
Dune namespace
Definition alignedallocator.hh:13
bool anyTrue(ADLTag< 5 >, const AlignedNumber< bool, align > &mask)
Definition debugalign.hh:556
const AlignedNumber< T, align > & cond(ADLTag< 5 >, AlignedNumber< bool, align > mask, const AlignedNumber< T, align > &ifTrue, const AlignedNumber< T, align > &ifFalse)
Definition debugalign.hh:548
T & lane(ADLTag< 5 >, std::size_t l, AlignedNumber< T, align > &v)
Definition debugalign.hh:533
Impl::ValueProxy< V, ProxyOperations > Proxy
A reference-like proxy for lanes of std::experimental::simd types.
Definition stdsimd.hh:182
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition typetraits.hh:194
Tag used to force late-binding lookup in Dune::Simd::Overloads.
Definition base.hh:182
should have a member type type
Definition standard.hh:60
should have a member type type
Definition standard.hh:67
should be derived from a Dune::index_constant
Definition standard.hh:74
Definition loop.hh:65
true for std::experimental::simd_mask types
Definition stdsimd.hh:85
true for std::experimental::simd and simd_mask types
Definition stdsimd.hh:91
true for the element types of std::experimental::simd
Definition stdsimd.hh:97
the vector type of a vector or mask type
Definition stdsimd.hh:101
V type
Definition stdsimd.hh:101
Operations of lane proxies with std::experimental::simd types.
Definition stdsimd.hh:124
DUNE_SIMD_STDSIMD_BINARY & DUNE_SIMD_STDSIMD_BINARY(^);DUNE_SIMD_STDSIMD_BINARY(|
DUNE_SIMD_STDSIMD_ASSIGN * DUNE_SIMD_STDSIMD_ASSIGN(/=);DUNE_SIMD_STDSIMD_ASSIGN(%=
ValueType value_type
Definition stdsimd.hh:125
DUNE_SIMD_STDSIMD_ASSIGN & DUNE_SIMD_STDSIMD_ASSIGN(^=);DUNE_SIMD_STDSIMD_ASSIGN(|=
DUNE_SIMD_STDSIMD_BINARY * DUNE_SIMD_STDSIMD_BINARY(/);DUNE_SIMD_STDSIMD_BINARY(%
T as_const(T... args)