From d62341414109ff16d6477e370e380c6dec9db9d6 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 9 Jun 2008 11:24:47 +0000 Subject: [PATCH] Unhappy buildbots. Revert 64052. Long doubles have unexpected effects on some builds. --- Modules/mathmodule.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 16d91e93b17..32c2400f4cc 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -324,12 +324,17 @@ FUNC1(tanh, tanh, 0, Note 3: The itermediate values lo, yr, and hi are declared volatile so aggressive compilers won't algebraicly reduce lo to always be exactly 0.0. + Also, the volatile declaration forces the values to be stored in memory as + regular doubles instead of extended long precision (80-bit) values. This + prevents double rounding because any addition or substraction of two doubles + can be resolved exactly into double-sized hi and lo values. As long as the + hi value gets forced into a double before yr and lo are computed, the extra + bits in downstream extended precision operations (x87 for example) will be + exactly zero and therefore can be losslessly stored back into a double, + thereby preventing double rounding. - Note 4: Intermediate values and partial sums are declared as long doubles - as a way to eliminate double rounding environments where the operations - are carried-out in extended precision but stored in double precision - variables. In some cases, this doesn't help because the compiler - treats long doubles as doubles (i.e. the MS compiler for Win32 builds). + Note 4: A similar implementation is in Modules/cmathmodule.c. + Be sure to update both when making changes. Note 5: The signature of math.sum() differs from __builtin__.sum() because the start argument doesn't make sense in the context of @@ -342,28 +347,28 @@ FUNC1(tanh, tanh, 0, /* Extend the partials array p[] by doubling its size. */ static int /* non-zero on error */ -_sum_realloc(long double **p_ptr, Py_ssize_t n, - long double *ps, Py_ssize_t *m_ptr) +_sum_realloc(double **p_ptr, Py_ssize_t n, + double *ps, Py_ssize_t *m_ptr) { void *v = NULL; Py_ssize_t m = *m_ptr; - m += m; /* long double */ - if (n < m && m < (PY_SSIZE_T_MAX / sizeof(long double))) { - long double *p = *p_ptr; + m += m; /* double */ + if (n < m && m < (PY_SSIZE_T_MAX / sizeof(double))) { + double *p = *p_ptr; if (p == ps) { - v = PyMem_Malloc(sizeof(long double) * m); + v = PyMem_Malloc(sizeof(double) * m); if (v != NULL) - memcpy(v, ps, sizeof(long double) * n); + memcpy(v, ps, sizeof(double) * n); } else - v = PyMem_Realloc(p, sizeof(long double) * m); + v = PyMem_Realloc(p, sizeof(double) * m); } if (v == NULL) { /* size overflow or no memory */ PyErr_SetString(PyExc_MemoryError, "math sum partials"); return 1; } - *p_ptr = (long double*) v; + *p_ptr = (double*) v; *m_ptr = m; return 0; } @@ -403,8 +408,8 @@ math_sum(PyObject *self, PyObject *seq) { PyObject *item, *iter, *sum = NULL; Py_ssize_t i, j, n = 0, m = NUM_PARTIALS; - long double x, y, t, ps[NUM_PARTIALS], *p = ps; - volatile long double hi, yr, lo; + double x, y, t, ps[NUM_PARTIALS], *p = ps; + volatile double hi, yr, lo; iter = PyObject_GetIter(seq); if (iter == NULL) @@ -423,7 +428,7 @@ math_sum(PyObject *self, PyObject *seq) goto _sum_error; break; } - x = (long double)PyFloat_AsDouble(item); + x = PyFloat_AsDouble(item); Py_DECREF(item); if (PyErr_Occurred()) goto _sum_error; @@ -490,7 +495,7 @@ math_sum(PyObject *self, PyObject *seq) goto _sum_error; } } - sum = PyFloat_FromDouble((double)hi); + sum = PyFloat_FromDouble(hi); _sum_error: PyFPE_END_PROTECT(hi) @@ -507,7 +512,6 @@ PyDoc_STRVAR(math_sum_doc, Return an accurate floating point sum of values in the iterable.\n\ Assumes IEEE-754 floating point arithmetic."); - static PyObject * math_factorial(PyObject *self, PyObject *arg) {