chebfun 0.4.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,39 @@
1
+ *.py[cod]
2
+ *.todo
3
+ *.ini
4
+ *~
5
+ */.ipynb_checkpoints/*
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Packages
11
+ *.egg
12
+ *.egg-info
13
+ dist
14
+ build
15
+ eggs
16
+ parts
17
+ bin
18
+ var
19
+ sdist
20
+ develop-eggs
21
+ .installed.cfg
22
+ lib
23
+ lib64
24
+
25
+ # Installer logs
26
+ pip-log.txt
27
+
28
+ # Unit test / coverage reports
29
+ .coverage
30
+ .tox
31
+ nosetests.xml
32
+ lcov.info
33
+
34
+ *.DS_Store
35
+ *.dylib
36
+ *.pyc
37
+ .idea/
38
+ docs/_*
39
+ pdoc
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2016: Mark Richardson and other contributors:
2
+
3
+ https://github.com/chebpy/chebpy/graphs/contributors
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
+
9
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10
+
11
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,58 @@
1
+ Metadata-Version: 2.4
2
+ Name: chebfun
3
+ Version: 0.4.4.1
4
+ Summary: A Python implementation of Chebfun
5
+ Project-URL: repository, https://github.com/chebpy/chebpy
6
+ Author-email: Mark Richardson <mrichardson82@gmail.com>
7
+ License-File: LICENSE.rst
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: numpy>=2.0
10
+ Provides-Extra: dev
11
+ Requires-Dist: matplotlib==3.10.0; extra == 'dev'
12
+ Requires-Dist: pre-commit>=4.2.0; extra == 'dev'
13
+ Requires-Dist: pytest-cov>=6.2.1; extra == 'dev'
14
+ Requires-Dist: pytest>=8.4.1; extra == 'dev'
15
+ Description-Content-Type: text/x-rst
16
+
17
+ ================================================
18
+ ChebPy - A Python implementation of Chebfun
19
+ ================================================
20
+
21
+ .. image:: https://github.com/chebpy/chebpy/actions/workflows/unittest.yml/badge.svg
22
+ :target: https://github.com/chebpy/chebpy/actions/workflows/unittest.yml
23
+ .. image:: https://coveralls.io/repos/github/chebpy/chebpy/badge.svg?branch=master
24
+ :target: https://coveralls.io/github/chebpy/chebpy?branch=master
25
+ .. image:: https://img.shields.io/badge/python-%203.8_--%203.13-blue.svg?
26
+ :target: https://github.com/chebpy/chebpy/actions/workflows/unittest.yml
27
+ .. image:: https://img.shields.io/conda/dn/conda-forge/chebfun?label=conda%20downloads
28
+ :target: https://anaconda.org/conda-forge/chebfun
29
+ .. image:: https://img.shields.io/badge/code%20style-black-000000.svg
30
+ :target: https://github.com/psf/black
31
+ .. image:: https://mybinder.org/badge_logo.svg
32
+ :target: https://mybinder.org/v2/gh/chebpy/chebpy/v0.4.3?filepath=docs%2Fnotebook-getting-started.ipynb
33
+
34
+ |
35
+
36
+
37
+ Numerical computing with Chebyshev series approximations in Python.
38
+
39
+
40
+ .. image:: docs/chebpy-readme-image1.png
41
+
42
+
43
+ ChebPy is a Python implementation of `Chebfun <http://www.chebfun.org/>`_.
44
+
45
+ - The software is licensed under a 3-Clause BSD License, see `LICENSE.rst <LICENSE.rst>`_.
46
+ - For installation details, see `INSTALL.rst <INSTALL.rst>`_.
47
+ - The code is documented in various files in the `docs <docs/>`_ folder.
48
+
49
+
50
+ The figure above was generated with the following simple ChebPy code:
51
+
52
+ .. code:: python
53
+
54
+ f = chebfun(lambda x: np.sin(x**2) + np.sin(x)**2, [0, 10])
55
+ g = chebfun(lambda x: np.exp(-(x-5)**2/10), [0, 10])
56
+ r = (f-g).roots()
57
+ ax = f.plot(); g.plot()
58
+ ax.plot(r, f(r), 'o')
@@ -0,0 +1,42 @@
1
+ ================================================
2
+ ChebPy - A Python implementation of Chebfun
3
+ ================================================
4
+
5
+ .. image:: https://github.com/chebpy/chebpy/actions/workflows/unittest.yml/badge.svg
6
+ :target: https://github.com/chebpy/chebpy/actions/workflows/unittest.yml
7
+ .. image:: https://coveralls.io/repos/github/chebpy/chebpy/badge.svg?branch=master
8
+ :target: https://coveralls.io/github/chebpy/chebpy?branch=master
9
+ .. image:: https://img.shields.io/badge/python-%203.8_--%203.13-blue.svg?
10
+ :target: https://github.com/chebpy/chebpy/actions/workflows/unittest.yml
11
+ .. image:: https://img.shields.io/conda/dn/conda-forge/chebfun?label=conda%20downloads
12
+ :target: https://anaconda.org/conda-forge/chebfun
13
+ .. image:: https://img.shields.io/badge/code%20style-black-000000.svg
14
+ :target: https://github.com/psf/black
15
+ .. image:: https://mybinder.org/badge_logo.svg
16
+ :target: https://mybinder.org/v2/gh/chebpy/chebpy/v0.4.3?filepath=docs%2Fnotebook-getting-started.ipynb
17
+
18
+ |
19
+
20
+
21
+ Numerical computing with Chebyshev series approximations in Python.
22
+
23
+
24
+ .. image:: docs/chebpy-readme-image1.png
25
+
26
+
27
+ ChebPy is a Python implementation of `Chebfun <http://www.chebfun.org/>`_.
28
+
29
+ - The software is licensed under a 3-Clause BSD License, see `LICENSE.rst <LICENSE.rst>`_.
30
+ - For installation details, see `INSTALL.rst <INSTALL.rst>`_.
31
+ - The code is documented in various files in the `docs <docs/>`_ folder.
32
+
33
+
34
+ The figure above was generated with the following simple ChebPy code:
35
+
36
+ .. code:: python
37
+
38
+ f = chebfun(lambda x: np.sin(x**2) + np.sin(x)**2, [0, 10])
39
+ g = chebfun(lambda x: np.exp(-(x-5)**2/10), [0, 10])
40
+ r = (f-g).roots()
41
+ ax = f.plot(); g.plot()
42
+ ax.plot(r, f(r), 'o')
@@ -0,0 +1,4 @@
1
+ __version__ = "0.4.3.3"
2
+
3
+ from .api import chebfun, pwc
4
+ from .core.settings import ChebPreferences as UserPreferences
@@ -0,0 +1,41 @@
1
+ """User-facing functions"""
2
+
3
+ from .core.bndfun import Bndfun
4
+ from .core.chebfun import Chebfun
5
+ from .core.utilities import Domain
6
+ from .core.settings import _preferences as prefs
7
+
8
+
9
+ def chebfun(f=None, domain=None, n=None):
10
+ """Chebfun constructor"""
11
+ # chebfun()
12
+ if f is None:
13
+ return Chebfun.initempty()
14
+
15
+ domain = domain if domain is not None else prefs.domain
16
+
17
+ # chebfun(lambda x: f(x), ... )
18
+ if hasattr(f, "__call__"):
19
+ return Chebfun.initfun(f, domain, n)
20
+
21
+ # chebfun('x', ... )
22
+ if isinstance(f, str) and len(f) == 1 and f.isalpha():
23
+ if n:
24
+ return Chebfun.initfun(lambda x: x, domain, n)
25
+ else:
26
+ return Chebfun.initidentity(domain)
27
+
28
+ try:
29
+ # chebfun(3.14, ... ), chebfun('3.14', ... )
30
+ return Chebfun.initconst(float(f), domain)
31
+ except (OverflowError, ValueError):
32
+ raise ValueError(f"Unable to construct const function from {{{f}}}")
33
+
34
+
35
+ def pwc(domain=[-1, 0, 1], values=[0, 1]):
36
+ """Initialise a piecewise-constant Chebfun"""
37
+ funs = []
38
+ intervals = [x for x in Domain(domain).intervals]
39
+ for interval, value in zip(intervals, values):
40
+ funs.append(Bndfun.initconst(value, interval))
41
+ return Chebfun(funs)
File without changes
@@ -0,0 +1,326 @@
1
+ import warnings
2
+
3
+ import numpy as np
4
+
5
+ from .ffts import fft, ifft
6
+ from .utilities import Interval, infnorm
7
+ from .settings import _preferences as prefs
8
+ from .decorators import preandpostprocess
9
+
10
+ # supress numpy division and multiply warnings
11
+ np.seterr(divide="ignore", invalid="ignore")
12
+
13
+ # constants
14
+ SPLITPOINT = -0.004849834917525
15
+
16
+
17
+ # local helpers
18
+ def find(x):
19
+ return np.where(x)[0]
20
+
21
+
22
+ def rootsunit(ak, htol=None):
23
+ """Compute the roots of a funciton on [-1,1] using the coefficeints
24
+ in the associated Chebyshev series representation.
25
+
26
+ References
27
+ ----------
28
+ .. [1] I. J. Good, "The colleague matrix, a Chebyshev analogue of the
29
+ companion matrix", Quarterly Journal of Mathematics 12 (1961).
30
+
31
+ .. [2] J. A. Boyd, "Computing zeros on a real interval through
32
+ Chebyshev expansion and polynomial rootfinding", SIAM Journal on
33
+ Numerical Analysis 40 (2002).
34
+
35
+ .. [3] L. N. Trefethen, Approximation Theory and Approximation
36
+ Practice, SIAM, 2013, chapter 18.
37
+ """
38
+ htol = htol if htol is not None else 1e2 * prefs.eps
39
+ n = standard_chop(ak, tol=htol)
40
+ ak = ak[:n]
41
+
42
+ # if n > 50, we split and recurse
43
+ if n > 50:
44
+ chebpts = chebpts2(ak.size)
45
+ lmap = Interval(-1, SPLITPOINT)
46
+ rmap = Interval(SPLITPOINT, 1)
47
+ lpts = lmap(chebpts)
48
+ rpts = rmap(chebpts)
49
+ lval = clenshaw(lpts, ak)
50
+ rval = clenshaw(rpts, ak)
51
+ lcfs = vals2coeffs2(lval)
52
+ rcfs = vals2coeffs2(rval)
53
+ lrts = rootsunit(lcfs, 2 * htol)
54
+ rrts = rootsunit(rcfs, 2 * htol)
55
+ return np.append(lmap(lrts), rmap(rrts))
56
+
57
+ # trivial base case
58
+ if n <= 1:
59
+ return np.array([])
60
+
61
+ # nontrivial base case: either compute directly or solve
62
+ # a Colleague Matrix eigenvalue problem
63
+ if n == 2:
64
+ rts = np.array([-ak[0] / ak[1]])
65
+ elif n <= 50:
66
+ v = 0.5 * np.ones(n - 2)
67
+ C = np.diag(v, -1) + np.diag(v, 1)
68
+ C[0, 1] = 1
69
+ D = np.zeros(C.shape, dtype=ak.dtype)
70
+ D[-1, :] = ak[:-1]
71
+ E = C - 0.5 * 1.0 / ak[-1] * D
72
+ rts = np.linalg.eigvals(E)
73
+
74
+ # discard values with large imaginary part and treat the remaining
75
+ # ones as real; then sort and retain only the roots inside [-1,1]
76
+ mask = abs(np.imag(rts)) < htol
77
+ rts = np.real(rts[mask])
78
+ rts = rts[abs(rts) <= 1.0 + htol]
79
+ rts = np.sort(rts)
80
+ if rts.size >= 2:
81
+ rts[0] = max([rts[0], -1])
82
+ rts[-1] = min([rts[-1], 1])
83
+ return rts
84
+
85
+
86
+ @preandpostprocess
87
+ def bary(xx, fk, xk, vk):
88
+ """Barycentric interpolation formula. See:
89
+
90
+ J.P. Berrut, L.N. Trefethen, Barycentric Lagrange Interpolation, SIAM
91
+ Review (2004)
92
+
93
+ Inputs
94
+ ------
95
+ xx : numpy ndarray
96
+ array of evaluation points
97
+ fk : numpy ndarray
98
+ array of function values at the interpolation nodes xk
99
+ xk: numpy ndarray
100
+ array of interpolation nodes
101
+ vk: numpy ndarray
102
+ barycentric weights corresponding to the interpolation nodes xk
103
+ """
104
+
105
+ # either iterate over the evaluation points, or ...
106
+ if xx.size < 4 * xk.size:
107
+ out = np.zeros(xx.size)
108
+ for i in range(xx.size):
109
+ tt = vk / (xx[i] - xk)
110
+ out[i] = np.dot(tt, fk) / tt.sum()
111
+
112
+ # ... iterate over the barycenters
113
+ else:
114
+ numer = np.zeros(xx.size)
115
+ denom = np.zeros(xx.size)
116
+ for j in range(xk.size):
117
+ temp = vk[j] / (xx - xk[j])
118
+ numer = numer + temp * fk[j]
119
+ denom = denom + temp
120
+ out = numer / denom
121
+
122
+ # replace NaNs
123
+ for k in find(np.isnan(out)):
124
+ idx = find(xx[k] == xk)
125
+ if idx.size > 0:
126
+ out[k] = fk[idx[0]]
127
+
128
+ return out
129
+
130
+
131
+ @preandpostprocess
132
+ def clenshaw(xx, ak):
133
+ """Clenshaw's algorithm for the evaluation of a first-kind Chebyshev
134
+ series expansion at some array of points x"""
135
+ bk1 = 0 * xx
136
+ bk2 = 0 * xx
137
+ xx = 2 * xx
138
+ idx = range(ak.size)
139
+ for k in idx[ak.size : 1 : -2]:
140
+ bk2 = ak[k] + xx * bk1 - bk2
141
+ bk1 = ak[k - 1] + xx * bk2 - bk1
142
+ if np.mod(ak.size - 1, 2) == 1:
143
+ bk1, bk2 = ak[1] + xx * bk1 - bk2, bk1
144
+ out = ak[0] + 0.5 * xx * bk1 - bk2
145
+ return out
146
+
147
+
148
+ def standard_chop(coeffs, tol=None):
149
+ """Chop a Chebyshev series to a given tolerance. This is a Python
150
+ transcription of the algorithm described in:
151
+
152
+ J. Aurentz and L.N. Trefethen, Chopping a Chebyshev series (2015)
153
+ (http://arxiv.org/pdf/1512.01803v1.pdf)
154
+ """
155
+
156
+ # check magnitude of tol:
157
+ tol = tol if tol is not None else prefs.eps
158
+ if tol >= 1:
159
+ cutoff = 1
160
+ return cutoff
161
+
162
+ # ensure length at least 17:
163
+ n = coeffs.size
164
+ cutoff = n
165
+ if n < 17:
166
+ return cutoff
167
+
168
+ # Step 1: Convert coeffs input to a new monotonically nonincreasing
169
+ # vector (envelope) normalized to begin with the value 1.
170
+ b = np.flipud(np.abs(coeffs))
171
+ m = np.flipud(np.maximum.accumulate(b))
172
+ if m[0] == 0.0:
173
+ # TODO: check this
174
+ cutoff = 1 # cutoff = 0
175
+ return cutoff
176
+ envelope = m / m[0]
177
+
178
+ # Step 2: Scan envelope for a value plateauPoint, the first point, if any,
179
+ # that is followed by a plateau
180
+ for j in np.arange(1, n):
181
+ j2 = round(1.25 * j + 5)
182
+ if j2 > n - 1:
183
+ # there is no plateau: exit
184
+ return cutoff
185
+ e1 = envelope[j]
186
+ e2 = envelope[int(j2)]
187
+ r = 3 * (1 - np.log(e1) / np.log(tol))
188
+ plateau = (e1 == 0.0) | (e2 / e1 > r)
189
+ if plateau:
190
+ # a plateau has been found: go to Step 3
191
+ plateauPoint = j
192
+ break
193
+
194
+ # Step 3: Fix cutoff at a point where envelope, plus a linear function
195
+ # included to bias the result towards the left end, is minimal.
196
+ if envelope[int(plateauPoint)] == 0.0:
197
+ cutoff = plateauPoint
198
+ else:
199
+ j3 = sum(envelope >= tol ** (7.0 / 6.0))
200
+ if j3 < j2:
201
+ j2 = j3 + 1
202
+ envelope[j2] = tol ** (7.0 / 6.0)
203
+ cc = np.log10(envelope[: int(j2)])
204
+ cc = cc + np.linspace(0, (-1.0 / 3.0) * np.log10(tol), int(j2))
205
+ d = np.argmin(cc)
206
+ # TODO: check this
207
+ cutoff = d # + 2
208
+ return min((cutoff, n - 1))
209
+
210
+
211
+ def adaptive(cls, fun, hscale=1, maxpow2=None):
212
+ """Adaptive constructor: cycle over powers of two, calling
213
+ standard_chop each time, the output of which determines whether or not
214
+ we are happy."""
215
+ minpow2 = 4 # 17 points
216
+ maxpow2 = maxpow2 if maxpow2 is not None else prefs.maxpow2
217
+ for k in range(minpow2, max(minpow2, maxpow2) + 1):
218
+ n = 2**k + 1
219
+ points = cls._chebpts(n)
220
+ values = fun(points)
221
+ coeffs = cls._vals2coeffs(values)
222
+ eps = prefs.eps
223
+ tol = eps * max(hscale, 1) # scale (decrease) tolerance by hscale
224
+ chplen = standard_chop(coeffs, tol=tol)
225
+ if chplen < coeffs.size:
226
+ coeffs = coeffs[:chplen]
227
+ break
228
+ if k == maxpow2:
229
+ warnings.warn("The {} constructor did not converge: using {} points".format(cls.__name__, n))
230
+ break
231
+ return coeffs
232
+
233
+
234
+ def coeffmult(fc, gc):
235
+ """Coefficient-Space multiplication of equal-length first-kind
236
+ Chebyshev series."""
237
+ Fc = np.append(2.0 * fc[:1], (fc[1:], fc[:0:-1]))
238
+ Gc = np.append(2.0 * gc[:1], (gc[1:], gc[:0:-1]))
239
+ ak = ifft(fft(Fc) * fft(Gc))
240
+ ak = np.append(ak[:1], ak[1:] + ak[:0:-1]) * 0.25
241
+ ak = ak[: fc.size]
242
+ inputcfs = np.append(fc, gc)
243
+ out = np.real(ak) if np.isreal(inputcfs).all() else ak
244
+ return out
245
+
246
+
247
+ def barywts2(n):
248
+ """Barycentric weights for Chebyshev points of 2nd kind"""
249
+ if n == 0:
250
+ wts = np.array([])
251
+ elif n == 1:
252
+ wts = np.array([1])
253
+ else:
254
+ wts = np.append(np.ones(n - 1), 0.5)
255
+ wts[n - 2 :: -2] = -1
256
+ wts[0] = 0.5 * wts[0]
257
+ return wts
258
+
259
+
260
+ def chebpts2(n):
261
+ """Return n Chebyshev points of the second-kind"""
262
+ if n == 1:
263
+ pts = np.array([0.0])
264
+ else:
265
+ nn = np.arange(n)
266
+ pts = np.cos(nn[::-1] * np.pi / (n - 1))
267
+ return pts
268
+
269
+
270
+ def vals2coeffs2(vals):
271
+ """Map function values at Chebyshev points of 2nd kind to
272
+ first-kind Chebyshev polynomial coefficients"""
273
+ n = vals.size
274
+ if n <= 1:
275
+ coeffs = vals
276
+ return coeffs
277
+ tmp = np.append(vals[::-1], vals[1:-1])
278
+ if np.isreal(vals).all():
279
+ coeffs = ifft(tmp)
280
+ coeffs = np.real(coeffs)
281
+ elif np.isreal(1j * vals).all():
282
+ coeffs = ifft(np.imag(tmp))
283
+ coeffs = 1j * np.real(coeffs)
284
+ else:
285
+ coeffs = ifft(tmp)
286
+ coeffs = coeffs[:n]
287
+ coeffs[1 : n - 1] = 2 * coeffs[1 : n - 1]
288
+ return coeffs
289
+
290
+
291
+ def coeffs2vals2(coeffs):
292
+ """Map first-kind Chebyshev polynomial coefficients to
293
+ function values at Chebyshev points of 2nd kind"""
294
+ n = coeffs.size
295
+ if n <= 1:
296
+ vals = coeffs
297
+ return vals
298
+ coeffs = coeffs.copy()
299
+ coeffs[1 : n - 1] = 0.5 * coeffs[1 : n - 1]
300
+ tmp = np.append(coeffs, coeffs[n - 2 : 0 : -1])
301
+ if np.isreal(coeffs).all():
302
+ vals = fft(tmp)
303
+ vals = np.real(vals)
304
+ elif np.isreal(1j * coeffs).all():
305
+ vals = fft(np.imag(tmp))
306
+ vals = 1j * np.real(vals)
307
+ else:
308
+ vals = fft(tmp)
309
+ vals = vals[n - 1 :: -1]
310
+ return vals
311
+
312
+
313
+ def newtonroots(fun, rts, tol=None, maxiter=None):
314
+ """Rootfinding for a callable and differentiable fun, typically used to
315
+ polish already computed roots."""
316
+ tol = tol if tol is not None else 2 * prefs.eps
317
+ maxiter = maxiter if maxiter is not None else prefs.maxiter
318
+ if rts.size > 0:
319
+ dfun = fun.diff()
320
+ prv = np.inf * rts
321
+ count = 0
322
+ while (infnorm(rts - prv) > tol) & (count <= maxiter):
323
+ count += 1
324
+ prv = rts
325
+ rts = rts - fun(rts) / dfun(rts)
326
+ return rts
@@ -0,0 +1,7 @@
1
+ from .classicfun import Classicfun
2
+
3
+
4
+ class Bndfun(Classicfun):
5
+ """Class to approximate functions on bounded intervals [a,b]"""
6
+
7
+ pass