AmpGen 2.1
Loading...
Searching...
No Matches
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#if INSTRUCTION_SET == INSTRUCTION_SET_SCALAR
15namespace scalar {
16 using real_v = double;
17 using complex_v = std::complex<double>;
18}
19#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2f
20// #pragma message("Enable AVX2f")
22#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2d
23// #pragma message("Enable AVX2d")
25#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX512d
26// #pragma message("Enable AVX512d")
28#elif INSTRUCTION_SET == INSTRUCTION_SET_ARM128d
30#else
31#pragma message("Unrecognised instruction set")
32#endif
33
34namespace AmpGen {
35#if INSTRUCTION_SET == INSTRUCTION_SET_AVX512d
36 namespace AVX = AVX512d;
37#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2d
38 namespace AVX = AVX2d;
39#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2f
40 namespace AVX = AVX2f;
41#elif INSTRUCTION_SET == INSTRUCTION_SET_SCALAR
42 namespace AVX = scalar;
43#elif INSTRUCTION_SET == INSTRUCTION_SET_ARM128d
44 namespace AVX = ARM128d;
45#endif
46
47 using real_v = AVX::real_v;
48 using complex_v = AVX::complex_v;
49 namespace utils {
50 template <typename T> struct is_vector_type : std::false_type {};
51 template <typename T> struct size {
52 static constexpr unsigned value = 1;
53 };
54 template <typename T> struct is_complex_type : std::false_type {};
55 template <typename T> struct is_complex_type<AmpGen::Complex<T>> : std::true_type {};
56
57#if INSTRUCTION_SET != 0
58 template <> struct is_vector_type<complex_v> : std::true_type {};
59 template <> struct is_vector_type<real_v> : std::true_type {};
60 template <> struct size<complex_v> {
61 static constexpr unsigned value = real_v::size;
62 };
63 template <> struct size<real_v> {
64 static constexpr unsigned value = real_v::size;
65 };
66#endif
67#if INSTRUCTION_SET == INSTRUCTION_SET_ARM128d
68 template <> struct size<AVX::int_v> {
69 static constexpr unsigned value = 2;
70 };
71 template <> struct is_vector_type<AVX::int_v> : std::true_type {};
72#endif
73 template <typename simd_type, typename container_type, typename functor_type>
74 simd_type gather(const container_type &container, const functor_type &functor, unsigned offset = 0, typename simd_type::scalar_type df = 0.) {
75 std::array<typename simd_type::scalar_type, simd_type::size> rv;
76 if(df == 0.)
77 for(unsigned k = 0; k != simd_type::size; ++k)
78 rv[k] = offset + k < container.size() ? functor(container[offset + k]) : functor(container[container.size() - 1]);
79 else
80 for(unsigned k = 0; k != simd_type::size; ++k) rv[k] = offset + k < container.size() ? functor(container[offset + k]) : df;
81 return simd_type(rv.data());
82 }
83
84 template <typename simd_type> size_t aligned_size(const size_t &unaligned_size) {
85 return size<simd_type>::value * unsigned(1 + (unaligned_size - 1) / size<simd_type>::value);
86 }
87 template <typename simd_type> auto sum_elements(const simd_type &obj) {
88 if constexpr(is_vector_type<simd_type>::value and std::is_same_v<simd_type, real_v>) {
89 const auto arr = obj.to_ptr();
90 auto rt = arr[0];
91 for(unsigned i = 1; i != size<simd_type>::value; ++i) rt += arr[i];
92 return rt;
93 } else
94 return obj;
95 }
96 template <typename simd_type> bool all_of(const simd_type &obj) {
97 if constexpr(size<simd_type>::value == 1) return obj;
98#if INSTRUCTION_SET == INSTRUCTION_SET_AVX2d
99 return _mm256_movemask_pd(obj) == 0xF;
100#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2f
101 return _mm256_movemask_ps(obj) == 0xFF;
102#endif
103 return false;
104 }
105 template <typename simd_type, typename value_type> bool all_of(const simd_type &obj, const value_type &v) { return all_of(obj == v); }
106 template <typename T> auto make_complex(T &&re, T &&im) { return std::complex<T>(re, im); }
107 template <unsigned p = 0, typename vtype> auto get(vtype v) {
109 return std::complex(get<p>(v.real()), get<p>(v.imag()));
110 else if constexpr(is_vector_type<vtype>::value)
111 return v.at(p);
112 else if constexpr(std::is_same<vtype, complex_v>::value)
113 return std::complex(get<p>(v.real()), get<p>(v.imag()));
114 else if constexpr(!is_vector_type<vtype>::value)
115 return v;
116 }
117 template <typename vtype> auto at(vtype v, const unsigned p = 0) {
118 if constexpr(is_vector_type<vtype>::value) {
119 if constexpr(std::is_same<vtype, real_v>::value) return v.at(p);
120 if constexpr(std::is_same<vtype, complex_v>::value) return std::complex(at(v.real(), p), at(v.imag(), p));
121 } else
122 return v;
123 }
124 template <typename> struct is_std__complex : std::false_type {};
125 template <typename T> struct is_std__complex<std::complex<T>> : std::true_type {};
126
127 template <typename T> inline auto norm(T &&value) {
128 if constexpr(is_std__complex<std::remove_reference_t<T>>::value) {
129 return std::norm(value);
130 } else {
131 return value.norm();
132 }
133 }
134
135 template <typename type, typename store_type> void store(store_type *container, const type &v) {
136 if constexpr(is_vector_type<type>::value) {
137 auto arr = v.to_ptr();
138 for(unsigned k = 0; k != utils::size<type>::value; ++k) container[k] = arr[k];
139 } else {
140 *container = v;
141 }
142 }
143 }
144}
145
146#endif
auto make_complex(T &&re, T &&im)
Definition utils.h:106
auto sum_elements(const simd_type &obj)
Definition utils.h:87
simd_type gather(const container_type &container, const functor_type &functor, unsigned offset=0, typename simd_type::scalar_type df=0.)
Definition utils.h:74
bool all_of(const simd_type &obj)
Definition utils.h:96
void store(store_type *container, const type &v)
Definition utils.h:135
auto at(vtype v, const unsigned p=0)
Definition utils.h:117
auto norm(T &&value)
Definition utils.h:127
size_t aligned_size(const size_t &unaligned_size)
Definition utils.h:84
auto get(vtype v)
Definition utils.h:107
AVX::real_v real_v
Definition utils.h:47
AVX::complex_v complex_v
Definition utils.h:48
Definition utils.h:15
double real_v
Definition utils.h:16
std::complex< double > complex_v
Definition utils.h:17
static constexpr unsigned value
Definition utils.h:52