[Bug libstdc++/89991] Complex numbers: Calculation of imaginary part is not correct

sgk at troutmask dot apl.washington.edu gcc-bugzilla@gcc.gnu.org
Mon Apr 8 14:32:00 GMT 2019


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89991

--- Comment #10 from Steve Kargl <sgk at troutmask dot apl.washington.edu> ---
On Mon, Apr 08, 2019 at 09:59:22AM +0000, redi at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89991
> 
> --- Comment #7 from Jonathan Wakely <redi at gcc dot gnu.org> ---
> I think it's allowed. The standards have very little to say about accuracy of
> any mathematical functions, and complex<double>(0, 0.0) == complex<double>(0,
> -0.0) is true according to the standard, because +0.0 == -0.0 is true.
> 


I don't have a copy of the C++ standard, so take this specualtion.
pow(z,0.5) is equivalent to sqrt(z).  From the C standard, one has

conj(csqrt(z)) = csqrt(conj(z)).

g++ does not enforce this when the imaginary part is -0;
while gcc does.

% cat c.c
#include <complex.h>
#include <stdio.h>

int
main(void)
{
   double complex z, t0, t1, t2, t3;

   z = CMPLX(-1.8425031517782417e-07, -0.0);
   t0 = cpow(z, 0.5);
   t1 = csqrt(z);
   t2 = csqrt(conj(z));
   t3 = conj(csqrt(z));
   printf("             z = CMPLX(% .16le, % .16le)\n", creal(z), cimag(z));
   printf("  cpow(z, 0.5) = CMPLX(% .16le, % .16le)\n", creal(t0), cimag(t0));
   printf("      csqrt(z) = CMPLX(% .16le, % .16le)\n", creal(t1), cimag(t1));
   printf("csqrt(conj(z)) = CMPLX(% .16le, % .16le)\n", creal(t2), cimag(t2));
   printf("conj(csqrt(z)) = CMPLX(% .16le, % .16le)\n", creal(t3), cimag(t3));
   return 0;
}
% gcc8 -o z c.c -lm && ./z
             z = CMPLX(-1.8425031517782417e-07, -0.0000000000000000e+00)
  cpow(z, 0.5) = CMPLX( 2.6283607659835831e-20, -4.2924388775825818e-04)
      csqrt(z) = CMPLX( 0.0000000000000000e+00, -4.2924388775825818e-04)
csqrt(conj(z)) = CMPLX( 0.0000000000000000e+00,  4.2924388775825818e-04)
conj(csqrt(z)) = CMPLX( 0.0000000000000000e+00,  4.2924388775825818e-04)


mobile:kargl[210] cat a.cpp
#include <complex>
#include <iomanip>
#include <iostream>

int
main(int argc, char *argv[])
{
   std::complex<double> z, t0, t1, t2, t3;
   z  = std::complex<double>(-1.8425031517782417e-07, -0.0);
   t0 = std::pow(z, 0.5);
   t1 = std::sqrt(z);
   t2 = std::sqrt(std::conj(z));
   t3 = std::conj(std::sqrt(z));
   std::cout << "            z = " << std::setprecision(15) << z  << std::endl;
   std::cout << "   pow(z,0.5) = " << std::setprecision(15) << t0 << std::endl;
   std::cout << "      sqrt(z) = " << std::setprecision(15) << t1 << std::endl;
   std::cout << "sqrt(conj(z)) = " << std::setprecision(15) << t2 << std::endl;
   std::cout << "conj(sqrt(z)) = " << std::setprecision(15) << t3 << std::endl;
   return 0;
}

%  g++8 -o z  a.cpp -lm && ./z
            z = (-1.84250315177824e-07,-0)
   pow(z,0.5) = (2.62836076598358e-20,-0.000429243887758258)
      sqrt(z) = (0,0.000429243887758258)
sqrt(conj(z)) = (0,0.000429243887758258)
conj(sqrt(z)) = (0,-0.000429243887758258)

This looks wrong.


More information about the Gcc-bugs mailing list