tanhq.c 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* s_tanhl.c -- long double version of s_tanh.c.
  2. * Conversion to long double by Ulrich Drepper,
  3. * Cygnus Support, drepper@cygnus.com.
  4. */
  5. /*
  6. * ====================================================
  7. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  8. *
  9. * Developed at SunPro, a Sun Microsystems, Inc. business.
  10. * Permission to use, copy, modify, and distribute this
  11. * software is freely granted, provided that this notice
  12. * is preserved.
  13. * ====================================================
  14. */
  15. /* Changes for 128-bit long double contributed by
  16. Stephen L. Moshier <moshier@na-net.ornl.gov> */
  17. /* tanhq(x)
  18. * Return the Hyperbolic Tangent of x
  19. *
  20. * Method :
  21. * x -x
  22. * e - e
  23. * 0. tanhq(x) is defined to be -----------
  24. * x -x
  25. * e + e
  26. * 1. reduce x to non-negative by tanhq(-x) = -tanhq(x).
  27. * 2. 0 <= x <= 2**-57 : tanhq(x) := x*(one+x)
  28. * -t
  29. * 2**-57 < x <= 1 : tanhq(x) := -----; t = expm1q(-2x)
  30. * t + 2
  31. * 2
  32. * 1 <= x <= 40.0 : tanhq(x) := 1- ----- ; t=expm1q(2x)
  33. * t + 2
  34. * 40.0 < x <= INF : tanhq(x) := 1.
  35. *
  36. * Special cases:
  37. * tanhq(NaN) is NaN;
  38. * only tanhq(0)=0 is exact for finite argument.
  39. */
  40. #include "quadmath-imp.h"
  41. static const __float128 one = 1.0, two = 2.0, tiny = 1.0e-4900Q;
  42. __float128
  43. tanhq (__float128 x)
  44. {
  45. __float128 t, z;
  46. uint32_t jx, ix;
  47. ieee854_float128 u;
  48. /* Words of |x|. */
  49. u.value = x;
  50. jx = u.words32.w0;
  51. ix = jx & 0x7fffffff;
  52. /* x is INF or NaN */
  53. if (ix >= 0x7fff0000)
  54. {
  55. /* for NaN it's not important which branch: tanhq(NaN) = NaN */
  56. if (jx & 0x80000000)
  57. return one / x - one; /* tanhq(-inf)= -1; */
  58. else
  59. return one / x + one; /* tanhq(+inf)=+1 */
  60. }
  61. /* |x| < 40 */
  62. if (ix < 0x40044000)
  63. {
  64. if (u.value == 0)
  65. return x; /* x == +- 0 */
  66. if (ix < 0x3fc60000) /* |x| < 2^-57 */
  67. {
  68. math_check_force_underflow (x);
  69. return x * (one + tiny); /* tanh(small) = small */
  70. }
  71. u.words32.w0 = ix; /* Absolute value of x. */
  72. if (ix >= 0x3fff0000)
  73. { /* |x| >= 1 */
  74. t = expm1q (two * u.value);
  75. z = one - two / (t + two);
  76. }
  77. else
  78. {
  79. t = expm1q (-two * u.value);
  80. z = -t / (t + two);
  81. }
  82. /* |x| > 40, return +-1 */
  83. }
  84. else
  85. {
  86. z = one - tiny; /* raised inexact flag */
  87. }
  88. return (jx & 0x80000000) ? -z : z;
  89. }