rwindowsmacoshyperbolic-function

Hyperbolic Tangent in R throws NAN in Windows but not in Mac?


When estimating the hyperbolic tangent in Windows using the R base function tanh for large (real, with 0 imaginary part) values the function returns 'NaN':

tanh(356 + 0i)
> NaN + 0i

However, in Mac the same value returns 1 (coinciding with the "real" mathematical value should be close to 1):

tanh(356 + 0i)
> 1 + 0i

Question 1: Does anybody have a clue on why is this happening?

Extra info

This seems not a floating point problem because it seems that Mac's tanh returns 1 for arbitrarily large values:

tanh(999999677873648767519238192348124812341234182374817239847812738481234871823+0i)
> 1 + 0i

The problem seems to be related with the imaginary part as:

tanh(356)
> 1

in both Windows and Mac. The issue seems to be system (or processor?)-specific as we have tried it in:

These Windows machines throw NaN, the Mac's 1 + 0i. In all cases we are using R version 3.3.3 the "newest" (64 bit).


Solution

  • @Ben Bolker is right on spot. Windows uses somewhat old C libraries, and here it is the "mathlib" part of glibc.

    More specifically, according to the CRAN download page for R-devel for Windows https://cran.r-project.org/bin/windows/base/rdevel.html , the R 3.3.z series uses the gcc 4.6.3 (March 2012) toolchain, whereas "R-devel", the upcoming (not yet released!) R 3.4.z series uses the gcc 4.9.3 (June 2015) toolchain.

    **However* I've just checked (installed the R-devel binary from CRAN on our Windows server virtual machine) and I see that the problem is still present there: In yesterday's version of R-devel, tanh(500+0i) still returns NaN+0i.

    I now think a better solution would be to use R's internal substitute (in R's src/main/complex.c): We have

    #ifndef HAVE_CTANH
    #define ctanh R_ctanh
    static double complex ctanh(double complex z)
    {
        return -I * ctan(z * I); /* A&S 4.5.9 */
    }
    #endif
    

    and we should use it, as I see that indeed, also on Windows,

    R> -1i * tan((500+0i)*1i)
    

    gives

    [1] 1+0i
    

    as it should for tanh(500+0i) --- but does not on Windows.