1 #ifndef DUNE_COMMON_SIMD_STANDARD_HH 2 #define DUNE_COMMON_SIMD_STANDARD_HH 3 4 /** @file 5 * @ingroup SIMDStandard 6 * @brief SIMD abstractions for the standard built-in types 7 * 8 * This file should not normally be included by users of the SIMD abstraction 9 * (i.e. other Dune headers). Neither should it be included by the 10 * translation units passing built-in types to Dune headers that in turn 11 * support SIMD types through the SIMD abstraction. Dune-functionality always 12 * supports built-in types. Either because that functionality does not 13 * support SIMD types and so only supports built-in types, or if it does 14 * support SIMD types it must include `<dune/common/simd/simd.hh>`, which in 15 * turn includes this header. 16 */ 17 18 #include <cstddef> 19 #include <type_traits> 20 #include <utility> 21 22 #include <dune/common/indices.hh> 23 #include <dune/common/simd/base.hh> 24 #include <dune/common/simd/defaults.hh> 25 26 /** @defgroup SIMDStandard SIMD Abstraction Implementation for standard types 27 * @ingroup SIMDApp 28 * 29 * This implements the vectorization interface for scalar types. It applies 30 * to any type that does not have a specialized interface implementation. 31 * 32 * As an application developer, there is nothing special you need to do to get 33 * support for standard types in the vectorization abstraction. If the dune 34 * classes you are using provide support for vectorization, they will include 35 * `<dune/common/simd/simd.hh>`, which will pull in the abstraction for 36 * standard types automatically. You simply need to make sure that the types 37 * themselves are supported: 38 * - for built-in types there is nothing you need to do, 39 * - for `std::complex`, you need to `#include <complex>` 40 * - etc. 41 */ 42 43 namespace Dune { 44 namespace Simd { 45 46 namespace Overloads { 47 48 /** @name Specialized classes and overloaded functions 49 * @ingroup SIMDStandard 50 * @{ 51 */ 52 53 //! should have a member type \c type 54 /** 55 * Implements Simd::Scalar 56 */ 57 template<class V, class> 58 struct ScalarType { using type = V; }; 59 60 //! should have a member type \c type 61 /** 62 * Implements Simd::Rebind 63 */ 64 template<class S, class, class> 65 struct RebindType { using type = S; }; 66 67 //! should be derived from an Dune::index_constant 68 /** 69 * Implements Simd::lanes() 70 */ 71 template<class, class> 72 struct LaneCount : public index_constant<1> { }; 73 74 //! implements Simd::lane() 75 /** 76 * This binds to rvalues and const lvalues. It would bind to non-const 77 * lvalues too, but those are caught by the overload with ADLTag<3>. 78 * Using a universal reference here would bind to any argument with a 79 * perfect match. This would mean ambiguous overloads with other 80 * abstractions, if those only declare overloads for `const TheirType &` 81 * and `TheirType &`, because because universal references match 82 * perfectly. 83 */ 84 template<class V> lane(ADLTag<2>,std::size_t,V v)85 V lane(ADLTag<2>, std::size_t, V v) 86 { 87 return v; 88 } 89 90 template<class V> lane(ADLTag<3>,std::size_t,V & v)91 V &lane(ADLTag<3>, std::size_t, V &v) 92 { 93 return v; 94 } 95 96 // No Simd::cond() implementation, the overload for bool masks in the 97 // interface is sufficient 98 99 //! implements Simd::anyTrue() anyTrue(ADLTag<2>,bool mask)100 inline bool anyTrue(ADLTag<2>, bool mask) { return mask; } 101 102 //! implements Simd::allTrue() allTrue(ADLTag<2>,bool mask)103 inline bool allTrue(ADLTag<2>, bool mask) { return mask; } 104 105 //! implements Simd::anyFalse() anyFalse(ADLTag<2>,bool mask)106 inline bool anyFalse(ADLTag<2>, bool mask) { return !mask; } 107 108 //! implements Simd::allFalse() allFalse(ADLTag<2>,bool mask)109 inline bool allFalse(ADLTag<2>, bool mask) { return !mask; } 110 111 //! @} group SIMDStandard 112 113 } // namespace Overloads 114 } // namespace Simd 115 } // namespace Dune 116 117 #endif // DUNE_COMMON_SIMD_STANDARD_HH 118