49#if defined(__AVX512F__)
53#elif defined(__SSE2__) || defined(__ARM_NEON) || defined(__ARM_NEON__)
69#ifdef CODI_REVERSE_TYPE
88template <class Scalar_t, size_t N = preferredLen<Scalar_t>()>
90#define FOREACH for (size_t k = 0; k < N; ++k)
91 static_assert(N > 0,
"Invalid SIMD size");
95 enum :
size_t {
Size = N };
103#define ARRAY_BOILERPLATE \
105 FORCEINLINE Scalar& operator[](size_t k) { return x_[k]; } \
106 FORCEINLINE const Scalar& operator[](size_t k) const { return x_[k]; } \
108 FORCEINLINE Array() = default; \
109 FORCEINLINE Array(Scalar x) { bcast(x); } \
110 FORCEINLINE Array(std::initializer_list<Scalar> vals) { \
111 auto it = vals.begin(); \
117 FORCEINLINE Array(Scalar x0, Scalar dx) { FOREACH x_[k] = x0 + k * dx; } \
118 FORCEINLINE Array(const Scalar* ptr) { load(ptr); } \
120 FORCEINLINE Array(const Scalar* beg, const T& off) { \
124 FORCEINLINE Scalar sum() const { \
126 FOREACH { s += x_[k]; } \
129 FORCEINLINE Scalar dot(const Array& other) const { \
131 FOREACH { s += x_[k] * other[k]; } \
135#if defined(CODI_REVERSE_TYPE) || defined(CODI_FORWARD_TYPE)
138 template <class U = Scalar, su2enable_if<std::is_same<U, su2double>::value> = 0>
142 template <class U = Scalar, su2enable_if<std::is_same<U, su2double>::value> = 0>
167 FOREACH x_[k] = begin[offsets[k]];
172#define MAKE_COMPOUND(OP) \
173 FORCEINLINE Array& operator OP(Scalar x) { \
174 FOREACH { x_[k] OP x; } \
178 FORCEINLINE Array& operator OP(const CVecExpr<U, Scalar>& expr) { \
179 FOREACH { x_[k] OP expr.derived()[k]; } \
216#define ARRAY_T Array<double, 2>
217#define SCALAR_T double
218#define REGISTER_T __m128d
219#define SIZE_TAG SizeTag::TWO()
221static const __m128d abs_mask_2d = _mm_castsi128_pd(_mm_set1_epi64x(
abs_mask_d));
222static const __m128d sign_mask_2d = _mm_castsi128_pd(_mm_set1_epi64x(
sign_mask_d));
223static const __m128d ones_2d = _mm_set1_pd(1);
239FORCEINLINE __m128d
eq_p(__m128d a, __m128d b) {
return _mm_and_pd(ones_2d, _mm_cmpeq_pd(a, b)); }
240FORCEINLINE __m128d
lt_p(__m128d a, __m128d b) {
return _mm_and_pd(ones_2d, _mm_cmplt_pd(a, b)); }
241FORCEINLINE __m128d
le_p(__m128d a, __m128d b) {
return _mm_and_pd(ones_2d, _mm_cmple_pd(a, b)); }
242FORCEINLINE __m128d
ne_p(__m128d a, __m128d b) {
return _mm_and_pd(ones_2d, _mm_cmpneq_pd(a, b)); }
243FORCEINLINE __m128d
ge_p(__m128d a, __m128d b) {
return _mm_and_pd(ones_2d, _mm_cmpge_pd(a, b)); }
244FORCEINLINE __m128d
gt_p(__m128d a, __m128d b) {
return _mm_and_pd(ones_2d, _mm_cmpgt_pd(a, b)); }
249FORCEINLINE __m128d
sign_p(__m128d x) {
return _mm_or_pd(ones_2d, _mm_and_pd(x, sign_mask_2d)); }
259#define ARRAY_T Array<float, 4>
260#define SCALAR_T float
261#define REGISTER_T __m128
262#define SIZE_TAG SizeTag::FOUR()
264static const __m128 abs_mask_4s = _mm_castsi128_ps(_mm_set1_epi32(
abs_mask_s));
265static const __m128 sign_mask_4s = _mm_castsi128_ps(_mm_set1_epi32(
sign_mask_s));
266static const __m128 ones_4s = _mm_set1_ps(1);
282FORCEINLINE __m128
eq_p(__m128 a, __m128 b) {
return _mm_and_ps(ones_4s, _mm_cmpeq_ps(a, b)); }
283FORCEINLINE __m128
lt_p(__m128 a, __m128 b) {
return _mm_and_ps(ones_4s, _mm_cmplt_ps(a, b)); }
284FORCEINLINE __m128
le_p(__m128 a, __m128 b) {
return _mm_and_ps(ones_4s, _mm_cmple_ps(a, b)); }
285FORCEINLINE __m128
ne_p(__m128 a, __m128 b) {
return _mm_and_ps(ones_4s, _mm_cmpneq_ps(a, b)); }
286FORCEINLINE __m128
ge_p(__m128 a, __m128 b) {
return _mm_and_ps(ones_4s, _mm_cmpge_ps(a, b)); }
287FORCEINLINE __m128
gt_p(__m128 a, __m128 b) {
return _mm_and_ps(ones_4s, _mm_cmpgt_ps(a, b)); }
302#define ARRAY_T Array<double, 4>
303#define SCALAR_T double
304#define REGISTER_T __m256d
305#define SIZE_TAG SizeTag::FOUR()
307static const __m256d abs_mask_4d = _mm256_castsi256_pd(_mm256_set1_epi64x(
abs_mask_d));
308static const __m256d sign_mask_4d = _mm256_castsi256_pd(_mm256_set1_epi64x(
sign_mask_d));
309static const __m256d ones_4d = _mm256_set1_pd(1);
312FORCEINLINE __m256d
load_p(SizeTag::FOUR,
const double* p) {
return _mm256_load_pd(p); }
313FORCEINLINE __m256d
loadu_p(SizeTag::FOUR,
const double* p) {
return _mm256_loadu_pd(p); }
318FORCEINLINE __m256d
add_p(__m256d a, __m256d b) {
return _mm256_add_pd(a, b); }
319FORCEINLINE __m256d
sub_p(__m256d a, __m256d b) {
return _mm256_sub_pd(a, b); }
320FORCEINLINE __m256d
mul_p(__m256d a, __m256d b) {
return _mm256_mul_pd(a, b); }
321FORCEINLINE __m256d
div_p(__m256d a, __m256d b) {
return _mm256_div_pd(a, b); }
322FORCEINLINE __m256d
max_p(__m256d a, __m256d b) {
return _mm256_max_pd(a, b); }
323FORCEINLINE __m256d
min_p(__m256d a, __m256d b) {
return _mm256_min_pd(a, b); }
325FORCEINLINE __m256d
eq_p(__m256d a, __m256d b) {
return _mm256_and_pd(ones_4d, _mm256_cmp_pd(a, b, 0)); }
326FORCEINLINE __m256d
lt_p(__m256d a, __m256d b) {
return _mm256_and_pd(ones_4d, _mm256_cmp_pd(a, b, 1)); }
327FORCEINLINE __m256d
le_p(__m256d a, __m256d b) {
return _mm256_and_pd(ones_4d, _mm256_cmp_pd(a, b, 2)); }
328FORCEINLINE __m256d
ne_p(__m256d a, __m256d b) {
return _mm256_and_pd(ones_4d, _mm256_cmp_pd(a, b, 4)); }
329FORCEINLINE __m256d
ge_p(__m256d a, __m256d b) {
return _mm256_and_pd(ones_4d, _mm256_cmp_pd(a, b, 13)); }
330FORCEINLINE __m256d
gt_p(__m256d a, __m256d b) {
return _mm256_and_pd(ones_4d, _mm256_cmp_pd(a, b, 14)); }
333FORCEINLINE __m256d
abs_p(__m256d x) {
return _mm256_and_pd(x, abs_mask_4d); }
334FORCEINLINE __m256d
neg_p(__m256d x) {
return _mm256_xor_pd(x, sign_mask_4d); }
335FORCEINLINE __m256d
sign_p(__m256d x) {
return _mm256_or_pd(ones_4d, _mm256_and_pd(x, sign_mask_4d)); }
342#define ARRAY_T Array<float, 8>
343#define SCALAR_T float
344#define REGISTER_T __m256
345#define SIZE_TAG SizeTag::EIGHT()
347static const __m256 abs_mask_8s = _mm256_castsi256_ps(_mm256_set1_epi32(
abs_mask_s));
348static const __m256 sign_mask_8s = _mm256_castsi256_ps(_mm256_set1_epi32(
sign_mask_s));
349static const __m256 ones_8s = _mm256_set1_ps(1);
352FORCEINLINE __m256
load_p(SizeTag::EIGHT,
const float* p) {
return _mm256_load_ps(p); }
353FORCEINLINE __m256
loadu_p(SizeTag::EIGHT,
const float* p) {
return _mm256_loadu_ps(p); }
365FORCEINLINE __m256
eq_p(__m256 a, __m256 b) {
return _mm256_and_ps(ones_8s, _mm256_cmp_ps(a, b, 0)); }
366FORCEINLINE __m256
lt_p(__m256 a, __m256 b) {
return _mm256_and_ps(ones_8s, _mm256_cmp_ps(a, b, 1)); }
367FORCEINLINE __m256
le_p(__m256 a, __m256 b) {
return _mm256_and_ps(ones_8s, _mm256_cmp_ps(a, b, 2)); }
368FORCEINLINE __m256
ne_p(__m256 a, __m256 b) {
return _mm256_and_ps(ones_8s, _mm256_cmp_ps(a, b, 4)); }
369FORCEINLINE __m256
ge_p(__m256 a, __m256 b) {
return _mm256_and_ps(ones_8s, _mm256_cmp_ps(a, b, 13)); }
370FORCEINLINE __m256
gt_p(__m256 a, __m256 b) {
return _mm256_and_ps(ones_8s, _mm256_cmp_ps(a, b, 14)); }
374FORCEINLINE __m256
neg_p(__m256 x) {
return _mm256_xor_ps(x, sign_mask_8s); }
375FORCEINLINE __m256
sign_p(__m256 x) {
return _mm256_or_ps(ones_8s, _mm256_and_ps(x, sign_mask_8s)); }
385#define ARRAY_T Array<double, 8>
386#define SCALAR_T double
387#define REGISTER_T __m512d
388#define SIZE_TAG SizeTag::EIGHT()
390static const __m512d abs_mask_8d = _mm512_castsi512_pd(_mm512_set1_epi64(
abs_mask_d));
391static const __m512d sign_mask_8d = _mm512_castsi512_pd(_mm512_set1_epi64(
sign_mask_d));
392static const __m512d ones_8d = _mm512_set1_pd(1);
394FORCEINLINE __m512d
set1_p(SizeTag::EIGHT,
double p) {
return _mm512_set1_pd(p); }
395FORCEINLINE __m512d
load_p(SizeTag::EIGHT,
const double* p) {
return _mm512_load_pd(p); }
396FORCEINLINE __m512d
loadu_p(SizeTag::EIGHT,
const double* p) {
return _mm512_loadu_pd(p); }
401FORCEINLINE __m512d
add_p(__m512d a, __m512d b) {
return _mm512_add_pd(a, b); }
402FORCEINLINE __m512d
sub_p(__m512d a, __m512d b) {
return _mm512_sub_pd(a, b); }
403FORCEINLINE __m512d
mul_p(__m512d a, __m512d b) {
return _mm512_mul_pd(a, b); }
404FORCEINLINE __m512d
div_p(__m512d a, __m512d b) {
return _mm512_div_pd(a, b); }
405FORCEINLINE __m512d
max_p(__m512d a, __m512d b) {
return _mm512_max_pd(a, b); }
406FORCEINLINE __m512d
min_p(__m512d a, __m512d b) {
return _mm512_min_pd(a, b); }
410 return _mm512_mask_blend_pd(_mm512_cmp_pd_mask(a, b, opCode), _mm512_setzero_pd(), ones_8d);
412FORCEINLINE __m512d
eq_p(__m512d a, __m512d b) {
return cmp_p<0>(a, b); }
413FORCEINLINE __m512d
lt_p(__m512d a, __m512d b) {
return cmp_p<1>(a, b); }
414FORCEINLINE __m512d
le_p(__m512d a, __m512d b) {
return cmp_p<2>(a, b); }
415FORCEINLINE __m512d
ne_p(__m512d a, __m512d b) {
return cmp_p<4>(a, b); }
416FORCEINLINE __m512d
ge_p(__m512d a, __m512d b) {
return cmp_p<13>(a, b); }
417FORCEINLINE __m512d
gt_p(__m512d a, __m512d b) {
return cmp_p<14>(a, b); }
420FORCEINLINE __m512d
abs_p(__m512d x) {
return _mm512_and_pd(x, abs_mask_8d); }
421FORCEINLINE __m512d
neg_p(__m512d x) {
return _mm512_xor_pd(x, sign_mask_8d); }
422FORCEINLINE __m512d
sign_p(__m512d x) {
return _mm512_or_pd(ones_8d, _mm512_and_pd(x, sign_mask_8d)); }
429#define ARRAY_T Array<float, 16>
430#define SCALAR_T float
431#define REGISTER_T __m512
432#define SIZE_TAG SizeTag::SIXTEEN()
434static const __m512 abs_mask_16s = _mm512_castsi512_ps(_mm512_set1_epi32(
abs_mask_s));
435static const __m512 sign_mask_16s = _mm512_castsi512_ps(_mm512_set1_epi32(
sign_mask_s));
436static const __m512 ones_16s = _mm512_set1_ps(1);
438FORCEINLINE __m512
set1_p(SizeTag::SIXTEEN,
float p) {
return _mm512_set1_ps(p); }
439FORCEINLINE __m512
load_p(SizeTag::SIXTEEN,
const float* p) {
return _mm512_load_ps(p); }
440FORCEINLINE __m512
loadu_p(SizeTag::SIXTEEN,
const float* p) {
return _mm512_loadu_ps(p); }
454 return _mm512_mask_blend_ps(_mm512_cmp_ps_mask(a, b, opCode), _mm512_setzero_ps(), ones_16s);
464FORCEINLINE __m512
abs_p(__m512 x) {
return _mm512_and_ps(x, abs_mask_16s); }
465FORCEINLINE __m512
neg_p(__m512 x) {
return _mm512_xor_ps(x, sign_mask_16s); }
466FORCEINLINE __m512
sign_p(__m512 x) {
return _mm512_or_ps(ones_16s, _mm512_and_ps(x, sign_mask_16s)); }
472#if defined(__ARM_NEON) || defined(__ARM_NEON__)
476#define ARRAY_T Array<double, 2>
477#define SCALAR_T double
478#define REGISTER_T float64x2_t
479#define SIZE_TAG SizeTag::TWO()
481static const uint64x2_t abs_mask_2d_u = vdupq_n_u64(
abs_mask_d);
482static const uint64x2_t sign_mask_2d_u = vdupq_n_u64(
sign_mask_d);
483static const uint64x2_t ones_2d_u = vreinterpretq_u64_f64(vdupq_n_f64(1.0));
484static const uint64x2_t ones_2u = vdupq_n_u64(~0ULL);
487FORCEINLINE float64x2_t
load_p(SizeTag::TWO,
const double* p) {
return vld1q_f64(p); }
488FORCEINLINE float64x2_t
loadu_p(SizeTag::TWO,
const double* p) {
return vld1q_f64(p); }
494FORCEINLINE float64x2_t
add_p(float64x2_t a, float64x2_t b) {
return vaddq_f64(a, b); }
495FORCEINLINE float64x2_t
sub_p(float64x2_t a, float64x2_t b) {
return vsubq_f64(a, b); }
496FORCEINLINE float64x2_t
mul_p(float64x2_t a, float64x2_t b) {
return vmulq_f64(a, b); }
497FORCEINLINE float64x2_t
div_p(float64x2_t a, float64x2_t b) {
return vdivq_f64(a, b); }
498FORCEINLINE float64x2_t
max_p(float64x2_t a, float64x2_t b) {
return vmaxq_f64(a, b); }
499FORCEINLINE float64x2_t
min_p(float64x2_t a, float64x2_t b) {
return vminq_f64(a, b); }
502FORCEINLINE float64x2_t int2float(uint64x2_t a) {
return vreinterpretq_f64_u64(a); }
503FORCEINLINE float64x2_t cmp2float(uint64x2_t cmp) {
return int2float(vandq_u64(ones_2d_u, cmp)); }
504FORCEINLINE float64x2_t
eq_p(float64x2_t a, float64x2_t b) {
return cmp2float(vceqq_f64(a, b)); }
505FORCEINLINE float64x2_t
lt_p(float64x2_t a, float64x2_t b) {
return cmp2float(vcltq_f64(a, b)); }
506FORCEINLINE float64x2_t
le_p(float64x2_t a, float64x2_t b) {
return cmp2float(vcleq_f64(a, b)); }
507FORCEINLINE float64x2_t
ne_p(float64x2_t a, float64x2_t b) {
return cmp2float(veorq_u64(ones_2u, vceqq_f64(a, b))); }
508FORCEINLINE float64x2_t
ge_p(float64x2_t a, float64x2_t b) {
return cmp2float(vcgeq_f64(a, b)); }
509FORCEINLINE float64x2_t
gt_p(float64x2_t a, float64x2_t b) {
return cmp2float(vcgtq_f64(a, b)); }
512FORCEINLINE float64x2_t
abs_p(float64x2_t x) {
return int2float(vandq_u64(vreinterpretq_u64_f64(x), abs_mask_2d_u)); }
513FORCEINLINE float64x2_t
neg_p(float64x2_t x) {
return int2float(veorq_u64(vreinterpretq_u64_f64(x), sign_mask_2d_u)); }
515 return int2float(vorrq_u64(ones_2d_u, vandq_u64(vreinterpretq_u64_f64(x), sign_mask_2d_u)));
523#define ARRAY_T Array<float, 4>
524#define SCALAR_T float
525#define REGISTER_T float32x4_t
526#define SIZE_TAG SizeTag::FOUR()
528static const uint32x4_t abs_mask_4s_u = vdupq_n_u32(
abs_mask_s);
529static const uint32x4_t sign_mask_4s_u = vdupq_n_u32(
sign_mask_s);
530static const uint32x4_t ones_4s_u = vreinterpretq_u32_f32(vdupq_n_f32(1.0f));
533FORCEINLINE float32x4_t
load_p(SizeTag::FOUR,
const float* p) {
return vld1q_f32(p); }
534FORCEINLINE float32x4_t
loadu_p(SizeTag::FOUR,
const float* p) {
return vld1q_f32(p); }
538FORCEINLINE float32x4_t
add_p(float32x4_t a, float32x4_t b) {
return vaddq_f32(a, b); }
539FORCEINLINE float32x4_t
sub_p(float32x4_t a, float32x4_t b) {
return vsubq_f32(a, b); }
540FORCEINLINE float32x4_t
mul_p(float32x4_t a, float32x4_t b) {
return vmulq_f32(a, b); }
541FORCEINLINE float32x4_t
div_p(float32x4_t a, float32x4_t b) {
return vdivq_f32(a, b); }
542FORCEINLINE float32x4_t
max_p(float32x4_t a, float32x4_t b) {
return vmaxq_f32(a, b); }
543FORCEINLINE float32x4_t
min_p(float32x4_t a, float32x4_t b) {
return vminq_f32(a, b); }
545FORCEINLINE float32x4_t int2float(uint32x4_t a) {
return vreinterpretq_f32_u32(a); }
546FORCEINLINE float32x4_t cmp2float(uint32x4_t cmp) {
return int2float(vandq_u32(ones_4s_u, cmp)); }
547FORCEINLINE float32x4_t
eq_p(float32x4_t a, float32x4_t b) {
return cmp2float(vceqq_f32(a, b)); }
548FORCEINLINE float32x4_t
lt_p(float32x4_t a, float32x4_t b) {
return cmp2float(vcltq_f32(a, b)); }
549FORCEINLINE float32x4_t
le_p(float32x4_t a, float32x4_t b) {
return cmp2float(vcleq_f32(a, b)); }
550FORCEINLINE float32x4_t
ne_p(float32x4_t a, float32x4_t b) {
return cmp2float(vmvnq_u32(vceqq_f32(a, b))); }
551FORCEINLINE float32x4_t
ge_p(float32x4_t a, float32x4_t b) {
return cmp2float(vcgeq_f32(a, b)); }
552FORCEINLINE float32x4_t
gt_p(float32x4_t a, float32x4_t b) {
return cmp2float(vcgtq_f32(a, b)); }
555FORCEINLINE float32x4_t
abs_p(float32x4_t x) {
return int2float(vandq_u32(vreinterpretq_u32_f32(x), abs_mask_4s_u)); }
556FORCEINLINE float32x4_t
neg_p(float32x4_t x) {
return int2float(veorq_u32(vreinterpretq_u32_f32(x), sign_mask_4s_u)); }
558 return int2float(vorrq_u32(ones_4s_u, vandq_u32(vreinterpretq_u32_f32(x), sign_mask_4s_u)));
565#undef ARRAY_BOILERPLATE