File failed to load: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/config/TeX-MML-AM_CHTML/MathJax.js
AmpGen 2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
utils.h
Go to the documentation of this file.
1#ifndef AMPGEN_SIMD_UTILS_H
2#define AMPGEN_SIMD_UTILS_H
3
4#include <array>
5#include <complex>
6#include "AmpGen/Complex.h"
7
8#define INSTRUCTION_SET_SCALAR 0
9#define INSTRUCTION_SET_AVX2f 1
10#define INSTRUCTION_SET_AVX2d 2
11#define INSTRUCTION_SET_AVX512d 3
12#define INSTRUCTION_SET_ARM128d 10
13
14
15#if INSTRUCTION_SET == INSTRUCTION_SET_SCALAR
16 namespace scalar { using real_v = double; using complex_v = std::complex<double>; }
17#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2f
18// #pragma message("Enable AVX2f")
20#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2d
21// #pragma message("Enable AVX2d")
23#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX512d
24// #pragma message("Enable AVX512d")
26#elif INSTRUCTION_SET == INSTRUCTION_SET_ARM128d
28#else
29 #pragma message("Unrecognised instruction set")
30#endif
31
32namespace AmpGen {
33
34#if INSTRUCTION_SET == INSTRUCTION_SET_AVX512d
35 namespace AVX = AVX512d;
36#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2d
37 namespace AVX = AVX2d;
38#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2f
39 namespace AVX = AVX2f;
40#elif INSTRUCTION_SET == INSTRUCTION_SET_SCALAR
41 namespace AVX = scalar;
42#elif INSTRUCTION_SET == INSTRUCTION_SET_ARM128d
43 namespace AVX = ARM128d;
44#endif
45
46 using real_v = AVX::real_v;
47 using complex_v = AVX::complex_v;
48 namespace utils {
49
50 template <typename T> struct is_vector_type : std::false_type {};
51 template <typename T> struct size { static constexpr unsigned value = 1; } ;
52 template <typename T> struct is_complex_type : std::false_type {};
53 template <typename T> struct is_complex_type<AmpGen::Complex<T>> : std::true_type {};
54
55 #if INSTRUCTION_SET != 0
56 template <> struct is_vector_type <complex_v> : std::true_type {};
57 template <> struct is_vector_type <real_v > : std::true_type {};
58 template <> struct size <complex_v>{ static constexpr unsigned value = real_v::size; };
59 template <> struct size <real_v> { static constexpr unsigned value = real_v::size; };
60 #endif
61 #if INSTRUCTION_SET == INSTRUCTION_SET_ARM128d
62 template <> struct size <AVX::int_v> { static constexpr unsigned value = 2; };
63 template <> struct is_vector_type <AVX::int_v> : std::true_type {};
64 #endif
65 template <typename simd_type, typename container_type, typename functor_type> simd_type gather(
66 const container_type& container, const functor_type& functor, unsigned offset=0, typename simd_type::scalar_type df =0.)
67 {
68 std::array<typename simd_type::scalar_type, simd_type::size> rv;
69 if( df == 0. )
70 for( unsigned k = 0 ; k != simd_type::size; ++k ) rv[k] = offset + k < container.size() ? functor(container[offset+k]) : functor(container[container.size()-1]);
71 else
72 for( unsigned k = 0 ; k != simd_type::size; ++k ) rv[k] = offset + k < container.size() ? functor(container[offset+k]) : df;
73 return simd_type( rv.data() );
74 }
75
76 template <typename simd_type> size_t aligned_size( const size_t& unaligned_size ) {
77 return size<simd_type>::value * unsigned ( 1 + (unaligned_size -1 ) / size<simd_type>::value );
78 }
79 template <typename simd_type> auto sum_elements( const simd_type& obj )
80 {
81 if constexpr ( is_vector_type<simd_type>::value and std::is_same_v<simd_type, real_v> )
82 {
83 const auto arr = obj.to_ptr();
84 auto rt = arr[0];
85 for( unsigned i = 1 ; i != size<simd_type>::value; ++i ) rt += arr[i];
86 return rt;
87 }
88 else return obj;
89 }
90 template <typename simd_type> bool all_of( const simd_type& obj)
91 {
92 if constexpr( size<simd_type>::value == 1 ) return obj;
93 #if INSTRUCTION_SET == INSTRUCTION_SET_AVX2d
94 return _mm256_movemask_pd( obj ) == 0xF;
95 #elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2f
96 return _mm256_movemask_ps( obj ) == 0xFF;
97 #endif
98 return false;
99 }
100 template <typename simd_type, typename value_type> bool all_of( const simd_type& obj, const value_type& v )
101 {
102 return all_of( obj == v );
103 }
104 template <typename T> auto make_complex( T&& re, T&& im ) { return std::complex<T>(re,im); }
105 template <unsigned p=0, typename vtype> auto get( vtype v )
106 {
107 if constexpr ( is_complex_type<vtype>::value ) return std::complex( get<p>(v.real() ), get<p>(v.imag() ) );
108 else if constexpr ( is_vector_type<vtype>::value ) return v.at(p);
109 else if constexpr ( std::is_same<vtype, complex_v>::value ) return std::complex( get<p>(v.real()), get<p>(v.imag()) );
110 else if constexpr ( !is_vector_type<vtype>::value ) return v;
111 }
112 template < typename vtype> auto at( vtype v, const unsigned p=0 )
113 {
114 if constexpr ( is_vector_type<vtype>::value )
115 {
116 if constexpr ( std::is_same<vtype, real_v>::value ) return v.at(p);
117 if constexpr ( std::is_same<vtype, complex_v>::value ) return std::complex( at( v.real(), p), at( v.imag(), p) );
118 }
119 else return v;
120 }
121 template <typename> struct is_std__complex : std::false_type{};
122 template <typename T> struct is_std__complex<std::complex<T>> : std::true_type {} ;
123
124 template <typename T> inline auto norm( T&& value ){
125 if constexpr( is_std__complex<std::remove_reference_t<T>> ::value ){ return std::norm(value); }
126 else { return value.norm(); }
127 }
128
129 template <typename type, typename store_type> void store( store_type* container, const type& v)
130 {
131 if constexpr( is_vector_type<type>::value )
132 {
133 auto arr = v.to_ptr();
134 for( unsigned k = 0 ; k != utils::size<type>::value; ++k ) container[k] = arr[k];
135 }
136 else {
137 *container = v;
138 }
139 }
140 }
141}
142
143#endif
auto make_complex(T &&re, T &&im)
Definition utils.h:104
auto sum_elements(const simd_type &obj)
Definition utils.h:79
simd_type gather(const container_type &container, const functor_type &functor, unsigned offset=0, typename simd_type::scalar_type df=0.)
Definition utils.h:65
bool all_of(const simd_type &obj)
Definition utils.h:90
void store(store_type *container, const type &v)
Definition utils.h:129
auto at(vtype v, const unsigned p=0)
Definition utils.h:112
auto norm(T &&value)
Definition utils.h:124
size_t aligned_size(const size_t &unaligned_size)
Definition utils.h:76
auto get(vtype v)
Definition utils.h:105
AVX::real_v real_v
Definition utils.h:46
AVX::complex_v complex_v
Definition utils.h:47
Definition utils.h:16
double real_v
Definition utils.h:16
std::complex< double > complex_v
Definition utils.h:16
static constexpr unsigned value
Definition utils.h:51