Issue #28256: Cleanup _math.c
Only define fallback implementations when needed. It avoids producing deadcode when the system provides required math functions.
This commit is contained in:
parent
22e36afc17
commit
bf9655854b
|
@ -19,13 +19,19 @@
|
||||||
* ====================================================
|
* ====================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if !defined(HAVE_ACOSH) || !defined(HAVE_ASINH)
|
||||||
static const double ln2 = 6.93147180559945286227E-01;
|
static const double ln2 = 6.93147180559945286227E-01;
|
||||||
static const double two_pow_m28 = 3.7252902984619141E-09; /* 2**-28 */
|
|
||||||
static const double two_pow_p28 = 268435456.0; /* 2**28 */
|
static const double two_pow_p28 = 268435456.0; /* 2**28 */
|
||||||
#ifndef Py_NAN
|
#endif
|
||||||
|
#if !defined(HAVE_ASINH) || !defined(HAVE_ATANH)
|
||||||
|
static const double two_pow_m28 = 3.7252902984619141E-09; /* 2**-28 */
|
||||||
|
#endif
|
||||||
|
#if !defined(HAVE_ATANH) && !defined(Py_NAN)
|
||||||
static const double zero = 0.0;
|
static const double zero = 0.0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_ACOSH
|
||||||
/* acosh(x)
|
/* acosh(x)
|
||||||
* Method :
|
* Method :
|
||||||
* Based on
|
* Based on
|
||||||
|
@ -59,23 +65,25 @@ _Py_acosh(double x)
|
||||||
return x+x;
|
return x+x;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return log(x)+ln2; /* acosh(huge)=log(2x) */
|
return log(x) + ln2; /* acosh(huge)=log(2x) */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (x == 1.) {
|
else if (x == 1.) {
|
||||||
return 0.0; /* acosh(1) = 0 */
|
return 0.0; /* acosh(1) = 0 */
|
||||||
}
|
}
|
||||||
else if (x > 2.) { /* 2 < x < 2**28 */
|
else if (x > 2.) { /* 2 < x < 2**28 */
|
||||||
double t = x*x;
|
double t = x * x;
|
||||||
return log(2.0*x - 1.0 / (x + sqrt(t - 1.0)));
|
return log(2.0 * x - 1.0 / (x + sqrt(t - 1.0)));
|
||||||
}
|
}
|
||||||
else { /* 1 < x <= 2 */
|
else { /* 1 < x <= 2 */
|
||||||
double t = x - 1.0;
|
double t = x - 1.0;
|
||||||
return m_log1p(t + sqrt(2.0*t + t*t));
|
return m_log1p(t + sqrt(2.0 * t + t * t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_ACOSH */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_ASINH
|
||||||
/* asinh(x)
|
/* asinh(x)
|
||||||
* Method :
|
* Method :
|
||||||
* Based on
|
* Based on
|
||||||
|
@ -100,10 +108,10 @@ _Py_asinh(double x)
|
||||||
return x; /* return x inexact except 0 */
|
return x; /* return x inexact except 0 */
|
||||||
}
|
}
|
||||||
if (absx > two_pow_p28) { /* |x| > 2**28 */
|
if (absx > two_pow_p28) { /* |x| > 2**28 */
|
||||||
w = log(absx)+ln2;
|
w = log(absx) + ln2;
|
||||||
}
|
}
|
||||||
else if (absx > 2.0) { /* 2 < |x| < 2**28 */
|
else if (absx > 2.0) { /* 2 < |x| < 2**28 */
|
||||||
w = log(2.0*absx + 1.0 / (sqrt(x*x + 1.0) + absx));
|
w = log(2.0 * absx + 1.0 / (sqrt(x * x + 1.0) + absx));
|
||||||
}
|
}
|
||||||
else { /* 2**-28 <= |x| < 2= */
|
else { /* 2**-28 <= |x| < 2= */
|
||||||
double t = x*x;
|
double t = x*x;
|
||||||
|
@ -112,7 +120,10 @@ _Py_asinh(double x)
|
||||||
return copysign(w, x);
|
return copysign(w, x);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_ASINH */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_ATANH
|
||||||
/* atanh(x)
|
/* atanh(x)
|
||||||
* Method :
|
* Method :
|
||||||
* 1.Reduced x to positive by atanh(-x) = -atanh(x)
|
* 1.Reduced x to positive by atanh(-x) = -atanh(x)
|
||||||
|
@ -145,7 +156,7 @@ _Py_atanh(double x)
|
||||||
#ifdef Py_NAN
|
#ifdef Py_NAN
|
||||||
return Py_NAN;
|
return Py_NAN;
|
||||||
#else
|
#else
|
||||||
return x/zero;
|
return x / zero;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (absx < two_pow_m28) { /* |x| < 2**-28 */
|
if (absx < two_pow_m28) { /* |x| < 2**-28 */
|
||||||
|
@ -160,7 +171,10 @@ _Py_atanh(double x)
|
||||||
}
|
}
|
||||||
return copysign(t, x);
|
return copysign(t, x);
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_ATANH */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_EXPM1
|
||||||
/* Mathematically, expm1(x) = exp(x) - 1. The expm1 function is designed
|
/* Mathematically, expm1(x) = exp(x) - 1. The expm1 function is designed
|
||||||
to avoid the significant loss of precision that arises from direct
|
to avoid the significant loss of precision that arises from direct
|
||||||
evaluation of the expression exp(x) - 1, for x near 0. */
|
evaluation of the expression exp(x) - 1, for x near 0. */
|
||||||
|
@ -186,16 +200,17 @@ _Py_expm1(double x)
|
||||||
else
|
else
|
||||||
return exp(x) - 1.0;
|
return exp(x) - 1.0;
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_EXPM1 */
|
||||||
|
|
||||||
|
|
||||||
/* log1p(x) = log(1+x). The log1p function is designed to avoid the
|
/* log1p(x) = log(1+x). The log1p function is designed to avoid the
|
||||||
significant loss of precision that arises from direct evaluation when x is
|
significant loss of precision that arises from direct evaluation when x is
|
||||||
small. */
|
small. */
|
||||||
|
|
||||||
#ifdef HAVE_LOG1P
|
|
||||||
|
|
||||||
double
|
double
|
||||||
_Py_log1p(double x)
|
_Py_log1p(double x)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_LOG1P
|
||||||
/* Some platforms supply a log1p function but don't respect the sign of
|
/* Some platforms supply a log1p function but don't respect the sign of
|
||||||
zero: log1p(-0.0) gives 0.0 instead of the correct result of -0.0.
|
zero: log1p(-0.0) gives 0.0 instead of the correct result of -0.0.
|
||||||
|
|
||||||
|
@ -208,13 +223,7 @@ _Py_log1p(double x)
|
||||||
else {
|
else {
|
||||||
return log1p(x);
|
return log1p(x);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
double
|
|
||||||
_Py_log1p(double x)
|
|
||||||
{
|
|
||||||
/* For x small, we use the following approach. Let y be the nearest float
|
/* For x small, we use the following approach. Let y be the nearest float
|
||||||
to 1+x, then
|
to 1+x, then
|
||||||
|
|
||||||
|
@ -236,7 +245,7 @@ _Py_log1p(double x)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double y;
|
double y;
|
||||||
if (fabs(x) < DBL_EPSILON/2.) {
|
if (fabs(x) < DBL_EPSILON / 2.) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
else if (-0.5 <= x && x <= 1.) {
|
else if (-0.5 <= x && x <= 1.) {
|
||||||
|
@ -246,12 +255,12 @@ _Py_log1p(double x)
|
||||||
happens, then results from log1p will be inaccurate
|
happens, then results from log1p will be inaccurate
|
||||||
for small x. */
|
for small x. */
|
||||||
y = 1.+x;
|
y = 1.+x;
|
||||||
return log(y)-((y-1.)-x)/y;
|
return log(y) - ((y - 1.) - x) / y;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* NaNs and infinities should end up here */
|
/* NaNs and infinities should end up here */
|
||||||
return log(1.+x);
|
return log(1.+x);
|
||||||
}
|
}
|
||||||
|
#endif /* ifdef HAVE_LOG1P */
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ifdef HAVE_LOG1P */
|
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
double _Py_acosh(double x);
|
|
||||||
double _Py_asinh(double x);
|
|
||||||
double _Py_atanh(double x);
|
|
||||||
double _Py_expm1(double x);
|
|
||||||
double _Py_log1p(double x);
|
|
||||||
|
|
||||||
#ifdef HAVE_ACOSH
|
#ifdef HAVE_ACOSH
|
||||||
#define m_acosh acosh
|
# define m_acosh acosh
|
||||||
#else
|
#else
|
||||||
/* if the system doesn't have acosh, use the substitute
|
/* if the system doesn't have acosh, use the substitute
|
||||||
function defined in Modules/_math.c. */
|
function defined in Modules/_math.c. */
|
||||||
#define m_acosh _Py_acosh
|
double _Py_acosh(double x);
|
||||||
|
# define m_acosh _Py_acosh
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ASINH
|
#ifdef HAVE_ASINH
|
||||||
#define m_asinh asinh
|
# define m_asinh asinh
|
||||||
#else
|
#else
|
||||||
/* if the system doesn't have asinh, use the substitute
|
/* if the system doesn't have asinh, use the substitute
|
||||||
function defined in Modules/_math.c. */
|
function defined in Modules/_math.c. */
|
||||||
#define m_asinh _Py_asinh
|
double _Py_asinh(double x);
|
||||||
|
# define m_asinh _Py_asinh
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ATANH
|
#ifdef HAVE_ATANH
|
||||||
#define m_atanh atanh
|
# define m_atanh atanh
|
||||||
#else
|
#else
|
||||||
/* if the system doesn't have atanh, use the substitute
|
/* if the system doesn't have atanh, use the substitute
|
||||||
function defined in Modules/_math.c. */
|
function defined in Modules/_math.c. */
|
||||||
|
double _Py_atanh(double x);
|
||||||
#define m_atanh _Py_atanh
|
#define m_atanh _Py_atanh
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_EXPM1
|
#ifdef HAVE_EXPM1
|
||||||
#define m_expm1 expm1
|
# define m_expm1 expm1
|
||||||
#else
|
#else
|
||||||
/* if the system doesn't have expm1, use the substitute
|
/* if the system doesn't have expm1, use the substitute
|
||||||
function defined in Modules/_math.c. */
|
function defined in Modules/_math.c. */
|
||||||
|
double _Py_expm1(double x);
|
||||||
#define m_expm1 _Py_expm1
|
#define m_expm1 _Py_expm1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
double _Py_log1p(double x);
|
||||||
|
|
||||||
/* Use the substitute from _math.c on all platforms:
|
/* Use the substitute from _math.c on all platforms:
|
||||||
it includes workarounds for buggy handling of zeros. */
|
it includes workarounds for buggy handling of zeros. */
|
||||||
#define m_log1p _Py_log1p
|
#define m_log1p _Py_log1p
|
||||||
|
|
Loading…
Reference in New Issue