<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2597: std::log misspecified for complex numbers</title>
<meta property="og:title" content="Issue 2597: std::log misspecified for complex numbers">
<meta property="og:description" content="C++ library issue. Status: C++20">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2597.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++20">C++20</a> status.</em></p>
<h3 id="2597"><a href="lwg-defects.html#2597">2597</a>. <code>std::log</code> misspecified for complex numbers</h3>
<p><b>Section:</b> 29.4.8 <a href="https://wg21.link/complex.transcendentals">[complex.transcendentals]</a> <b>Status:</b> <a href="lwg-active.html#C++20">C++20</a>
 <b>Submitter:</b> Thomas Koeppe <b>Opened:</b> 2016-03-01 <b>Last modified:</b> 2021-02-25</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="lwg-index.html#complex.transcendentals">issues</a> in [complex.transcendentals].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++20">C++20</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The current specification of <code>std::log</code> is inconsistent for complex numbers, specifically, the Returns clause 
(29.4.8 <a href="https://wg21.link/complex.transcendentals">[complex.transcendentals]</a>). On the one hand, it states that the imaginary part of the return value lies 
in the <em>closed</em> interval <code>[-<i>i</i> &pi;, +<i>i</i> &pi;]</code>. On the other hand, it says that "the branch 
cuts are along the negative real axis" and "the imaginary part of <code>log(x)</code> is <code>+&pi;</code> when <code>x</code> 
is a negative real number".
</p>
<p>
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 <code>x</code> is a real 
number, then <code>log(x + 0<i>i</i>) = +&pi;</code>, but <code>log(x - 0<i>i</i>) = -&pi;</code>, 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 <em>two distinct</em> real numbers, 
<code>x + 0<i>i</i></code> and <code>x - 0<i>i</i></code>, that compare equal but whose logarithms differ by <code>2 &pi; <i>i</i></code>.
</p>
<p>
The resolution should consist of two parts:
</p>
<ol>
<li><p>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++.</p></li>
<li><p>Change the Returns clause of <code>log</code> appropriately. For example: "When <code>x</code> is a negative real number, 
<code>imag(log(x + 0<i>i</i>))</code> is <code>&pi;</code>, and <code>imag(log(x - 0<i>i</i>))</code> is <code>-&pi;</code>."</p></li>
</ol>
<p>
Current implementations seem to behave as described in (2). 
(<a href="http://melpon.org/wandbox/permlink/pwBDeGiY3HDtFAh8">Try-it-at-home link</a>)
</p>

<p><i>[2016-11-12, Issaquah]</i></p>

<p>Move to Open - Thomas to provide wording</p>

<p><i>[2016-11-15, Thomas comments and provides wording]</i></p>

<p>
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.
<p/>
The change applies to both <code>std::log</code> and <code>std::sqrt</code>.
<p/>
Updated try-at-home link, see <a href="http://melpon.org/wandbox/permlink/tVYVUNfeZ1yoFnp8">here</a>.
</p>

<p><i>[2017-03-04, Kona]</i></p>

<p>Minor wording update and status to Tentatively Ready.</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<p>
This wording is relative to N4606.
</p>
<ol>
<li><p>Change the "returns" element for <code>std::log</code> (29.4.8 <a href="https://wg21.link/complex.transcendentals">[complex.transcendentals]</a> p17):</p>

<blockquote>
<pre>
template&lt;class T&gt; complex&lt;T&gt; log(const complex&lt;T&gt;&amp; x);
</pre>
<blockquote>
<p>
-16- <i>Remarks:</i> The branch cuts are along the negative real axis.
<p/>
-17- <i>Returns:</i> The complex natural (base-&#8495;) logarithm of <code>x</code>. For all <code>x</code>, <code>imag(log(x))</code> 
lies in the interval <code>[</code>-&pi;, &pi;<code>]</code><del>, and when <code>x</code> is a negative real number, <code>imag(log(x))</code> 
is &pi;</del>. <ins>[<i>Note:</i> The semantics of <code>std::log</code> are intended to be the same in C++ as they are for 
<code>clog</code> in C. &mdash; <i>end note</i>]</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Change the "returns" element for <code>std::sqrt</code> (29.4.8 <a href="https://wg21.link/complex.transcendentals">[complex.transcendentals]</a> p25):</p>

<blockquote>
<pre>
template&lt;class T&gt; complex&lt;T&gt; sqrt(const complex&lt;T&gt;&amp; x);
</pre>
<blockquote>
<p>
-24- <i>Remarks:</i> The branch cuts are along the negative real axis.
<p/>
-25- <i>Returns:</i> The complex square root of <code>x</code>, in the range of the right half-plane. <del>If the argument is a
negative real number, the value returned lies on the positive imaginary axis.</del><ins>[<i>Note:</i> The semantics of 
<code>std::sqrt</code> are intended to be the same in C++ as they are for <code>csqrt</code> in C. &mdash; <i>end note</i>]</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>
</blockquote>


<p id="res-2597"><b>Proposed resolution:</b></p>
<p>
This wording is relative to N4606.
</p>
<ol>
<li><p>Change the "returns" element for <code>std::log</code> (29.4.8 <a href="https://wg21.link/complex.transcendentals">[complex.transcendentals]</a> p17):</p>

<blockquote>
<pre>
template&lt;class T&gt; complex&lt;T&gt; log(const complex&lt;T&gt;&amp; x);
</pre>
<blockquote>
<p>
-16- <i>Remarks:</i> The branch cuts are along the negative real axis.
<p/>
-17- <i>Returns:</i> The complex natural (base-&#8495;) logarithm of <code>x</code>. For all <code>x</code>, <code>imag(log(x))</code> 
lies in the interval <code>[</code>-&pi;, &pi;<code>]</code><del>, and when <code>x</code> is a negative real number, <code>imag(log(x))</code> 
is &pi;</del>. <ins>[<i>Note:</i> the semantics of this function are intended to be the same in C++ as they are for 
<code>clog</code> in C. &mdash; <i>end note</i>]</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Change the "returns" element for <code>std::sqrt</code> (29.4.8 <a href="https://wg21.link/complex.transcendentals">[complex.transcendentals]</a> p25):</p>

<blockquote>
<pre>
template&lt;class T&gt; complex&lt;T&gt; sqrt(const complex&lt;T&gt;&amp; x);
</pre>
<blockquote>
<p>
-24- <i>Remarks:</i> The branch cuts are along the negative real axis.
<p/>
-25- <i>Returns:</i> The complex square root of <code>x</code>, in the range of the right half-plane. <del>If the argument is a
negative real number, the value returned lies on the positive imaginary axis.</del><ins>[<i>Note:</i> The semantics of 
this function are intended to be the same in C++ as they are for <code>csqrt</code> in C. &mdash; <i>end note</i>]</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>





</body>
</html>
