On 2017/3/24 23:08, Jeroen Ooms wrote:
I was able to reproduce the problem on msys2 with gcc 6.3:

  #include <iostream>
  #include <cmath>
  #include <complex>

  int main(){
    std::cout << std::fixed;
    std::complex<double> z(356, 0);
    std::cout << "tanh" << z << " = " << std::tanh(z)
         << " (tanh(356) = " << std::tanh(356) << ")\n";
  }

On Linux / OS-X we get:

  tanh(356.000000,0.000000) = (1.000000,-0.000000) (tanh(356) = 1.000000)

But on Windows we get:

  tanh(356.000000,0.000000) = (nan,0.000000) (tanh(356) = 1.000000)
After a little investigation the problem is located here:

In mingw-w64-crt\complex\ctanh.def.h:

     __FLT_ABI(sincos) (__FLT_CST(2.0) * __imag__ z, &s, &c);

     d = (__FLT_ABI(cosh) (__FLT_CST(2.0) * __real__ z) + c);

     if (d == __FLT_CST(0.0))
     {
       __complex__ __FLT_TYPE ez = __FLT_ABI(cexp) (z);
       __complex__ __FLT_TYPE emz = __FLT_ABI(cexp) (-z);

       return (ez - emz) / (ez + emz);
     }

     __real__ ret = __FLT_ABI(sinh) (__FLT_CST(2.0) * __real__ z) / d;

Given `__real__ z` is 356, `cosh(712)` is called, which yields positive infinity. Since it doesn't compare equal with zero, the `if` branch is not taken and the result of `sinh(712)`, which is also positive infinity, is divided by the previous result, yielding a NaN.

In the code above `ret` is normally set to `sinh(2 * __real__ z) / cosh(2 * __real__ z)`. Acknowledging the fact that both can be NaNs we can replace it with `tanh(2 * __real__ z)` directly ({sin,cos,tan}h functions are part of MSVCRT). The attached patch should fix the problem.

I am not a mathematician, though. So please correct me.

--
Best regards,
LH_Mouse





 From a46cc6ea45467cad2b0669417fdbe7afed78dade Mon Sep 17 00:00:00 2001
From: Liu Hao <[email protected]>
Date: Fri, 24 Mar 2017 23:49:39 +0800
Subject: [PATCH] Quick fix for ctanh() functions.

Signed-off-by: Liu Hao <[email protected]>
---
  mingw-w64-crt/complex/ctanh.def.h | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mingw-w64-crt/complex/ctanh.def.h b/mingw-w64-crt/complex/ctanh.def.h
index 11a18364..c36b75c7 100644
--- a/mingw-w64-crt/complex/ctanh.def.h
+++ b/mingw-w64-crt/complex/ctanh.def.h
@@ -88,7 +88,7 @@ __FLT_ABI(ctanh) (__FLT_TYPE __complex__ z)
      return (ez - emz) / (ez + emz);
    }

-  __real__ ret = __FLT_ABI(sinh) (__FLT_CST(2.0) * __real__ z) / d;
+  __real__ ret = __FLT_ABI(tanh) (__FLT_CST(2.0) * __real__ z);
    __imag__ ret = s / d;
    return ret;
  }
--
2.12.0



From a46cc6ea45467cad2b0669417fdbe7afed78dade Mon Sep 17 00:00:00 2001
From: Liu Hao <[email protected]>
Date: Fri, 24 Mar 2017 23:49:39 +0800
Subject: [PATCH] Quick fix for ctanh() functions.

Signed-off-by: Liu Hao <[email protected]>
---
 mingw-w64-crt/complex/ctanh.def.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mingw-w64-crt/complex/ctanh.def.h 
b/mingw-w64-crt/complex/ctanh.def.h
index 11a18364..c36b75c7 100644
--- a/mingw-w64-crt/complex/ctanh.def.h
+++ b/mingw-w64-crt/complex/ctanh.def.h
@@ -88,7 +88,7 @@ __FLT_ABI(ctanh) (__FLT_TYPE __complex__ z)
     return (ez - emz) / (ez + emz);
   }
 
-  __real__ ret = __FLT_ABI(sinh) (__FLT_CST(2.0) * __real__ z) / d;
+  __real__ ret = __FLT_ABI(tanh) (__FLT_CST(2.0) * __real__ z);
   __imag__ ret = s / d;
   return ret;
 }
-- 
2.12.0

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to