@@ -372,6 +372,69 @@ namespace xsimd
372372 detail::store_masked (mem, src, mask.mask (), Mode {});
373373 }
374374
375+ namespace detail
376+ {
377+ // complex_low
378+ template <class A >
379+ XSIMD_INLINE batch<float , A> complex_low (batch<std::complex <float >, A> const & self, requires_arch<avx512f>) noexcept
380+ {
381+ __m512i idx = _mm512_setr_epi32 (0 , 16 , 1 , 17 , 2 , 18 , 3 , 19 , 4 , 20 , 5 , 21 , 6 , 22 , 7 , 23 );
382+ return _mm512_permutex2var_ps (self.real (), idx, self.imag ());
383+ }
384+ template <class A >
385+ XSIMD_INLINE batch<double , A> complex_low (batch<std::complex <double >, A> const & self, requires_arch<avx512f>) noexcept
386+ {
387+ __m512i idx = _mm512_setr_epi64 (0 , 8 , 1 , 9 , 2 , 10 , 3 , 11 );
388+ return _mm512_permutex2var_pd (self.real (), idx, self.imag ());
389+ }
390+
391+ // complex_high
392+ template <class A >
393+ XSIMD_INLINE batch<float , A> complex_high (batch<std::complex <float >, A> const & self, requires_arch<avx512f>) noexcept
394+ {
395+ __m512i idx = _mm512_setr_epi32 (8 , 24 , 9 , 25 , 10 , 26 , 11 , 27 , 12 , 28 , 13 , 29 , 14 , 30 , 15 , 31 );
396+ return _mm512_permutex2var_ps (self.real (), idx, self.imag ());
397+ }
398+ template <class A >
399+ XSIMD_INLINE batch<double , A> complex_high (batch<std::complex <double >, A> const & self, requires_arch<avx512f>) noexcept
400+ {
401+ __m512i idx = _mm512_setr_epi64 (4 , 12 , 5 , 13 , 6 , 14 , 7 , 15 );
402+ return _mm512_permutex2var_pd (self.real (), idx, self.imag ());
403+ }
404+ }
405+
406+ namespace detail
407+ {
408+ template <class A , class T >
409+ std::array<batch_bool<T, A>, 2 > zip_complex_mask (batch_bool<T, A> mask)
410+ {
411+ using mask_register_type = typename batch_bool<T, A>::register_type;
412+ mask_register_type nmask = mask.to_native ();
413+
414+ constexpr mask_register_type lo_bitmask = xsimd::utils::make_low_mask<mask_register_type>(mask.size / 2 );
415+ mask_register_type lo_mask = nmask & lo_bitmask;
416+ lo_mask = detail::interleave (lo_mask);
417+
418+ constexpr mask_register_type hi_bitmask = lo_bitmask << (mask.size / 2 );
419+ mask_register_type hi_mask = (nmask & hi_bitmask) >> (mask.size / 2 );
420+ hi_mask = detail::interleave (hi_mask);
421+
422+ return { batch_bool<T, A> { lo_mask }, batch_bool<T, A> { hi_mask } };
423+ }
424+ }
425+
426+ template <class A , class T , class Mode >
427+ XSIMD_INLINE void
428+ store_complex_masked (std::complex <T>* mem, batch<std::complex <T>, A> const & src, batch_bool<T, A> mask, Mode mode, requires_arch<avx512f>) noexcept
429+ {
430+ auto [lo_mask, hi_mask] = detail::zip_complex_mask (mask);
431+
432+ auto src_lo = detail::complex_low (src, A {});
433+ auto src_hi = detail::complex_high (src, A {});
434+ store_masked (reinterpret_cast <T*>(mem), src_lo, lo_mask, mode, A {});
435+ store_masked (reinterpret_cast <T*>(mem) + src.size , src_hi, hi_mask, mode, A {});
436+ }
437+
375438 // abs
376439 template <class A >
377440 XSIMD_INLINE batch<float , A> abs (batch<float , A> const & self, requires_arch<avx512f>) noexcept
@@ -972,36 +1035,6 @@ namespace xsimd
9721035 }
9731036 }
9741037
975- namespace detail
976- {
977- // complex_low
978- template <class A >
979- XSIMD_INLINE batch<float , A> complex_low (batch<std::complex <float >, A> const & self, requires_arch<avx512f>) noexcept
980- {
981- __m512i idx = _mm512_setr_epi32 (0 , 16 , 1 , 17 , 2 , 18 , 3 , 19 , 4 , 20 , 5 , 21 , 6 , 22 , 7 , 23 );
982- return _mm512_permutex2var_ps (self.real (), idx, self.imag ());
983- }
984- template <class A >
985- XSIMD_INLINE batch<double , A> complex_low (batch<std::complex <double >, A> const & self, requires_arch<avx512f>) noexcept
986- {
987- __m512i idx = _mm512_setr_epi64 (0 , 8 , 1 , 9 , 2 , 10 , 3 , 11 );
988- return _mm512_permutex2var_pd (self.real (), idx, self.imag ());
989- }
990-
991- // complex_high
992- template <class A >
993- XSIMD_INLINE batch<float , A> complex_high (batch<std::complex <float >, A> const & self, requires_arch<avx512f>) noexcept
994- {
995- __m512i idx = _mm512_setr_epi32 (8 , 24 , 9 , 25 , 10 , 26 , 11 , 27 , 12 , 28 , 13 , 29 , 14 , 30 , 15 , 31 );
996- return _mm512_permutex2var_ps (self.real (), idx, self.imag ());
997- }
998- template <class A >
999- XSIMD_INLINE batch<double , A> complex_high (batch<std::complex <double >, A> const & self, requires_arch<avx512f>) noexcept
1000- {
1001- __m512i idx = _mm512_setr_epi64 (4 , 12 , 5 , 13 , 6 , 14 , 7 , 15 );
1002- return _mm512_permutex2var_pd (self.real (), idx, self.imag ());
1003- }
1004- }
10051038 // incr_if
10061039 template <class A , class T , class = std::enable_if_t <std::is_integral_v<T>>>
10071040 XSIMD_INLINE batch<T, A> decr_if (batch<T, A> const & self, batch_bool<T, A> const & mask, requires_arch<avx512f>) noexcept
@@ -1633,6 +1666,16 @@ namespace xsimd
16331666 }
16341667 }
16351668
1669+ template <class A , class T , class Mode >
1670+ XSIMD_INLINE batch<std::complex <T>, A>
1671+ load_complex_masked (std::complex <T> const * mem, batch_bool<T, A> mask, Mode mode, requires_arch<avx512f>) noexcept
1672+ {
1673+ auto [lo_mask, hi_mask] = detail::zip_complex_mask (mask);
1674+ batch<T, A> res_lo = batch<T, A>::load (reinterpret_cast <T const *>(mem), lo_mask, mode);
1675+ batch<T, A> res_hi = batch<T, A>::load (reinterpret_cast <T const *>(mem) + mask.size , hi_mask, mode);
1676+ return detail::load_complex (res_lo, res_hi, A {});
1677+ }
1678+
16361679 // load_unaligned
16371680 template <class A , class T , class = std::enable_if_t <std::is_integral_v<T>>>
16381681 XSIMD_INLINE batch<T, A> load_unaligned (T const * mem, convert<T>, requires_arch<avx512f>) noexcept
0 commit comments