aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Core/MathFunctions.h
diff options
context:
space:
mode:
authorGravatar Srinivas Vasudevan <srvasude@gmail.com>2019-12-12 01:56:54 +0000
committerGravatar Rasmus Munk Larsen <rmlarsen@google.com>2019-12-12 01:56:54 +0000
commit88062b7feddcf3e8354c6857753523c2a80d864f (patch)
tree39a2b3928922d35946a324bd4828040ce6237709 /Eigen/src/Core/MathFunctions.h
parent381f8f3139533739c4a428843e2495b442989fcc (diff)
Fix implementation of complex expm1. Add tests that fail with previous implementation, but pass with the current one.
Diffstat (limited to 'Eigen/src/Core/MathFunctions.h')
-rw-r--r--Eigen/src/Core/MathFunctions.h19
1 files changed, 18 insertions, 1 deletions
diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h
index 4e6053b2e..dadf2cba2 100644
--- a/Eigen/src/Core/MathFunctions.h
+++ b/Eigen/src/Core/MathFunctions.h
@@ -529,7 +529,24 @@ struct expm1_impl<std::complex<RealScalar> > {
EIGEN_DEVICE_FUNC static inline std::complex<RealScalar> run(
const std::complex<RealScalar>& x) {
EIGEN_STATIC_ASSERT_NON_INTEGER(RealScalar)
- return std_fallback::expm1(x);
+ RealScalar xr = x.real();
+ RealScalar xi = x.imag();
+ // expm1(z) = exp(z) - 1
+ // = exp(x + i * y) - 1
+ // = exp(x) * (cos(y) + i * sin(y)) - 1
+ // = exp(x) * cos(y) - 1 + i * exp(x) * sin(y)
+ // Imag(expm1(z)) = exp(x) * sin(y)
+ // Real(expm1(z)) = exp(x) * cos(y) - 1
+ // = exp(x) * cos(y) - 1.
+ // = expm1(x) + exp(x) * (cos(y) - 1)
+ // = expm1(x) + exp(x) * (2 * sin(y / 2) ** 2)
+ RealScalar erm1 = std_fallback::expm1(xr);
+ RealScalar er = erm1 + RealScalar(1.);
+ RealScalar sin2 = sin(xi / RealScalar(2.));
+ sin2 = sin2 * sin2;
+ RealScalar s = sin(xi);
+ RealScalar real_part = erm1 - RealScalar(2.) * er * sin2;
+ return std::complex<RealScalar>(real_part, er * s);
}
};