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