Title
std::log misspecified for complex numbers
Status
c++20
Section
[complex.transcendentals]
Submitter
Thomas Koeppe

Created on 2016-03-01.00:00:00 last changed 38 months ago

Messages

Date: 2017-03-14.03:14:09

Proposed resolution:

This wording is relative to N4606.

  1. Change the "returns" element for std::log ([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 of x. For all x, imag(log(x)) lies in the interval [-π, π], and when x is a negative real number, imag(log(x)) is π. [Note: the semantics of this function are intended to be the same in C++ as they are for clog in C. — end note]

  2. Change the "returns" element for std::sqrt ([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 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 for csqrt in C. — end note]

Date: 2017-03-15.00:00:00

[ 2017-03-04, Kona ]

Minor wording update and status to Tentatively Ready.

Previous resolution [SUPERSEDED]:

This wording is relative to N4606.

  1. Change the "returns" element for std::log ([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 of x. For all x, imag(log(x)) lies in the interval [-π, π], and when x is a negative real number, imag(log(x)) is π. [Note: The semantics of std::log are intended to be the same in C++ as they are for clog in C. — end note]

  2. Change the "returns" element for std::sqrt ([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 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 std::sqrt are intended to be the same in C++ as they are for csqrt in C. — end note]

Date: 2016-11-15.00:00:00

[ 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.

Date: 2016-11-15.00:00:00

[ 2016-11-12, Issaquah ]

Move to Open - Thomas to provide wording

Date: 2016-03-01.00:00:00

The current specification of std::log is inconsistent for complex numbers, specifically, the Returns clause ([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:

  1. 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++.

  2. 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)

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2017-07-30 20:18:47adminsetstatus: voting -> wp
2017-06-26 13:46:20adminsetstatus: ready -> voting
2017-03-14 03:14:09adminsetmessages: + msg9103
2017-03-14 03:14:09adminsetstatus: open -> ready
2016-11-26 20:26:30adminsetmessages: + msg8690
2016-11-26 20:26:30adminsetmessages: + msg8689
2016-11-21 05:09:01adminsetmessages: + msg8658
2016-11-21 05:09:01adminsetstatus: new -> open
2016-03-01 00:00:00admincreate