diff --git a/Eigen/src/Core/arch/AVX/MathFunctions.h b/Eigen/src/Core/arch/AVX/MathFunctions.h index bc3ca6abc..7b43fbb5e 100644 --- a/Eigen/src/Core/arch/AVX/MathFunctions.h +++ b/Eigen/src/Core/arch/AVX/MathFunctions.h @@ -23,6 +23,7 @@ namespace internal { EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_FLOAT(Packet8f) +EIGEN_DOUBLE_PACKET_FUNCTION(atanh, Packet4d) EIGEN_DOUBLE_PACKET_FUNCTION(log, Packet4d) EIGEN_DOUBLE_PACKET_FUNCTION(log2, Packet4d) EIGEN_DOUBLE_PACKET_FUNCTION(exp, Packet4d) diff --git a/Eigen/src/Core/arch/AVX/PacketMath.h b/Eigen/src/Core/arch/AVX/PacketMath.h index b9a8fc3a0..77fd7e6af 100644 --- a/Eigen/src/Core/arch/AVX/PacketMath.h +++ b/Eigen/src/Core/arch/AVX/PacketMath.h @@ -148,6 +148,7 @@ struct packet_traits : default_packet_traits { HasSqrt = 1, HasRsqrt = 1, HasATan = 1, + HasATanh = 1, HasBlend = 1 }; }; diff --git a/Eigen/src/Core/arch/AVX512/PacketMath.h b/Eigen/src/Core/arch/AVX512/PacketMath.h index 36195430d..0a167c8c8 100644 --- a/Eigen/src/Core/arch/AVX512/PacketMath.h +++ b/Eigen/src/Core/arch/AVX512/PacketMath.h @@ -154,6 +154,7 @@ struct packet_traits : default_packet_traits { HasExp = 1, HasATan = 1, HasTanh = EIGEN_FAST_MATH, + HasATanh = 1, HasCmp = 1, HasDiv = 1 }; diff --git a/Eigen/src/Core/arch/AltiVec/PacketMath.h b/Eigen/src/Core/arch/AltiVec/PacketMath.h index 29c5a5da3..6998e7c05 100644 --- a/Eigen/src/Core/arch/AltiVec/PacketMath.h +++ b/Eigen/src/Core/arch/AltiVec/PacketMath.h @@ -3177,6 +3177,7 @@ struct packet_traits : default_packet_traits { HasSin = EIGEN_FAST_MATH, HasCos = EIGEN_FAST_MATH, HasTanh = EIGEN_FAST_MATH, + HasATanh = 1, HasATan = 0, HasLog = 0, HasExp = 1, diff --git a/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h b/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h index d404ec77d..6cd0b531f 100644 --- a/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h +++ b/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h @@ -1198,8 +1198,7 @@ template EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh_float(const Packet& x) { typedef typename unpacket_traits::type Scalar; static_assert(std::is_same::value, "Scalar type must be float"); - const Packet half = pset1(0.5f); - const Packet x_gt_half = pcmp_le(half, pabs(x)); + // For |x| in [0:0.5] we use a polynomial approximation of the form // P(x) = x + x^3*(c3 + x^2 * (c5 + x^2 * (... x^2 * c11) ... )). const Packet C3 = pset1(0.3333373963832855224609375f); @@ -1215,10 +1214,61 @@ EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh_float(const Pa p = pmadd(pmul(x, x2), p, x); // For |x| in ]0.5:1.0] we use atanh = 0.5*ln((1+x)/(1-x)); + const Packet half = pset1(0.5f); const Packet one = pset1(1.0f); Packet r = pdiv(padd(one, x), psub(one, x)); r = pmul(half, plog(r)); - return pselect(x_gt_half, r, p); + + const Packet x_gt_half = pcmp_le(half, pabs(x)); + const Packet x_eq_one = pcmp_eq(one, pabs(x)); + const Packet x_gt_one = pcmp_lt(one, pabs(x)); + const Packet inf = pset1(std::numeric_limits::infinity()); + return por(x_gt_one, pselect(x_eq_one, por(psignbit(x), inf), pselect(x_gt_half, r, p))); +} + +template +EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh_double(const Packet& x) { + typedef typename unpacket_traits::type Scalar; + static_assert(std::is_same::value, "Scalar type must be double"); + // For x in [-0.5:0.5] we use a rational approximation of the form + // R(x) = x + x^3*P(x^2)/Q(x^2), where P is or order 4 and Q is of order 5. + const Packet p0 = pset1(1.2306328729812676e-01); + const Packet p2 = pset1(-2.5949536095445679e-01); + const Packet p4 = pset1(1.8185306179826699e-01); + const Packet p6 = pset1(-4.7129526768798737e-02); + const Packet p8 = pset1(3.3071338469301391e-03); + + const Packet q0 = pset1(3.6918986189438030e-01); + const Packet q2 = pset1(-1.0000000000000000e+00); + const Packet q4 = pset1(9.8733495886883648e-01); + const Packet q6 = pset1(-4.2828141436397615e-01); + const Packet q8 = pset1(7.6391885763341910e-02); + const Packet q10 = pset1(-3.8679974580640881e-03); + + const Packet x2 = pmul(x, x); + const Packet x3 = pmul(x, x2); + Packet q = pmadd(q10, x2, q8); + Packet p = pmadd(p8, x2, p6); + q = pmadd(x2, q, q6); + p = pmadd(x2, p, p4); + q = pmadd(x2, q, q4); + p = pmadd(x2, p, p2); + q = pmadd(x2, q, q2); + p = pmadd(x2, p, p0); + q = pmadd(x2, q, q0); + Packet y_small = pmadd(x3, pdiv(p, q), x); + + // For |x| in ]0.5:1.0] we use atanh = 0.5*ln((1+x)/(1-x)); + const Packet half = pset1(0.5); + const Packet one = pset1(1.0); + Packet y_large = pdiv(padd(one, x), psub(one, x)); + y_large = pmul(half, plog(y_large)); + + const Packet x_gt_half = pcmp_le(half, pabs(x)); + const Packet x_eq_one = pcmp_eq(one, pabs(x)); + const Packet x_gt_one = pcmp_lt(one, pabs(x)); + const Packet inf = pset1(std::numeric_limits::infinity()); + return por(x_gt_one, pselect(x_eq_one, por(psignbit(x), inf), pselect(x_gt_half, y_large, y_small))); } template diff --git a/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h b/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h index d9e495f97..f470c20d9 100644 --- a/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h +++ b/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h @@ -114,6 +114,10 @@ EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet ptanh_double(const Pa template EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh_float(const Packet& x); +/** \internal \returns atanh(x) for double precision float */ +template +EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh_double(const Packet& x); + /** \internal \returns sqrt(x) for complex types */ template EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psqrt_complex(const Packet& a); @@ -182,6 +186,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet generic_round(const Packet& a); } #define EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_DOUBLE(PACKET) \ + EIGEN_DOUBLE_PACKET_FUNCTION(atanh, PACKET) \ EIGEN_DOUBLE_PACKET_FUNCTION(log, PACKET) \ EIGEN_DOUBLE_PACKET_FUNCTION(sin, PACKET) \ EIGEN_DOUBLE_PACKET_FUNCTION(cos, PACKET) \ diff --git a/Eigen/src/Core/arch/NEON/PacketMath.h b/Eigen/src/Core/arch/NEON/PacketMath.h index 2f59eeb3d..414f0f587 100644 --- a/Eigen/src/Core/arch/NEON/PacketMath.h +++ b/Eigen/src/Core/arch/NEON/PacketMath.h @@ -5133,6 +5133,7 @@ struct packet_traits : default_packet_traits { HasExp = 1, HasLog = 1, HasATan = 1, + HasATanh = 1, #endif HasSin = EIGEN_FAST_MATH, HasCos = EIGEN_FAST_MATH, diff --git a/Eigen/src/Core/arch/SSE/PacketMath.h b/Eigen/src/Core/arch/SSE/PacketMath.h index 00925f685..fe596e268 100644 --- a/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/Eigen/src/Core/arch/SSE/PacketMath.h @@ -220,6 +220,7 @@ struct packet_traits : default_packet_traits { HasSqrt = 1, HasRsqrt = 1, HasATan = 1, + HasATanh = 1, HasBlend = 1 }; };