Implement float pexp_complex

This commit is contained in:
Damiano Franzò
2024-02-14 14:55:03 +01:00
committed by Rasmus Munk Larsen
parent 4d419e2209
commit be06c9ad51
9 changed files with 133 additions and 4 deletions

View File

@@ -555,7 +555,7 @@ inline float trig_reduce_huge(float xf, Eigen::numext::int32_t* quadrant) {
return float(double(int64_t(p)) * pio2_62);
}
template <bool ComputeSine, typename Packet>
template <bool ComputeSine, typename Packet, bool ComputeBoth = false>
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
#if EIGEN_COMP_GNUC_STRICT
__attribute__((optimize("-fno-unsafe-math-optimizations")))
@@ -669,10 +669,21 @@ EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
y2 = pmadd(y2, x, x);
// Select the correct result from the two polynomials.
y = ComputeSine ? pselect(poly_mask, y2, y1) : pselect(poly_mask, y1, y2);
if (ComputeBoth) {
Packet peven = peven_mask(x);
Packet ysin = pselect(poly_mask, y2, y1);
Packet ycos = pselect(poly_mask, y1, y2);
Packet sign_bit_sin = pxor(_x, preinterpret<Packet>(plogical_shift_left<30>(y_int)));
Packet sign_bit_cos = preinterpret<Packet>(plogical_shift_left<30>(padd(y_int, csti_1)));
sign_bit_sin = pand(sign_bit_sin, cst_sign_mask); // clear all but left most bit
sign_bit_cos = pand(sign_bit_cos, cst_sign_mask); // clear all but left most bit
y = pselect(peven, pxor(ysin, sign_bit_sin), pxor(ycos, sign_bit_cos));
} else {
y = ComputeSine ? pselect(poly_mask, y2, y1) : pselect(poly_mask, y1, y2);
y = pxor(y, sign_bit);
}
// Update the sign and filter huge inputs
return pxor(y, sign_bit);
return y;
}
template <typename Packet>
@@ -1051,6 +1062,50 @@ EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog_complex(const Pa
return xres;
}
template <typename Packet>
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pexp_complex(const Packet& a) {
typedef typename unpacket_traits<Packet>::as_real RealPacket;
typedef typename unpacket_traits<Packet>::type Scalar;
typedef typename Scalar::value_type RealScalar;
const RealPacket even_mask = peven_mask(a.v);
const Packet even_maskp = Packet(even_mask);
const RealPacket odd_mask = pcplxflip(Packet(even_mask)).v;
Packet p0y = Packet(pand(odd_mask, a.v));
Packet py0 = pcplxflip(p0y);
Packet pyy = padd(p0y, py0);
RealPacket sincos = psincos_float<false, RealPacket, true>(pyy.v);
RealPacket cossin = pcplxflip(Packet(sincos)).v;
const RealPacket cst_pos_inf = pset1<RealPacket>(NumTraits<RealScalar>::infinity());
const RealPacket cst_neg_inf = pset1<RealPacket>(-NumTraits<RealScalar>::infinity());
Packet x_is_inf = Packet(pcmp_eq(a.v, cst_pos_inf));
Packet x_is_minf = Packet(pcmp_eq(a.v, cst_neg_inf));
Packet x_is_zero = Packet(pcmp_eq(pzero(a).v, a.v));
Packet x_real_is_inf = pand(even_maskp, x_is_inf);
Packet x_real_is_minf = pand(even_maskp, x_is_minf);
Packet inf0 = pset1<Packet>(Scalar(NumTraits<RealScalar>::infinity(), RealScalar(0)));
Packet x_is_inf0 = pand(x_real_is_inf, pcplxflip(x_is_zero));
x_is_inf0 = por(x_is_inf0, pcplxflip(x_is_inf0));
Packet x_imag_goes_zero = pand(por(x_is_minf, x_is_inf), pcplxflip(x_real_is_minf));
Packet x_is_nan = Packet(pisnan(a.v));
Packet x_real_goes_zero = pand(x_is_nan, pcplxflip(x_real_is_minf));
RealPacket pexp_real = pexp(a.v);
Packet pexp_half = Packet(pand(even_mask, pexp_real));
RealPacket xexp_flip_rp = pcplxflip(pexp_half).v;
RealPacket xexp = padd(pexp_half.v, xexp_flip_rp);
Packet result(pmul(cossin, xexp));
result = pselect(x_is_inf0, inf0, result);
result = pselect(x_real_is_minf, pzero(a), result);
result = pselect(x_imag_goes_zero, pzero(a), result);
result = pselect(x_real_goes_zero, pzero(a), result);
return result;
}
template <typename Packet>
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psqrt_complex(const Packet& a) {
typedef typename unpacket_traits<Packet>::type Scalar;