diff options
Diffstat (limited to 'numpy/polynomial')
-rw-r--r-- | numpy/polynomial/chebyshev.py | 60 | ||||
-rw-r--r-- | numpy/polynomial/tests/test_chebyshev.py | 20 |
2 files changed, 79 insertions, 1 deletions
diff --git a/numpy/polynomial/chebyshev.py b/numpy/polynomial/chebyshev.py index b983b2fec..79623d37e 100644 --- a/numpy/polynomial/chebyshev.py +++ b/numpy/polynomial/chebyshev.py @@ -52,6 +52,7 @@ Misc Functions - `chebline` -- Chebyshev series representing given straight line. - `cheb2poly` -- convert a Chebyshev series to a polynomial. - `poly2cheb` -- convert a polynomial to a Chebyshev series. +- `chebinterp` -- approximate a function with Chebyshev polynomials. Classes ------- @@ -87,6 +88,7 @@ References """ from __future__ import division, absolute_import, print_function +import numbers import warnings import numpy as np import numpy.linalg as la @@ -102,7 +104,7 @@ __all__ = [ 'chebvander', 'chebfit', 'chebtrim', 'chebroots', 'chebpts1', 'chebpts2', 'Chebyshev', 'chebval2d', 'chebval3d', 'chebgrid2d', 'chebgrid3d', 'chebvander2d', 'chebvander3d', 'chebcompanion', - 'chebgauss', 'chebweight'] + 'chebgauss', 'chebweight', 'chebinterp'] chebtrim = pu.trimcoef @@ -1886,6 +1888,55 @@ def chebroots(c): return r +def chebinterp(func, deg, args=()): + """Return the Chebyshev series instance that interpolates a given function + at the Chebyshev points of the first kind over the interval [-1, 1]. + + Parameters + ---------- + func : function + The function to be approximated. It must be a function of a single + variable of the form f(x,a,b,c...), where a,b,c... are extra arguments + that can be passed in the `args` parameter. + deg : int + Degree of the resulting polynomial expressed in a Chebyshev basis. + args : tuple, optional + Extra arguments to be used in the function call. + + Returns + ------- + new_series : series + A series that represents the polynomial interpolation + to the function. + + Examples + -------- + >>> from numpy import tanh, pi + >>> import numpy.polynomial.chebyshev as C + >>> C.chebinterp(lambda x: tanh(x)+0.5, 8, domain=[0, 2*np.pi]) + array([ 1.30198814, 0.3540514 , -0.25209078, 0.14032589, -0.05706644, + 0.01226391, 0.00367748, -0.00455335]) + + .. versionadded:: 1.14.0 + + """ + ideg = int(deg) + if ideg != deg: + raise ValueError("deg must be integer") + if ideg < 0: + raise ValueError("deg must be non-negative") + + degp1 = deg+1 + xcheb = chebpts1(degp1) + yfunc = func(xcheb, *args) + m = chebvander(xcheb, deg) + c = np.dot(m.T, yfunc) + c[0] /= degp1 + c[1:] /= 0.5*degp1 + + return c + + def chebgauss(deg): """ Gauss-Chebyshev quadrature. @@ -2069,6 +2120,13 @@ class Chebyshev(ABCPolyBase): _roots = staticmethod(chebroots) _fromroots = staticmethod(chebfromroots) + @classmethod + def fromfunction(cls, func, deg, domain=None, args=()): + """Wrapper method for chebinterp()""" + xfunc = lambda x: func(pu.mapdomain(x, [-1, 1], domain)) + coef = chebinterp(xfunc, deg, args) + return cls(coef, domain=domain, window=chebdomain) + # Virtual properties nickname = 'cheb' domain = np.array(chebdomain) diff --git a/numpy/polynomial/tests/test_chebyshev.py b/numpy/polynomial/tests/test_chebyshev.py index 2e4344731..74701af1a 100644 --- a/numpy/polynomial/tests/test_chebyshev.py +++ b/numpy/polynomial/tests/test_chebyshev.py @@ -471,6 +471,26 @@ class TestFitting(object): assert_almost_equal(coef1, coef2) +class TestInterp(object): + + @staticmethod + def f(x): + return x * (x - 1) * (x - 2) + + def test_raises(self): + assert_raises(ValueError, cheb.chebinterp, self.f, -1, [-1, 1]) + assert_raises(ValueError, cheb.chebinterp, self.f, 10.1, [-1, 1]) + + def test_dimensions(self): + for i in range(1, 5): + assert_(cheb.chebinterp(self.f, i, [-1, 1]).shape == (i+1,)) + + def test_approx(self): + assert_almost_equal(cheb.chebinterp(lambda x: [1, 1, 1, 1], 3, [-1, 1]), np.array([1, 0, 0, 0])) + assert_almost_equal(cheb.chebinterp(lambda x: x, 3, [-1, 1]), np.array([0, 1, 0, 0])) + assert_almost_equal(cheb.chebinterp(self.f, 3, [-1, 1]), np.array([-3/2, 11/4, -3/2, 1/4])) + + class TestCompanion(object): def test_raises(self): |