atanhl.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /* atanhl.c
  2. *
  3. * Inverse hyperbolic tangent, long double precision
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * long double x, y, atanhl();
  10. *
  11. * y = atanhl( x );
  12. *
  13. *
  14. *
  15. * DESCRIPTION:
  16. *
  17. * Returns inverse hyperbolic tangent of argument in the range
  18. * MINLOGL to MAXLOGL.
  19. *
  20. * If |x| < 0.5, the rational form x + x**3 P(x)/Q(x) is
  21. * employed. Otherwise,
  22. * atanh(x) = 0.5 * log( (1+x)/(1-x) ).
  23. *
  24. *
  25. *
  26. * ACCURACY:
  27. *
  28. * Relative error:
  29. * arithmetic domain # trials peak rms
  30. * IEEE -1,1 30000 1.1e-19 3.3e-20
  31. *
  32. */
  33. /*
  34. Cephes Math Library Release 2.7: May, 1998
  35. Copyright (C) 1987, 1991, 1998 by Stephen L. Moshier
  36. */
  37. #include <math.h>
  38. #ifdef UNK
  39. static long double P[] = {
  40. 2.9647757819596835680719E-3L,
  41. -8.0026596513099094380633E-1L,
  42. 7.7920941408493040219831E0L,
  43. -2.4330686602187898836837E1L,
  44. 3.0204265014595622991082E1L,
  45. -1.2961142942114056581210E1L,
  46. };
  47. static long double Q[] = {
  48. /* 1.0000000000000000000000E0L,*/
  49. -1.3729634163247557081869E1L,
  50. 6.2320841104088512332185E1L,
  51. -1.2469344457045341444078E2L,
  52. 1.1394285233959210574352E2L,
  53. -3.8883428826342169425890E1L,
  54. };
  55. #endif
  56. #ifdef IBMPC
  57. static short P[] = {
  58. 0x3aa2,0x036b,0xaf06,0xc24c,0x3ff6, XPD
  59. 0x528e,0x56e8,0x3af4,0xccde,0xbffe, XPD
  60. 0x9d89,0xc9a1,0xd5cf,0xf958,0x4001, XPD
  61. 0xa653,0x6cfa,0x3f04,0xc2a5,0xc003, XPD
  62. 0xc651,0x2b3d,0x55b2,0xf1a2,0x4003, XPD
  63. 0xd76d,0xf293,0xd76b,0xcf60,0xc002, XPD
  64. };
  65. static short Q[] = {
  66. /*0x0000,0x0000,0x0000,0x8000,0x3fff,*/
  67. 0xd1b9,0x5314,0x94df,0xdbac,0xc002, XPD
  68. 0x3caa,0x0517,0x8a92,0xf948,0x4004, XPD
  69. 0x535e,0xaf5f,0x0b2a,0xf963,0xc005, XPD
  70. 0xa6f9,0xb702,0xbd8a,0xe3e2,0x4005, XPD
  71. 0xe136,0xf5ee,0xa190,0x9b88,0xc004, XPD
  72. };
  73. #endif
  74. #ifdef MIEEE
  75. static long P[] = {
  76. 0x3ff60000,0xc24caf06,0x036b3aa2,
  77. 0xbffe0000,0xccde3af4,0x56e8528e,
  78. 0x40010000,0xf958d5cf,0xc9a19d89,
  79. 0xc0030000,0xc2a53f04,0x6cfaa653,
  80. 0x40030000,0xf1a255b2,0x2b3dc651,
  81. 0xc0020000,0xcf60d76b,0xf293d76d,
  82. };
  83. static long Q[] = {
  84. /*0x3fff0000,0x80000000,0x00000000,*/
  85. 0xc0020000,0xdbac94df,0x5314d1b9,
  86. 0x40040000,0xf9488a92,0x05173caa,
  87. 0xc0050000,0xf9630b2a,0xaf5f535e,
  88. 0x40050000,0xe3e2bd8a,0xb702a6f9,
  89. 0xc0040000,0x9b88a190,0xf5eee136,
  90. };
  91. #endif
  92. extern long double MAXNUML;
  93. #ifdef ANSIPROT
  94. extern long double fabsl ( long double );
  95. extern long double logl ( long double );
  96. extern long double polevll ( long double, void *, int );
  97. extern long double p1evll ( long double, void *, int );
  98. #else
  99. long double fabsl(), logl(), polevll(), p1evll();
  100. #endif
  101. #ifdef INFINITIES
  102. extern long double INFINITYL;
  103. #endif
  104. #ifdef NANS
  105. extern long double NANL;
  106. #endif
  107. long double atanhl(x)
  108. long double x;
  109. {
  110. long double s, z;
  111. #ifdef MINUSZERO
  112. if( x == 0.0L )
  113. return(x);
  114. #endif
  115. z = fabsl(x);
  116. if( z >= 1.0L )
  117. {
  118. if( x == 1.0L )
  119. {
  120. #ifdef INFINITIES
  121. return( INFINITYL );
  122. #else
  123. return( MAXNUML );
  124. #endif
  125. }
  126. if( x == -1.0L )
  127. {
  128. #ifdef INFINITIES
  129. return( -INFINITYL );
  130. #else
  131. return( -MAXNUML );
  132. #endif
  133. }
  134. mtherr( "atanhl", DOMAIN );
  135. #ifdef NANS
  136. return( NANL );
  137. #else
  138. return( MAXNUML );
  139. #endif
  140. }
  141. if( z < 1.0e-8L )
  142. return(x);
  143. if( z < 0.5L )
  144. {
  145. z = x * x;
  146. s = x + x * z * (polevll(z, P, 5) / p1evll(z, Q, 5));
  147. return(s);
  148. }
  149. return( 0.5L * logl((1.0L+x)/(1.0L-x)) );
  150. }