11#ifndef EIGEN_COMPLEX_AVX_H
12#define EIGEN_COMPLEX_AVX_H
15#include "../../InternalHeaderCheck.h"
21EIGEN_GCC_FAST_MATH_COMPLEX_VECTORIZE_WORKAROUND_PUSH
25 EIGEN_STRONG_INLINE Packet4cf() {}
26 EIGEN_STRONG_INLINE
explicit Packet4cf(
const __m256& a) : v(a) {}
30#ifndef EIGEN_VECTORIZE_AVX512
32struct packet_traits<std::complex<float> > : default_packet_traits {
33 typedef Packet4cf type;
34 typedef Packet2cf half;
58struct unpacket_traits<Packet4cf> {
59 typedef std::complex<float> type;
60 typedef Packet2cf half;
61 typedef Packet8f as_real;
66 masked_load_available =
false,
67 masked_store_available =
false
72EIGEN_STRONG_INLINE Packet4cf padd<Packet4cf>(
const Packet4cf& a,
const Packet4cf& b) {
73 return Packet4cf(_mm256_add_ps(a.v, b.v));
76EIGEN_STRONG_INLINE Packet4cf psub<Packet4cf>(
const Packet4cf& a,
const Packet4cf& b) {
77 return Packet4cf(_mm256_sub_ps(a.v, b.v));
80EIGEN_STRONG_INLINE Packet4cf pnegate(
const Packet4cf& a) {
81 return Packet4cf(pnegate(a.v));
84EIGEN_STRONG_INLINE Packet4cf pconj(
const Packet4cf& a) {
85 const __m256 mask = _mm256_castsi256_ps(_mm256_setr_epi32(0x00000000, SIGN_MASK_I32, 0x00000000, SIGN_MASK_I32,
86 0x00000000, SIGN_MASK_I32, 0x00000000, SIGN_MASK_I32));
87 return Packet4cf(_mm256_xor_ps(a.v, mask));
91EIGEN_STRONG_INLINE Packet4cf pmul(
const Packet4cf& a,
const Packet4cf& b) {
92 __m256 tmp1 = _mm256_mul_ps(_mm256_movehdup_ps(a.v), _mm256_permute_ps(b.v, _MM_SHUFFLE(2, 3, 0, 1)));
93 __m256 tmp2 = _mm256_moveldup_ps(a.v);
94#ifdef EIGEN_VECTORIZE_FMA
95 __m256 result = _mm256_fmaddsub_ps(tmp2, b.v, tmp1);
97 __m256 result = _mm256_addsub_ps(_mm256_mul_ps(tmp2, b.v), tmp1);
99 return Packet4cf(result);
103EIGEN_STRONG_INLINE Packet4cf pcmp_eq(
const Packet4cf& a,
const Packet4cf& b) {
104 __m256 eq = _mm256_cmp_ps(a.v, b.v, _CMP_EQ_OQ);
105 return Packet4cf(_mm256_and_ps(eq, _mm256_permute_ps(eq, 0xb1)));
109EIGEN_STRONG_INLINE Packet4cf ptrue<Packet4cf>(
const Packet4cf& a) {
110 return Packet4cf(ptrue(Packet8f(a.v)));
113EIGEN_STRONG_INLINE Packet4cf pand<Packet4cf>(
const Packet4cf& a,
const Packet4cf& b) {
114 return Packet4cf(_mm256_and_ps(a.v, b.v));
117EIGEN_STRONG_INLINE Packet4cf por<Packet4cf>(
const Packet4cf& a,
const Packet4cf& b) {
118 return Packet4cf(_mm256_or_ps(a.v, b.v));
121EIGEN_STRONG_INLINE Packet4cf pxor<Packet4cf>(
const Packet4cf& a,
const Packet4cf& b) {
122 return Packet4cf(_mm256_xor_ps(a.v, b.v));
125EIGEN_STRONG_INLINE Packet4cf pandnot<Packet4cf>(
const Packet4cf& a,
const Packet4cf& b) {
126 return Packet4cf(_mm256_andnot_ps(b.v, a.v));
130EIGEN_STRONG_INLINE Packet4cf pload<Packet4cf>(
const std::complex<float>* from) {
131 EIGEN_DEBUG_ALIGNED_LOAD
return Packet4cf(_mm256_load_ps(&numext::real_ref(*from)));
134EIGEN_STRONG_INLINE Packet4cf ploadu<Packet4cf>(
const std::complex<float>* from) {
135 EIGEN_DEBUG_UNALIGNED_LOAD
return Packet4cf(_mm256_loadu_ps(&numext::real_ref(*from)));
139EIGEN_STRONG_INLINE Packet4cf pset1<Packet4cf>(
const std::complex<float>& from) {
148 const __m128i lo64 = _mm_loadl_epi64(
reinterpret_cast<const __m128i*
>(&from));
149#ifdef EIGEN_VECTORIZE_AVX2
150 return Packet4cf(_mm256_castsi256_ps(_mm256_broadcastq_epi64(lo64)));
156 const __m128 lo = _mm_castpd_ps(_mm_movedup_pd(_mm_castsi128_pd(lo64)));
157 return Packet4cf(_mm256_insertf128_ps(_mm256_castps128_ps256(lo), lo, 1));
162EIGEN_STRONG_INLINE Packet4cf ploaddup<Packet4cf>(
const std::complex<float>* from) {
168 __m256 bcast = _mm256_broadcast_ps(
reinterpret_cast<const __m128*
>(
static_cast<const void*
>(from)));
169 return Packet4cf(_mm256_castpd_ps(_mm256_permute_pd(_mm256_castps_pd(bcast), 3 << 2)));
173EIGEN_STRONG_INLINE
void pstore<std::complex<float> >(std::complex<float>* to,
const Packet4cf& from) {
174 EIGEN_DEBUG_ALIGNED_STORE _mm256_store_ps(&numext::real_ref(*to), from.v);
177EIGEN_STRONG_INLINE
void pstoreu<std::complex<float> >(std::complex<float>* to,
const Packet4cf& from) {
178 EIGEN_DEBUG_UNALIGNED_STORE _mm256_storeu_ps(&numext::real_ref(*to), from.v);
182EIGEN_DEVICE_FUNC
inline Packet4cf pgather<std::complex<float>, Packet4cf>(
const std::complex<float>* from,
184 return Packet4cf(_mm256_set_ps(std::imag(from[3 * stride]), std::real(from[3 * stride]), std::imag(from[2 * stride]),
185 std::real(from[2 * stride]), std::imag(from[1 * stride]), std::real(from[1 * stride]),
186 std::imag(from[0 * stride]), std::real(from[0 * stride])));
190EIGEN_DEVICE_FUNC
inline void pscatter<std::complex<float>, Packet4cf>(std::complex<float>* to,
const Packet4cf& from,
192 __m128 low = _mm256_extractf128_ps(from.v, 0);
194 std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(low, low, 0)), _mm_cvtss_f32(_mm_shuffle_ps(low, low, 1)));
196 std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(low, low, 2)), _mm_cvtss_f32(_mm_shuffle_ps(low, low, 3)));
198 __m128 high = _mm256_extractf128_ps(from.v, 1);
200 std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(high, high, 0)), _mm_cvtss_f32(_mm_shuffle_ps(high, high, 1)));
202 std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(high, high, 2)), _mm_cvtss_f32(_mm_shuffle_ps(high, high, 3)));
206EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet4cf>(
const Packet4cf& a) {
207 return pfirst(Packet2cf(_mm256_castps256_ps128(a.v)));
211EIGEN_STRONG_INLINE Packet4cf preverse(
const Packet4cf& a) {
212 __m128 low = _mm256_extractf128_ps(a.v, 0);
213 __m128 high = _mm256_extractf128_ps(a.v, 1);
214 __m128d lowd = _mm_castps_pd(low);
215 __m128d highd = _mm_castps_pd(high);
216 low = _mm_castpd_ps(_mm_shuffle_pd(lowd, lowd, 0x1));
217 high = _mm_castpd_ps(_mm_shuffle_pd(highd, highd, 0x1));
218 __m256 result = _mm256_setzero_ps();
219 result = _mm256_insertf128_ps(result, low, 1);
220 result = _mm256_insertf128_ps(result, high, 0);
221 return Packet4cf(result);
225EIGEN_STRONG_INLINE std::complex<float> predux<Packet4cf>(
const Packet4cf& a) {
226 return predux(padd(Packet2cf(_mm256_extractf128_ps(a.v, 0)), Packet2cf(_mm256_extractf128_ps(a.v, 1))));
230EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet4cf>(
const Packet4cf& a) {
231 return predux_mul(pmul(Packet2cf(_mm256_extractf128_ps(a.v, 0)), Packet2cf(_mm256_extractf128_ps(a.v, 1))));
234EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet4cf, Packet8f)
237EIGEN_STRONG_INLINE Packet4cf pdiv<Packet4cf>(
const Packet4cf& a,
const Packet4cf& b) {
238 return pdiv_complex(a, b);
242EIGEN_STRONG_INLINE Packet4cf pcplxflip<Packet4cf>(
const Packet4cf& x) {
243 return Packet4cf(_mm256_shuffle_ps(x.v, x.v, _MM_SHUFFLE(2, 3, 0, 1)));
248 EIGEN_STRONG_INLINE Packet2cd() {}
249 EIGEN_STRONG_INLINE
explicit Packet2cd(
const __m256d& a) : v(a) {}
253#ifndef EIGEN_VECTORIZE_AVX512
255struct packet_traits<std::complex<double> > : default_packet_traits {
256 typedef Packet2cd type;
257 typedef Packet1cd half;
281struct unpacket_traits<Packet2cd> {
282 typedef std::complex<double> type;
283 typedef Packet1cd half;
284 typedef Packet4d as_real;
289 masked_load_available =
false,
290 masked_store_available =
false
295EIGEN_STRONG_INLINE Packet2cd padd<Packet2cd>(
const Packet2cd& a,
const Packet2cd& b) {
296 return Packet2cd(_mm256_add_pd(a.v, b.v));
299EIGEN_STRONG_INLINE Packet2cd psub<Packet2cd>(
const Packet2cd& a,
const Packet2cd& b) {
300 return Packet2cd(_mm256_sub_pd(a.v, b.v));
303EIGEN_STRONG_INLINE Packet2cd pnegate(
const Packet2cd& a) {
304 return Packet2cd(pnegate(a.v));
307EIGEN_STRONG_INLINE Packet2cd pconj(
const Packet2cd& a) {
309 _mm256_castsi256_pd(_mm256_set_epi32(SIGN_MASK_I32, 0x0, 0x0, 0x0, SIGN_MASK_I32, 0x0, 0x0, 0x0));
310 return Packet2cd(_mm256_xor_pd(a.v, mask));
314EIGEN_STRONG_INLINE Packet2cd pmul(
const Packet2cd& a,
const Packet2cd& b) {
315 __m256d tmp1 = _mm256_mul_pd(_mm256_permute_pd(a.v, 0xF), _mm256_permute_pd(b.v, 0x5));
316 __m256d tmp2 = _mm256_movedup_pd(a.v);
317#ifdef EIGEN_VECTORIZE_FMA
318 __m256d result = _mm256_fmaddsub_pd(tmp2, b.v, tmp1);
320 __m256d result = _mm256_addsub_pd(_mm256_mul_pd(tmp2, b.v), tmp1);
322 return Packet2cd(result);
326EIGEN_STRONG_INLINE Packet2cd pcmp_eq(
const Packet2cd& a,
const Packet2cd& b) {
327 __m256d eq = _mm256_cmp_pd(a.v, b.v, _CMP_EQ_OQ);
328 return Packet2cd(pand(eq, _mm256_permute_pd(eq, 0x5)));
332EIGEN_STRONG_INLINE Packet2cd ptrue<Packet2cd>(
const Packet2cd& a) {
333 return Packet2cd(ptrue(Packet4d(a.v)));
336EIGEN_STRONG_INLINE Packet2cd pand<Packet2cd>(
const Packet2cd& a,
const Packet2cd& b) {
337 return Packet2cd(_mm256_and_pd(a.v, b.v));
340EIGEN_STRONG_INLINE Packet2cd por<Packet2cd>(
const Packet2cd& a,
const Packet2cd& b) {
341 return Packet2cd(_mm256_or_pd(a.v, b.v));
344EIGEN_STRONG_INLINE Packet2cd pxor<Packet2cd>(
const Packet2cd& a,
const Packet2cd& b) {
345 return Packet2cd(_mm256_xor_pd(a.v, b.v));
348EIGEN_STRONG_INLINE Packet2cd pandnot<Packet2cd>(
const Packet2cd& a,
const Packet2cd& b) {
349 return Packet2cd(_mm256_andnot_pd(b.v, a.v));
353EIGEN_STRONG_INLINE Packet2cd pload<Packet2cd>(
const std::complex<double>* from) {
354 EIGEN_DEBUG_ALIGNED_LOAD
return Packet2cd(_mm256_load_pd((
const double*)from));
357EIGEN_STRONG_INLINE Packet2cd ploadu<Packet2cd>(
const std::complex<double>* from) {
358 EIGEN_DEBUG_UNALIGNED_LOAD
return Packet2cd(_mm256_loadu_pd((
const double*)from));
362EIGEN_STRONG_INLINE Packet2cd pset1<Packet2cd>(
const std::complex<double>& from) {
365 return Packet2cd(_mm256_broadcast_pd((
const __m128d*)(
const void*)&from));
371EIGEN_STRONG_INLINE Packet2cd ploaddup<Packet2cd>(
const std::complex<double>* from) {
372 return pset1<Packet2cd>(*from);
376EIGEN_STRONG_INLINE
void pstore<std::complex<double> >(std::complex<double>* to,
const Packet2cd& from) {
377 EIGEN_DEBUG_ALIGNED_STORE _mm256_store_pd((
double*)to, from.v);
380EIGEN_STRONG_INLINE
void pstoreu<std::complex<double> >(std::complex<double>* to,
const Packet2cd& from) {
381 EIGEN_DEBUG_UNALIGNED_STORE _mm256_storeu_pd((
double*)to, from.v);
385EIGEN_DEVICE_FUNC
inline Packet2cd pgather<std::complex<double>, Packet2cd>(
const std::complex<double>* from,
387 return Packet2cd(_mm256_set_pd(std::imag(from[1 * stride]), std::real(from[1 * stride]), std::imag(from[0 * stride]),
388 std::real(from[0 * stride])));
392EIGEN_DEVICE_FUNC
inline void pscatter<std::complex<double>, Packet2cd>(std::complex<double>* to,
const Packet2cd& from,
394 __m128d low = _mm256_extractf128_pd(from.v, 0);
395 to[stride * 0] = std::complex<double>(_mm_cvtsd_f64(low), _mm_cvtsd_f64(_mm_shuffle_pd(low, low, 1)));
396 __m128d high = _mm256_extractf128_pd(from.v, 1);
397 to[stride * 1] = std::complex<double>(_mm_cvtsd_f64(high), _mm_cvtsd_f64(_mm_shuffle_pd(high, high, 1)));
401EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet2cd>(
const Packet2cd& a) {
402 __m128d low = _mm256_extractf128_pd(a.v, 0);
403 EIGEN_ALIGN16
double res[2];
404 _mm_store_pd(res, low);
405 return std::complex<double>(res[0], res[1]);
409EIGEN_STRONG_INLINE Packet2cd preverse(
const Packet2cd& a) {
410 __m256d result = _mm256_permute2f128_pd(a.v, a.v, 1);
411 return Packet2cd(result);
415EIGEN_STRONG_INLINE std::complex<double> predux<Packet2cd>(
const Packet2cd& a) {
416 return predux(padd(Packet1cd(_mm256_extractf128_pd(a.v, 0)), Packet1cd(_mm256_extractf128_pd(a.v, 1))));
420EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet2cd>(
const Packet2cd& a) {
421 return predux(pmul(Packet1cd(_mm256_extractf128_pd(a.v, 0)), Packet1cd(_mm256_extractf128_pd(a.v, 1))));
424EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cd, Packet4d)
427EIGEN_STRONG_INLINE Packet2cd pdiv<Packet2cd>(
const Packet2cd& a,
const Packet2cd& b) {
428 return pdiv_complex(a, b);
432EIGEN_STRONG_INLINE Packet2cd pcplxflip<Packet2cd>(
const Packet2cd& x) {
433 return Packet2cd(_mm256_shuffle_pd(x.v, x.v, 0x5));
436EIGEN_DEVICE_FUNC
inline void ptranspose(PacketBlock<Packet4cf, 4>& kernel) {
437 __m256d P0 = _mm256_castps_pd(kernel.packet[0].v);
438 __m256d P1 = _mm256_castps_pd(kernel.packet[1].v);
439 __m256d P2 = _mm256_castps_pd(kernel.packet[2].v);
440 __m256d P3 = _mm256_castps_pd(kernel.packet[3].v);
442 __m256d T0 = _mm256_shuffle_pd(P0, P1, 15);
443 __m256d T1 = _mm256_shuffle_pd(P0, P1, 0);
444 __m256d T2 = _mm256_shuffle_pd(P2, P3, 15);
445 __m256d T3 = _mm256_shuffle_pd(P2, P3, 0);
447 kernel.packet[1].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T0, T2, 32));
448 kernel.packet[3].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T0, T2, 49));
449 kernel.packet[0].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T1, T3, 32));
450 kernel.packet[2].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T1, T3, 49));
453EIGEN_DEVICE_FUNC
inline void ptranspose(PacketBlock<Packet2cd, 2>& kernel) {
454 __m256d tmp = _mm256_permute2f128_pd(kernel.packet[0].v, kernel.packet[1].v, 0 + (2 << 4));
455 kernel.packet[1].v = _mm256_permute2f128_pd(kernel.packet[0].v, kernel.packet[1].v, 1 + (3 << 4));
456 kernel.packet[0].v = tmp;
459EIGEN_INSTANTIATE_COMPLEX_MATH_FUNCS_NO_EXP(Packet2cd)
460EIGEN_INSTANTIATE_COMPLEX_MATH_FUNCS(Packet4cf)
463EIGEN_STRONG_INLINE Packet2cd pexp<Packet2cd>(
const Packet2cd& a) {
464#ifdef EIGEN_VECTORIZE_AVX2
465 return pexp_complex<Packet2cd>(a);
470 return Packet2cd(_mm256_insertf128_pd(_mm256_castpd128_pd256(pexp(Packet1cd(_mm256_castpd256_pd128(a.v))).v),
471 pexp(Packet1cd(_mm256_extractf128_pd(a.v, 1))).v, 1));
475#ifdef EIGEN_VECTORIZE_FMA
478EIGEN_STRONG_INLINE Packet4cf pmadd(
const Packet4cf& a,
const Packet4cf& b,
const Packet4cf& c) {
479 __m256 a_odd = _mm256_movehdup_ps(a.v);
480 __m256 a_even = _mm256_moveldup_ps(a.v);
481 __m256 b_swap = _mm256_permute_ps(b.v, _MM_SHUFFLE(2, 3, 0, 1));
482 __m256 result = _mm256_fmaddsub_ps(a_even, b.v, _mm256_fmaddsub_ps(a_odd, b_swap, c.v));
483 return Packet4cf(result);
486EIGEN_STRONG_INLINE Packet4cf pmsub(
const Packet4cf& a,
const Packet4cf& b,
const Packet4cf& c) {
487 __m256 a_odd = _mm256_movehdup_ps(a.v);
488 __m256 a_even = _mm256_moveldup_ps(a.v);
489 __m256 b_swap = _mm256_permute_ps(b.v, _MM_SHUFFLE(2, 3, 0, 1));
490 __m256 result = _mm256_fmaddsub_ps(a_even, b.v, _mm256_fmsubadd_ps(a_odd, b_swap, c.v));
491 return Packet4cf(result);
494EIGEN_STRONG_INLINE Packet4cf pnmadd(
const Packet4cf& a,
const Packet4cf& b,
const Packet4cf& c) {
495 return pnegate(pmsub(a, b, c));
498EIGEN_STRONG_INLINE Packet4cf pnmsub(
const Packet4cf& a,
const Packet4cf& b,
const Packet4cf& c) {
499 return pnegate(pmadd(a, b, c));
503EIGEN_STRONG_INLINE Packet2cd pmadd(
const Packet2cd& a,
const Packet2cd& b,
const Packet2cd& c) {
504 __m256d a_odd = _mm256_permute_pd(a.v, 0xF);
505 __m256d a_even = _mm256_movedup_pd(a.v);
506 __m256d b_swap = _mm256_permute_pd(b.v, 0x5);
507 __m256d result = _mm256_fmaddsub_pd(a_even, b.v, _mm256_fmaddsub_pd(a_odd, b_swap, c.v));
508 return Packet2cd(result);
511EIGEN_STRONG_INLINE Packet2cd pmsub(
const Packet2cd& a,
const Packet2cd& b,
const Packet2cd& c) {
512 __m256d a_odd = _mm256_permute_pd(a.v, 0xF);
513 __m256d a_even = _mm256_movedup_pd(a.v);
514 __m256d b_swap = _mm256_permute_pd(b.v, 0x5);
515 __m256d result = _mm256_fmaddsub_pd(a_even, b.v, _mm256_fmsubadd_pd(a_odd, b_swap, c.v));
516 return Packet2cd(result);
519EIGEN_STRONG_INLINE Packet2cd pnmadd(
const Packet2cd& a,
const Packet2cd& b,
const Packet2cd& c) {
520 return pnegate(pmsub(a, b, c));
523EIGEN_STRONG_INLINE Packet2cd pnmsub(
const Packet2cd& a,
const Packet2cd& b,
const Packet2cd& c) {
524 return pnegate(pmadd(a, b, c));
531struct has_packet_segment<Packet2cf> : std::true_type {};
534struct has_packet_segment<Packet4cf> : std::true_type {};
537struct has_packet_segment<Packet2cd> : std::true_type {};
540#ifndef EIGEN_VECTORIZE_AVX512VL
545inline Packet2cf ploaduSegment<Packet2cf>(
const std::complex<float>* from, Index begin, Index count) {
546 return (Packet2cf)_mm_maskload_ps(&numext::real_ref(*from), segment_mask_2x64(begin, count));
550inline void pstoreuSegment<std::complex<float>, Packet2cf>(std::complex<float>* to,
const Packet2cf& from, Index begin,
552 _mm_maskstore_ps(&numext::real_ref(*to), segment_mask_2x64(begin, count), from.v);
556inline Packet4cf ploaduSegment<Packet4cf>(
const std::complex<float>* from, Index begin, Index count) {
557 return (Packet4cf)_mm256_maskload_ps(&numext::real_ref(*from), segment_mask_4x64(begin, count));
561inline void pstoreuSegment<std::complex<float>, Packet4cf>(std::complex<float>* to,
const Packet4cf& from, Index begin,
563 _mm256_maskstore_ps(&numext::real_ref(*to), segment_mask_4x64(begin, count), from.v);
569inline Packet2cd ploaduSegment<Packet2cd>(
const std::complex<double>* from, Index begin, Index count) {
570 return (Packet2cd)_mm256_maskload_pd(&numext::real_ref(*from), segment_mask_4x64(2 * begin, 2 * count));
574inline void pstoreuSegment<std::complex<double>, Packet2cd>(std::complex<double>* to,
const Packet2cd& from,
575 Index begin, Index count) {
576 _mm256_maskstore_pd(&numext::real_ref(*to), segment_mask_4x64(2 * begin, 2 * count), from.v);
583EIGEN_GCC_FAST_MATH_COMPLEX_VECTORIZE_WORKAROUND_POP
@ Aligned32
Definition Constants.h:239