12#ifndef EIGEN_ARCH_GENERIC_PACKET_MATH_COMPLEX_H
13#define EIGEN_ARCH_GENERIC_PACKET_MATH_COMPLEX_H
16#include "../../InternalHeaderCheck.h"
21EIGEN_GCC_FAST_MATH_COMPLEX_VECTORIZE_WORKAROUND_PUSH
27template <
typename Packet>
28EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pdiv_complex(
const Packet& x,
const Packet& y) {
29 using RealPacket =
typename unpacket_traits<Packet>::as_real;
30 using RealScalar =
typename unpacket_traits<RealPacket>::type;
34 const RealPacket one = pset1<RealPacket>(RealScalar(1));
35 const RealPacket abs_y = pabs(y.v);
36 const RealPacket abs_y_flip = pcplxflip(Packet(abs_y)).v;
38 const RealPacket mask = pcmp_lt(abs_y, abs_y_flip);
39 RealPacket y_scaled = pselect(mask, pdiv(abs_y, abs_y_flip), one);
40 y_scaled = por(y_scaled, pandnot(y.v, abs_y));
41 RealPacket denom = pmul(y.v, y_scaled);
42 denom = padd(denom, pcplxflip(Packet(denom)).v);
43 Packet num = pmul(x, pconj(Packet(y_scaled)));
44 return Packet(pdiv(num.v, denom));
47template <
typename Packet>
48EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pmul_complex(
const Packet& x,
const Packet& y) {
52 Packet x_re = pdupreal(x);
53 Packet x_im = pdupimag(x);
54 Packet tmp_re = Packet(pmul(x_re.v, y.v));
55 Packet tmp_im = Packet(pmul(x_im.v, y.v));
56 tmp_im = pcplxflip(pconj(tmp_im));
57 return padd(tmp_im, tmp_re);
60template <
typename Packet>
61EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog_complex(
const Packet& x) {
62 using RealPacket =
typename unpacket_traits<Packet>::as_real;
65 RealPacket x_flip = pcplxflip(x).v;
66 Packet x_norm = phypot_complex(x);
67 RealPacket xlogr = plog(x_norm.v);
70 RealPacket ximg = patan2(x.v, x_flip);
72 const RealPacket cst_pos_inf = pinf<RealPacket>();
73 RealPacket x_abs = pabs(x.v);
74 RealPacket is_x_pos_inf = pcmp_eq(x_abs, cst_pos_inf);
75 RealPacket is_y_pos_inf = pcplxflip(Packet(is_x_pos_inf)).v;
76 RealPacket is_any_inf = por(is_x_pos_inf, is_y_pos_inf);
77 RealPacket xreal = pselect(is_any_inf, cst_pos_inf, xlogr);
79 return Packet(pselect(peven_mask(xreal), xreal, ximg));
82template <
typename Packet>
83EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pexp_complex(
const Packet& a) {
84 using RealPacket =
typename unpacket_traits<Packet>::as_real;
85 using Scalar =
typename unpacket_traits<Packet>::type;
86 using RealScalar =
typename Scalar::value_type;
87 const RealPacket even_mask = peven_mask(a.v);
88 const RealPacket odd_mask = pcplxflip(Packet(even_mask)).v;
94 RealPacket x = pand(a.v, even_mask);
95 x = por(x, pcplxflip(Packet(x)).v);
96 RealPacket expx = pexp(x);
99 RealPacket y = pand(odd_mask, a.v);
100 y = por(y, pcplxflip(Packet(y)).v);
101 RealPacket cisy = psincos_selector<RealPacket>(y);
102 cisy = pcplxflip(Packet(cisy)).v;
104 const RealPacket cst_pos_inf = pinf<RealPacket>();
105 const RealPacket cst_neg_inf = por(psignmask<RealPacket>(), pinf<RealPacket>());
110 RealPacket cisy_sign = por(pandnot(cisy, pabs(cisy)), pset1<RealPacket>(RealScalar(1)));
111 cisy = pselect(pcmp_eq(x, cst_neg_inf), cisy_sign, cisy);
115 RealPacket y_sign = por(pandnot(y, pabs(y)), pset1<RealPacket>(RealScalar(1)));
116 cisy = pselect(pand(pcmp_eq(x, cst_pos_inf), pisnan(cisy)), pand(y_sign, even_mask), cisy);
122 RealPacket cisy_sign_one = por(pand(cisy, psignmask<RealPacket>()), pset1<RealPacket>(RealScalar(1)));
123 RealPacket expx_inf_y_finite = pand(pcmp_eq(expx, cst_pos_inf), pcmp_lt(pabs(y), cst_pos_inf));
124 cisy = pselect(expx_inf_y_finite, cisy_sign_one, cisy);
126 Packet result = Packet(pmul(expx, cisy));
129 result = pselect(Packet(pcmp_eq(y, pzero(y))), Packet(por(pand(expx, even_mask), pand(y, odd_mask))), result);
134template <
typename Packet>
135EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psqrt_complex(
const Packet& a) {
136 using Scalar =
typename unpacket_traits<Packet>::type;
137 using RealScalar =
typename Scalar::value_type;
138 using RealPacket =
typename unpacket_traits<Packet>::as_real;
176 RealPacket a_abs = pabs(a.v);
177 RealPacket a_abs_flip = pcplxflip(Packet(a_abs)).v;
178 RealPacket a_max = pmax(a_abs, a_abs_flip);
179 RealPacket a_min = pmin(a_abs, a_abs_flip);
180 RealPacket a_min_zero_mask = pcmp_eq(a_min, pzero(a_min));
181 RealPacket a_max_zero_mask = pcmp_eq(a_max, pzero(a_max));
182 RealPacket r = pdiv(a_min, a_max);
183 const RealPacket cst_one = pset1<RealPacket>(RealScalar(1));
184 RealPacket l = pmul(a_max, psqrt(padd(cst_one, pmul(r, r))));
186 l = pselect(a_min_zero_mask, a_max, l);
191 const RealPacket cst_half = pset1<RealPacket>(RealScalar(0.5));
193 rho.v = psqrt(pmul(cst_half, padd(a_abs, l)));
198 RealPacket eta = pandnot(pmul(cst_half, pdiv(a.v, pcplxflip(rho).v)), a_max_zero_mask);
199 RealPacket real_mask = peven_mask(a.v);
200 Packet positive_real_result;
202 positive_real_result.v = pselect(real_mask, rho.v, eta);
207 const RealPacket cst_imag_sign_mask = pandnot(psignmask<RealPacket>(), real_mask);
208 RealPacket imag_signs = pand(a.v, cst_imag_sign_mask);
209 Packet negative_real_result;
211 negative_real_result.v = por(pabs(pcplxflip(positive_real_result).v), imag_signs);
214 Packet negative_real_mask;
215 negative_real_mask.v = pcmp_lt(pand(real_mask, a.v), pzero(a.v));
216 negative_real_mask.v = por(negative_real_mask.v, pcplxflip(negative_real_mask).v);
217 Packet result = pselect(negative_real_mask, negative_real_result, positive_real_result);
224 const RealPacket cst_pos_inf = pinf<RealPacket>();
226 is_inf.v = pcmp_eq(a_abs, cst_pos_inf);
228 is_real_inf.v = pand(is_inf.v, real_mask);
229 is_real_inf = por(is_real_inf, pcplxflip(is_real_inf));
231 Packet real_inf_result;
232 real_inf_result.v = pmul(a_abs, pset1<Packet>(Scalar(RealScalar(1.0), RealScalar(0.0))).v);
233 real_inf_result.v = pselect(negative_real_mask.v, pcplxflip(real_inf_result).v, real_inf_result.v);
236 is_imag_inf.v = pandnot(is_inf.v, real_mask);
237 is_imag_inf = por(is_imag_inf, pcplxflip(is_imag_inf));
238 Packet imag_inf_result;
239 imag_inf_result.v = por(pand(cst_pos_inf, real_mask), pandnot(a.v, real_mask));
241 Packet result_is_nan = pisnan(result);
242 result = por(result_is_nan, result);
244 return pselect(is_imag_inf, imag_inf_result, pselect(is_real_inf, real_inf_result, result));
249template <
typename Packet>
250EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet phypot_complex(
const Packet& a) {
251 using Scalar =
typename unpacket_traits<Packet>::type;
252 using RealScalar =
typename Scalar::value_type;
253 using RealPacket =
typename unpacket_traits<Packet>::as_real;
255 const RealPacket cst_zero_rp = pset1<RealPacket>(
static_cast<RealScalar
>(0.0));
256 const RealPacket cst_minus_one_rp = pset1<RealPacket>(
static_cast<RealScalar
>(-1.0));
257 const RealPacket cst_two_rp = pset1<RealPacket>(
static_cast<RealScalar
>(2.0));
258 const RealPacket evenmask = peven_mask(a.v);
260 RealPacket a_abs = pabs(a.v);
261 RealPacket a_flip = pcplxflip(Packet(a_abs)).v;
262 RealPacket a_all = pselect(evenmask, a_abs, a_flip);
263 RealPacket b_all = pselect(evenmask, a_flip, a_abs);
265 RealPacket a2 = pmul(a.v, a.v);
266 RealPacket a2_flip = pcplxflip(Packet(a2)).v;
267 RealPacket h = psqrt(padd(a2, a2_flip));
268 RealPacket h_sq = pmul(h, h);
269 RealPacket a_sq = pselect(evenmask, a2, a2_flip);
270 RealPacket m_h_sq = pmul(h_sq, cst_minus_one_rp);
271 RealPacket m_a_sq = pmul(a_sq, cst_minus_one_rp);
272 RealPacket x = psub(psub(pmadd(h, h, m_h_sq), pmadd(b_all, b_all, psub(a_sq, h_sq))), pmadd(a_all, a_all, m_a_sq));
273 h = psub(h, pdiv(x, pmul(cst_two_rp, h)));
276 RealPacket iszero = pcmp_eq(por(a_abs, a_flip), cst_zero_rp);
278 h = pandnot(h, iszero);
282EIGEN_GCC_FAST_MATH_COMPLEX_VECTORIZE_WORKAROUND_POP