From fd8ca6f8d89c05f51babc81a9abe74b3bcc71b3b Mon Sep 17 00:00:00 2001 From: Matthias Maier Date: Wed, 4 Sep 2019 16:05:33 -0500 Subject: [PATCH] VectorizedArray: Implement a compare_and_apply_mask function --- include/deal.II/base/vectorization.h | 201 +++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/include/deal.II/base/vectorization.h b/include/deal.II/base/vectorization.h index 9c75428465..543efe5ed8 100644 --- a/include/deal.II/base/vectorization.h +++ b/include/deal.II/base/vectorization.h @@ -3957,9 +3957,210 @@ operator<<(std::ostream &out, const VectorizedArray &p) return out; } +//@} + +/** + * @name Ternary operations on VectorizedArray + */ +//@{ + + +/** + * TODO + */ +enum SIMDComparison : int +{ + equal = _CMP_EQ_OQ, + not_equal = _CMP_NEQ_OQ, + less_than = _CMP_LT_OQ, + less_than_or_equal = _CMP_LE_OQ, + greater_than = _CMP_GT_OQ, + greater_than_or_equal = _CMP_GE_OQ +}; + + +/** + * TODO + */ +template +DEAL_II_ALWAYS_INLINE inline Number +compare_and_apply_mask(const Number &left, + const Number &right, + const Number &true_value, + const Number &false_value) +{ + bool mask; + + switch (predicate) + { + case SIMDComparison::equal: + mask = left == right; + break; + case SIMDComparison::not_equal: + mask = left != right; + break; + case SIMDComparison::less_than: + mask = left < right; + break; + case SIMDComparison::less_than_or_equal: + mask = left <= right; + break; + case SIMDComparison::greater_than: + mask = left > right; + break; + case SIMDComparison::greater_than_or_equal: + mask = left >= right; + break; + } + + return mask ? true_value : false_value; +} + + +/** + * TODO + */ +template +DEAL_II_ALWAYS_INLINE inline VectorizedArray +compare_and_apply_mask(const VectorizedArray &left, + const VectorizedArray &right, + const VectorizedArray &true_value, + const VectorizedArray &false_value) +{ + bool mask; + + switch (predicate) + { + case SIMDComparison::equal: + mask = left.data == right.data; + break; + case SIMDComparison::not_equal: + mask = left.data != right.data; + break; + case SIMDComparison::less_than: + mask = left.data < right.data; + break; + case SIMDComparison::less_than_or_equal: + mask = left.data <= right.data; + break; + case SIMDComparison::greater_than: + mask = left.data > right.data; + break; + case SIMDComparison::greater_than_or_equal: + mask = left.data >= right.data; + break; + } + + return mask ? true_value.data : false_value.data; +} //@} +#ifndef DOXYGEN +# if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 3 && defined(__AVX512F__) + +template +DEAL_II_ALWAYS_INLINE inline VectorizedArray +compare_and_apply_mask(const VectorizedArray &left, + const VectorizedArray &right, + const VectorizedArray &true_values, + const VectorizedArray &false_values) +{ + const auto mask = _mm512_cmp_ps(left.data, right.data, predicate); + VectorizedArray result; + result.data = _mm512_or_ps(_mm512_and_ps(mask, true_values.data), + _mm512_andnot_ps(mask, false_values.data)); + return result; +} + + + +template +DEAL_II_ALWAYS_INLINE inline VectorizedArray +compare_and_apply_mask(const VectorizedArray &left, + const VectorizedArray &right, + const VectorizedArray &true_values, + const VectorizedArray &false_values) +{ + const auto mask = _mm512_cmp_pd(left.data, right.data, predicate); + VectorizedArray result; + result.data = _mm256_or_ps(_mm512_and_ps(mask, true_values.data), + _mm512_andnot_ps(mask, false_values.data)); + return result; +} + +# endif + +# if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 2 && defined(__AVX__) + +template +DEAL_II_ALWAYS_INLINE inline VectorizedArray +compare_and_apply_mask(const VectorizedArray &left, + const VectorizedArray &right, + const VectorizedArray &true_values, + const VectorizedArray &false_values) +{ + const auto mask = _mm256_cmp_ps(left.data, right.data, predicate); + + VectorizedArray result; + result.data = _mm256_or_ps(_mm256_and_ps(mask, true_values.data), + _mm256_andnot_ps(mask, false_values.data)); + return result; +} + + +template +DEAL_II_ALWAYS_INLINE inline VectorizedArray +compare_and_apply_mask(const VectorizedArray &left, + const VectorizedArray &right, + const VectorizedArray &true_values, + const VectorizedArray &false_values) +{ + const auto mask = _mm256_cmp_pd(left.data, right.data, predicate); + + VectorizedArray result; + result.data = _mm256_or_ps(_mm256_and_ps(mask, true_values.data), + _mm256_andnot_ps(mask, false_values.data)); + return result; +} + +# endif + +# if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__SSE2__) + +template +DEAL_II_ALWAYS_INLINE inline VectorizedArray +compare_and_apply_mask(const VectorizedArray &left, + const VectorizedArray &right, + const VectorizedArray &true_values, + const VectorizedArray &false_values) +{ + const auto mask = _mm_cmp_ps(left.data, right.data, predicate); + + VectorizedArray result; + result.data = _mm_or_ps(_mm_and_ps(mask, true_values.data), + _mm_andnot_ps(mask, false_values.data)); + return result; +} + + +template +DEAL_II_ALWAYS_INLINE inline VectorizedArray +compare_and_apply_mask(const VectorizedArray &left, + const VectorizedArray &right, + const VectorizedArray &true_values, + const VectorizedArray &false_values) +{ + const auto mask = _mm_cmp_pd(left.data, right.data, predicate); + + VectorizedArray result; + result.data = _mm_or_ps(_mm_and_ps(mask, true_values.data), + _mm_andnot_ps(mask, false_values.data)); + return result; +} + +# endif +#endif // DOXYGEN DEAL_II_NAMESPACE_CLOSE -- 2.39.5