cpython/Modules/_math.h

65 lines
2.0 KiB
C

/* 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
small. Use the substitute from _math.h on all platforms: it includes
workarounds for buggy handling of zeros.
*/
static double
_Py_log1p(double x)
{
/* Some platforms (e.g. MacOS X 10.8, see gh-59682) 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.
To save fiddling with configure tests and platform checks, we handle the
special case of zero input directly on all platforms.
*/
if (x == 0.0) {
return x;
}
else {
return log1p(x);
}
}
#define m_log1p _Py_log1p
/*
wrapper for atan2 that deals directly with special cases before
delegating to the platform libm for the remaining cases. This
is necessary to get consistent behaviour across platforms.
Windows, FreeBSD and alpha Tru64 are amongst platforms that don't
always follow C99. Windows screws up atan2 for inf and nan, and
alpha Tru64 5.1 doesn't follow C99 for atan2(0., 0.).
*/
static double
_Py_atan2(double y, double x)
{
if (isnan(x) || isnan(y))
return Py_NAN;
if (isinf(y)) {
if (isinf(x)) {
if (copysign(1., x) == 1.)
/* atan2(+-inf, +inf) == +-pi/4 */
return copysign(0.25*Py_MATH_PI, y);
else
/* atan2(+-inf, -inf) == +-pi*3/4 */
return copysign(0.75*Py_MATH_PI, y);
}
/* atan2(+-inf, x) == +-pi/2 for finite x */
return copysign(0.5*Py_MATH_PI, y);
}
if (isinf(x) || y == 0.) {
if (copysign(1., x) == 1.)
/* atan2(+-y, +inf) = atan2(+-0, +x) = +-0. */
return copysign(0., y);
else
/* atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. */
return copysign(Py_MATH_PI, y);
}
return atan2(y, x);
}
#define m_atan2 _Py_atan2