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