annotate Modules/mathmodule.c @ 87690:66c1c9f32567 default tip

Add use_weakref option to functools.lru_cache The use_weakref option makes lru_cache create weak references to the function arguments when creating the cache key, which prevents them from staying in the memory forever even after all other references to them are gone. This is a proof of concept for http://bugs.python.org/issue19859
author Radomir Dopieralski <devel@sheep.art.pl>
date Tue, 03 Dec 2013 16:02:48 +0100
parents 4d62a62ba44d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
1 /* Math module -- standard C math library functions, pi and e */
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
2
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
3 /* Here are some comments from Tim Peters, extracted from the
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
4 discussion attached to http://bugs.python.org/issue1640. They
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
5 describe the general aims of the math module with respect to
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
6 special values, IEEE-754 floating-point exceptions, and Python
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
7 exceptions.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
8
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
9 These are the "spirit of 754" rules:
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
10
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
11 1. If the mathematical result is a real number, but of magnitude too
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
12 large to approximate by a machine float, overflow is signaled and the
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
13 result is an infinity (with the appropriate sign).
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
14
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
15 2. If the mathematical result is a real number, but of magnitude too
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
16 small to approximate by a machine float, underflow is signaled and the
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
17 result is a zero (with the appropriate sign).
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
18
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
19 3. At a singularity (a value x such that the limit of f(y) as y
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
20 approaches x exists and is an infinity), "divide by zero" is signaled
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
21 and the result is an infinity (with the appropriate sign). This is
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
22 complicated a little by that the left-side and right-side limits may
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
23 not be the same; e.g., 1/x approaches +inf or -inf as x approaches 0
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
24 from the positive or negative directions. In that specific case, the
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
25 sign of the zero determines the result of 1/0.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
26
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
27 4. At a point where a function has no defined result in the extended
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
28 reals (i.e., the reals plus an infinity or two), invalid operation is
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
29 signaled and a NaN is returned.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
30
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
31 And these are what Python has historically /tried/ to do (but not
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
32 always successfully, as platform libm behavior varies a lot):
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
33
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
34 For #1, raise OverflowError.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
35
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
36 For #2, return a zero (with the appropriate sign if that happens by
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
37 accident ;-)).
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
38
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
39 For #3 and #4, raise ValueError. It may have made sense to raise
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
40 Python's ZeroDivisionError in #3, but historically that's only been
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
41 raised for division by zero and mod by zero.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
42
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
43 */
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
44
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
45 /*
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
46 In general, on an IEEE-754 platform the aim is to follow the C99
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
47 standard, including Annex 'F', whenever possible. Where the
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
48 standard recommends raising the 'divide-by-zero' or 'invalid'
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
49 floating-point exceptions, Python should raise a ValueError. Where
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
50 the standard recommends raising 'overflow', Python should raise an
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
51 OverflowError. In all other circumstances a value should be
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
52 returned.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
53 */
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
54
4635
49745ddb4f69 Renamed
Barry Warsaw <barry@python.org>
parents: 4503
diff changeset
55 #include "Python.h"
57758
b45ca11b9a3e Merged revisions 76861 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57660
diff changeset
56 #include "_math.h"
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
57
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
58 /*
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
59 sin(pi*x), giving accurate results for all finite x (especially x
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
60 integral or close to an integer). This is here for use in the
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
61 reflection formula for the gamma function. It conforms to IEEE
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
62 754-2008 for finite arguments, but not for infinities or nans.
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
63 */
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
64
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
65 static const double pi = 3.141592653589793238462643383279502884197;
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
66 static const double sqrtpi = 1.772453850905516027298167483341145182798;
62843
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
67 static const double logpi = 1.144729885849400174143427351353058711647;
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
68
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
69 static double
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
70 sinpi(double x)
498
56bb1067a880 Improve error handling.
Guido van Rossum <guido@python.org>
parents: 438
diff changeset
71 {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
72 double y, r;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
73 int n;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
74 /* this function should only ever be called for finite arguments */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
75 assert(Py_IS_FINITE(x));
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
76 y = fmod(fabs(x), 2.0);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
77 n = (int)round(2.0*y);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
78 assert(0 <= n && n <= 4);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
79 switch (n) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
80 case 0:
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
81 r = sin(pi*y);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
82 break;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
83 case 1:
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
84 r = cos(pi*(y-0.5));
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
85 break;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
86 case 2:
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
87 /* N.B. -sin(pi*(y-1.0)) is *not* equivalent: it would give
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
88 -0.0 instead of 0.0 when y == 1.0. */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
89 r = sin(pi*(1.0-y));
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
90 break;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
91 case 3:
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
92 r = -cos(pi*(y-1.5));
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
93 break;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
94 case 4:
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
95 r = sin(pi*(y-2.0));
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
96 break;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
97 default:
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
98 assert(0); /* should never get here */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
99 r = -1.23e200; /* silence gcc warning */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
100 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
101 return copysign(1.0, x)*r;
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
102 }
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
103
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
104 /* Implementation of the real gamma function. In extensive but non-exhaustive
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
105 random tests, this function proved accurate to within <= 10 ulps across the
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
106 entire float domain. Note that accuracy may depend on the quality of the
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
107 system math functions, the pow function in particular. Special cases
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
108 follow C99 annex F. The parameters and method are tailored to platforms
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
109 whose double format is the IEEE 754 binary64 format.
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
110
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
111 Method: for x > 0.0 we use the Lanczos approximation with parameters N=13
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
112 and g=6.024680040776729583740234375; these parameters are amongst those
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
113 used by the Boost library. Following Boost (again), we re-express the
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
114 Lanczos sum as a rational function, and compute it that way. The
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
115 coefficients below were computed independently using MPFR, and have been
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
116 double-checked against the coefficients in the Boost source code.
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
117
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
118 For x < 0.0 we use the reflection formula.
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
119
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
120 There's one minor tweak that deserves explanation: Lanczos' formula for
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
121 Gamma(x) involves computing pow(x+g-0.5, x-0.5) / exp(x+g-0.5). For many x
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
122 values, x+g-0.5 can be represented exactly. However, in cases where it
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
123 can't be represented exactly the small error in x+g-0.5 can be magnified
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
124 significantly by the pow and exp calls, especially for large x. A cheap
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
125 correction is to multiply by (1 + e*g/(x+g-0.5)), where e is the error
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
126 involved in the computation of x+g-0.5 (that is, e = computed value of
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
127 x+g-0.5 - exact value of x+g-0.5). Here's the proof:
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
128
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
129 Correction factor
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
130 -----------------
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
131 Write x+g-0.5 = y-e, where y is exactly representable as an IEEE 754
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
132 double, and e is tiny. Then:
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
133
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
134 pow(x+g-0.5,x-0.5)/exp(x+g-0.5) = pow(y-e, x-0.5)/exp(y-e)
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
135 = pow(y, x-0.5)/exp(y) * C,
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
136
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
137 where the correction_factor C is given by
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
138
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
139 C = pow(1-e/y, x-0.5) * exp(e)
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
140
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
141 Since e is tiny, pow(1-e/y, x-0.5) ~ 1-(x-0.5)*e/y, and exp(x) ~ 1+e, so:
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
142
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
143 C ~ (1-(x-0.5)*e/y) * (1+e) ~ 1 + e*(y-(x-0.5))/y
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
144
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
145 But y-(x-0.5) = g+e, and g+e ~ g. So we get C ~ 1 + e*g/y, and
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
146
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
147 pow(x+g-0.5,x-0.5)/exp(x+g-0.5) ~ pow(y, x-0.5)/exp(y) * (1 + e*g/y),
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
148
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
149 Note that for accuracy, when computing r*C it's better to do
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
150
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
151 r + e*g/y*r;
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
152
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
153 than
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
154
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
155 r * (1 + e*g/y);
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
156
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
157 since the addition in the latter throws away most of the bits of
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
158 information in e*g/y.
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
159 */
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
160
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
161 #define LANCZOS_N 13
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
162 static const double lanczos_g = 6.024680040776729583740234375;
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
163 static const double lanczos_g_minus_half = 5.524680040776729583740234375;
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
164 static const double lanczos_num_coeffs[LANCZOS_N] = {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
165 23531376880.410759688572007674451636754734846804940,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
166 42919803642.649098768957899047001988850926355848959,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
167 35711959237.355668049440185451547166705960488635843,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
168 17921034426.037209699919755754458931112671403265390,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
169 6039542586.3520280050642916443072979210699388420708,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
170 1439720407.3117216736632230727949123939715485786772,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
171 248874557.86205415651146038641322942321632125127801,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
172 31426415.585400194380614231628318205362874684987640,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
173 2876370.6289353724412254090516208496135991145378768,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
174 186056.26539522349504029498971604569928220784236328,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
175 8071.6720023658162106380029022722506138218516325024,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
176 210.82427775157934587250973392071336271166969580291,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
177 2.5066282746310002701649081771338373386264310793408
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
178 };
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
179
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
180 /* denominator is x*(x+1)*...*(x+LANCZOS_N-2) */
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
181 static const double lanczos_den_coeffs[LANCZOS_N] = {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
182 0.0, 39916800.0, 120543840.0, 150917976.0, 105258076.0, 45995730.0,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
183 13339535.0, 2637558.0, 357423.0, 32670.0, 1925.0, 66.0, 1.0};
19750
35b6a1d0b1e0 Rework the way we try to check for libm overflow, given that C99 no longer
Tim Peters <tim.peters@gmail.com>
parents: 19730
diff changeset
184
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
185 /* gamma values for small positive integers, 1 though NGAMMA_INTEGRAL */
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
186 #define NGAMMA_INTEGRAL 23
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
187 static const double gamma_integral[NGAMMA_INTEGRAL] = {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
188 1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
189 3628800.0, 39916800.0, 479001600.0, 6227020800.0, 87178291200.0,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
190 1307674368000.0, 20922789888000.0, 355687428096000.0,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
191 6402373705728000.0, 121645100408832000.0, 2432902008176640000.0,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
192 51090942171709440000.0, 1124000727777607680000.0,
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
193 };
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
194
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
195 /* Lanczos' sum L_g(x), for positive x */
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
196
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
197 static double
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
198 lanczos_sum(double x)
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
199 {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
200 double num = 0.0, den = 0.0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
201 int i;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
202 assert(x > 0.0);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
203 /* evaluate the rational function lanczos_sum(x). For large
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
204 x, the obvious algorithm risks overflow, so we instead
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
205 rescale the denominator and numerator of the rational
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
206 function by x**(1-LANCZOS_N) and treat this as a
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
207 rational function in 1/x. This also reduces the error for
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
208 larger x values. The choice of cutoff point (5.0 below) is
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
209 somewhat arbitrary; in tests, smaller cutoff values than
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
210 this resulted in lower accuracy. */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
211 if (x < 5.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
212 for (i = LANCZOS_N; --i >= 0; ) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
213 num = num * x + lanczos_num_coeffs[i];
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
214 den = den * x + lanczos_den_coeffs[i];
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
215 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
216 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
217 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
218 for (i = 0; i < LANCZOS_N; i++) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
219 num = num / x + lanczos_num_coeffs[i];
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
220 den = den / x + lanczos_den_coeffs[i];
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
221 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
222 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
223 return num/den;
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
224 }
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
225
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
226 static double
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
227 m_tgamma(double x)
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
228 {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
229 double absx, r, y, z, sqrtpow;
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
230
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
231 /* special cases */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
232 if (!Py_IS_FINITE(x)) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
233 if (Py_IS_NAN(x) || x > 0.0)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
234 return x; /* tgamma(nan) = nan, tgamma(inf) = inf */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
235 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
236 errno = EDOM;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
237 return Py_NAN; /* tgamma(-inf) = nan, invalid */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
238 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
239 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
240 if (x == 0.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
241 errno = EDOM;
72467
7482d0e3476a Return +-Py_HUGE_VAL for tgamma(+-0) instead of risking FP exceptions by computing 1.0 / 0.0.
Mark Dickinson <mdickinson@enthought.com>
parents: 69975
diff changeset
242 /* tgamma(+-0.0) = +-inf, divide-by-zero */
7482d0e3476a Return +-Py_HUGE_VAL for tgamma(+-0) instead of risking FP exceptions by computing 1.0 / 0.0.
Mark Dickinson <mdickinson@enthought.com>
parents: 69975
diff changeset
243 return copysign(Py_HUGE_VAL, x);
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
244 }
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
245
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
246 /* integer arguments */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
247 if (x == floor(x)) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
248 if (x < 0.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
249 errno = EDOM; /* tgamma(n) = nan, invalid for */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
250 return Py_NAN; /* negative integers n */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
251 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
252 if (x <= NGAMMA_INTEGRAL)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
253 return gamma_integral[(int)x - 1];
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
254 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
255 absx = fabs(x);
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
256
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
257 /* tiny arguments: tgamma(x) ~ 1/x for x near 0 */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
258 if (absx < 1e-20) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
259 r = 1.0/x;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
260 if (Py_IS_INFINITY(r))
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
261 errno = ERANGE;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
262 return r;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
263 }
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
264
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
265 /* large arguments: assuming IEEE 754 doubles, tgamma(x) overflows for
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
266 x > 200, and underflows to +-0.0 for x < -200, not a negative
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
267 integer. */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
268 if (absx > 200.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
269 if (x < 0.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
270 return 0.0/sinpi(x);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
271 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
272 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
273 errno = ERANGE;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
274 return Py_HUGE_VAL;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
275 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
276 }
19750
35b6a1d0b1e0 Rework the way we try to check for libm overflow, given that C99 no longer
Tim Peters <tim.peters@gmail.com>
parents: 19730
diff changeset
277
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
278 y = absx + lanczos_g_minus_half;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
279 /* compute error in sum */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
280 if (absx > lanczos_g_minus_half) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
281 /* note: the correction can be foiled by an optimizing
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
282 compiler that (incorrectly) thinks that an expression like
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
283 a + b - a - b can be optimized to 0.0. This shouldn't
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
284 happen in a standards-conforming compiler. */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
285 double q = y - absx;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
286 z = q - lanczos_g_minus_half;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
287 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
288 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
289 double q = y - lanczos_g_minus_half;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
290 z = q - absx;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
291 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
292 z = z * lanczos_g / y;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
293 if (x < 0.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
294 r = -pi / sinpi(absx) / absx * exp(y) / lanczos_sum(absx);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
295 r -= z * r;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
296 if (absx < 140.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
297 r /= pow(y, absx - 0.5);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
298 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
299 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
300 sqrtpow = pow(y, absx / 2.0 - 0.25);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
301 r /= sqrtpow;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
302 r /= sqrtpow;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
303 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
304 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
305 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
306 r = lanczos_sum(absx) / exp(y);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
307 r += z * r;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
308 if (absx < 140.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
309 r *= pow(y, absx - 0.5);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
310 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
311 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
312 sqrtpow = pow(y, absx / 2.0 - 0.25);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
313 r *= sqrtpow;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
314 r *= sqrtpow;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
315 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
316 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
317 if (Py_IS_INFINITY(r))
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
318 errno = ERANGE;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
319 return r;
498
56bb1067a880 Improve error handling.
Guido van Rossum <guido@python.org>
parents: 438
diff changeset
320 }
56bb1067a880 Improve error handling.
Guido van Rossum <guido@python.org>
parents: 438
diff changeset
321
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
322 /*
57660
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
323 lgamma: natural log of the absolute value of the Gamma function.
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
324 For large arguments, Lanczos' formula works extremely well here.
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
325 */
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
326
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
327 static double
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
328 m_lgamma(double x)
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
329 {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
330 double r, absx;
57660
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
331
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
332 /* special cases */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
333 if (!Py_IS_FINITE(x)) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
334 if (Py_IS_NAN(x))
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
335 return x; /* lgamma(nan) = nan */
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
336 else
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
337 return Py_HUGE_VAL; /* lgamma(+-inf) = +inf */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
338 }
57660
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
339
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
340 /* integer arguments */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
341 if (x == floor(x) && x <= 2.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
342 if (x <= 0.0) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
343 errno = EDOM; /* lgamma(n) = inf, divide-by-zero for */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
344 return Py_HUGE_VAL; /* integers n <= 0 */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
345 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
346 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
347 return 0.0; /* lgamma(1) = lgamma(2) = 0.0 */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
348 }
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
349 }
57660
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
350
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
351 absx = fabs(x);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
352 /* tiny arguments: lgamma(x) ~ -log(fabs(x)) for small x */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
353 if (absx < 1e-20)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
354 return -log(absx);
57660
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
355
62843
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
356 /* Lanczos' formula. We could save a fraction of a ulp in accuracy by
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
357 having a second set of numerator coefficients for lanczos_sum that
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
358 absorbed the exp(-lanczos_g) term, and throwing out the lanczos_g
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
359 subtraction below; it's probably not worth it. */
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
360 r = log(lanczos_sum(absx)) - lanczos_g;
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
361 r += (absx - 0.5) * (log(absx + lanczos_g - 0.5) - 1);
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
362 if (x < 0.0)
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
363 /* Use reflection formula to get value for negative x. */
e655849e79c6 Minor refactoring in lgamma code, for clarity.
Mark Dickinson <dickinsm@gmail.com>
parents: 62684
diff changeset
364 r = logpi - log(fabs(sinpi(absx))) - log(absx) - r;
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
365 if (Py_IS_INFINITY(r))
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
366 errno = ERANGE;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
367 return r;
57660
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
368 }
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
369
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
370 /*
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
371 Implementations of the error function erf(x) and the complementary error
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
372 function erfc(x).
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
373
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
374 Method: following 'Numerical Recipes' by Flannery, Press et. al. (2nd ed.,
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
375 Cambridge University Press), we use a series approximation for erf for
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
376 small x, and a continued fraction approximation for erfc(x) for larger x;
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
377 combined with the relations erf(-x) = -erf(x) and erfc(x) = 1.0 - erf(x),
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
378 this gives us erf(x) and erfc(x) for all x.
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
379
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
380 The series expansion used is:
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
381
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
382 erf(x) = x*exp(-x*x)/sqrt(pi) * [
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
383 2/1 + 4/3 x**2 + 8/15 x**4 + 16/105 x**6 + ...]
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
384
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
385 The coefficient of x**(2k-2) here is 4**k*factorial(k)/factorial(2*k).
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
386 This series converges well for smallish x, but slowly for larger x.
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
387
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
388 The continued fraction expansion used is:
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
389
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
390 erfc(x) = x*exp(-x*x)/sqrt(pi) * [1/(0.5 + x**2 -) 0.5/(2.5 + x**2 - )
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
391 3.0/(4.5 + x**2 - ) 7.5/(6.5 + x**2 - ) ...]
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
392
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
393 after the first term, the general term has the form:
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
394
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
395 k*(k-0.5)/(2*k+0.5 + x**2 - ...).
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
396
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
397 This expansion converges fast for larger x, but convergence becomes
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
398 infinitely slow as x approaches 0.0. The (somewhat naive) continued
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
399 fraction evaluation algorithm used below also risks overflow for large x;
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
400 but for large x, erfc(x) == 0.0 to within machine precision. (For
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
401 example, erfc(30.0) is approximately 2.56e-393).
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
402
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
403 Parameters: use series expansion for abs(x) < ERF_SERIES_CUTOFF and
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
404 continued fraction expansion for ERF_SERIES_CUTOFF <= abs(x) <
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
405 ERFC_CONTFRAC_CUTOFF. ERFC_SERIES_TERMS and ERFC_CONTFRAC_TERMS are the
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
406 numbers of terms to use for the relevant expansions. */
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
407
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
408 #define ERF_SERIES_CUTOFF 1.5
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
409 #define ERF_SERIES_TERMS 25
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
410 #define ERFC_CONTFRAC_CUTOFF 30.0
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
411 #define ERFC_CONTFRAC_TERMS 50
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
412
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
413 /*
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
414 Error function, via power series.
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
415
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
416 Given a finite float x, return an approximation to erf(x).
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
417 Converges reasonably fast for small x.
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
418 */
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
419
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
420 static double
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
421 m_erf_series(double x)
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
422 {
62317
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
423 double x2, acc, fk, result;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
424 int i, saved_errno;
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
425
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
426 x2 = x * x;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
427 acc = 0.0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
428 fk = (double)ERF_SERIES_TERMS + 0.5;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
429 for (i = 0; i < ERF_SERIES_TERMS; i++) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
430 acc = 2.0 + x2 * acc / fk;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
431 fk -= 1.0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
432 }
62317
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
433 /* Make sure the exp call doesn't affect errno;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
434 see m_erfc_contfrac for more. */
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
435 saved_errno = errno;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
436 result = acc * x * exp(-x2) / sqrtpi;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
437 errno = saved_errno;
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
438 return result;
498
56bb1067a880 Improve error handling.
Guido van Rossum <guido@python.org>
parents: 438
diff changeset
439 }
56bb1067a880 Improve error handling.
Guido van Rossum <guido@python.org>
parents: 438
diff changeset
440
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
441 /*
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
442 Complementary error function, via continued fraction expansion.
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
443
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
444 Given a positive float x, return an approximation to erfc(x). Converges
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
445 reasonably fast for x large (say, x > 2.0), and should be safe from
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
446 overflow if x and nterms are not too large. On an IEEE 754 machine, with x
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
447 <= 30.0, we're safe up to nterms = 100. For x >= 30.0, erfc(x) is smaller
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
448 than the smallest representable nonzero float. */
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
449
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
450 static double
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
451 m_erfc_contfrac(double x)
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
452 {
62317
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
453 double x2, a, da, p, p_last, q, q_last, b, result;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
454 int i, saved_errno;
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
455
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
456 if (x >= ERFC_CONTFRAC_CUTOFF)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
457 return 0.0;
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
458
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
459 x2 = x*x;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
460 a = 0.0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
461 da = 0.5;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
462 p = 1.0; p_last = 0.0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
463 q = da + x2; q_last = 1.0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
464 for (i = 0; i < ERFC_CONTFRAC_TERMS; i++) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
465 double temp;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
466 a += da;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
467 da += 2.0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
468 b = da + x2;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
469 temp = p; p = b*p - a*p_last; p_last = temp;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
470 temp = q; q = b*q - a*q_last; q_last = temp;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
471 }
62317
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
472 /* Issue #8986: On some platforms, exp sets errno on underflow to zero;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
473 save the current errno value so that we can restore it later. */
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
474 saved_errno = errno;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
475 result = p / q * x * exp(-x2) / sqrtpi;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
476 errno = saved_errno;
d064e8934f4d Merged revisions 81967 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61599
diff changeset
477 return result;
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
478 }
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
479
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
480 /* Error function erf(x), for general x */
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
481
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
482 static double
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
483 m_erf(double x)
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
484 {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
485 double absx, cf;
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
486
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
487 if (Py_IS_NAN(x))
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
488 return x;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
489 absx = fabs(x);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
490 if (absx < ERF_SERIES_CUTOFF)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
491 return m_erf_series(x);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
492 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
493 cf = m_erfc_contfrac(absx);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
494 return x > 0.0 ? 1.0 - cf : cf - 1.0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
495 }
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
496 }
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
497
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
498 /* Complementary error function erfc(x), for general x. */
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
499
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
500 static double
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
501 m_erfc(double x)
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
502 {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
503 double absx, cf;
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
504
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
505 if (Py_IS_NAN(x))
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
506 return x;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
507 absx = fabs(x);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
508 if (absx < ERF_SERIES_CUTOFF)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
509 return 1.0 - m_erf_series(x);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
510 else {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
511 cf = m_erfc_contfrac(absx);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
512 return x > 0.0 ? cf : 2.0 - cf;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
513 }
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
514 }
57660
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
515
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
516 /*
46516
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
517 wrapper for atan2 that deals directly with special cases before
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
518 delegating to the platform libm for the remaining cases. This
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
519 is necessary to get consistent behaviour across platforms.
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
520 Windows, FreeBSD and alpha Tru64 are amongst platforms that don't
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
521 always follow C99.
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
522 */
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
523
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
524 static double
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
525 m_atan2(double y, double x)
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
526 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
527 if (Py_IS_NAN(x) || Py_IS_NAN(y))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
528 return Py_NAN;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
529 if (Py_IS_INFINITY(y)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
530 if (Py_IS_INFINITY(x)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
531 if (copysign(1., x) == 1.)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
532 /* atan2(+-inf, +inf) == +-pi/4 */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
533 return copysign(0.25*Py_MATH_PI, y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
534 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
535 /* atan2(+-inf, -inf) == +-pi*3/4 */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
536 return copysign(0.75*Py_MATH_PI, y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
537 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
538 /* atan2(+-inf, x) == +-pi/2 for finite x */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
539 return copysign(0.5*Py_MATH_PI, y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
540 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
541 if (Py_IS_INFINITY(x) || y == 0.) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
542 if (copysign(1., x) == 1.)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
543 /* atan2(+-y, +inf) = atan2(+-0, +x) = +-0. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
544 return copysign(0., y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
545 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
546 /* atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
547 return copysign(Py_MATH_PI, y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
548 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
549 return atan2(y, x);
46516
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
550 }
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
551
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
552 /*
50123
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
553 Various platforms (Solaris, OpenBSD) do nonstandard things for log(0),
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
554 log(-ve), log(NaN). Here are wrappers for log and log10 that deal with
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
555 special values directly, passing positive non-special values through to
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
556 the system log/log10.
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
557 */
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
558
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
559 static double
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
560 m_log(double x)
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
561 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
562 if (Py_IS_FINITE(x)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
563 if (x > 0.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
564 return log(x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
565 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
566 if (x == 0.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
567 return -Py_HUGE_VAL; /* log(0) = -inf */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
568 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
569 return Py_NAN; /* log(-ve) = nan */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
570 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
571 else if (Py_IS_NAN(x))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
572 return x; /* log(nan) = nan */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
573 else if (x > 0.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
574 return x; /* log(inf) = inf */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
575 else {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
576 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
577 return Py_NAN; /* log(-inf) = nan */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
578 }
50123
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
579 }
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
580
69946
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
581 /*
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
582 log2: log to base 2.
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
583
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
584 Uses an algorithm that should:
69973
627780933948 Grammatical fix for a comment for log2, to avoid referring to an *algorithm* as monotonic.
Mark Dickinson <mdickinson@enthought.com>
parents: 69971
diff changeset
585
69946
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
586 (a) produce exact results for powers of 2, and
69973
627780933948 Grammatical fix for a comment for log2, to avoid referring to an *algorithm* as monotonic.
Mark Dickinson <mdickinson@enthought.com>
parents: 69971
diff changeset
587 (b) give a monotonic log2 (for positive finite floats),
627780933948 Grammatical fix for a comment for log2, to avoid referring to an *algorithm* as monotonic.
Mark Dickinson <mdickinson@enthought.com>
parents: 69971
diff changeset
588 assuming that the system log is monotonic.
69946
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
589 */
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
590
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
591 static double
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
592 m_log2(double x)
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
593 {
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
594 if (!Py_IS_FINITE(x)) {
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
595 if (Py_IS_NAN(x))
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
596 return x; /* log2(nan) = nan */
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
597 else if (x > 0.0)
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
598 return x; /* log2(+inf) = +inf */
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
599 else {
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
600 errno = EDOM;
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
601 return Py_NAN; /* log2(-inf) = nan, invalid-operation */
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
602 }
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
603 }
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
604
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
605 if (x > 0.0) {
69975
565f43f6bed4 Issue #11888: Use system log2() when available
Victor Stinner <victor.stinner@haypocalc.com>
parents: 69973
diff changeset
606 #ifdef HAVE_LOG2
565f43f6bed4 Issue #11888: Use system log2() when available
Victor Stinner <victor.stinner@haypocalc.com>
parents: 69973
diff changeset
607 return log2(x);
565f43f6bed4 Issue #11888: Use system log2() when available
Victor Stinner <victor.stinner@haypocalc.com>
parents: 69973
diff changeset
608 #else
69946
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
609 double m;
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
610 int e;
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
611 m = frexp(x, &e);
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
612 /* We want log2(m * 2**e) == log(m) / log(2) + e. Care is needed when
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
613 * x is just greater than 1.0: in that case e is 1, log(m) is negative,
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
614 * and we get significant cancellation error from the addition of
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
615 * log(m) / log(2) to e. The slight rewrite of the expression below
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
616 * avoids this problem.
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
617 */
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
618 if (x >= 1.0) {
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
619 return log(2.0 * m) / log(2.0) + (e - 1);
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
620 }
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
621 else {
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
622 return log(m) / log(2.0) + e;
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
623 }
69975
565f43f6bed4 Issue #11888: Use system log2() when available
Victor Stinner <victor.stinner@haypocalc.com>
parents: 69973
diff changeset
624 #endif
69946
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
625 }
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
626 else if (x == 0.0) {
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
627 errno = EDOM;
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
628 return -Py_HUGE_VAL; /* log2(0) = -inf, divide-by-zero */
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
629 }
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
630 else {
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
631 errno = EDOM;
69971
12c65eb7d6de Fix cut-and-paste typo in comment: log10 -> log2.
Mark Dickinson <mdickinson@enthought.com>
parents: 69946
diff changeset
632 return Py_NAN; /* log2(-inf) = nan, invalid-operation */
69946
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
633 }
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
634 }
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
635
50123
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
636 static double
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
637 m_log10(double x)
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
638 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
639 if (Py_IS_FINITE(x)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
640 if (x > 0.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
641 return log10(x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
642 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
643 if (x == 0.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
644 return -Py_HUGE_VAL; /* log10(0) = -inf */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
645 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
646 return Py_NAN; /* log10(-ve) = nan */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
647 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
648 else if (Py_IS_NAN(x))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
649 return x; /* log10(nan) = nan */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
650 else if (x > 0.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
651 return x; /* log10(inf) = inf */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
652 else {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
653 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
654 return Py_NAN; /* log10(-inf) = nan */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
655 }
50123
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
656 }
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
657
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
658
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
659 /* Call is_error when errno != 0, and where x is the result libm
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
660 * returned. is_error will usually set up an exception and return
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
661 * true (1), but may return false (0) without setting up an exception.
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
662 */
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
663 static int
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
664 is_error(double x)
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
665 {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
666 int result = 1; /* presumption of guilt */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
667 assert(errno); /* non-zero errno is a precondition for calling */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
668 if (errno == EDOM)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
669 PyErr_SetString(PyExc_ValueError, "math domain error");
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
670
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
671 else if (errno == ERANGE) {
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
672 /* ANSI C generally requires libm functions to set ERANGE
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
673 * on overflow, but also generally *allows* them to set
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
674 * ERANGE on underflow too. There's no consistency about
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
675 * the latter across platforms.
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
676 * Alas, C99 never requires that errno be set.
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
677 * Here we suppress the underflow errors (libm functions
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
678 * should return a zero on underflow, and +- HUGE_VAL on
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
679 * overflow, so testing the result for zero suffices to
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
680 * distinguish the cases).
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
681 *
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
682 * On some platforms (Ubuntu/ia64) it seems that errno can be
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
683 * set to ERANGE for subnormal results that do *not* underflow
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
684 * to zero. So to be safe, we'll ignore ERANGE whenever the
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
685 * function result is less than one in absolute value.
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
686 */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
687 if (fabs(x) < 1.0)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
688 result = 0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
689 else
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
690 PyErr_SetString(PyExc_OverflowError,
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
691 "math range error");
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
692 }
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
693 else
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
694 /* Unexpected math error */
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
695 PyErr_SetFromErrno(PyExc_ValueError);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
696 return result;
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
697 }
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
698
50123
20a84e063052 Merged revisions 67708 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48606
diff changeset
699 /*
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
700 math_1 is used to wrap a libm function f that takes a double
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
701 arguments and returns a double.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
702
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
703 The error reporting follows these rules, which are designed to do
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
704 the right thing on C89/C99 platforms and IEEE 754/non IEEE 754
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
705 platforms.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
706
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
707 - a NaN result from non-NaN inputs causes ValueError to be raised
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
708 - an infinite result from finite inputs causes OverflowError to be
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
709 raised if can_overflow is 1, or raises ValueError if can_overflow
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
710 is 0.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
711 - if the result is finite and errno == EDOM then ValueError is
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
712 raised
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
713 - if the result is finite and nonzero and errno == ERANGE then
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
714 OverflowError is raised
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
715
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
716 The last rule is used to catch overflow on platforms which follow
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
717 C89 but for which HUGE_VAL is not an infinity.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
718
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
719 For the majority of one-argument functions these rules are enough
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
720 to ensure that Python's functions behave as specified in 'Annex F'
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
721 of the C99 standard, with the 'invalid' and 'divide-by-zero'
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
722 floating-point exceptions mapping to Python's ValueError and the
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
723 'overflow' floating-point exception mapping to OverflowError.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
724 math_1 only works for functions that don't have singularities *and*
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
725 the possibility of overflow; fortunately, that covers everything we
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
726 care about right now.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
727 */
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
728
4635
49745ddb4f69 Renamed
Barry Warsaw <barry@python.org>
parents: 4503
diff changeset
729 static PyObject *
44499
31e294d08ce1 Make math.floor and math.ceil return ints instead of floats.
Jeffrey Yasskin <jyasskin@gmail.com>
parents: 44460
diff changeset
730 math_1_to_whatever(PyObject *arg, double (*func) (double),
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
731 PyObject *(*from_double_func) (double),
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
732 int can_overflow)
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
733 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
734 double x, r;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
735 x = PyFloat_AsDouble(arg);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
736 if (x == -1.0 && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
737 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
738 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
739 PyFPE_START_PROTECT("in math_1", return 0);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
740 r = (*func)(x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
741 PyFPE_END_PROTECT(r);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
742 if (Py_IS_NAN(r) && !Py_IS_NAN(x)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
743 PyErr_SetString(PyExc_ValueError,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
744 "math domain error"); /* invalid arg */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
745 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
746 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
747 if (Py_IS_INFINITY(r) && Py_IS_FINITE(x)) {
75604
692efd6ac771 fix indentation
Benjamin Peterson <benjamin@python.org>
parents: 68257
diff changeset
748 if (can_overflow)
692efd6ac771 fix indentation
Benjamin Peterson <benjamin@python.org>
parents: 68257
diff changeset
749 PyErr_SetString(PyExc_OverflowError,
692efd6ac771 fix indentation
Benjamin Peterson <benjamin@python.org>
parents: 68257
diff changeset
750 "math range error"); /* overflow */
692efd6ac771 fix indentation
Benjamin Peterson <benjamin@python.org>
parents: 68257
diff changeset
751 else
692efd6ac771 fix indentation
Benjamin Peterson <benjamin@python.org>
parents: 68257
diff changeset
752 PyErr_SetString(PyExc_ValueError,
692efd6ac771 fix indentation
Benjamin Peterson <benjamin@python.org>
parents: 68257
diff changeset
753 "math domain error"); /* singularity */
692efd6ac771 fix indentation
Benjamin Peterson <benjamin@python.org>
parents: 68257
diff changeset
754 return NULL;
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
755 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
756 if (Py_IS_FINITE(r) && errno && is_error(r))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
757 /* this branch unnecessary on most platforms */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
758 return NULL;
46617
e42fe19ba6fd Whoops. errno should only be tested when the result is finite.
Mark Dickinson <dickinsm@gmail.com>
parents: 46616
diff changeset
759
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
760 return (*from_double_func)(r);
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
761 }
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
762
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
763 /* variant of math_1, to be used when the function being wrapped is known to
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
764 set errno properly (that is, errno = EDOM for invalid or divide-by-zero,
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
765 errno = ERANGE for overflow). */
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
766
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
767 static PyObject *
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
768 math_1a(PyObject *arg, double (*func) (double))
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
769 {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
770 double x, r;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
771 x = PyFloat_AsDouble(arg);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
772 if (x == -1.0 && PyErr_Occurred())
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
773 return NULL;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
774 errno = 0;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
775 PyFPE_START_PROTECT("in math_1a", return 0);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
776 r = (*func)(x);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
777 PyFPE_END_PROTECT(r);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
778 if (errno && is_error(r))
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
779 return NULL;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
780 return PyFloat_FromDouble(r);
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
781 }
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
782
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
783 /*
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
784 math_2 is used to wrap a libm function f that takes two double
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
785 arguments and returns a double.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
786
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
787 The error reporting follows these rules, which are designed to do
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
788 the right thing on C89/C99 platforms and IEEE 754/non IEEE 754
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
789 platforms.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
790
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
791 - a NaN result from non-NaN inputs causes ValueError to be raised
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
792 - an infinite result from finite inputs causes OverflowError to be
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
793 raised.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
794 - if the result is finite and errno == EDOM then ValueError is
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
795 raised
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
796 - if the result is finite and nonzero and errno == ERANGE then
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
797 OverflowError is raised
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
798
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
799 The last rule is used to catch overflow on platforms which follow
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
800 C89 but for which HUGE_VAL is not an infinity.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
801
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
802 For most two-argument functions (copysign, fmod, hypot, atan2)
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
803 these rules are enough to ensure that Python's functions behave as
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
804 specified in 'Annex F' of the C99 standard, with the 'invalid' and
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
805 'divide-by-zero' floating-point exceptions mapping to Python's
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
806 ValueError and the 'overflow' floating-point exception mapping to
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
807 OverflowError.
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
808 */
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
809
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
810 static PyObject *
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
811 math_1(PyObject *arg, double (*func) (double), int can_overflow)
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
812 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
813 return math_1_to_whatever(arg, func, PyFloat_FromDouble, can_overflow);
44499
31e294d08ce1 Make math.floor and math.ceil return ints instead of floats.
Jeffrey Yasskin <jyasskin@gmail.com>
parents: 44460
diff changeset
814 }
31e294d08ce1 Make math.floor and math.ceil return ints instead of floats.
Jeffrey Yasskin <jyasskin@gmail.com>
parents: 44460
diff changeset
815
31e294d08ce1 Make math.floor and math.ceil return ints instead of floats.
Jeffrey Yasskin <jyasskin@gmail.com>
parents: 44460
diff changeset
816 static PyObject *
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
817 math_1_to_int(PyObject *arg, double (*func) (double), int can_overflow)
44499
31e294d08ce1 Make math.floor and math.ceil return ints instead of floats.
Jeffrey Yasskin <jyasskin@gmail.com>
parents: 44460
diff changeset
818 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
819 return math_1_to_whatever(arg, func, PyLong_FromDouble, can_overflow);
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
820 }
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
821
4635
49745ddb4f69 Renamed
Barry Warsaw <barry@python.org>
parents: 4503
diff changeset
822 static PyObject *
40450
cc992d75d5b3 Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents: 37191
diff changeset
823 math_2(PyObject *args, double (*func) (double, double), char *funcname)
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
824 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
825 PyObject *ox, *oy;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
826 double x, y, r;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
827 if (! PyArg_UnpackTuple(args, funcname, 2, 2, &ox, &oy))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
828 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
829 x = PyFloat_AsDouble(ox);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
830 y = PyFloat_AsDouble(oy);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
831 if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
832 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
833 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
834 PyFPE_START_PROTECT("in math_2", return 0);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
835 r = (*func)(x, y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
836 PyFPE_END_PROTECT(r);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
837 if (Py_IS_NAN(r)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
838 if (!Py_IS_NAN(x) && !Py_IS_NAN(y))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
839 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
840 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
841 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
842 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
843 else if (Py_IS_INFINITY(r)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
844 if (Py_IS_FINITE(x) && Py_IS_FINITE(y))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
845 errno = ERANGE;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
846 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
847 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
848 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
849 if (errno && is_error(r))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
850 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
851 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
852 return PyFloat_FromDouble(r);
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
853 }
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
854
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
855 #define FUNC1(funcname, func, can_overflow, docstring) \
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
856 static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
857 return math_1(args, func, can_overflow); \
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
858 }\
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
859 PyDoc_STRVAR(math_##funcname##_doc, docstring);
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
860
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
861 #define FUNC1A(funcname, func, docstring) \
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
862 static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
863 return math_1a(args, func); \
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
864 }\
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
865 PyDoc_STRVAR(math_##funcname##_doc, docstring);
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
866
13326
24717405dd89 ANSI-fication, remove Py_PROTO, etc.
Fred Drake <fdrake@acm.org>
parents: 13309
diff changeset
867 #define FUNC2(funcname, func, docstring) \
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
868 static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
869 return math_2(args, func, #funcname); \
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
870 }\
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
871 PyDoc_STRVAR(math_##funcname##_doc, docstring);
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
872
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
873 FUNC1(acos, acos, 0,
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
874 "acos(x)\n\nReturn the arc cosine (measured in radians) of x.")
57866
9751ddcc1882 Merged revisions 76978 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57808
diff changeset
875 FUNC1(acosh, m_acosh, 0,
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
876 "acosh(x)\n\nReturn the hyperbolic arc cosine (measured in radians) of x.")
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
877 FUNC1(asin, asin, 0,
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
878 "asin(x)\n\nReturn the arc sine (measured in radians) of x.")
57866
9751ddcc1882 Merged revisions 76978 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57808
diff changeset
879 FUNC1(asinh, m_asinh, 0,
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
880 "asinh(x)\n\nReturn the hyperbolic arc sine (measured in radians) of x.")
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
881 FUNC1(atan, atan, 0,
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
882 "atan(x)\n\nReturn the arc tangent (measured in radians) of x.")
46516
ec48490b969a Merged revisions 62420-62421,62423-62424 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46505
diff changeset
883 FUNC2(atan2, m_atan2,
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
884 "atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n"
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
885 "Unlike atan(y/x), the signs of both x and y are considered.")
57866
9751ddcc1882 Merged revisions 76978 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57808
diff changeset
886 FUNC1(atanh, m_atanh, 0,
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
887 "atanh(x)\n\nReturn the hyperbolic arc tangent (measured in radians) of x.")
42754
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
888
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
889 static PyObject * math_ceil(PyObject *self, PyObject *number) {
74578
7d96679c5d46 use the static identifier api for looking up special methods
Benjamin Peterson <benjamin@python.org>
parents: 72510
diff changeset
890 _Py_IDENTIFIER(__ceil__);
62684
3304dc56dda4 Style/consistency nit: make math_floor and math_ceil code look the same.
Mark Dickinson <dickinsm@gmail.com>
parents: 62680
diff changeset
891 PyObject *method, *result;
42754
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
892
74578
7d96679c5d46 use the static identifier api for looking up special methods
Benjamin Peterson <benjamin@python.org>
parents: 72510
diff changeset
893 method = _PyObject_LookupSpecial(number, &PyId___ceil__);
62680
35370d7236c9 fix lookup of __ceil__
Benjamin Peterson <benjamin@python.org>
parents: 62679
diff changeset
894 if (method == NULL) {
35370d7236c9 fix lookup of __ceil__
Benjamin Peterson <benjamin@python.org>
parents: 62679
diff changeset
895 if (PyErr_Occurred())
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
896 return NULL;
62680
35370d7236c9 fix lookup of __ceil__
Benjamin Peterson <benjamin@python.org>
parents: 62679
diff changeset
897 return math_1_to_int(number, ceil, 0);
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
898 }
62684
3304dc56dda4 Style/consistency nit: make math_floor and math_ceil code look the same.
Mark Dickinson <dickinsm@gmail.com>
parents: 62680
diff changeset
899 result = PyObject_CallFunctionObjArgs(method, NULL);
3304dc56dda4 Style/consistency nit: make math_floor and math_ceil code look the same.
Mark Dickinson <dickinsm@gmail.com>
parents: 62680
diff changeset
900 Py_DECREF(method);
3304dc56dda4 Style/consistency nit: make math_floor and math_ceil code look the same.
Mark Dickinson <dickinsm@gmail.com>
parents: 62680
diff changeset
901 return result;
42754
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
902 }
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
903
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
904 PyDoc_STRVAR(math_ceil_doc,
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
905 "ceil(x)\n\nReturn the ceiling of x as an int.\n"
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
906 "This is the smallest integral value >= x.");
42754
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
907
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
908 FUNC2(copysign, copysign,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
909 "copysign(x, y)\n\nReturn x with the sign of y.")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
910 FUNC1(cos, cos, 0,
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
911 "cos(x)\n\nReturn the cosine of x (measured in radians).")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
912 FUNC1(cosh, cosh, 1,
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
913 "cosh(x)\n\nReturn the hyperbolic cosine of x.")
57770
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
914 FUNC1A(erf, m_erf,
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
915 "erf(x)\n\nError function at x.")
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
916 FUNC1A(erfc, m_erfc,
1e8164b5f36d Merged revisions 76878 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57758
diff changeset
917 "erfc(x)\n\nComplementary error function at x.")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
918 FUNC1(exp, exp, 1,
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
919 "exp(x)\n\nReturn e raised to the power of x.")
57758
b45ca11b9a3e Merged revisions 76861 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57660
diff changeset
920 FUNC1(expm1, m_expm1, 1,
b45ca11b9a3e Merged revisions 76861 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57660
diff changeset
921 "expm1(x)\n\nReturn exp(x)-1.\n"
b45ca11b9a3e Merged revisions 76861 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57660
diff changeset
922 "This function avoids the loss of precision involved in the direct "
b45ca11b9a3e Merged revisions 76861 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57660
diff changeset
923 "evaluation of exp(x)-1 for small x.")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
924 FUNC1(fabs, fabs, 0,
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
925 "fabs(x)\n\nReturn the absolute value of the float x.")
42754
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
926
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
927 static PyObject * math_floor(PyObject *self, PyObject *number) {
74578
7d96679c5d46 use the static identifier api for looking up special methods
Benjamin Peterson <benjamin@python.org>
parents: 72510
diff changeset
928 _Py_IDENTIFIER(__floor__);
62679
4b0c88275f3b account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents: 62668
diff changeset
929 PyObject *method, *result;
42754
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
930
74578
7d96679c5d46 use the static identifier api for looking up special methods
Benjamin Peterson <benjamin@python.org>
parents: 72510
diff changeset
931 method = _PyObject_LookupSpecial(number, &PyId___floor__);
62668
a89a3d92f8ae correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents: 62495
diff changeset
932 if (method == NULL) {
a89a3d92f8ae correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents: 62495
diff changeset
933 if (PyErr_Occurred())
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
934 return NULL;
62668
a89a3d92f8ae correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents: 62495
diff changeset
935 return math_1_to_int(number, floor, 0);
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
936 }
62679
4b0c88275f3b account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents: 62668
diff changeset
937 result = PyObject_CallFunctionObjArgs(method, NULL);
4b0c88275f3b account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents: 62668
diff changeset
938 Py_DECREF(method);
4b0c88275f3b account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents: 62668
diff changeset
939 return result;
42754
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
940 }
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
941
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
942 PyDoc_STRVAR(math_floor_doc,
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
943 "floor(x)\n\nReturn the floor of x as an int.\n"
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
944 "This is the largest integral value <= x.");
42754
1c98b445d847 Fix math.ceil() and math.floor() to fall back to __ceil__ and __floor__
Guido van Rossum <guido@python.org>
parents: 42334
diff changeset
945
56270
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
946 FUNC1A(gamma, m_tgamma,
47b82fbdc2bb Merged revisions 75117 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 50250
diff changeset
947 "gamma(x)\n\nGamma function at x.")
57660
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
948 FUNC1A(lgamma, m_lgamma,
7cb73e7c176d Merged revisions 76755 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57209
diff changeset
949 "lgamma(x)\n\nNatural logarithm of absolute value of Gamma function at x.")
62844
87555f45cd6b Issue #9186: log1p(-1.0) should raise ValueError, not OverflowError.
Mark Dickinson <dickinsm@gmail.com>
parents: 62843
diff changeset
950 FUNC1(log1p, m_log1p, 0,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
951 "log1p(x)\n\nReturn the natural logarithm of 1+x (base e).\n"
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
952 "The result is computed in a way which is accurate for x near zero.")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
953 FUNC1(sin, sin, 0,
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
954 "sin(x)\n\nReturn the sine of x (measured in radians).")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
955 FUNC1(sinh, sinh, 1,
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
956 "sinh(x)\n\nReturn the hyperbolic sine of x.")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
957 FUNC1(sqrt, sqrt, 0,
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
958 "sqrt(x)\n\nReturn the square root of x.")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
959 FUNC1(tan, tan, 0,
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
960 "tan(x)\n\nReturn the tangent of x (measured in radians).")
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
961 FUNC1(tanh, tanh, 0,
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
962 "tanh(x)\n\nReturn the hyperbolic tangent of x.")
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
963
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
964 /* Precision summation function as msum() by Raymond Hettinger in
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
965 <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/393090>,
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
966 enhanced with the exact partials sum and roundoff from Mark
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
967 Dickinson's post at <http://bugs.python.org/file10357/msum4.py>.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
968 See those links for more details, proofs and other references.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
969
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
970 Note 1: IEEE 754R floating point semantics are assumed,
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
971 but the current implementation does not re-establish special
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
972 value semantics across iterations (i.e. handling -Inf + Inf).
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
973
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
974 Note 2: No provision is made for intermediate overflow handling;
47559
2925b568aacc Merged revisions 63562,63570,63728,63734,63784,63788,63802,63817,63827,63839,63887,63975,63998 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47320
diff changeset
975 therefore, sum([1e+308, 1e-308, 1e+308]) returns 1e+308 while
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
976 sum([1e+308, 1e+308, 1e-308]) raises an OverflowError due to the
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
977 overflow of the first partial sum.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
978
48407
e22deaeb6c1b Merged revisions 64365,64370,64406,64408-64409,64412,64416-64417,64420-64421,64425-64428 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 48331
diff changeset
979 Note 3: The intermediate values lo, yr, and hi are declared volatile so
e22deaeb6c1b Merged revisions 64365,64370,64406,64408-64409,64412,64416-64417,64420-64421,64425-64428 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 48331
diff changeset
980 aggressive compilers won't algebraically reduce lo to always be exactly 0.0.
47559
2925b568aacc Merged revisions 63562,63570,63728,63734,63784,63788,63802,63817,63827,63839,63887,63975,63998 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47320
diff changeset
981 Also, the volatile declaration forces the values to be stored in memory as
2925b568aacc Merged revisions 63562,63570,63728,63734,63784,63788,63802,63817,63827,63839,63887,63975,63998 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47320
diff changeset
982 regular doubles instead of extended long precision (80-bit) values. This
48407
e22deaeb6c1b Merged revisions 64365,64370,64406,64408-64409,64412,64416-64417,64420-64421,64425-64428 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 48331
diff changeset
983 prevents double rounding because any addition or subtraction of two doubles
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
984 can be resolved exactly into double-sized hi and lo values. As long as the
47559
2925b568aacc Merged revisions 63562,63570,63728,63734,63784,63788,63802,63817,63827,63839,63887,63975,63998 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47320
diff changeset
985 hi value gets forced into a double before yr and lo are computed, the extra
2925b568aacc Merged revisions 63562,63570,63728,63734,63784,63788,63802,63817,63827,63839,63887,63975,63998 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47320
diff changeset
986 bits in downstream extended precision operations (x87 for example) will be
2925b568aacc Merged revisions 63562,63570,63728,63734,63784,63788,63802,63817,63827,63839,63887,63975,63998 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47320
diff changeset
987 exactly zero and therefore can be losslessly stored back into a double,
2925b568aacc Merged revisions 63562,63570,63728,63734,63784,63788,63802,63817,63827,63839,63887,63975,63998 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47320
diff changeset
988 thereby preventing double rounding.
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
989
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
990 Note 4: A similar implementation is in Modules/cmathmodule.c.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
991 Be sure to update both when making changes.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
992
48606
f121a963ab69 Merged revisions 65258,65292,65299,65308-65309,65315,65326 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48407
diff changeset
993 Note 5: The signature of math.fsum() differs from __builtin__.sum()
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
994 because the start argument doesn't make sense in the context of
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
995 accurate summation. Since the partials table is collapsed before
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
996 returning a result, sum(seq2, start=sum(seq1)) may not equal the
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
997 accurate result returned by sum(itertools.chain(seq1, seq2)).
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
998 */
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
999
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1000 #define NUM_PARTIALS 32 /* initial partials array size, on stack */
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1001
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1002 /* Extend the partials array p[] by doubling its size. */
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1003 static int /* non-zero on error */
48606
f121a963ab69 Merged revisions 65258,65292,65299,65308-65309,65315,65326 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48407
diff changeset
1004 _fsum_realloc(double **p_ptr, Py_ssize_t n,
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1005 double *ps, Py_ssize_t *m_ptr)
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1006 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1007 void *v = NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1008 Py_ssize_t m = *m_ptr;
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1009
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1010 m += m; /* double */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1011 if (n < m && m < (PY_SSIZE_T_MAX / sizeof(double))) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1012 double *p = *p_ptr;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1013 if (p == ps) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1014 v = PyMem_Malloc(sizeof(double) * m);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1015 if (v != NULL)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1016 memcpy(v, ps, sizeof(double) * n);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1017 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1018 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1019 v = PyMem_Realloc(p, sizeof(double) * m);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1020 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1021 if (v == NULL) { /* size overflow or no memory */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1022 PyErr_SetString(PyExc_MemoryError, "math.fsum partials");
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1023 return 1;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1024 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1025 *p_ptr = (double*) v;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1026 *m_ptr = m;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1027 return 0;
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1028 }
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1029
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1030 /* Full precision summation of a sequence of floats.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1031
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1032 def msum(iterable):
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1033 partials = [] # sorted, non-overlapping partial sums
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1034 for x in iterable:
62496
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1035 i = 0
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1036 for y in partials:
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1037 if abs(x) < abs(y):
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1038 x, y = y, x
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1039 hi = x + y
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1040 lo = y - (hi - x)
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1041 if lo:
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1042 partials[i] = lo
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1043 i += 1
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1044 x = hi
0c87490767bf Merged revisions 82223 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 61467
diff changeset
1045 partials[i:] = [x]
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1046 return sum_exact(partials)
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1047
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1048 Rounded x+y stored in hi with the roundoff stored in lo. Together hi+lo
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1049 are exactly equal to x+y. The inner loop applies hi/lo summation to each
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1050 partial so that the list of partial sums remains exact.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1051
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1052 Sum_exact() adds the partial sums exactly and correctly rounds the final
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1053 result (using the round-half-to-even rule). The items in partials remain
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1054 non-zero, non-special, non-overlapping and strictly increasing in
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1055 magnitude, but possibly not all having the same sign.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1056
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1057 Depends on IEEE 754 arithmetic guarantees and half-even rounding.
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1058 */
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1059
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1060 static PyObject*
48606
f121a963ab69 Merged revisions 65258,65292,65299,65308-65309,65315,65326 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48407
diff changeset
1061 math_fsum(PyObject *self, PyObject *seq)
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1062 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1063 PyObject *item, *iter, *sum = NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1064 Py_ssize_t i, j, n = 0, m = NUM_PARTIALS;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1065 double x, y, t, ps[NUM_PARTIALS], *p = ps;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1066 double xsave, special_sum = 0.0, inf_sum = 0.0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1067 volatile double hi, yr, lo;
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1068
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1069 iter = PyObject_GetIter(seq);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1070 if (iter == NULL)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1071 return NULL;
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1072
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1073 PyFPE_START_PROTECT("fsum", Py_DECREF(iter); return NULL)
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1074
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1075 for(;;) { /* for x in iterable */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1076 assert(0 <= n && n <= m);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1077 assert((m == NUM_PARTIALS && p == ps) ||
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1078 (m > NUM_PARTIALS && p != NULL));
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1079
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1080 item = PyIter_Next(iter);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1081 if (item == NULL) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1082 if (PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1083 goto _fsum_error;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1084 break;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1085 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1086 x = PyFloat_AsDouble(item);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1087 Py_DECREF(item);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1088 if (PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1089 goto _fsum_error;
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1090
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1091 xsave = x;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1092 for (i = j = 0; j < n; j++) { /* for y in partials */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1093 y = p[j];
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1094 if (fabs(x) < fabs(y)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1095 t = x; x = y; y = t;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1096 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1097 hi = x + y;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1098 yr = hi - x;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1099 lo = y - yr;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1100 if (lo != 0.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1101 p[i++] = lo;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1102 x = hi;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1103 }
48606
f121a963ab69 Merged revisions 65258,65292,65299,65308-65309,65315,65326 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48407
diff changeset
1104
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1105 n = i; /* ps[i:] = [x] */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1106 if (x != 0.0) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1107 if (! Py_IS_FINITE(x)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1108 /* a nonfinite x could arise either as
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1109 a result of intermediate overflow, or
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1110 as a result of a nan or inf in the
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1111 summands */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1112 if (Py_IS_FINITE(xsave)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1113 PyErr_SetString(PyExc_OverflowError,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1114 "intermediate overflow in fsum");
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1115 goto _fsum_error;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1116 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1117 if (Py_IS_INFINITY(xsave))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1118 inf_sum += xsave;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1119 special_sum += xsave;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1120 /* reset partials */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1121 n = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1122 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1123 else if (n >= m && _fsum_realloc(&p, n, ps, &m))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1124 goto _fsum_error;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1125 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1126 p[n++] = x;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1127 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1128 }
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1129
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1130 if (special_sum != 0.0) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1131 if (Py_IS_NAN(inf_sum))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1132 PyErr_SetString(PyExc_ValueError,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1133 "-inf + inf in fsum");
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1134 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1135 sum = PyFloat_FromDouble(special_sum);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1136 goto _fsum_error;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1137 }
48606
f121a963ab69 Merged revisions 65258,65292,65299,65308-65309,65315,65326 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48407
diff changeset
1138
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1139 hi = 0.0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1140 if (n > 0) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1141 hi = p[--n];
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1142 /* sum_exact(ps, hi) from the top, stop when the sum becomes
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1143 inexact. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1144 while (n > 0) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1145 x = hi;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1146 y = p[--n];
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1147 assert(fabs(y) < fabs(x));
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1148 hi = x + y;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1149 yr = hi - x;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1150 lo = y - yr;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1151 if (lo != 0.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1152 break;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1153 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1154 /* Make half-even rounding work across multiple partials.
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1155 Needed so that sum([1e-16, 1, 1e16]) will round-up the last
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1156 digit to two instead of down to zero (the 1e-16 makes the 1
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1157 slightly closer to two). With a potential 1 ULP rounding
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1158 error fixed-up, math.fsum() can guarantee commutativity. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1159 if (n > 0 && ((lo < 0.0 && p[n-1] < 0.0) ||
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1160 (lo > 0.0 && p[n-1] > 0.0))) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1161 y = lo * 2.0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1162 x = hi + y;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1163 yr = x - hi;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1164 if (y == yr)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1165 hi = x;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1166 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1167 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1168 sum = PyFloat_FromDouble(hi);
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1169
48606
f121a963ab69 Merged revisions 65258,65292,65299,65308-65309,65315,65326 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48407
diff changeset
1170 _fsum_error:
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1171 PyFPE_END_PROTECT(hi)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1172 Py_DECREF(iter);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1173 if (p != ps)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1174 PyMem_Free(p);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1175 return sum;
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1176 }
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1177
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1178 #undef NUM_PARTIALS
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1179
48606
f121a963ab69 Merged revisions 65258,65292,65299,65308-65309,65315,65326 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 48407
diff changeset
1180 PyDoc_STRVAR(math_fsum_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1181 "fsum(iterable)\n\n\
47320
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1182 Return an accurate floating point sum of values in the iterable.\n\
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1183 Assumes IEEE-754 floating point arithmetic.");
3975ec2b0de2 Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 47175
diff changeset
1184
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1185 /* Return the smallest integer k such that n < 2**k, or 0 if n == 0.
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1186 * Equivalent to floor(lg(x))+1. Also equivalent to: bitwidth_of_type -
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1187 * count_leading_zero_bits(x)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1188 */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1189
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1190 /* XXX: This routine does more or less the same thing as
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1191 * bits_in_digit() in Objects/longobject.c. Someday it would be nice to
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1192 * consolidate them. On BSD, there's a library function called fls()
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1193 * that we could use, and GCC provides __builtin_clz().
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1194 */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1195
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1196 static unsigned long
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1197 bit_length(unsigned long n)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1198 {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1199 unsigned long len = 0;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1200 while (n != 0) {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1201 ++len;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1202 n >>= 1;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1203 }
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1204 return len;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1205 }
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1206
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1207 static unsigned long
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1208 count_set_bits(unsigned long n)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1209 {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1210 unsigned long count = 0;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1211 while (n != 0) {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1212 ++count;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1213 n &= n - 1; /* clear least significant bit */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1214 }
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1215 return count;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1216 }
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1217
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1218 /* Divide-and-conquer factorial algorithm
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1219 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1220 * Based on the formula and psuedo-code provided at:
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1221 * http://www.luschny.de/math/factorial/binarysplitfact.html
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1222 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1223 * Faster algorithms exist, but they're more complicated and depend on
62859
ca05371cff10 Fix typo in a comment in mathmodule.c.
Ezio Melotti <ezio.melotti@gmail.com>
parents: 62844
diff changeset
1224 * a fast prime factorization algorithm.
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1225 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1226 * Notes on the algorithm
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1227 * ----------------------
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1228 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1229 * factorial(n) is written in the form 2**k * m, with m odd. k and m are
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1230 * computed separately, and then combined using a left shift.
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1231 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1232 * The function factorial_odd_part computes the odd part m (i.e., the greatest
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1233 * odd divisor) of factorial(n), using the formula:
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1234 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1235 * factorial_odd_part(n) =
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1236 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1237 * product_{i >= 0} product_{0 < j <= n / 2**i, j odd} j
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1238 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1239 * Example: factorial_odd_part(20) =
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1240 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1241 * (1) *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1242 * (1) *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1243 * (1 * 3 * 5) *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1244 * (1 * 3 * 5 * 7 * 9)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1245 * (1 * 3 * 5 * 7 * 9 * 11 * 13 * 15 * 17 * 19)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1246 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1247 * Here i goes from large to small: the first term corresponds to i=4 (any
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1248 * larger i gives an empty product), and the last term corresponds to i=0.
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1249 * Each term can be computed from the last by multiplying by the extra odd
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1250 * numbers required: e.g., to get from the penultimate term to the last one,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1251 * we multiply by (11 * 13 * 15 * 17 * 19).
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1252 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1253 * To see a hint of why this formula works, here are the same numbers as above
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1254 * but with the even parts (i.e., the appropriate powers of 2) included. For
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1255 * each subterm in the product for i, we multiply that subterm by 2**i:
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1256 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1257 * factorial(20) =
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1258 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1259 * (16) *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1260 * (8) *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1261 * (4 * 12 * 20) *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1262 * (2 * 6 * 10 * 14 * 18) *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1263 * (1 * 3 * 5 * 7 * 9 * 11 * 13 * 15 * 17 * 19)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1264 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1265 * The factorial_partial_product function computes the product of all odd j in
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1266 * range(start, stop) for given start and stop. It's used to compute the
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1267 * partial products like (11 * 13 * 15 * 17 * 19) in the example above. It
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1268 * operates recursively, repeatedly splitting the range into two roughly equal
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1269 * pieces until the subranges are small enough to be computed using only C
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1270 * integer arithmetic.
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1271 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1272 * The two-valuation k (i.e., the exponent of the largest power of 2 dividing
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1273 * the factorial) is computed independently in the main math_factorial
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1274 * function. By standard results, its value is:
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1275 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1276 * two_valuation = n//2 + n//4 + n//8 + ....
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1277 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1278 * It can be shown (e.g., by complete induction on n) that two_valuation is
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1279 * equal to n - count_set_bits(n), where count_set_bits(n) gives the number of
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1280 * '1'-bits in the binary expansion of n.
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1281 */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1282
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1283 /* factorial_partial_product: Compute product(range(start, stop, 2)) using
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1284 * divide and conquer. Assumes start and stop are odd and stop > start.
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1285 * max_bits must be >= bit_length(stop - 2). */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1286
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1287 static PyObject *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1288 factorial_partial_product(unsigned long start, unsigned long stop,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1289 unsigned long max_bits)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1290 {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1291 unsigned long midpoint, num_operands;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1292 PyObject *left = NULL, *right = NULL, *result = NULL;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1293
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1294 /* If the return value will fit an unsigned long, then we can
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1295 * multiply in a tight, fast loop where each multiply is O(1).
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1296 * Compute an upper bound on the number of bits required to store
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1297 * the answer.
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1298 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1299 * Storing some integer z requires floor(lg(z))+1 bits, which is
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1300 * conveniently the value returned by bit_length(z). The
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1301 * product x*y will require at most
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1302 * bit_length(x) + bit_length(y) bits to store, based
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1303 * on the idea that lg product = lg x + lg y.
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1304 *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1305 * We know that stop - 2 is the largest number to be multiplied. From
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1306 * there, we have: bit_length(answer) <= num_operands *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1307 * bit_length(stop - 2)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1308 */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1309
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1310 num_operands = (stop - start) / 2;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1311 /* The "num_operands <= 8 * SIZEOF_LONG" check guards against the
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1312 * unlikely case of an overflow in num_operands * max_bits. */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1313 if (num_operands <= 8 * SIZEOF_LONG &&
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1314 num_operands * max_bits <= 8 * SIZEOF_LONG) {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1315 unsigned long j, total;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1316 for (total = start, j = start + 2; j < stop; j += 2)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1317 total *= j;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1318 return PyLong_FromUnsignedLong(total);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1319 }
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1320
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1321 /* find midpoint of range(start, stop), rounded up to next odd number. */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1322 midpoint = (start + num_operands) | 1;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1323 left = factorial_partial_product(start, midpoint,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1324 bit_length(midpoint - 2));
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1325 if (left == NULL)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1326 goto error;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1327 right = factorial_partial_product(midpoint, stop, max_bits);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1328 if (right == NULL)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1329 goto error;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1330 result = PyNumber_Multiply(left, right);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1331
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1332 error:
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1333 Py_XDECREF(left);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1334 Py_XDECREF(right);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1335 return result;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1336 }
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1337
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1338 /* factorial_odd_part: compute the odd part of factorial(n). */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1339
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1340 static PyObject *
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1341 factorial_odd_part(unsigned long n)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1342 {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1343 long i;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1344 unsigned long v, lower, upper;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1345 PyObject *partial, *tmp, *inner, *outer;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1346
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1347 inner = PyLong_FromLong(1);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1348 if (inner == NULL)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1349 return NULL;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1350 outer = inner;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1351 Py_INCREF(outer);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1352
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1353 upper = 3;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1354 for (i = bit_length(n) - 2; i >= 0; i--) {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1355 v = n >> i;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1356 if (v <= 2)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1357 continue;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1358 lower = upper;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1359 /* (v + 1) | 1 = least odd integer strictly larger than n / 2**i */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1360 upper = (v + 1) | 1;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1361 /* Here inner is the product of all odd integers j in the range (0,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1362 n/2**(i+1)]. The factorial_partial_product call below gives the
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1363 product of all odd integers j in the range (n/2**(i+1), n/2**i]. */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1364 partial = factorial_partial_product(lower, upper, bit_length(upper-2));
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1365 /* inner *= partial */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1366 if (partial == NULL)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1367 goto error;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1368 tmp = PyNumber_Multiply(inner, partial);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1369 Py_DECREF(partial);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1370 if (tmp == NULL)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1371 goto error;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1372 Py_DECREF(inner);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1373 inner = tmp;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1374 /* Now inner is the product of all odd integers j in the range (0,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1375 n/2**i], giving the inner product in the formula above. */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1376
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1377 /* outer *= inner; */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1378 tmp = PyNumber_Multiply(outer, inner);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1379 if (tmp == NULL)
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1380 goto error;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1381 Py_DECREF(outer);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1382 outer = tmp;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1383 }
79933
b4bfcf7a4773 Fix math.factorial KeyboardInterrupt segfault. Thanks Amaury for report and diagnosis.
Mark Dickinson <mdickinson@enthought.com>
parents: 75604
diff changeset
1384 Py_DECREF(inner);
b4bfcf7a4773 Fix math.factorial KeyboardInterrupt segfault. Thanks Amaury for report and diagnosis.
Mark Dickinson <mdickinson@enthought.com>
parents: 75604
diff changeset
1385 return outer;
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1386
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1387 error:
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1388 Py_DECREF(outer);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1389 Py_DECREF(inner);
79933
b4bfcf7a4773 Fix math.factorial KeyboardInterrupt segfault. Thanks Amaury for report and diagnosis.
Mark Dickinson <mdickinson@enthought.com>
parents: 75604
diff changeset
1390 return NULL;
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1391 }
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1392
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1393 /* Lookup table for small factorial values */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1394
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1395 static const unsigned long SmallFactorials[] = {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1396 1, 1, 2, 6, 24, 120, 720, 5040, 40320,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1397 362880, 3628800, 39916800, 479001600,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1398 #if SIZEOF_LONG >= 8
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1399 6227020800, 87178291200, 1307674368000,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1400 20922789888000, 355687428096000, 6402373705728000,
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1401 121645100408832000, 2432902008176640000
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1402 #endif
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1403 };
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1404
4635
49745ddb4f69 Renamed
Barry Warsaw <barry@python.org>
parents: 4503
diff changeset
1405 static PyObject *
47562
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1406 math_factorial(PyObject *self, PyObject *arg)
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1407 {
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1408 long x;
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1409 PyObject *result, *odd_part, *two_valuation;
47562
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1410
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1411 if (PyFloat_Check(arg)) {
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1412 PyObject *lx;
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1413 double dx = PyFloat_AS_DOUBLE((PyFloatObject *)arg);
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1414 if (!(Py_IS_FINITE(dx) && dx == floor(dx))) {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1415 PyErr_SetString(PyExc_ValueError,
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1416 "factorial() only accepts integral values");
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1417 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1418 }
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1419 lx = PyLong_FromDouble(dx);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1420 if (lx == NULL)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1421 return NULL;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1422 x = PyLong_AsLong(lx);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1423 Py_DECREF(lx);
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1424 }
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1425 else
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1426 x = PyLong_AsLong(arg);
47562
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1427
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1428 if (x == -1 && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1429 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1430 if (x < 0) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1431 PyErr_SetString(PyExc_ValueError,
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1432 "factorial() not defined for negative values");
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1433 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1434 }
47562
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1435
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1436 /* use lookup table if x is small */
72510
b534b56379cb Use the new Py_ARRAY_LENGTH macro
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72467
diff changeset
1437 if (x < (long)Py_ARRAY_LENGTH(SmallFactorials))
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1438 return PyLong_FromUnsignedLong(SmallFactorials[x]);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1439
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1440 /* else express in the form odd_part * 2**two_valuation, and compute as
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1441 odd_part << two_valuation. */
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1442 odd_part = factorial_odd_part(x);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1443 if (odd_part == NULL)
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1444 return NULL;
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1445 two_valuation = PyLong_FromLong(x - count_set_bits(x));
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1446 if (two_valuation == NULL) {
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1447 Py_DECREF(odd_part);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1448 return NULL;
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1449 }
61599
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1450 result = PyNumber_Lshift(odd_part, two_valuation);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1451 Py_DECREF(two_valuation);
1e149b50aca6 Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents: 61466
diff changeset
1452 Py_DECREF(odd_part);
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1453 return result;
47562
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1454 }
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1455
50250
1adfabcbe073 Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50123
diff changeset
1456 PyDoc_STRVAR(math_factorial_doc,
1adfabcbe073 Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50123
diff changeset
1457 "factorial(x) -> Integral\n"
1adfabcbe073 Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50123
diff changeset
1458 "\n"
1adfabcbe073 Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50123
diff changeset
1459 "Find x!. Raise a ValueError if x is negative or non-integral.");
47562
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1460
bd584f121c4b Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
Georg Brandl <georg@python.org>
parents: 47559
diff changeset
1461 static PyObject *
45082
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1462 math_trunc(PyObject *self, PyObject *number)
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1463 {
74578
7d96679c5d46 use the static identifier api for looking up special methods
Benjamin Peterson <benjamin@python.org>
parents: 72510
diff changeset
1464 _Py_IDENTIFIER(__trunc__);
62679
4b0c88275f3b account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents: 62668
diff changeset
1465 PyObject *trunc, *result;
45082
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1466
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1467 if (Py_TYPE(number)->tp_dict == NULL) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1468 if (PyType_Ready(Py_TYPE(number)) < 0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1469 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1470 }
45082
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1471
74578
7d96679c5d46 use the static identifier api for looking up special methods
Benjamin Peterson <benjamin@python.org>
parents: 72510
diff changeset
1472 trunc = _PyObject_LookupSpecial(number, &PyId___trunc__);
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1473 if (trunc == NULL) {
62668
a89a3d92f8ae correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents: 62495
diff changeset
1474 if (!PyErr_Occurred())
a89a3d92f8ae correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents: 62495
diff changeset
1475 PyErr_Format(PyExc_TypeError,
a89a3d92f8ae correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents: 62495
diff changeset
1476 "type %.100s doesn't define __trunc__ method",
a89a3d92f8ae correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents: 62495
diff changeset
1477 Py_TYPE(number)->tp_name);
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1478 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1479 }
62679
4b0c88275f3b account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents: 62668
diff changeset
1480 result = PyObject_CallFunctionObjArgs(trunc, NULL);
4b0c88275f3b account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents: 62668
diff changeset
1481 Py_DECREF(trunc);
4b0c88275f3b account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents: 62668
diff changeset
1482 return result;
45082
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1483 }
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1484
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1485 PyDoc_STRVAR(math_trunc_doc,
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1486 "trunc(x:Real) -> Integral\n"
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1487 "\n"
45134
bdcf40d1b38e Merged revisions 60481,60485,60489-60520,60523-60527,60530-60533,60535-60538,60540-60551 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45082
diff changeset
1488 "Truncates x to the nearest Integral toward 0. Uses the __trunc__ magic method.");
45082
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1489
d7540031b959 Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45029
diff changeset
1490 static PyObject *
40450
cc992d75d5b3 Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents: 37191
diff changeset
1491 math_frexp(PyObject *self, PyObject *arg)
407
9b3d557665a9 Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents: 320
diff changeset
1492 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1493 int i;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1494 double x = PyFloat_AsDouble(arg);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1495 if (x == -1.0 && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1496 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1497 /* deal with special cases directly, to sidestep platform
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1498 differences */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1499 if (Py_IS_NAN(x) || Py_IS_INFINITY(x) || !x) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1500 i = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1501 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1502 else {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1503 PyFPE_START_PROTECT("in math_frexp", return 0);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1504 x = frexp(x, &i);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1505 PyFPE_END_PROTECT(x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1506 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1507 return Py_BuildValue("(di)", x, i);
407
9b3d557665a9 Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents: 320
diff changeset
1508 }
9b3d557665a9 Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents: 320
diff changeset
1509
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1510 PyDoc_STRVAR(math_frexp_doc,
19712
b4521436e8f8 Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents: 19048
diff changeset
1511 "frexp(x)\n"
b4521436e8f8 Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents: 19048
diff changeset
1512 "\n"
b4521436e8f8 Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents: 19048
diff changeset
1513 "Return the mantissa and exponent of x, as pair (m, e).\n"
b4521436e8f8 Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents: 19048
diff changeset
1514 "m is a float and e is an int, such that x = m * 2.**e.\n"
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1515 "If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0.");
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
1516
4635
49745ddb4f69 Renamed
Barry Warsaw <barry@python.org>
parents: 4503
diff changeset
1517 static PyObject *
13326
24717405dd89 ANSI-fication, remove Py_PROTO, etc.
Fred Drake <fdrake@acm.org>
parents: 13309
diff changeset
1518 math_ldexp(PyObject *self, PyObject *args)
407
9b3d557665a9 Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents: 320
diff changeset
1519 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1520 double x, r;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1521 PyObject *oexp;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1522 long exp;
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1523 int overflow;
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1524 if (! PyArg_ParseTuple(args, "dO:ldexp", &x, &oexp))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1525 return NULL;
47063
081c15806e28 Merged revisions 62914-62916,62918-62919,62921-62922,62924-62942,62944-62945,62947-62949 via svnmerge from
Alexandre Vassalotti <alexandre@peadrop.com>
parents: 46791
diff changeset
1526
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1527 if (PyLong_Check(oexp)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1528 /* on overflow, replace exponent with either LONG_MAX
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1529 or LONG_MIN, depending on the sign. */
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1530 exp = PyLong_AsLongAndOverflow(oexp, &overflow);
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1531 if (exp == -1 && PyErr_Occurred())
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1532 return NULL;
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1533 if (overflow)
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1534 exp = overflow < 0 ? LONG_MIN : LONG_MAX;
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1535 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1536 else {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1537 PyErr_SetString(PyExc_TypeError,
85418
4d62a62ba44d Issue #18783: Removed existing mentions of Python long type in docstrings,
Serhiy Storchaka <storchaka@gmail.com>
parents: 79934
diff changeset
1538 "Expected an int as second argument to ldexp.");
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1539 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1540 }
47063
081c15806e28 Merged revisions 62914-62916,62918-62919,62921-62922,62924-62942,62944-62945,62947-62949 via svnmerge from
Alexandre Vassalotti <alexandre@peadrop.com>
parents: 46791
diff changeset
1541
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1542 if (x == 0. || !Py_IS_FINITE(x)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1543 /* NaNs, zeros and infinities are returned unchanged */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1544 r = x;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1545 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1546 } else if (exp > INT_MAX) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1547 /* overflow */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1548 r = copysign(Py_HUGE_VAL, x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1549 errno = ERANGE;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1550 } else if (exp < INT_MIN) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1551 /* underflow to +-0 */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1552 r = copysign(0., x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1553 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1554 } else {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1555 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1556 PyFPE_START_PROTECT("in math_ldexp", return 0);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1557 r = ldexp(x, (int)exp);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1558 PyFPE_END_PROTECT(r);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1559 if (Py_IS_INFINITY(r))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1560 errno = ERANGE;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1561 }
47063
081c15806e28 Merged revisions 62914-62916,62918-62919,62921-62922,62924-62942,62944-62945,62947-62949 via svnmerge from
Alexandre Vassalotti <alexandre@peadrop.com>
parents: 46791
diff changeset
1562
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1563 if (errno && is_error(r))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1564 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1565 return PyFloat_FromDouble(r);
407
9b3d557665a9 Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents: 320
diff changeset
1566 }
9b3d557665a9 Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents: 320
diff changeset
1567
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1568 PyDoc_STRVAR(math_ldexp_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1569 "ldexp(x, i)\n\n\
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1570 Return x * (2**i).");
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
1571
4635
49745ddb4f69 Renamed
Barry Warsaw <barry@python.org>
parents: 4503
diff changeset
1572 static PyObject *
40450
cc992d75d5b3 Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents: 37191
diff changeset
1573 math_modf(PyObject *self, PyObject *arg)
407
9b3d557665a9 Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents: 320
diff changeset
1574 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1575 double y, x = PyFloat_AsDouble(arg);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1576 if (x == -1.0 && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1577 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1578 /* some platforms don't do the right thing for NaNs and
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1579 infinities, so we take care of special cases directly. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1580 if (!Py_IS_FINITE(x)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1581 if (Py_IS_INFINITY(x))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1582 return Py_BuildValue("(dd)", copysign(0., x), x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1583 else if (Py_IS_NAN(x))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1584 return Py_BuildValue("(dd)", x, x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1585 }
46505
63965327b3ef Merged revisions 62386-62387,62389-62393,62396,62400-62402,62407,62409-62410,62412-62414,62418-62419 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46477
diff changeset
1586
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1587 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1588 PyFPE_START_PROTECT("in math_modf", return 0);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1589 x = modf(x, &y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1590 PyFPE_END_PROTECT(x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1591 return Py_BuildValue("(dd)", x, y);
407
9b3d557665a9 Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents: 320
diff changeset
1592 }
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
1593
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1594 PyDoc_STRVAR(math_modf_doc,
19712
b4521436e8f8 Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents: 19048
diff changeset
1595 "modf(x)\n"
b4521436e8f8 Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents: 19048
diff changeset
1596 "\n"
b4521436e8f8 Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents: 19048
diff changeset
1597 "Return the fractional and integer parts of x. Both results carry the sign\n"
50250
1adfabcbe073 Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50123
diff changeset
1598 "of x and are floats.");
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
1599
85418
4d62a62ba44d Issue #18783: Removed existing mentions of Python long type in docstrings,
Serhiy Storchaka <storchaka@gmail.com>
parents: 79934
diff changeset
1600 /* A decent logarithm is easy to compute even for huge ints, but libm can't
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1601 do that by itself -- loghelper can. func is log or log10, and name is
85418
4d62a62ba44d Issue #18783: Removed existing mentions of Python long type in docstrings,
Serhiy Storchaka <storchaka@gmail.com>
parents: 79934
diff changeset
1602 "log" or "log10". Note that overflow of the result isn't possible: an int
58088
46d60e5ff103 Merged revisions 77234 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57866
diff changeset
1603 can contain no more than INT_MAX * SHIFT bits, so has value certainly less
46d60e5ff103 Merged revisions 77234 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents: 57866
diff changeset
1604 than 2**(2**64 * 2**16) == 2**2**80, and log2 of that is 2**80, which is
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1605 small enough to fit in an IEEE single. log and log10 are even smaller.
85418
4d62a62ba44d Issue #18783: Removed existing mentions of Python long type in docstrings,
Serhiy Storchaka <storchaka@gmail.com>
parents: 79934
diff changeset
1606 However, intermediate overflow is possible for an int if the number of bits
4d62a62ba44d Issue #18783: Removed existing mentions of Python long type in docstrings,
Serhiy Storchaka <storchaka@gmail.com>
parents: 79934
diff changeset
1607 in that int is larger than PY_SSIZE_T_MAX. */
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1608
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1609 static PyObject*
40450
cc992d75d5b3 Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents: 37191
diff changeset
1610 loghelper(PyObject* arg, double (*func)(double), char *funcname)
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1611 {
85418
4d62a62ba44d Issue #18783: Removed existing mentions of Python long type in docstrings,
Serhiy Storchaka <storchaka@gmail.com>
parents: 79934
diff changeset
1612 /* If it is int, do it ourselves. */
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1613 if (PyLong_Check(arg)) {
65026
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1614 double x, result;
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1615 Py_ssize_t e;
65026
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1616
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1617 /* Negative or zero inputs give a ValueError. */
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1618 if (Py_SIZE(arg) <= 0) {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1619 PyErr_SetString(PyExc_ValueError,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1620 "math domain error");
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1621 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1622 }
64969
c8dc4b5e54fb Issue #9599: Tweak loghelper algorithm to return slightly improved results for powers of 2.
Mark Dickinson <dickinsm@gmail.com>
parents: 62970
diff changeset
1623
65026
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1624 x = PyLong_AsDouble(arg);
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1625 if (x == -1.0 && PyErr_Occurred()) {
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1626 if (!PyErr_ExceptionMatches(PyExc_OverflowError))
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1627 return NULL;
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1628 /* Here the conversion to double overflowed, but it's possible
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1629 to compute the log anyway. Clear the exception and continue. */
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1630 PyErr_Clear();
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1631 x = _PyLong_Frexp((PyLongObject *)arg, &e);
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1632 if (x == -1.0 && PyErr_Occurred())
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1633 return NULL;
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1634 /* Value is ~= x * 2**e, so the log ~= log(x) + log(2) * e. */
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1635 result = func(x) + func(2.0) * e;
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1636 }
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1637 else
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1638 /* Successfully converted x to a double. */
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1639 result = func(x);
a9349fd3d0f7 Issue #9599: Further accuracy tweaks to loghelper. For an integer n that's small enough to be converted to a float without overflow, log(n) is now computed as log(float(n)), and similarly for log10.
Mark Dickinson <dickinsm@gmail.com>
parents: 64969
diff changeset
1640 return PyFloat_FromDouble(result);
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1641 }
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1642
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1643 /* Else let libm handle it by itself. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1644 return math_1(arg, func, 0);
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1645 }
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1646
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1647 static PyObject *
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1648 math_log(PyObject *self, PyObject *args)
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1649 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1650 PyObject *arg;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1651 PyObject *base = NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1652 PyObject *num, *den;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1653 PyObject *ans;
26661
b12e326b4ea2 Apply SF patch 652930: Add optional base argument to math.log(x[, base]).
Raymond Hettinger <python@rcn.com>
parents: 24471
diff changeset
1654
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1655 if (!PyArg_UnpackTuple(args, "log", 1, 2, &arg, &base))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1656 return NULL;
26661
b12e326b4ea2 Apply SF patch 652930: Add optional base argument to math.log(x[, base]).
Raymond Hettinger <python@rcn.com>
parents: 24471
diff changeset
1657
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1658 num = loghelper(arg, m_log, "log");
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1659 if (num == NULL || base == NULL)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1660 return num;
26661
b12e326b4ea2 Apply SF patch 652930: Add optional base argument to math.log(x[, base]).
Raymond Hettinger <python@rcn.com>
parents: 24471
diff changeset
1661
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1662 den = loghelper(base, m_log, "log");
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1663 if (den == NULL) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1664 Py_DECREF(num);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1665 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1666 }
26661
b12e326b4ea2 Apply SF patch 652930: Add optional base argument to math.log(x[, base]).
Raymond Hettinger <python@rcn.com>
parents: 24471
diff changeset
1667
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1668 ans = PyNumber_TrueDivide(num, den);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1669 Py_DECREF(num);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1670 Py_DECREF(den);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1671 return ans;
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1672 }
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1673
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1674 PyDoc_STRVAR(math_log_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1675 "log(x[, base])\n\n\
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1676 Return the logarithm of x to the given base.\n\
26661
b12e326b4ea2 Apply SF patch 652930: Add optional base argument to math.log(x[, base]).
Raymond Hettinger <python@rcn.com>
parents: 24471
diff changeset
1677 If the base not specified, returns the natural logarithm (base e) of x.");
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1678
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1679 static PyObject *
69946
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1680 math_log2(PyObject *self, PyObject *arg)
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1681 {
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1682 return loghelper(arg, m_log2, "log2");
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1683 }
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1684
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1685 PyDoc_STRVAR(math_log2_doc,
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1686 "log2(x)\n\nReturn the base 2 logarithm of x.");
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1687
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1688 static PyObject *
40450
cc992d75d5b3 Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents: 37191
diff changeset
1689 math_log10(PyObject *self, PyObject *arg)
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1690 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1691 return loghelper(arg, m_log10, "log10");
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1692 }
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1693
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1694 PyDoc_STRVAR(math_log10_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1695 "log10(x)\n\nReturn the base 10 logarithm of x.");
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1696
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1697 static PyObject *
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1698 math_fmod(PyObject *self, PyObject *args)
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1699 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1700 PyObject *ox, *oy;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1701 double r, x, y;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1702 if (! PyArg_UnpackTuple(args, "fmod", 2, 2, &ox, &oy))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1703 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1704 x = PyFloat_AsDouble(ox);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1705 y = PyFloat_AsDouble(oy);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1706 if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1707 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1708 /* fmod(x, +/-Inf) returns x for finite x. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1709 if (Py_IS_INFINITY(y) && Py_IS_FINITE(x))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1710 return PyFloat_FromDouble(x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1711 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1712 PyFPE_START_PROTECT("in math_fmod", return 0);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1713 r = fmod(x, y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1714 PyFPE_END_PROTECT(r);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1715 if (Py_IS_NAN(r)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1716 if (!Py_IS_NAN(x) && !Py_IS_NAN(y))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1717 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1718 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1719 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1720 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1721 if (errno && is_error(r))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1722 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1723 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1724 return PyFloat_FromDouble(r);
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1725 }
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1726
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1727 PyDoc_STRVAR(math_fmod_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1728 "fmod(x, y)\n\nReturn fmod(x, y), according to platform C."
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1729 " x % y may differ.");
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1730
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1731 static PyObject *
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1732 math_hypot(PyObject *self, PyObject *args)
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1733 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1734 PyObject *ox, *oy;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1735 double r, x, y;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1736 if (! PyArg_UnpackTuple(args, "hypot", 2, 2, &ox, &oy))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1737 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1738 x = PyFloat_AsDouble(ox);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1739 y = PyFloat_AsDouble(oy);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1740 if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1741 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1742 /* hypot(x, +/-Inf) returns Inf, even if x is a NaN. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1743 if (Py_IS_INFINITY(x))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1744 return PyFloat_FromDouble(fabs(x));
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1745 if (Py_IS_INFINITY(y))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1746 return PyFloat_FromDouble(fabs(y));
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1747 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1748 PyFPE_START_PROTECT("in math_hypot", return 0);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1749 r = hypot(x, y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1750 PyFPE_END_PROTECT(r);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1751 if (Py_IS_NAN(r)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1752 if (!Py_IS_NAN(x) && !Py_IS_NAN(y))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1753 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1754 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1755 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1756 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1757 else if (Py_IS_INFINITY(r)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1758 if (Py_IS_FINITE(x) && Py_IS_FINITE(y))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1759 errno = ERANGE;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1760 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1761 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1762 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1763 if (errno && is_error(r))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1764 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1765 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1766 return PyFloat_FromDouble(r);
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1767 }
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1768
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1769 PyDoc_STRVAR(math_hypot_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1770 "hypot(x, y)\n\nReturn the Euclidean distance, sqrt(x*x + y*y).");
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1771
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1772 /* pow can't use math_2, but needs its own wrapper: the problem is
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1773 that an infinite result can arise either as a result of overflow
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1774 (in which case OverflowError should be raised) or as a result of
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1775 e.g. 0.**-5. (for which ValueError needs to be raised.)
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1776 */
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1777
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1778 static PyObject *
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1779 math_pow(PyObject *self, PyObject *args)
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1780 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1781 PyObject *ox, *oy;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1782 double r, x, y;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1783 int odd_y;
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1784
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1785 if (! PyArg_UnpackTuple(args, "pow", 2, 2, &ox, &oy))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1786 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1787 x = PyFloat_AsDouble(ox);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1788 y = PyFloat_AsDouble(oy);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1789 if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1790 return NULL;
46505
63965327b3ef Merged revisions 62386-62387,62389-62393,62396,62400-62402,62407,62409-62410,62412-62414,62418-62419 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 46477
diff changeset
1791
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1792 /* deal directly with IEEE specials, to cope with problems on various
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1793 platforms whose semantics don't exactly match C99 */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1794 r = 0.; /* silence compiler warning */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1795 if (!Py_IS_FINITE(x) || !Py_IS_FINITE(y)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1796 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1797 if (Py_IS_NAN(x))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1798 r = y == 0. ? 1. : x; /* NaN**0 = 1 */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1799 else if (Py_IS_NAN(y))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1800 r = x == 1. ? 1. : y; /* 1**NaN = 1 */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1801 else if (Py_IS_INFINITY(x)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1802 odd_y = Py_IS_FINITE(y) && fmod(fabs(y), 2.0) == 1.0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1803 if (y > 0.)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1804 r = odd_y ? x : fabs(x);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1805 else if (y == 0.)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1806 r = 1.;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1807 else /* y < 0. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1808 r = odd_y ? copysign(0., x) : 0.;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1809 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1810 else if (Py_IS_INFINITY(y)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1811 if (fabs(x) == 1.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1812 r = 1.;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1813 else if (y > 0. && fabs(x) > 1.0)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1814 r = y;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1815 else if (y < 0. && fabs(x) < 1.0) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1816 r = -y; /* result is +inf */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1817 if (x == 0.) /* 0**-inf: divide-by-zero */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1818 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1819 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1820 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1821 r = 0.;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1822 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1823 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1824 else {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1825 /* let libm handle finite**finite */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1826 errno = 0;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1827 PyFPE_START_PROTECT("in math_pow", return 0);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1828 r = pow(x, y);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1829 PyFPE_END_PROTECT(r);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1830 /* a NaN result should arise only from (-ve)**(finite
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1831 non-integer); in this case we want to raise ValueError. */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1832 if (!Py_IS_FINITE(r)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1833 if (Py_IS_NAN(r)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1834 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1835 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1836 /*
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1837 an infinite result here arises either from:
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1838 (A) (+/-0.)**negative (-> divide-by-zero)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1839 (B) overflow of x**y with x and y finite
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1840 */
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1841 else if (Py_IS_INFINITY(r)) {
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1842 if (x == 0.)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1843 errno = EDOM;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1844 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1845 errno = ERANGE;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1846 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1847 }
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1848 }
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1849
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1850 if (errno && is_error(r))
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1851 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1852 else
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1853 return PyFloat_FromDouble(r);
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1854 }
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1855
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1856 PyDoc_STRVAR(math_pow_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1857 "pow(x, y)\n\nReturn x**y (x to the power of y).");
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
1858
44441
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1859 static const double degToRad = Py_MATH_PI / 180.0;
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1860 static const double radToDeg = 180.0 / Py_MATH_PI;
23427
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1861
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1862 static PyObject *
40450
cc992d75d5b3 Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents: 37191
diff changeset
1863 math_degrees(PyObject *self, PyObject *arg)
23427
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1864 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1865 double x = PyFloat_AsDouble(arg);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1866 if (x == -1.0 && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1867 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1868 return PyFloat_FromDouble(x * radToDeg);
23427
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1869 }
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1870
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1871 PyDoc_STRVAR(math_degrees_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1872 "degrees(x)\n\n\
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1873 Convert angle x from radians to degrees.");
23427
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1874
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1875 static PyObject *
40450
cc992d75d5b3 Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents: 37191
diff changeset
1876 math_radians(PyObject *self, PyObject *arg)
23427
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1877 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1878 double x = PyFloat_AsDouble(arg);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1879 if (x == -1.0 && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1880 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1881 return PyFloat_FromDouble(x * degToRad);
23427
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1882 }
a4d675b8b53c Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents: 19758
diff changeset
1883
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1884 PyDoc_STRVAR(math_radians_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1885 "radians(x)\n\n\
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1886 Convert angle x from degrees to radians.");
19713
9433dd3c197e Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents: 19712
diff changeset
1887
44441
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1888 static PyObject *
62968
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1889 math_isfinite(PyObject *self, PyObject *arg)
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1890 {
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1891 double x = PyFloat_AsDouble(arg);
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1892 if (x == -1.0 && PyErr_Occurred())
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1893 return NULL;
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1894 return PyBool_FromLong((long)Py_IS_FINITE(x));
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1895 }
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1896
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1897 PyDoc_STRVAR(math_isfinite_doc,
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1898 "isfinite(x) -> bool\n\n\
62970
4c11e4140ced Improve docstrings for isnan, isinf and isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62968
diff changeset
1899 Return True if x is neither an infinity nor a NaN, and False otherwise.");
62968
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1900
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1901 static PyObject *
44441
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1902 math_isnan(PyObject *self, PyObject *arg)
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1903 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1904 double x = PyFloat_AsDouble(arg);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1905 if (x == -1.0 && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1906 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1907 return PyBool_FromLong((long)Py_IS_NAN(x));
44441
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1908 }
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1909
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1910 PyDoc_STRVAR(math_isnan_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1911 "isnan(x) -> bool\n\n\
62970
4c11e4140ced Improve docstrings for isnan, isinf and isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62968
diff changeset
1912 Return True if x is a NaN (not a number), and False otherwise.");
44441
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1913
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1914 static PyObject *
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1915 math_isinf(PyObject *self, PyObject *arg)
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1916 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1917 double x = PyFloat_AsDouble(arg);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1918 if (x == -1.0 && PyErr_Occurred())
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1919 return NULL;
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1920 return PyBool_FromLong((long)Py_IS_INFINITY(x));
44441
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1921 }
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1922
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1923 PyDoc_STRVAR(math_isinf_doc,
57210
a0951f11be3d Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 50250
diff changeset
1924 "isinf(x) -> bool\n\n\
62970
4c11e4140ced Improve docstrings for isnan, isinf and isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62968
diff changeset
1925 Return True if x is a positive or negative infinity, and False otherwise.");
44441
b91ca87e6f32 Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 44351
diff changeset
1926
4635
49745ddb4f69 Renamed
Barry Warsaw <barry@python.org>
parents: 4503
diff changeset
1927 static PyMethodDef math_methods[] = {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1928 {"acos", math_acos, METH_O, math_acos_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1929 {"acosh", math_acosh, METH_O, math_acosh_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1930 {"asin", math_asin, METH_O, math_asin_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1931 {"asinh", math_asinh, METH_O, math_asinh_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1932 {"atan", math_atan, METH_O, math_atan_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1933 {"atan2", math_atan2, METH_VARARGS, math_atan2_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1934 {"atanh", math_atanh, METH_O, math_atanh_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1935 {"ceil", math_ceil, METH_O, math_ceil_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1936 {"copysign", math_copysign, METH_VARARGS, math_copysign_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1937 {"cos", math_cos, METH_O, math_cos_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1938 {"cosh", math_cosh, METH_O, math_cosh_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1939 {"degrees", math_degrees, METH_O, math_degrees_doc},
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1940 {"erf", math_erf, METH_O, math_erf_doc},
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1941 {"erfc", math_erfc, METH_O, math_erfc_doc},
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1942 {"exp", math_exp, METH_O, math_exp_doc},
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1943 {"expm1", math_expm1, METH_O, math_expm1_doc},
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1944 {"fabs", math_fabs, METH_O, math_fabs_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1945 {"factorial", math_factorial, METH_O, math_factorial_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1946 {"floor", math_floor, METH_O, math_floor_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1947 {"fmod", math_fmod, METH_VARARGS, math_fmod_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1948 {"frexp", math_frexp, METH_O, math_frexp_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1949 {"fsum", math_fsum, METH_O, math_fsum_doc},
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1950 {"gamma", math_gamma, METH_O, math_gamma_doc},
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1951 {"hypot", math_hypot, METH_VARARGS, math_hypot_doc},
62968
53e7ae8ca039 Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents: 62859
diff changeset
1952 {"isfinite", math_isfinite, METH_O, math_isfinite_doc},
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1953 {"isinf", math_isinf, METH_O, math_isinf_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1954 {"isnan", math_isnan, METH_O, math_isnan_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1955 {"ldexp", math_ldexp, METH_VARARGS, math_ldexp_doc},
61466
cab14be0ada1 Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 58125
diff changeset
1956 {"lgamma", math_lgamma, METH_O, math_lgamma_doc},
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1957 {"log", math_log, METH_VARARGS, math_log_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1958 {"log1p", math_log1p, METH_O, math_log1p_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1959 {"log10", math_log10, METH_O, math_log10_doc},
69946
6d1cbfcee45a Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents: 68457
diff changeset
1960 {"log2", math_log2, METH_O, math_log2_doc},
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1961 {"modf", math_modf, METH_O, math_modf_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1962 {"pow", math_pow, METH_VARARGS, math_pow_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1963 {"radians", math_radians, METH_O, math_radians_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1964 {"sin", math_sin, METH_O, math_sin_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1965 {"sinh", math_sinh, METH_O, math_sinh_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1966 {"sqrt", math_sqrt, METH_O, math_sqrt_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1967 {"tan", math_tan, METH_O, math_tan_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1968 {"tanh", math_tanh, METH_O, math_tanh_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1969 {"trunc", math_trunc, METH_O, math_trunc_doc},
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1970 {NULL, NULL} /* sentinel */
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
1971 };
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
1972
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
1973
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1974 PyDoc_STRVAR(module_doc,
19712
b4521436e8f8 Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents: 19048
diff changeset
1975 "This module is always available. It provides access to the\n"
23832
ed1ba37a46b7 Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents: 23427
diff changeset
1976 "mathematical functions defined by the C standard.");
9593
f22f769bf3d9 Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents: 9588
diff changeset
1977
47580
94f64f11fdd0 Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents: 47562
diff changeset
1978
94f64f11fdd0 Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents: 47562
diff changeset
1979 static struct PyModuleDef mathmodule = {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1980 PyModuleDef_HEAD_INIT,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1981 "math",
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1982 module_doc,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1983 -1,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1984 math_methods,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1985 NULL,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1986 NULL,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1987 NULL,
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1988 NULL
47580
94f64f11fdd0 Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents: 47562
diff changeset
1989 };
94f64f11fdd0 Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents: 47562
diff changeset
1990
24471
f66b3a3509c7 Excise DL_EXPORT/DL_IMPORT from Modules/*. Required adding a prototype
Mark Hammond <mhammond@skippinet.com.au>
parents: 23832
diff changeset
1991 PyMODINIT_FUNC
47580
94f64f11fdd0 Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents: 47562
diff changeset
1992 PyInit_math(void)
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
1993 {
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1994 PyObject *m;
19048
e282d6b2b758 Part of SF patch [#431848] mathmodule.c: doc strings & conversion, from
Tim Peters <tim.peters@gmail.com>
parents: 18066
diff changeset
1995
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1996 m = PyModule_Create(&mathmodule);
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1997 if (m == NULL)
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
1998 goto finally;
4752
7367fb107108 Better error checking in initmath().
Barry Warsaw <barry@python.org>
parents: 4635
diff changeset
1999
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
2000 PyModule_AddObject(m, "pi", PyFloat_FromDouble(Py_MATH_PI));
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
2001 PyModule_AddObject(m, "e", PyFloat_FromDouble(Py_MATH_E));
4752
7367fb107108 Better error checking in initmath().
Barry Warsaw <barry@python.org>
parents: 4635
diff changeset
2002
46477
b69f443ef480 Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 45134
diff changeset
2003 finally:
61467
f197407bdba2 Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57210
diff changeset
2004 return m;
6
fc6fcd7df4f7 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
2005 }