atanh.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /* atanh.c
  2. *
  3. * Inverse hyperbolic tangent
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * double x, y, atanh();
  10. *
  11. * y = atanh( x );
  12. *
  13. *
  14. *
  15. * DESCRIPTION:
  16. *
  17. * Returns inverse hyperbolic tangent of argument in the range
  18. * MINLOG to MAXLOG.
  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. * DEC -1,1 50000 2.4e-17 6.4e-18
  31. * IEEE -1,1 30000 1.9e-16 5.2e-17
  32. *
  33. */
  34. /* atanh.c */
  35. /*
  36. Cephes Math Library Release 2.8: June, 2000
  37. Copyright (C) 1987, 1995, 2000 by Stephen L. Moshier
  38. */
  39. #include <math.h>
  40. #ifdef UNK
  41. static double P[] = {
  42. -8.54074331929669305196E-1,
  43. 1.20426861384072379242E1,
  44. -4.61252884198732692637E1,
  45. 6.54566728676544377376E1,
  46. -3.09092539379866942570E1
  47. };
  48. static double Q[] = {
  49. /* 1.00000000000000000000E0,*/
  50. -1.95638849376911654834E1,
  51. 1.08938092147140262656E2,
  52. -2.49839401325893582852E2,
  53. 2.52006675691344555838E2,
  54. -9.27277618139601130017E1
  55. };
  56. #endif
  57. #ifdef DEC
  58. static unsigned short P[] = {
  59. 0140132,0122235,0105775,0130300,
  60. 0041100,0127327,0124407,0034722,
  61. 0141470,0100113,0115607,0130535,
  62. 0041602,0164721,0003257,0013673,
  63. 0141367,0043046,0166673,0045750
  64. };
  65. static unsigned short Q[] = {
  66. /*0040200,0000000,0000000,0000000,*/
  67. 0141234,0101326,0015460,0134564,
  68. 0041731,0160115,0116451,0032045,
  69. 0142171,0153343,0000532,0167226,
  70. 0042174,0000665,0077604,0000310,
  71. 0141671,0072235,0031114,0074377
  72. };
  73. #endif
  74. #ifdef IBMPC
  75. static unsigned short P[] = {
  76. 0xb618,0xb17f,0x5493,0xbfeb,
  77. 0xe73a,0xf520,0x15da,0x4028,
  78. 0xf62c,0x7370,0x1009,0xc047,
  79. 0xe2f7,0x20d5,0x5d3a,0x4050,
  80. 0x697d,0xddb7,0xe8c4,0xc03e
  81. };
  82. static unsigned short Q[] = {
  83. /*0x0000,0x0000,0x0000,0x3ff0,*/
  84. 0x172f,0xc366,0x905a,0xc033,
  85. 0x2685,0xb3a5,0x3c09,0x405b,
  86. 0x5dd3,0x602b,0x3adc,0xc06f,
  87. 0x8019,0xaff0,0x8036,0x406f,
  88. 0x8f20,0xa649,0x2e93,0xc057
  89. };
  90. #endif
  91. #ifdef MIEEE
  92. static unsigned short P[] = {
  93. 0xbfeb,0x5493,0xb17f,0xb618,
  94. 0x4028,0x15da,0xf520,0xe73a,
  95. 0xc047,0x1009,0x7370,0xf62c,
  96. 0x4050,0x5d3a,0x20d5,0xe2f7,
  97. 0xc03e,0xe8c4,0xddb7,0x697d
  98. };
  99. static unsigned short Q[] = {
  100. 0xc033,0x905a,0xc366,0x172f,
  101. 0x405b,0x3c09,0xb3a5,0x2685,
  102. 0xc06f,0x3adc,0x602b,0x5dd3,
  103. 0x406f,0x8036,0xaff0,0x8019,
  104. 0xc057,0x2e93,0xa649,0x8f20
  105. };
  106. #endif
  107. #ifdef ANSIPROT
  108. extern double fabs ( double );
  109. extern double log ( double x );
  110. extern double polevl ( double x, void *P, int N );
  111. extern double p1evl ( double x, void *P, int N );
  112. #else
  113. double fabs(), log(), polevl(), p1evl();
  114. #endif
  115. extern double INFINITY, NAN;
  116. double atanh(x)
  117. double x;
  118. {
  119. double s, z;
  120. #ifdef MINUSZERO
  121. if( x == 0.0 )
  122. return(x);
  123. #endif
  124. z = fabs(x);
  125. if( z >= 1.0 )
  126. {
  127. if( x == 1.0 )
  128. return( INFINITY );
  129. if( x == -1.0 )
  130. return( -INFINITY );
  131. mtherr( "atanh", DOMAIN );
  132. return( NAN );
  133. }
  134. if( z < 1.0e-7 )
  135. return(x);
  136. if( z < 0.5 )
  137. {
  138. z = x * x;
  139. s = x + x * z * (polevl(z, P, 4) / p1evl(z, Q, 5));
  140. return(s);
  141. }
  142. return( 0.5 * log((1.0+x)/(1.0-x)) );
  143. }