diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2010-06-13 10:50:29 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2010-06-13 10:50:29 (GMT) |
commit | e979ec8fbf873efc266e665ae946df30dea97f6e (patch) | |
tree | b7874d842ee46fc829ea31fe335dd284fd42945d /Modules/mathmodule.c | |
parent | 8842c356aa98869e3d80b10cad5d5aeee22d5569 (diff) | |
download | cpython-e979ec8fbf873efc266e665ae946df30dea97f6e.zip cpython-e979ec8fbf873efc266e665ae946df30dea97f6e.tar.gz cpython-e979ec8fbf873efc266e665ae946df30dea97f6e.tar.bz2 |
Issue #8986: erfc was raising OverflowError on Linux for arguments in
the (approximate) range (-27.3, 30.0), as a result of an escaped errno
value.
Diffstat (limited to 'Modules/mathmodule.c')
-rw-r--r-- | Modules/mathmodule.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 77b56a0..b3b80f4 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -428,8 +428,8 @@ m_lgamma(double x) static double m_erf_series(double x) { - double x2, acc, fk; - int i; + double x2, acc, fk, result; + int i, saved_errno; x2 = x * x; acc = 0.0; @@ -438,7 +438,12 @@ m_erf_series(double x) acc = 2.0 + x2 * acc / fk; fk -= 1.0; } - return acc * x * exp(-x2) / sqrtpi; + /* Make sure the exp call doesn't affect errno; + see m_erfc_contfrac for more. */ + saved_errno = errno; + result = acc * x * exp(-x2) / sqrtpi; + errno = saved_errno; + return result; } /* @@ -453,8 +458,8 @@ m_erf_series(double x) static double m_erfc_contfrac(double x) { - double x2, a, da, p, p_last, q, q_last, b; - int i; + double x2, a, da, p, p_last, q, q_last, b, result; + int i, saved_errno; if (x >= ERFC_CONTFRAC_CUTOFF) return 0.0; @@ -472,7 +477,12 @@ m_erfc_contfrac(double x) temp = p; p = b*p - a*p_last; p_last = temp; temp = q; q = b*q - a*q_last; q_last = temp; } - return p / q * x * exp(-x2) / sqrtpi; + /* Issue #8986: On some platforms, exp sets errno on underflow to zero; + save the current errno value so that we can restore it later. */ + saved_errno = errno; + result = p / q * x * exp(-x2) / sqrtpi; + errno = saved_errno; + return result; } /* Error function erf(x), for general x */ |