Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions include/xsimd/types/xsimd_batch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,8 @@ namespace xsimd
// Compile-time mask overloads
template <class U, bool... Values, class Mode = aligned_mode>
[[nodiscard]] static XSIMD_INLINE batch load(U const* mem, batch_bool_constant<value_type, A, Values...> mask, Mode = {}) noexcept;
template <class Mode = aligned_mode>
[[nodiscard]] static XSIMD_INLINE batch load(value_type const* mem, batch_bool<T, A> mask, Mode = {}) noexcept;
template <class U>
[[nodiscard]] static XSIMD_INLINE batch load(U const* mem, stream_mode) noexcept;
template <class U>
Expand All @@ -562,6 +564,8 @@ namespace xsimd
// Compile-time mask overloads
template <class U, bool... Values, class Mode = aligned_mode>
XSIMD_INLINE void store(U* mem, batch_bool_constant<value_type, A, Values...> mask, Mode = {}) const noexcept;
template <class Mode = aligned_mode>
XSIMD_INLINE void store(value_type* mem, batch_bool<T, A> mask, Mode = {}) const noexcept;
template <class U>
XSIMD_INLINE void store(U* mem, stream_mode) const noexcept;

Expand Down Expand Up @@ -1506,6 +1510,17 @@ namespace xsimd
kernel::store_masked<A>(mem, *this, mask, mode, A {});
}

template <class T, class A>
template <class Mode>
XSIMD_INLINE void batch<std::complex<T>, A>::store(value_type* mem, batch_bool<T, A> mask, Mode) const noexcept
{
alignas(A::alignment()) std::array<value_type, size> buffer;
store_aligned(buffer.data());
for (std::size_t i = 0; i < size; ++i)
if (mask.get(i))
mem[i] = buffer[i];
}

template <class T, class A>
XSIMD_INLINE void batch<std::complex<T>, A>::store_aligned(T* real_dst, T* imag_dst) const noexcept
{
Expand Down Expand Up @@ -1544,6 +1559,16 @@ namespace xsimd
return kernel::load_masked<A>(mem, mask, kernel::convert<value_type> {}, mode, A {});
}

template <class T, class A>
template <class Mode>
XSIMD_INLINE batch<std::complex<T>, A> batch<std::complex<T>, A>::load(value_type const* mem, batch_bool<T, A> mask, Mode) noexcept
{
alignas(A::alignment()) std::array<value_type, size> buffer {};
for (std::size_t i = 0; i < size; ++i)
buffer[i] = mask.get(i) ? mem[i] : value_type(0);
return load_aligned(buffer.data());
}

template <class T, class A>
template <class U>
XSIMD_INLINE batch<std::complex<T>, A> batch<std::complex<T>, A>::load(U const* mem, stream_mode) noexcept
Expand Down
34 changes: 34 additions & 0 deletions test/test_batch_complex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,40 @@ struct batch_complex_test
CHECK_EQ(ares_real, areal);
CHECK_EQ(ares_imag, aimag);
}
{
// Runtime-masked load / store
alignas(arch_type::alignment()) array_type amem;
for (size_t i = 0; i < size; ++i)
amem[i] = lhs[i];

uint64_t bits = 0;
for (size_t i = 0; i < size; ++i)
if (i % 2 == 0)
bits |= uint64_t(1) << i;
using mask_type = typename batch_type::batch_bool_type;
auto mask = mask_type::from_mask(bits);

batch_type loaded = batch_type::load(amem.data(), mask, xsimd::aligned_mode());
for (size_t i = 0; i < size; ++i)
{
if (i % 2 == 0)
CHECK_EQ(loaded.get(i), amem[i]);
else
CHECK_EQ(loaded.get(i), value_type(0, 0));
}

batch_type to_store = batch_type::load_unaligned(rhs.data());
alignas(arch_type::alignment()) array_type adest;
std::fill(adest.begin(), adest.end(), value_type(0, 0));
to_store.store(adest.data(), mask, xsimd::aligned_mode());
for (size_t i = 0; i < size; ++i)
{
if (i % 2 == 0)
CHECK_EQ(adest[i], rhs[i]);
else
CHECK_EQ(adest[i], value_type(0, 0));
}
}
}
#ifdef XSIMD_ENABLE_XTL_COMPLEX
void test_load_store_xtl() const
Expand Down
Loading