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

--- Comment #18 from Steve Kargl <sgk at troutmask dot apl.washington.edu> ---
On Mon, Apr 08, 2019 at 08:03:36PM +0000, pinskia at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89991
> 
> --- Comment #17 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
> >Doesn't this gets the wrong answer for __y = -0 (as -0 < 0 is false)?
> 
> No, you missed this part:
> //                     The branch cut is on the negative axis.

No, I didn't miss that part.

> So maybe the bug is inside FreeBSD and Window's libm.  Glibc fixed the branch
> cuts issues back in 2012 for csqrt but the other OS's did not change theirs.

For the C++ code in comment, on x86_64-*-freebsd.

% 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)

The last two lines are definitely wrong.

troutmask:sgk[209] nm z | grep csqrt
troutmask:sgk[210] nm z | grep sqrt
000000000040156b W _ZSt14__complex_sqrtIdESt7complexIT_ERKS2_
000000000040143d W _ZSt4sqrtIdESt7complexIT_ERKS2_
                 U sqrt@@FBSD_1.0

There is no reference to csqrt in the exectuable.  If I change
/usr/local/lib/gcc8/include/c++/complex to use copysign
to account for __y = -0 like

  template<typename _Tp>
    complex<_Tp>
    __complex_sqrt(const complex<_Tp>& __z)
    {
      _Tp __x = __z.real();
      _Tp __y = __z.imag();

      if (__x == _Tp())
        {
          _Tp __t = sqrt(abs(__y) / 2);
//          return complex<_Tp>(__t, __y < _Tp() ? -__t : __t);
          return complex<_Tp>(__t, copysign(__t, __y));
        }
      else
        {
          _Tp __t = sqrt(2 * (std::abs(__z) + abs(__x)));
          _Tp __u = __t / 2;
//          return __x > _Tp()
//            ? complex<_Tp>(__u, __y / __t)
//            : complex<_Tp>(abs(__y) / __t, __y < _Tp() ? -__u : __u);
          return __x > _Tp()
            ? complex<_Tp>(__u, __y / __t)
            : complex<_Tp>(abs(__y) / __t, copysign(__u, __y));
        }
    }


The C++ code in comment #10 gives

 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)

The correct answer.  QED.

Reply via email to