<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/78738>78738</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            libc++ complex sqrt gives different result than libstdc++ or C code
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            libc++
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          mppf
      </td>
    </tr>
</table>

<pre>
    On Mac OS X or on Ubuntu 23.10, I see different results from `sqrt` applied to the complex number `-1.0 + 0.0i`. I would expect the result to be `0.0 + 1.0i` but the real portion is ending up as a small but non-zero floating point value. This only seems to occur when using libc++. It does not occur when using libstdc++ or with the equivalent C code.

Here is a C++ reproducer:

``` c++
/*

This program shows a difference in behavior between
libc++'s complex sqrt and libstdc++'s implementation.

$ clang++-17 test.cpp -stdlib=libc++
$ ./a.out
long double: -2.50828e-20
double: 6.12323e-17
float: -4.37114e-08

$ clang++-17 test.cpp
$ ./a.out
long double: 0
double: 0
float: 0

*/

#include <complex>
#include <cmath>
#include <cstdio>

int main(int argc, char** argv) {
 {
    auto c = std::complex<long double>(-1.0, 0.0);
    auto n = std::sqrt(c);
    printf("long double: %g\n", (double) std::real(n));
  }

  {
    auto c = std::complex<double>(-1.0, 0.0);
    auto n = std::sqrt(c);
    printf("double: %g\n", std::real(n));
  }

  {
    auto c = std::complex<float>(-1.0, 0.0);
    auto n = std::sqrt(c);
    printf("float: %g\n", std::real(n));
  }

  return 0;
}
```

I also wrote an equivalent C program and I don't see the issue there on Mac OS X:

``` c
#include <complex.h>
#include <math.h>
#include <stdio.h>

int main(int argc, char** argv) {
  {
    long double complex c = CMPLXL(-1.0, 0.0);
    long double complex n = csqrtl(c);
 printf("long double: %g\n", (double) creall(n));
  }

  {
 double complex c = CMPLX(-1.0, 0.0);
    double complex n = csqrt(c);
 printf("double: %g\n", creal(n));
  }

  {
    float complex c = CMPLXF(-1.0, 0.0);
    float complex n = csqrtf(c);
 printf("float: %g\n", (double) crealf(n));
  }

  return 0;
}
```

(For some reason, on the Ubuntu system, I can't compile this C program with clang; I get errors about `CMPLX` being undeclared. However, that is a different issue).

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0Vl2PmzgU_TXOy1WQMSGQhzzMZBp1pFZdaXelvhpzA14Zm9omaffXr2yYSZiZRG1XI0UB4ft17HuuD3dONhpxS_J7kj8s-OBbY7dd3x8Wlal_bL9o-MwFfPkTvoKxYDT8XQ3aD8CyJKWE7eARHCLU8nBAi9qDRTco7-BgTQdkTd0368maAu97JbEGb8C3CMJ0vcLvoIeuQhsMl2lCgbB7oAmVZE0TeISTGVQN-L1H4aPbGD0EqTA40cknHX2gGp7suILeWC-NBukAdS11A0MP3AEH13GlorE2evkvWgMHZbgPNr2R2sORqwET-KuVDoxWPwLKzoXERojBwqlFDYMLDkpWgrB7wu4TePRQG3SgjX_T0Pl6sg3beZK-jeXit0EeuQr7twNhakwIfSD0bvz_iBYDCA67yddib009CLQku7s0JWs6_mBKM31me8JmhhFYb01jeQeuNacQ_ukUBYLUUGHLj9JYqNCfEPXoeEZLWOGezzEcM3Bdz0FGExksOtSeh9OYISNsBUJx3Yzmy7QAj84nou9h6XytZEWyh4uUz14JYXuemMFPVRndQG2GSiHJ7mDJkpyWrMQlo6PBeW2dpCxjGS7TYlyKJx-9VklWpOkKl7T8ySp_tqBXVdAXuek8YTyx2ZdMaqGGGoFku2nTSfbhzdWO-_bamvO1NOfF-B_6veNSE1aGV24bEZgtWm5jJXfh05GwDZBiOoKLNwDggzcggGQP4HwdWjK7e65xN9uKD4SVgekhAQ2PDcleRtLzSHGCsFK8tO2t1P5AWEkYe7HdhOUNyXeaMBYSEVZOa2xzjhtmBGGlDnFnoUnxcLk98Ctg3xnnVYjvi2pq03cC9UyC_4_Joh-sBvpsc7Z4moyXDo_AlTNwssYjcD2fw0_TMUy1R6iNJqzw8bYLI1s6N8Q3i-FafLolb8zj60ROrtE1MPnqYqTy5epvk3neChdceh7vY2fsPv_x6eun203wlvfYEyL0gnrVDL9JYxGa4pc7_Tqs26iuA7qJ5yoU8Zs0jVR5q_z97frnfhflH27Wf42Zr0_i8C78JKzcGwvOdFHSucDBXaBbYOCkRN0P57EbpajgI0kDUKkCPaW7YHLUW-NNnt3DIzToAa011gGvzOCDohybIUhJjIpR1ygUt1gn8NGc8Ig2pPIt96MkOyvfOBEI20wKZ1Fvs3qTbfgCt2lB83WxKYty0W5XAkVF06KuOEtZmWerXNSlWNXrfFNtymwht4yyFU3TTZrnRV4mhzXjgrF1Vub0QPmarCh2XKpEqWOXGNssYu5tURZZuVC8QuWipGfsUq6xIPHtNjgtq6FxZEWVdN6dw3jpFW7PPnN518gjuldSP-yFfq1tRx27GKzatt73LgzGoEL3jfTtUCXCdITtQ-bpseyt-QeFJ2wf0TjC9hHQfwEAAP__iDaWNQ">