@@ -101,10 +101,6 @@ get_math_module_state(PyObject *module)
101
101
102
102
static const double pi = 3.141592653589793238462643383279502884197 ;
103
103
static const double logpi = 1.144729885849400174143427351353058711647 ;
104
- #if !defined(HAVE_ERF ) || !defined(HAVE_ERFC )
105
- static const double sqrtpi = 1.772453850905516027298167483341145182798 ;
106
- #endif /* !defined(HAVE_ERF) || !defined(HAVE_ERFC) */
107
-
108
104
109
105
/* Version of PyFloat_AsDouble() with in-line fast paths
110
106
for exact floats and integers. Gives a substantial
@@ -162,7 +158,9 @@ m_sinpi(double x)
162
158
return copysign (1.0 , x )* r ;
163
159
}
164
160
165
- /* Implementation of the real gamma function. In extensive but non-exhaustive
161
+ /* Implementation of the real gamma function. Kept here to work around
162
+ issues (see e.g. gh-70309) with quality of libm's tgamma/lgamma implementations
163
+ on various platforms (Windows, MacOS). In extensive but non-exhaustive
166
164
random tests, this function proved accurate to within <= 10 ulps across the
167
165
entire float domain. Note that accuracy may depend on the quality of the
168
166
system math functions, the pow function in particular. Special cases
@@ -458,163 +456,6 @@ m_lgamma(double x)
458
456
return r ;
459
457
}
460
458
461
- #if !defined(HAVE_ERF ) || !defined(HAVE_ERFC )
462
-
463
- /*
464
- Implementations of the error function erf(x) and the complementary error
465
- function erfc(x).
466
-
467
- Method: we use a series approximation for erf for small x, and a continued
468
- fraction approximation for erfc(x) for larger x;
469
- combined with the relations erf(-x) = -erf(x) and erfc(x) = 1.0 - erf(x),
470
- this gives us erf(x) and erfc(x) for all x.
471
-
472
- The series expansion used is:
473
-
474
- erf(x) = x*exp(-x*x)/sqrt(pi) * [
475
- 2/1 + 4/3 x**2 + 8/15 x**4 + 16/105 x**6 + ...]
476
-
477
- The coefficient of x**(2k-2) here is 4**k*factorial(k)/factorial(2*k).
478
- This series converges well for smallish x, but slowly for larger x.
479
-
480
- The continued fraction expansion used is:
481
-
482
- erfc(x) = x*exp(-x*x)/sqrt(pi) * [1/(0.5 + x**2 -) 0.5/(2.5 + x**2 - )
483
- 3.0/(4.5 + x**2 - ) 7.5/(6.5 + x**2 - ) ...]
484
-
485
- after the first term, the general term has the form:
486
-
487
- k*(k-0.5)/(2*k+0.5 + x**2 - ...).
488
-
489
- This expansion converges fast for larger x, but convergence becomes
490
- infinitely slow as x approaches 0.0. The (somewhat naive) continued
491
- fraction evaluation algorithm used below also risks overflow for large x;
492
- but for large x, erfc(x) == 0.0 to within machine precision. (For
493
- example, erfc(30.0) is approximately 2.56e-393).
494
-
495
- Parameters: use series expansion for abs(x) < ERF_SERIES_CUTOFF and
496
- continued fraction expansion for ERF_SERIES_CUTOFF <= abs(x) <
497
- ERFC_CONTFRAC_CUTOFF. ERFC_SERIES_TERMS and ERFC_CONTFRAC_TERMS are the
498
- numbers of terms to use for the relevant expansions. */
499
-
500
- #define ERF_SERIES_CUTOFF 1.5
501
- #define ERF_SERIES_TERMS 25
502
- #define ERFC_CONTFRAC_CUTOFF 30.0
503
- #define ERFC_CONTFRAC_TERMS 50
504
-
505
- /*
506
- Error function, via power series.
507
-
508
- Given a finite float x, return an approximation to erf(x).
509
- Converges reasonably fast for small x.
510
- */
511
-
512
- static double
513
- m_erf_series (double x )
514
- {
515
- double x2 , acc , fk , result ;
516
- int i , saved_errno ;
517
-
518
- x2 = x * x ;
519
- acc = 0.0 ;
520
- fk = (double )ERF_SERIES_TERMS + 0.5 ;
521
- for (i = 0 ; i < ERF_SERIES_TERMS ; i ++ ) {
522
- acc = 2.0 + x2 * acc / fk ;
523
- fk -= 1.0 ;
524
- }
525
- /* Make sure the exp call doesn't affect errno;
526
- see m_erfc_contfrac for more. */
527
- saved_errno = errno ;
528
- result = acc * x * exp (- x2 ) / sqrtpi ;
529
- errno = saved_errno ;
530
- return result ;
531
- }
532
-
533
- /*
534
- Complementary error function, via continued fraction expansion.
535
-
536
- Given a positive float x, return an approximation to erfc(x). Converges
537
- reasonably fast for x large (say, x > 2.0), and should be safe from
538
- overflow if x and nterms are not too large. On an IEEE 754 machine, with x
539
- <= 30.0, we're safe up to nterms = 100. For x >= 30.0, erfc(x) is smaller
540
- than the smallest representable nonzero float. */
541
-
542
- static double
543
- m_erfc_contfrac (double x )
544
- {
545
- double x2 , a , da , p , p_last , q , q_last , b , result ;
546
- int i , saved_errno ;
547
-
548
- if (x >= ERFC_CONTFRAC_CUTOFF )
549
- return 0.0 ;
550
-
551
- x2 = x * x ;
552
- a = 0.0 ;
553
- da = 0.5 ;
554
- p = 1.0 ; p_last = 0.0 ;
555
- q = da + x2 ; q_last = 1.0 ;
556
- for (i = 0 ; i < ERFC_CONTFRAC_TERMS ; i ++ ) {
557
- double temp ;
558
- a += da ;
559
- da += 2.0 ;
560
- b = da + x2 ;
561
- temp = p ; p = b * p - a * p_last ; p_last = temp ;
562
- temp = q ; q = b * q - a * q_last ; q_last = temp ;
563
- }
564
- /* Issue #8986: On some platforms, exp sets errno on underflow to zero;
565
- save the current errno value so that we can restore it later. */
566
- saved_errno = errno ;
567
- result = p / q * x * exp (- x2 ) / sqrtpi ;
568
- errno = saved_errno ;
569
- return result ;
570
- }
571
-
572
- #endif /* !defined(HAVE_ERF) || !defined(HAVE_ERFC) */
573
-
574
- /* Error function erf(x), for general x */
575
-
576
- static double
577
- m_erf (double x )
578
- {
579
- #ifdef HAVE_ERF
580
- return erf (x );
581
- #else
582
- double absx , cf ;
583
-
584
- if (Py_IS_NAN (x ))
585
- return x ;
586
- absx = fabs (x );
587
- if (absx < ERF_SERIES_CUTOFF )
588
- return m_erf_series (x );
589
- else {
590
- cf = m_erfc_contfrac (absx );
591
- return x > 0.0 ? 1.0 - cf : cf - 1.0 ;
592
- }
593
- #endif
594
- }
595
-
596
- /* Complementary error function erfc(x), for general x. */
597
-
598
- static double
599
- m_erfc (double x )
600
- {
601
- #ifdef HAVE_ERFC
602
- return erfc (x );
603
- #else
604
- double absx , cf ;
605
-
606
- if (Py_IS_NAN (x ))
607
- return x ;
608
- absx = fabs (x );
609
- if (absx < ERF_SERIES_CUTOFF )
610
- return 1.0 - m_erf_series (x );
611
- else {
612
- cf = m_erfc_contfrac (absx );
613
- return x > 0.0 ? cf : 2.0 - cf ;
614
- }
615
- #endif
616
- }
617
-
618
459
/*
619
460
wrapper for atan2 that deals directly with special cases before
620
461
delegating to the platform libm for the remaining cases. This
@@ -801,25 +642,7 @@ m_log2(double x)
801
642
}
802
643
803
644
if (x > 0.0 ) {
804
- #ifdef HAVE_LOG2
805
645
return log2 (x );
806
- #else
807
- double m ;
808
- int e ;
809
- m = frexp (x , & e );
810
- /* We want log2(m * 2**e) == log(m) / log(2) + e. Care is needed when
811
- * x is just greater than 1.0: in that case e is 1, log(m) is negative,
812
- * and we get significant cancellation error from the addition of
813
- * log(m) / log(2) to e. The slight rewrite of the expression below
814
- * avoids this problem.
815
- */
816
- if (x >= 1.0 ) {
817
- return log (2.0 * m ) / log (2.0 ) + (e - 1 );
818
- }
819
- else {
820
- return log (m ) / log (2.0 ) + e ;
821
- }
822
- #endif
823
646
}
824
647
else if (x == 0.0 ) {
825
648
errno = EDOM ;
@@ -1261,10 +1084,10 @@ FUNC1(cos, cos, 0,
1261
1084
FUNC1 (cosh , cosh , 1 ,
1262
1085
"cosh($module, x, /)\n--\n\n"
1263
1086
"Return the hyperbolic cosine of x." )
1264
- FUNC1A (erf , m_erf ,
1087
+ FUNC1A (erf , erf ,
1265
1088
"erf($module, x, /)\n--\n\n"
1266
1089
"Error function at x." )
1267
- FUNC1A (erfc , m_erfc ,
1090
+ FUNC1A (erfc , erfc ,
1268
1091
"erfc($module, x, /)\n--\n\n"
1269
1092
"Complementary error function at x." )
1270
1093
FUNC1 (exp , exp , 1 ,
0 commit comments