This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Major error in cmath routines
Type: behavior Stage:
Components: Extension Modules Versions: Python 3.0, Python 2.7, Python 2.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: mark.dickinson Nosy List: christian.heimes, mark.dickinson, thor222
Priority: critical Keywords:

Created on 2008-10-17 15:16 by thor222, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (3)
msg74917 - (view) Author: Shawn Mequin (thor222) Date: 2008-10-17 15:16
There's an error in the way cmath computes the inverse sine, cosine and
tangent functions.

Example:
In 2.6: cmath.asin(2) returns 1.5707963267948966+1.3169578969248166j
However, the answer should be 1.5707963267948966-1.3169578969248166j
cmath.asin(2) returns the correct answer in 2.5.2.

Same problem exists in cmath.acos:
In 2.6: cmath.acos(2) = -1.3169578969248164j, but should be
1.3169578969248164j (once again, 2.5.2 returns the correct answer).

However, in 2.5.2 and 2.6, cmath.asin(1j) = 0.88137358701954283j, which
is correct.
msg74920 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2008-10-17 15:53
I'm pretty sure that Python 2.6 is correct and Python 2.5 is wrong.

Python 2.6:
>>> cmath.asin(2.0)
(1.5707963267948966+1.3169578969248166j)
>>> cmath.asin(2.0+(+1E-300j))
(1.5707963267948966+1.3169578969248166j)
>>> cmath.asin(2.0+(-1E-300j))
(1.5707963267948966-1.3169578969248166j)

Python 2.5:
>>> cmath.asin(2.0)
(1.5707963267948966-1.3169578969248166j)
>>> cmath.asin(2.0+(+1E-300j))
(1.5707963267948966+1.3169578969248164j)
>>> cmath.asin(2.0+(-1E-300j))
(1.5707963267948966-1.3169578969248166j)

I used -1E-300j to get value that is almost a negative complex zero.
msg74925 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2008-10-17 17:00
This is not a bug, at least in the sense that the behaviour of Python 
2.6 is intentional:  asin has branch cuts from 1 to infinity and -1 to -
infinity along the real axis.  As explained by the note at the top of 
the cmath documentation, on platforms with signed zeros (which is pretty 
much all platforms these days), the sign of the imaginary part of the 
argument is used to determine which side of the branch cut to use.  So:

>>> import cmath
>>> cmath.asin(complex(2.0, 0.0))
(1.5707963267948966+1.3169578969248166j)
>>> cmath.asin(complex(2.0, -0.0))
(1.5707963267948966-1.3169578969248166j)

This is fairly standard practice, and usually the right thing in 
applications;  see the Kahan paper referred to at the bottom of the 
cmath docs.  It also follows the suggestions outlined in Annex G of the 
C99 standard.
History
Date User Action Args
2022-04-11 14:56:40adminsetgithub: 48389
2008-10-17 17:00:20mark.dickinsonsetstatus: open -> closed
resolution: not a bug
messages: + msg74925
2008-10-17 15:53:20christian.heimessetmessages: + msg74920
2008-10-17 15:44:07christian.heimessetpriority: critical
assignee: mark.dickinson
components: + Extension Modules, - Library (Lib)
versions: + Python 3.0, Python 2.7
2008-10-17 15:17:58benjamin.petersonsetnosy: + mark.dickinson, christian.heimes
2008-10-17 15:16:23thor222settype: behavior
2008-10-17 15:16:04thor222create