@@ -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. */
349344static 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