You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
6.5 KiB

  1. /* Definitions of some C99 math library functions, for those platforms
  2. that don't implement these functions already. */
  3. #include "Python.h"
  4. #include <float.h>
  5. #include "_math.h"
  6. /* The following copyright notice applies to the original
  7. implementations of acosh, asinh and atanh. */
  8. /*
  9. * ====================================================
  10. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  11. *
  12. * Developed at SunPro, a Sun Microsystems, Inc. business.
  13. * Permission to use, copy, modify, and distribute this
  14. * software is freely granted, provided that this notice
  15. * is preserved.
  16. * ====================================================
  17. */
  18. static const double ln2 = 6.93147180559945286227E-01;
  19. static const double two_pow_m28 = 3.7252902984619141E-09; /* 2**-28 */
  20. static const double two_pow_p28 = 268435456.0; /* 2**28 */
  21. static const double zero = 0.0;
  22. /* acosh(x)
  23. * Method :
  24. * Based on
  25. * acosh(x) = log [ x + sqrt(x*x-1) ]
  26. * we have
  27. * acosh(x) := log(x)+ln2, if x is large; else
  28. * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
  29. * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
  30. *
  31. * Special cases:
  32. * acosh(x) is NaN with signal if x<1.
  33. * acosh(NaN) is NaN without signal.
  34. */
  35. double
  36. _Py_acosh(double x)
  37. {
  38. if (Py_IS_NAN(x)) {
  39. return x+x;
  40. }
  41. if (x < 1.) { /* x < 1; return a signaling NaN */
  42. errno = EDOM;
  43. #ifdef Py_NAN
  44. return Py_NAN;
  45. #else
  46. return (x-x)/(x-x);
  47. #endif
  48. }
  49. else if (x >= two_pow_p28) { /* x > 2**28 */
  50. if (Py_IS_INFINITY(x)) {
  51. return x+x;
  52. }
  53. else {
  54. return log(x)+ln2; /* acosh(huge)=log(2x) */
  55. }
  56. }
  57. else if (x == 1.) {
  58. return 0.0; /* acosh(1) = 0 */
  59. }
  60. else if (x > 2.) { /* 2 < x < 2**28 */
  61. double t = x*x;
  62. return log(2.0*x - 1.0 / (x + sqrt(t - 1.0)));
  63. }
  64. else { /* 1 < x <= 2 */
  65. double t = x - 1.0;
  66. return m_log1p(t + sqrt(2.0*t + t*t));
  67. }
  68. }
  69. /* asinh(x)
  70. * Method :
  71. * Based on
  72. * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
  73. * we have
  74. * asinh(x) := x if 1+x*x=1,
  75. * := sign(x)*(log(x)+ln2)) for large |x|, else
  76. * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
  77. * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
  78. */
  79. double
  80. _Py_asinh(double x)
  81. {
  82. double w;
  83. double absx = fabs(x);
  84. if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) {
  85. return x+x;
  86. }
  87. if (absx < two_pow_m28) { /* |x| < 2**-28 */
  88. return x; /* return x inexact except 0 */
  89. }
  90. if (absx > two_pow_p28) { /* |x| > 2**28 */
  91. w = log(absx)+ln2;
  92. }
  93. else if (absx > 2.0) { /* 2 < |x| < 2**28 */
  94. w = log(2.0*absx + 1.0 / (sqrt(x*x + 1.0) + absx));
  95. }
  96. else { /* 2**-28 <= |x| < 2= */
  97. double t = x*x;
  98. w = m_log1p(absx + t / (1.0 + sqrt(1.0 + t)));
  99. }
  100. return copysign(w, x);
  101. }
  102. /* atanh(x)
  103. * Method :
  104. * 1.Reduced x to positive by atanh(-x) = -atanh(x)
  105. * 2.For x>=0.5
  106. * 1 2x x
  107. * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * -------)
  108. * 2 1 - x 1 - x
  109. *
  110. * For x<0.5
  111. * atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
  112. *
  113. * Special cases:
  114. * atanh(x) is NaN if |x| >= 1 with signal;
  115. * atanh(NaN) is that NaN with no signal;
  116. *
  117. */
  118. double
  119. _Py_atanh(double x)
  120. {
  121. double absx;
  122. double t;
  123. if (Py_IS_NAN(x)) {
  124. return x+x;
  125. }
  126. absx = fabs(x);
  127. if (absx >= 1.) { /* |x| >= 1 */
  128. errno = EDOM;
  129. #ifdef Py_NAN
  130. return Py_NAN;
  131. #else
  132. return x/zero;
  133. #endif
  134. }
  135. if (absx < two_pow_m28) { /* |x| < 2**-28 */
  136. return x;
  137. }
  138. if (absx < 0.5) { /* |x| < 0.5 */
  139. t = absx+absx;
  140. t = 0.5 * m_log1p(t + t*absx / (1.0 - absx));
  141. }
  142. else { /* 0.5 <= |x| <= 1.0 */
  143. t = 0.5 * m_log1p((absx + absx) / (1.0 - absx));
  144. }
  145. return copysign(t, x);
  146. }
  147. /* Mathematically, expm1(x) = exp(x) - 1. The expm1 function is designed
  148. to avoid the significant loss of precision that arises from direct
  149. evaluation of the expression exp(x) - 1, for x near 0. */
  150. double
  151. _Py_expm1(double x)
  152. {
  153. /* For abs(x) >= log(2), it's safe to evaluate exp(x) - 1 directly; this
  154. also works fine for infinities and nans.
  155. For smaller x, we can use a method due to Kahan that achieves close to
  156. full accuracy.
  157. */
  158. if (fabs(x) < 0.7) {
  159. double u;
  160. u = exp(x);
  161. if (u == 1.0)
  162. return x;
  163. else
  164. return (u - 1.0) * x / log(u);
  165. }
  166. else
  167. return exp(x) - 1.0;
  168. }
  169. /* log1p(x) = log(1+x). The log1p function is designed to avoid the
  170. significant loss of precision that arises from direct evaluation when x is
  171. small. */
  172. double
  173. _Py_log1p(double x)
  174. {
  175. /* For x small, we use the following approach. Let y be the nearest float
  176. to 1+x, then
  177. 1+x = y * (1 - (y-1-x)/y)
  178. so log(1+x) = log(y) + log(1-(y-1-x)/y). Since (y-1-x)/y is tiny, the
  179. second term is well approximated by (y-1-x)/y. If abs(x) >=
  180. DBL_EPSILON/2 or the rounding-mode is some form of round-to-nearest
  181. then y-1-x will be exactly representable, and is computed exactly by
  182. (y-1)-x.
  183. If abs(x) < DBL_EPSILON/2 and the rounding mode is not known to be
  184. round-to-nearest then this method is slightly dangerous: 1+x could be
  185. rounded up to 1+DBL_EPSILON instead of down to 1, and in that case
  186. y-1-x will not be exactly representable any more and the result can be
  187. off by many ulps. But this is easily fixed: for a floating-point
  188. number |x| < DBL_EPSILON/2., the closest floating-point number to
  189. log(1+x) is exactly x.
  190. */
  191. double y;
  192. if (fabs(x) < DBL_EPSILON/2.) {
  193. return x;
  194. }
  195. else if (-0.5 <= x && x <= 1.) {
  196. /* WARNING: it's possible than an overeager compiler
  197. will incorrectly optimize the following two lines
  198. to the equivalent of "return log(1.+x)". If this
  199. happens, then results from log1p will be inaccurate
  200. for small x. */
  201. y = 1.+x;
  202. return log(y)-((y-1.)-x)/y;
  203. }
  204. else {
  205. /* NaNs and infinities should end up here */
  206. return log(1.+x);
  207. }
  208. }