Issue 2597: std::log misspecified for complex numbers (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.
2597. std::log misspecified for complex numbers
Section: 29.4.8 [complex.transcendentals] Status: C++20 Submitter: Thomas Koeppe Opened: 2016-03-01 Last modified: 2021-02-25
Priority: 3
View all other issues in [complex.transcendentals].
View all issues with C++20 status.
Discussion:
The current specification of std::log is inconsistent for complex numbers, specifically, the Returns clause (29.4.8 [complex.transcendentals]). On the one hand, it states that the imaginary part of the return value lies in the closed interval [-_i_ π, +_i_ π]. On the other hand, it says that "the branch cuts are along the negative real axis" and "the imaginary part of log(x) is +π when xis a negative real number".
The inconsistency lies in the difference between the mathematical concept of a branch cut and the nature of floating point numbers in C++. The corresponding specification in the C standard makes it clearer that if x is a real number, then log(x + 0_i_) = +π, but log(x - 0_i_) = -π, i.e. they consider positive and negative zero to represent the two different limits of approaching the branch cut from opposite directions. In other words, the term "negative real number" is misleading, and in fact there are two distinct real numbers, x + 0_i_ and x - 0_i_, that compare equal but whose logarithms differ by 2 π _i_.
The resolution should consist of two parts:
- Double-check that our usage and definition of "branch cut" is sufficiently unambiguous. The C standard contains a lot more wording around this that we don't have in C++.
- Change the Returns clause of
logappropriately. For example: "Whenxis a negative real number,imag(log(x + 0_i_))isπ, andimag(log(x - 0_i_))is-π."
Current implementations seem to behave as described in (2). (Try-it-at-home link)
[2016-11-12, Issaquah]
Move to Open - Thomas to provide wording
[2016-11-15, Thomas comments and provides wording]
Following LWG discussion in Issaquah, I now propose to resolve this issue by removing the normative requirement on the function limits, and instead adding a note that the intention is to match the behaviour of C. This allows implementations to use the behaviour of C without having to specify what floating point numbers really are.
The change applies to both std::log and std::sqrt.
Updated try-at-home link, see here.
[2017-03-04, Kona]
Minor wording update and status to Tentatively Ready.
Previous resolution [SUPERSEDED]:
This wording is relative to N4606.
- Change the "returns" element for
std::log(29.4.8 [complex.transcendentals] p17):template complex log(const complex& x);
-16- Remarks: The branch cuts are along the negative real axis.
-17- Returns: The complex natural (base-ℯ) logarithm of
x. For allx,imag(log(x))lies in the interval[-π, π], and when. [Note: The semantics ofxis a negative real number,imag(log(x))is πstd::logare intended to be the same in C++ as they are forclogin C. — _end note_]- Change the "returns" element for
std::sqrt(29.4.8 [complex.transcendentals] p25):template complex sqrt(const complex& x);
-24- Remarks: The branch cuts are along the negative real axis.
-25- Returns: The complex square root of
x, in the range of the right half-plane.If the argument is a negative real number, the value returned lies on the positive imaginary axis.[Note: The semantics ofstd::sqrtare intended to be the same in C++ as they are forcsqrtin C. — _end note_]
Proposed resolution:
This wording is relative to N4606.
- Change the "returns" element for
std::log(29.4.8 [complex.transcendentals] p17):template complex log(const complex& x);
-16- Remarks: The branch cuts are along the negative real axis.
-17- Returns: The complex natural (base-ℯ) logarithm of
x. For allx,imag(log(x))lies in the interval[-π, π], and when. [Note: the semantics of this function are intended to be the same in C++ as they are forxis a negative real number,imag(log(x))is πclogin C. — _end note_] - Change the "returns" element for
std::sqrt(29.4.8 [complex.transcendentals] p25):template complex sqrt(const complex& x);
-24- Remarks: The branch cuts are along the negative real axis.
-25- Returns: The complex square root of
x, in the range of the right half-plane.If the argument is a negative real number, the value returned lies on the positive imaginary axis.[Note: The semantics of this function are intended to be the same in C++ as they are forcsqrtin C. — _end note_]