Skip to content

Commit e385873

Browse files
committed
gh-157859: Fix cmath.atanh() returning inf at ±1 ± sqrt(DBL_MIN)*1j
cmath_atanh_impl() selects its near-pole formula with `ay < CM_SQRT_DBL_MIN`. At equality the general formula computes 4/(0 + ay*ay) = 4/DBL_MIN, which overflows, so the finite input 1 + 2**-511j (and its three sign/conjugate mirrors, and the corresponding cmath.atan() inputs) returned inf. Use `<=` so the boundary word takes the near-pole formula, which is accurate there.
1 parent 6b97452 commit e385873

3 files changed

Lines changed: 18 additions & 1 deletion

File tree

Lib/test/mathdata/cmath_testcases.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,13 @@ atan0301 atan 1e-155 1.0 -> 0.78539816339744828 178.79691829731851
853853
atan0302 atan 9.9999999999999999e-161 -1.0 -> 0.78539816339744828 -184.55338102980363
854854
atan0303 atan -1e-165 1.0 -> -0.78539816339744828 190.30984376228875
855855
atan0304 atan -9.9998886718268301e-321 -1.0 -> -0.78539816339744828 -368.76019403576692
856+
-- gh-157859: real part at and next to sqrt(DBL_MIN) = 2**-511 (see atanh0305-0310)
857+
atan0305 atan 1.4916681462400412e-154 1.0 -> 0.78539816339744828 177.445678223346
858+
atan0306 atan 1.4916681462400413e-154 1.0 -> 0.78539816339744828 177.445678223346
859+
atan0307 atan 1.4916681462400417e-154 1.0 -> 0.78539816339744828 177.445678223346
860+
atan0308 atan -1.4916681462400413e-154 1.0 -> -0.78539816339744828 177.445678223346
861+
atan0309 atan 1.4916681462400413e-154 -1.0 -> 0.78539816339744828 -177.445678223346
862+
atan0310 atan -1.4916681462400413e-154 -1.0 -> -0.78539816339744828 -177.445678223346
856863

857864
-- Additional real values (mpmath)
858865
atan0400 atan 1.7976931348623157e+308 0.0 -> 1.5707963267948966192 0.0
@@ -1043,6 +1050,14 @@ atanh0301 atanh 1.0 9.9999999999999997e-155 -> 177.64562575082149 0.785398163397
10431050
atanh0302 atanh -1.0 1e-161 -> -185.70467357630065 0.78539816339744828
10441051
atanh0303 atanh 1.0 -1e-165 -> 190.30984376228875 -0.78539816339744828
10451052
atanh0304 atanh -1.0 -9.8813129168249309e-324 -> -372.22003596069061 -0.78539816339744828
1053+
-- gh-157859: imaginary part at and next to sqrt(DBL_MIN) = 2**-511, where
1054+
-- the near-pole and general formulas meet; the boundary value overflowed.
1055+
atanh0305 atanh 1.0 1.4916681462400412e-154 -> 177.445678223346 0.78539816339744828
1056+
atanh0306 atanh 1.0 1.4916681462400413e-154 -> 177.445678223346 0.78539816339744828
1057+
atanh0307 atanh 1.0 1.4916681462400417e-154 -> 177.445678223346 0.78539816339744828
1058+
atanh0308 atanh 1.0 -1.4916681462400413e-154 -> 177.445678223346 -0.78539816339744828
1059+
atanh0309 atanh -1.0 1.4916681462400413e-154 -> -177.445678223346 0.78539816339744828
1060+
atanh0310 atanh -1.0 -1.4916681462400413e-154 -> -177.445678223346 -0.78539816339744828
10461061

10471062
-- special values
10481063
atanh1000 atanh 0.0 0.0 -> 0.0 0.0
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :func:`cmath.atanh` and :func:`cmath.atan` returning an infinite
2+
component instead of a finite result for certain inputs near their poles.

Modules/cmathmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ cmath_atanh_impl(PyObject *module, Py_complex z)
382382
r.real = z.real/4./h/h;
383383
r.imag = copysign(Py_MATH_PI/2., z.imag);
384384
errno = 0;
385-
} else if (z.real == 1. && ay < CM_SQRT_DBL_MIN) {
385+
} else if (z.real == 1. && ay <= CM_SQRT_DBL_MIN) {
386386
/* C99 standard says: atanh(1+/-0.) should be inf +/- 0i */
387387
if (ay == 0.) {
388388
r.real = INF;

0 commit comments

Comments
 (0)