Mercurial > cpython-lru_cache-weakref
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 |
| rev | line source |
|---|---|
| 6 | 1 /* Math module -- standard C math library functions, pi and e */ |
| 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 | 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 | 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 | 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 | 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 | 748 if (can_overflow) |
| 749 PyErr_SetString(PyExc_OverflowError, | |
| 750 "math range error"); /* overflow */ | |
| 751 else | |
| 752 PyErr_SetString(PyExc_ValueError, | |
| 753 "math domain error"); /* singularity */ | |
| 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 | 820 } |
| 821 | |
| 4635 | 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 | 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 | 853 } |
| 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1971 }; |
| 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 | 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 | 2005 } |
