~pythonregexp2.7/python/issue2636-11

« back to all changes in this revision

Viewing changes to Modules/mathmodule.c

  • Committer: Jeffrey C. "The TimeHorse" Jacobs
  • Date: 2008-09-21 17:53:26 UTC
  • mfrom: (39025.1.14 Regexp-2.7)
  • Revision ID: darklord@timehorse.com-20080921175326-92vaej2hc3yuecxb
Merged in changes from the core Regexp branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
82
82
                 * should return a zero on underflow, and +- HUGE_VAL on
83
83
                 * overflow, so testing the result for zero suffices to
84
84
                 * distinguish the cases).
 
85
                 *
 
86
                 * On some platforms (Ubuntu/ia64) it seems that errno can be
 
87
                 * set to ERANGE for subnormal results that do *not* underflow
 
88
                 * to zero.  So to be safe, we'll ignore ERANGE whenever the
 
89
                 * function result is less than one in absolute value.
85
90
                 */
86
 
                if (x)
 
91
                if (fabs(x) < 1.0)
 
92
                        result = 0;
 
93
                else
87
94
                        PyErr_SetString(PyExc_OverflowError,
88
95
                                        "math range error");
89
 
                else
90
 
                        result = 0;
91
96
        }
92
97
        else
93
98
                /* Unexpected math error */
322
327
   sum([1e+308, 1e+308, 1e-308]) raises an OverflowError due to the
323
328
   overflow of the first partial sum.
324
329
 
325
 
   Note 3: The itermediate values lo, yr, and hi are declared volatile so
326
 
   aggressive compilers won't algebraicly reduce lo to always be exactly 0.0.
 
330
   Note 3: The intermediate values lo, yr, and hi are declared volatile so
 
331
   aggressive compilers won't algebraically reduce lo to always be exactly 0.0.
327
332
   Also, the volatile declaration forces the values to be stored in memory as
328
333
   regular doubles instead of extended long precision (80-bit) values.  This
329
 
   prevents double rounding because any addition or substraction of two doubles
 
334
   prevents double rounding because any addition or subtraction of two doubles
330
335
   can be resolved exactly into double-sized hi and lo values.  As long as the 
331
336
   hi value gets forced into a double before yr and lo are computed, the extra
332
337
   bits in downstream extended precision operations (x87 for example) will be
336
341
   Note 4: A similar implementation is in Modules/cmathmodule.c.
337
342
   Be sure to update both when making changes.
338
343
 
339
 
   Note 5: The signature of math.sum() differs from __builtin__.sum()
 
344
   Note 5: The signature of math.fsum() differs from __builtin__.sum()
340
345
   because the start argument doesn't make sense in the context of
341
346
   accurate summation.  Since the partials table is collapsed before
342
347
   returning a result, sum(seq2, start=sum(seq1)) may not equal the
347
352
 
348
353
/* Extend the partials array p[] by doubling its size. */
349
354
static int                          /* non-zero on error */
350
 
_sum_realloc(double **p_ptr, Py_ssize_t  n,
 
355
_fsum_realloc(double **p_ptr, Py_ssize_t  n,
351
356
             double  *ps,    Py_ssize_t *m_ptr)
352
357
{
353
358
        void *v = NULL;
365
370
                        v = PyMem_Realloc(p, sizeof(double) * m);
366
371
        }
367
372
        if (v == NULL) {        /* size overflow or no memory */
368
 
                PyErr_SetString(PyExc_MemoryError, "math sum partials");
 
373
                PyErr_SetString(PyExc_MemoryError, "math.fsum partials");
369
374
                return 1;
370
375
        }
371
376
        *p_ptr = (double*) v;
404
409
*/
405
410
 
406
411
static PyObject*
407
 
math_sum(PyObject *self, PyObject *seq)
 
412
math_fsum(PyObject *self, PyObject *seq)
408
413
{
409
414
        PyObject *item, *iter, *sum = NULL;
410
415
        Py_ssize_t i, j, n = 0, m = NUM_PARTIALS;
411
416
        double x, y, t, ps[NUM_PARTIALS], *p = ps;
 
417
        double xsave, special_sum = 0.0, inf_sum = 0.0;
412
418
        volatile double hi, yr, lo;
413
419
 
414
420
        iter = PyObject_GetIter(seq);
415
421
        if (iter == NULL)
416
422
                return NULL;
417
423
 
418
 
        PyFPE_START_PROTECT("sum", Py_DECREF(iter); return NULL)
 
424
        PyFPE_START_PROTECT("fsum", Py_DECREF(iter); return NULL)
419
425
 
420
426
        for(;;) {           /* for x in iterable */
421
427
                assert(0 <= n && n <= m);
425
431
                item = PyIter_Next(iter);
426
432
                if (item == NULL) {
427
433
                        if (PyErr_Occurred())
428
 
                                goto _sum_error;
 
434
                                goto _fsum_error;
429
435
                        break;
430
436
                }
431
437
                x = PyFloat_AsDouble(item);
432
438
                Py_DECREF(item);
433
439
                if (PyErr_Occurred())
434
 
                        goto _sum_error;
 
440
                        goto _fsum_error;
435
441
 
 
442
                xsave = x;
436
443
                for (i = j = 0; j < n; j++) {       /* for y in partials */
437
444
                        y = p[j];
438
445
                        if (fabs(x) < fabs(y)) {
439
 
                                        t = x; x = y; y = t;
 
446
                                t = x; x = y; y = t;
440
447
                        }
441
448
                        hi = x + y;
442
449
                        yr = hi - x;
445
452
                                p[i++] = lo;
446
453
                        x = hi;
447
454
                }
448
 
                
449
 
                n = i;                              /* ps[i:] = [x] */                   
 
455
 
 
456
                n = i;                              /* ps[i:] = [x] */
450
457
                if (x != 0.0) {
451
 
                        /* If non-finite, reset partials, effectively
452
 
                           adding subsequent items without roundoff
453
 
                           and yielding correct non-finite results,
454
 
                           provided IEEE 754 rules are observed */
455
 
                        if (! Py_IS_FINITE(x))
 
458
                        if (! Py_IS_FINITE(x)) {
 
459
                                /* a nonfinite x could arise either as
 
460
                                   a result of intermediate overflow, or
 
461
                                   as a result of a nan or inf in the
 
462
                                   summands */
 
463
                                if (Py_IS_FINITE(xsave)) {
 
464
                                        PyErr_SetString(PyExc_OverflowError,
 
465
                                              "intermediate overflow in fsum");
 
466
                                        goto _fsum_error;
 
467
                                }
 
468
                                if (Py_IS_INFINITY(xsave))
 
469
                                        inf_sum += xsave;
 
470
                                special_sum += xsave;
 
471
                                /* reset partials */
456
472
                                n = 0;
457
 
                        else if (n >= m && _sum_realloc(&p, n, ps, &m))
458
 
                                goto _sum_error;
459
 
                        p[n++] = x;
 
473
                        }
 
474
                        else if (n >= m && _fsum_realloc(&p, n, ps, &m))
 
475
                                goto _fsum_error;
 
476
                        else
 
477
                                p[n++] = x;
460
478
                }
461
479
        }
462
480
 
 
481
        if (special_sum != 0.0) {
 
482
                if (Py_IS_NAN(inf_sum))
 
483
                        PyErr_SetString(PyExc_ValueError,
 
484
                                        "-inf + inf in fsum");
 
485
                else
 
486
                        sum = PyFloat_FromDouble(special_sum);
 
487
                goto _fsum_error;
 
488
        }
 
489
 
463
490
        hi = 0.0;
464
491
        if (n > 0) {
465
492
                hi = p[--n];
466
 
                if (Py_IS_FINITE(hi)) {
467
 
                        /* sum_exact(ps, hi) from the top, stop when the sum becomes inexact. */
468
 
                        while (n > 0) {
469
 
                                x = hi;
470
 
                                y = p[--n];
471
 
                                assert(fabs(y) < fabs(x));
472
 
                                hi = x + y;
473
 
                                yr = hi - x;
474
 
                                lo = y - yr;
475
 
                                if (lo != 0.0)
476
 
                                        break;
477
 
                        }
478
 
                        /* Make half-even rounding work across multiple partials.  Needed 
479
 
                           so that sum([1e-16, 1, 1e16]) will round-up the last digit to 
480
 
                           two instead of down to zero (the 1e-16 makes the 1 slightly 
481
 
                           closer to two).  With a potential 1 ULP rounding error fixed-up,
482
 
                           math.sum() can guarantee commutativity. */
483
 
                        if (n > 0 && ((lo < 0.0 && p[n-1] < 0.0) ||
484
 
                                      (lo > 0.0 && p[n-1] > 0.0))) {
485
 
                                y = lo * 2.0;
486
 
                                x = hi + y;
487
 
                                yr = x - hi;
488
 
                                if (y == yr)
489
 
                                        hi = x;
490
 
                        }
 
493
                /* sum_exact(ps, hi) from the top, stop when the sum becomes
 
494
                   inexact. */
 
495
                while (n > 0) {
 
496
                        x = hi;
 
497
                        y = p[--n];
 
498
                        assert(fabs(y) < fabs(x));
 
499
                        hi = x + y;
 
500
                        yr = hi - x;
 
501
                        lo = y - yr;
 
502
                        if (lo != 0.0)
 
503
                                break;
491
504
                }
492
 
                else {  /* raise exception corresponding to a special value */
493
 
                        errno = Py_IS_NAN(hi) ? EDOM : ERANGE;
494
 
                        if (is_error(hi))
495
 
                                goto _sum_error;
 
505
                /* Make half-even rounding work across multiple partials.
 
506
                   Needed so that sum([1e-16, 1, 1e16]) will round-up the last
 
507
                   digit to two instead of down to zero (the 1e-16 makes the 1
 
508
                   slightly closer to two).  With a potential 1 ULP rounding
 
509
                   error fixed-up, math.fsum() can guarantee commutativity. */
 
510
                if (n > 0 && ((lo < 0.0 && p[n-1] < 0.0) ||
 
511
                              (lo > 0.0 && p[n-1] > 0.0))) {
 
512
                        y = lo * 2.0;
 
513
                        x = hi + y;
 
514
                        yr = x - hi;
 
515
                        if (y == yr)
 
516
                                hi = x;
496
517
                }
497
518
        }
498
519
        sum = PyFloat_FromDouble(hi);
499
520
 
500
 
_sum_error:
 
521
_fsum_error:
501
522
        PyFPE_END_PROTECT(hi)
502
523
        Py_DECREF(iter);
503
524
        if (p != ps)
507
528
 
508
529
#undef NUM_PARTIALS
509
530
 
510
 
PyDoc_STRVAR(math_sum_doc,
 
531
PyDoc_STRVAR(math_fsum_doc,
511
532
"sum(iterable)\n\n\
512
533
Return an accurate floating point sum of values in the iterable.\n\
513
534
Assumes IEEE-754 floating point arithmetic.");
514
535
 
515
 
 
516
536
static PyObject *
517
537
math_factorial(PyObject *self, PyObject *arg)
518
538
{
555
575
 
556
576
error:
557
577
        Py_DECREF(result);
558
 
        Py_XDECREF(iobj);
559
578
        return NULL;
560
579
}
561
580
 
1002
1021
        {"floor",       math_floor,     METH_O,         math_floor_doc},
1003
1022
        {"fmod",        math_fmod,      METH_VARARGS,   math_fmod_doc},
1004
1023
        {"frexp",       math_frexp,     METH_O,         math_frexp_doc},
 
1024
        {"fsum",        math_fsum,      METH_O,         math_fsum_doc},
1005
1025
        {"hypot",       math_hypot,     METH_VARARGS,   math_hypot_doc},
1006
1026
        {"isinf",       math_isinf,     METH_O,         math_isinf_doc},
1007
1027
        {"isnan",       math_isnan,     METH_O,         math_isnan_doc},
1015
1035
        {"sin",         math_sin,       METH_O,         math_sin_doc},
1016
1036
        {"sinh",        math_sinh,      METH_O,         math_sinh_doc},
1017
1037
        {"sqrt",        math_sqrt,      METH_O,         math_sqrt_doc},
1018
 
        {"sum",         math_sum,       METH_O,         math_sum_doc},
1019
1038
        {"tan",         math_tan,       METH_O,         math_tan_doc},
1020
1039
        {"tanh",        math_tanh,      METH_O,         math_tanh_doc},
1021
 
        {"trunc",       math_trunc,     METH_O,         math_trunc_doc},
 
1040
        {"trunc",       math_trunc,     METH_O,         math_trunc_doc},
1022
1041
        {NULL,          NULL}           /* sentinel */
1023
1042
};
1024
1043