diff --git a/include/xsimd/arch/xsimd_avx512f.hpp b/include/xsimd/arch/xsimd_avx512f.hpp index 06da6218e..414a26f34 100644 --- a/include/xsimd/arch/xsimd_avx512f.hpp +++ b/include/xsimd/arch/xsimd_avx512f.hpp @@ -1962,25 +1962,19 @@ namespace xsimd } // reduce_max - template > + template > XSIMD_INLINE T reduce_max(batch const& self, requires_arch) noexcept { - constexpr batch_constant mask; - batch step = _mm512_permutexvar_epi64(mask.as_batch(), self); - batch acc = max(self, step); - __m256i low = _mm512_castsi512_si256(acc); - return reduce_max(batch(low)); + batch low(detail::lower_half(self)), high(detail::upper_half(self)); + return reduce_max(max(low, high)); } // reduce_min - template > + template > XSIMD_INLINE T reduce_min(batch const& self, requires_arch) noexcept { - constexpr batch_constant mask; - batch step = _mm512_permutexvar_epi64(mask.as_batch(), self); - batch acc = min(self, step); - __m256i low = _mm512_castsi512_si256(acc); - return reduce_min(batch(low)); + batch low(detail::lower_half(self)), high(detail::upper_half(self)); + return reduce_min(min(low, high)); } // reduce_mul diff --git a/test/test_batch.cpp b/test/test_batch.cpp index 0bee8b1fc..3ee94ee4f 100644 --- a/test/test_batch.cpp +++ b/test/test_batch.cpp @@ -1070,6 +1070,22 @@ struct batch_test INFO("reduce_min"); CHECK_SCALAR_EQ(res, expected); } + // reduce_max / reduce_min with the extremum at each position + for (std::size_t i = 0; i < size; ++i) + { + array_type data; + data.fill(value_type(1)); + { + data[i] = std::numeric_limits::max(); + INFO("reduce_max, extremum at index ", i); + CHECK_SCALAR_EQ(reduce_max(batch_type::load_unaligned(data.data())), data[i]); + } + { + data[i] = std::numeric_limits::lowest(); + INFO("reduce_min, extremum at index ", i); + CHECK_SCALAR_EQ(reduce_min(batch_type::load_unaligned(data.data())), data[i]); + } + } // reduce_mul { value_type expected = std::accumulate(lhs.cbegin(), lhs.cend(), value_type(1), std::multiplies());