Mercurial > cpython-lru_cache-weakref
annotate Modules/mathmodule.c @ 73323:dad02a080bbc
Improve byte-compilation in packaging to be independent of -O or -B.
The code I fixed to comply with PEP 3147 still had one bug: When run
under python -O, some paths for pyc files would be pyo, because I called
imp.cache_from_source without explicit debug_override argument in some
places, and under -O that would return .pyo (this is well explained in
the imp docs). Now all code (util.byte_compile, build_py, install_lib)
can create .pyo files according to options given by users,
without interference from the calling Python’s own optimize mode.
On a related topic, I also removed the code that prevented byte
compilation under python -B. The rationale is that packaging gives
control over the creation of pyc files to the user with its own explicit
option, and the behavior should not be changed if the calling Python
happens to run with -B for whatever reason. I will argue that this is a
bug fix and ask to be allowed to backport this change to distutils.
Finally, I moved one nugget of information about the --compile and
--optimize options from the source into the doc. It clears up a
misunderstanding that I (and maybe other people) had.
| author | Éric Araujo <merwok@netwok.org> |
|---|---|
| date | Thu, 03 Nov 2011 05:08:28 +0100 |
| parents | b534b56379cb |
| children | 7d96679c5d46 |
| 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)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
748 if (can_overflow) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
749 PyErr_SetString(PyExc_OverflowError, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
750 "math range error"); /* overflow */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
751 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
752 PyErr_SetString(PyExc_ValueError, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
753 "math domain error"); /* singularity */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
754 return NULL; |
|
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) { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
890 static PyObject *ceil_str = NULL; |
|
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 |
|
62680
35370d7236c9
fix lookup of __ceil__
Benjamin Peterson <benjamin@python.org>
parents:
62679
diff
changeset
|
893 method = _PyObject_LookupSpecial(number, "__ceil__", &ceil_str); |
|
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) { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
928 static PyObject *floor_str = NULL; |
|
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 |
|
62668
a89a3d92f8ae
correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents:
62495
diff
changeset
|
931 method = _PyObject_LookupSpecial(number, "__floor__", &floor_str); |
|
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 } |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1384 |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1385 goto done; |
|
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 done: |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1390 Py_DECREF(inner); |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1391 return outer; |
|
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 |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1394 /* Lookup table for small factorial values */ |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1395 |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1396 static const unsigned long SmallFactorials[] = { |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1397 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
|
1398 362880, 3628800, 39916800, 479001600, |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1399 #if SIZEOF_LONG >= 8 |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1400 6227020800, 87178291200, 1307674368000, |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1401 20922789888000, 355687428096000, 6402373705728000, |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1402 121645100408832000, 2432902008176640000 |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1403 #endif |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1404 }; |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1405 |
| 4635 | 1406 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
|
1407 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
|
1408 { |
|
61599
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1409 long x; |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1410 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
|
1411 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1412 if (PyFloat_Check(arg)) { |
|
61466
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1413 PyObject *lx; |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1414 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
|
1415 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
|
1416 PyErr_SetString(PyExc_ValueError, |
|
61599
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1417 "factorial() only accepts integral values"); |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1418 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1419 } |
|
61466
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1420 lx = PyLong_FromDouble(dx); |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1421 if (lx == NULL) |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1422 return NULL; |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1423 x = PyLong_AsLong(lx); |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1424 Py_DECREF(lx); |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1425 } |
|
61466
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1426 else |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1427 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
|
1428 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1429 if (x == -1 && PyErr_Occurred()) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1430 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1431 if (x < 0) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1432 PyErr_SetString(PyExc_ValueError, |
|
61599
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1433 "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
|
1434 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1435 } |
|
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
|
1436 |
|
61599
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1437 /* 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
|
1438 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
|
1439 return PyLong_FromUnsignedLong(SmallFactorials[x]); |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1440 |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1441 /* 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
|
1442 odd_part << two_valuation. */ |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1443 odd_part = factorial_odd_part(x); |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1444 if (odd_part == NULL) |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1445 return NULL; |
|
61599
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1446 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
|
1447 if (two_valuation == NULL) { |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1448 Py_DECREF(odd_part); |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1449 return NULL; |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1450 } |
|
61599
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1451 result = PyNumber_Lshift(odd_part, two_valuation); |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1452 Py_DECREF(two_valuation); |
|
1e149b50aca6
Issue #8692: Improve performance of math.factorial:
Mark Dickinson <dickinsm@gmail.com>
parents:
61466
diff
changeset
|
1453 Py_DECREF(odd_part); |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1454 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
|
1455 } |
|
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
|
1456 |
|
50250
1adfabcbe073
Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50123
diff
changeset
|
1457 PyDoc_STRVAR(math_factorial_doc, |
|
1adfabcbe073
Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50123
diff
changeset
|
1458 "factorial(x) -> Integral\n" |
|
1adfabcbe073
Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50123
diff
changeset
|
1459 "\n" |
|
1adfabcbe073
Merged revisions 67886-67887 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50123
diff
changeset
|
1460 "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
|
1461 |
|
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
|
1462 static PyObject * |
|
45082
d7540031b959
Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45029
diff
changeset
|
1463 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
|
1464 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1465 static PyObject *trunc_str = NULL; |
|
62679
4b0c88275f3b
account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents:
62668
diff
changeset
|
1466 PyObject *trunc, *result; |
|
45082
d7540031b959
Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45029
diff
changeset
|
1467 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1468 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
|
1469 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
|
1470 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1471 } |
|
45082
d7540031b959
Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45029
diff
changeset
|
1472 |
|
62668
a89a3d92f8ae
correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents:
62495
diff
changeset
|
1473 trunc = _PyObject_LookupSpecial(number, "__trunc__", &trunc_str); |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1474 if (trunc == NULL) { |
|
62668
a89a3d92f8ae
correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents:
62495
diff
changeset
|
1475 if (!PyErr_Occurred()) |
|
a89a3d92f8ae
correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents:
62495
diff
changeset
|
1476 PyErr_Format(PyExc_TypeError, |
|
a89a3d92f8ae
correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents:
62495
diff
changeset
|
1477 "type %.100s doesn't define __trunc__ method", |
|
a89a3d92f8ae
correctly lookup __trunc__ and __floor__
Benjamin Peterson <benjamin@python.org>
parents:
62495
diff
changeset
|
1478 Py_TYPE(number)->tp_name); |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1479 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1480 } |
|
62679
4b0c88275f3b
account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents:
62668
diff
changeset
|
1481 result = PyObject_CallFunctionObjArgs(trunc, NULL); |
|
4b0c88275f3b
account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents:
62668
diff
changeset
|
1482 Py_DECREF(trunc); |
|
4b0c88275f3b
account for different ref counting semantics of _PyObject_LookupSpecial
Benjamin Peterson <benjamin@python.org>
parents:
62668
diff
changeset
|
1483 return result; |
|
45082
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 |
|
d7540031b959
Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45029
diff
changeset
|
1486 PyDoc_STRVAR(math_trunc_doc, |
|
d7540031b959
Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45029
diff
changeset
|
1487 "trunc(x:Real) -> Integral\n" |
|
d7540031b959
Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45029
diff
changeset
|
1488 "\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
|
1489 "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
|
1490 |
|
d7540031b959
Merged revisions 60475-60479,60481-60488 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45029
diff
changeset
|
1491 static PyObject * |
|
40450
cc992d75d5b3
Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents:
37191
diff
changeset
|
1492 math_frexp(PyObject *self, PyObject *arg) |
|
407
9b3d557665a9
Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents:
320
diff
changeset
|
1493 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1494 int i; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1495 double x = PyFloat_AsDouble(arg); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1496 if (x == -1.0 && PyErr_Occurred()) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1497 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1498 /* 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
|
1499 differences */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1500 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
|
1501 i = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1502 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1503 else { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1504 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
|
1505 x = frexp(x, &i); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1506 PyFPE_END_PROTECT(x); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1507 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1508 return Py_BuildValue("(di)", x, i); |
|
407
9b3d557665a9
Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents:
320
diff
changeset
|
1509 } |
|
9b3d557665a9
Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents:
320
diff
changeset
|
1510 |
|
23832
ed1ba37a46b7
Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents:
23427
diff
changeset
|
1511 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
|
1512 "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
|
1513 "\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 "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
|
1515 "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
|
1516 "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
|
1517 |
| 4635 | 1518 static PyObject * |
|
13326
24717405dd89
ANSI-fication, remove Py_PROTO, etc.
Fred Drake <fdrake@acm.org>
parents:
13309
diff
changeset
|
1519 math_ldexp(PyObject *self, PyObject *args) |
|
407
9b3d557665a9
Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents:
320
diff
changeset
|
1520 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1521 double x, r; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1522 PyObject *oexp; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1523 long exp; |
|
61466
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1524 int overflow; |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1525 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
|
1526 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
|
1527 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1528 if (PyLong_Check(oexp)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1529 /* 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
|
1530 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
|
1531 exp = PyLong_AsLongAndOverflow(oexp, &overflow); |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1532 if (exp == -1 && PyErr_Occurred()) |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1533 return NULL; |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1534 if (overflow) |
|
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1535 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
|
1536 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1537 else { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1538 PyErr_SetString(PyExc_TypeError, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1539 "Expected an int or long as second argument " |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1540 "to ldexp."); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1541 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1542 } |
|
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
|
1543 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1544 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
|
1545 /* 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
|
1546 r = x; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1547 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1548 } else if (exp > INT_MAX) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1549 /* overflow */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1550 r = copysign(Py_HUGE_VAL, x); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1551 errno = ERANGE; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1552 } else if (exp < INT_MIN) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1553 /* underflow to +-0 */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1554 r = copysign(0., x); |
|
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 } else { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1557 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1558 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
|
1559 r = ldexp(x, (int)exp); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1560 PyFPE_END_PROTECT(r); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1561 if (Py_IS_INFINITY(r)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1562 errno = ERANGE; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1563 } |
|
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
|
1564 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1565 if (errno && is_error(r)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1566 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1567 return PyFloat_FromDouble(r); |
|
407
9b3d557665a9
Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents:
320
diff
changeset
|
1568 } |
|
9b3d557665a9
Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents:
320
diff
changeset
|
1569 |
|
23832
ed1ba37a46b7
Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents:
23427
diff
changeset
|
1570 PyDoc_STRVAR(math_ldexp_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1571 "ldexp(x, i)\n\n\ |
|
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1572 Return x * (2**i)."); |
|
9593
f22f769bf3d9
Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents:
9588
diff
changeset
|
1573 |
| 4635 | 1574 static PyObject * |
|
40450
cc992d75d5b3
Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents:
37191
diff
changeset
|
1575 math_modf(PyObject *self, PyObject *arg) |
|
407
9b3d557665a9
Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents:
320
diff
changeset
|
1576 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1577 double y, x = PyFloat_AsDouble(arg); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1578 if (x == -1.0 && PyErr_Occurred()) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1579 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1580 /* 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
|
1581 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
|
1582 if (!Py_IS_FINITE(x)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1583 if (Py_IS_INFINITY(x)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1584 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
|
1585 else if (Py_IS_NAN(x)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1586 return Py_BuildValue("(dd)", x, x); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1587 } |
|
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
|
1588 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1589 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1590 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
|
1591 x = modf(x, &y); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1592 PyFPE_END_PROTECT(x); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1593 return Py_BuildValue("(dd)", x, y); |
|
407
9b3d557665a9
Added frexp, ldexp, modf, fmod.
Guido van Rossum <guido@python.org>
parents:
320
diff
changeset
|
1594 } |
| 6 | 1595 |
|
23832
ed1ba37a46b7
Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents:
23427
diff
changeset
|
1596 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
|
1597 "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
|
1598 "\n" |
|
b4521436e8f8
Mechanical fiddling to make this easier to work with in my editor.
Tim Peters <tim.peters@gmail.com>
parents:
19048
diff
changeset
|
1599 "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
|
1600 "of x and are floats."); |
|
9593
f22f769bf3d9
Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents:
9588
diff
changeset
|
1601 |
|
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
|
1602 /* A decent logarithm is easy to compute even for huge longs, but libm can't |
|
9433dd3c197e
Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents:
19712
diff
changeset
|
1603 do that by itself -- loghelper can. func is log or log10, and name is |
|
58088
46d60e5ff103
Merged revisions 77234 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents:
57866
diff
changeset
|
1604 "log" or "log10". Note that overflow of the result isn't possible: a long |
|
46d60e5ff103
Merged revisions 77234 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents:
57866
diff
changeset
|
1605 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
|
1606 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
|
1607 small enough to fit in an IEEE single. log and log10 are even smaller. |
|
58088
46d60e5ff103
Merged revisions 77234 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents:
57866
diff
changeset
|
1608 However, intermediate overflow is possible for a long if the number of bits |
|
46d60e5ff103
Merged revisions 77234 via svnmerge from
Mark Dickinson <dickinsm@gmail.com>
parents:
57866
diff
changeset
|
1609 in that long 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
|
1610 |
|
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 static PyObject* |
|
40450
cc992d75d5b3
Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents:
37191
diff
changeset
|
1612 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
|
1613 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1614 /* If it is long, do it ourselves. */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1615 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
|
1616 double x, result; |
|
61466
cab14be0ada1
Recorded merge of revisions 81029 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
58125
diff
changeset
|
1617 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
|
1618 |
|
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
|
1619 /* 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
|
1620 if (Py_SIZE(arg) <= 0) { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1621 PyErr_SetString(PyExc_ValueError, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1622 "math domain error"); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1623 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1624 } |
|
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
|
1625 |
|
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
|
1626 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
|
1627 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
|
1628 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
|
1629 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
|
1630 /* 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
|
1631 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
|
1632 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
|
1633 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
|
1634 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
|
1635 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
|
1636 /* 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
|
1637 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
|
1638 } |
|
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 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
|
1640 /* 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
|
1641 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
|
1642 return PyFloat_FromDouble(result); |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1643 } |
|
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
|
1644 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1645 /* 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
|
1646 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
|
1647 } |
|
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 |
|
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 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
|
1650 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
|
1651 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1652 PyObject *arg; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1653 PyObject *base = NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1654 PyObject *num, *den; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1655 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
|
1656 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1657 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
|
1658 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
|
1659 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1660 num = loghelper(arg, m_log, "log"); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1661 if (num == NULL || base == NULL) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1662 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
|
1663 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1664 den = loghelper(base, m_log, "log"); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1665 if (den == NULL) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1666 Py_DECREF(num); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1667 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1668 } |
|
26661
b12e326b4ea2
Apply SF patch 652930: Add optional base argument to math.log(x[, base]).
Raymond Hettinger <python@rcn.com>
parents:
24471
diff
changeset
|
1669 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1670 ans = PyNumber_TrueDivide(num, den); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1671 Py_DECREF(num); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1672 Py_DECREF(den); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1673 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
|
1674 } |
|
9433dd3c197e
Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents:
19712
diff
changeset
|
1675 |
|
23832
ed1ba37a46b7
Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents:
23427
diff
changeset
|
1676 PyDoc_STRVAR(math_log_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1677 "log(x[, base])\n\n\ |
|
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1678 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
|
1679 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
|
1680 |
|
9433dd3c197e
Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents:
19712
diff
changeset
|
1681 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
|
1682 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
|
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 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
|
1685 } |
|
6d1cbfcee45a
Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents:
68457
diff
changeset
|
1686 |
|
6d1cbfcee45a
Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents:
68457
diff
changeset
|
1687 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
|
1688 "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
|
1689 |
|
6d1cbfcee45a
Issue #11888: Add log2 function to math module. Patch written by Mark
Victor Stinner <victor.stinner@haypocalc.com>
parents:
68457
diff
changeset
|
1690 static PyObject * |
|
40450
cc992d75d5b3
Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents:
37191
diff
changeset
|
1691 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
|
1692 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1693 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
|
1694 } |
|
9433dd3c197e
Return reasonable results for math.log(long) and math.log10(long) (we were
Tim Peters <tim.peters@gmail.com>
parents:
19712
diff
changeset
|
1695 |
|
23832
ed1ba37a46b7
Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents:
23427
diff
changeset
|
1696 PyDoc_STRVAR(math_log10_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1697 "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
|
1698 |
|
46477
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1699 static PyObject * |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1700 math_fmod(PyObject *self, PyObject *args) |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1701 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1702 PyObject *ox, *oy; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1703 double r, x, y; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1704 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
|
1705 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1706 x = PyFloat_AsDouble(ox); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1707 y = PyFloat_AsDouble(oy); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1708 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
|
1709 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1710 /* 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
|
1711 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
|
1712 return PyFloat_FromDouble(x); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1713 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1714 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
|
1715 r = fmod(x, y); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1716 PyFPE_END_PROTECT(r); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1717 if (Py_IS_NAN(r)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1718 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
|
1719 errno = EDOM; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1720 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1721 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1722 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1723 if (errno && is_error(r)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1724 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1725 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1726 return PyFloat_FromDouble(r); |
|
46477
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1727 } |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1728 |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1729 PyDoc_STRVAR(math_fmod_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1730 "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
|
1731 " x % y may differ."); |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1732 |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1733 static PyObject * |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1734 math_hypot(PyObject *self, PyObject *args) |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1735 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1736 PyObject *ox, *oy; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1737 double r, x, y; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1738 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
|
1739 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1740 x = PyFloat_AsDouble(ox); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1741 y = PyFloat_AsDouble(oy); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1742 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
|
1743 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1744 /* 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
|
1745 if (Py_IS_INFINITY(x)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1746 return PyFloat_FromDouble(fabs(x)); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1747 if (Py_IS_INFINITY(y)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1748 return PyFloat_FromDouble(fabs(y)); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1749 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1750 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
|
1751 r = hypot(x, y); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1752 PyFPE_END_PROTECT(r); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1753 if (Py_IS_NAN(r)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1754 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
|
1755 errno = EDOM; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1756 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1757 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1758 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1759 else if (Py_IS_INFINITY(r)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1760 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
|
1761 errno = ERANGE; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1762 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1763 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1764 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1765 if (errno && is_error(r)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1766 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1767 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1768 return PyFloat_FromDouble(r); |
|
46477
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1769 } |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1770 |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1771 PyDoc_STRVAR(math_hypot_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1772 "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
|
1773 |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1774 /* 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
|
1775 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
|
1776 (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
|
1777 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
|
1778 */ |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1779 |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1780 static PyObject * |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1781 math_pow(PyObject *self, PyObject *args) |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1782 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1783 PyObject *ox, *oy; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1784 double r, x, y; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1785 int odd_y; |
|
46477
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1786 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1787 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
|
1788 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1789 x = PyFloat_AsDouble(ox); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1790 y = PyFloat_AsDouble(oy); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1791 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
|
1792 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
|
1793 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1794 /* 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
|
1795 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
|
1796 r = 0.; /* silence compiler warning */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1797 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
|
1798 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1799 if (Py_IS_NAN(x)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1800 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
|
1801 else if (Py_IS_NAN(y)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1802 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
|
1803 else if (Py_IS_INFINITY(x)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1804 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
|
1805 if (y > 0.) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1806 r = odd_y ? x : fabs(x); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1807 else if (y == 0.) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1808 r = 1.; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1809 else /* y < 0. */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1810 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
|
1811 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1812 else if (Py_IS_INFINITY(y)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1813 if (fabs(x) == 1.0) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1814 r = 1.; |
|
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; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1817 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
|
1818 r = -y; /* result is +inf */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1819 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
|
1820 errno = EDOM; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1821 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1822 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1823 r = 0.; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1824 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1825 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1826 else { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1827 /* let libm handle finite**finite */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1828 errno = 0; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1829 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
|
1830 r = pow(x, y); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1831 PyFPE_END_PROTECT(r); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1832 /* 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
|
1833 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
|
1834 if (!Py_IS_FINITE(r)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1835 if (Py_IS_NAN(r)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1836 errno = EDOM; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1837 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1838 /* |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1839 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
|
1840 (A) (+/-0.)**negative (-> divide-by-zero) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1841 (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
|
1842 */ |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1843 else if (Py_IS_INFINITY(r)) { |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1844 if (x == 0.) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1845 errno = EDOM; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1846 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1847 errno = ERANGE; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1848 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1849 } |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1850 } |
|
46477
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1851 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1852 if (errno && is_error(r)) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1853 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1854 else |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1855 return PyFloat_FromDouble(r); |
|
46477
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1856 } |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1857 |
|
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
1858 PyDoc_STRVAR(math_pow_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1859 "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
|
1860 |
|
44441
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1861 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
|
1862 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
|
1863 |
|
a4d675b8b53c
Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents:
19758
diff
changeset
|
1864 static PyObject * |
|
40450
cc992d75d5b3
Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents:
37191
diff
changeset
|
1865 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
|
1866 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1867 double x = PyFloat_AsDouble(arg); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1868 if (x == -1.0 && PyErr_Occurred()) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1869 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1870 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
|
1871 } |
|
a4d675b8b53c
Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents:
19758
diff
changeset
|
1872 |
|
23832
ed1ba37a46b7
Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents:
23427
diff
changeset
|
1873 PyDoc_STRVAR(math_degrees_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1874 "degrees(x)\n\n\ |
|
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1875 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
|
1876 |
|
a4d675b8b53c
Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents:
19758
diff
changeset
|
1877 static PyObject * |
|
40450
cc992d75d5b3
Four months of trunk changes (including a few releases...)
Thomas Wouters <thomas@python.org>
parents:
37191
diff
changeset
|
1878 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
|
1879 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1880 double x = PyFloat_AsDouble(arg); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1881 if (x == -1.0 && PyErr_Occurred()) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1882 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1883 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
|
1884 } |
|
a4d675b8b53c
Added degrees() and radians() to mathmodule. Closes patch 552452 and
Raymond Hettinger <python@rcn.com>
parents:
19758
diff
changeset
|
1885 |
|
23832
ed1ba37a46b7
Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents:
23427
diff
changeset
|
1886 PyDoc_STRVAR(math_radians_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1887 "radians(x)\n\n\ |
|
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1888 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
|
1889 |
|
44441
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1890 static PyObject * |
|
62968
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1891 math_isfinite(PyObject *self, PyObject *arg) |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1892 { |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1893 double x = PyFloat_AsDouble(arg); |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1894 if (x == -1.0 && PyErr_Occurred()) |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1895 return NULL; |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1896 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
|
1897 } |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1898 |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1899 PyDoc_STRVAR(math_isfinite_doc, |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1900 "isfinite(x) -> bool\n\n\ |
|
62970
4c11e4140ced
Improve docstrings for isnan, isinf and isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62968
diff
changeset
|
1901 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
|
1902 |
|
53e7ae8ca039
Issue #9165: Add math.isfinite and cmath.isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62859
diff
changeset
|
1903 static PyObject * |
|
44441
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1904 math_isnan(PyObject *self, PyObject *arg) |
|
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1905 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1906 double x = PyFloat_AsDouble(arg); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1907 if (x == -1.0 && PyErr_Occurred()) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1908 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1909 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
|
1910 } |
|
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1911 |
|
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1912 PyDoc_STRVAR(math_isnan_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1913 "isnan(x) -> bool\n\n\ |
|
62970
4c11e4140ced
Improve docstrings for isnan, isinf and isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62968
diff
changeset
|
1914 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
|
1915 |
|
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1916 static PyObject * |
|
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1917 math_isinf(PyObject *self, PyObject *arg) |
|
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1918 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1919 double x = PyFloat_AsDouble(arg); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1920 if (x == -1.0 && PyErr_Occurred()) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1921 return NULL; |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1922 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
|
1923 } |
|
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1924 |
|
b91ca87e6f32
Merged revisions 59666-59679 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
44351
diff
changeset
|
1925 PyDoc_STRVAR(math_isinf_doc, |
|
57210
a0951f11be3d
Merged revisions 76235 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents:
50250
diff
changeset
|
1926 "isinf(x) -> bool\n\n\ |
|
62970
4c11e4140ced
Improve docstrings for isnan, isinf and isfinite.
Mark Dickinson <dickinsm@gmail.com>
parents:
62968
diff
changeset
|
1927 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
|
1928 |
| 4635 | 1929 static PyMethodDef math_methods[] = { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1930 {"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
|
1931 {"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
|
1932 {"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
|
1933 {"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
|
1934 {"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
|
1935 {"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
|
1936 {"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
|
1937 {"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
|
1938 {"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
|
1939 {"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
|
1940 {"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
|
1941 {"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
|
1942 {"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
|
1943 {"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
|
1944 {"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
|
1945 {"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
|
1946 {"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
|
1947 {"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
|
1948 {"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
|
1949 {"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
|
1950 {"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
|
1951 {"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
|
1952 {"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
|
1953 {"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
|
1954 {"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
|
1955 {"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
|
1956 {"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
|
1957 {"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
|
1958 {"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
|
1959 {"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
|
1960 {"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
|
1961 {"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
|
1962 {"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
|
1963 {"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
|
1964 {"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
|
1965 {"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
|
1966 {"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
|
1967 {"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
|
1968 {"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
|
1969 {"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
|
1970 {"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
|
1971 {"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
|
1972 {NULL, NULL} /* sentinel */ |
| 6 | 1973 }; |
| 1974 | |
|
9593
f22f769bf3d9
Added Doc strings -- by Chris Petrilli.
Guido van Rossum <guido@python.org>
parents:
9588
diff
changeset
|
1975 |
|
23832
ed1ba37a46b7
Patch #568124: Add doc string macros.
Martin v. Löwis <martin@v.loewis.de>
parents:
23427
diff
changeset
|
1976 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
|
1977 "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
|
1978 "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
|
1979 |
|
47580
94f64f11fdd0
Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents:
47562
diff
changeset
|
1980 |
|
94f64f11fdd0
Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents:
47562
diff
changeset
|
1981 static struct PyModuleDef mathmodule = { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1982 PyModuleDef_HEAD_INIT, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1983 "math", |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1984 module_doc, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1985 -1, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1986 math_methods, |
|
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, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1989 NULL, |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1990 NULL |
|
47580
94f64f11fdd0
Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents:
47562
diff
changeset
|
1991 }; |
|
94f64f11fdd0
Implement PEP 3121: new module initialization and finalization API.
Martin v. Löwis <martin@v.loewis.de>
parents:
47562
diff
changeset
|
1992 |
|
24471
f66b3a3509c7
Excise DL_EXPORT/DL_IMPORT from Modules/*. Required adding a prototype
Mark Hammond <mhammond@skippinet.com.au>
parents:
23832
diff
changeset
|
1993 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
|
1994 PyInit_math(void) |
| 6 | 1995 { |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1996 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
|
1997 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1998 m = PyModule_Create(&mathmodule); |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
1999 if (m == NULL) |
|
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
2000 goto finally; |
|
4752
7367fb107108
Better error checking in initmath().
Barry Warsaw <barry@python.org>
parents:
4635
diff
changeset
|
2001 |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
2002 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
|
2003 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
|
2004 |
|
46477
b69f443ef480
Merged revisions 62380,62382-62383 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents:
45134
diff
changeset
|
2005 finally: |
|
61467
f197407bdba2
Recorded merge of revisions 81032 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents:
57210
diff
changeset
|
2006 return m; |
| 6 | 2007 } |
