(root)/
glibc-2.38/
sysdeps/
ieee754/
dbl-64/
s_tanh.c
       1  /* @(#)s_tanh.c 5.1 93/09/24 */
       2  /*
       3   * ====================================================
       4   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
       5   *
       6   * Developed at SunPro, a Sun Microsystems, Inc. business.
       7   * Permission to use, copy, modify, and distribute this
       8   * software is freely granted, provided that this notice
       9   * is preserved.
      10   * ====================================================
      11   */
      12  
      13  #if defined(LIBM_SCCS) && !defined(lint)
      14  static char rcsid[] = "$NetBSD: s_tanh.c,v 1.7 1995/05/10 20:48:22 jtc Exp $";
      15  #endif
      16  
      17  /* Tanh(x)
      18   * Return the Hyperbolic Tangent of x
      19   *
      20   * Method :
      21   *				       x    -x
      22   *				      e  - e
      23   *	0. tanh(x) is defined to be -----------
      24   *				       x    -x
      25   *				      e  + e
      26   *	1. reduce x to non-negative by tanh(-x) = -tanh(x).
      27   *	2.  0      <= x <= 2**-55 : tanh(x) := x*(one+x)
      28   *					        -t
      29   *	    2**-55 <  x <=  1     : tanh(x) := -----; t = expm1(-2x)
      30   *					       t + 2
      31   *						     2
      32   *	    1      <= x <=  22.0  : tanh(x) := 1-  ----- ; t=expm1(2x)
      33   *						   t + 2
      34   *	    22.0   <  x <= INF    : tanh(x) := 1.
      35   *
      36   * Special cases:
      37   *	tanh(NaN) is NaN;
      38   *	only tanh(0)=0 is exact for finite argument.
      39   */
      40  
      41  #include <float.h>
      42  #include <math.h>
      43  #include <math_private.h>
      44  #include <math-underflow.h>
      45  #include <libm-alias-double.h>
      46  
      47  static const double one = 1.0, two = 2.0, tiny = 1.0e-300;
      48  
      49  double
      50  __tanh (double x)
      51  {
      52    double t, z;
      53    int32_t jx, ix, lx;
      54  
      55    /* High word of |x|. */
      56    EXTRACT_WORDS (jx, lx, x);
      57    ix = jx & 0x7fffffff;
      58  
      59    /* x is INF or NaN */
      60    if (ix >= 0x7ff00000)
      61      {
      62        if (jx >= 0)
      63  	return one / x + one;               /* tanh(+-inf)=+-1 */
      64        else
      65  	return one / x - one;               /* tanh(NaN) = NaN */
      66      }
      67  
      68    /* |x| < 22 */
      69    if (ix < 0x40360000)                  /* |x|<22 */
      70      {
      71        if ((ix | lx) == 0)
      72  	return x;                       /* x == +-0 */
      73        if (ix < 0x3c800000)              /* |x|<2**-55 */
      74  	{
      75  	  math_check_force_underflow (x);
      76  	  return x * (one + x);           /* tanh(small) = small */
      77  	}
      78        if (ix >= 0x3ff00000)             /* |x|>=1  */
      79  	{
      80  	  t = __expm1 (two * fabs (x));
      81  	  z = one - two / (t + two);
      82  	}
      83        else
      84  	{
      85  	  t = __expm1 (-two * fabs (x));
      86  	  z = -t / (t + two);
      87  	}
      88        /* |x| > 22, return +-1 */
      89      }
      90    else
      91      {
      92        z = one - tiny;                   /* raised inexact flag */
      93      }
      94    return (jx >= 0) ? z : -z;
      95  }
      96  libm_alias_double (__tanh, tanh)