mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Add reciprocal packet op and fast specializations for float with SSE, AVX, and AVX512.
This commit is contained in:
@@ -17,6 +17,35 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal Fast reciprocal using Newton-Raphson's method.
|
||||
We assume that the starting guess provided in approx_a_recip has at least
|
||||
half the leading mantissa bits in the correct result, such that a single
|
||||
Newton-Raphson step is sufficient to get within 1-2 ulps of the currect result.
|
||||
*/
|
||||
template <typename Packet, int Steps>
|
||||
struct generic_reciprocal_newton_step {
|
||||
static_assert(Steps > 0, "Steps must be at least 1.");
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Packet
|
||||
run(const Packet& a, const Packet& approx_a_recip) {
|
||||
using Scalar = typename unpacket_traits<Packet>::type;
|
||||
const Packet two = pset1<Packet>(Scalar(2));
|
||||
const Packet neg_a = pnegate(a);
|
||||
// Refine the approximation using one Newton-Raphson step:
|
||||
// x_{i} = x_{i-1} * (2 - a * x_{i-1})
|
||||
const Packet x =
|
||||
generic_reciprocal_newton_step<Packet,Steps - 1>::run(a, approx_a_recip);
|
||||
return pmul(x, pmadd(neg_a, x, two));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Packet>
|
||||
struct generic_reciprocal_newton_step<Packet, 0> {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Packet
|
||||
run(const Packet& /*unused*/, const Packet& approx_a_recip) {
|
||||
return approx_a_recip;
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns the hyperbolic tan of \a a (coeff-wise)
|
||||
Doesn't do anything fancy, just a 13/6-degree rational interpolant which
|
||||
is accurate up to a couple of ulps in the (approximate) range [-8, 8],
|
||||
|
||||
Reference in New Issue
Block a user