[Python-checkins] r64052 - python/trunk/Modules/mathmodule.c

raymond.hettinger python-checkins at python.org
Mon Jun 9 11:29:18 CEST 2008


Author: raymond.hettinger
Date: Mon Jun  9 11:29:17 2008
New Revision: 64052

Log:
Address double-rounding scenarios by setting all variables to long doubles.

Modified:
   python/trunk/Modules/mathmodule.c

Modified: python/trunk/Modules/mathmodule.c
==============================================================================
--- python/trunk/Modules/mathmodule.c	(original)
+++ python/trunk/Modules/mathmodule.c	Mon Jun  9 11:29:17 2008
@@ -324,17 +324,12 @@
 
    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: A similar implementation is in Modules/cmathmodule.c.
-   Be sure to update both when making changes.
+   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 5: The signature of math.sum() differs from __builtin__.sum()
    because the start argument doesn't make sense in the context of
@@ -347,28 +342,28 @@
 
 /* Extend the partials array p[] by doubling its size. */
 static int                          /* non-zero on error */
-_sum_realloc(double **p_ptr, Py_ssize_t  n,
-             double  *ps,    Py_ssize_t *m_ptr)
+_sum_realloc(long double **p_ptr, Py_ssize_t  n,
+             long double  *ps,    Py_ssize_t *m_ptr)
 {
 	void *v = NULL;
 	Py_ssize_t m = *m_ptr;
 
-	m += m;  /* double */
-	if (n < m && m < (PY_SSIZE_T_MAX / sizeof(double))) {
-		double *p = *p_ptr;
+	m += m;  /* long double */
+	if (n < m && m < (PY_SSIZE_T_MAX / sizeof(long double))) {
+		long double *p = *p_ptr;
 		if (p == ps) {
-			v = PyMem_Malloc(sizeof(double) * m);
+			v = PyMem_Malloc(sizeof(long double) * m);
 			if (v != NULL)
-				memcpy(v, ps, sizeof(double) * n);
+				memcpy(v, ps, sizeof(long double) * n);
 		}
 		else
-			v = PyMem_Realloc(p, sizeof(double) * m);
+			v = PyMem_Realloc(p, sizeof(long double) * m);
 	}
 	if (v == NULL) {        /* size overflow or no memory */
 		PyErr_SetString(PyExc_MemoryError, "math sum partials");
 		return 1;
 	}
-	*p_ptr = (double*) v;
+	*p_ptr = (long double*) v;
 	*m_ptr = m;
 	return 0;
 }
@@ -408,8 +403,8 @@
 {
 	PyObject *item, *iter, *sum = NULL;
 	Py_ssize_t i, j, n = 0, m = NUM_PARTIALS;
-	double x, y, t, ps[NUM_PARTIALS], *p = ps;
-	volatile double hi, yr, lo;
+	long double x, y, t, ps[NUM_PARTIALS], *p = ps;
+	volatile long double hi, yr, lo;
 
 	iter = PyObject_GetIter(seq);
 	if (iter == NULL)
@@ -428,7 +423,7 @@
 				goto _sum_error;
 			break;
 		}
-		x = PyFloat_AsDouble(item);
+		x = (long double)PyFloat_AsDouble(item);
 		Py_DECREF(item);
 		if (PyErr_Occurred())
 			goto _sum_error;
@@ -495,7 +490,7 @@
 				goto _sum_error;
 		}
 	}
-	sum = PyFloat_FromDouble(hi);
+	sum = PyFloat_FromDouble((double)hi);
 
 _sum_error:
 	PyFPE_END_PROTECT(hi)


More information about the Python-checkins mailing list