std::log
misspecified for complex numbersSection: 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 x
is 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 + 0i) = +π
, but log(x - 0i) = -π
, 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 + 0i
and x - 0i
, 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 log
appropriately. For example: "When x
is a negative real number,
imag(log(x + 0i))
is π
, and imag(log(x - 0i))
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 bothstd::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<class T> complex<T> log(const complex<T>& x);-16- Remarks: The branch cuts are along the negative real axis.
-17- Returns: The complex natural (base-ℯ) logarithm ofx
. For allx
,imag(log(x))
lies in the interval[
-π, π]
, and when. [Note: The semantics ofx
is a negative real number,imag(log(x))
is πstd::log
are intended to be the same in C++ as they are forclog
in C. — end note]Change the "returns" element for
std::sqrt
(29.4.8 [complex.transcendentals] p25):template<class T> complex<T> sqrt(const complex<T>& x);-24- Remarks: The branch cuts are along the negative real axis.
-25- Returns: The complex square root ofx
, 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::sqrt
are intended to be the same in C++ as they are forcsqrt
in 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<class T> complex<T> log(const complex<T>& x);-16- Remarks: The branch cuts are along the negative real axis.
-17- Returns: The complex natural (base-ℯ) logarithm ofx
. 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 forx
is a negative real number,imag(log(x))
is πclog
in C. — end note]
Change the "returns" element for std::sqrt
(29.4.8 [complex.transcendentals] p25):
template<class T> complex<T> sqrt(const complex<T>& x);-24- Remarks: The branch cuts are along the negative real axis.
-25- Returns: The complex square root ofx
, 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 forcsqrt
in C. — end note]