Coverage Report

Created: 2025-08-03 06:59

/src/moddable/xs/tools/fdlibm/s_tanh.c
Line
Count
Source
1
/*
2
 * ====================================================
3
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4
 *
5
 * Developed at SunPro, a Sun Microsystems, Inc. business.
6
 * Permission to use, copy, modify, and distribute this
7
 * software is freely granted, provided that this notice
8
 * is preserved.
9
 * ====================================================
10
 */
11
12
/* Tanh(x)
13
 * Return the Hyperbolic Tangent of x
14
 *
15
 * Method :
16
 *               x    -x
17
 *              e  - e
18
 *  0. tanh(x) is defined to be -----------
19
 *               x    -x
20
 *              e  + e
21
 *  1. reduce x to non-negative by tanh(-x) = -tanh(x).
22
 *  2.  0      <= x <  2**-28 : tanh(x) := x with inexact if x != 0
23
 *                  -t
24
 *      2**-28 <= x <  1      : tanh(x) := -----; t = expm1(-2x)
25
 *                 t + 2
26
 *                 2
27
 *      1      <= x <  22     : tanh(x) := 1 - -----; t = expm1(2x)
28
 *               t + 2
29
 *      22     <= x <= INF    : tanh(x) := 1.
30
 *
31
 * Special cases:
32
 *  tanh(NaN) is NaN;
33
 *  only tanh(0)=0 is exact for finite argument.
34
 */
35
36
#include "math_private.h"
37
38
static const volatile double tiny = 1.0e-300;
39
static const double one = 1.0, two = 2.0, huge = 1.0e300;
40
41
double
42
s_tanh(double x)
43
3.46k
{
44
3.46k
  double t,z;
45
3.46k
  int32_t jx,ix;
46
47
3.46k
  GET_HIGH_WORD(jx,x);
48
3.46k
  ix = jx&0x7fffffff;
49
50
    /* x is INF or NaN */
51
3.46k
  if(ix>=0x7ff00000) {
52
869
      if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
53
686
      else       return one/x-one;    /* tanh(NaN) = NaN */
54
869
  }
55
56
    /* |x| < 22 */
57
2.60k
  if (ix < 0x40360000) {   /* |x|<22 */
58
2.29k
      if (ix<0x3e300000) { /* |x|<2**-28 */
59
222
    if(huge+x>one) return x; /* tanh(tiny) = tiny with inexact */
60
222
      }
61
2.07k
      if (ix>=0x3ff00000) { /* |x|>=1  */
62
392
    t = s_expm1(two*fabs(x));
63
392
    z = one - two/(t+two);
64
1.68k
      } else {
65
1.68k
          t = s_expm1(-two*fabs(x));
66
1.68k
          z= -t/(t+two);
67
1.68k
      }
68
    /* |x| >= 22, return +-1 */
69
2.07k
  } else {
70
306
      z = one - tiny;   /* raise inexact flag */
71
306
  }
72
2.37k
  return (jx>=0)? z: -z;
73
2.60k
}