annotate DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/polynomial/chebyshev.py @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2a2c65a20a8b
children
rev   line source
Chris@87 1 """
Chris@87 2 Objects for dealing with Chebyshev series.
Chris@87 3
Chris@87 4 This module provides a number of objects (mostly functions) useful for
Chris@87 5 dealing with Chebyshev series, including a `Chebyshev` class that
Chris@87 6 encapsulates the usual arithmetic operations. (General information
Chris@87 7 on how this module represents and works with such polynomials is in the
Chris@87 8 docstring for its "parent" sub-package, `numpy.polynomial`).
Chris@87 9
Chris@87 10 Constants
Chris@87 11 ---------
Chris@87 12 - `chebdomain` -- Chebyshev series default domain, [-1,1].
Chris@87 13 - `chebzero` -- (Coefficients of the) Chebyshev series that evaluates
Chris@87 14 identically to 0.
Chris@87 15 - `chebone` -- (Coefficients of the) Chebyshev series that evaluates
Chris@87 16 identically to 1.
Chris@87 17 - `chebx` -- (Coefficients of the) Chebyshev series for the identity map,
Chris@87 18 ``f(x) = x``.
Chris@87 19
Chris@87 20 Arithmetic
Chris@87 21 ----------
Chris@87 22 - `chebadd` -- add two Chebyshev series.
Chris@87 23 - `chebsub` -- subtract one Chebyshev series from another.
Chris@87 24 - `chebmul` -- multiply two Chebyshev series.
Chris@87 25 - `chebdiv` -- divide one Chebyshev series by another.
Chris@87 26 - `chebpow` -- raise a Chebyshev series to an positive integer power
Chris@87 27 - `chebval` -- evaluate a Chebyshev series at given points.
Chris@87 28 - `chebval2d` -- evaluate a 2D Chebyshev series at given points.
Chris@87 29 - `chebval3d` -- evaluate a 3D Chebyshev series at given points.
Chris@87 30 - `chebgrid2d` -- evaluate a 2D Chebyshev series on a Cartesian product.
Chris@87 31 - `chebgrid3d` -- evaluate a 3D Chebyshev series on a Cartesian product.
Chris@87 32
Chris@87 33 Calculus
Chris@87 34 --------
Chris@87 35 - `chebder` -- differentiate a Chebyshev series.
Chris@87 36 - `chebint` -- integrate a Chebyshev series.
Chris@87 37
Chris@87 38 Misc Functions
Chris@87 39 --------------
Chris@87 40 - `chebfromroots` -- create a Chebyshev series with specified roots.
Chris@87 41 - `chebroots` -- find the roots of a Chebyshev series.
Chris@87 42 - `chebvander` -- Vandermonde-like matrix for Chebyshev polynomials.
Chris@87 43 - `chebvander2d` -- Vandermonde-like matrix for 2D power series.
Chris@87 44 - `chebvander3d` -- Vandermonde-like matrix for 3D power series.
Chris@87 45 - `chebgauss` -- Gauss-Chebyshev quadrature, points and weights.
Chris@87 46 - `chebweight` -- Chebyshev weight function.
Chris@87 47 - `chebcompanion` -- symmetrized companion matrix in Chebyshev form.
Chris@87 48 - `chebfit` -- least-squares fit returning a Chebyshev series.
Chris@87 49 - `chebpts1` -- Chebyshev points of the first kind.
Chris@87 50 - `chebpts2` -- Chebyshev points of the second kind.
Chris@87 51 - `chebtrim` -- trim leading coefficients from a Chebyshev series.
Chris@87 52 - `chebline` -- Chebyshev series representing given straight line.
Chris@87 53 - `cheb2poly` -- convert a Chebyshev series to a polynomial.
Chris@87 54 - `poly2cheb` -- convert a polynomial to a Chebyshev series.
Chris@87 55
Chris@87 56 Classes
Chris@87 57 -------
Chris@87 58 - `Chebyshev` -- A Chebyshev series class.
Chris@87 59
Chris@87 60 See also
Chris@87 61 --------
Chris@87 62 `numpy.polynomial`
Chris@87 63
Chris@87 64 Notes
Chris@87 65 -----
Chris@87 66 The implementations of multiplication, division, integration, and
Chris@87 67 differentiation use the algebraic identities [1]_:
Chris@87 68
Chris@87 69 .. math ::
Chris@87 70 T_n(x) = \\frac{z^n + z^{-n}}{2} \\\\
Chris@87 71 z\\frac{dx}{dz} = \\frac{z - z^{-1}}{2}.
Chris@87 72
Chris@87 73 where
Chris@87 74
Chris@87 75 .. math :: x = \\frac{z + z^{-1}}{2}.
Chris@87 76
Chris@87 77 These identities allow a Chebyshev series to be expressed as a finite,
Chris@87 78 symmetric Laurent series. In this module, this sort of Laurent series
Chris@87 79 is referred to as a "z-series."
Chris@87 80
Chris@87 81 References
Chris@87 82 ----------
Chris@87 83 .. [1] A. T. Benjamin, et al., "Combinatorial Trigonometry with Chebyshev
Chris@87 84 Polynomials," *Journal of Statistical Planning and Inference 14*, 2008
Chris@87 85 (preprint: http://www.math.hmc.edu/~benjamin/papers/CombTrig.pdf, pg. 4)
Chris@87 86
Chris@87 87 """
Chris@87 88 from __future__ import division, absolute_import, print_function
Chris@87 89
Chris@87 90 import warnings
Chris@87 91 import numpy as np
Chris@87 92 import numpy.linalg as la
Chris@87 93
Chris@87 94 from . import polyutils as pu
Chris@87 95 from ._polybase import ABCPolyBase
Chris@87 96
Chris@87 97 __all__ = [
Chris@87 98 'chebzero', 'chebone', 'chebx', 'chebdomain', 'chebline', 'chebadd',
Chris@87 99 'chebsub', 'chebmulx', 'chebmul', 'chebdiv', 'chebpow', 'chebval',
Chris@87 100 'chebder', 'chebint', 'cheb2poly', 'poly2cheb', 'chebfromroots',
Chris@87 101 'chebvander', 'chebfit', 'chebtrim', 'chebroots', 'chebpts1',
Chris@87 102 'chebpts2', 'Chebyshev', 'chebval2d', 'chebval3d', 'chebgrid2d',
Chris@87 103 'chebgrid3d', 'chebvander2d', 'chebvander3d', 'chebcompanion',
Chris@87 104 'chebgauss', 'chebweight']
Chris@87 105
Chris@87 106 chebtrim = pu.trimcoef
Chris@87 107
Chris@87 108 #
Chris@87 109 # A collection of functions for manipulating z-series. These are private
Chris@87 110 # functions and do minimal error checking.
Chris@87 111 #
Chris@87 112
Chris@87 113 def _cseries_to_zseries(c):
Chris@87 114 """Covert Chebyshev series to z-series.
Chris@87 115
Chris@87 116 Covert a Chebyshev series to the equivalent z-series. The result is
Chris@87 117 never an empty array. The dtype of the return is the same as that of
Chris@87 118 the input. No checks are run on the arguments as this routine is for
Chris@87 119 internal use.
Chris@87 120
Chris@87 121 Parameters
Chris@87 122 ----------
Chris@87 123 c : 1-D ndarray
Chris@87 124 Chebyshev coefficients, ordered from low to high
Chris@87 125
Chris@87 126 Returns
Chris@87 127 -------
Chris@87 128 zs : 1-D ndarray
Chris@87 129 Odd length symmetric z-series, ordered from low to high.
Chris@87 130
Chris@87 131 """
Chris@87 132 n = c.size
Chris@87 133 zs = np.zeros(2*n-1, dtype=c.dtype)
Chris@87 134 zs[n-1:] = c/2
Chris@87 135 return zs + zs[::-1]
Chris@87 136
Chris@87 137
Chris@87 138 def _zseries_to_cseries(zs):
Chris@87 139 """Covert z-series to a Chebyshev series.
Chris@87 140
Chris@87 141 Covert a z series to the equivalent Chebyshev series. The result is
Chris@87 142 never an empty array. The dtype of the return is the same as that of
Chris@87 143 the input. No checks are run on the arguments as this routine is for
Chris@87 144 internal use.
Chris@87 145
Chris@87 146 Parameters
Chris@87 147 ----------
Chris@87 148 zs : 1-D ndarray
Chris@87 149 Odd length symmetric z-series, ordered from low to high.
Chris@87 150
Chris@87 151 Returns
Chris@87 152 -------
Chris@87 153 c : 1-D ndarray
Chris@87 154 Chebyshev coefficients, ordered from low to high.
Chris@87 155
Chris@87 156 """
Chris@87 157 n = (zs.size + 1)//2
Chris@87 158 c = zs[n-1:].copy()
Chris@87 159 c[1:n] *= 2
Chris@87 160 return c
Chris@87 161
Chris@87 162
Chris@87 163 def _zseries_mul(z1, z2):
Chris@87 164 """Multiply two z-series.
Chris@87 165
Chris@87 166 Multiply two z-series to produce a z-series.
Chris@87 167
Chris@87 168 Parameters
Chris@87 169 ----------
Chris@87 170 z1, z2 : 1-D ndarray
Chris@87 171 The arrays must be 1-D but this is not checked.
Chris@87 172
Chris@87 173 Returns
Chris@87 174 -------
Chris@87 175 product : 1-D ndarray
Chris@87 176 The product z-series.
Chris@87 177
Chris@87 178 Notes
Chris@87 179 -----
Chris@87 180 This is simply convolution. If symmetric/anti-symmetric z-series are
Chris@87 181 denoted by S/A then the following rules apply:
Chris@87 182
Chris@87 183 S*S, A*A -> S
Chris@87 184 S*A, A*S -> A
Chris@87 185
Chris@87 186 """
Chris@87 187 return np.convolve(z1, z2)
Chris@87 188
Chris@87 189
Chris@87 190 def _zseries_div(z1, z2):
Chris@87 191 """Divide the first z-series by the second.
Chris@87 192
Chris@87 193 Divide `z1` by `z2` and return the quotient and remainder as z-series.
Chris@87 194 Warning: this implementation only applies when both z1 and z2 have the
Chris@87 195 same symmetry, which is sufficient for present purposes.
Chris@87 196
Chris@87 197 Parameters
Chris@87 198 ----------
Chris@87 199 z1, z2 : 1-D ndarray
Chris@87 200 The arrays must be 1-D and have the same symmetry, but this is not
Chris@87 201 checked.
Chris@87 202
Chris@87 203 Returns
Chris@87 204 -------
Chris@87 205
Chris@87 206 (quotient, remainder) : 1-D ndarrays
Chris@87 207 Quotient and remainder as z-series.
Chris@87 208
Chris@87 209 Notes
Chris@87 210 -----
Chris@87 211 This is not the same as polynomial division on account of the desired form
Chris@87 212 of the remainder. If symmetric/anti-symmetric z-series are denoted by S/A
Chris@87 213 then the following rules apply:
Chris@87 214
Chris@87 215 S/S -> S,S
Chris@87 216 A/A -> S,A
Chris@87 217
Chris@87 218 The restriction to types of the same symmetry could be fixed but seems like
Chris@87 219 unneeded generality. There is no natural form for the remainder in the case
Chris@87 220 where there is no symmetry.
Chris@87 221
Chris@87 222 """
Chris@87 223 z1 = z1.copy()
Chris@87 224 z2 = z2.copy()
Chris@87 225 len1 = len(z1)
Chris@87 226 len2 = len(z2)
Chris@87 227 if len2 == 1:
Chris@87 228 z1 /= z2
Chris@87 229 return z1, z1[:1]*0
Chris@87 230 elif len1 < len2:
Chris@87 231 return z1[:1]*0, z1
Chris@87 232 else:
Chris@87 233 dlen = len1 - len2
Chris@87 234 scl = z2[0]
Chris@87 235 z2 /= scl
Chris@87 236 quo = np.empty(dlen + 1, dtype=z1.dtype)
Chris@87 237 i = 0
Chris@87 238 j = dlen
Chris@87 239 while i < j:
Chris@87 240 r = z1[i]
Chris@87 241 quo[i] = z1[i]
Chris@87 242 quo[dlen - i] = r
Chris@87 243 tmp = r*z2
Chris@87 244 z1[i:i+len2] -= tmp
Chris@87 245 z1[j:j+len2] -= tmp
Chris@87 246 i += 1
Chris@87 247 j -= 1
Chris@87 248 r = z1[i]
Chris@87 249 quo[i] = r
Chris@87 250 tmp = r*z2
Chris@87 251 z1[i:i+len2] -= tmp
Chris@87 252 quo /= scl
Chris@87 253 rem = z1[i+1:i-1+len2].copy()
Chris@87 254 return quo, rem
Chris@87 255
Chris@87 256
Chris@87 257 def _zseries_der(zs):
Chris@87 258 """Differentiate a z-series.
Chris@87 259
Chris@87 260 The derivative is with respect to x, not z. This is achieved using the
Chris@87 261 chain rule and the value of dx/dz given in the module notes.
Chris@87 262
Chris@87 263 Parameters
Chris@87 264 ----------
Chris@87 265 zs : z-series
Chris@87 266 The z-series to differentiate.
Chris@87 267
Chris@87 268 Returns
Chris@87 269 -------
Chris@87 270 derivative : z-series
Chris@87 271 The derivative
Chris@87 272
Chris@87 273 Notes
Chris@87 274 -----
Chris@87 275 The zseries for x (ns) has been multiplied by two in order to avoid
Chris@87 276 using floats that are incompatible with Decimal and likely other
Chris@87 277 specialized scalar types. This scaling has been compensated by
Chris@87 278 multiplying the value of zs by two also so that the two cancels in the
Chris@87 279 division.
Chris@87 280
Chris@87 281 """
Chris@87 282 n = len(zs)//2
Chris@87 283 ns = np.array([-1, 0, 1], dtype=zs.dtype)
Chris@87 284 zs *= np.arange(-n, n+1)*2
Chris@87 285 d, r = _zseries_div(zs, ns)
Chris@87 286 return d
Chris@87 287
Chris@87 288
Chris@87 289 def _zseries_int(zs):
Chris@87 290 """Integrate a z-series.
Chris@87 291
Chris@87 292 The integral is with respect to x, not z. This is achieved by a change
Chris@87 293 of variable using dx/dz given in the module notes.
Chris@87 294
Chris@87 295 Parameters
Chris@87 296 ----------
Chris@87 297 zs : z-series
Chris@87 298 The z-series to integrate
Chris@87 299
Chris@87 300 Returns
Chris@87 301 -------
Chris@87 302 integral : z-series
Chris@87 303 The indefinite integral
Chris@87 304
Chris@87 305 Notes
Chris@87 306 -----
Chris@87 307 The zseries for x (ns) has been multiplied by two in order to avoid
Chris@87 308 using floats that are incompatible with Decimal and likely other
Chris@87 309 specialized scalar types. This scaling has been compensated by
Chris@87 310 dividing the resulting zs by two.
Chris@87 311
Chris@87 312 """
Chris@87 313 n = 1 + len(zs)//2
Chris@87 314 ns = np.array([-1, 0, 1], dtype=zs.dtype)
Chris@87 315 zs = _zseries_mul(zs, ns)
Chris@87 316 div = np.arange(-n, n+1)*2
Chris@87 317 zs[:n] /= div[:n]
Chris@87 318 zs[n+1:] /= div[n+1:]
Chris@87 319 zs[n] = 0
Chris@87 320 return zs
Chris@87 321
Chris@87 322 #
Chris@87 323 # Chebyshev series functions
Chris@87 324 #
Chris@87 325
Chris@87 326
Chris@87 327 def poly2cheb(pol):
Chris@87 328 """
Chris@87 329 Convert a polynomial to a Chebyshev series.
Chris@87 330
Chris@87 331 Convert an array representing the coefficients of a polynomial (relative
Chris@87 332 to the "standard" basis) ordered from lowest degree to highest, to an
Chris@87 333 array of the coefficients of the equivalent Chebyshev series, ordered
Chris@87 334 from lowest to highest degree.
Chris@87 335
Chris@87 336 Parameters
Chris@87 337 ----------
Chris@87 338 pol : array_like
Chris@87 339 1-D array containing the polynomial coefficients
Chris@87 340
Chris@87 341 Returns
Chris@87 342 -------
Chris@87 343 c : ndarray
Chris@87 344 1-D array containing the coefficients of the equivalent Chebyshev
Chris@87 345 series.
Chris@87 346
Chris@87 347 See Also
Chris@87 348 --------
Chris@87 349 cheb2poly
Chris@87 350
Chris@87 351 Notes
Chris@87 352 -----
Chris@87 353 The easy way to do conversions between polynomial basis sets
Chris@87 354 is to use the convert method of a class instance.
Chris@87 355
Chris@87 356 Examples
Chris@87 357 --------
Chris@87 358 >>> from numpy import polynomial as P
Chris@87 359 >>> p = P.Polynomial(range(4))
Chris@87 360 >>> p
Chris@87 361 Polynomial([ 0., 1., 2., 3.], [-1., 1.])
Chris@87 362 >>> c = p.convert(kind=P.Chebyshev)
Chris@87 363 >>> c
Chris@87 364 Chebyshev([ 1. , 3.25, 1. , 0.75], [-1., 1.])
Chris@87 365 >>> P.poly2cheb(range(4))
Chris@87 366 array([ 1. , 3.25, 1. , 0.75])
Chris@87 367
Chris@87 368 """
Chris@87 369 [pol] = pu.as_series([pol])
Chris@87 370 deg = len(pol) - 1
Chris@87 371 res = 0
Chris@87 372 for i in range(deg, -1, -1):
Chris@87 373 res = chebadd(chebmulx(res), pol[i])
Chris@87 374 return res
Chris@87 375
Chris@87 376
Chris@87 377 def cheb2poly(c):
Chris@87 378 """
Chris@87 379 Convert a Chebyshev series to a polynomial.
Chris@87 380
Chris@87 381 Convert an array representing the coefficients of a Chebyshev series,
Chris@87 382 ordered from lowest degree to highest, to an array of the coefficients
Chris@87 383 of the equivalent polynomial (relative to the "standard" basis) ordered
Chris@87 384 from lowest to highest degree.
Chris@87 385
Chris@87 386 Parameters
Chris@87 387 ----------
Chris@87 388 c : array_like
Chris@87 389 1-D array containing the Chebyshev series coefficients, ordered
Chris@87 390 from lowest order term to highest.
Chris@87 391
Chris@87 392 Returns
Chris@87 393 -------
Chris@87 394 pol : ndarray
Chris@87 395 1-D array containing the coefficients of the equivalent polynomial
Chris@87 396 (relative to the "standard" basis) ordered from lowest order term
Chris@87 397 to highest.
Chris@87 398
Chris@87 399 See Also
Chris@87 400 --------
Chris@87 401 poly2cheb
Chris@87 402
Chris@87 403 Notes
Chris@87 404 -----
Chris@87 405 The easy way to do conversions between polynomial basis sets
Chris@87 406 is to use the convert method of a class instance.
Chris@87 407
Chris@87 408 Examples
Chris@87 409 --------
Chris@87 410 >>> from numpy import polynomial as P
Chris@87 411 >>> c = P.Chebyshev(range(4))
Chris@87 412 >>> c
Chris@87 413 Chebyshev([ 0., 1., 2., 3.], [-1., 1.])
Chris@87 414 >>> p = c.convert(kind=P.Polynomial)
Chris@87 415 >>> p
Chris@87 416 Polynomial([ -2., -8., 4., 12.], [-1., 1.])
Chris@87 417 >>> P.cheb2poly(range(4))
Chris@87 418 array([ -2., -8., 4., 12.])
Chris@87 419
Chris@87 420 """
Chris@87 421 from .polynomial import polyadd, polysub, polymulx
Chris@87 422
Chris@87 423 [c] = pu.as_series([c])
Chris@87 424 n = len(c)
Chris@87 425 if n < 3:
Chris@87 426 return c
Chris@87 427 else:
Chris@87 428 c0 = c[-2]
Chris@87 429 c1 = c[-1]
Chris@87 430 # i is the current degree of c1
Chris@87 431 for i in range(n - 1, 1, -1):
Chris@87 432 tmp = c0
Chris@87 433 c0 = polysub(c[i - 2], c1)
Chris@87 434 c1 = polyadd(tmp, polymulx(c1)*2)
Chris@87 435 return polyadd(c0, polymulx(c1))
Chris@87 436
Chris@87 437
Chris@87 438 #
Chris@87 439 # These are constant arrays are of integer type so as to be compatible
Chris@87 440 # with the widest range of other types, such as Decimal.
Chris@87 441 #
Chris@87 442
Chris@87 443 # Chebyshev default domain.
Chris@87 444 chebdomain = np.array([-1, 1])
Chris@87 445
Chris@87 446 # Chebyshev coefficients representing zero.
Chris@87 447 chebzero = np.array([0])
Chris@87 448
Chris@87 449 # Chebyshev coefficients representing one.
Chris@87 450 chebone = np.array([1])
Chris@87 451
Chris@87 452 # Chebyshev coefficients representing the identity x.
Chris@87 453 chebx = np.array([0, 1])
Chris@87 454
Chris@87 455
Chris@87 456 def chebline(off, scl):
Chris@87 457 """
Chris@87 458 Chebyshev series whose graph is a straight line.
Chris@87 459
Chris@87 460
Chris@87 461
Chris@87 462 Parameters
Chris@87 463 ----------
Chris@87 464 off, scl : scalars
Chris@87 465 The specified line is given by ``off + scl*x``.
Chris@87 466
Chris@87 467 Returns
Chris@87 468 -------
Chris@87 469 y : ndarray
Chris@87 470 This module's representation of the Chebyshev series for
Chris@87 471 ``off + scl*x``.
Chris@87 472
Chris@87 473 See Also
Chris@87 474 --------
Chris@87 475 polyline
Chris@87 476
Chris@87 477 Examples
Chris@87 478 --------
Chris@87 479 >>> import numpy.polynomial.chebyshev as C
Chris@87 480 >>> C.chebline(3,2)
Chris@87 481 array([3, 2])
Chris@87 482 >>> C.chebval(-3, C.chebline(3,2)) # should be -3
Chris@87 483 -3.0
Chris@87 484
Chris@87 485 """
Chris@87 486 if scl != 0:
Chris@87 487 return np.array([off, scl])
Chris@87 488 else:
Chris@87 489 return np.array([off])
Chris@87 490
Chris@87 491
Chris@87 492 def chebfromroots(roots):
Chris@87 493 """
Chris@87 494 Generate a Chebyshev series with given roots.
Chris@87 495
Chris@87 496 The function returns the coefficients of the polynomial
Chris@87 497
Chris@87 498 .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
Chris@87 499
Chris@87 500 in Chebyshev form, where the `r_n` are the roots specified in `roots`.
Chris@87 501 If a zero has multiplicity n, then it must appear in `roots` n times.
Chris@87 502 For instance, if 2 is a root of multiplicity three and 3 is a root of
Chris@87 503 multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
Chris@87 504 roots can appear in any order.
Chris@87 505
Chris@87 506 If the returned coefficients are `c`, then
Chris@87 507
Chris@87 508 .. math:: p(x) = c_0 + c_1 * T_1(x) + ... + c_n * T_n(x)
Chris@87 509
Chris@87 510 The coefficient of the last term is not generally 1 for monic
Chris@87 511 polynomials in Chebyshev form.
Chris@87 512
Chris@87 513 Parameters
Chris@87 514 ----------
Chris@87 515 roots : array_like
Chris@87 516 Sequence containing the roots.
Chris@87 517
Chris@87 518 Returns
Chris@87 519 -------
Chris@87 520 out : ndarray
Chris@87 521 1-D array of coefficients. If all roots are real then `out` is a
Chris@87 522 real array, if some of the roots are complex, then `out` is complex
Chris@87 523 even if all the coefficients in the result are real (see Examples
Chris@87 524 below).
Chris@87 525
Chris@87 526 See Also
Chris@87 527 --------
Chris@87 528 polyfromroots, legfromroots, lagfromroots, hermfromroots,
Chris@87 529 hermefromroots.
Chris@87 530
Chris@87 531 Examples
Chris@87 532 --------
Chris@87 533 >>> import numpy.polynomial.chebyshev as C
Chris@87 534 >>> C.chebfromroots((-1,0,1)) # x^3 - x relative to the standard basis
Chris@87 535 array([ 0. , -0.25, 0. , 0.25])
Chris@87 536 >>> j = complex(0,1)
Chris@87 537 >>> C.chebfromroots((-j,j)) # x^2 + 1 relative to the standard basis
Chris@87 538 array([ 1.5+0.j, 0.0+0.j, 0.5+0.j])
Chris@87 539
Chris@87 540 """
Chris@87 541 if len(roots) == 0:
Chris@87 542 return np.ones(1)
Chris@87 543 else:
Chris@87 544 [roots] = pu.as_series([roots], trim=False)
Chris@87 545 roots.sort()
Chris@87 546 p = [chebline(-r, 1) for r in roots]
Chris@87 547 n = len(p)
Chris@87 548 while n > 1:
Chris@87 549 m, r = divmod(n, 2)
Chris@87 550 tmp = [chebmul(p[i], p[i+m]) for i in range(m)]
Chris@87 551 if r:
Chris@87 552 tmp[0] = chebmul(tmp[0], p[-1])
Chris@87 553 p = tmp
Chris@87 554 n = m
Chris@87 555 return p[0]
Chris@87 556
Chris@87 557
Chris@87 558 def chebadd(c1, c2):
Chris@87 559 """
Chris@87 560 Add one Chebyshev series to another.
Chris@87 561
Chris@87 562 Returns the sum of two Chebyshev series `c1` + `c2`. The arguments
Chris@87 563 are sequences of coefficients ordered from lowest order term to
Chris@87 564 highest, i.e., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
Chris@87 565
Chris@87 566 Parameters
Chris@87 567 ----------
Chris@87 568 c1, c2 : array_like
Chris@87 569 1-D arrays of Chebyshev series coefficients ordered from low to
Chris@87 570 high.
Chris@87 571
Chris@87 572 Returns
Chris@87 573 -------
Chris@87 574 out : ndarray
Chris@87 575 Array representing the Chebyshev series of their sum.
Chris@87 576
Chris@87 577 See Also
Chris@87 578 --------
Chris@87 579 chebsub, chebmul, chebdiv, chebpow
Chris@87 580
Chris@87 581 Notes
Chris@87 582 -----
Chris@87 583 Unlike multiplication, division, etc., the sum of two Chebyshev series
Chris@87 584 is a Chebyshev series (without having to "reproject" the result onto
Chris@87 585 the basis set) so addition, just like that of "standard" polynomials,
Chris@87 586 is simply "component-wise."
Chris@87 587
Chris@87 588 Examples
Chris@87 589 --------
Chris@87 590 >>> from numpy.polynomial import chebyshev as C
Chris@87 591 >>> c1 = (1,2,3)
Chris@87 592 >>> c2 = (3,2,1)
Chris@87 593 >>> C.chebadd(c1,c2)
Chris@87 594 array([ 4., 4., 4.])
Chris@87 595
Chris@87 596 """
Chris@87 597 # c1, c2 are trimmed copies
Chris@87 598 [c1, c2] = pu.as_series([c1, c2])
Chris@87 599 if len(c1) > len(c2):
Chris@87 600 c1[:c2.size] += c2
Chris@87 601 ret = c1
Chris@87 602 else:
Chris@87 603 c2[:c1.size] += c1
Chris@87 604 ret = c2
Chris@87 605 return pu.trimseq(ret)
Chris@87 606
Chris@87 607
Chris@87 608 def chebsub(c1, c2):
Chris@87 609 """
Chris@87 610 Subtract one Chebyshev series from another.
Chris@87 611
Chris@87 612 Returns the difference of two Chebyshev series `c1` - `c2`. The
Chris@87 613 sequences of coefficients are from lowest order term to highest, i.e.,
Chris@87 614 [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
Chris@87 615
Chris@87 616 Parameters
Chris@87 617 ----------
Chris@87 618 c1, c2 : array_like
Chris@87 619 1-D arrays of Chebyshev series coefficients ordered from low to
Chris@87 620 high.
Chris@87 621
Chris@87 622 Returns
Chris@87 623 -------
Chris@87 624 out : ndarray
Chris@87 625 Of Chebyshev series coefficients representing their difference.
Chris@87 626
Chris@87 627 See Also
Chris@87 628 --------
Chris@87 629 chebadd, chebmul, chebdiv, chebpow
Chris@87 630
Chris@87 631 Notes
Chris@87 632 -----
Chris@87 633 Unlike multiplication, division, etc., the difference of two Chebyshev
Chris@87 634 series is a Chebyshev series (without having to "reproject" the result
Chris@87 635 onto the basis set) so subtraction, just like that of "standard"
Chris@87 636 polynomials, is simply "component-wise."
Chris@87 637
Chris@87 638 Examples
Chris@87 639 --------
Chris@87 640 >>> from numpy.polynomial import chebyshev as C
Chris@87 641 >>> c1 = (1,2,3)
Chris@87 642 >>> c2 = (3,2,1)
Chris@87 643 >>> C.chebsub(c1,c2)
Chris@87 644 array([-2., 0., 2.])
Chris@87 645 >>> C.chebsub(c2,c1) # -C.chebsub(c1,c2)
Chris@87 646 array([ 2., 0., -2.])
Chris@87 647
Chris@87 648 """
Chris@87 649 # c1, c2 are trimmed copies
Chris@87 650 [c1, c2] = pu.as_series([c1, c2])
Chris@87 651 if len(c1) > len(c2):
Chris@87 652 c1[:c2.size] -= c2
Chris@87 653 ret = c1
Chris@87 654 else:
Chris@87 655 c2 = -c2
Chris@87 656 c2[:c1.size] += c1
Chris@87 657 ret = c2
Chris@87 658 return pu.trimseq(ret)
Chris@87 659
Chris@87 660
Chris@87 661 def chebmulx(c):
Chris@87 662 """Multiply a Chebyshev series by x.
Chris@87 663
Chris@87 664 Multiply the polynomial `c` by x, where x is the independent
Chris@87 665 variable.
Chris@87 666
Chris@87 667
Chris@87 668 Parameters
Chris@87 669 ----------
Chris@87 670 c : array_like
Chris@87 671 1-D array of Chebyshev series coefficients ordered from low to
Chris@87 672 high.
Chris@87 673
Chris@87 674 Returns
Chris@87 675 -------
Chris@87 676 out : ndarray
Chris@87 677 Array representing the result of the multiplication.
Chris@87 678
Chris@87 679 Notes
Chris@87 680 -----
Chris@87 681
Chris@87 682 .. versionadded:: 1.5.0
Chris@87 683
Chris@87 684 """
Chris@87 685 # c is a trimmed copy
Chris@87 686 [c] = pu.as_series([c])
Chris@87 687 # The zero series needs special treatment
Chris@87 688 if len(c) == 1 and c[0] == 0:
Chris@87 689 return c
Chris@87 690
Chris@87 691 prd = np.empty(len(c) + 1, dtype=c.dtype)
Chris@87 692 prd[0] = c[0]*0
Chris@87 693 prd[1] = c[0]
Chris@87 694 if len(c) > 1:
Chris@87 695 tmp = c[1:]/2
Chris@87 696 prd[2:] = tmp
Chris@87 697 prd[0:-2] += tmp
Chris@87 698 return prd
Chris@87 699
Chris@87 700
Chris@87 701 def chebmul(c1, c2):
Chris@87 702 """
Chris@87 703 Multiply one Chebyshev series by another.
Chris@87 704
Chris@87 705 Returns the product of two Chebyshev series `c1` * `c2`. The arguments
Chris@87 706 are sequences of coefficients, from lowest order "term" to highest,
Chris@87 707 e.g., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
Chris@87 708
Chris@87 709 Parameters
Chris@87 710 ----------
Chris@87 711 c1, c2 : array_like
Chris@87 712 1-D arrays of Chebyshev series coefficients ordered from low to
Chris@87 713 high.
Chris@87 714
Chris@87 715 Returns
Chris@87 716 -------
Chris@87 717 out : ndarray
Chris@87 718 Of Chebyshev series coefficients representing their product.
Chris@87 719
Chris@87 720 See Also
Chris@87 721 --------
Chris@87 722 chebadd, chebsub, chebdiv, chebpow
Chris@87 723
Chris@87 724 Notes
Chris@87 725 -----
Chris@87 726 In general, the (polynomial) product of two C-series results in terms
Chris@87 727 that are not in the Chebyshev polynomial basis set. Thus, to express
Chris@87 728 the product as a C-series, it is typically necessary to "reproject"
Chris@87 729 the product onto said basis set, which typically produces
Chris@87 730 "unintuitive live" (but correct) results; see Examples section below.
Chris@87 731
Chris@87 732 Examples
Chris@87 733 --------
Chris@87 734 >>> from numpy.polynomial import chebyshev as C
Chris@87 735 >>> c1 = (1,2,3)
Chris@87 736 >>> c2 = (3,2,1)
Chris@87 737 >>> C.chebmul(c1,c2) # multiplication requires "reprojection"
Chris@87 738 array([ 6.5, 12. , 12. , 4. , 1.5])
Chris@87 739
Chris@87 740 """
Chris@87 741 # c1, c2 are trimmed copies
Chris@87 742 [c1, c2] = pu.as_series([c1, c2])
Chris@87 743 z1 = _cseries_to_zseries(c1)
Chris@87 744 z2 = _cseries_to_zseries(c2)
Chris@87 745 prd = _zseries_mul(z1, z2)
Chris@87 746 ret = _zseries_to_cseries(prd)
Chris@87 747 return pu.trimseq(ret)
Chris@87 748
Chris@87 749
Chris@87 750 def chebdiv(c1, c2):
Chris@87 751 """
Chris@87 752 Divide one Chebyshev series by another.
Chris@87 753
Chris@87 754 Returns the quotient-with-remainder of two Chebyshev series
Chris@87 755 `c1` / `c2`. The arguments are sequences of coefficients from lowest
Chris@87 756 order "term" to highest, e.g., [1,2,3] represents the series
Chris@87 757 ``T_0 + 2*T_1 + 3*T_2``.
Chris@87 758
Chris@87 759 Parameters
Chris@87 760 ----------
Chris@87 761 c1, c2 : array_like
Chris@87 762 1-D arrays of Chebyshev series coefficients ordered from low to
Chris@87 763 high.
Chris@87 764
Chris@87 765 Returns
Chris@87 766 -------
Chris@87 767 [quo, rem] : ndarrays
Chris@87 768 Of Chebyshev series coefficients representing the quotient and
Chris@87 769 remainder.
Chris@87 770
Chris@87 771 See Also
Chris@87 772 --------
Chris@87 773 chebadd, chebsub, chebmul, chebpow
Chris@87 774
Chris@87 775 Notes
Chris@87 776 -----
Chris@87 777 In general, the (polynomial) division of one C-series by another
Chris@87 778 results in quotient and remainder terms that are not in the Chebyshev
Chris@87 779 polynomial basis set. Thus, to express these results as C-series, it
Chris@87 780 is typically necessary to "reproject" the results onto said basis
Chris@87 781 set, which typically produces "unintuitive" (but correct) results;
Chris@87 782 see Examples section below.
Chris@87 783
Chris@87 784 Examples
Chris@87 785 --------
Chris@87 786 >>> from numpy.polynomial import chebyshev as C
Chris@87 787 >>> c1 = (1,2,3)
Chris@87 788 >>> c2 = (3,2,1)
Chris@87 789 >>> C.chebdiv(c1,c2) # quotient "intuitive," remainder not
Chris@87 790 (array([ 3.]), array([-8., -4.]))
Chris@87 791 >>> c2 = (0,1,2,3)
Chris@87 792 >>> C.chebdiv(c2,c1) # neither "intuitive"
Chris@87 793 (array([ 0., 2.]), array([-2., -4.]))
Chris@87 794
Chris@87 795 """
Chris@87 796 # c1, c2 are trimmed copies
Chris@87 797 [c1, c2] = pu.as_series([c1, c2])
Chris@87 798 if c2[-1] == 0:
Chris@87 799 raise ZeroDivisionError()
Chris@87 800
Chris@87 801 lc1 = len(c1)
Chris@87 802 lc2 = len(c2)
Chris@87 803 if lc1 < lc2:
Chris@87 804 return c1[:1]*0, c1
Chris@87 805 elif lc2 == 1:
Chris@87 806 return c1/c2[-1], c1[:1]*0
Chris@87 807 else:
Chris@87 808 z1 = _cseries_to_zseries(c1)
Chris@87 809 z2 = _cseries_to_zseries(c2)
Chris@87 810 quo, rem = _zseries_div(z1, z2)
Chris@87 811 quo = pu.trimseq(_zseries_to_cseries(quo))
Chris@87 812 rem = pu.trimseq(_zseries_to_cseries(rem))
Chris@87 813 return quo, rem
Chris@87 814
Chris@87 815
Chris@87 816 def chebpow(c, pow, maxpower=16):
Chris@87 817 """Raise a Chebyshev series to a power.
Chris@87 818
Chris@87 819 Returns the Chebyshev series `c` raised to the power `pow`. The
Chris@87 820 argument `c` is a sequence of coefficients ordered from low to high.
Chris@87 821 i.e., [1,2,3] is the series ``T_0 + 2*T_1 + 3*T_2.``
Chris@87 822
Chris@87 823 Parameters
Chris@87 824 ----------
Chris@87 825 c : array_like
Chris@87 826 1-D array of Chebyshev series coefficients ordered from low to
Chris@87 827 high.
Chris@87 828 pow : integer
Chris@87 829 Power to which the series will be raised
Chris@87 830 maxpower : integer, optional
Chris@87 831 Maximum power allowed. This is mainly to limit growth of the series
Chris@87 832 to unmanageable size. Default is 16
Chris@87 833
Chris@87 834 Returns
Chris@87 835 -------
Chris@87 836 coef : ndarray
Chris@87 837 Chebyshev series of power.
Chris@87 838
Chris@87 839 See Also
Chris@87 840 --------
Chris@87 841 chebadd, chebsub, chebmul, chebdiv
Chris@87 842
Chris@87 843 Examples
Chris@87 844 --------
Chris@87 845
Chris@87 846 """
Chris@87 847 # c is a trimmed copy
Chris@87 848 [c] = pu.as_series([c])
Chris@87 849 power = int(pow)
Chris@87 850 if power != pow or power < 0:
Chris@87 851 raise ValueError("Power must be a non-negative integer.")
Chris@87 852 elif maxpower is not None and power > maxpower:
Chris@87 853 raise ValueError("Power is too large")
Chris@87 854 elif power == 0:
Chris@87 855 return np.array([1], dtype=c.dtype)
Chris@87 856 elif power == 1:
Chris@87 857 return c
Chris@87 858 else:
Chris@87 859 # This can be made more efficient by using powers of two
Chris@87 860 # in the usual way.
Chris@87 861 zs = _cseries_to_zseries(c)
Chris@87 862 prd = zs
Chris@87 863 for i in range(2, power + 1):
Chris@87 864 prd = np.convolve(prd, zs)
Chris@87 865 return _zseries_to_cseries(prd)
Chris@87 866
Chris@87 867
Chris@87 868 def chebder(c, m=1, scl=1, axis=0):
Chris@87 869 """
Chris@87 870 Differentiate a Chebyshev series.
Chris@87 871
Chris@87 872 Returns the Chebyshev series coefficients `c` differentiated `m` times
Chris@87 873 along `axis`. At each iteration the result is multiplied by `scl` (the
Chris@87 874 scaling factor is for use in a linear change of variable). The argument
Chris@87 875 `c` is an array of coefficients from low to high degree along each
Chris@87 876 axis, e.g., [1,2,3] represents the series ``1*T_0 + 2*T_1 + 3*T_2``
Chris@87 877 while [[1,2],[1,2]] represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) +
Chris@87 878 2*T_0(x)*T_1(y) + 2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is
Chris@87 879 ``y``.
Chris@87 880
Chris@87 881 Parameters
Chris@87 882 ----------
Chris@87 883 c : array_like
Chris@87 884 Array of Chebyshev series coefficients. If c is multidimensional
Chris@87 885 the different axis correspond to different variables with the
Chris@87 886 degree in each axis given by the corresponding index.
Chris@87 887 m : int, optional
Chris@87 888 Number of derivatives taken, must be non-negative. (Default: 1)
Chris@87 889 scl : scalar, optional
Chris@87 890 Each differentiation is multiplied by `scl`. The end result is
Chris@87 891 multiplication by ``scl**m``. This is for use in a linear change of
Chris@87 892 variable. (Default: 1)
Chris@87 893 axis : int, optional
Chris@87 894 Axis over which the derivative is taken. (Default: 0).
Chris@87 895
Chris@87 896 .. versionadded:: 1.7.0
Chris@87 897
Chris@87 898 Returns
Chris@87 899 -------
Chris@87 900 der : ndarray
Chris@87 901 Chebyshev series of the derivative.
Chris@87 902
Chris@87 903 See Also
Chris@87 904 --------
Chris@87 905 chebint
Chris@87 906
Chris@87 907 Notes
Chris@87 908 -----
Chris@87 909 In general, the result of differentiating a C-series needs to be
Chris@87 910 "reprojected" onto the C-series basis set. Thus, typically, the
Chris@87 911 result of this function is "unintuitive," albeit correct; see Examples
Chris@87 912 section below.
Chris@87 913
Chris@87 914 Examples
Chris@87 915 --------
Chris@87 916 >>> from numpy.polynomial import chebyshev as C
Chris@87 917 >>> c = (1,2,3,4)
Chris@87 918 >>> C.chebder(c)
Chris@87 919 array([ 14., 12., 24.])
Chris@87 920 >>> C.chebder(c,3)
Chris@87 921 array([ 96.])
Chris@87 922 >>> C.chebder(c,scl=-1)
Chris@87 923 array([-14., -12., -24.])
Chris@87 924 >>> C.chebder(c,2,-1)
Chris@87 925 array([ 12., 96.])
Chris@87 926
Chris@87 927 """
Chris@87 928 c = np.array(c, ndmin=1, copy=1)
Chris@87 929 if c.dtype.char in '?bBhHiIlLqQpP':
Chris@87 930 c = c.astype(np.double)
Chris@87 931 cnt, iaxis = [int(t) for t in [m, axis]]
Chris@87 932
Chris@87 933 if cnt != m:
Chris@87 934 raise ValueError("The order of derivation must be integer")
Chris@87 935 if cnt < 0:
Chris@87 936 raise ValueError("The order of derivation must be non-negative")
Chris@87 937 if iaxis != axis:
Chris@87 938 raise ValueError("The axis must be integer")
Chris@87 939 if not -c.ndim <= iaxis < c.ndim:
Chris@87 940 raise ValueError("The axis is out of range")
Chris@87 941 if iaxis < 0:
Chris@87 942 iaxis += c.ndim
Chris@87 943
Chris@87 944 if cnt == 0:
Chris@87 945 return c
Chris@87 946
Chris@87 947 c = np.rollaxis(c, iaxis)
Chris@87 948 n = len(c)
Chris@87 949 if cnt >= n:
Chris@87 950 c = c[:1]*0
Chris@87 951 else:
Chris@87 952 for i in range(cnt):
Chris@87 953 n = n - 1
Chris@87 954 c *= scl
Chris@87 955 der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
Chris@87 956 for j in range(n, 2, -1):
Chris@87 957 der[j - 1] = (2*j)*c[j]
Chris@87 958 c[j - 2] += (j*c[j])/(j - 2)
Chris@87 959 if n > 1:
Chris@87 960 der[1] = 4*c[2]
Chris@87 961 der[0] = c[1]
Chris@87 962 c = der
Chris@87 963 c = np.rollaxis(c, 0, iaxis + 1)
Chris@87 964 return c
Chris@87 965
Chris@87 966
Chris@87 967 def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
Chris@87 968 """
Chris@87 969 Integrate a Chebyshev series.
Chris@87 970
Chris@87 971 Returns the Chebyshev series coefficients `c` integrated `m` times from
Chris@87 972 `lbnd` along `axis`. At each iteration the resulting series is
Chris@87 973 **multiplied** by `scl` and an integration constant, `k`, is added.
Chris@87 974 The scaling factor is for use in a linear change of variable. ("Buyer
Chris@87 975 beware": note that, depending on what one is doing, one may want `scl`
Chris@87 976 to be the reciprocal of what one might expect; for more information,
Chris@87 977 see the Notes section below.) The argument `c` is an array of
Chris@87 978 coefficients from low to high degree along each axis, e.g., [1,2,3]
Chris@87 979 represents the series ``T_0 + 2*T_1 + 3*T_2`` while [[1,2],[1,2]]
Chris@87 980 represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) + 2*T_0(x)*T_1(y) +
Chris@87 981 2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
Chris@87 982
Chris@87 983 Parameters
Chris@87 984 ----------
Chris@87 985 c : array_like
Chris@87 986 Array of Chebyshev series coefficients. If c is multidimensional
Chris@87 987 the different axis correspond to different variables with the
Chris@87 988 degree in each axis given by the corresponding index.
Chris@87 989 m : int, optional
Chris@87 990 Order of integration, must be positive. (Default: 1)
Chris@87 991 k : {[], list, scalar}, optional
Chris@87 992 Integration constant(s). The value of the first integral at zero
Chris@87 993 is the first value in the list, the value of the second integral
Chris@87 994 at zero is the second value, etc. If ``k == []`` (the default),
Chris@87 995 all constants are set to zero. If ``m == 1``, a single scalar can
Chris@87 996 be given instead of a list.
Chris@87 997 lbnd : scalar, optional
Chris@87 998 The lower bound of the integral. (Default: 0)
Chris@87 999 scl : scalar, optional
Chris@87 1000 Following each integration the result is *multiplied* by `scl`
Chris@87 1001 before the integration constant is added. (Default: 1)
Chris@87 1002 axis : int, optional
Chris@87 1003 Axis over which the integral is taken. (Default: 0).
Chris@87 1004
Chris@87 1005 .. versionadded:: 1.7.0
Chris@87 1006
Chris@87 1007 Returns
Chris@87 1008 -------
Chris@87 1009 S : ndarray
Chris@87 1010 C-series coefficients of the integral.
Chris@87 1011
Chris@87 1012 Raises
Chris@87 1013 ------
Chris@87 1014 ValueError
Chris@87 1015 If ``m < 1``, ``len(k) > m``, ``np.isscalar(lbnd) == False``, or
Chris@87 1016 ``np.isscalar(scl) == False``.
Chris@87 1017
Chris@87 1018 See Also
Chris@87 1019 --------
Chris@87 1020 chebder
Chris@87 1021
Chris@87 1022 Notes
Chris@87 1023 -----
Chris@87 1024 Note that the result of each integration is *multiplied* by `scl`.
Chris@87 1025 Why is this important to note? Say one is making a linear change of
Chris@87 1026 variable :math:`u = ax + b` in an integral relative to `x`. Then
Chris@87 1027 .. math::`dx = du/a`, so one will need to set `scl` equal to
Chris@87 1028 :math:`1/a`- perhaps not what one would have first thought.
Chris@87 1029
Chris@87 1030 Also note that, in general, the result of integrating a C-series needs
Chris@87 1031 to be "reprojected" onto the C-series basis set. Thus, typically,
Chris@87 1032 the result of this function is "unintuitive," albeit correct; see
Chris@87 1033 Examples section below.
Chris@87 1034
Chris@87 1035 Examples
Chris@87 1036 --------
Chris@87 1037 >>> from numpy.polynomial import chebyshev as C
Chris@87 1038 >>> c = (1,2,3)
Chris@87 1039 >>> C.chebint(c)
Chris@87 1040 array([ 0.5, -0.5, 0.5, 0.5])
Chris@87 1041 >>> C.chebint(c,3)
Chris@87 1042 array([ 0.03125 , -0.1875 , 0.04166667, -0.05208333, 0.01041667,
Chris@87 1043 0.00625 ])
Chris@87 1044 >>> C.chebint(c, k=3)
Chris@87 1045 array([ 3.5, -0.5, 0.5, 0.5])
Chris@87 1046 >>> C.chebint(c,lbnd=-2)
Chris@87 1047 array([ 8.5, -0.5, 0.5, 0.5])
Chris@87 1048 >>> C.chebint(c,scl=-2)
Chris@87 1049 array([-1., 1., -1., -1.])
Chris@87 1050
Chris@87 1051 """
Chris@87 1052 c = np.array(c, ndmin=1, copy=1)
Chris@87 1053 if c.dtype.char in '?bBhHiIlLqQpP':
Chris@87 1054 c = c.astype(np.double)
Chris@87 1055 if not np.iterable(k):
Chris@87 1056 k = [k]
Chris@87 1057 cnt, iaxis = [int(t) for t in [m, axis]]
Chris@87 1058
Chris@87 1059 if cnt != m:
Chris@87 1060 raise ValueError("The order of integration must be integer")
Chris@87 1061 if cnt < 0:
Chris@87 1062 raise ValueError("The order of integration must be non-negative")
Chris@87 1063 if len(k) > cnt:
Chris@87 1064 raise ValueError("Too many integration constants")
Chris@87 1065 if iaxis != axis:
Chris@87 1066 raise ValueError("The axis must be integer")
Chris@87 1067 if not -c.ndim <= iaxis < c.ndim:
Chris@87 1068 raise ValueError("The axis is out of range")
Chris@87 1069 if iaxis < 0:
Chris@87 1070 iaxis += c.ndim
Chris@87 1071
Chris@87 1072 if cnt == 0:
Chris@87 1073 return c
Chris@87 1074
Chris@87 1075 c = np.rollaxis(c, iaxis)
Chris@87 1076 k = list(k) + [0]*(cnt - len(k))
Chris@87 1077 for i in range(cnt):
Chris@87 1078 n = len(c)
Chris@87 1079 c *= scl
Chris@87 1080 if n == 1 and np.all(c[0] == 0):
Chris@87 1081 c[0] += k[i]
Chris@87 1082 else:
Chris@87 1083 tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
Chris@87 1084 tmp[0] = c[0]*0
Chris@87 1085 tmp[1] = c[0]
Chris@87 1086 if n > 1:
Chris@87 1087 tmp[2] = c[1]/4
Chris@87 1088 for j in range(2, n):
Chris@87 1089 t = c[j]/(2*j + 1)
Chris@87 1090 tmp[j + 1] = c[j]/(2*(j + 1))
Chris@87 1091 tmp[j - 1] -= c[j]/(2*(j - 1))
Chris@87 1092 tmp[0] += k[i] - chebval(lbnd, tmp)
Chris@87 1093 c = tmp
Chris@87 1094 c = np.rollaxis(c, 0, iaxis + 1)
Chris@87 1095 return c
Chris@87 1096
Chris@87 1097
Chris@87 1098 def chebval(x, c, tensor=True):
Chris@87 1099 """
Chris@87 1100 Evaluate a Chebyshev series at points x.
Chris@87 1101
Chris@87 1102 If `c` is of length `n + 1`, this function returns the value:
Chris@87 1103
Chris@87 1104 .. math:: p(x) = c_0 * T_0(x) + c_1 * T_1(x) + ... + c_n * T_n(x)
Chris@87 1105
Chris@87 1106 The parameter `x` is converted to an array only if it is a tuple or a
Chris@87 1107 list, otherwise it is treated as a scalar. In either case, either `x`
Chris@87 1108 or its elements must support multiplication and addition both with
Chris@87 1109 themselves and with the elements of `c`.
Chris@87 1110
Chris@87 1111 If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
Chris@87 1112 `c` is multidimensional, then the shape of the result depends on the
Chris@87 1113 value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
Chris@87 1114 x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
Chris@87 1115 scalars have shape (,).
Chris@87 1116
Chris@87 1117 Trailing zeros in the coefficients will be used in the evaluation, so
Chris@87 1118 they should be avoided if efficiency is a concern.
Chris@87 1119
Chris@87 1120 Parameters
Chris@87 1121 ----------
Chris@87 1122 x : array_like, compatible object
Chris@87 1123 If `x` is a list or tuple, it is converted to an ndarray, otherwise
Chris@87 1124 it is left unchanged and treated as a scalar. In either case, `x`
Chris@87 1125 or its elements must support addition and multiplication with
Chris@87 1126 with themselves and with the elements of `c`.
Chris@87 1127 c : array_like
Chris@87 1128 Array of coefficients ordered so that the coefficients for terms of
Chris@87 1129 degree n are contained in c[n]. If `c` is multidimensional the
Chris@87 1130 remaining indices enumerate multiple polynomials. In the two
Chris@87 1131 dimensional case the coefficients may be thought of as stored in
Chris@87 1132 the columns of `c`.
Chris@87 1133 tensor : boolean, optional
Chris@87 1134 If True, the shape of the coefficient array is extended with ones
Chris@87 1135 on the right, one for each dimension of `x`. Scalars have dimension 0
Chris@87 1136 for this action. The result is that every column of coefficients in
Chris@87 1137 `c` is evaluated for every element of `x`. If False, `x` is broadcast
Chris@87 1138 over the columns of `c` for the evaluation. This keyword is useful
Chris@87 1139 when `c` is multidimensional. The default value is True.
Chris@87 1140
Chris@87 1141 .. versionadded:: 1.7.0
Chris@87 1142
Chris@87 1143 Returns
Chris@87 1144 -------
Chris@87 1145 values : ndarray, algebra_like
Chris@87 1146 The shape of the return value is described above.
Chris@87 1147
Chris@87 1148 See Also
Chris@87 1149 --------
Chris@87 1150 chebval2d, chebgrid2d, chebval3d, chebgrid3d
Chris@87 1151
Chris@87 1152 Notes
Chris@87 1153 -----
Chris@87 1154 The evaluation uses Clenshaw recursion, aka synthetic division.
Chris@87 1155
Chris@87 1156 Examples
Chris@87 1157 --------
Chris@87 1158
Chris@87 1159 """
Chris@87 1160 c = np.array(c, ndmin=1, copy=1)
Chris@87 1161 if c.dtype.char in '?bBhHiIlLqQpP':
Chris@87 1162 c = c.astype(np.double)
Chris@87 1163 if isinstance(x, (tuple, list)):
Chris@87 1164 x = np.asarray(x)
Chris@87 1165 if isinstance(x, np.ndarray) and tensor:
Chris@87 1166 c = c.reshape(c.shape + (1,)*x.ndim)
Chris@87 1167
Chris@87 1168 if len(c) == 1:
Chris@87 1169 c0 = c[0]
Chris@87 1170 c1 = 0
Chris@87 1171 elif len(c) == 2:
Chris@87 1172 c0 = c[0]
Chris@87 1173 c1 = c[1]
Chris@87 1174 else:
Chris@87 1175 x2 = 2*x
Chris@87 1176 c0 = c[-2]
Chris@87 1177 c1 = c[-1]
Chris@87 1178 for i in range(3, len(c) + 1):
Chris@87 1179 tmp = c0
Chris@87 1180 c0 = c[-i] - c1
Chris@87 1181 c1 = tmp + c1*x2
Chris@87 1182 return c0 + c1*x
Chris@87 1183
Chris@87 1184
Chris@87 1185 def chebval2d(x, y, c):
Chris@87 1186 """
Chris@87 1187 Evaluate a 2-D Chebyshev series at points (x, y).
Chris@87 1188
Chris@87 1189 This function returns the values:
Chris@87 1190
Chris@87 1191 .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * T_i(x) * T_j(y)
Chris@87 1192
Chris@87 1193 The parameters `x` and `y` are converted to arrays only if they are
Chris@87 1194 tuples or a lists, otherwise they are treated as a scalars and they
Chris@87 1195 must have the same shape after conversion. In either case, either `x`
Chris@87 1196 and `y` or their elements must support multiplication and addition both
Chris@87 1197 with themselves and with the elements of `c`.
Chris@87 1198
Chris@87 1199 If `c` is a 1-D array a one is implicitly appended to its shape to make
Chris@87 1200 it 2-D. The shape of the result will be c.shape[2:] + x.shape.
Chris@87 1201
Chris@87 1202 Parameters
Chris@87 1203 ----------
Chris@87 1204 x, y : array_like, compatible objects
Chris@87 1205 The two dimensional series is evaluated at the points `(x, y)`,
Chris@87 1206 where `x` and `y` must have the same shape. If `x` or `y` is a list
Chris@87 1207 or tuple, it is first converted to an ndarray, otherwise it is left
Chris@87 1208 unchanged and if it isn't an ndarray it is treated as a scalar.
Chris@87 1209 c : array_like
Chris@87 1210 Array of coefficients ordered so that the coefficient of the term
Chris@87 1211 of multi-degree i,j is contained in ``c[i,j]``. If `c` has
Chris@87 1212 dimension greater than 2 the remaining indices enumerate multiple
Chris@87 1213 sets of coefficients.
Chris@87 1214
Chris@87 1215 Returns
Chris@87 1216 -------
Chris@87 1217 values : ndarray, compatible object
Chris@87 1218 The values of the two dimensional Chebyshev series at points formed
Chris@87 1219 from pairs of corresponding values from `x` and `y`.
Chris@87 1220
Chris@87 1221 See Also
Chris@87 1222 --------
Chris@87 1223 chebval, chebgrid2d, chebval3d, chebgrid3d
Chris@87 1224
Chris@87 1225 Notes
Chris@87 1226 -----
Chris@87 1227
Chris@87 1228 .. versionadded::1.7.0
Chris@87 1229
Chris@87 1230 """
Chris@87 1231 try:
Chris@87 1232 x, y = np.array((x, y), copy=0)
Chris@87 1233 except:
Chris@87 1234 raise ValueError('x, y are incompatible')
Chris@87 1235
Chris@87 1236 c = chebval(x, c)
Chris@87 1237 c = chebval(y, c, tensor=False)
Chris@87 1238 return c
Chris@87 1239
Chris@87 1240
Chris@87 1241 def chebgrid2d(x, y, c):
Chris@87 1242 """
Chris@87 1243 Evaluate a 2-D Chebyshev series on the Cartesian product of x and y.
Chris@87 1244
Chris@87 1245 This function returns the values:
Chris@87 1246
Chris@87 1247 .. math:: p(a,b) = \sum_{i,j} c_{i,j} * T_i(a) * T_j(b),
Chris@87 1248
Chris@87 1249 where the points `(a, b)` consist of all pairs formed by taking
Chris@87 1250 `a` from `x` and `b` from `y`. The resulting points form a grid with
Chris@87 1251 `x` in the first dimension and `y` in the second.
Chris@87 1252
Chris@87 1253 The parameters `x` and `y` are converted to arrays only if they are
Chris@87 1254 tuples or a lists, otherwise they are treated as a scalars. In either
Chris@87 1255 case, either `x` and `y` or their elements must support multiplication
Chris@87 1256 and addition both with themselves and with the elements of `c`.
Chris@87 1257
Chris@87 1258 If `c` has fewer than two dimensions, ones are implicitly appended to
Chris@87 1259 its shape to make it 2-D. The shape of the result will be c.shape[2:] +
Chris@87 1260 x.shape + y.shape.
Chris@87 1261
Chris@87 1262 Parameters
Chris@87 1263 ----------
Chris@87 1264 x, y : array_like, compatible objects
Chris@87 1265 The two dimensional series is evaluated at the points in the
Chris@87 1266 Cartesian product of `x` and `y`. If `x` or `y` is a list or
Chris@87 1267 tuple, it is first converted to an ndarray, otherwise it is left
Chris@87 1268 unchanged and, if it isn't an ndarray, it is treated as a scalar.
Chris@87 1269 c : array_like
Chris@87 1270 Array of coefficients ordered so that the coefficient of the term of
Chris@87 1271 multi-degree i,j is contained in `c[i,j]`. If `c` has dimension
Chris@87 1272 greater than two the remaining indices enumerate multiple sets of
Chris@87 1273 coefficients.
Chris@87 1274
Chris@87 1275 Returns
Chris@87 1276 -------
Chris@87 1277 values : ndarray, compatible object
Chris@87 1278 The values of the two dimensional Chebyshev series at points in the
Chris@87 1279 Cartesian product of `x` and `y`.
Chris@87 1280
Chris@87 1281 See Also
Chris@87 1282 --------
Chris@87 1283 chebval, chebval2d, chebval3d, chebgrid3d
Chris@87 1284
Chris@87 1285 Notes
Chris@87 1286 -----
Chris@87 1287
Chris@87 1288 .. versionadded::1.7.0
Chris@87 1289
Chris@87 1290 """
Chris@87 1291 c = chebval(x, c)
Chris@87 1292 c = chebval(y, c)
Chris@87 1293 return c
Chris@87 1294
Chris@87 1295
Chris@87 1296 def chebval3d(x, y, z, c):
Chris@87 1297 """
Chris@87 1298 Evaluate a 3-D Chebyshev series at points (x, y, z).
Chris@87 1299
Chris@87 1300 This function returns the values:
Chris@87 1301
Chris@87 1302 .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * T_i(x) * T_j(y) * T_k(z)
Chris@87 1303
Chris@87 1304 The parameters `x`, `y`, and `z` are converted to arrays only if
Chris@87 1305 they are tuples or a lists, otherwise they are treated as a scalars and
Chris@87 1306 they must have the same shape after conversion. In either case, either
Chris@87 1307 `x`, `y`, and `z` or their elements must support multiplication and
Chris@87 1308 addition both with themselves and with the elements of `c`.
Chris@87 1309
Chris@87 1310 If `c` has fewer than 3 dimensions, ones are implicitly appended to its
Chris@87 1311 shape to make it 3-D. The shape of the result will be c.shape[3:] +
Chris@87 1312 x.shape.
Chris@87 1313
Chris@87 1314 Parameters
Chris@87 1315 ----------
Chris@87 1316 x, y, z : array_like, compatible object
Chris@87 1317 The three dimensional series is evaluated at the points
Chris@87 1318 `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
Chris@87 1319 any of `x`, `y`, or `z` is a list or tuple, it is first converted
Chris@87 1320 to an ndarray, otherwise it is left unchanged and if it isn't an
Chris@87 1321 ndarray it is treated as a scalar.
Chris@87 1322 c : array_like
Chris@87 1323 Array of coefficients ordered so that the coefficient of the term of
Chris@87 1324 multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
Chris@87 1325 greater than 3 the remaining indices enumerate multiple sets of
Chris@87 1326 coefficients.
Chris@87 1327
Chris@87 1328 Returns
Chris@87 1329 -------
Chris@87 1330 values : ndarray, compatible object
Chris@87 1331 The values of the multidimensional polynomial on points formed with
Chris@87 1332 triples of corresponding values from `x`, `y`, and `z`.
Chris@87 1333
Chris@87 1334 See Also
Chris@87 1335 --------
Chris@87 1336 chebval, chebval2d, chebgrid2d, chebgrid3d
Chris@87 1337
Chris@87 1338 Notes
Chris@87 1339 -----
Chris@87 1340
Chris@87 1341 .. versionadded::1.7.0
Chris@87 1342
Chris@87 1343 """
Chris@87 1344 try:
Chris@87 1345 x, y, z = np.array((x, y, z), copy=0)
Chris@87 1346 except:
Chris@87 1347 raise ValueError('x, y, z are incompatible')
Chris@87 1348
Chris@87 1349 c = chebval(x, c)
Chris@87 1350 c = chebval(y, c, tensor=False)
Chris@87 1351 c = chebval(z, c, tensor=False)
Chris@87 1352 return c
Chris@87 1353
Chris@87 1354
Chris@87 1355 def chebgrid3d(x, y, z, c):
Chris@87 1356 """
Chris@87 1357 Evaluate a 3-D Chebyshev series on the Cartesian product of x, y, and z.
Chris@87 1358
Chris@87 1359 This function returns the values:
Chris@87 1360
Chris@87 1361 .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * T_i(a) * T_j(b) * T_k(c)
Chris@87 1362
Chris@87 1363 where the points `(a, b, c)` consist of all triples formed by taking
Chris@87 1364 `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
Chris@87 1365 a grid with `x` in the first dimension, `y` in the second, and `z` in
Chris@87 1366 the third.
Chris@87 1367
Chris@87 1368 The parameters `x`, `y`, and `z` are converted to arrays only if they
Chris@87 1369 are tuples or a lists, otherwise they are treated as a scalars. In
Chris@87 1370 either case, either `x`, `y`, and `z` or their elements must support
Chris@87 1371 multiplication and addition both with themselves and with the elements
Chris@87 1372 of `c`.
Chris@87 1373
Chris@87 1374 If `c` has fewer than three dimensions, ones are implicitly appended to
Chris@87 1375 its shape to make it 3-D. The shape of the result will be c.shape[3:] +
Chris@87 1376 x.shape + y.shape + z.shape.
Chris@87 1377
Chris@87 1378 Parameters
Chris@87 1379 ----------
Chris@87 1380 x, y, z : array_like, compatible objects
Chris@87 1381 The three dimensional series is evaluated at the points in the
Chris@87 1382 Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
Chris@87 1383 list or tuple, it is first converted to an ndarray, otherwise it is
Chris@87 1384 left unchanged and, if it isn't an ndarray, it is treated as a
Chris@87 1385 scalar.
Chris@87 1386 c : array_like
Chris@87 1387 Array of coefficients ordered so that the coefficients for terms of
Chris@87 1388 degree i,j are contained in ``c[i,j]``. If `c` has dimension
Chris@87 1389 greater than two the remaining indices enumerate multiple sets of
Chris@87 1390 coefficients.
Chris@87 1391
Chris@87 1392 Returns
Chris@87 1393 -------
Chris@87 1394 values : ndarray, compatible object
Chris@87 1395 The values of the two dimensional polynomial at points in the Cartesian
Chris@87 1396 product of `x` and `y`.
Chris@87 1397
Chris@87 1398 See Also
Chris@87 1399 --------
Chris@87 1400 chebval, chebval2d, chebgrid2d, chebval3d
Chris@87 1401
Chris@87 1402 Notes
Chris@87 1403 -----
Chris@87 1404
Chris@87 1405 .. versionadded::1.7.0
Chris@87 1406
Chris@87 1407 """
Chris@87 1408 c = chebval(x, c)
Chris@87 1409 c = chebval(y, c)
Chris@87 1410 c = chebval(z, c)
Chris@87 1411 return c
Chris@87 1412
Chris@87 1413
Chris@87 1414 def chebvander(x, deg):
Chris@87 1415 """Pseudo-Vandermonde matrix of given degree.
Chris@87 1416
Chris@87 1417 Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
Chris@87 1418 `x`. The pseudo-Vandermonde matrix is defined by
Chris@87 1419
Chris@87 1420 .. math:: V[..., i] = T_i(x),
Chris@87 1421
Chris@87 1422 where `0 <= i <= deg`. The leading indices of `V` index the elements of
Chris@87 1423 `x` and the last index is the degree of the Chebyshev polynomial.
Chris@87 1424
Chris@87 1425 If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
Chris@87 1426 matrix ``V = chebvander(x, n)``, then ``np.dot(V, c)`` and
Chris@87 1427 ``chebval(x, c)`` are the same up to roundoff. This equivalence is
Chris@87 1428 useful both for least squares fitting and for the evaluation of a large
Chris@87 1429 number of Chebyshev series of the same degree and sample points.
Chris@87 1430
Chris@87 1431 Parameters
Chris@87 1432 ----------
Chris@87 1433 x : array_like
Chris@87 1434 Array of points. The dtype is converted to float64 or complex128
Chris@87 1435 depending on whether any of the elements are complex. If `x` is
Chris@87 1436 scalar it is converted to a 1-D array.
Chris@87 1437 deg : int
Chris@87 1438 Degree of the resulting matrix.
Chris@87 1439
Chris@87 1440 Returns
Chris@87 1441 -------
Chris@87 1442 vander : ndarray
Chris@87 1443 The pseudo Vandermonde matrix. The shape of the returned matrix is
Chris@87 1444 ``x.shape + (deg + 1,)``, where The last index is the degree of the
Chris@87 1445 corresponding Chebyshev polynomial. The dtype will be the same as
Chris@87 1446 the converted `x`.
Chris@87 1447
Chris@87 1448 """
Chris@87 1449 ideg = int(deg)
Chris@87 1450 if ideg != deg:
Chris@87 1451 raise ValueError("deg must be integer")
Chris@87 1452 if ideg < 0:
Chris@87 1453 raise ValueError("deg must be non-negative")
Chris@87 1454
Chris@87 1455 x = np.array(x, copy=0, ndmin=1) + 0.0
Chris@87 1456 dims = (ideg + 1,) + x.shape
Chris@87 1457 dtyp = x.dtype
Chris@87 1458 v = np.empty(dims, dtype=dtyp)
Chris@87 1459 # Use forward recursion to generate the entries.
Chris@87 1460 v[0] = x*0 + 1
Chris@87 1461 if ideg > 0:
Chris@87 1462 x2 = 2*x
Chris@87 1463 v[1] = x
Chris@87 1464 for i in range(2, ideg + 1):
Chris@87 1465 v[i] = v[i-1]*x2 - v[i-2]
Chris@87 1466 return np.rollaxis(v, 0, v.ndim)
Chris@87 1467
Chris@87 1468
Chris@87 1469 def chebvander2d(x, y, deg):
Chris@87 1470 """Pseudo-Vandermonde matrix of given degrees.
Chris@87 1471
Chris@87 1472 Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
Chris@87 1473 points `(x, y)`. The pseudo-Vandermonde matrix is defined by
Chris@87 1474
Chris@87 1475 .. math:: V[..., deg[1]*i + j] = T_i(x) * T_j(y),
Chris@87 1476
Chris@87 1477 where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
Chris@87 1478 `V` index the points `(x, y)` and the last index encodes the degrees of
Chris@87 1479 the Chebyshev polynomials.
Chris@87 1480
Chris@87 1481 If ``V = chebvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
Chris@87 1482 correspond to the elements of a 2-D coefficient array `c` of shape
Chris@87 1483 (xdeg + 1, ydeg + 1) in the order
Chris@87 1484
Chris@87 1485 .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
Chris@87 1486
Chris@87 1487 and ``np.dot(V, c.flat)`` and ``chebval2d(x, y, c)`` will be the same
Chris@87 1488 up to roundoff. This equivalence is useful both for least squares
Chris@87 1489 fitting and for the evaluation of a large number of 2-D Chebyshev
Chris@87 1490 series of the same degrees and sample points.
Chris@87 1491
Chris@87 1492 Parameters
Chris@87 1493 ----------
Chris@87 1494 x, y : array_like
Chris@87 1495 Arrays of point coordinates, all of the same shape. The dtypes
Chris@87 1496 will be converted to either float64 or complex128 depending on
Chris@87 1497 whether any of the elements are complex. Scalars are converted to
Chris@87 1498 1-D arrays.
Chris@87 1499 deg : list of ints
Chris@87 1500 List of maximum degrees of the form [x_deg, y_deg].
Chris@87 1501
Chris@87 1502 Returns
Chris@87 1503 -------
Chris@87 1504 vander2d : ndarray
Chris@87 1505 The shape of the returned matrix is ``x.shape + (order,)``, where
Chris@87 1506 :math:`order = (deg[0]+1)*(deg([1]+1)`. The dtype will be the same
Chris@87 1507 as the converted `x` and `y`.
Chris@87 1508
Chris@87 1509 See Also
Chris@87 1510 --------
Chris@87 1511 chebvander, chebvander3d. chebval2d, chebval3d
Chris@87 1512
Chris@87 1513 Notes
Chris@87 1514 -----
Chris@87 1515
Chris@87 1516 .. versionadded::1.7.0
Chris@87 1517
Chris@87 1518 """
Chris@87 1519 ideg = [int(d) for d in deg]
Chris@87 1520 is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
Chris@87 1521 if is_valid != [1, 1]:
Chris@87 1522 raise ValueError("degrees must be non-negative integers")
Chris@87 1523 degx, degy = ideg
Chris@87 1524 x, y = np.array((x, y), copy=0) + 0.0
Chris@87 1525
Chris@87 1526 vx = chebvander(x, degx)
Chris@87 1527 vy = chebvander(y, degy)
Chris@87 1528 v = vx[..., None]*vy[..., None,:]
Chris@87 1529 return v.reshape(v.shape[:-2] + (-1,))
Chris@87 1530
Chris@87 1531
Chris@87 1532 def chebvander3d(x, y, z, deg):
Chris@87 1533 """Pseudo-Vandermonde matrix of given degrees.
Chris@87 1534
Chris@87 1535 Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
Chris@87 1536 points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
Chris@87 1537 then The pseudo-Vandermonde matrix is defined by
Chris@87 1538
Chris@87 1539 .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = T_i(x)*T_j(y)*T_k(z),
Chris@87 1540
Chris@87 1541 where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
Chris@87 1542 indices of `V` index the points `(x, y, z)` and the last index encodes
Chris@87 1543 the degrees of the Chebyshev polynomials.
Chris@87 1544
Chris@87 1545 If ``V = chebvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
Chris@87 1546 of `V` correspond to the elements of a 3-D coefficient array `c` of
Chris@87 1547 shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
Chris@87 1548
Chris@87 1549 .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
Chris@87 1550
Chris@87 1551 and ``np.dot(V, c.flat)`` and ``chebval3d(x, y, z, c)`` will be the
Chris@87 1552 same up to roundoff. This equivalence is useful both for least squares
Chris@87 1553 fitting and for the evaluation of a large number of 3-D Chebyshev
Chris@87 1554 series of the same degrees and sample points.
Chris@87 1555
Chris@87 1556 Parameters
Chris@87 1557 ----------
Chris@87 1558 x, y, z : array_like
Chris@87 1559 Arrays of point coordinates, all of the same shape. The dtypes will
Chris@87 1560 be converted to either float64 or complex128 depending on whether
Chris@87 1561 any of the elements are complex. Scalars are converted to 1-D
Chris@87 1562 arrays.
Chris@87 1563 deg : list of ints
Chris@87 1564 List of maximum degrees of the form [x_deg, y_deg, z_deg].
Chris@87 1565
Chris@87 1566 Returns
Chris@87 1567 -------
Chris@87 1568 vander3d : ndarray
Chris@87 1569 The shape of the returned matrix is ``x.shape + (order,)``, where
Chris@87 1570 :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`. The dtype will
Chris@87 1571 be the same as the converted `x`, `y`, and `z`.
Chris@87 1572
Chris@87 1573 See Also
Chris@87 1574 --------
Chris@87 1575 chebvander, chebvander3d. chebval2d, chebval3d
Chris@87 1576
Chris@87 1577 Notes
Chris@87 1578 -----
Chris@87 1579
Chris@87 1580 .. versionadded::1.7.0
Chris@87 1581
Chris@87 1582 """
Chris@87 1583 ideg = [int(d) for d in deg]
Chris@87 1584 is_valid = [id == d and id >= 0 for id, d in zip(ideg, deg)]
Chris@87 1585 if is_valid != [1, 1, 1]:
Chris@87 1586 raise ValueError("degrees must be non-negative integers")
Chris@87 1587 degx, degy, degz = ideg
Chris@87 1588 x, y, z = np.array((x, y, z), copy=0) + 0.0
Chris@87 1589
Chris@87 1590 vx = chebvander(x, degx)
Chris@87 1591 vy = chebvander(y, degy)
Chris@87 1592 vz = chebvander(z, degz)
Chris@87 1593 v = vx[..., None, None]*vy[..., None,:, None]*vz[..., None, None,:]
Chris@87 1594 return v.reshape(v.shape[:-3] + (-1,))
Chris@87 1595
Chris@87 1596
Chris@87 1597 def chebfit(x, y, deg, rcond=None, full=False, w=None):
Chris@87 1598 """
Chris@87 1599 Least squares fit of Chebyshev series to data.
Chris@87 1600
Chris@87 1601 Return the coefficients of a Legendre series of degree `deg` that is the
Chris@87 1602 least squares fit to the data values `y` given at points `x`. If `y` is
Chris@87 1603 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
Chris@87 1604 fits are done, one for each column of `y`, and the resulting
Chris@87 1605 coefficients are stored in the corresponding columns of a 2-D return.
Chris@87 1606 The fitted polynomial(s) are in the form
Chris@87 1607
Chris@87 1608 .. math:: p(x) = c_0 + c_1 * T_1(x) + ... + c_n * T_n(x),
Chris@87 1609
Chris@87 1610 where `n` is `deg`.
Chris@87 1611
Chris@87 1612 Parameters
Chris@87 1613 ----------
Chris@87 1614 x : array_like, shape (M,)
Chris@87 1615 x-coordinates of the M sample points ``(x[i], y[i])``.
Chris@87 1616 y : array_like, shape (M,) or (M, K)
Chris@87 1617 y-coordinates of the sample points. Several data sets of sample
Chris@87 1618 points sharing the same x-coordinates can be fitted at once by
Chris@87 1619 passing in a 2D-array that contains one dataset per column.
Chris@87 1620 deg : int
Chris@87 1621 Degree of the fitting series
Chris@87 1622 rcond : float, optional
Chris@87 1623 Relative condition number of the fit. Singular values smaller than
Chris@87 1624 this relative to the largest singular value will be ignored. The
Chris@87 1625 default value is len(x)*eps, where eps is the relative precision of
Chris@87 1626 the float type, about 2e-16 in most cases.
Chris@87 1627 full : bool, optional
Chris@87 1628 Switch determining nature of return value. When it is False (the
Chris@87 1629 default) just the coefficients are returned, when True diagnostic
Chris@87 1630 information from the singular value decomposition is also returned.
Chris@87 1631 w : array_like, shape (`M`,), optional
Chris@87 1632 Weights. If not None, the contribution of each point
Chris@87 1633 ``(x[i],y[i])`` to the fit is weighted by `w[i]`. Ideally the
Chris@87 1634 weights are chosen so that the errors of the products ``w[i]*y[i]``
Chris@87 1635 all have the same variance. The default value is None.
Chris@87 1636
Chris@87 1637 .. versionadded:: 1.5.0
Chris@87 1638
Chris@87 1639 Returns
Chris@87 1640 -------
Chris@87 1641 coef : ndarray, shape (M,) or (M, K)
Chris@87 1642 Chebyshev coefficients ordered from low to high. If `y` was 2-D,
Chris@87 1643 the coefficients for the data in column k of `y` are in column
Chris@87 1644 `k`.
Chris@87 1645
Chris@87 1646 [residuals, rank, singular_values, rcond] : list
Chris@87 1647 These values are only returned if `full` = True
Chris@87 1648
Chris@87 1649 resid -- sum of squared residuals of the least squares fit
Chris@87 1650 rank -- the numerical rank of the scaled Vandermonde matrix
Chris@87 1651 sv -- singular values of the scaled Vandermonde matrix
Chris@87 1652 rcond -- value of `rcond`.
Chris@87 1653
Chris@87 1654 For more details, see `linalg.lstsq`.
Chris@87 1655
Chris@87 1656 Warns
Chris@87 1657 -----
Chris@87 1658 RankWarning
Chris@87 1659 The rank of the coefficient matrix in the least-squares fit is
Chris@87 1660 deficient. The warning is only raised if `full` = False. The
Chris@87 1661 warnings can be turned off by
Chris@87 1662
Chris@87 1663 >>> import warnings
Chris@87 1664 >>> warnings.simplefilter('ignore', RankWarning)
Chris@87 1665
Chris@87 1666 See Also
Chris@87 1667 --------
Chris@87 1668 polyfit, legfit, lagfit, hermfit, hermefit
Chris@87 1669 chebval : Evaluates a Chebyshev series.
Chris@87 1670 chebvander : Vandermonde matrix of Chebyshev series.
Chris@87 1671 chebweight : Chebyshev weight function.
Chris@87 1672 linalg.lstsq : Computes a least-squares fit from the matrix.
Chris@87 1673 scipy.interpolate.UnivariateSpline : Computes spline fits.
Chris@87 1674
Chris@87 1675 Notes
Chris@87 1676 -----
Chris@87 1677 The solution is the coefficients of the Chebyshev series `p` that
Chris@87 1678 minimizes the sum of the weighted squared errors
Chris@87 1679
Chris@87 1680 .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
Chris@87 1681
Chris@87 1682 where :math:`w_j` are the weights. This problem is solved by setting up
Chris@87 1683 as the (typically) overdetermined matrix equation
Chris@87 1684
Chris@87 1685 .. math:: V(x) * c = w * y,
Chris@87 1686
Chris@87 1687 where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
Chris@87 1688 coefficients to be solved for, `w` are the weights, and `y` are the
Chris@87 1689 observed values. This equation is then solved using the singular value
Chris@87 1690 decomposition of `V`.
Chris@87 1691
Chris@87 1692 If some of the singular values of `V` are so small that they are
Chris@87 1693 neglected, then a `RankWarning` will be issued. This means that the
Chris@87 1694 coefficient values may be poorly determined. Using a lower order fit
Chris@87 1695 will usually get rid of the warning. The `rcond` parameter can also be
Chris@87 1696 set to a value smaller than its default, but the resulting fit may be
Chris@87 1697 spurious and have large contributions from roundoff error.
Chris@87 1698
Chris@87 1699 Fits using Chebyshev series are usually better conditioned than fits
Chris@87 1700 using power series, but much can depend on the distribution of the
Chris@87 1701 sample points and the smoothness of the data. If the quality of the fit
Chris@87 1702 is inadequate splines may be a good alternative.
Chris@87 1703
Chris@87 1704 References
Chris@87 1705 ----------
Chris@87 1706 .. [1] Wikipedia, "Curve fitting",
Chris@87 1707 http://en.wikipedia.org/wiki/Curve_fitting
Chris@87 1708
Chris@87 1709 Examples
Chris@87 1710 --------
Chris@87 1711
Chris@87 1712 """
Chris@87 1713 order = int(deg) + 1
Chris@87 1714 x = np.asarray(x) + 0.0
Chris@87 1715 y = np.asarray(y) + 0.0
Chris@87 1716
Chris@87 1717 # check arguments.
Chris@87 1718 if deg < 0:
Chris@87 1719 raise ValueError("expected deg >= 0")
Chris@87 1720 if x.ndim != 1:
Chris@87 1721 raise TypeError("expected 1D vector for x")
Chris@87 1722 if x.size == 0:
Chris@87 1723 raise TypeError("expected non-empty vector for x")
Chris@87 1724 if y.ndim < 1 or y.ndim > 2:
Chris@87 1725 raise TypeError("expected 1D or 2D array for y")
Chris@87 1726 if len(x) != len(y):
Chris@87 1727 raise TypeError("expected x and y to have same length")
Chris@87 1728
Chris@87 1729 # set up the least squares matrices in transposed form
Chris@87 1730 lhs = chebvander(x, deg).T
Chris@87 1731 rhs = y.T
Chris@87 1732 if w is not None:
Chris@87 1733 w = np.asarray(w) + 0.0
Chris@87 1734 if w.ndim != 1:
Chris@87 1735 raise TypeError("expected 1D vector for w")
Chris@87 1736 if len(x) != len(w):
Chris@87 1737 raise TypeError("expected x and w to have same length")
Chris@87 1738 # apply weights. Don't use inplace operations as they
Chris@87 1739 # can cause problems with NA.
Chris@87 1740 lhs = lhs * w
Chris@87 1741 rhs = rhs * w
Chris@87 1742
Chris@87 1743 # set rcond
Chris@87 1744 if rcond is None:
Chris@87 1745 rcond = len(x)*np.finfo(x.dtype).eps
Chris@87 1746
Chris@87 1747 # Determine the norms of the design matrix columns.
Chris@87 1748 if issubclass(lhs.dtype.type, np.complexfloating):
Chris@87 1749 scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
Chris@87 1750 else:
Chris@87 1751 scl = np.sqrt(np.square(lhs).sum(1))
Chris@87 1752 scl[scl == 0] = 1
Chris@87 1753
Chris@87 1754 # Solve the least squares problem.
Chris@87 1755 c, resids, rank, s = la.lstsq(lhs.T/scl, rhs.T, rcond)
Chris@87 1756 c = (c.T/scl).T
Chris@87 1757
Chris@87 1758 # warn on rank reduction
Chris@87 1759 if rank != order and not full:
Chris@87 1760 msg = "The fit may be poorly conditioned"
Chris@87 1761 warnings.warn(msg, pu.RankWarning)
Chris@87 1762
Chris@87 1763 if full:
Chris@87 1764 return c, [resids, rank, s, rcond]
Chris@87 1765 else:
Chris@87 1766 return c
Chris@87 1767
Chris@87 1768
Chris@87 1769 def chebcompanion(c):
Chris@87 1770 """Return the scaled companion matrix of c.
Chris@87 1771
Chris@87 1772 The basis polynomials are scaled so that the companion matrix is
Chris@87 1773 symmetric when `c` is aa Chebyshev basis polynomial. This provides
Chris@87 1774 better eigenvalue estimates than the unscaled case and for basis
Chris@87 1775 polynomials the eigenvalues are guaranteed to be real if
Chris@87 1776 `numpy.linalg.eigvalsh` is used to obtain them.
Chris@87 1777
Chris@87 1778 Parameters
Chris@87 1779 ----------
Chris@87 1780 c : array_like
Chris@87 1781 1-D array of Chebyshev series coefficients ordered from low to high
Chris@87 1782 degree.
Chris@87 1783
Chris@87 1784 Returns
Chris@87 1785 -------
Chris@87 1786 mat : ndarray
Chris@87 1787 Scaled companion matrix of dimensions (deg, deg).
Chris@87 1788
Chris@87 1789 Notes
Chris@87 1790 -----
Chris@87 1791
Chris@87 1792 .. versionadded::1.7.0
Chris@87 1793
Chris@87 1794 """
Chris@87 1795 # c is a trimmed copy
Chris@87 1796 [c] = pu.as_series([c])
Chris@87 1797 if len(c) < 2:
Chris@87 1798 raise ValueError('Series must have maximum degree of at least 1.')
Chris@87 1799 if len(c) == 2:
Chris@87 1800 return np.array([[-c[0]/c[1]]])
Chris@87 1801
Chris@87 1802 n = len(c) - 1
Chris@87 1803 mat = np.zeros((n, n), dtype=c.dtype)
Chris@87 1804 scl = np.array([1.] + [np.sqrt(.5)]*(n-1))
Chris@87 1805 top = mat.reshape(-1)[1::n+1]
Chris@87 1806 bot = mat.reshape(-1)[n::n+1]
Chris@87 1807 top[0] = np.sqrt(.5)
Chris@87 1808 top[1:] = 1/2
Chris@87 1809 bot[...] = top
Chris@87 1810 mat[:, -1] -= (c[:-1]/c[-1])*(scl/scl[-1])*.5
Chris@87 1811 return mat
Chris@87 1812
Chris@87 1813
Chris@87 1814 def chebroots(c):
Chris@87 1815 """
Chris@87 1816 Compute the roots of a Chebyshev series.
Chris@87 1817
Chris@87 1818 Return the roots (a.k.a. "zeros") of the polynomial
Chris@87 1819
Chris@87 1820 .. math:: p(x) = \\sum_i c[i] * T_i(x).
Chris@87 1821
Chris@87 1822 Parameters
Chris@87 1823 ----------
Chris@87 1824 c : 1-D array_like
Chris@87 1825 1-D array of coefficients.
Chris@87 1826
Chris@87 1827 Returns
Chris@87 1828 -------
Chris@87 1829 out : ndarray
Chris@87 1830 Array of the roots of the series. If all the roots are real,
Chris@87 1831 then `out` is also real, otherwise it is complex.
Chris@87 1832
Chris@87 1833 See Also
Chris@87 1834 --------
Chris@87 1835 polyroots, legroots, lagroots, hermroots, hermeroots
Chris@87 1836
Chris@87 1837 Notes
Chris@87 1838 -----
Chris@87 1839 The root estimates are obtained as the eigenvalues of the companion
Chris@87 1840 matrix, Roots far from the origin of the complex plane may have large
Chris@87 1841 errors due to the numerical instability of the series for such
Chris@87 1842 values. Roots with multiplicity greater than 1 will also show larger
Chris@87 1843 errors as the value of the series near such points is relatively
Chris@87 1844 insensitive to errors in the roots. Isolated roots near the origin can
Chris@87 1845 be improved by a few iterations of Newton's method.
Chris@87 1846
Chris@87 1847 The Chebyshev series basis polynomials aren't powers of `x` so the
Chris@87 1848 results of this function may seem unintuitive.
Chris@87 1849
Chris@87 1850 Examples
Chris@87 1851 --------
Chris@87 1852 >>> import numpy.polynomial.chebyshev as cheb
Chris@87 1853 >>> cheb.chebroots((-1, 1,-1, 1)) # T3 - T2 + T1 - T0 has real roots
Chris@87 1854 array([ -5.00000000e-01, 2.60860684e-17, 1.00000000e+00])
Chris@87 1855
Chris@87 1856 """
Chris@87 1857 # c is a trimmed copy
Chris@87 1858 [c] = pu.as_series([c])
Chris@87 1859 if len(c) < 2:
Chris@87 1860 return np.array([], dtype=c.dtype)
Chris@87 1861 if len(c) == 2:
Chris@87 1862 return np.array([-c[0]/c[1]])
Chris@87 1863
Chris@87 1864 m = chebcompanion(c)
Chris@87 1865 r = la.eigvals(m)
Chris@87 1866 r.sort()
Chris@87 1867 return r
Chris@87 1868
Chris@87 1869
Chris@87 1870 def chebgauss(deg):
Chris@87 1871 """
Chris@87 1872 Gauss-Chebyshev quadrature.
Chris@87 1873
Chris@87 1874 Computes the sample points and weights for Gauss-Chebyshev quadrature.
Chris@87 1875 These sample points and weights will correctly integrate polynomials of
Chris@87 1876 degree :math:`2*deg - 1` or less over the interval :math:`[-1, 1]` with
Chris@87 1877 the weight function :math:`f(x) = 1/\sqrt{1 - x^2}`.
Chris@87 1878
Chris@87 1879 Parameters
Chris@87 1880 ----------
Chris@87 1881 deg : int
Chris@87 1882 Number of sample points and weights. It must be >= 1.
Chris@87 1883
Chris@87 1884 Returns
Chris@87 1885 -------
Chris@87 1886 x : ndarray
Chris@87 1887 1-D ndarray containing the sample points.
Chris@87 1888 y : ndarray
Chris@87 1889 1-D ndarray containing the weights.
Chris@87 1890
Chris@87 1891 Notes
Chris@87 1892 -----
Chris@87 1893
Chris@87 1894 .. versionadded:: 1.7.0
Chris@87 1895
Chris@87 1896 The results have only been tested up to degree 100, higher degrees may
Chris@87 1897 be problematic. For Gauss-Chebyshev there are closed form solutions for
Chris@87 1898 the sample points and weights. If n = `deg`, then
Chris@87 1899
Chris@87 1900 .. math:: x_i = \cos(\pi (2 i - 1) / (2 n))
Chris@87 1901
Chris@87 1902 .. math:: w_i = \pi / n
Chris@87 1903
Chris@87 1904 """
Chris@87 1905 ideg = int(deg)
Chris@87 1906 if ideg != deg or ideg < 1:
Chris@87 1907 raise ValueError("deg must be a non-negative integer")
Chris@87 1908
Chris@87 1909 x = np.cos(np.pi * np.arange(1, 2*ideg, 2) / (2.0*ideg))
Chris@87 1910 w = np.ones(ideg)*(np.pi/ideg)
Chris@87 1911
Chris@87 1912 return x, w
Chris@87 1913
Chris@87 1914
Chris@87 1915 def chebweight(x):
Chris@87 1916 """
Chris@87 1917 The weight function of the Chebyshev polynomials.
Chris@87 1918
Chris@87 1919 The weight function is :math:`1/\sqrt{1 - x^2}` and the interval of
Chris@87 1920 integration is :math:`[-1, 1]`. The Chebyshev polynomials are
Chris@87 1921 orthogonal, but not normalized, with respect to this weight function.
Chris@87 1922
Chris@87 1923 Parameters
Chris@87 1924 ----------
Chris@87 1925 x : array_like
Chris@87 1926 Values at which the weight function will be computed.
Chris@87 1927
Chris@87 1928 Returns
Chris@87 1929 -------
Chris@87 1930 w : ndarray
Chris@87 1931 The weight function at `x`.
Chris@87 1932
Chris@87 1933 Notes
Chris@87 1934 -----
Chris@87 1935
Chris@87 1936 .. versionadded:: 1.7.0
Chris@87 1937
Chris@87 1938 """
Chris@87 1939 w = 1./(np.sqrt(1. + x) * np.sqrt(1. - x))
Chris@87 1940 return w
Chris@87 1941
Chris@87 1942
Chris@87 1943 def chebpts1(npts):
Chris@87 1944 """
Chris@87 1945 Chebyshev points of the first kind.
Chris@87 1946
Chris@87 1947 The Chebyshev points of the first kind are the points ``cos(x)``,
Chris@87 1948 where ``x = [pi*(k + .5)/npts for k in range(npts)]``.
Chris@87 1949
Chris@87 1950 Parameters
Chris@87 1951 ----------
Chris@87 1952 npts : int
Chris@87 1953 Number of sample points desired.
Chris@87 1954
Chris@87 1955 Returns
Chris@87 1956 -------
Chris@87 1957 pts : ndarray
Chris@87 1958 The Chebyshev points of the first kind.
Chris@87 1959
Chris@87 1960 See Also
Chris@87 1961 --------
Chris@87 1962 chebpts2
Chris@87 1963
Chris@87 1964 Notes
Chris@87 1965 -----
Chris@87 1966
Chris@87 1967 .. versionadded:: 1.5.0
Chris@87 1968
Chris@87 1969 """
Chris@87 1970 _npts = int(npts)
Chris@87 1971 if _npts != npts:
Chris@87 1972 raise ValueError("npts must be integer")
Chris@87 1973 if _npts < 1:
Chris@87 1974 raise ValueError("npts must be >= 1")
Chris@87 1975
Chris@87 1976 x = np.linspace(-np.pi, 0, _npts, endpoint=False) + np.pi/(2*_npts)
Chris@87 1977 return np.cos(x)
Chris@87 1978
Chris@87 1979
Chris@87 1980 def chebpts2(npts):
Chris@87 1981 """
Chris@87 1982 Chebyshev points of the second kind.
Chris@87 1983
Chris@87 1984 The Chebyshev points of the second kind are the points ``cos(x)``,
Chris@87 1985 where ``x = [pi*k/(npts - 1) for k in range(npts)]``.
Chris@87 1986
Chris@87 1987 Parameters
Chris@87 1988 ----------
Chris@87 1989 npts : int
Chris@87 1990 Number of sample points desired.
Chris@87 1991
Chris@87 1992 Returns
Chris@87 1993 -------
Chris@87 1994 pts : ndarray
Chris@87 1995 The Chebyshev points of the second kind.
Chris@87 1996
Chris@87 1997 Notes
Chris@87 1998 -----
Chris@87 1999
Chris@87 2000 .. versionadded:: 1.5.0
Chris@87 2001
Chris@87 2002 """
Chris@87 2003 _npts = int(npts)
Chris@87 2004 if _npts != npts:
Chris@87 2005 raise ValueError("npts must be integer")
Chris@87 2006 if _npts < 2:
Chris@87 2007 raise ValueError("npts must be >= 2")
Chris@87 2008
Chris@87 2009 x = np.linspace(-np.pi, 0, _npts)
Chris@87 2010 return np.cos(x)
Chris@87 2011
Chris@87 2012
Chris@87 2013 #
Chris@87 2014 # Chebyshev series class
Chris@87 2015 #
Chris@87 2016
Chris@87 2017 class Chebyshev(ABCPolyBase):
Chris@87 2018 """A Chebyshev series class.
Chris@87 2019
Chris@87 2020 The Chebyshev class provides the standard Python numerical methods
Chris@87 2021 '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
Chris@87 2022 methods listed below.
Chris@87 2023
Chris@87 2024 Parameters
Chris@87 2025 ----------
Chris@87 2026 coef : array_like
Chris@87 2027 Chebyshev coefficients in order of increasing degree, i.e.,
Chris@87 2028 ``(1, 2, 3)`` gives ``1*T_0(x) + 2*T_1(x) + 3*T_2(x)``.
Chris@87 2029 domain : (2,) array_like, optional
Chris@87 2030 Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
Chris@87 2031 to the interval ``[window[0], window[1]]`` by shifting and scaling.
Chris@87 2032 The default value is [-1, 1].
Chris@87 2033 window : (2,) array_like, optional
Chris@87 2034 Window, see `domain` for its use. The default value is [-1, 1].
Chris@87 2035
Chris@87 2036 .. versionadded:: 1.6.0
Chris@87 2037
Chris@87 2038 """
Chris@87 2039 # Virtual Functions
Chris@87 2040 _add = staticmethod(chebadd)
Chris@87 2041 _sub = staticmethod(chebsub)
Chris@87 2042 _mul = staticmethod(chebmul)
Chris@87 2043 _div = staticmethod(chebdiv)
Chris@87 2044 _pow = staticmethod(chebpow)
Chris@87 2045 _val = staticmethod(chebval)
Chris@87 2046 _int = staticmethod(chebint)
Chris@87 2047 _der = staticmethod(chebder)
Chris@87 2048 _fit = staticmethod(chebfit)
Chris@87 2049 _line = staticmethod(chebline)
Chris@87 2050 _roots = staticmethod(chebroots)
Chris@87 2051 _fromroots = staticmethod(chebfromroots)
Chris@87 2052
Chris@87 2053 # Virtual properties
Chris@87 2054 nickname = 'cheb'
Chris@87 2055 domain = np.array(chebdomain)
Chris@87 2056 window = np.array(chebdomain)