Skip to content

complex: Fix expm1 precision loss for small arguments#1634

Open
duncanita wants to merge 1 commit intoc3d:devfrom
duncanita:fix/complex-expm1-precision
Open

complex: Fix expm1 precision loss for small arguments#1634
duncanita wants to merge 1 commit intoc3d:devfrom
duncanita:fix/complex-expm1-precision

Conversation

@duncanita
Copy link

Summary

  • Rewrite complex expm1(z) to use a cancellation-free formula that separates real and imaginary parts:
    • Real: expm1(a)*cos(b) - 2*sin(b/2)^2
    • Imaginary: (expm1(a)+1)*sin(b)
  • The previous exp(z)-1 approach lost significant digits for small z due to catastrophic cancellation
  • Reuses expm1(a) instead of calling exp(a) separately, eliminating one full Taylor series evaluation
  • Preserves full precision down to 1E-40 at 200 digits

Test plan

  • All 3312 existing tests pass
  • 9 new complex expm1 tests added covering: zero, real axis, purely imaginary (pi and small), mixed small, very small (1E-10), negative real, high precision (200 digits/100 significant figures at 1E-40), and halving identity verification

Use cancellation-free formula that separates real and imaginary parts:
  real: expm1(a)*cos(b) - 2*sin(b/2)^2
  imag: (expm1(a)+1)*sin(b)

The previous exp(z)-1 approach lost digits when z was small due to
catastrophic cancellation.  The new formula delegates to the real
expm1() for the real component and uses a half-angle identity for the
cosine term, preserving full precision down to 1E-40 at 200 digits.
The imaginary part reuses expm1(a) instead of calling exp(a) separately,
eliminating one full Taylor series evaluation.
@duncanita duncanita changed the base branch from stable to dev February 17, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments