+/**
+ * @name Packing and unpacking of a VectorizedArray
+ */
+//@{
+
+
/**
* Create a vectorized array that sets all entries in the array to the given
* scalar, i.e., broadcasts the scalar to all array elements.
}
+//@}
+
+#ifndef DOXYGEN
+
// for safety, also check that __AVX512F__ is defined in case the user manually
// set some conflicting compile flags which prevent compilation
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 3 && defined(__AVX512F__)
+# if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 3 && defined(__AVX512F__)
/**
* Specialization of VectorizedArray class for double and AVX-512.
// additions with multiplication (fused multiply-add) if those
// instructions are available. Otherwise, we need to use the built-in
// intrinsic command for __m512d
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data += vec.data;
-# else
+# else
data = _mm512_add_pd(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator-=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data -= vec.data;
-# else
+# else
data = _mm512_sub_pd(data, vec.data);
-# endif
+# endif
return *this;
}
/**
VectorizedArray &
operator*=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data *= vec.data;
-# else
+# else
data = _mm512_mul_pd(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator/=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data /= vec.data;
-# else
+# else
data = _mm512_div_pd(data, vec.data);
-# endif
+# endif
return *this;
}
// additions with multiplication (fused multiply-add) if those
// instructions are available. Otherwise, we need to use the built-in
// intrinsic command for __m512d
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data += vec.data;
-# else
+# else
data = _mm512_add_ps(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator-=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data -= vec.data;
-# else
+# else
data = _mm512_sub_ps(data, vec.data);
-# endif
+# endif
return *this;
}
/**
VectorizedArray &
operator*=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data *= vec.data;
-# else
+# else
data = _mm512_mul_ps(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator/=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data /= vec.data;
-# else
+# else
data = _mm512_div_ps(data, vec.data);
-# endif
+# endif
return *this;
}
out[offsets[v] + i] = in[i][v];
}
-#endif
+# endif
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 2 && defined(__AVX__)
+# if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 2 && defined(__AVX__)
/**
* Specialization of VectorizedArray class for double and AVX.
// additions with multiplication (fused multiply-add) if those
// instructions are available. Otherwise, we need to use the built-in
// intrinsic command for __m256d
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data += vec.data;
-# else
+# else
data = _mm256_add_pd(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator-=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data -= vec.data;
-# else
+# else
data = _mm256_sub_pd(data, vec.data);
-# endif
+# endif
return *this;
}
/**
VectorizedArray &
operator*=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data *= vec.data;
-# else
+# else
data = _mm256_mul_pd(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator/=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data /= vec.data;
-# else
+# else
data = _mm256_div_pd(data, vec.data);
-# endif
+# endif
return *this;
}
void
gather(const double *base_ptr, const unsigned int *offsets)
{
-# ifdef __AVX2__
+# ifdef __AVX2__
// unfortunately, there does not appear to be a 128 bit integer load, so
// do it by some reinterpret casts here. this is allowed because the Intel
// API allows aliasing between different vector types.
_mm_loadu_ps(reinterpret_cast<const float *>(offsets));
const __m128i index = *reinterpret_cast<const __m128i *>(&index_val);
data = _mm256_i32gather_pd(base_ptr, index, 8);
-# else
+# else
for (unsigned int i = 0; i < 4; ++i)
*(reinterpret_cast<double *>(&data) + i) = base_ptr[offsets[i]];
-# endif
+# endif
}
/**
// additions with multiplication (fused multiply-add) if those
// instructions are available. Otherwise, we need to use the built-in
// intrinsic command for __m256d
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data += vec.data;
-# else
+# else
data = _mm256_add_ps(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator-=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data -= vec.data;
-# else
+# else
data = _mm256_sub_ps(data, vec.data);
-# endif
+# endif
return *this;
}
/**
VectorizedArray &
operator*=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data *= vec.data;
-# else
+# else
data = _mm256_mul_ps(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator/=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data /= vec.data;
-# else
+# else
data = _mm256_div_ps(data, vec.data);
-# endif
+# endif
return *this;
}
void
gather(const float *base_ptr, const unsigned int *offsets)
{
-# ifdef __AVX2__
+# ifdef __AVX2__
// unfortunately, there does not appear to be a 256 bit integer load, so
// do it by some reinterpret casts here. this is allowed because the Intel
// API allows aliasing between different vector types.
_mm256_loadu_ps(reinterpret_cast<const float *>(offsets));
const __m256i index = *reinterpret_cast<const __m256i *>(&index_val);
data = _mm256_i32gather_ps(base_ptr, index, 4);
-# else
+# else
for (unsigned int i = 0; i < 8; ++i)
*(reinterpret_cast<float *>(&data) + i) = base_ptr[offsets[i]];
-# endif
+# endif
}
/**
out[offsets[v] + i] = in[i][v];
}
-#endif
+# endif
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__SSE2__)
+# if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__SSE2__)
/**
* Specialization for double and SSE2.
VectorizedArray &
operator+=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data += vec.data;
-# else
+# else
data = _mm_add_pd(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator-=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data -= vec.data;
-# else
+# else
data = _mm_sub_pd(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator*=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data *= vec.data;
-# else
+# else
data = _mm_mul_pd(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator/=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data /= vec.data;
-# else
+# else
data = _mm_div_pd(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator+=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data += vec.data;
-# else
+# else
data = _mm_add_ps(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator-=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data -= vec.data;
-# else
+# else
data = _mm_sub_ps(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator*=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data *= vec.data;
-# else
+# else
data = _mm_mul_ps(data, vec.data);
-# endif
+# endif
return *this;
}
VectorizedArray &
operator/=(const VectorizedArray &vec)
{
-# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+# ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
data /= vec.data;
-# else
+# else
data = _mm_div_ps(data, vec.data);
-# endif
+# endif
return *this;
}
-#endif // if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0 && defined(__SSE2__)
+# endif // if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0 && defined(__SSE2__)
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__ALTIVEC__) && \
- defined(__VSX__)
+# if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__ALTIVEC__) && \
+ defined(__VSX__)
template <>
class VectorizedArray<double, 2>
const VectorizedArray<Number2, width2> &);
};
-#endif // if DEAL_II_VECTORIZATION_LEVEL >=1 && defined(__ALTIVEC__) &&
- // defined(__VSX__)
+# endif // if DEAL_II_VECTORIZATION_LEVEL >=1 && defined(__ALTIVEC__) &&
+ // defined(__VSX__)
+
+#endif // DOXYGEN
+/**
+ * @name Arithmetic operations with VectorizedArray
+ */
+//@{
/**
* Relational operator == for VectorizedArray
return out;
}
+
+//@}
+
+
+
DEAL_II_NAMESPACE_CLOSE
/**