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.");
584 template <
typename OtherNumber>
597 template <
typename OtherNumber>
676 gather(
const Number *base_ptr,
const unsigned int *offsets)
680 data = base_ptr[offsets[0]];
700 scatter(
const unsigned int *offsets, Number *base_ptr)
const
703 base_ptr[offsets[0]] =
data;
789 template <
typename Number2, std::
size_t w
idth2>
792 template <
typename Number2, std::
size_t w
idth2>
795 template <
typename Number2, std::
size_t w
idth2>
799 template <
typename Number2, std::
size_t w
idth2>
818template <
typename Number,
836template <
typename VectorizedArrayType>
841 std::is_same_v<VectorizedArrayType,
843 VectorizedArrayType::size()>>,
844 "VectorizedArrayType is not a VectorizedArray.");
846 VectorizedArrayType result = u;
863template <
typename Number, std::
size_t w
idth>
866 const std::array<const Number *, width> &ptrs,
867 const unsigned int offset)
869 for (
unsigned int v = 0; v < width; ++v)
870 out.
data[v] = ptrs[v][offset];
900template <
typename Number, std::
size_t w
idth>
904 const unsigned int *offsets,
907 for (
unsigned int i = 0; i < n_entries; ++i)
908 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
909 out[i][v] = in[offsets[v] + i];
924template <
typename Number, std::
size_t w
idth>
927 const std::array<const Number *, width> &in,
930 for (
unsigned int i = 0; i < n_entries; ++i)
931 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
932 out[i][v] = in[v][i];
975template <
typename Number, std::
size_t w
idth>
978 const unsigned int n_entries,
980 const unsigned int *offsets,
984 for (
unsigned int i = 0; i < n_entries; ++i)
985 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
986 out[offsets[v] + i] += in[i][v];
988 for (
unsigned int i = 0; i < n_entries; ++i)
989 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
990 out[offsets[v] + i] = in[i][v];
1005template <
typename Number, std::
size_t w
idth>
1008 const unsigned int n_entries,
1010 const std::array<Number *, width> &out)
1013 for (
unsigned int i = 0; i < n_entries; ++i)
1014 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
1015 out[v][i] += in[i][v];
1017 for (
unsigned int i = 0; i < n_entries; ++i)
1018 for (
unsigned int v = 0; v < VectorizedArray<Number, width>::size(); ++v)
1019 out[v][i] = in[i][v];
1027# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ARM_NEON)
1065 template <
typename U>
1076 data = vdupq_n_f64(x);
1086 operator=(
const double scalar) && =
delete;
1094 return *(
reinterpret_cast<double *
>(&
data) + comp);
1103 return *(
reinterpret_cast<const double *
>(&
data) + comp);
1152 load(
const double *ptr)
1154 data = vld1q_f64(ptr);
1159 load(
const float *ptr)
1162 for (
unsigned int i = 0; i < 2; ++i)
1173 store(
double *ptr)
const
1175 vst1q_f64(ptr,
data);
1180 store(
float *ptr)
const
1183 for (
unsigned int i = 0; i < 2; ++i)
1195 Assert(
reinterpret_cast<std::size_t
>(ptr) % 16 == 0,
1197 vst1q_f64(ptr,
data);
1204 gather(
const double *base_ptr,
const unsigned int *offsets)
1207 for (
unsigned int i = 0; i < 2; ++i)
1209 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
1216 scatter(
const unsigned int *offsets,
double *base_ptr)
const
1218 for (
unsigned int i = 0; i < 2; ++i)
1220 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
1230 return vaddvq_f64(
data);
1249 mutable float64x2_t
data;
1301 template <
typename Number2, std::
size_t w
idth2>
1304 template <
typename Number2, std::
size_t w
idth2>
1307 template <
typename Number2, std::
size_t w
idth2>
1311 template <
typename Number2, std::
size_t w
idth2>
1353 template <
typename U>
1364 data = vdupq_n_f32(x);
1374 operator=(
const float scalar) && =
delete;
1382 return *(
reinterpret_cast<float *
>(&
data) + comp);
1391 return *(
reinterpret_cast<const float *
>(&
data) + comp);
1440 load(
const float *ptr)
1442 data = vld1q_f32(ptr);
1452 store(
float *ptr)
const
1454 vst1q_f32(ptr,
data);
1465 Assert(
reinterpret_cast<std::size_t
>(ptr) % 16 == 0,
1467 vst1q_f32(ptr,
data);
1474 gather(
const float *base_ptr,
const unsigned int *offsets)
1477 for (
unsigned int i = 0; i < 4; ++i)
1479 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
1486 scatter(
const unsigned int *offsets,
float *base_ptr)
const
1488 for (
unsigned int i = 0; i < 4; ++i)
1490 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
1500 return vaddvq_f32(
data);
1520 mutable float32x4_t
data;
1572 template <
typename Number2, std::
size_t w
idth2>
1575 template <
typename Number2, std::
size_t w
idth2>
1578 template <
typename Number2, std::
size_t w
idth2>
1582 template <
typename Number2, std::
size_t w
idth2>
1591# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__SSE2__)
1629 template <
typename U>
1641 data = _mm_set1_pd(x);
1651 operator=(
const double scalar) && =
delete;
1661 return *(
reinterpret_cast<double *
>(&
data) + comp);
1672 return *(
reinterpret_cast<const double *
>(&
data) + comp);
1682# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
1697# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
1712# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
1727# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
1742 load(
const double *ptr)
1744 data = _mm_loadu_pd(ptr);
1749 load(
const float *ptr)
1752 for (
unsigned int i = 0; i < 2; ++i)
1764 store(
double *ptr)
const
1766 _mm_storeu_pd(ptr,
data);
1771 store(
float *ptr)
const
1774 for (
unsigned int i = 0; i < 2; ++i)
1786 Assert(
reinterpret_cast<std::size_t
>(ptr) % 16 == 0,
1788 _mm_stream_pd(ptr,
data);
1796 gather(
const double *base_ptr,
const unsigned int *offsets)
1799 for (
unsigned int i = 0; i < 2; ++i)
1801 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
1809 scatter(
const unsigned int *offsets,
double *base_ptr)
const
1811 for (
unsigned int i = 0; i < 2; ++i)
1813 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
1823 __m128d t1 = _mm_unpackhi_pd(
data,
data);
1824 __m128d t2 = _mm_add_pd(
data, t1);
1825 return _mm_cvtsd_f64(t2);
1835 for (std::size_t i = 0; i < 2; ++i)
1873 __m128d
mask = _mm_set1_pd(-0.);
1875 res.
data = _mm_andnot_pd(mask,
data);
1906 template <
typename Number2, std::
size_t w
idth2>
1909 template <
typename Number2, std::
size_t w
idth2>
1912 template <
typename Number2, std::
size_t w
idth2>
1916 template <
typename Number2, std::
size_t w
idth2>
1930 const std::array<const double *, 2> &in,
1933 const unsigned int n_chunks = n_entries / 2;
1934 for (
unsigned int i = 0; i < n_chunks; ++i)
1936 __m128d u0 = _mm_loadu_pd(in[0] + 2 * i);
1937 __m128d u1 = _mm_loadu_pd(in[1] + 2 * i);
1938 out[2 * i + 0].
data = _mm_unpacklo_pd(u0, u1);
1939 out[2 * i + 1].
data = _mm_unpackhi_pd(u0, u1);
1943 for (
unsigned int i = 2 * n_chunks; i < n_entries; ++i)
1944 for (
unsigned int v = 0; v < 2; ++v)
1945 out[i][v] = in[v][i];
1957 const unsigned int *offsets,
1961 {{in + offsets[0], in + offsets[1]}},
1973 const unsigned int n_entries,
1975 const std::array<double *, 2> &out)
1977 const unsigned int n_chunks = n_entries / 2;
1980 for (
unsigned int i = 0; i < n_chunks; ++i)
1982 __m128d u0 = in[2 * i + 0].
data;
1983 __m128d u1 = in[2 * i + 1].
data;
1984 __m128d res0 = _mm_unpacklo_pd(u0, u1);
1985 __m128d res1 = _mm_unpackhi_pd(u0, u1);
1986 _mm_storeu_pd(out[0] + 2 * i,
1987 _mm_add_pd(_mm_loadu_pd(out[0] + 2 * i), res0));
1988 _mm_storeu_pd(out[1] + 2 * i,
1989 _mm_add_pd(_mm_loadu_pd(out[1] + 2 * i), res1));
1993 for (
unsigned int i = 2 * n_chunks; i < n_entries; ++i)
1994 for (
unsigned int v = 0; v < 2; ++v)
1995 out[v][i] += in[i][v];
1999 for (
unsigned int i = 0; i < n_chunks; ++i)
2001 __m128d u0 = in[2 * i + 0].
data;
2002 __m128d u1 = in[2 * i + 1].
data;
2003 __m128d res0 = _mm_unpacklo_pd(u0, u1);
2004 __m128d res1 = _mm_unpackhi_pd(u0, u1);
2005 _mm_storeu_pd(out[0] + 2 * i, res0);
2006 _mm_storeu_pd(out[1] + 2 * i, res1);
2010 for (
unsigned int i = 2 * n_chunks; i < n_entries; ++i)
2011 for (
unsigned int v = 0; v < 2; ++v)
2012 out[v][i] = in[i][v];
2024 const unsigned int n_entries,
2026 const unsigned int *offsets,
2032 {{out + offsets[0], out + offsets[1]}});
2073 template <
typename U>
2085 data = _mm_set1_ps(x);
2095 operator=(
const float scalar) && =
delete;
2105 return *(
reinterpret_cast<float *
>(&
data) + comp);
2116 return *(
reinterpret_cast<const float *
>(&
data) + comp);
2126# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2141# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2156# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2171# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2186 load(
const float *ptr)
2188 data = _mm_loadu_ps(ptr);
2199 store(
float *ptr)
const
2201 _mm_storeu_ps(ptr,
data);
2212 Assert(
reinterpret_cast<std::size_t
>(ptr) % 16 == 0,
2214 _mm_stream_ps(ptr,
data);
2222 gather(
const float *base_ptr,
const unsigned int *offsets)
2225 for (
unsigned int i = 0; i < 4; ++i)
2227 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
2235 scatter(
const unsigned int *offsets,
float *base_ptr)
const
2237 for (
unsigned int i = 0; i < 4; ++i)
2239 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
2249 __m128 t1 = _mm_movehl_ps(
data,
data);
2250 __m128 t2 = _mm_add_ps(
data, t1);
2251 __m128 t3 = _mm_shuffle_ps(t2, t2, 1);
2252 __m128 t4 = _mm_add_ss(t2, t3);
2253 return _mm_cvtss_f32(t4);
2263 for (std::size_t i = 0; i < 4; ++i)
2300 __m128
mask = _mm_set1_ps(-0.f);
2302 res.
data = _mm_andnot_ps(mask,
data);
2333 template <
typename Number2, std::
size_t w
idth2>
2336 template <
typename Number2, std::
size_t w
idth2>
2339 template <
typename Number2, std::
size_t w
idth2>
2343 template <
typename Number2, std::
size_t w
idth2>
2357 const std::array<const float *, 4> &in,
2360 const unsigned int n_chunks = n_entries / 4;
2361 for (
unsigned int i = 0; i < n_chunks; ++i)
2363 __m128 u0 = _mm_loadu_ps(in[0] + 4 * i);
2364 __m128 u1 = _mm_loadu_ps(in[1] + 4 * i);
2365 __m128 u2 = _mm_loadu_ps(in[2] + 4 * i);
2366 __m128 u3 = _mm_loadu_ps(in[3] + 4 * i);
2367 __m128 v0 = _mm_shuffle_ps(u0, u1, 0x44);
2368 __m128 v1 = _mm_shuffle_ps(u0, u1, 0xee);
2369 __m128 v2 = _mm_shuffle_ps(u2, u3, 0x44);
2370 __m128 v3 = _mm_shuffle_ps(u2, u3, 0xee);
2371 out[4 * i + 0].
data = _mm_shuffle_ps(v0, v2, 0x88);
2372 out[4 * i + 1].
data = _mm_shuffle_ps(v0, v2, 0xdd);
2373 out[4 * i + 2].
data = _mm_shuffle_ps(v1, v3, 0x88);
2374 out[4 * i + 3].
data = _mm_shuffle_ps(v1, v3, 0xdd);
2378 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
2379 for (
unsigned int v = 0; v < 4; ++v)
2380 out[i][v] = in[v][i];
2392 const unsigned int *offsets,
2397 {{in + offsets[0], in + offsets[1], in + offsets[2], in + offsets[3]}},
2409 const unsigned int n_entries,
2411 const std::array<float *, 4> &out)
2413 const unsigned int n_chunks = n_entries / 4;
2414 for (
unsigned int i = 0; i < n_chunks; ++i)
2416 __m128 u0 = in[4 * i + 0].
data;
2417 __m128 u1 = in[4 * i + 1].
data;
2418 __m128 u2 = in[4 * i + 2].
data;
2419 __m128 u3 = in[4 * i + 3].
data;
2420 __m128 t0 = _mm_shuffle_ps(u0, u1, 0x44);
2421 __m128 t1 = _mm_shuffle_ps(u0, u1, 0xee);
2422 __m128 t2 = _mm_shuffle_ps(u2, u3, 0x44);
2423 __m128 t3 = _mm_shuffle_ps(u2, u3, 0xee);
2424 u0 = _mm_shuffle_ps(t0, t2, 0x88);
2425 u1 = _mm_shuffle_ps(t0, t2, 0xdd);
2426 u2 = _mm_shuffle_ps(t1, t3, 0x88);
2427 u3 = _mm_shuffle_ps(t1, t3, 0xdd);
2434 u0 = _mm_add_ps(_mm_loadu_ps(out[0] + 4 * i), u0);
2435 _mm_storeu_ps(out[0] + 4 * i, u0);
2436 u1 = _mm_add_ps(_mm_loadu_ps(out[1] + 4 * i), u1);
2437 _mm_storeu_ps(out[1] + 4 * i, u1);
2438 u2 = _mm_add_ps(_mm_loadu_ps(out[2] + 4 * i), u2);
2439 _mm_storeu_ps(out[2] + 4 * i, u2);
2440 u3 = _mm_add_ps(_mm_loadu_ps(out[3] + 4 * i), u3);
2441 _mm_storeu_ps(out[3] + 4 * i, u3);
2445 _mm_storeu_ps(out[0] + 4 * i, u0);
2446 _mm_storeu_ps(out[1] + 4 * i, u1);
2447 _mm_storeu_ps(out[2] + 4 * i, u2);
2448 _mm_storeu_ps(out[3] + 4 * i, u3);
2454 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
2455 for (
unsigned int v = 0; v < 4; ++v)
2456 out[v][i] += in[i][v];
2458 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
2459 for (
unsigned int v = 0; v < 4; ++v)
2460 out[v][i] = in[i][v];
2471 const unsigned int n_entries,
2473 const unsigned int *offsets,
2480 {{out + offsets[0], out + offsets[1], out + offsets[2], out + offsets[3]}});
2487# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
2525 template <
typename U>
2537 data = _mm256_set1_pd(x);
2547 operator=(
const double scalar) && =
delete;
2557 return *(
reinterpret_cast<double *
>(&
data) + comp);
2568 return *(
reinterpret_cast<const double *
>(&
data) + comp);
2583# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2598# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2612# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2627# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
2642 load(
const double *ptr)
2644 data = _mm256_loadu_pd(ptr);
2649 load(
const float *ptr)
2651 data = _mm256_cvtps_pd(_mm_loadu_ps(ptr));
2662 store(
double *ptr)
const
2664 _mm256_storeu_pd(ptr,
data);
2669 store(
float *ptr)
const
2671 _mm_storeu_ps(ptr, _mm256_cvtpd_ps(
data));
2682 Assert(
reinterpret_cast<std::size_t
>(ptr) % 32 == 0,
2684 _mm256_stream_pd(ptr,
data);
2692 gather(
const double *base_ptr,
const unsigned int *offsets)
2694# if defined(__AVX2__) && defined(DEAL_II_USE_VECTORIZATION_GATHER)
2698 const __m128 index_val =
2699 _mm_loadu_ps(
reinterpret_cast<const float *
>(offsets));
2700 const __m128i
index = *
reinterpret_cast<const __m128i *
>(&index_val);
2705 __m256d
zero = _mm256_setzero_pd();
2706 __m128i neq32 = _mm_andnot_si128(_mm_cmpeq_epi32(index, _mm_set1_epi32(-1)),
2707 _mm_set1_epi32(-1));
2709 __m256d
mask = _mm256_castsi256_pd(_mm256_cvtepi32_epi64(neq32));
2711 data = _mm256_mask_i32gather_pd(zero, base_ptr, index, mask, 8);
2714 for (
unsigned int i = 0; i < 4; ++i)
2716 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
2725 scatter(
const unsigned int *offsets,
double *base_ptr)
const
2728 for (
unsigned int i = 0; i < 4; ++i)
2730 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
2741 t1.
data = _mm_add_pd(this->get_lower(), this->get_upper());
2771 return _mm256_castpd256_pd128(
data);
2781 return _mm256_extractf128_pd(
data, 1);
2808 __m256d
mask = _mm256_set1_pd(-0.);
2810 res.
data = _mm256_andnot_pd(mask,
data);
2841 template <
typename Number2, std::
size_t w
idth2>
2844 template <
typename Number2, std::
size_t w
idth2>
2847 template <
typename Number2, std::
size_t w
idth2>
2851 template <
typename Number2, std::
size_t w
idth2>
2865 const std::array<const double *, 4> &in,
2868 const unsigned int n_chunks = n_entries / 4;
2869 const double *in0 = in[0];
2870 const double *in1 = in[1];
2871 const double *in2 = in[2];
2872 const double *in3 = in[3];
2874 for (
unsigned int i = 0; i < n_chunks; ++i)
2876 __m256d u0 = _mm256_loadu_pd(in0 + 4 * i);
2877 __m256d u1 = _mm256_loadu_pd(in1 + 4 * i);
2878 __m256d u2 = _mm256_loadu_pd(in2 + 4 * i);
2879 __m256d u3 = _mm256_loadu_pd(in3 + 4 * i);
2880 __m256d t0 = _mm256_permute2f128_pd(u0, u2, 0x20);
2881 __m256d t1 = _mm256_permute2f128_pd(u1, u3, 0x20);
2882 __m256d t2 = _mm256_permute2f128_pd(u0, u2, 0x31);
2883 __m256d t3 = _mm256_permute2f128_pd(u1, u3, 0x31);
2884 out[4 * i + 0].
data = _mm256_unpacklo_pd(t0, t1);
2885 out[4 * i + 1].
data = _mm256_unpackhi_pd(t0, t1);
2886 out[4 * i + 2].
data = _mm256_unpacklo_pd(t2, t3);
2887 out[4 * i + 3].
data = _mm256_unpackhi_pd(t2, t3);
2891 const unsigned int i = 4 * n_chunks;
2892 const unsigned int remainder = n_entries - i;
2897 __m256i
mask{-1, -1, -1, 0};
2898 __m256d u0 = _mm256_maskload_pd(in[0] + i, mask);
2899 __m256d u1 = _mm256_maskload_pd(in[1] + i, mask);
2900 __m256d u2 = _mm256_maskload_pd(in[2] + i, mask);
2901 __m256d u3 = _mm256_maskload_pd(in[3] + i, mask);
2902 __m256d t0 = _mm256_permute2f128_pd(u0, u2, 0x20);
2903 __m256d t1 = _mm256_permute2f128_pd(u1, u3, 0x20);
2904 __m256d t2 = _mm256_permute2f128_pd(u0, u2, 0x31);
2905 __m256d t3 = _mm256_permute2f128_pd(u1, u3, 0x31);
2906 out[i + 0].
data = _mm256_unpacklo_pd(t0, t1);
2907 out[i + 1].
data = _mm256_unpackhi_pd(t0, t1);
2908 out[i + 2].
data = _mm256_unpacklo_pd(t2, t3);
2910 else if (remainder == 2)
2913 __m256d t0, t1 = {};
2914 t0 = _mm256_insertf128_pd(t1, _mm_loadu_pd(in[0] + i), 0);
2915 t0 = _mm256_insertf128_pd(t0, _mm_loadu_pd(in[2] + i), 1);
2916 t1 = _mm256_insertf128_pd(t1, _mm_loadu_pd(in[1] + i), 0);
2917 t1 = _mm256_insertf128_pd(t1, _mm_loadu_pd(in[3] + i), 1);
2919 out[i + 0].
data = _mm256_unpacklo_pd(t0, t1);
2920 out[i + 1].
data = _mm256_unpackhi_pd(t0, t1);
2922 else if (remainder == 1)
2923 for (
unsigned int v = 0; v < 4; ++v)
2924 out[i][v] = in[v][i];
2936 const unsigned int *offsets,
2941 {{in + offsets[0], in + offsets[1], in + offsets[2], in + offsets[3]}},
2953 const unsigned int n_entries,
2955 const std::array<double *, 4> &out)
2957 const unsigned int n_chunks = n_entries / 4;
2958 double *out0 = out[0];
2959 double *out1 = out[1];
2960 double *out2 = out[2];
2961 double *out3 = out[3];
2962 for (
unsigned int i = 0; i < n_chunks; ++i)
2964 __m256d u0 = in[4 * i + 0].
data;
2965 __m256d u1 = in[4 * i + 1].
data;
2966 __m256d u2 = in[4 * i + 2].
data;
2967 __m256d u3 = in[4 * i + 3].
data;
2968 __m256d t0 = _mm256_permute2f128_pd(u0, u2, 0x20);
2969 __m256d t1 = _mm256_permute2f128_pd(u1, u3, 0x20);
2970 __m256d t2 = _mm256_permute2f128_pd(u0, u2, 0x31);
2971 __m256d t3 = _mm256_permute2f128_pd(u1, u3, 0x31);
2972 __m256d res0 = _mm256_unpacklo_pd(t0, t1);
2973 __m256d res1 = _mm256_unpackhi_pd(t0, t1);
2974 __m256d res2 = _mm256_unpacklo_pd(t2, t3);
2975 __m256d res3 = _mm256_unpackhi_pd(t2, t3);
2982 res0 = _mm256_add_pd(_mm256_loadu_pd(out0 + 4 * i), res0);
2983 _mm256_storeu_pd(out0 + 4 * i, res0);
2984 res1 = _mm256_add_pd(_mm256_loadu_pd(out1 + 4 * i), res1);
2985 _mm256_storeu_pd(out1 + 4 * i, res1);
2986 res2 = _mm256_add_pd(_mm256_loadu_pd(out2 + 4 * i), res2);
2987 _mm256_storeu_pd(out2 + 4 * i, res2);
2988 res3 = _mm256_add_pd(_mm256_loadu_pd(out3 + 4 * i), res3);
2989 _mm256_storeu_pd(out3 + 4 * i, res3);
2993 _mm256_storeu_pd(out0 + 4 * i, res0);
2994 _mm256_storeu_pd(out1 + 4 * i, res1);
2995 _mm256_storeu_pd(out2 + 4 * i, res2);
2996 _mm256_storeu_pd(out3 + 4 * i, res3);
3002 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
3003 for (
unsigned int v = 0; v < 4; ++v)
3004 out[v][i] += in[i][v];
3006 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
3007 for (
unsigned int v = 0; v < 4; ++v)
3008 out[v][i] = in[i][v];
3019 const unsigned int n_entries,
3021 const unsigned int *offsets,
3028 {{out + offsets[0], out + offsets[1], out + offsets[2], out + offsets[3]}});
3069 template <
typename U>
3081 data = _mm256_set1_ps(x);
3091 operator=(
const float scalar) && =
delete;
3101 return *(
reinterpret_cast<float *
>(&
data) + comp);
3112 return *(
reinterpret_cast<const float *
>(&
data) + comp);
3127# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3142# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3156# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3171# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3186 load(
const float *ptr)
3188 data = _mm256_loadu_ps(ptr);
3199 store(
float *ptr)
const
3201 _mm256_storeu_ps(ptr,
data);
3212 Assert(
reinterpret_cast<std::size_t
>(ptr) % 32 == 0,
3214 _mm256_stream_ps(ptr,
data);
3222 gather(
const float *base_ptr,
const unsigned int *offsets)
3224# if defined(__AVX2__) && defined(DEAL_II_USE_VECTORIZATION_GATHER)
3228 const __m256 index_val =
3229 _mm256_loadu_ps(
reinterpret_cast<const float *
>(offsets));
3230 const __m256i
index = *
reinterpret_cast<const __m256i *
>(&index_val);
3235 __m256
zero = _mm256_setzero_ps();
3237 __m256i inverse_mask = _mm256_cmpeq_epi32(index, invalid);
3238 __m256i
mask = _mm256_xor_si256(invalid, inverse_mask);
3240 data = _mm256_mask_i32gather_ps(
3241 zero, base_ptr, index, *
reinterpret_cast<__m256 *
>(&mask), 4);
3244 for (
unsigned int i = 0; i < 8; ++i)
3246 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
3255 scatter(
const unsigned int *offsets,
float *base_ptr)
const
3258 for (
unsigned int i = 0; i < 8; ++i)
3260 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
3271 t1.
data = _mm_add_ps(this->get_lower(), this->get_upper());
3301 return _mm256_castps256_ps128(
data);
3311 return _mm256_extractf128_ps(
data, 1);
3338 __m256
mask = _mm256_set1_ps(-0.f);
3340 res.
data = _mm256_andnot_ps(mask,
data);
3371 template <
typename Number2, std::
size_t w
idth2>
3374 template <
typename Number2, std::
size_t w
idth2>
3377 template <
typename Number2, std::
size_t w
idth2>
3381 template <
typename Number2, std::
size_t w
idth2>
3395 const std::array<const float *, 8> &in,
3398 const unsigned int n_chunks = n_entries / 4;
3399 for (
unsigned int i = 0; i < n_chunks; ++i)
3403 __m256 t0, t1, t2, t3 = {};
3404 t0 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[0] + 4 * i), 0);
3405 t0 = _mm256_insertf128_ps(t0, _mm_loadu_ps(in[4] + 4 * i), 1);
3406 t1 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[1] + 4 * i), 0);
3407 t1 = _mm256_insertf128_ps(t1, _mm_loadu_ps(in[5] + 4 * i), 1);
3408 t2 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[2] + 4 * i), 0);
3409 t2 = _mm256_insertf128_ps(t2, _mm_loadu_ps(in[6] + 4 * i), 1);
3410 t3 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[3] + 4 * i), 0);
3411 t3 = _mm256_insertf128_ps(t3, _mm_loadu_ps(in[7] + 4 * i), 1);
3413 __m256 v0 = _mm256_shuffle_ps(t0, t1, 0x44);
3414 __m256 v1 = _mm256_shuffle_ps(t0, t1, 0xee);
3415 __m256 v2 = _mm256_shuffle_ps(t2, t3, 0x44);
3416 __m256 v3 = _mm256_shuffle_ps(t2, t3, 0xee);
3417 out[4 * i + 0].
data = _mm256_shuffle_ps(v0, v2, 0x88);
3418 out[4 * i + 1].
data = _mm256_shuffle_ps(v0, v2, 0xdd);
3419 out[4 * i + 2].
data = _mm256_shuffle_ps(v1, v3, 0x88);
3420 out[4 * i + 3].
data = _mm256_shuffle_ps(v1, v3, 0xdd);
3424 const unsigned int i = 4 * n_chunks;
3425 const unsigned int remainder = n_entries - i;
3430 __m128i
mask = _mm_setr_epi32(-1, -1, -1, 0);
3431 __m256 t0, t1, t2, t3 = {};
3432 t0 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[0] + i, mask), 0);
3433 t0 = _mm256_insertf128_ps(t0, _mm_maskload_ps(in[4] + i, mask), 1);
3434 t1 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[1] + i, mask), 0);
3435 t1 = _mm256_insertf128_ps(t1, _mm_maskload_ps(in[5] + i, mask), 1);
3436 t2 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[2] + i, mask), 0);
3437 t2 = _mm256_insertf128_ps(t2, _mm_maskload_ps(in[6] + i, mask), 1);
3438 t3 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[3] + i, mask), 0);
3439 t3 = _mm256_insertf128_ps(t3, _mm_maskload_ps(in[7] + i, mask), 1);
3440 __m256 v0 = _mm256_shuffle_ps(t0, t1, 0x44);
3441 __m256 v1 = _mm256_shuffle_ps(t0, t1, 0xee);
3442 __m256 v2 = _mm256_shuffle_ps(t2, t3, 0x44);
3443 __m256 v3 = _mm256_shuffle_ps(t2, t3, 0xee);
3444 out[i + 0].
data = _mm256_shuffle_ps(v0, v2, 0x88);
3445 out[i + 1].
data = _mm256_shuffle_ps(v0, v2, 0xdd);
3446 out[i + 2].
data = _mm256_shuffle_ps(v1, v3, 0x88);
3448 else if (remainder == 2)
3452 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[0] + i));
3453 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[1] + i));
3454 __m256i v0 = _mm256_castsi128_si256(_mm_unpacklo_epi64(t0, t1));
3455 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[4] + i));
3456 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[5] + i));
3457 v0 = _mm256_inserti128_si256(v0, _mm_unpacklo_epi64(t0, t1), 1);
3458 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[2] + i));
3459 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[3] + i));
3460 __m256i v1 = _mm256_castsi128_si256(_mm_unpacklo_epi64(t0, t1));
3461 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[6] + i));
3462 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[7] + i));
3463 v1 = _mm256_inserti128_si256(v1, _mm_unpacklo_epi64(t0, t1), 1);
3464 out[i + 0].
data = _mm256_shuffle_ps(_mm256_castsi256_ps(v0),
3465 _mm256_castsi256_ps(v1),
3467 out[i + 1].
data = _mm256_shuffle_ps(_mm256_castsi256_ps(v0),
3468 _mm256_castsi256_ps(v1),
3471 else if (remainder == 1)
3472 for (
unsigned int v = 0; v < 8; ++v)
3473 out[i][v] = in[v][i];
3485 const unsigned int *offsets,
3508 const unsigned int n_entries,
3510 const std::array<float *, 8> &out)
3512 const unsigned int n_chunks = n_entries / 4;
3513 for (
unsigned int i = 0; i < n_chunks; ++i)
3515 __m256 u0 = in[4 * i + 0].
data;
3516 __m256 u1 = in[4 * i + 1].
data;
3517 __m256 u2 = in[4 * i + 2].
data;
3518 __m256 u3 = in[4 * i + 3].
data;
3519 __m256 t0 = _mm256_shuffle_ps(u0, u1, 0x44);
3520 __m256 t1 = _mm256_shuffle_ps(u0, u1, 0xee);
3521 __m256 t2 = _mm256_shuffle_ps(u2, u3, 0x44);
3522 __m256 t3 = _mm256_shuffle_ps(u2, u3, 0xee);
3523 u0 = _mm256_shuffle_ps(t0, t2, 0x88);
3524 u1 = _mm256_shuffle_ps(t0, t2, 0xdd);
3525 u2 = _mm256_shuffle_ps(t1, t3, 0x88);
3526 u3 = _mm256_shuffle_ps(t1, t3, 0xdd);
3527 __m128 res0 = _mm256_extractf128_ps(u0, 0);
3528 __m128 res4 = _mm256_extractf128_ps(u0, 1);
3529 __m128 res1 = _mm256_extractf128_ps(u1, 0);
3530 __m128 res5 = _mm256_extractf128_ps(u1, 1);
3531 __m128 res2 = _mm256_extractf128_ps(u2, 0);
3532 __m128 res6 = _mm256_extractf128_ps(u2, 1);
3533 __m128 res3 = _mm256_extractf128_ps(u3, 0);
3534 __m128 res7 = _mm256_extractf128_ps(u3, 1);
3541 res0 = _mm_add_ps(_mm_loadu_ps(out[0] + 4 * i), res0);
3542 _mm_storeu_ps(out[0] + 4 * i, res0);
3543 res1 = _mm_add_ps(_mm_loadu_ps(out[1] + 4 * i), res1);
3544 _mm_storeu_ps(out[1] + 4 * i, res1);
3545 res2 = _mm_add_ps(_mm_loadu_ps(out[2] + 4 * i), res2);
3546 _mm_storeu_ps(out[2] + 4 * i, res2);
3547 res3 = _mm_add_ps(_mm_loadu_ps(out[3] + 4 * i), res3);
3548 _mm_storeu_ps(out[3] + 4 * i, res3);
3549 res4 = _mm_add_ps(_mm_loadu_ps(out[4] + 4 * i), res4);
3550 _mm_storeu_ps(out[4] + 4 * i, res4);
3551 res5 = _mm_add_ps(_mm_loadu_ps(out[5] + 4 * i), res5);
3552 _mm_storeu_ps(out[5] + 4 * i, res5);
3553 res6 = _mm_add_ps(_mm_loadu_ps(out[6] + 4 * i), res6);
3554 _mm_storeu_ps(out[6] + 4 * i, res6);
3555 res7 = _mm_add_ps(_mm_loadu_ps(out[7] + 4 * i), res7);
3556 _mm_storeu_ps(out[7] + 4 * i, res7);
3560 _mm_storeu_ps(out[0] + 4 * i, res0);
3561 _mm_storeu_ps(out[1] + 4 * i, res1);
3562 _mm_storeu_ps(out[2] + 4 * i, res2);
3563 _mm_storeu_ps(out[3] + 4 * i, res3);
3564 _mm_storeu_ps(out[4] + 4 * i, res4);
3565 _mm_storeu_ps(out[5] + 4 * i, res5);
3566 _mm_storeu_ps(out[6] + 4 * i, res6);
3567 _mm_storeu_ps(out[7] + 4 * i, res7);
3572 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
3573 for (
unsigned int v = 0; v < 8; ++v)
3574 out[v][i] += in[i][v];
3576 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
3577 for (
unsigned int v = 0; v < 8; ++v)
3578 out[v][i] = in[i][v];
3589 const unsigned int n_entries,
3591 const unsigned int *offsets,
3604 out + offsets[7]}});
3612# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512 && defined(__AVX512F__)
3650 template <
typename U>
3662 data = _mm512_set1_pd(x);
3673 operator=(
const double scalar) && =
delete;
3683 return *(
reinterpret_cast<double *
>(&
data) + comp);
3694 return *(
reinterpret_cast<const double *
>(&
data) + comp);
3709# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3724# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3738# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3753# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
3768 load(
const double *ptr)
3770 data = _mm512_loadu_pd(ptr);
3775 load(
const float *ptr)
3777 data = _mm512_cvtps_pd(_mm256_loadu_ps(ptr));
3788 store(
double *ptr)
const
3790 _mm512_storeu_pd(ptr,
data);
3795 store(
float *ptr)
const
3797 _mm256_storeu_ps(ptr, _mm512_cvtpd_ps(
data));
3808 Assert(
reinterpret_cast<std::size_t
>(ptr) % 64 == 0,
3810 _mm512_stream_pd(ptr,
data);
3818 gather(
const double *base_ptr,
const unsigned int *offsets)
3820# ifdef DEAL_II_USE_VECTORIZATION_GATHER
3824 const __m256 index_val =
3825 _mm256_loadu_ps(
reinterpret_cast<const float *
>(offsets));
3826 const __m256i
index = *
reinterpret_cast<const __m256i *
>(&index_val);
3833 const __m256i
equal = _mm256_cmpeq_epi32(invalid, index);
3835 static_cast<__mmask8
>(~(_mm256_movemask_ps(_mm256_castsi256_ps(
equal))));
3837 data = _mm512_mask_i32gather_pd(zero, mask, index, base_ptr, 8);
3840 for (
unsigned int i = 0; i < 8; ++i)
3842 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
3851 scatter(
const unsigned int *offsets,
double *base_ptr)
const
3853# ifdef DEAL_II_USE_VECTORIZATION_GATHER
3854 for (
unsigned int i = 0; i < 8; ++i)
3855 for (
unsigned int j = i + 1; j < 8; ++j)
3857 offsets[i] != offsets[j],
3858 ExcMessage(
"Result of scatter undefined if two offset elements"
3859 " point to the same position"));
3864 const __m256 index_val =
3865 _mm256_loadu_ps(
reinterpret_cast<const float *
>(offsets));
3866 const __m256i
index = *
reinterpret_cast<const __m256i *
>(&index_val);
3868 const __m256i
equal = _mm256_cmpeq_epi32(invalid, index);
3870 static_cast<__mmask8
>(~(_mm256_movemask_ps(_mm256_castsi256_ps(
equal))));
3871 _mm512_mask_i32scatter_pd(base_ptr, mask, index,
data, 8);
3874 for (
unsigned int i = 0; i < 8; ++i)
3876 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
3888 t1.
data = _mm256_add_pd(this->get_lower(), this->get_upper());
3899 res.
data = _mm512_roundscale_pd(
data, _MM_FROUND_TO_NEG_INF);
3918 return _mm512_castpd512_pd256(
data);
3928 return _mm512_extractf64x4_pd(
data, 1);
3957 __m512d
mask = _mm512_set1_pd(-0.);
3959 res.
data =
reinterpret_cast<__m512d
>(
3960 _mm512_andnot_epi64(
reinterpret_cast<__m512i
>(mask),
3961 reinterpret_cast<__m512i
>(
data)));
3992 template <
typename Number2, std::
size_t w
idth2>
3995 template <
typename Number2, std::
size_t w
idth2>
3998 template <
typename Number2, std::
size_t w
idth2>
4002 template <
typename Number2, std::
size_t w
idth2>
4016 const std::array<const double *, 8> &in,
4024 const unsigned int n_chunks = n_entries / 4;
4025 for (
unsigned int i = 0; i < n_chunks; ++i)
4027 __m512d t0, t1, t2, t3 = {};
4029 t0 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[0] + 4 * i), 0);
4030 t0 = _mm512_insertf64x4(t0, _mm256_loadu_pd(in[2] + 4 * i), 1);
4031 t1 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[1] + 4 * i), 0);
4032 t1 = _mm512_insertf64x4(t1, _mm256_loadu_pd(in[3] + 4 * i), 1);
4033 t2 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[4] + 4 * i), 0);
4034 t2 = _mm512_insertf64x4(t2, _mm256_loadu_pd(in[6] + 4 * i), 1);
4035 t3 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[5] + 4 * i), 0);
4036 t3 = _mm512_insertf64x4(t3, _mm256_loadu_pd(in[7] + 4 * i), 1);
4038 __m512d v0 = _mm512_shuffle_f64x2(t0, t2, 0x88);
4039 __m512d v1 = _mm512_shuffle_f64x2(t0, t2, 0xdd);
4040 __m512d v2 = _mm512_shuffle_f64x2(t1, t3, 0x88);
4041 __m512d v3 = _mm512_shuffle_f64x2(t1, t3, 0xdd);
4042 out[4 * i + 0].
data = _mm512_unpacklo_pd(v0, v2);
4043 out[4 * i + 1].
data = _mm512_unpackhi_pd(v0, v2);
4044 out[4 * i + 2].
data = _mm512_unpacklo_pd(v1, v3);
4045 out[4 * i + 3].
data = _mm512_unpackhi_pd(v1, v3);
4049 const unsigned int i = 4 * n_chunks;
4050 const unsigned int remainder = n_entries - i;
4055 __m256i
mask{-1, -1, -1, 0};
4056 __m512d t0, t1, t2, t3 = {};
4058 t0 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[0] + i, mask), 0);
4059 t0 = _mm512_insertf64x4(t0, _mm256_maskload_pd(in[2] + i, mask), 1);
4060 t1 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[1] + i, mask), 0);
4061 t1 = _mm512_insertf64x4(t1, _mm256_maskload_pd(in[3] + i, mask), 1);
4062 t2 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[4] + i, mask), 0);
4063 t2 = _mm512_insertf64x4(t2, _mm256_maskload_pd(in[6] + i, mask), 1);
4064 t3 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[5] + i, mask), 0);
4065 t3 = _mm512_insertf64x4(t3, _mm256_maskload_pd(in[7] + i, mask), 1);
4067 __m512d v0 = _mm512_shuffle_f64x2(t0, t2, 0x88);
4068 __m512d v1 = _mm512_shuffle_f64x2(t0, t2, 0xdd);
4069 __m512d v2 = _mm512_shuffle_f64x2(t1, t3, 0x88);
4070 __m512d v3 = _mm512_shuffle_f64x2(t1, t3, 0xdd);
4071 out[i + 0].
data = _mm512_unpacklo_pd(v0, v2);
4072 out[i + 1].
data = _mm512_unpackhi_pd(v0, v2);
4073 out[i + 2].
data = _mm512_unpacklo_pd(v1, v3);
4075 else if (remainder == 2)
4078 __m256d t0, t1, t2, t3 = {};
4079 t0 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[0] + i), 0);
4080 t0 = _mm256_insertf128_pd(t0, _mm_loadu_pd(in[2] + i), 1);
4081 t1 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[1] + i), 0);
4082 t1 = _mm256_insertf128_pd(t1, _mm_loadu_pd(in[3] + i), 1);
4083 t2 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[4] + i), 0);
4084 t2 = _mm256_insertf128_pd(t2, _mm_loadu_pd(in[6] + i), 1);
4085 t3 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[5] + i), 0);
4086 t3 = _mm256_insertf128_pd(t3, _mm_loadu_pd(in[7] + i), 1);
4088 __m512d v0, v1 = {};
4089 v0 = _mm512_insertf64x4(v1, t0, 0);
4090 v0 = _mm512_insertf64x4(v0, t2, 1);
4091 v1 = _mm512_insertf64x4(v1, t1, 0);
4092 v1 = _mm512_insertf64x4(v1, t3, 1);
4093 out[i + 0].
data = _mm512_unpacklo_pd(v0, v1);
4094 out[i + 1].
data = _mm512_unpackhi_pd(v0, v1);
4096 else if (remainder == 1)
4097 for (
unsigned int v = 0; v < 8; ++v)
4098 out[i][v] = in[v][i];
4110 const unsigned int *offsets,
4133 const unsigned int n_entries,
4135 const std::array<double *, 8> &out)
4139 const unsigned int n_chunks = n_entries / 4;
4140 __m512i mask1 = _mm512_set_epi64(0xd, 0xc, 0x5, 0x4, 0x9, 0x8, 0x1, 0x0);
4141 __m512i mask2 = _mm512_set_epi64(0xf, 0xe, 0x7, 0x6, 0xb, 0xa, 0x3, 0x2);
4142 for (
unsigned int i = 0; i < n_chunks; ++i)
4144 __m512d t0 = _mm512_unpacklo_pd(in[i * 4].data, in[i * 4 + 1].data);
4145 __m512d t1 = _mm512_unpackhi_pd(in[i * 4].data, in[i * 4 + 1].data);
4146 __m512d t2 = _mm512_unpacklo_pd(in[i * 4 + 2].data, in[i * 4 + 3].data);
4147 __m512d t3 = _mm512_unpackhi_pd(in[i * 4 + 2].data, in[i * 4 + 3].data);
4148 __m512d v0 = _mm512_permutex2var_pd(t0, mask1, t2);
4149 __m512d v1 = _mm512_permutex2var_pd(t0, mask2, t2);
4150 __m512d v2 = _mm512_permutex2var_pd(t1, mask1, t3);
4151 __m512d v3 = _mm512_permutex2var_pd(t1, mask2, t3);
4152 __m256d res0 = _mm512_extractf64x4_pd(v0, 0);
4153 __m256d res4 = _mm512_extractf64x4_pd(v0, 1);
4154 __m256d res1 = _mm512_extractf64x4_pd(v2, 0);
4155 __m256d res5 = _mm512_extractf64x4_pd(v2, 1);
4156 __m256d res2 = _mm512_extractf64x4_pd(v1, 0);
4157 __m256d res6 = _mm512_extractf64x4_pd(v1, 1);
4158 __m256d res3 = _mm512_extractf64x4_pd(v3, 0);
4159 __m256d res7 = _mm512_extractf64x4_pd(v3, 1);
4166 res0 = _mm256_add_pd(_mm256_loadu_pd(out[0] + 4 * i), res0);
4167 _mm256_storeu_pd(out[0] + 4 * i, res0);
4168 res1 = _mm256_add_pd(_mm256_loadu_pd(out[1] + 4 * i), res1);
4169 _mm256_storeu_pd(out[1] + 4 * i, res1);
4170 res2 = _mm256_add_pd(_mm256_loadu_pd(out[2] + 4 * i), res2);
4171 _mm256_storeu_pd(out[2] + 4 * i, res2);
4172 res3 = _mm256_add_pd(_mm256_loadu_pd(out[3] + 4 * i), res3);
4173 _mm256_storeu_pd(out[3] + 4 * i, res3);
4174 res4 = _mm256_add_pd(_mm256_loadu_pd(out[4] + 4 * i), res4);
4175 _mm256_storeu_pd(out[4] + 4 * i, res4);
4176 res5 = _mm256_add_pd(_mm256_loadu_pd(out[5] + 4 * i), res5);
4177 _mm256_storeu_pd(out[5] + 4 * i, res5);
4178 res6 = _mm256_add_pd(_mm256_loadu_pd(out[6] + 4 * i), res6);
4179 _mm256_storeu_pd(out[6] + 4 * i, res6);
4180 res7 = _mm256_add_pd(_mm256_loadu_pd(out[7] + 4 * i), res7);
4181 _mm256_storeu_pd(out[7] + 4 * i, res7);
4185 _mm256_storeu_pd(out[0] + 4 * i, res0);
4186 _mm256_storeu_pd(out[1] + 4 * i, res1);
4187 _mm256_storeu_pd(out[2] + 4 * i, res2);
4188 _mm256_storeu_pd(out[3] + 4 * i, res3);
4189 _mm256_storeu_pd(out[4] + 4 * i, res4);
4190 _mm256_storeu_pd(out[5] + 4 * i, res5);
4191 _mm256_storeu_pd(out[6] + 4 * i, res6);
4192 _mm256_storeu_pd(out[7] + 4 * i, res7);
4197 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
4198 for (
unsigned int v = 0; v < 8; ++v)
4199 out[v][i] += in[i][v];
4201 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
4202 for (
unsigned int v = 0; v < 8; ++v)
4203 out[v][i] = in[i][v];
4214 const unsigned int n_entries,
4216 const unsigned int *offsets,
4229 out + offsets[7]}});
4270 template <
typename U>
4282 data = _mm512_set1_ps(x);
4292 operator=(
const float scalar) && =
delete;
4302 return *(
reinterpret_cast<float *
>(&
data) + comp);
4313 return *(
reinterpret_cast<const float *
>(&
data) + comp);
4328# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
4343# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
4357# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
4372# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
4387 load(
const float *ptr)
4389 data = _mm512_loadu_ps(ptr);
4400 store(
float *ptr)
const
4402 _mm512_storeu_ps(ptr,
data);
4413 Assert(
reinterpret_cast<std::size_t
>(ptr) % 64 == 0,
4415 _mm512_stream_ps(ptr,
data);
4423 gather(
const float *base_ptr,
const unsigned int *offsets)
4425# ifdef DEAL_II_USE_VECTORIZATION_GATHER
4429 const __m512 index_val =
4430 _mm512_loadu_ps(
reinterpret_cast<const float *
>(offsets));
4431 const __m512i
index = *
reinterpret_cast<const __m512i *
>(&index_val);
4438 __mmask16
mask = _mm512_cmpneq_epu32_mask(invalid, index);
4440 data = _mm512_mask_i32gather_ps(zero, mask, index, base_ptr, 4);
4443 for (
unsigned int i = 0; i < 16; ++i)
4445 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
4454 scatter(
const unsigned int *offsets,
float *base_ptr)
const
4456# ifdef DEAL_II_USE_VECTORIZATION_GATHER
4457 for (
unsigned int i = 0; i < 16; ++i)
4458 for (
unsigned int j = i + 1; j < 16; ++j)
4460 offsets[i] != offsets[j],
4461 ExcMessage(
"Result of scatter undefined if two offset elements"
4462 " point to the same position"));
4467 const __m512 index_val =
4468 _mm512_loadu_ps(
reinterpret_cast<const float *
>(offsets));
4469 const __m512i
index = *
reinterpret_cast<const __m512i *
>(&index_val);
4471 __mmask16
mask = _mm512_cmpneq_epu32_mask(invalid, index);
4472 _mm512_mask_i32scatter_ps(base_ptr, mask, index,
data, 4);
4474 for (
unsigned int i = 0; i < 16; ++i)
4476 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
4488 t1.
data = _mm256_add_ps(this->get_lower(), this->get_upper());
4500 res.
data = _mm512_roundscale_ps(
data, _MM_FROUND_TO_NEG_INF);
4519 return _mm512_castps512_ps256(
data);
4529 return _mm256_castpd_ps(_mm512_extractf64x4_pd(_mm512_castps_pd(
data), 1));
4558 __m512
mask = _mm512_set1_ps(-0.f);
4560 res.
data =
reinterpret_cast<__m512
>(
4561 _mm512_andnot_epi32(
reinterpret_cast<__m512i
>(mask),
4562 reinterpret_cast<__m512i
>(
data)));
4593 template <
typename Number2, std::
size_t w
idth2>
4596 template <
typename Number2, std::
size_t w
idth2>
4599 template <
typename Number2, std::
size_t w
idth2>
4603 template <
typename Number2, std::
size_t w
idth2>
4617 const std::array<const float *, 16> &in,
4624 const unsigned int n_chunks = n_entries / 4;
4626 for (
unsigned int i = 0; i < n_chunks; ++i)
4628 __m512 t0, t1, t2, t3 = {};
4630 t0 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[0] + 4 * i), 0);
4631 t0 = _mm512_insertf32x4(t0, _mm_loadu_ps(in[4] + 4 * i), 1);
4632 t0 = _mm512_insertf32x4(t0, _mm_loadu_ps(in[8] + 4 * i), 2);
4633 t0 = _mm512_insertf32x4(t0, _mm_loadu_ps(in[12] + 4 * i), 3);
4634 t1 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[1] + 4 * i), 0);
4635 t1 = _mm512_insertf32x4(t1, _mm_loadu_ps(in[5] + 4 * i), 1);
4636 t1 = _mm512_insertf32x4(t1, _mm_loadu_ps(in[9] + 4 * i), 2);
4637 t1 = _mm512_insertf32x4(t1, _mm_loadu_ps(in[13] + 4 * i), 3);
4638 t2 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[2] + 4 * i), 0);
4639 t2 = _mm512_insertf32x4(t2, _mm_loadu_ps(in[6] + 4 * i), 1);
4640 t2 = _mm512_insertf32x4(t2, _mm_loadu_ps(in[10] + 4 * i), 2);
4641 t2 = _mm512_insertf32x4(t2, _mm_loadu_ps(in[14] + 4 * i), 3);
4642 t3 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[3] + 4 * i), 0);
4643 t3 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[7] + 4 * i), 1);
4644 t3 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[11] + 4 * i), 2);
4645 t3 = _mm512_insertf32x4(t3, _mm_loadu_ps(in[15] + 4 * i), 3);
4647 __m512 v0 = _mm512_shuffle_ps(t0, t1, 0x44);
4648 __m512 v1 = _mm512_shuffle_ps(t0, t1, 0xee);
4649 __m512 v2 = _mm512_shuffle_ps(t2, t3, 0x44);
4650 __m512 v3 = _mm512_shuffle_ps(t2, t3, 0xee);
4652 out[4 * i + 0].
data = _mm512_shuffle_ps(v0, v2, 0x88);
4653 out[4 * i + 1].
data = _mm512_shuffle_ps(v0, v2, 0xdd);
4654 out[4 * i + 2].
data = _mm512_shuffle_ps(v1, v3, 0x88);
4655 out[4 * i + 3].
data = _mm512_shuffle_ps(v1, v3, 0xdd);
4659 const unsigned int i = 4 * n_chunks;
4660 const unsigned int remainder = n_entries - i;
4663 __m512 t0, t1, t2, t3 = {};
4667 __m128i
mask = _mm_setr_epi32(-1, -1, -1, 0);
4668 t0 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[0] + i, mask), 0);
4669 t0 = _mm512_insertf32x4(t0, _mm_maskload_ps(in[4] + i, mask), 1);
4670 t0 = _mm512_insertf32x4(t0, _mm_maskload_ps(in[8] + i, mask), 2);
4671 t0 = _mm512_insertf32x4(t0, _mm_maskload_ps(in[12] + i, mask), 3);
4672 t1 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[1] + i, mask), 0);
4673 t1 = _mm512_insertf32x4(t1, _mm_maskload_ps(in[5] + i, mask), 1);
4674 t1 = _mm512_insertf32x4(t1, _mm_maskload_ps(in[9] + i, mask), 2);
4675 t1 = _mm512_insertf32x4(t1, _mm_maskload_ps(in[13] + i, mask), 3);
4676 t2 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[2] + i, mask), 0);
4677 t2 = _mm512_insertf32x4(t2, _mm_maskload_ps(in[6] + i, mask), 1);
4678 t2 = _mm512_insertf32x4(t2, _mm_maskload_ps(in[10] + i, mask), 2);
4679 t2 = _mm512_insertf32x4(t2, _mm_maskload_ps(in[14] + i, mask), 3);
4680 t3 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[3] + i, mask), 0);
4681 t3 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[7] + i, mask), 1);
4682 t3 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[11] + i, mask), 2);
4683 t3 = _mm512_insertf32x4(t3, _mm_maskload_ps(in[15] + i, mask), 3);
4684 __m512 v0 = _mm512_shuffle_ps(t0, t1, 0x44);
4685 __m512 v1 = _mm512_shuffle_ps(t0, t1, 0xee);
4686 __m512 v2 = _mm512_shuffle_ps(t2, t3, 0x44);
4687 __m512 v3 = _mm512_shuffle_ps(t2, t3, 0xee);
4688 out[i + 0].
data = _mm512_shuffle_ps(v0, v2, 0x88);
4689 out[i + 1].
data = _mm512_shuffle_ps(v0, v2, 0xdd);
4690 out[i + 2].
data = _mm512_shuffle_ps(v1, v3, 0x88);
4692 else if (remainder == 2)
4698 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[0] + i));
4699 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[1] + i));
4701 _mm512_insertf32x4(v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 0);
4702 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[4] + i));
4703 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[5] + i));
4705 _mm512_insertf32x4(v0, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 1);
4706 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[8] + i));
4707 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[9] + i));
4709 _mm512_insertf32x4(v0, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 2);
4710 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[12] + i));
4711 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[13] + i));
4713 _mm512_insertf32x4(v0, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 3);
4714 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[2] + i));
4715 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[3] + i));
4717 _mm512_insertf32x4(v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 0);
4718 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[6] + i));
4719 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[7] + i));
4721 _mm512_insertf32x4(v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 1);
4722 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[10] + i));
4723 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[11] + i));
4725 _mm512_insertf32x4(v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 2);
4726 t0 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[14] + i));
4727 t1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(in[15] + i));
4729 _mm512_insertf32x4(v1, _mm_castsi128_ps(_mm_unpacklo_epi64(t0, t1)), 3);
4730 out[i + 0].
data = _mm512_shuffle_ps(v0, v1, 0x88);
4731 out[i + 1].
data = _mm512_shuffle_ps(v0, v1, 0xdd);
4733 else if (remainder == 1)
4734 for (
unsigned int v = 0; v < 16; ++v)
4735 out[i][v] = in[v][i];
4747 const unsigned int *offsets,
4778 const unsigned int n_entries,
4780 const std::array<float *, 16> &out)
4782 const unsigned int n_chunks = n_entries / 4;
4783 for (
unsigned int i = 0; i < n_chunks; ++i)
4785 __m512 t0 = _mm512_shuffle_ps(in[4 * i].data, in[1 + 4 * i].data, 0x44);
4786 __m512 t1 = _mm512_shuffle_ps(in[4 * i].data, in[1 + 4 * i].data, 0xee);
4788 _mm512_shuffle_ps(in[2 + 4 * i].data, in[3 + 4 * i].data, 0x44);
4790 _mm512_shuffle_ps(in[2 + 4 * i].data, in[3 + 4 * i].data, 0xee);
4791 __m512 u0 = _mm512_shuffle_ps(t0, t2, 0x88);
4792 __m512 u1 = _mm512_shuffle_ps(t0, t2, 0xdd);
4793 __m512 u2 = _mm512_shuffle_ps(t1, t3, 0x88);
4794 __m512 u3 = _mm512_shuffle_ps(t1, t3, 0xdd);
4796 __m128 res0 = _mm512_extractf32x4_ps(u0, 0);
4797 __m128 res4 = _mm512_extractf32x4_ps(u0, 1);
4798 __m128 res8 = _mm512_extractf32x4_ps(u0, 2);
4799 __m128 res12 = _mm512_extractf32x4_ps(u0, 3);
4800 __m128 res1 = _mm512_extractf32x4_ps(u1, 0);
4801 __m128 res5 = _mm512_extractf32x4_ps(u1, 1);
4802 __m128 res9 = _mm512_extractf32x4_ps(u1, 2);
4803 __m128 res13 = _mm512_extractf32x4_ps(u1, 3);
4804 __m128 res2 = _mm512_extractf32x4_ps(u2, 0);
4805 __m128 res6 = _mm512_extractf32x4_ps(u2, 1);
4806 __m128 res10 = _mm512_extractf32x4_ps(u2, 2);
4807 __m128 res14 = _mm512_extractf32x4_ps(u2, 3);
4808 __m128 res3 = _mm512_extractf32x4_ps(u3, 0);
4809 __m128 res7 = _mm512_extractf32x4_ps(u3, 1);
4810 __m128 res11 = _mm512_extractf32x4_ps(u3, 2);
4811 __m128 res15 = _mm512_extractf32x4_ps(u3, 3);
4818 res0 = _mm_add_ps(_mm_loadu_ps(out[0] + 4 * i), res0);
4819 _mm_storeu_ps(out[0] + 4 * i, res0);
4820 res1 = _mm_add_ps(_mm_loadu_ps(out[1] + 4 * i), res1);
4821 _mm_storeu_ps(out[1] + 4 * i, res1);
4822 res2 = _mm_add_ps(_mm_loadu_ps(out[2] + 4 * i), res2);
4823 _mm_storeu_ps(out[2] + 4 * i, res2);
4824 res3 = _mm_add_ps(_mm_loadu_ps(out[3] + 4 * i), res3);
4825 _mm_storeu_ps(out[3] + 4 * i, res3);
4826 res4 = _mm_add_ps(_mm_loadu_ps(out[4] + 4 * i), res4);
4827 _mm_storeu_ps(out[4] + 4 * i, res4);
4828 res5 = _mm_add_ps(_mm_loadu_ps(out[5] + 4 * i), res5);
4829 _mm_storeu_ps(out[5] + 4 * i, res5);
4830 res6 = _mm_add_ps(_mm_loadu_ps(out[6] + 4 * i), res6);
4831 _mm_storeu_ps(out[6] + 4 * i, res6);
4832 res7 = _mm_add_ps(_mm_loadu_ps(out[7] + 4 * i), res7);
4833 _mm_storeu_ps(out[7] + 4 * i, res7);
4834 res8 = _mm_add_ps(_mm_loadu_ps(out[8] + 4 * i), res8);
4835 _mm_storeu_ps(out[8] + 4 * i, res8);
4836 res9 = _mm_add_ps(_mm_loadu_ps(out[9] + 4 * i), res9);
4837 _mm_storeu_ps(out[9] + 4 * i, res9);
4838 res10 = _mm_add_ps(_mm_loadu_ps(out[10] + 4 * i), res10);
4839 _mm_storeu_ps(out[10] + 4 * i, res10);
4840 res11 = _mm_add_ps(_mm_loadu_ps(out[11] + 4 * i), res11);
4841 _mm_storeu_ps(out[11] + 4 * i, res11);
4842 res12 = _mm_add_ps(_mm_loadu_ps(out[12] + 4 * i), res12);
4843 _mm_storeu_ps(out[12] + 4 * i, res12);
4844 res13 = _mm_add_ps(_mm_loadu_ps(out[13] + 4 * i), res13);
4845 _mm_storeu_ps(out[13] + 4 * i, res13);
4846 res14 = _mm_add_ps(_mm_loadu_ps(out[14] + 4 * i), res14);
4847 _mm_storeu_ps(out[14] + 4 * i, res14);
4848 res15 = _mm_add_ps(_mm_loadu_ps(out[15] + 4 * i), res15);
4849 _mm_storeu_ps(out[15] + 4 * i, res15);
4853 _mm_storeu_ps(out[0] + 4 * i, res0);
4854 _mm_storeu_ps(out[1] + 4 * i, res1);
4855 _mm_storeu_ps(out[2] + 4 * i, res2);
4856 _mm_storeu_ps(out[3] + 4 * i, res3);
4857 _mm_storeu_ps(out[4] + 4 * i, res4);
4858 _mm_storeu_ps(out[5] + 4 * i, res5);
4859 _mm_storeu_ps(out[6] + 4 * i, res6);
4860 _mm_storeu_ps(out[7] + 4 * i, res7);
4861 _mm_storeu_ps(out[8] + 4 * i, res8);
4862 _mm_storeu_ps(out[9] + 4 * i, res9);
4863 _mm_storeu_ps(out[10] + 4 * i, res10);
4864 _mm_storeu_ps(out[11] + 4 * i, res11);
4865 _mm_storeu_ps(out[12] + 4 * i, res12);
4866 _mm_storeu_ps(out[13] + 4 * i, res13);
4867 _mm_storeu_ps(out[14] + 4 * i, res14);
4868 _mm_storeu_ps(out[15] + 4 * i, res15);
4873 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
4874 for (
unsigned int v = 0; v < 16; ++v)
4875 out[v][i] += in[i][v];
4877 for (
unsigned int i = 4 * n_chunks; i < n_entries; ++i)
4878 for (
unsigned int v = 0; v < 16; ++v)
4879 out[v][i] = in[i][v];
4890 const unsigned int n_entries,
4892 const unsigned int *offsets,
4913 out + offsets[15]}});
4918# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ALTIVEC__) && \
4954 template <
typename U>
4966 data = vec_splats(x);
4981 operator=(
const double scalar) && =
delete;
4991 return *(
reinterpret_cast<double *
>(&
data) + comp);
5002 return *(
reinterpret_cast<const double *
>(&
data) + comp);
5055 load(
const double *ptr)
5057 data = vec_vsx_ld(0, ptr);
5066 store(
double *ptr)
const
5068 vec_vsx_st(
data, 0, ptr);
5086 gather(
const double *base_ptr,
const unsigned int *offsets)
5089 for (
unsigned int i = 0; i < 2; ++i)
5091 *(
reinterpret_cast<double *
>(&
data) + i) = base_ptr[offsets[i]];
5099 scatter(
const unsigned int *offsets,
double *base_ptr)
const
5101 for (
unsigned int i = 0; i < 2; ++i)
5103 base_ptr[offsets[i]] = *(
reinterpret_cast<const double *
>(&
data) + i);
5111 __vector
double data;
5167 template <
typename Number2, std::
size_t w
idth2>
5170 template <
typename Number2, std::
size_t w
idth2>
5173 template <
typename Number2, std::
size_t w
idth2>
5177 template <
typename Number2, std::
size_t w
idth2>
5218 template <
typename U>
5230 data = vec_splats(x);
5245 operator=(
const float scalar) && =
delete;
5255 return *(
reinterpret_cast<float *
>(&
data) + comp);
5266 return *(
reinterpret_cast<const float *
>(&
data) + comp);
5319 load(
const float *ptr)
5321 data = vec_vsx_ld(0, ptr);
5330 store(
float *ptr)
const
5332 vec_vsx_st(
data, 0, ptr);
5350 gather(
const float *base_ptr,
const unsigned int *offsets)
5353 for (
unsigned int i = 0; i < 4; ++i)
5355 *(
reinterpret_cast<float *
>(&
data) + i) = base_ptr[offsets[i]];
5363 scatter(
const unsigned int *offsets,
float *base_ptr)
const
5365 for (
unsigned int i = 0; i < 4; ++i)
5367 base_ptr[offsets[i]] = *(
reinterpret_cast<const float *
>(&
data) + i);
5375 __vector
float data;
5431 template <
typename Number2, std::
size_t w
idth2>
5434 template <
typename Number2, std::
size_t w
idth2>
5437 template <
typename Number2, std::
size_t w
idth2>
5441 template <
typename Number2, std::
size_t w
idth2>
5465template <
typename Number, std::
size_t w
idth>
5470 for (
unsigned int i = 0; i < VectorizedArray<Number, width>::size(); ++i)
5471 if (lhs[i] != rhs[i])
5483template <
typename Number, std::
size_t w
idth>
5497template <
typename Number, std::
size_t w
idth>
5511template <
typename Number, std::
size_t w
idth>
5525template <
typename Number, std::
size_t w
idth>
5540template <
typename Number, std::
size_t w
idth>
5556template <std::
size_t w
idth>
5570template <
typename Number, std::
size_t w
idth>
5585template <std::
size_t w
idth>
5598template <
typename Number, std::
size_t w
idth>
5614template <std::
size_t w
idth>
5628template <
typename Number, std::
size_t w
idth>
5644template <std::
size_t w
idth>
5658template <
typename Number, std::
size_t w
idth>
5674template <std::
size_t w
idth>
5688template <
typename Number, std::
size_t w
idth>
5703template <std::
size_t w
idth>
5716template <
typename Number, std::
size_t w
idth>
5732template <std::
size_t w
idth>
5746template <
typename Number, std::
size_t w
idth>
5762template <std::
size_t w
idth>
5775template <
typename Number, std::
size_t w
idth>
5787template <
typename Number, std::
size_t w
idth>
5801template <
typename Number, std::
size_t w
idth>
5802inline std::ostream &
5806 for (
unsigned int i = 0; i < n - 1; ++i)
5829#if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
5910template <SIMDComparison predicate,
typename Number>
5913 const Number &right,
5914 const Number &true_value,
5915 const Number &false_value)
5921 mask = (left == right);
5924 mask = (left != right);
5927 mask = (left < right);
5930 mask = (left <= right);
5933 mask = (left > right);
5936 mask = (left >= right);
5940 return mask ? true_value : false_value;
5948template <SIMDComparison predicate,
typename Number>
5966# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 512 && defined(__AVX512F__)
5968template <SIMDComparison predicate>
5975 const __mmask16
mask =
5976 _mm512_cmp_ps_mask(left.
data, right.
data,
static_cast<int>(predicate));
5978 result.
data = _mm512_mask_mov_ps(false_values.
data, mask, true_values.
data);
5984template <SIMDComparison predicate>
5991 const __mmask16
mask =
5992 _mm512_cmp_pd_mask(left.
data, right.
data,
static_cast<int>(predicate));
5994 result.
data = _mm512_mask_mov_pd(false_values.
data, mask, true_values.
data);
6000# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 256 && defined(__AVX__)
6002template <SIMDComparison predicate>
6010 _mm256_cmp_ps(left.
data, right.
data,
static_cast<int>(predicate));
6013 result.
data = _mm256_blendv_ps(false_values.
data, true_values.
data, mask);
6018template <SIMDComparison predicate>
6026 _mm256_cmp_pd(left.
data, right.
data,
static_cast<int>(predicate));
6029 result.
data = _mm256_blendv_pd(false_values.
data, true_values.
data, mask);
6035# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__SSE2__)
6037template <SIMDComparison predicate>
6068 result.
data = _mm_or_ps(_mm_and_ps(mask, true_values.
data),
6069 _mm_andnot_ps(mask, false_values.
data));
6075template <SIMDComparison predicate>
6106 result.
data = _mm_or_pd(_mm_and_pd(mask, true_values.
data),
6107 _mm_andnot_pd(mask, false_values.
data));
6114# if DEAL_II_VECTORIZATION_WIDTH_IN_BITS >= 128 && defined(__ARM_NEON)
6116template <SIMDComparison predicate>
6147 result.
data = vreinterpretq_f32_u32(vorrq_u32(
6148 vandq_u32(mask, vreinterpretq_u32_f32(true_values.
data)),
6149 vandq_u32(vmvnq_u32(mask), vreinterpretq_u32_f32(false_values.
data))));
6155template <SIMDComparison predicate>
6169 mask = vreinterpretq_u64_u32(
6170 vmvnq_u32(vreinterpretq_u32_u64(vceqq_f64(left.
data, right.
data))));
6187 result.
data = vreinterpretq_f64_u64(vorrq_u64(
6188 vandq_u64(mask, vreinterpretq_u64_f64(true_values.
data)),
6189 vandq_u64(vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(mask))),
6190 vreinterpretq_u64_f64(false_values.
data))));
6201 template <
typename T>
6212 static constexpr std::size_t
6229 static constexpr std::size_t
6250 static const value_type &
6274 static const value_type &
6283 template <
typename T, std::
size_t w
idth_>
6294 static constexpr std::size_t
6312 static constexpr std::size_t
6332 static const value_type &
6343 static vectorized_value_type &
6356 static const vectorized_value_type &
6385 template <
typename Number, std::
size_t w
idth>
6386 inline ::VectorizedArray<Number, width>
6387 sin(const ::VectorizedArray<Number, width> &x)
6390 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6405 template <
typename Number, std::
size_t w
idth>
6406 inline ::VectorizedArray<Number, width>
6407 cos(const ::VectorizedArray<Number, width> &x)
6410 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6425 template <
typename Number, std::
size_t w
idth>
6426 inline ::VectorizedArray<Number, width>
6427 tan(const ::VectorizedArray<Number, width> &x)
6430 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6445 template <
typename Number, std::
size_t w
idth>
6446 inline ::VectorizedArray<Number, width>
6447 acos(const ::VectorizedArray<Number, width> &x)
6450 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6465 template <
typename Number, std::
size_t w
idth>
6466 inline ::VectorizedArray<Number, width>
6467 asin(const ::VectorizedArray<Number, width> &x)
6470 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6485 template <
typename Number, std::
size_t w
idth>
6486 inline ::VectorizedArray<Number, width>
6487 atan(const ::VectorizedArray<Number, width> &x)
6490 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6505 template <
typename Number, std::
size_t w
idth>
6506 inline ::VectorizedArray<Number, width>
6507 cosh(const ::VectorizedArray<Number, width> &x)
6510 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6525 template <
typename Number, std::
size_t w
idth>
6526 inline ::VectorizedArray<Number, width>
6527 sinh(const ::VectorizedArray<Number, width> &x)
6530 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6545 template <
typename Number, std::
size_t w
idth>
6546 inline ::VectorizedArray<Number, width>
6547 tanh(const ::VectorizedArray<Number, width> &x)
6550 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6565 template <
typename Number, std::
size_t w
idth>
6566 inline ::VectorizedArray<Number, width>
6567 acosh(const ::VectorizedArray<Number, width> &x)
6570 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6585 template <
typename Number, std::
size_t w
idth>
6586 inline ::VectorizedArray<Number, width>
6587 asinh(const ::VectorizedArray<Number, width> &x)
6590 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6605 template <
typename Number, std::
size_t w
idth>
6606 inline ::VectorizedArray<Number, width>
6607 atanh(const ::VectorizedArray<Number, width> &x)
6610 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6625 template <
typename Number, std::
size_t w
idth>
6626 inline ::VectorizedArray<Number, width>
6627 exp(const ::VectorizedArray<Number, width> &x)
6630 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6645 template <
typename Number, std::
size_t w
idth>
6646 inline ::VectorizedArray<Number, width>
6647 log(const ::VectorizedArray<Number, width> &x)
6650 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6665 template <
typename Number, std::
size_t w
idth>
6666 inline ::VectorizedArray<Number, width>
6667 sqrt(const ::VectorizedArray<Number, width> &x)
6669 return x.get_sqrt();
6681 template <
typename Number, std::
size_t w
idth>
6682 inline ::VectorizedArray<Number, width>
6683 pow(const ::VectorizedArray<Number, width> &x,
const Number p)
6686 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6702 template <
typename Number, std::
size_t w
idth>
6703 inline ::VectorizedArray<Number, width>
6704 pow(const ::VectorizedArray<Number, width> &x,
6705 const ::VectorizedArray<Number, width> &p)
6708 for (
unsigned int i = 0; i < ::VectorizedArray<Number, width>::size();
6723 template <
typename Number, std::
size_t w
idth>
6724 inline ::VectorizedArray<Number, width>
6725 abs(const ::VectorizedArray<Number, width> &x)
6739 template <
typename Number, std::
size_t w
idth>
6740 inline ::VectorizedArray<Number, width>
6741 max(const ::VectorizedArray<Number, width> &x,
6742 const ::VectorizedArray<Number, width> &y)
6744 return x.get_max(y);
6756 template <
typename Number, std::
size_t w
idth>
6757 inline ::VectorizedArray<Number, width>
6758 min(const ::VectorizedArray<Number, width> &x,
6759 const ::VectorizedArray<Number, width> &y)
6761 return x.get_min(y);
6772#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 > sinh(const::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > operator/(const VectorizedArray< Number, width > &v, const Number &u)
VectorizedArray< Number, width > acos(const::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > cos(const::VectorizedArray< Number, width > &x)
VectorizedArray get_abs() const
VectorizedArray< float, width > operator/(const VectorizedArray< float, width > &v, const double u)
VectorizedArray< Number, width > exp(const::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > operator*(const VectorizedArray< Number, width > &v, const Number &u)
VectorizedArray< Number, width > operator-(const VectorizedArray< Number, width > &v, const Number &u)
Number & operator[](const unsigned int comp)
VectorizedArray get_floor() const
VectorizedArray< Number, width > asinh(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 > operator+(const VectorizedArray< Number, width > &u)
VectorizedArray< Number, width > atanh(const::VectorizedArray< Number, width > &x)
VectorizedArray()=default
bool operator==(const VectorizedArray< Number, width > &lhs, const VectorizedArray< Number, width > &rhs)
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
const Number & operator[](const unsigned int comp) const
VectorizedArray< Number, width > pow(const::VectorizedArray< Number, width > &x, const::VectorizedArray< Number, width > &p)
VectorizedArray< Number, width > log(const::VectorizedArray< Number, width > &x)
VectorizedArray get_min(const VectorizedArray &other) const
VectorizedArray< Number, width > cosh(const::VectorizedArray< Number, width > &x)
void store(OtherNumber *ptr) const
VectorizedArray< float, width > operator-(const VectorizedArray< float, width > &v, const double u)
VectorizedArray< Number, width > min(const::VectorizedArray< Number, width > &x, const::VectorizedArray< Number, width > &y)
void load(const OtherNumber *ptr)
void scatter(const unsigned int *offsets, Number *base_ptr) const
VectorizedArray< Number, width > operator-(const Number &u, const VectorizedArray< Number, width > &v)
VectorizedArray< Number, width > sin(const::VectorizedArray< Number, width > &x)
VectorizedArray & operator=(const Number scalar) &&=delete
VectorizedArray< Number, width > pow(const::VectorizedArray< Number, width > &x, const Number p)
VectorizedArray< Number, width > atan(const::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > operator*(const VectorizedArray< Number, width > &u, const VectorizedArray< Number, width > &v)
VectorizedArray & operator-=(const VectorizedArray &vec)
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 get_sqrt() const
VectorizedArray< Number, width > operator/(const Number &u, const VectorizedArray< Number, width > &v)
VectorizedArray< Number, width > abs(const::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > tan(const::VectorizedArray< Number, width > &x)
VectorizedArray & operator+=(const VectorizedArray &vec)
VectorizedArray< Number, width > acosh(const::VectorizedArray< Number, width > &x)
VectorizedArray< Number, width > sqrt(const::VectorizedArray< Number, width > &x)
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 > max(const::VectorizedArray< Number, width > &x, const::VectorizedArray< Number, width > &y)
VectorizedArray< Number, width > asin(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< Number, width > tanh(const::VectorizedArray< Number, width > &x)
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)
const bool IsBlockVector< VectorType >::value
constexpr types::blas_int zero
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)
VectorizedArray< typename EnableIfScalar< Number >::type, width > type
VectorizedArray< T, width_ > vectorized_value_type
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)
static constexpr unsigned int max_width
typename T::value_type value_type
std::ptrdiff_t difference_type
contiguous_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)