diff --git a/include/xsimd/arch/xsimd_avx.hpp b/include/xsimd/arch/xsimd_avx.hpp index 84b1ba3a0..f15c72e74 100644 --- a/include/xsimd/arch/xsimd_avx.hpp +++ b/include/xsimd/arch/xsimd_avx.hpp @@ -1477,10 +1477,10 @@ namespace xsimd { if (std::is_signed_v) { - auto mask = (other >> (8 * sizeof(T) - 1)); + auto negative = other < batch(T(0)); auto self_pos_branch = min(std::numeric_limits::max() - other, self); auto self_neg_branch = max(std::numeric_limits::min() - other, self); - return other + select(batch_bool(mask.data), self_neg_branch, self_pos_branch); + return other + select(negative, self_neg_branch, self_pos_branch); } else { @@ -1728,10 +1728,10 @@ namespace xsimd } else if (std::is_signed_v) { - auto mask = (other >> (8 * sizeof(T) - 1)); + auto negative = other < batch(T(0)); auto self_overflow_branch = min(std::numeric_limits::max() + other, self); auto self_underflow_branch = max(std::numeric_limits::min() + other, self); - return select(batch_bool(mask.data), self_overflow_branch, self_underflow_branch) - other; + return select(negative, self_overflow_branch, self_underflow_branch) - other; } else { diff --git a/include/xsimd/arch/xsimd_avx512f.hpp b/include/xsimd/arch/xsimd_avx512f.hpp index 02934de8b..271a1bc08 100644 --- a/include/xsimd/arch/xsimd_avx512f.hpp +++ b/include/xsimd/arch/xsimd_avx512f.hpp @@ -1544,6 +1544,8 @@ namespace xsimd XSIMD_INLINE unsigned char tobitset(unsigned char unpacked[N]) { static_assert(N == 8 || N == 4 || N == 2, "valid pack size"); + // The multiply gathers the N selected bits into the top N bits + // of the 8 * N bit product, so the shift is 8 * N - N. if constexpr (N == 8) { uint64_t data; @@ -1561,7 +1563,7 @@ namespace xsimd const uint32_t magic = (0x80 + 0x4000 + 0x200000 + 0x10000000); - unsigned char res = ((data * magic) >> 24) & 0xFF; + unsigned char res = ((data * magic) >> 28) & 0xFF; return res; } else if constexpr (N == 2) @@ -1571,7 +1573,7 @@ namespace xsimd const uint16_t magic = (0x80 + 0x4000); - unsigned char res = ((data * magic) >> 8) & 0xFF; + unsigned char res = ((data * magic) >> 14) & 0xFF; return res; } } diff --git a/include/xsimd/arch/xsimd_common_fwd.hpp b/include/xsimd/arch/xsimd_common_fwd.hpp index b247b2bd6..495049785 100644 --- a/include/xsimd/arch/xsimd_common_fwd.hpp +++ b/include/xsimd/arch/xsimd_common_fwd.hpp @@ -60,8 +60,12 @@ namespace xsimd XSIMD_INLINE batch bitwise_rshift(batch const& self, batch const& other, requires_arch) noexcept; template >> XSIMD_INLINE batch bitwise_rshift(batch const& self, requires_arch) noexcept; + template + XSIMD_INLINE batch decr_if(batch const& self, Mask const& mask, requires_arch) noexcept; template XSIMD_INLINE batch_bool gt(batch const& self, batch const& other, requires_arch) noexcept; + template + XSIMD_INLINE batch incr_if(batch const& self, Mask const& mask, requires_arch) noexcept; template >> XSIMD_INLINE batch mul(batch const& self, batch const& other, requires_arch) noexcept; template >>