AmpGen
2.1
Toggle main menu visibility
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
15
namespace
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")
21
#include "
AmpGen/simd/avx2f_types.h
"
22
#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX2d
23
// #pragma message("Enable AVX2d")
24
#include "
AmpGen/simd/avx2d_types.h
"
25
#elif INSTRUCTION_SET == INSTRUCTION_SET_AVX512d
26
// #pragma message("Enable AVX512d")
27
#include "
AmpGen/simd/avx512d_types.h
"
28
#elif INSTRUCTION_SET == INSTRUCTION_SET_ARM128d
29
#include "
AmpGen/simd/arm128d_types.h
"
30
#else
31
#pragma message("Unrecognised instruction set")
32
#endif
33
34
namespace
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) {
108
if
constexpr
(
is_complex_type<vtype>::value
)
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
Complex.h
arm128d_types.h
avx2d_types.h
avx2f_types.h
avx512d_types.h
AmpGen::utils
Definition
utils.h:49
AmpGen::utils::make_complex
auto make_complex(T &&re, T &&im)
Definition
utils.h:106
AmpGen::utils::sum_elements
auto sum_elements(const simd_type &obj)
Definition
utils.h:87
AmpGen::utils::gather
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
AmpGen::utils::all_of
bool all_of(const simd_type &obj)
Definition
utils.h:96
AmpGen::utils::store
void store(store_type *container, const type &v)
Definition
utils.h:135
AmpGen::utils::at
auto at(vtype v, const unsigned p=0)
Definition
utils.h:117
AmpGen::utils::norm
auto norm(T &&value)
Definition
utils.h:127
AmpGen::utils::aligned_size
size_t aligned_size(const size_t &unaligned_size)
Definition
utils.h:84
AmpGen::utils::get
auto get(vtype v)
Definition
utils.h:107
AmpGen
Definition
AddCPConjugate.h:2
AmpGen::real_v
AVX::real_v real_v
Definition
utils.h:47
AmpGen::complex_v
AVX::complex_v complex_v
Definition
utils.h:48
scalar
Definition
utils.h:15
scalar::real_v
double real_v
Definition
utils.h:16
scalar::complex_v
std::complex< double > complex_v
Definition
utils.h:17
AmpGen::Complex
Definition
Complex.h:7
AmpGen::utils::is_complex_type
Definition
utils.h:54
AmpGen::utils::is_std__complex
Definition
utils.h:124
AmpGen::utils::is_vector_type
Definition
utils.h:50
AmpGen::utils::size
Definition
utils.h:51
AmpGen::utils::size::value
static constexpr unsigned value
Definition
utils.h:52
AmpGen
simd
utils.h
Generated on
for AmpGen by
1.17.0