Skip to content

Commit 7121e8f

Browse files
author
raymond.hettinger
committed
Address double-rounding scenarios by setting all variables to long doubles.
git-svn-id: http://svn.python.org/projects/python/trunk@64052 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 6490752 commit 7121e8f

1 file changed

Lines changed: 19 additions & 24 deletions

File tree

Modules/mathmodule.c

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -324,17 +324,12 @@ FUNC1(tanh, tanh, 0,
324324
325325
Note 3: The itermediate values lo, yr, and hi are declared volatile so
326326
aggressive compilers won't algebraicly reduce lo to always be exactly 0.0.
327-
Also, the volatile declaration forces the values to be stored in memory as
328-
regular doubles instead of extended long precision (80-bit) values. This
329-
prevents double rounding because any addition or substraction of two doubles
330-
can be resolved exactly into double-sized hi and lo values. As long as the
331-
hi value gets forced into a double before yr and lo are computed, the extra
332-
bits in downstream extended precision operations (x87 for example) will be
333-
exactly zero and therefore can be losslessly stored back into a double,
334-
thereby preventing double rounding.
335-
336-
Note 4: A similar implementation is in Modules/cmathmodule.c.
337-
Be sure to update both when making changes.
327+
328+
Note 4: Intermediate values and partial sums are declared as long doubles
329+
as a way to eliminate double rounding environments where the operations
330+
are carried-out in extended precision but stored in double precision
331+
variables. In some cases, this doesn't help because the compiler
332+
treats long doubles as doubles (i.e. the MS compiler for Win32 builds).
338333
339334
Note 5: The signature of math.sum() differs from __builtin__.sum()
340335
because the start argument doesn't make sense in the context of
@@ -347,28 +342,28 @@ FUNC1(tanh, tanh, 0,
347342

348343
/* Extend the partials array p[] by doubling its size. */
349344
static int /* non-zero on error */
350-
_sum_realloc(double **p_ptr, Py_ssize_t n,
351-
double *ps, Py_ssize_t *m_ptr)
345+
_sum_realloc(long double **p_ptr, Py_ssize_t n,
346+
long double *ps, Py_ssize_t *m_ptr)
352347
{
353348
void *v = NULL;
354349
Py_ssize_t m = *m_ptr;
355350

356-
m += m; /* double */
357-
if (n < m && m < (PY_SSIZE_T_MAX / sizeof(double))) {
358-
double *p = *p_ptr;
351+
m += m; /* long double */
352+
if (n < m && m < (PY_SSIZE_T_MAX / sizeof(long double))) {
353+
long double *p = *p_ptr;
359354
if (p == ps) {
360-
v = PyMem_Malloc(sizeof(double) * m);
355+
v = PyMem_Malloc(sizeof(long double) * m);
361356
if (v != NULL)
362-
memcpy(v, ps, sizeof(double) * n);
357+
memcpy(v, ps, sizeof(long double) * n);
363358
}
364359
else
365-
v = PyMem_Realloc(p, sizeof(double) * m);
360+
v = PyMem_Realloc(p, sizeof(long double) * m);
366361
}
367362
if (v == NULL) { /* size overflow or no memory */
368363
PyErr_SetString(PyExc_MemoryError, "math sum partials");
369364
return 1;
370365
}
371-
*p_ptr = (double*) v;
366+
*p_ptr = (long double*) v;
372367
*m_ptr = m;
373368
return 0;
374369
}
@@ -408,8 +403,8 @@ math_sum(PyObject *self, PyObject *seq)
408403
{
409404
PyObject *item, *iter, *sum = NULL;
410405
Py_ssize_t i, j, n = 0, m = NUM_PARTIALS;
411-
double x, y, t, ps[NUM_PARTIALS], *p = ps;
412-
volatile double hi, yr, lo;
406+
long double x, y, t, ps[NUM_PARTIALS], *p = ps;
407+
volatile long double hi, yr, lo;
413408

414409
iter = PyObject_GetIter(seq);
415410
if (iter == NULL)
@@ -428,7 +423,7 @@ math_sum(PyObject *self, PyObject *seq)
428423
goto _sum_error;
429424
break;
430425
}
431-
x = PyFloat_AsDouble(item);
426+
x = (long double)PyFloat_AsDouble(item);
432427
Py_DECREF(item);
433428
if (PyErr_Occurred())
434429
goto _sum_error;
@@ -495,7 +490,7 @@ math_sum(PyObject *self, PyObject *seq)
495490
goto _sum_error;
496491
}
497492
}
498-
sum = PyFloat_FromDouble(hi);
493+
sum = PyFloat_FromDouble((double)hi);
499494

500495
_sum_error:
501496
PyFPE_END_PROTECT(hi)

0 commit comments

Comments
 (0)