14#ifndef dealii_vectorization_h
15#define dealii_vectorization_h
43#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS > 0
52# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && !defined(__AVX__)
54 "Mismatch in vectorization capabilities: AVX was detected during configuration of deal.II and switched on, but it is apparently not available for the file you are trying to compile at the moment. Check compilation flags controlling the instruction set, such as -march=native."
56# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512 && !defined(__AVX512F__)
58 "Mismatch in vectorization capabilities: AVX-512F was detected during configuration of deal.II and switched on, but it is apparently not available for the file you are trying to compile at the moment. Check compilation flags controlling the instruction set, such as -march=native."
63# elif defined(__ALTIVEC__)
71# elif defined(__ARM_NEON)
73# elif defined(__x86_64__)
74# include <x86intrin.h>
86template <
typename Number, std::
size_t w
idth>
120 "You are trying to compare iterators into different arrays."));
132 "You are trying to compare iterators into different arrays."));
140 constexpr const typename T::value_type &
152 template <
typename U = T>
153 constexpr std::enable_if_t<!std::is_same_v<U, const U>,
154 typename T::value_type> &
197 "You can't decrement an iterator that is already at the beginning of the range."));
215 constexpr std::ptrdiff_t
218 return static_cast<std::ptrdiff_t
>(
lane) -
219 static_cast<std::ptrdiff_t
>(other.
lane);
248template <
typename VectorizedArrayType, std::
size_t w
idth>
264 template <
typename U>
267 const unsigned int n_initializers = list.size();
269 ExcMessage(
"The initializer list must have at most "
270 "as many elements as the vector length."));
273 std::copy_n(list.begin(), n_initializers, this->begin());
276 if (n_initializers <
size())
277 std::fill(this->
begin() + n_initializers, this->
end(), 0.0);
283 static constexpr std::size_t
296 static_cast<VectorizedArrayType &
>(*
this), 0);
307 static_cast<const VectorizedArrayType &
>(*
this), 0);
317 static_cast<VectorizedArrayType &
>(*
this), width);
328 static_cast<const VectorizedArrayType &
>(*
this), width);
345 VectorizedArrayType p =
static_cast<const VectorizedArrayType &
>(*this);
441template <
typename Number, std::
size_t w
idth>
472 static_assert(width == 1,
473 "You specified an illegal width that is not supported.");
481 template <
typename U>
485 static_assert(width == 1,
486 "You specified an illegal width that is not supported.");
577 template <
typename OtherNumber>
590 template <
typename OtherNumber>
667 gather(
const Number *base_ptr,
const unsigned int *offsets)
671 data = base_ptr[offsets[0]];
690 scatter(
const unsigned int *offsets, Number *base_ptr)
const
693 base_ptr[offsets[0]] =
data;
774 template <
typename Number2, std::
size_t w
idth2>
777 template <
typename Number2, std::
size_t w
idth2>
780 template <
typename Number2, std::
size_t w
idth2>
784 template <
typename Number2, std::
size_t w
idth2>
803template <
typename Number,
821template <
typename VectorizedArrayType>
826 std::is_same_v<VectorizedArrayType,
828 VectorizedArrayType::size()>>,
829 "VectorizedArrayType is not a VectorizedArray.");
831 VectorizedArrayType result = u;
848template <
typename Number, std::
size_t w
idth>
851 const std::array<const Number *, width> &ptrs,
852 const unsigned int offset)
854 for (
unsigned int v = 0; v < width; ++v)
855 out.
data[v] = ptrs[v][offset];
885template <
typename Number, std::
size_t w
idth>
889 const unsigned int *offsets,
892 for (
unsigned int i = 0; i < n_entries; ++i)
893 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
894 out[i][v] = in[offsets[v] + i];
909template <
typename Number, std::
size_t w
idth>
912 const std::array<const Number *, width> &in,
915 for (
unsigned int i = 0; i < n_entries; ++i)
916 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
917 out[i][v] = in[v][i];
960template <
typename Number, std::
size_t w
idth>
963 const unsigned int n_entries,
965 const unsigned int *offsets,
969 for (
unsigned int i = 0; i < n_entries; ++i)
970 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
971 out[offsets[v] + i] += in[i][v];
973 for (
unsigned int i = 0; i < n_entries; ++i)
974 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
975 out[offsets[v] + i] = in[i][v];
990template <
typename Number, std::
size_t w
idth>
993 const unsigned int n_entries,
995 const std::array<Number *, width> &out)
998 for (
unsigned int i = 0; i < n_entries; ++i)
999 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
1000 out[v][i] += in[i][v];
1002 for (
unsigned int i = 0; i < n_entries; ++i)
1003 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
1004 out[v][i] = in[i][v];
1012# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ARM_NEON)
1050 template <
typename U>
1061 data = vdupq_n_f64(x);
1071 operator=(
const double scalar) && =
delete;
1079 return *(
reinterpret_cast<double *
>(&
data) + comp);
1088 return *(
reinterpret_cast<const double *
>(&
data) + comp);
1137 load(
const double *ptr)
1139 data = vld1q_f64(ptr);
1143 load(
const float *ptr)
1146 for (
unsigned int i = 0; i < 2; ++i)
1157 store(
double *ptr)
const
1159 vst1q_f64(ptr,
data);
1163 store(
float *ptr)
const
1166 for (
unsigned int i = 0; i < 2; ++i)
1177 Assert(
reinterpret_cast<std::size_t
>(ptr) % 16 == 0,
1179 vst1q_f64(ptr,
data);
1186 gather(
const double *base_ptr,
const unsigned int *offsets)
1189 for (
unsigned int i = 0; i < 2; ++i)
1191 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
1198 scatter(
const unsigned int *offsets,
double *base_ptr)
const
1200 for (
unsigned int i = 0; i < 2; ++i)
1202 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
1212 return vaddvq_f64(
data);
1231 mutable float64x2_t
data;
1283 template <
typename Number2, std::
size_t w
idth2>
1286 template <
typename Number2, std::
size_t w
idth2>
1289 template <
typename Number2, std::
size_t w
idth2>
1293 template <
typename Number2, std::
size_t w
idth2>
1335 template <
typename U>
1346 data = vdupq_n_f32(x);
1356 operator=(
const float scalar) && =
delete;
1364 return *(
reinterpret_cast<float *
>(&
data) + comp);
1373 return *(
reinterpret_cast<const float *
>(&
data) + comp);
1422 load(
const float *ptr)
1424 data = vld1q_f32(ptr);
1434 store(
float *ptr)
const
1436 vst1q_f32(ptr,
data);
1446 Assert(
reinterpret_cast<std::size_t
>(ptr) % 16 == 0,
1448 vst1q_f32(ptr,
data);
1455 gather(
const float *base_ptr,
const unsigned int *offsets)
1458 for (
unsigned int i = 0; i < 4; ++i)
1460 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
1467 scatter(
const unsigned int *offsets,
float *base_ptr)
const
1469 for (
unsigned int i = 0; i < 4; ++i)
1471 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
1481 return vaddvq_f32(
data);
1501 mutable float32x4_t
data;
1553 template <
typename Number2, std::
size_t w
idth2>
1556 template <
typename Number2, std::
size_t w
idth2>
1559 template <
typename Number2, std::
size_t w
idth2>
1563 template <
typename Number2, std::
size_t w
idth2>
1572# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__SSE2__)
1610 template <
typename U>
1621 data = _mm_set1_pd(x);
1631 operator=(
const double scalar) && =
delete;
1640 return *(
reinterpret_cast<double *
>(&
data) + comp);
1650 return *(
reinterpret_cast<const double *
>(&
data) + comp);
1659# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
1673# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
1687# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
1701# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
1715 load(
const double *ptr)
1717 data = _mm_loadu_pd(ptr);
1721 load(
const float *ptr)
1724 for (
unsigned int i = 0; i < 2; ++i)
1735 store(
double *ptr)
const
1737 _mm_storeu_pd(ptr,
data);
1741 store(
float *ptr)
const
1744 for (
unsigned int i = 0; i < 2; ++i)
1755 Assert(
reinterpret_cast<std::size_t
>(ptr) % 16 == 0,
1757 _mm_stream_pd(ptr,
data);
1764 gather(
const double *base_ptr,
const unsigned int *offsets)
1767 for (
unsigned int i = 0; i < 2; ++i)
1769 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
1776 scatter(
const unsigned int *offsets,
double *base_ptr)
const
1778 for (
unsigned int i = 0; i < 2; ++i)
1780 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
1790 __m128d t1 = _mm_unpackhi_pd(
data,
data);
1791 __m128d t2 = _mm_add_pd(
data, t1);
1792 return _mm_cvtsd_f64(t2);
1802 for (std::size_t i = 0; i < 2; ++i)
1838 __m128d
mask = _mm_set1_pd(-0.);
1840 res.
data = _mm_andnot_pd(mask,
data);
1869 template <
typename Number2, std::
size_t w
idth2>
1872 template <
typename Number2, std::
size_t w
idth2>
1875 template <
typename Number2, std::
size_t w
idth2>
1879 template <
typename Number2, std::
size_t w
idth2>
1893 const std::array<const double *, 2> &in,
1896 const unsigned int n_chunks = n_entries / 2;
1897 for (
unsigned int i = 0; i < n_chunks; ++i)
1899 __m128d u0 = _mm_loadu_pd(in[0] + 2 * i);
1900 __m128d u1 = _mm_loadu_pd(in[1] + 2 * i);
1901 out[2 * i + 0].
data = _mm_unpacklo_pd(u0, u1);
1902 out[2 * i + 1].
data = _mm_unpackhi_pd(u0, u1);
1906 for (
unsigned int i = 2 * n_chunks; i < n_entries; ++i)
1907 for (
unsigned int v = 0; v < 2; ++v)
1908 out[i][v] = in[v][i];
1920 const unsigned int *offsets,
1924 {{in + offsets[0], in + offsets[1]}},
1936 const unsigned int n_entries,
1938 const std::array<double *, 2> &out)
1940 const unsigned int n_chunks = n_entries / 2;
1943 for (
unsigned int i = 0; i < n_chunks; ++i)
1945 __m128d u0 = in[2 * i + 0].
data;
1946 __m128d u1 = in[2 * i + 1].
data;
1947 __m128d res0 = _mm_unpacklo_pd(u0, u1);
1948 __m128d res1 = _mm_unpackhi_pd(u0, u1);
1949 _mm_storeu_pd(out[0] + 2 * i,
1950 _mm_add_pd(_mm_loadu_pd(out[0] + 2 * i), res0));
1951 _mm_storeu_pd(out[1] + 2 * i,
1952 _mm_add_pd(_mm_loadu_pd(out[1] + 2 * i), res1));
1956 for (
unsigned int i = 2 * n_chunks; i < n_entries; ++i)
1957 for (
unsigned int v = 0; v < 2; ++v)
1958 out[v][i] += in[i][v];
1962 for (
unsigned int i = 0; i < n_chunks; ++i)
1964 __m128d u0 = in[2 * i + 0].
data;
1965 __m128d u1 = in[2 * i + 1].
data;
1966 __m128d res0 = _mm_unpacklo_pd(u0, u1);
1967 __m128d res1 = _mm_unpackhi_pd(u0, u1);
1968 _mm_storeu_pd(out[0] + 2 * i, res0);
1969 _mm_storeu_pd(out[1] + 2 * i, res1);
1973 for (
unsigned int i = 2 * n_chunks; i < n_entries; ++i)
1974 for (
unsigned int v = 0; v < 2; ++v)
1975 out[v][i] = in[i][v];
1987 const unsigned int n_entries,
1989 const unsigned int *offsets,
1995 {{out + offsets[0], out + offsets[1]}});
2036 template <
typename U>
2047 data = _mm_set1_ps(x);
2057 operator=(
const float scalar) && =
delete;
2066 return *(
reinterpret_cast<float *
>(&
data) + comp);
2076 return *(
reinterpret_cast<const float *
>(&
data) + comp);
2085# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2099# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2113# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2127# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2141 load(
const float *ptr)
2143 data = _mm_loadu_ps(ptr);
2153 store(
float *ptr)
const
2155 _mm_storeu_ps(ptr,
data);
2165 Assert(
reinterpret_cast<std::size_t
>(ptr) % 16 == 0,
2167 _mm_stream_ps(ptr,
data);
2174 gather(
const float *base_ptr,
const unsigned int *offsets)
2177 for (
unsigned int i = 0; i < 4; ++i)
2179 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
2186 scatter(
const unsigned int *offsets,
float *base_ptr)
const
2188 for (
unsigned int i = 0; i < 4; ++i)
2190 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
2200 __m128 t1 = _mm_movehl_ps(
data,
data);
2201 __m128 t2 = _mm_add_ps(
data, t1);
2202 __m128 t3 = _mm_shuffle_ps(t2, t2, 1);
2203 __m128 t4 = _mm_add_ss(t2, t3);
2204 return _mm_cvtss_f32(t4);
2214 for (std::size_t i = 0; i < 4; ++i)
2249 __m128
mask = _mm_set1_ps(-0.f);
2251 res.
data = _mm_andnot_ps(mask,
data);
2280 template <
typename Number2, std::
size_t w
idth2>
2283 template <
typename Number2, std::
size_t w
idth2>
2286 template <
typename Number2, std::
size_t w
idth2>
2290 template <
typename Number2, std::
size_t w
idth2>
2304 const std::array<const float *, 4> &in,
2307 const unsigned int n_chunks = n_entries / 4;
2308 for (
unsigned int i = 0; i < n_chunks; ++i)
2310 __m128 u0 = _mm_loadu_ps(in[0] + 4 * i);
2311 __m128 u1 = _mm_loadu_ps(in[1] + 4 * i);
2312 __m128 u2 = _mm_loadu_ps(in[2] + 4 * i);
2313 __m128 u3 = _mm_loadu_ps(in[3] + 4 * i);
2314 __m128
v0 = _mm_shuffle_ps(u0, u1, 0x44);
2315 __m128
v1 = _mm_shuffle_ps(u0, u1, 0xee);
2316 __m128 v2 = _mm_shuffle_ps(u2, u3, 0x44);
2317 __m128 v3 = _mm_shuffle_ps(u2, u3, 0xee);
2318 out[4 * i + 0].
data = _mm_shuffle_ps(
v0, v2, 0x88);
2319 out[4 * i + 1].
data = _mm_shuffle_ps(
v0, v2, 0xdd);
2320 out[4 * i + 2].
data = _mm_shuffle_ps(
v1, v3, 0x88);
2321 out[4 * i + 3].
data = _mm_shuffle_ps(
v1, v3, 0xdd);
2325 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
2326 for (
unsigned int v = 0; v < 4; ++v)
2327 out[i][v] = in[v][i];
2339 const unsigned int *offsets,
2344 {{in + offsets[0], in + offsets[1], in + offsets[2], in + offsets[3]}},
2356 const unsigned int n_entries,
2358 const std::array<float *, 4> &out)
2360 const unsigned int n_chunks = n_entries / 4;
2361 for (
unsigned int i = 0; i < n_chunks; ++i)
2363 __m128 u0 = in[4 * i + 0].
data;
2364 __m128 u1 = in[4 * i + 1].
data;
2365 __m128 u2 = in[4 * i + 2].
data;
2366 __m128 u3 = in[4 * i + 3].
data;
2367 __m128 t0 = _mm_shuffle_ps(u0, u1, 0x44);
2368 __m128 t1 = _mm_shuffle_ps(u0, u1, 0xee);
2369 __m128 t2 = _mm_shuffle_ps(u2, u3, 0x44);
2370 __m128 t3 = _mm_shuffle_ps(u2, u3, 0xee);
2371 u0 = _mm_shuffle_ps(t0, t2, 0x88);
2372 u1 = _mm_shuffle_ps(t0, t2, 0xdd);
2373 u2 = _mm_shuffle_ps(t1, t3, 0x88);
2374 u3 = _mm_shuffle_ps(t1, t3, 0xdd);
2381 u0 = _mm_add_ps(_mm_loadu_ps(out[0] + 4 * i), u0);
2382 _mm_storeu_ps(out[0] + 4 * i, u0);
2383 u1 = _mm_add_ps(_mm_loadu_ps(out[1] + 4 * i), u1);
2384 _mm_storeu_ps(out[1] + 4 * i, u1);
2385 u2 = _mm_add_ps(_mm_loadu_ps(out[2] + 4 * i), u2);
2386 _mm_storeu_ps(out[2] + 4 * i, u2);
2387 u3 = _mm_add_ps(_mm_loadu_ps(out[3] + 4 * i), u3);
2388 _mm_storeu_ps(out[3] + 4 * i, u3);
2392 _mm_storeu_ps(out[0] + 4 * i, u0);
2393 _mm_storeu_ps(out[1] + 4 * i, u1);
2394 _mm_storeu_ps(out[2] + 4 * i, u2);
2395 _mm_storeu_ps(out[3] + 4 * i, u3);
2401 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
2402 for (
unsigned int v = 0; v < 4; ++v)
2403 out[v][i] += in[i][v];
2405 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
2406 for (
unsigned int v = 0; v < 4; ++v)
2407 out[v][i] = in[i][v];
2418 const unsigned int n_entries,
2420 const unsigned int *offsets,
2427 {{out + offsets[0], out + offsets[1], out + offsets[2], out + offsets[3]}});
2434# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
2472 template <
typename U>
2483 data = _mm256_set1_pd(x);
2493 operator=(
const double scalar) && =
delete;
2502 return *(
reinterpret_cast<double *
>(&
data) + comp);
2512 return *(
reinterpret_cast<const double *
>(&
data) + comp);
2526# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2540# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2553# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2567# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2581 load(
const double *ptr)
2583 data = _mm256_loadu_pd(ptr);
2587 load(
const float *ptr)
2589 data = _mm256_cvtps_pd(_mm_loadu_ps(ptr));
2599 store(
double *ptr)
const
2601 _mm256_storeu_pd(ptr,
data);
2605 store(
float *ptr)
const
2607 _mm_storeu_ps(ptr, _mm256_cvtpd_ps(
data));
2617 Assert(
reinterpret_cast<std::size_t
>(ptr) % 32 == 0,
2619 _mm256_stream_pd(ptr,
data);
2626 gather(
const double *base_ptr,
const unsigned int *offsets)
2628# if defined(__AVX2__) && defined(DEAL_II_USE_VECTORIZATION_GATHER)
2632 const __m128 index_val =
2633 _mm_loadu_ps(
reinterpret_cast<const float *
>(offsets));
2634 const __m128i
index = *
reinterpret_cast<const __m128i *
>(&index_val);
2639 __m256d
zero = _mm256_setzero_pd();
2640 __m128i neq32 = _mm_andnot_si128(_mm_cmpeq_epi32(index, _mm_set1_epi32(-1)),
2641 _mm_set1_epi32(-1));
2643 __m256d
mask = _mm256_castsi256_pd(_mm256_cvtepi32_epi64(neq32));
2645 data = _mm256_mask_i32gather_pd(zero, base_ptr, index, mask, 8);
2648 for (
unsigned int i = 0; i < 4; ++i)
2650 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
2658 scatter(
const unsigned int *offsets,
double *base_ptr)
const
2661 for (
unsigned int i = 0; i < 4; ++i)
2663 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
2674 t1.
data = _mm_add_pd(this->get_lower(), this->get_upper());
2703 return _mm256_castpd256_pd128(
data);
2712 return _mm256_extractf128_pd(
data, 1);
2737 __m256d
mask = _mm256_set1_pd(-0.);
2739 res.
data = _mm256_andnot_pd(mask,
data);
2768 template <
typename Number2, std::
size_t w
idth2>
2771 template <
typename Number2, std::
size_t w
idth2>
2774 template <
typename Number2, std::
size_t w
idth2>
2778 template <
typename Number2, std::
size_t w
idth2>
2792 const std::array<const double *, 4> &in,
2795 const unsigned int n_chunks = n_entries / 4;
2796 const double *in0 = in[0];
2797 const double *in1 = in[1];
2798 const double *in2 = in[2];
2799 const double *in3 = in[3];
2801 for (
unsigned int i = 0; i < n_chunks; ++i)
2803 __m256d u0 = _mm256_loadu_pd(in0 + 4 * i);
2804 __m256d u1 = _mm256_loadu_pd(in1 + 4 * i);
2805 __m256d u2 = _mm256_loadu_pd(in2 + 4 * i);
2806 __m256d u3 = _mm256_loadu_pd(in3 + 4 * i);
2807 __m256d t0 = _mm256_permute2f128_pd(u0, u2, 0x20);
2808 __m256d t1 = _mm256_permute2f128_pd(u1, u3, 0x20);
2809 __m256d t2 = _mm256_permute2f128_pd(u0, u2, 0x31);
2810 __m256d t3 = _mm256_permute2f128_pd(u1, u3, 0x31);
2811 out[4 * i + 0].
data = _mm256_unpacklo_pd(t0, t1);
2812 out[4 * i + 1].
data = _mm256_unpackhi_pd(t0, t1);
2813 out[4 * i + 2].
data = _mm256_unpacklo_pd(t2, t3);
2814 out[4 * i + 3].
data = _mm256_unpackhi_pd(t2, t3);
2818 const unsigned int i = 4 * n_chunks;
2819 const unsigned int remainder = n_entries - i;
2824 __m256i
mask{-1, -1, -1, 0};
2825 __m256d u0 = _mm256_maskload_pd(in[0] + i, mask);
2826 __m256d u1 = _mm256_maskload_pd(in[1] + i, mask);
2827 __m256d u2 = _mm256_maskload_pd(in[2] + i, mask);
2828 __m256d u3 = _mm256_maskload_pd(in[3] + i, mask);
2829 __m256d t0 = _mm256_permute2f128_pd(u0, u2, 0x20);
2830 __m256d t1 = _mm256_permute2f128_pd(u1, u3, 0x20);
2831 __m256d t2 = _mm256_permute2f128_pd(u0, u2, 0x31);
2832 __m256d t3 = _mm256_permute2f128_pd(u1, u3, 0x31);
2833 out[i + 0].
data = _mm256_unpacklo_pd(t0, t1);
2834 out[i + 1].
data = _mm256_unpackhi_pd(t0, t1);
2835 out[i + 2].
data = _mm256_unpacklo_pd(t2, t3);
2837 else if (remainder == 2)
2840 __m256d t0, t1 = {};
2841 t0 = _mm256_insertf128_pd(t1, _mm_loadu_pd(in[0] + i), 0);
2842 t0 = _mm256_insertf128_pd(t0, _mm_loadu_pd(in[2] + i), 1);
2843 t1 = _mm256_insertf128_pd(t1, _mm_loadu_pd(in[1] + i), 0);
2844 t1 = _mm256_insertf128_pd(t1, _mm_loadu_pd(in[3] + i), 1);
2846 out[i + 0].
data = _mm256_unpacklo_pd(t0, t1);
2847 out[i + 1].
data = _mm256_unpackhi_pd(t0, t1);
2849 else if (remainder == 1)
2850 for (
unsigned int v = 0; v < 4; ++v)
2851 out[i][v] = in[v][i];
2863 const unsigned int *offsets,
2868 {{in + offsets[0], in + offsets[1], in + offsets[2], in + offsets[3]}},
2880 const unsigned int n_entries,
2882 const std::array<double *, 4> &out)
2884 const unsigned int n_chunks = n_entries / 4;
2885 double *out0 = out[0];
2886 double *out1 = out[1];
2887 double *out2 = out[2];
2888 double *out3 = out[3];
2889 for (
unsigned int i = 0; i < n_chunks; ++i)
2891 __m256d u0 = in[4 * i + 0].
data;
2892 __m256d u1 = in[4 * i + 1].
data;
2893 __m256d u2 = in[4 * i + 2].
data;
2894 __m256d u3 = in[4 * i + 3].
data;
2895 __m256d t0 = _mm256_permute2f128_pd(u0, u2, 0x20);
2896 __m256d t1 = _mm256_permute2f128_pd(u1, u3, 0x20);
2897 __m256d t2 = _mm256_permute2f128_pd(u0, u2, 0x31);
2898 __m256d t3 = _mm256_permute2f128_pd(u1, u3, 0x31);
2899 __m256d res0 = _mm256_unpacklo_pd(t0, t1);
2900 __m256d res1 = _mm256_unpackhi_pd(t0, t1);
2901 __m256d res2 = _mm256_unpacklo_pd(t2, t3);
2902 __m256d res3 = _mm256_unpackhi_pd(t2, t3);
2909 res0 = _mm256_add_pd(_mm256_loadu_pd(out0 + 4 * i), res0);
2910 _mm256_storeu_pd(out0 + 4 * i, res0);
2911 res1 = _mm256_add_pd(_mm256_loadu_pd(out1 + 4 * i), res1);
2912 _mm256_storeu_pd(out1 + 4 * i, res1);
2913 res2 = _mm256_add_pd(_mm256_loadu_pd(out2 + 4 * i), res2);
2914 _mm256_storeu_pd(out2 + 4 * i, res2);
2915 res3 = _mm256_add_pd(_mm256_loadu_pd(out3 + 4 * i), res3);
2916 _mm256_storeu_pd(out3 + 4 * i, res3);
2920 _mm256_storeu_pd(out0 + 4 * i, res0);
2921 _mm256_storeu_pd(out1 + 4 * i, res1);
2922 _mm256_storeu_pd(out2 + 4 * i, res2);
2923 _mm256_storeu_pd(out3 + 4 * i, res3);
2929 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
2930 for (
unsigned int v = 0; v < 4; ++v)
2931 out[v][i] += in[i][v];
2933 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
2934 for (
unsigned int v = 0; v < 4; ++v)
2935 out[v][i] = in[i][v];
2946 const unsigned int n_entries,
2948 const unsigned int *offsets,
2955 {{out + offsets[0], out + offsets[1], out + offsets[2], out + offsets[3]}});
2996 template <
typename U>
3007 data = _mm256_set1_ps(x);
3017 operator=(
const float scalar) && =
delete;
3026 return *(
reinterpret_cast<float *
>(&
data) + comp);
3036 return *(
reinterpret_cast<const float *
>(&
data) + comp);
3050# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3064# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3077# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3091# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3105 load(
const float *ptr)
3107 data = _mm256_loadu_ps(ptr);
3117 store(
float *ptr)
const
3119 _mm256_storeu_ps(ptr,
data);
3129 Assert(
reinterpret_cast<std::size_t
>(ptr) % 32 == 0,
3131 _mm256_stream_ps(ptr,
data);
3138 gather(
const float *base_ptr,
const unsigned int *offsets)
3140# if defined(__AVX2__) && defined(DEAL_II_USE_VECTORIZATION_GATHER)
3144 const __m256 index_val =
3145 _mm256_loadu_ps(
reinterpret_cast<const float *
>(offsets));
3146 const __m256i
index = *
reinterpret_cast<const __m256i *
>(&index_val);
3151 __m256
zero = _mm256_setzero_ps();
3153 __m256i inverse_mask = _mm256_cmpeq_epi32(index, invalid);
3154 __m256i
mask = _mm256_xor_si256(invalid, inverse_mask);
3156 data = _mm256_mask_i32gather_ps(
3157 zero, base_ptr, index, *
reinterpret_cast<__m256 *
>(&mask), 4);
3160 for (
unsigned int i = 0; i < 8; ++i)
3162 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
3170 scatter(
const unsigned int *offsets,
float *base_ptr)
const
3173 for (
unsigned int i = 0; i < 8; ++i)
3175 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
3186 t1.
data = _mm_add_ps(this->get_lower(), this->get_upper());
3215 return _mm256_castps256_ps128(
data);
3224 return _mm256_extractf128_ps(
data, 1);
3249 __m256
mask = _mm256_set1_ps(-0.f);
3251 res.
data = _mm256_andnot_ps(mask,
data);
3280 template <
typename Number2, std::
size_t w
idth2>
3283 template <
typename Number2, std::
size_t w
idth2>
3286 template <
typename Number2, std::
size_t w
idth2>
3290 template <
typename Number2, std::
size_t w
idth2>
3304 const std::array<const float *, 8> &in,
3307 const unsigned int n_chunks = n_entries / 4;
3308 for (
unsigned int i = 0; i < n_chunks; ++i)
3312 __m256 t0, t1, t2, t3 = {};
3313 t0 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[0] + 4 * i), 0);
3314 t0 = _mm256_insertf128_ps(t0, _mm_loadu_ps(in[4] + 4 * i), 1);
3315 t1 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[1] + 4 * i), 0);
3316 t1 = _mm256_insertf128_ps(t1, _mm_loadu_ps(in[5] + 4 * i), 1);
3317 t2 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[2] + 4 * i), 0);
3318 t2 = _mm256_insertf128_ps(t2, _mm_loadu_ps(in[6] + 4 * i), 1);
3319 t3 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[3] + 4 * i), 0);
3320 t3 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[7] + 4 * i), 1);
3322 __m256
v0 = _mm256_shuffle_ps(t0, t1, 0x44);
3323 __m256
v1 = _mm256_shuffle_ps(t0, t1, 0xee);
3324 __m256 v2 = _mm256_shuffle_ps(t2, t3, 0x44);
3325 __m256 v3 = _mm256_shuffle_ps(t2, t3, 0xee);
3326 out[4 * i + 0].
data = _mm256_shuffle_ps(
v0, v2, 0x88);
3327 out[4 * i + 1].
data = _mm256_shuffle_ps(
v0, v2, 0xdd);
3328 out[4 * i + 2].
data = _mm256_shuffle_ps(
v1, v3, 0x88);
3329 out[4 * i + 3].
data = _mm256_shuffle_ps(
v1, v3, 0xdd);
3333 const unsigned int i = 4 * n_chunks;
3334 const unsigned int remainder = n_entries - i;
3339 __m128i
mask = _mm_setr_epi32(-1, -1, -1, 0);
3340 __m256 t0, t1, t2, t3 = {};
3341 t0 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[0] + i, mask), 0);
3342 t0 = _mm256_insertf128_ps(t0, _mm_maskload_ps(in[4] + i, mask), 1);
3343 t1 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[1] + i, mask), 0);
3344 t1 = _mm256_insertf128_ps(t1, _mm_maskload_ps(in[5] + i, mask), 1);
3345 t2 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[2] + i, mask), 0);
3346 t2 = _mm256_insertf128_ps(t2, _mm_maskload_ps(in[6] + i, mask), 1);
3347 t3 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[3] + i, mask), 0);
3348 t3 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[7] + i, mask), 1);
3349 __m256
v0 = _mm256_shuffle_ps(t0, t1, 0x44);
3350 __m256
v1 = _mm256_shuffle_ps(t0, t1, 0xee);
3351 __m256 v2 = _mm256_shuffle_ps(t2, t3, 0x44);
3352 __m256 v3 = _mm256_shuffle_ps(t2, t3, 0xee);
3353 out[i + 0].
data = _mm256_shuffle_ps(
v0, v2, 0x88);
3354 out[i + 1].
data = _mm256_shuffle_ps(
v0, v2, 0xdd);
3355 out[i + 2].
data = _mm256_shuffle_ps(
v1, v3, 0x88);
3357 else if (remainder == 2)
3361 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[0] + i));
3362 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[1] + i));
3363 __m256i
v0 = _mm256_castsi128_si256(_mm_unpacklo_epi64(t0, t1));
3364 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[4] + i));
3365 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[5] + i));
3366 v0 = _mm256_inserti128_si256(
v0, _mm_unpacklo_epi64(t0, t1), 1);
3367 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[2] + i));
3368 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[3] + i));
3369 __m256i
v1 = _mm256_castsi128_si256(_mm_unpacklo_epi64(t0, t1));
3370 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[6] + i));
3371 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[7] + i));
3372 v1 = _mm256_inserti128_si256(
v1, _mm_unpacklo_epi64(t0, t1), 1);
3373 out[i + 0].
data = _mm256_shuffle_ps(_mm256_castsi256_ps(
v0),
3374 _mm256_castsi256_ps(
v1),
3376 out[i + 1].
data = _mm256_shuffle_ps(_mm256_castsi256_ps(
v0),
3377 _mm256_castsi256_ps(
v1),
3380 else if (remainder == 1)
3381 for (
unsigned int v = 0; v < 8; ++v)
3382 out[i][v] = in[v][i];
3394 const unsigned int *offsets,
3417 const unsigned int n_entries,
3419 const std::array<float *, 8> &out)
3421 const unsigned int n_chunks = n_entries / 4;
3422 for (
unsigned int i = 0; i < n_chunks; ++i)
3424 __m256 u0 = in[4 * i + 0].
data;
3425 __m256 u1 = in[4 * i + 1].
data;
3426 __m256 u2 = in[4 * i + 2].
data;
3427 __m256 u3 = in[4 * i + 3].
data;
3428 __m256 t0 = _mm256_shuffle_ps(u0, u1, 0x44);
3429 __m256 t1 = _mm256_shuffle_ps(u0, u1, 0xee);
3430 __m256 t2 = _mm256_shuffle_ps(u2, u3, 0x44);
3431 __m256 t3 = _mm256_shuffle_ps(u2, u3, 0xee);
3432 u0 = _mm256_shuffle_ps(t0, t2, 0x88);
3433 u1 = _mm256_shuffle_ps(t0, t2, 0xdd);
3434 u2 = _mm256_shuffle_ps(t1, t3, 0x88);
3435 u3 = _mm256_shuffle_ps(t1, t3, 0xdd);
3436 __m128 res0 = _mm256_extractf128_ps(u0, 0);
3437 __m128 res4 = _mm256_extractf128_ps(u0, 1);
3438 __m128 res1 = _mm256_extractf128_ps(u1, 0);
3439 __m128 res5 = _mm256_extractf128_ps(u1, 1);
3440 __m128 res2 = _mm256_extractf128_ps(u2, 0);
3441 __m128 res6 = _mm256_extractf128_ps(u2, 1);
3442 __m128 res3 = _mm256_extractf128_ps(u3, 0);
3443 __m128 res7 = _mm256_extractf128_ps(u3, 1);
3450 res0 = _mm_add_ps(_mm_loadu_ps(out[0] + 4 * i), res0);
3451 _mm_storeu_ps(out[0] + 4 * i, res0);
3452 res1 = _mm_add_ps(_mm_loadu_ps(out[1] + 4 * i), res1);
3453 _mm_storeu_ps(out[1] + 4 * i, res1);
3454 res2 = _mm_add_ps(_mm_loadu_ps(out[2] + 4 * i), res2);
3455 _mm_storeu_ps(out[2] + 4 * i, res2);
3456 res3 = _mm_add_ps(_mm_loadu_ps(out[3] + 4 * i), res3);
3457 _mm_storeu_ps(out[3] + 4 * i, res3);
3458 res4 = _mm_add_ps(_mm_loadu_ps(out[4] + 4 * i), res4);
3459 _mm_storeu_ps(out[4] + 4 * i, res4);
3460 res5 = _mm_add_ps(_mm_loadu_ps(out[5] + 4 * i), res5);
3461 _mm_storeu_ps(out[5] + 4 * i, res5);
3462 res6 = _mm_add_ps(_mm_loadu_ps(out[6] + 4 * i), res6);
3463 _mm_storeu_ps(out[6] + 4 * i, res6);
3464 res7 = _mm_add_ps(_mm_loadu_ps(out[7] + 4 * i), res7);
3465 _mm_storeu_ps(out[7] + 4 * i, res7);
3469 _mm_storeu_ps(out[0] + 4 * i, res0);
3470 _mm_storeu_ps(out[1] + 4 * i, res1);
3471 _mm_storeu_ps(out[2] + 4 * i, res2);
3472 _mm_storeu_ps(out[3] + 4 * i, res3);
3473 _mm_storeu_ps(out[4] + 4 * i, res4);
3474 _mm_storeu_ps(out[5] + 4 * i, res5);
3475 _mm_storeu_ps(out[6] + 4 * i, res6);
3476 _mm_storeu_ps(out[7] + 4 * i, res7);
3481 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
3482 for (
unsigned int v = 0; v < 8; ++v)
3483 out[v][i] += in[i][v];
3485 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
3486 for (
unsigned int v = 0; v < 8; ++v)
3487 out[v][i] = in[i][v];
3498 const unsigned int n_entries,
3500 const unsigned int *offsets,
3513 out + offsets[7]}});
3521# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512 && defined(__AVX512F__)
3559 template <
typename U>
3570 data = _mm512_set1_pd(x);
3581 operator=(
const double scalar) && =
delete;
3590 return *(
reinterpret_cast<double *
>(&
data) + comp);
3600 return *(
reinterpret_cast<const double *
>(&
data) + comp);
3614# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3628# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3641# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3655# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3669 load(
const double *ptr)
3671 data = _mm512_loadu_pd(ptr);
3675 load(
const float *ptr)
3677 data = _mm512_cvtps_pd(_mm256_loadu_ps(ptr));
3687 store(
double *ptr)
const
3689 _mm512_storeu_pd(ptr,
data);
3693 store(
float *ptr)
const
3695 _mm256_storeu_ps(ptr, _mm512_cvtpd_ps(
data));
3705 Assert(
reinterpret_cast<std::size_t
>(ptr) % 64 == 0,
3707 _mm512_stream_pd(ptr,
data);
3714 gather(
const double *base_ptr,
const unsigned int *offsets)
3716# ifdef DEAL_II_USE_VECTORIZATION_GATHER
3720 const __m256 index_val =
3721 _mm256_loadu_ps(
reinterpret_cast<const float *
>(offsets));
3722 const __m256i
index = *
reinterpret_cast<const __m256i *
>(&index_val);
3729 const __m256i
equal = _mm256_cmpeq_epi32(invalid, index);
3731 static_cast<__mmask8
>(~(_mm256_movemask_ps(_mm256_castsi256_ps(
equal))));
3733 data = _mm512_mask_i32gather_pd(zero, mask, index, base_ptr, 8);
3736 for (
unsigned int i = 0; i < 8; ++i)
3738 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
3746 scatter(
const unsigned int *offsets,
double *base_ptr)
const
3748# ifdef DEAL_II_USE_VECTORIZATION_GATHER
3749 for (
unsigned int i = 0; i < 8; ++i)
3750 for (
unsigned int j = i + 1; j < 8; ++j)
3752 offsets[i] != offsets[j],
3753 ExcMessage(
"Result of scatter undefined if two offset elements"
3754 " point to the same position"));
3759 const __m256 index_val =
3760 _mm256_loadu_ps(
reinterpret_cast<const float *
>(offsets));
3761 const __m256i
index = *
reinterpret_cast<const __m256i *
>(&index_val);
3763 const __m256i
equal = _mm256_cmpeq_epi32(invalid, index);
3765 static_cast<__mmask8
>(~(_mm256_movemask_ps(_mm256_castsi256_ps(
equal))));
3766 _mm512_mask_i32scatter_pd(base_ptr, mask, index,
data, 8);
3769 for (
unsigned int i = 0; i < 8; ++i)
3771 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
3783 t1.
data = _mm256_add_pd(this->get_lower(), this->get_upper());
3794 res.
data = _mm512_roundscale_pd(
data, _MM_FROUND_TO_NEG_INF);
3812 return _mm512_castpd512_pd256(
data);
3821 return _mm512_extractf64x4_pd(
data, 1);
3848 __m512d
mask = _mm512_set1_pd(-0.);
3850 res.
data =
reinterpret_cast<__m512d
>(
3851 _mm512_andnot_epi64(
reinterpret_cast<__m512i
>(mask),
3852 reinterpret_cast<__m512i
>(
data)));
3881 template <
typename Number2, std::
size_t w
idth2>
3884 template <
typename Number2, std::
size_t w
idth2>
3887 template <
typename Number2, std::
size_t w
idth2>
3891 template <
typename Number2, std::
size_t w
idth2>
3905 const std::array<const double *, 8> &in,
3913 const unsigned int n_chunks = n_entries / 4;
3914 for (
unsigned int i = 0; i < n_chunks; ++i)
3916 __m512d t0, t1, t2, t3 = {};
3918 t0 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[0] + 4 * i), 0);
3919 t0 = _mm512_insertf64x4(t0, _mm256_loadu_pd(in[2] + 4 * i), 1);
3920 t1 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[1] + 4 * i), 0);
3921 t1 = _mm512_insertf64x4(t1, _mm256_loadu_pd(in[3] + 4 * i), 1);
3922 t2 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[4] + 4 * i), 0);
3923 t2 = _mm512_insertf64x4(t2, _mm256_loadu_pd(in[6] + 4 * i), 1);
3924 t3 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[5] + 4 * i), 0);
3925 t3 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[7] + 4 * i), 1);
3927 __m512d
v0 = _mm512_shuffle_f64x2(t0, t2, 0x88);
3928 __m512d
v1 = _mm512_shuffle_f64x2(t0, t2, 0xdd);
3929 __m512d v2 = _mm512_shuffle_f64x2(t1, t3, 0x88);
3930 __m512d v3 = _mm512_shuffle_f64x2(t1, t3, 0xdd);
3931 out[4 * i + 0].
data = _mm512_unpacklo_pd(
v0, v2);
3932 out[4 * i + 1].
data = _mm512_unpackhi_pd(
v0, v2);
3933 out[4 * i + 2].
data = _mm512_unpacklo_pd(
v1, v3);
3934 out[4 * i + 3].
data = _mm512_unpackhi_pd(
v1, v3);
3938 const unsigned int i = 4 * n_chunks;
3939 const unsigned int remainder = n_entries - i;
3944 __m256i
mask{-1, -1, -1, 0};
3945 __m512d t0, t1, t2, t3 = {};
3947 t0 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[0] + i, mask), 0);
3948 t0 = _mm512_insertf64x4(t0, _mm256_maskload_pd(in[2] + i, mask), 1);
3949 t1 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[1] + i, mask), 0);
3950 t1 = _mm512_insertf64x4(t1, _mm256_maskload_pd(in[3] + i, mask), 1);
3951 t2 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[4] + i, mask), 0);
3952 t2 = _mm512_insertf64x4(t2, _mm256_maskload_pd(in[6] + i, mask), 1);
3953 t3 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[5] + i, mask), 0);
3954 t3 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[7] + i, mask), 1);
3956 __m512d
v0 = _mm512_shuffle_f64x2(t0, t2, 0x88);
3957 __m512d
v1 = _mm512_shuffle_f64x2(t0, t2, 0xdd);
3958 __m512d v2 = _mm512_shuffle_f64x2(t1, t3, 0x88);
3959 __m512d v3 = _mm512_shuffle_f64x2(t1, t3, 0xdd);
3960 out[i + 0].
data = _mm512_unpacklo_pd(
v0, v2);
3961 out[i + 1].
data = _mm512_unpackhi_pd(
v0, v2);
3962 out[i + 2].
data = _mm512_unpacklo_pd(
v1, v3);
3964 else if (remainder == 2)
3967 __m256d t0, t1, t2, t3 = {};
3968 t0 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[0] + i), 0);
3969 t0 = _mm256_insertf128_pd(t0, _mm_loadu_pd(in[2] + i), 1);
3970 t1 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[1] + i), 0);
3971 t1 = _mm256_insertf128_pd(t1, _mm_loadu_pd(in[3] + i), 1);
3972 t2 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[4] + i), 0);
3973 t2 = _mm256_insertf128_pd(t2, _mm_loadu_pd(in[6] + i), 1);
3974 t3 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[5] + i), 0);
3975 t3 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[7] + i), 1);
3977 __m512d
v0,
v1 = {};
3978 v0 = _mm512_insertf64x4(
v1, t0, 0);
3979 v0 = _mm512_insertf64x4(
v0, t2, 1);
3980 v1 = _mm512_insertf64x4(
v1, t1, 0);
3981 v1 = _mm512_insertf64x4(
v1, t3, 1);
3982 out[i + 0].
data = _mm512_unpacklo_pd(
v0,
v1);
3983 out[i + 1].
data = _mm512_unpackhi_pd(
v0,
v1);
3985 else if (remainder == 1)
3986 for (
unsigned int v = 0; v < 8; ++v)
3987 out[i][v] = in[v][i];
3999 const unsigned int *offsets,
4022 const unsigned int n_entries,
4024 const std::array<double *, 8> &out)
4028 const unsigned int n_chunks = n_entries / 4;
4029 __m512i mask1 = _mm512_set_epi64(0xd, 0xc, 0x5, 0x4, 0x9, 0x8, 0x1, 0x0);
4030 __m512i mask2 = _mm512_set_epi64(0xf, 0xe, 0x7, 0x6, 0xb, 0xa, 0x3, 0x2);
4031 for (
unsigned int i = 0; i < n_chunks; ++i)
4033 __m512d t0 = _mm512_unpacklo_pd(in[i * 4].
data, in[i * 4 + 1].
data);
4034 __m512d t1 = _mm512_unpackhi_pd(in[i * 4].
data, in[i * 4 + 1].
data);
4035 __m512d t2 = _mm512_unpacklo_pd(in[i * 4 + 2].
data, in[i * 4 + 3].
data);
4036 __m512d t3 = _mm512_unpackhi_pd(in[i * 4 + 2].
data, in[i * 4 + 3].
data);
4037 __m512d
v0 = _mm512_permutex2var_pd(t0, mask1, t2);
4038 __m512d
v1 = _mm512_permutex2var_pd(t0, mask2, t2);
4039 __m512d v2 = _mm512_permutex2var_pd(t1, mask1, t3);
4040 __m512d v3 = _mm512_permutex2var_pd(t1, mask2, t3);
4041 __m256d res0 = _mm512_extractf64x4_pd(
v0, 0);
4042 __m256d res4 = _mm512_extractf64x4_pd(
v0, 1);
4043 __m256d res1 = _mm512_extractf64x4_pd(v2, 0);
4044 __m256d res5 = _mm512_extractf64x4_pd(v2, 1);
4045 __m256d res2 = _mm512_extractf64x4_pd(
v1, 0);
4046 __m256d res6 = _mm512_extractf64x4_pd(
v1, 1);
4047 __m256d res3 = _mm512_extractf64x4_pd(v3, 0);
4048 __m256d res7 = _mm512_extractf64x4_pd(v3, 1);
4055 res0 = _mm256_add_pd(_mm256_loadu_pd(out[0] + 4 * i), res0);
4056 _mm256_storeu_pd(out[0] + 4 * i, res0);
4057 res1 = _mm256_add_pd(_mm256_loadu_pd(out[1] + 4 * i), res1);
4058 _mm256_storeu_pd(out[1] + 4 * i, res1);
4059 res2 = _mm256_add_pd(_mm256_loadu_pd(out[2] + 4 * i), res2);
4060 _mm256_storeu_pd(out[2] + 4 * i, res2);
4061 res3 = _mm256_add_pd(_mm256_loadu_pd(out[3] + 4 * i), res3);
4062 _mm256_storeu_pd(out[3] + 4 * i, res3);
4063 res4 = _mm256_add_pd(_mm256_loadu_pd(out[4] + 4 * i), res4);
4064 _mm256_storeu_pd(out[4] + 4 * i, res4);
4065 res5 = _mm256_add_pd(_mm256_loadu_pd(out[5] + 4 * i), res5);
4066 _mm256_storeu_pd(out[5] + 4 * i, res5);
4067 res6 = _mm256_add_pd(_mm256_loadu_pd(out[6] + 4 * i), res6);
4068 _mm256_storeu_pd(out[6] + 4 * i, res6);
4069 res7 = _mm256_add_pd(_mm256_loadu_pd(out[7] + 4 * i), res7);
4070 _mm256_storeu_pd(out[7] + 4 * i, res7);
4074 _mm256_storeu_pd(out[0] + 4 * i, res0);
4075 _mm256_storeu_pd(out[1] + 4 * i, res1);
4076 _mm256_storeu_pd(out[2] + 4 * i, res2);
4077 _mm256_storeu_pd(out[3] + 4 * i, res3);
4078 _mm256_storeu_pd(out[4] + 4 * i, res4);
4079 _mm256_storeu_pd(out[5] + 4 * i, res5);
4080 _mm256_storeu_pd(out[6] + 4 * i, res6);
4081 _mm256_storeu_pd(out[7] + 4 * i, res7);
4086 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
4087 for (
unsigned int v = 0; v < 8; ++v)
4088 out[v][i] += in[i][v];
4090 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
4091 for (
unsigned int v = 0; v < 8; ++v)
4092 out[v][i] = in[i][v];
4103 const unsigned int n_entries,
4105 const unsigned int *offsets,
4118 out + offsets[7]}});
4159 template <
typename U>
4170 data = _mm512_set1_ps(x);
4180 operator=(
const float scalar) && =
delete;
4189 return *(
reinterpret_cast<float *
>(&
data) + comp);
4199 return *(
reinterpret_cast<const float *
>(&
data) + comp);
4213# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
4227# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
4240# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
4254# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
4268 load(
const float *ptr)
4270 data = _mm512_loadu_ps(ptr);
4280 store(
float *ptr)
const
4282 _mm512_storeu_ps(ptr,
data);
4292 Assert(
reinterpret_cast<std::size_t
>(ptr) % 64 == 0,
4294 _mm512_stream_ps(ptr,
data);
4301 gather(
const float *base_ptr,
const unsigned int *offsets)
4303# ifdef DEAL_II_USE_VECTORIZATION_GATHER
4307 const __m512 index_val =
4308 _mm512_loadu_ps(
reinterpret_cast<const float *
>(offsets));
4309 const __m512i
index = *
reinterpret_cast<const __m512i *
>(&index_val);
4316 __mmask16
mask = _mm512_cmpneq_epu32_mask(invalid, index);
4318 data = _mm512_mask_i32gather_ps(zero, mask, index, base_ptr, 4);
4321 for (
unsigned int i = 0; i < 16; ++i)
4323 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
4331 scatter(
const unsigned int *offsets,
float *base_ptr)
const
4333# ifdef DEAL_II_USE_VECTORIZATION_GATHER
4334 for (
unsigned int i = 0; i < 16; ++i)
4335 for (
unsigned int j = i + 1; j < 16; ++j)
4337 offsets[i] != offsets[j],
4338 ExcMessage(
"Result of scatter undefined if two offset elements"
4339 " point to the same position"));
4344 const __m512 index_val =
4345 _mm512_loadu_ps(
reinterpret_cast<const float *
>(offsets));
4346 const __m512i
index = *
reinterpret_cast<const __m512i *
>(&index_val);
4348 __mmask16
mask = _mm512_cmpneq_epu32_mask(invalid, index);
4349 _mm512_mask_i32scatter_ps(base_ptr, mask, index,
data, 4);
4351 for (
unsigned int i = 0; i < 16; ++i)
4353 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
4365 t1.
data = _mm256_add_ps(this->get_lower(), this->get_upper());
4376 res.
data = _mm512_roundscale_ps(
data, _MM_FROUND_TO_NEG_INF);
4394 return _mm512_castps512_ps256(
data);
4403 return _mm256_castpd_ps(_mm512_extractf64x4_pd(_mm512_castps_pd(
data), 1));
4430 __m512
mask = _mm512_set1_ps(-0.f);
4432 res.
data =
reinterpret_cast<__m512
>(
4433 _mm512_andnot_epi32(
reinterpret_cast<__m512i
>(mask),
4434 reinterpret_cast<__m512i
>(
data)));
4463 template <
typename Number2, std::
size_t w
idth2>
4466 template <
typename Number2, std::
size_t w
idth2>
4469 template <
typename Number2, std::
size_t w
idth2>
4473 template <
typename Number2, std::
size_t w
idth2>
4487 const std::array<const float *, 16> &in,
4494 const unsigned int n_chunks = n_entries / 4;
4496 for (
unsigned int i = 0; i < n_chunks; ++i)
4498 __m512 t0, t1, t2, t3 = {};
4500 t0 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[0] + 4 * i), 0);
4501 t0 = _mm512_insertf32x4(t0, _mm_loadu_ps(in[4] + 4 * i), 1);
4502 t0 = _mm512_insertf32x4(t0, _mm_loadu_ps(in[8] + 4 * i), 2);
4503 t0 = _mm512_insertf32x4(t0, _mm_loadu_ps(in[12] + 4 * i), 3);
4504 t1 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[1] + 4 * i), 0);
4505 t1 = _mm512_insertf32x4(t1, _mm_loadu_ps(in[5] + 4 * i), 1);
4506 t1 = _mm512_insertf32x4(t1, _mm_loadu_ps(in[9] + 4 * i), 2);
4507 t1 = _mm512_insertf32x4(t1, _mm_loadu_ps(in[13] + 4 * i), 3);
4508 t2 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[2] + 4 * i), 0);
4509 t2 = _mm512_insertf32x4(t2, _mm_loadu_ps(in[6] + 4 * i), 1);
4510 t2 = _mm512_insertf32x4(t2, _mm_loadu_ps(in[10] + 4 * i), 2);
4511 t2 = _mm512_insertf32x4(t2, _mm_loadu_ps(in[14] + 4 * i), 3);
4512 t3 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[3] + 4 * i), 0);
4513 t3 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[7] + 4 * i), 1);
4514 t3 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[11] + 4 * i), 2);
4515 t3 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[15] + 4 * i), 3);
4517 __m512
v0 = _mm512_shuffle_ps(t0, t1, 0x44);
4518 __m512
v1 = _mm512_shuffle_ps(t0, t1, 0xee);
4519 __m512 v2 = _mm512_shuffle_ps(t2, t3, 0x44);
4520 __m512 v3 = _mm512_shuffle_ps(t2, t3, 0xee);
4522 out[4 * i + 0].
data = _mm512_shuffle_ps(
v0, v2, 0x88);
4523 out[4 * i + 1].
data = _mm512_shuffle_ps(
v0, v2, 0xdd);
4524 out[4 * i + 2].
data = _mm512_shuffle_ps(
v1, v3, 0x88);
4525 out[4 * i + 3].
data = _mm512_shuffle_ps(
v1, v3, 0xdd);
4529 const unsigned int i = 4 * n_chunks;
4530 const unsigned int remainder = n_entries - i;
4533 __m512 t0, t1, t2, t3 = {};
4537 __m128i
mask = _mm_setr_epi32(-1, -1, -1, 0);
4538 t0 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[0] + i, mask), 0);
4539 t0 = _mm512_insertf32x4(t0, _mm_maskload_ps(in[4] + i, mask), 1);
4540 t0 = _mm512_insertf32x4(t0, _mm_maskload_ps(in[8] + i, mask), 2);
4541 t0 = _mm512_insertf32x4(t0, _mm_maskload_ps(in[12] + i, mask), 3);
4542 t1 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[1] + i, mask), 0);
4543 t1 = _mm512_insertf32x4(t1, _mm_maskload_ps(in[5] + i, mask), 1);
4544 t1 = _mm512_insertf32x4(t1, _mm_maskload_ps(in[9] + i, mask), 2);
4545 t1 = _mm512_insertf32x4(t1, _mm_maskload_ps(in[13] + i, mask), 3);
4546 t2 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[2] + i, mask), 0);
4547 t2 = _mm512_insertf32x4(t2, _mm_maskload_ps(in[6] + i, mask), 1);
4548 t2 = _mm512_insertf32x4(t2, _mm_maskload_ps(in[10] + i, mask), 2);
4549 t2 = _mm512_insertf32x4(t2, _mm_maskload_ps(in[14] + i, mask), 3);
4550 t3 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[3] + i, mask), 0);
4551 t3 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[7] + i, mask), 1);
4552 t3 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[11] + i, mask), 2);
4553 t3 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[15] + i, mask), 3);
4554 __m512
v0 = _mm512_shuffle_ps(t0, t1, 0x44);
4555 __m512
v1 = _mm512_shuffle_ps(t0, t1, 0xee);
4556 __m512 v2 = _mm512_shuffle_ps(t2, t3, 0x44);
4557 __m512 v3 = _mm512_shuffle_ps(t2, t3, 0xee);
4558 out[i + 0].
data = _mm512_shuffle_ps(
v0, v2, 0x88);
4559 out[i + 1].
data = _mm512_shuffle_ps(
v0, v2, 0xdd);
4560 out[i + 2].
data = _mm512_shuffle_ps(
v1, v3, 0x88);
4562 else if (remainder == 2)
4568 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[0] + i));
4569 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[1] + i));
4571 _mm512_insertf32x4(
v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 0);
4572 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[4] + i));
4573 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[5] + i));
4575 _mm512_insertf32x4(
v0, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 1);
4576 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[8] + i));
4577 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[9] + i));
4579 _mm512_insertf32x4(
v0, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 2);
4580 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[12] + i));
4581 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[13] + i));
4583 _mm512_insertf32x4(
v0, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 3);
4584 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[2] + i));
4585 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[3] + i));
4587 _mm512_insertf32x4(
v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 0);
4588 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[6] + i));
4589 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[7] + i));
4591 _mm512_insertf32x4(
v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 1);
4592 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[10] + i));
4593 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[11] + i));
4595 _mm512_insertf32x4(
v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 2);
4596 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[14] + i));
4597 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[15] + i));
4599 _mm512_insertf32x4(
v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 3);
4600 out[i + 0].
data = _mm512_shuffle_ps(
v0,
v1, 0x88);
4601 out[i + 1].
data = _mm512_shuffle_ps(
v0,
v1, 0xdd);
4603 else if (remainder == 1)
4604 for (
unsigned int v = 0; v < 16; ++v)
4605 out[i][v] = in[v][i];
4617 const unsigned int *offsets,
4648 const unsigned int n_entries,
4650 const std::array<float *, 16> &out)
4652 const unsigned int n_chunks = n_entries / 4;
4653 for (
unsigned int i = 0; i < n_chunks; ++i)
4655 __m512 t0 = _mm512_shuffle_ps(in[4 * i].
data, in[1 + 4 * i].
data, 0x44);
4656 __m512 t1 = _mm512_shuffle_ps(in[4 * i].
data, in[1 + 4 * i].
data, 0xee);
4658 _mm512_shuffle_ps(in[2 + 4 * i].
data, in[3 + 4 * i].
data, 0x44);
4660 _mm512_shuffle_ps(in[2 + 4 * i].
data, in[3 + 4 * i].
data, 0xee);
4661 __m512 u0 = _mm512_shuffle_ps(t0, t2, 0x88);
4662 __m512 u1 = _mm512_shuffle_ps(t0, t2, 0xdd);
4663 __m512 u2 = _mm512_shuffle_ps(t1, t3, 0x88);
4664 __m512 u3 = _mm512_shuffle_ps(t1, t3, 0xdd);
4666 __m128 res0 = _mm512_extractf32x4_ps(u0, 0);
4667 __m128 res4 = _mm512_extractf32x4_ps(u0, 1);
4668 __m128 res8 = _mm512_extractf32x4_ps(u0, 2);
4669 __m128 res12 = _mm512_extractf32x4_ps(u0, 3);
4670 __m128 res1 = _mm512_extractf32x4_ps(u1, 0);
4671 __m128 res5 = _mm512_extractf32x4_ps(u1, 1);
4672 __m128 res9 = _mm512_extractf32x4_ps(u1, 2);
4673 __m128 res13 = _mm512_extractf32x4_ps(u1, 3);
4674 __m128 res2 = _mm512_extractf32x4_ps(u2, 0);
4675 __m128 res6 = _mm512_extractf32x4_ps(u2, 1);
4676 __m128 res10 = _mm512_extractf32x4_ps(u2, 2);
4677 __m128 res14 = _mm512_extractf32x4_ps(u2, 3);
4678 __m128 res3 = _mm512_extractf32x4_ps(u3, 0);
4679 __m128 res7 = _mm512_extractf32x4_ps(u3, 1);
4680 __m128 res11 = _mm512_extractf32x4_ps(u3, 2);
4681 __m128 res15 = _mm512_extractf32x4_ps(u3, 3);
4688 res0 = _mm_add_ps(_mm_loadu_ps(out[0] + 4 * i), res0);
4689 _mm_storeu_ps(out[0] + 4 * i, res0);
4690 res1 = _mm_add_ps(_mm_loadu_ps(out[1] + 4 * i), res1);
4691 _mm_storeu_ps(out[1] + 4 * i, res1);
4692 res2 = _mm_add_ps(_mm_loadu_ps(out[2] + 4 * i), res2);
4693 _mm_storeu_ps(out[2] + 4 * i, res2);
4694 res3 = _mm_add_ps(_mm_loadu_ps(out[3] + 4 * i), res3);
4695 _mm_storeu_ps(out[3] + 4 * i, res3);
4696 res4 = _mm_add_ps(_mm_loadu_ps(out[4] + 4 * i), res4);
4697 _mm_storeu_ps(out[4] + 4 * i, res4);
4698 res5 = _mm_add_ps(_mm_loadu_ps(out[5] + 4 * i), res5);
4699 _mm_storeu_ps(out[5] + 4 * i, res5);
4700 res6 = _mm_add_ps(_mm_loadu_ps(out[6] + 4 * i), res6);
4701 _mm_storeu_ps(out[6] + 4 * i, res6);
4702 res7 = _mm_add_ps(_mm_loadu_ps(out[7] + 4 * i), res7);
4703 _mm_storeu_ps(out[7] + 4 * i, res7);
4704 res8 = _mm_add_ps(_mm_loadu_ps(out[8] + 4 * i), res8);
4705 _mm_storeu_ps(out[8] + 4 * i, res8);
4706 res9 = _mm_add_ps(_mm_loadu_ps(out[9] + 4 * i), res9);
4707 _mm_storeu_ps(out[9] + 4 * i, res9);
4708 res10 = _mm_add_ps(_mm_loadu_ps(out[10] + 4 * i), res10);
4709 _mm_storeu_ps(out[10] + 4 * i, res10);
4710 res11 = _mm_add_ps(_mm_loadu_ps(out[11] + 4 * i), res11);
4711 _mm_storeu_ps(out[11] + 4 * i, res11);
4712 res12 = _mm_add_ps(_mm_loadu_ps(out[12] + 4 * i), res12);
4713 _mm_storeu_ps(out[12] + 4 * i, res12);
4714 res13 = _mm_add_ps(_mm_loadu_ps(out[13] + 4 * i), res13);
4715 _mm_storeu_ps(out[13] + 4 * i, res13);
4716 res14 = _mm_add_ps(_mm_loadu_ps(out[14] + 4 * i), res14);
4717 _mm_storeu_ps(out[14] + 4 * i, res14);
4718 res15 = _mm_add_ps(_mm_loadu_ps(out[15] + 4 * i), res15);
4719 _mm_storeu_ps(out[15] + 4 * i, res15);
4723 _mm_storeu_ps(out[0] + 4 * i, res0);
4724 _mm_storeu_ps(out[1] + 4 * i, res1);
4725 _mm_storeu_ps(out[2] + 4 * i, res2);
4726 _mm_storeu_ps(out[3] + 4 * i, res3);
4727 _mm_storeu_ps(out[4] + 4 * i, res4);
4728 _mm_storeu_ps(out[5] + 4 * i, res5);
4729 _mm_storeu_ps(out[6] + 4 * i, res6);
4730 _mm_storeu_ps(out[7] + 4 * i, res7);
4731 _mm_storeu_ps(out[8] + 4 * i, res8);
4732 _mm_storeu_ps(out[9] + 4 * i, res9);
4733 _mm_storeu_ps(out[10] + 4 * i, res10);
4734 _mm_storeu_ps(out[11] + 4 * i, res11);
4735 _mm_storeu_ps(out[12] + 4 * i, res12);
4736 _mm_storeu_ps(out[13] + 4 * i, res13);
4737 _mm_storeu_ps(out[14] + 4 * i, res14);
4738 _mm_storeu_ps(out[15] + 4 * i, res15);
4743 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
4744 for (
unsigned int v = 0; v < 16; ++v)
4745 out[v][i] += in[i][v];
4747 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
4748 for (
unsigned int v = 0; v < 16; ++v)
4749 out[v][i] = in[i][v];
4760 const unsigned int n_entries,
4762 const unsigned int *offsets,
4783 out + offsets[15]}});
4788# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ALTIVEC__) && \
4824 template <
typename U>
4835 data = vec_splats(x);
4850 operator=(
const double scalar) && =
delete;
4859 return *(
reinterpret_cast<double *
>(&
data) + comp);
4869 return *(
reinterpret_cast<const double *
>(&
data) + comp);
4917 load(
const double *ptr)
4919 data = vec_vsx_ld(0, ptr);
4927 store(
double *ptr)
const
4929 vec_vsx_st(
data, 0, ptr);
4945 gather(
const double *base_ptr,
const unsigned int *offsets)
4948 for (
unsigned int i = 0; i < 2; ++i)
4950 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
4957 scatter(
const unsigned int *offsets,
double *base_ptr)
const
4959 for (
unsigned int i = 0; i < 2; ++i)
4961 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
4969 __vector
double data;
5021 template <
typename Number2, std::
size_t w
idth2>
5024 template <
typename Number2, std::
size_t w
idth2>
5027 template <
typename Number2, std::
size_t w
idth2>
5031 template <
typename Number2, std::
size_t w
idth2>
5072 template <
typename U>
5083 data = vec_splats(x);
5098 operator=(
const float scalar) && =
delete;
5107 return *(
reinterpret_cast<float *
>(&
data) + comp);
5117 return *(
reinterpret_cast<const float *
>(&
data) + comp);
5165 load(
const float *ptr)
5167 data = vec_vsx_ld(0, ptr);
5175 store(
float *ptr)
const
5177 vec_vsx_st(
data, 0, ptr);
5193 gather(
const float *base_ptr,
const unsigned int *offsets)
5196 for (
unsigned int i = 0; i < 4; ++i)
5198 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
5205 scatter(
const unsigned int *offsets,
float *base_ptr)
const
5207 for (
unsigned int i = 0; i < 4; ++i)
5209 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
5217 __vector
float data;
5269 template <
typename Number2, std::
size_t w
idth2>
5272 template <
typename Number2, std::
size_t w
idth2>
5275 template <
typename Number2, std::
size_t w
idth2>
5279 template <
typename Number2, std::
size_t w
idth2>
5303template <
typename Number, std::
size_t w
idth>
5308 for (
unsigned int i = 0; i < VectorizedArray<Number, width>::size(); ++i)
5309 if (lhs[i] != rhs[i])
5321template <
typename Number, std::
size_t w
idth>
5335template <
typename Number, std::
size_t w
idth>
5349template <
typename Number, std::
size_t w
idth>
5363template <
typename Number, std::
size_t w
idth>
5378template <
typename Number, std::
size_t w
idth>
5394template <std::
size_t w
idth>
5408template <
typename Number, std::
size_t w
idth>
5423template <std::
size_t w
idth>
5436template <
typename Number, std::
size_t w
idth>
5452template <std::
size_t w
idth>
5466template <
typename Number, std::
size_t w
idth>
5482template <std::
size_t w
idth>
5496template <
typename Number, std::
size_t w
idth>
5512template <std::
size_t w
idth>
5526template <
typename Number, std::
size_t w
idth>
5541template <std::
size_t w
idth>
5554template <
typename Number, std::
size_t w
idth>
5570template <std::
size_t w
idth>
5584template <
typename Number, std::
size_t w
idth>
5600template <std::
size_t w
idth>
5613template <
typename Number, std::
size_t w
idth>
5625template <
typename Number, std::
size_t w
idth>
5639template <
typename Number, std::
size_t w
idth>
5640inline std::ostream &
5644 for (
unsigned int i = 0; i < n - 1; ++i)
5667#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
5748template <SIMDComparison predicate,
typename Number>
5751 const Number &right,
5752 const Number &true_value,
5753 const Number &false_value)
5759 mask = (left == right);
5762 mask = (left != right);
5765 mask = (left < right);
5768 mask = (left <= right);
5771 mask = (left > right);
5774 mask = (left >= right);
5778 return mask ? true_value : false_value;
5786template <SIMDComparison predicate,
typename Number>
5794 result.
data = compare_and_apply_mask<predicate, Number>(left.
data,
5804# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512 && defined(__AVX512F__)
5806template <SIMDComparison predicate>
5813 const __mmask16
mask =
5814 _mm512_cmp_ps_mask(left.
data, right.
data,
static_cast<int>(predicate));
5816 result.
data = _mm512_mask_mov_ps(false_values.
data, mask, true_values.
data);
5822template <SIMDComparison predicate>
5829 const __mmask16
mask =
5830 _mm512_cmp_pd_mask(left.
data, right.
data,
static_cast<int>(predicate));
5832 result.
data = _mm512_mask_mov_pd(false_values.
data, mask, true_values.
data);
5838# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
5840template <SIMDComparison predicate>
5848 _mm256_cmp_ps(left.
data, right.
data,
static_cast<int>(predicate));
5851 result.
data = _mm256_blendv_ps(false_values.
data, true_values.
data, mask);
5856template <SIMDComparison predicate>
5864 _mm256_cmp_pd(left.
data, right.
data,
static_cast<int>(predicate));
5867 result.
data = _mm256_blendv_pd(false_values.
data, true_values.
data, mask);
5873# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__SSE2__)
5875template <SIMDComparison predicate>
5906 result.
data = _mm_or_ps(_mm_and_ps(mask, true_values.
data),
5907 _mm_andnot_ps(mask, false_values.
data));
5913template <SIMDComparison predicate>
5944 result.
data = _mm_or_pd(_mm_and_pd(mask, true_values.
data),
5945 _mm_andnot_pd(mask, false_values.
data));
5952# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ARM_NEON)
5954template <SIMDComparison predicate>
5985 result.
data = vreinterpretq_f32_u32(vorrq_u32(
5986 vandq_u32(mask, vreinterpretq_u32_f32(true_values.
data)),
5987 vandq_u32(vmvnq_u32(mask), vreinterpretq_u32_f32(false_values.
data))));
5993template <SIMDComparison predicate>
6007 mask = vreinterpretq_u64_u32(
6008 vmvnq_u32(vreinterpretq_u32_u64(vceqq_f64(left.
data, right.
data))));
6025 result.
data = vreinterpretq_f64_u64(vorrq_u64(
6026 vandq_u64(mask, vreinterpretq_u64_f64(true_values.
data)),
6027 vandq_u64(vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(mask))),
6028 vreinterpretq_u64_f64(false_values.
data))));
6039 template <
typename T>
6050 static constexpr std::size_t
6067 static constexpr std::size_t
6121 template <
typename T, std::
size_t w
idth_>
6132 static constexpr std::size_t
6150 static constexpr std::size_t
6223 template <
typename Number, std::
size_t w
idth>
6224 inline ::VectorizedArray<Number, width>
6225 sin(const ::VectorizedArray<Number, width> &x)
6228 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6243 template <
typename Number, std::
size_t w
idth>
6244 inline ::VectorizedArray<Number, width>
6245 cos(const ::VectorizedArray<Number, width> &x)
6248 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6263 template <
typename Number, std::
size_t w
idth>
6264 inline ::VectorizedArray<Number, width>
6265 tan(const ::VectorizedArray<Number, width> &x)
6268 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6283 template <
typename Number, std::
size_t w
idth>
6284 inline ::VectorizedArray<Number, width>
6285 acos(const ::VectorizedArray<Number, width> &x)
6288 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6303 template <
typename Number, std::
size_t w
idth>
6304 inline ::VectorizedArray<Number, width>
6305 asin(const ::VectorizedArray<Number, width> &x)
6308 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6323 template <
typename Number, std::
size_t w
idth>
6324 inline ::VectorizedArray<Number, width>
6325 atan(const ::VectorizedArray<Number, width> &x)
6328 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6343 template <
typename Number, std::
size_t w
idth>
6344 inline ::VectorizedArray<Number, width>
6345 cosh(const ::VectorizedArray<Number, width> &x)
6348 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6363 template <
typename Number, std::
size_t w
idth>
6364 inline ::VectorizedArray<Number, width>
6365 sinh(const ::VectorizedArray<Number, width> &x)
6368 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6383 template <
typename Number, std::
size_t w
idth>
6384 inline ::VectorizedArray<Number, width>
6385 tanh(const ::VectorizedArray<Number, width> &x)
6388 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6403 template <
typename Number, std::
size_t w
idth>
6404 inline ::VectorizedArray<Number, width>
6405 acosh(const ::VectorizedArray<Number, width> &x)
6408 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6423 template <
typename Number, std::
size_t w
idth>
6424 inline ::VectorizedArray<Number, width>
6425 asinh(const ::VectorizedArray<Number, width> &x)
6428 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6443 template <
typename Number, std::
size_t w
idth>
6444 inline ::VectorizedArray<Number, width>
6445 atanh(const ::VectorizedArray<Number, width> &x)
6448 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6463 template <
typename Number, std::
size_t w
idth>
6464 inline ::VectorizedArray<Number, width>
6465 exp(const ::VectorizedArray<Number, width> &x)
6468 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6483 template <
typename Number, std::
size_t w
idth>
6484 inline ::VectorizedArray<Number, width>
6485 log(const ::VectorizedArray<Number, width> &x)
6488 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6503 template <
typename Number, std::
size_t w
idth>
6504 inline ::VectorizedArray<Number, width>
6505 sqrt(const ::VectorizedArray<Number, width> &x)
6507 return x.get_sqrt();
6519 template <
typename Number, std::
size_t w
idth>
6520 inline ::VectorizedArray<Number, width>
6521 pow(const ::VectorizedArray<Number, width> &x,
const Number p)
6524 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6540 template <
typename Number, std::
size_t w
idth>
6541 inline ::VectorizedArray<Number, width>
6542 pow(const ::VectorizedArray<Number, width> &x,
6543 const ::VectorizedArray<Number, width> &p)
6546 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6561 template <
typename Number, std::
size_t w
idth>
6562 inline ::VectorizedArray<Number, width>
6563 abs(const ::VectorizedArray<Number, width> &x)
6577 template <
typename Number, std::
size_t w
idth>
6578 inline ::VectorizedArray<Number, width>
6579 max(const ::VectorizedArray<Number, width> &x,
6580 const ::VectorizedArray<Number, width> &y)
6582 return x.get_max(y);
6594 template <
typename Number, std::
size_t w
idth>
6595 inline ::VectorizedArray<Number, width>
6596 min(const ::VectorizedArray<Number, width> &x,
6597 const ::VectorizedArray<Number, width> &y)
6599 return x.get_min(y);
6610#ifdef DEAL_II_HAVE_CXX20
constexpr VectorizedArrayBase()=default
constexpr VectorizedArrayIterator< const VectorizedArrayType > begin() const
constexpr VectorizedArrayBase(const std::initializer_list< U > &list)
constexpr VectorizedArrayIterator< const VectorizedArrayType > end() const
constexpr VectorizedArrayIterator< VectorizedArrayType > begin()
constexpr VectorizedArrayIterator< VectorizedArrayType > end()
static constexpr std::size_t size()
auto dot_product(const VectorizedArrayType &v) const
constexpr VectorizedArrayIterator< T > & operator++()
constexpr VectorizedArrayIterator(T &data, const std::size_t lane)
constexpr VectorizedArrayIterator< T > operator+(const std::size_t &offset) const
constexpr VectorizedArrayIterator< T > & operator+=(const std::size_t offset)
constexpr bool operator==(const VectorizedArrayIterator< T > &other) const
constexpr std::enable_if_t<!std::is_same_v< U, const U >, typename T::value_type > & operator*()
constexpr const T::value_type & operator*() const
constexpr VectorizedArrayIterator< T > & operator--()
constexpr std::ptrdiff_t operator-(const VectorizedArrayIterator< T > &other) const
constexpr bool operator!=(const VectorizedArrayIterator< T > &other) const
VectorizedArray< Number, width > operator-(const VectorizedArray< Number, width > &u)
VectorizedArray & operator=(const Number scalar) &
VectorizedArray< float, width > operator+(const VectorizedArray< float, width > &v, const double u)
VectorizedArray & operator/=(const VectorizedArray &vec)
void gather(const Number *base_ptr, const unsigned int *offsets)
void vectorized_load_and_transpose(const unsigned int n_entries, const Number *in, const unsigned int *offsets, VectorizedArray< Number, width > *out)
VectorizedArray< Number, width > operator+(const VectorizedArray< Number, width > &v, const Number &u)
VectorizedArrayType make_vectorized_array(const typename VectorizedArrayType::value_type &u)
VectorizedArray< Number, width > operator/(const VectorizedArray< Number, width > &v, const Number &u)
VectorizedArray< Number, width > asinh(const ::VectorizedArray< Number, width > &x)
VectorizedArray get_abs() const
VectorizedArray< float, width > operator/(const VectorizedArray< float, width > &v, const double u)
VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &x, const ::VectorizedArray< Number, width > &y)
VectorizedArray< Number, width > log(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > operator*(const VectorizedArray< Number, width > &v, const Number &u)
VectorizedArray< Number, width > exp(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > operator-(const VectorizedArray< Number, width > &v, const Number &u)
Number & operator[](const unsigned int comp)
VectorizedArray get_floor() const
VectorizedArray< float, width > operator-(const double u, const VectorizedArray< float, width > &v)
VectorizedArray< Number, width > operator+(const Number &u, const VectorizedArray< Number, width > &v)
VectorizedArray< Number, width > operator+(const VectorizedArray< Number, width > &u)
VectorizedArray()=default
bool operator==(const VectorizedArray< Number, width > &lhs, const VectorizedArray< Number, width > &rhs)
VectorizedArray< Number, width > tan(const ::VectorizedArray< Number, width > &x)
VectorizedArray(const Number scalar)
VectorizedArray< Number, width > operator-(const VectorizedArray< Number, width > &u, const VectorizedArray< Number, width > &v)
VectorizedArray< float, width > operator*(const VectorizedArray< float, width > &v, const double u)
VectorizedArray & operator*=(const VectorizedArray &vec)
VectorizedArray get_max(const VectorizedArray &other) const
VectorizedArray< Number, width > atan(const ::VectorizedArray< Number, width > &x)
const Number & operator[](const unsigned int comp) const
VectorizedArray< Number, width > tanh(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &x, const ::VectorizedArray< Number, width > &y)
VectorizedArray get_min(const VectorizedArray &other) const
VectorizedArray< Number, width > cosh(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &x, const Number p)
VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &x, const ::VectorizedArray< Number, width > &p)
VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &x)
void store(OtherNumber *ptr) const
VectorizedArray< float, width > operator-(const VectorizedArray< float, width > &v, const double u)
void load(const OtherNumber *ptr)
void scatter(const unsigned int *offsets, Number *base_ptr) const
VectorizedArray< Number, width > atanh(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > operator-(const Number &u, const VectorizedArray< Number, width > &v)
VectorizedArray & operator=(const Number scalar) &&=delete
VectorizedArray< Number, width > operator*(const VectorizedArray< Number, width > &u, const VectorizedArray< Number, width > &v)
VectorizedArray & operator-=(const VectorizedArray &vec)
VectorizedArray< Number, width > acos(const ::VectorizedArray< Number, width > &x)
VectorizedArray< float, width > operator+(const double u, const VectorizedArray< float, width > &v)
VectorizedArray< Number, width > operator*(const Number &u, const VectorizedArray< Number, width > &v)
VectorizedArray< Number, width > sinh(const ::VectorizedArray< Number, width > &x)
VectorizedArray get_sqrt() const
VectorizedArray< Number, width > asin(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > operator/(const Number &u, const VectorizedArray< Number, width > &v)
VectorizedArray & operator+=(const VectorizedArray &vec)
VectorizedArray< Number, width > make_vectorized_array(const Number &u)
VectorizedArray< Number, width > operator/(const VectorizedArray< Number, width > &u, const VectorizedArray< Number, width > &v)
VectorizedArray< Number, width > operator+(const VectorizedArray< Number, width > &u, const VectorizedArray< Number, width > &v)
VectorizedArray< Number, width > acosh(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &x)
void streaming_store(Number *ptr) const
VectorizedArray(const std::initializer_list< U > &list)
void vectorized_transpose_and_store(const bool add_into, const unsigned int n_entries, const VectorizedArray< Number, width > *in, const unsigned int *offsets, Number *out)
VectorizedArray< float, width > operator/(const double u, const VectorizedArray< float, width > &v)
VectorizedArray< float, width > operator*(const double u, const VectorizedArray< float, width > &v)
static constexpr bool is_implemented
#define DEAL_II_ALWAYS_INLINE
#define DEAL_II_OPENMP_SIMD_PRAGMA
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< index_type > data
constexpr types::blas_int zero
* * * RotationFunction< dim, Number >::RotationFunction Number(dim)
constexpr unsigned int invalid_unsigned_int
inline ::VectorizedArray< Number, width > acosh(const ::VectorizedArray< Number, width > &x)
::VectorizedArray< Number, width > log(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > exp(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > tan(const ::VectorizedArray< Number, width > &)
inline ::VectorizedArray< Number, width > asinh(const ::VectorizedArray< Number, width > &x)
inline ::VectorizedArray< Number, width > tanh(const ::VectorizedArray< Number, width > &x)
inline ::VectorizedArray< Number, width > sinh(const ::VectorizedArray< Number, width > &x)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
inline ::VectorizedArray< Number, width > cosh(const ::VectorizedArray< Number, width > &x)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
inline ::VectorizedArray< Number, width > atanh(const ::VectorizedArray< Number, width > &x)
inline ::VectorizedArray< Number, width > atan(const ::VectorizedArray< Number, width > &x)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
inline ::VectorizedArray< Number, width > acos(const ::VectorizedArray< Number, width > &x)
inline ::VectorizedArray< Number, width > asin(const ::VectorizedArray< Number, width > &x)
static value_type & get(vectorized_value_type &values, unsigned int c)
static constexpr std::size_t stride()
static vectorized_value_type & get_from_vectorized(vectorized_value_type &values, unsigned int c)
static constexpr std::size_t width()
static const value_type & get(const vectorized_value_type &values, unsigned int c)
static const vectorized_value_type & get_from_vectorized(const vectorized_value_type &values, unsigned int c)
static constexpr std::size_t width()
static constexpr std::size_t stride()
static const value_type & get(const value_type &value, unsigned int c)
VectorizedArray< T > vectorized_value_type
static const value_type & get_from_vectorized(const vectorized_value_type &values, unsigned int c)
static value_type & get_from_vectorized(vectorized_value_type &values, unsigned int c)
static value_type & get(value_type &value, unsigned int c)
typename T::value_type value_type
std::ptrdiff_t difference_type
random_access_iterator_tag iterator_category
void vectorized_load_and_transpose(const unsigned int n_entries, const Number *in, const unsigned int *offsets, VectorizedArray< Number, width > *out)
std::ostream & operator<<(std::ostream &out, const VectorizedArray< Number, width > &p)
Number compare_and_apply_mask(const Number &left, const Number &right, const Number &true_value, const Number &false_value)
void gather(VectorizedArray< Number, width > &out, const std::array< const Number *, width > &ptrs, const unsigned int offset)
void vectorized_transpose_and_store(const bool add_into, const unsigned int n_entries, const VectorizedArray< Number, width > *in, const unsigned int *offsets, Number *out)