(root)/
glibc-2.38/
sysdeps/
ieee754/
ldbl-128/
s_tanhl.c
       1  /* s_tanhl.c -- long double version of s_tanh.c.
       2   */
       3  
       4  /*
       5   * ====================================================
       6   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
       7   *
       8   * Developed at SunPro, a Sun Microsystems, Inc. business.
       9   * Permission to use, copy, modify, and distribute this
      10   * software is freely granted, provided that this notice
      11   * is preserved.
      12   * ====================================================
      13   */
      14  
      15  /* tanhl(x)
      16   * Return the Hyperbolic Tangent of x
      17   *
      18   * Method :
      19   *                                      x    -x
      20   *                                     e  - e
      21   *      0. tanhl(x) is defined to be -----------
      22   *                                      x    -x
      23   *                                     e  + e
      24   *      1. reduce x to non-negative by tanhl(-x) = -tanhl(x).
      25   *      2.  0      <= x <= 2**-57 : tanhl(x) := x*(one+x)
      26   *                                               -t
      27   *          2**-57 <  x <=  1     : tanhl(x) := -----; t = expm1l(-2x)
      28   *                                              t + 2
      29   *                                                    2
      30   *          1      <= x <=  40.0  : tanhl(x) := 1-  ----- ; t=expm1l(2x)
      31   *                                                  t + 2
      32   *          40.0   <  x <= INF    : tanhl(x) := 1.
      33   *
      34   * Special cases:
      35   *      tanhl(NaN) is NaN;
      36   *      only tanhl(0)=0 is exact for finite argument.
      37   */
      38  
      39  #include <float.h>
      40  #include <math.h>
      41  #include <math_private.h>
      42  #include <math-underflow.h>
      43  #include <libm-alias-ldouble.h>
      44  
      45  static const _Float128 one = 1.0, two = 2.0, tiny = L(1.0e-4900);
      46  
      47  _Float128
      48  __tanhl (_Float128 x)
      49  {
      50    _Float128 t, z;
      51    uint32_t jx, ix;
      52    ieee854_long_double_shape_type u;
      53  
      54    /* Words of |x|. */
      55    u.value = x;
      56    jx = u.parts32.w0;
      57    ix = jx & 0x7fffffff;
      58    /* x is INF or NaN */
      59    if (ix >= 0x7fff0000)
      60      {
      61        /* for NaN it's not important which branch: tanhl(NaN) = NaN */
      62        if (jx & 0x80000000)
      63  	return one / x - one;	/* tanhl(-inf)= -1; */
      64        else
      65  	return one / x + one;	/* tanhl(+inf)=+1 */
      66      }
      67  
      68    /* |x| < 40 */
      69    if (ix < 0x40044000)
      70      {
      71        if (u.value == 0)
      72  	return x;		/* x == +- 0 */
      73        if (ix < 0x3fc60000)	/* |x| < 2^-57 */
      74  	{
      75  	  math_check_force_underflow (x);
      76  	  return x * (one + tiny); /* tanh(small) = small */
      77  	}
      78        u.parts32.w0 = ix;	/* Absolute value of x.  */
      79        if (ix >= 0x3fff0000)
      80  	{			/* |x| >= 1  */
      81  	  t = __expm1l (two * u.value);
      82  	  z = one - two / (t + two);
      83  	}
      84        else
      85  	{
      86  	  t = __expm1l (-two * u.value);
      87  	  z = -t / (t + two);
      88  	}
      89        /* |x| > 40, return +-1 */
      90      }
      91    else
      92      {
      93        z = one - tiny;		/* raised inexact flag */
      94      }
      95    return (jx & 0x80000000) ? -z : z;
      96  }
      97  libm_alias_ldouble (__tanh, tanh)