summaryrefslogtreecommitdiff
path: root/numpy/polynomial
diff options
context:
space:
mode:
authorJarrod Millman <millman@berkeley.edu>2010-02-17 23:53:04 +0000
committerJarrod Millman <millman@berkeley.edu>2010-02-17 23:53:04 +0000
commite2bb09430d90c73a7be6e47ea8c4528f094f693f (patch)
tree3ded297a6cbe634446d6a54afc4e95c8c71553e6 /numpy/polynomial
parentdcc721a5bddde3afd4ce47d7a7b76ec6c7102b92 (diff)
downloadnumpy-e2bb09430d90c73a7be6e47ea8c4528f094f693f.tar.gz
more docstring updates from pydoc website (thanks to everyone who contributed!)
Diffstat (limited to 'numpy/polynomial')
-rw-r--r--numpy/polynomial/__init__.py15
-rw-r--r--numpy/polynomial/chebyshev.py500
-rw-r--r--numpy/polynomial/polynomial.py512
-rw-r--r--numpy/polynomial/polytemplate.py10
-rw-r--r--numpy/polynomial/polyutils.py237
5 files changed, 900 insertions, 374 deletions
diff --git a/numpy/polynomial/__init__.py b/numpy/polynomial/__init__.py
index 6aedbef47..7e755ca52 100644
--- a/numpy/polynomial/__init__.py
+++ b/numpy/polynomial/__init__.py
@@ -1,3 +1,18 @@
+"""
+A sub-package for efficiently dealing with polynomials.
+
+Within the documentation for this sub-package, a "finite power series,"
+i.e., a polynomial (also referred to simply as a "series") is represented
+by a 1-D numpy array of the polynomial's coefficients, ordered from lowest
+order term to highest. For example, array([1,2,3]) represents
+``P_0 + 2*P_1 + 3*P_2``, where P_n is the n-th order basis polynomial
+applicable to the specific module in question, e.g., `polynomial` (which
+"wraps" the "standard" basis) or `chebyshev`. For optimal performance,
+all operations on polynomials, including evaluation at an argument, are
+implemented as operations on the coefficients. Additional (module-specific)
+information can be found in the docstring for the module of interest.
+
+"""
from polynomial import *
from chebyshev import *
from polyutils import *
diff --git a/numpy/polynomial/chebyshev.py b/numpy/polynomial/chebyshev.py
index e25ed8a6f..662f664a9 100644
--- a/numpy/polynomial/chebyshev.py
+++ b/numpy/polynomial/chebyshev.py
@@ -1,50 +1,58 @@
-"""Functions for dealing with Chebyshev series.
+"""
+Objects for dealing with Chebyshev series.
-This module provide s a number of functions that are useful in dealing with
-Chebyshev series as well as a ``Chebyshev`` class that encapsuletes the usual
-arithmetic operations. All the Chebyshev series are assumed to be ordered
-from low to high, thus ``array([1,2,3])`` will be treated as the series
-``T_0 + 2*T_1 + 3*T_2``
+This module provides a number of objects (mostly functions) useful for
+dealing with Chebyshev series, including a `Chebyshev` class that
+encapsulates the usual arithmetic operations. (General information
+on how this module represents and works with such polynomials is in the
+docstring for its "parent" sub-package, `numpy.polynomial`).
Constants
---------
-- chebdomain -- Chebyshev series default domain
-- chebzero -- Chebyshev series that evaluates to 0.
-- chebone -- Chebyshev series that evaluates to 1.
-- chebx -- Chebyshev series of the identity map (x).
+- `chebdomain` -- Chebyshev series default domain, [-1,1].
+- `chebzero` -- (Coefficients of the) Chebyshev series that evaluates
+ identically to 0.
+- `chebone` -- (Coefficients of the) Chebyshev series that evaluates
+ identically to 1.
+- `chebx` -- (Coefficients of the) Chebyshev series for the identity map,
+ ``f(x) = x``.
Arithmetic
----------
-- chebadd -- add a Chebyshev series to another.
-- chebsub -- subtract a Chebyshev series from another.
-- chebmul -- multiply a Chebyshev series by another
-- chebdiv -- divide one Chebyshev series by another.
-- chebval -- evaluate a Chebyshev series at given points.
+- `chebadd` -- add two Chebyshev series.
+- `chebsub` -- subtract one Chebyshev series from another.
+- `chebmul` -- multiply two Chebyshev series.
+- `chebdiv` -- divide one Chebyshev series by another.
+- `chebval` -- evaluate a Chebyshev series at given points.
Calculus
--------
-- chebder -- differentiate a Chebyshev series.
-- chebint -- integrate a Chebyshev series.
+- `chebder` -- differentiate a Chebyshev series.
+- `chebint` -- integrate a Chebyshev series.
Misc Functions
--------------
-- chebfromroots -- create a Chebyshev series with specified roots.
-- chebroots -- find the roots of a Chebyshev series.
-- chebvander -- Vandermode like matrix for Chebyshev polynomials.
-- chebfit -- least squares fit returning a Chebyshev series.
-- chebtrim -- trim leading coefficients from a Chebyshev series.
-- chebline -- Chebyshev series of given straight line
-- cheb2poly -- convert a Chebyshev series to a polynomial.
-- poly2cheb -- convert a polynomial to a Chebyshev series.
+- `chebfromroots` -- create a Chebyshev series with specified roots.
+- `chebroots` -- find the roots of a Chebyshev series.
+- `chebvander` -- Vandermonde-like matrix for Chebyshev polynomials.
+- `chebfit` -- least-squares fit returning a Chebyshev series.
+- `chebtrim` -- trim leading coefficients from a Chebyshev series.
+- `chebline` -- Chebyshev series of given straight line.
+- `cheb2poly` -- convert a Chebyshev series to a polynomial.
+- `poly2cheb` -- convert a polynomial to a Chebyshev series.
Classes
-------
-- Chebyshev -- Chebyshev series class.
+- `Chebyshev` -- A Chebyshev series class.
+
+See also
+--------
+`numpy.polynomial`
Notes
-----
The implementations of multiplication, division, integration, and
-differentiation use the algebraic identities:
+differentiation use the algebraic identities [1]_:
.. math ::
T_n(x) = \\frac{z^n + z^{-n}}{2} \\\\
@@ -55,8 +63,14 @@ where
.. math :: x = \\frac{z + z^{-1}}{2}.
These identities allow a Chebyshev series to be expressed as a finite,
-symmetric Laurent series. These sorts of Laurent series are referred to as
-z-series in this module.
+symmetric Laurent series. In this module, this sort of Laurent series
+is referred to as a "z-series."
+
+References
+----------
+.. [1] A. T. Benjamin, et al., "Combinatorial Trigonometry with Chebyshev
+ Polynomials," *Journal of Statistical Planning and Inference 14*, 2008
+ (preprint: http://www.math.hmc.edu/~benjamin/papers/CombTrig.pdf, pg. 4)
"""
from __future__ import division
@@ -289,20 +303,24 @@ def _zseries_int(zs) :
def poly2cheb(pol) :
- """Convert a polynomial to a Chebyshev series.
+ """
+ poly2cheb(pol)
- Convert a series containing polynomial coefficients ordered by degree
- from low to high to an equivalent Chebyshev series ordered from low to
- high.
+ Convert a polynomial to a Chebyshev series.
- Inputs
- ------
+ Convert an array representing the coefficients of a polynomial (relative
+ to the "standard" basis) ordered from lowest degree to highest, to an
+ array of the coefficients of the equivalent Chebyshev series, ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
pol : array_like
- 1-d array containing the polynomial coeffients
+ 1-d array containing the polynomial coefficients
Returns
-------
- cseries : ndarray
+ cs : ndarray
1-d array containing the coefficients of the equivalent Chebyshev
series.
@@ -310,6 +328,23 @@ def poly2cheb(pol) :
--------
cheb2poly
+ Notes
+ -----
+ Note that a consequence of the input needing to be array_like and that
+ the output is an ndarray, is that if one is going to use this function
+ to convert a Polynomial instance, P, to a Chebyshev instance, T, the
+ usage is ``T = Chebyshev(poly2cheb(P.coef))``; see Examples below.
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> p = P.Polynomial(np.arange(4))
+ >>> p
+ Polynomial([ 0., 1., 2., 3.], [-1., 1.])
+ >>> c = P.Chebyshev(P.poly2cheb(p.coef))
+ >>> c
+ Chebyshev([ 1. , 3.25, 1. , 0.75], [-1., 1.])
+
"""
[pol] = pu.as_series([pol])
pol = pol[::-1]
@@ -322,28 +357,50 @@ def poly2cheb(pol) :
def cheb2poly(cs) :
- """Convert a Chebyshev series to a polynomial.
+ """
+ cheb2poly(cs)
- Covert a series containing Chebyshev series coefficients orderd from
- low to high to an equivalent polynomial ordered from low to
- high by degree.
+ Convert a Chebyshev series to a polynomial.
- Inputs
- ------
+ Convert an array representing the coefficients of a Chebyshev series,
+ ordered from lowest degree to highest, to an array of the coefficients
+ of the equivalent polynomial (relative to the "standard" basis) ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
cs : array_like
- 1-d array containing the Chebyshev series coeffients ordered from
- low to high.
+ 1-d array containing the Chebyshev series coefficients, ordered
+ from lowest order term to highest.
Returns
-------
pol : ndarray
1-d array containing the coefficients of the equivalent polynomial
- ordered from low to high by degree.
+ (relative to the "standard" basis) ordered from lowest order term
+ to highest.
See Also
--------
poly2cheb
+ Notes
+ -----
+ Note that a consequence of the input needing to be array_like and that
+ the output is an ndarray, is that if one is going to use this function
+ to convert a Chebyshev instance, T, to a Polynomial instance, P, the
+ usage is ``P = Polynomial(cheb2poly(T.coef))``; see Examples below.
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> c = P.Chebyshev(np.arange(4))
+ >>> c
+ Chebyshev([ 0., 1., 2., 3.], [-1., 1.])
+ >>> p = P.Polynomial(P.cheb2poly(c.coef))
+ >>> p
+ Polynomial([ -2., -8., 4., 12.], [-1., 1.])
+
"""
[cs] = pu.as_series([cs])
pol = np.zeros(len(cs), dtype=cs.dtype)
@@ -373,19 +430,33 @@ chebone = np.array([1])
chebx = np.array([0,1])
def chebline(off, scl) :
- """Chebyshev series whose graph is a straight line
+ """
+ Chebyshev series whose graph is a straight line.
+
- The line has the formula ``off + scl*x``
- Parameters:
- -----------
+ Parameters
+ ----------
off, scl : scalars
The specified line is given by ``off + scl*x``.
- Returns:
+ Returns
+ -------
+ y : ndarray
+ This module's representation of the Chebyshev series for
+ ``off + scl*x``.
+
+ See Also
+ --------
+ polyline
+
+ Examples
--------
- series : 1d ndarray
- The Chebyshev series representation of ``off + scl*x``.
+ >>> import numpy.polynomial.chebyshev as C
+ >>> C.chebline(3,2)
+ array([3, 2])
+ >>> C.chebval(-3, C.chebline(3,2)) # should be -3
+ -3.0
"""
if scl != 0 :
@@ -394,25 +465,55 @@ def chebline(off, scl) :
return np.array([off])
def chebfromroots(roots) :
- """Generate a Chebyschev series with given roots.
+ """
+ Generate a Chebyshev series with the given roots.
- Generate a Chebyshev series whose roots are given by `roots`. The
- resulting series is the produet `(x - roots[0])*(x - roots[1])*...`
+ Return the array of coefficients for the C-series whose roots (a.k.a.
+ "zeros") are given by *roots*. The returned array of coefficients is
+ ordered from lowest order "term" to highest, and zeros of multiplicity
+ greater than one must be included in *roots* a number of times equal
+ to their multiplicity (e.g., if `2` is a root of multiplicity three,
+ then [2,2,2] must be in *roots*).
- Inputs
- ------
+ Parameters
+ ----------
roots : array_like
- 1-d array containing the roots in sorted order.
+ Sequence containing the roots.
Returns
-------
- series : ndarray
- 1-d array containing the coefficients of the Chebeshev series
- ordered from low to high.
+ out : ndarray
+ 1-d array of the C-series' coefficients, ordered from low to
+ high. If all roots are real, ``out.dtype`` is a float type;
+ otherwise, ``out.dtype`` is a complex type, even if all the
+ coefficients in the result are real (see Examples below).
See Also
--------
- chebroots
+ polyfromroots
+
+ Notes
+ -----
+ What is returned are the :math:`c_i` such that:
+
+ .. math::
+
+ \\sum_{i=0}^{n} c_i*T_i(x) = \\prod_{i=0}^{n} (x - roots[i])
+
+ where ``n == len(roots)`` and :math:`T_i(x)` is the `i`-th Chebyshev
+ (basis) polynomial over the domain `[-1,1]`. Note that, unlike
+ `polyfromroots`, due to the nature of the C-series basis set, the
+ above identity *does not* imply :math:`c_n = 1` identically (see
+ Examples).
+
+ Examples
+ --------
+ >>> import numpy.polynomial.chebyshev as C
+ >>> C.chebfromroots((-1,0,1)) # x^3 - x relative to the standard basis
+ array([ 0. , -0.25, 0. , 0.25])
+ >>> j = complex(0,1)
+ >>> C.chebfromroots((-j,j)) # x^2 + 1 relative to the standard basis
+ array([ 1.5+0.j, 0.0+0.j, 0.5+0.j])
"""
if len(roots) == 0 :
@@ -427,27 +528,43 @@ def chebfromroots(roots) :
def chebadd(c1, c2):
- """Add one Chebyshev series to another.
+ """
+ Add one Chebyshev series to another.
- Returns the sum of two Chebyshev series `c1` + `c2`. The arguments are
- sequences of coefficients ordered from low to high, i.e., [1,2,3] is
- the series "T_0 + 2*T_1 + 3*T_2".
+ Returns the sum of two Chebyshev series `c1` + `c2`. The arguments
+ are sequences of coefficients ordered from lowest order term to
+ highest, i.e., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
Parameters
----------
c1, c2 : array_like
- 1d arrays of Chebyshev series coefficients ordered from low to
+ 1-d arrays of Chebyshev series coefficients ordered from low to
high.
Returns
-------
out : ndarray
- Chebyshev series of the sum.
+ Array representing the Chebyshev series of their sum.
See Also
--------
chebsub, chebmul, chebdiv, chebpow
+ Notes
+ -----
+ Unlike multiplication, division, etc., the sum of two Chebyshev series
+ is a Chebyshev series (without having to "reproject" the result onto
+ the basis set) so addition, just like that of "standard" polynomials,
+ is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> C.chebadd(c1,c2)
+ array([ 4., 4., 4.])
+
"""
# c1, c2 are trimmed copies
[c1, c2] = pu.as_series([c1, c2])
@@ -461,29 +578,44 @@ def chebadd(c1, c2):
def chebsub(c1, c2):
- """Subtract one Chebyshev series from another.
+ """
+ Subtract one Chebyshev series from another.
- Returns the difference of two Chebyshev series `c1` - `c2`. The
- sequences of coefficients are ordered from low to high, i.e., [1,2,3]
- is the series ``T_0 + 2*T_1 + 3*T_2.``
+ Returns the difference of two Chebyshev series `c1` - `c2`. The
+ sequences of coefficients are from lowest order term to highest, i.e.,
+ [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
Parameters
----------
c1, c2 : array_like
- 1d arrays of Chebyshev series coefficients ordered from low to
+ 1-d arrays of Chebyshev series coefficients ordered from low to
high.
Returns
-------
out : ndarray
- Chebyshev series of the difference.
+ Of Chebyshev series coefficients representing their difference.
See Also
--------
chebadd, chebmul, chebdiv, chebpow
+ Notes
+ -----
+ Unlike multiplication, division, etc., the difference of two Chebyshev
+ series is a Chebyshev series (without having to "reproject" the result
+ onto the basis set) so subtraction, just like that of "standard"
+ polynomials, is simply "component-wise."
+
Examples
--------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> C.chebsub(c1,c2)
+ array([-2., 0., 2.])
+ >>> C.chebsub(c2,c1) # -C.chebsub(c1,c2)
+ array([ 2., 0., -2.])
"""
# c1, c2 are trimmed copies
@@ -499,27 +631,44 @@ def chebsub(c1, c2):
def chebmul(c1, c2):
- """Multiply one Chebyshev series by another.
+ """
+ Multiply one Chebyshev series by another.
- Returns the product of two Chebyshev series `c1` * `c2`. The arguments
- are sequences of coefficients ordered from low to high, i.e., [1,2,3]
- is the series ``T_0 + 2*T_1 + 3*T_2.``
+ Returns the product of two Chebyshev series `c1` * `c2`. The arguments
+ are sequences of coefficients, from lowest order "term" to highest,
+ e.g., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
Parameters
----------
c1, c2 : array_like
- 1d arrays of chebyshev series coefficients ordered from low to
+ 1-d arrays of Chebyshev series coefficients ordered from low to
high.
Returns
-------
out : ndarray
- Chebyshev series of the product.
+ Of Chebyshev series coefficients representing their product.
See Also
--------
chebadd, chebsub, chebdiv, chebpow
+ Notes
+ -----
+ In general, the (polynomial) product of two C-series results in terms
+ that are not in the Chebyshev polynomial basis set. Thus, to express
+ the product as a C-series, it is typically necessary to "re-project"
+ the product onto said basis set, which typically produces
+ "un-intuitive" (but correct) results; see Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> C.chebmul(c1,c2) # multiplication requires "reprojection"
+ array([ 6.5, 12. , 12. , 4. , 1.5])
+
"""
# c1, c2 are trimmed copies
[c1, c2] = pu.as_series([c1, c2])
@@ -531,29 +680,49 @@ def chebmul(c1, c2):
def chebdiv(c1, c2):
- """Divide one Chebyshev series by another.
+ """
+ Divide one Chebyshev series by another.
- Returns the quotient of two Chebyshev series `c1` / `c2`. The arguments
- are sequences of coefficients ordered from low to high, i.e., [1,2,3]
- is the series ``T_0 + 2*T_1 + 3*T_2.``
+ Returns the quotient-with-remainder of two Chebyshev series
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
+ order "term" to highest, e.g., [1,2,3] represents the series
+ ``T_0 + 2*T_1 + 3*T_2``.
Parameters
----------
c1, c2 : array_like
- 1d arrays of chebyshev series coefficients ordered from low to
+ 1-d arrays of Chebyshev series coefficients ordered from low to
high.
Returns
-------
- [quo, rem] : ndarray
- Chebyshev series of the quotient and remainder.
+ [quo, rem] : ndarrays
+ Of Chebyshev series coefficients representing the quotient and
+ remainder.
See Also
--------
chebadd, chebsub, chebmul, chebpow
+ Notes
+ -----
+ In general, the (polynomial) division of one C-series by another
+ results in quotient and remainder terms that are not in the Chebyshev
+ polynomial basis set. Thus, to express these results as C-series, it
+ is typically necessary to "re-project" the results onto said basis
+ set, which typically produces "un-intuitive" (but correct) results;
+ see Examples section below.
+
Examples
--------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> C.chebdiv(c1,c2) # quotient "intuitive," remainder not
+ (array([ 3.]), array([-8., -4.]))
+ >>> c2 = (0,1,2,3)
+ >>> C.chebdiv(c2,c1) # neither "intuitive"
+ (array([ 0., 2.]), array([-2., -4.]))
"""
# c1, c2 are trimmed copies
@@ -627,24 +796,25 @@ def chebpow(cs, pow, maxpower=16) :
return _zseries_to_cseries(prd)
def chebder(cs, m=1, scl=1) :
- """Differentiate a Chebyshev series.
+ """
+ Differentiate a Chebyshev series.
- Returns the series `cs` differentiated `m` times. At each iteration the
- result is multiplied by `scl`. The scaling factor is for use in a
- linear change of variable. The argument `cs` is a sequence of
- coefficients ordered from low to high. i.e., [1,2,3] is the series
+ Returns the series `cs` differentiated `m` times. At each iteration the
+ result is multiplied by `scl` (the scaling factor is for use in a linear
+ change of variable). The argument `cs` is the sequence of coefficients
+ from lowest order "term" to highest, e.g., [1,2,3] represents the series
``T_0 + 2*T_1 + 3*T_2``.
Parameters
----------
cs: array_like
- 1d array of chebyshev series coefficients ordered from low to high.
+ 1-d array of Chebyshev series coefficients ordered from low to high.
m : int, optional
- Order of differentiation, must be non-negative. (default: 1)
+ Number of derivatives taken, must be non-negative. (Default: 1)
scl : scalar, optional
- The result of each derivation is multiplied by `scl`. The end
- result is multiplication by `scl`**`m`. This is for use in a linear
- change of variable. (default: 1)
+ Each differentiation is multiplied by `scl`. The end result is
+ multiplication by ``scl**m``. This is for use in a linear change of
+ variable. (Default: 1)
Returns
-------
@@ -655,8 +825,25 @@ def chebder(cs, m=1, scl=1) :
--------
chebint
+ Notes
+ -----
+ In general, the result of differentiating a C-series needs to be
+ "re-projected" onto the C-series basis set. Thus, typically, the
+ result of this function is "un-intuitive," albeit correct; see Examples
+ section below.
+
Examples
--------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> cs = (1,2,3,4)
+ >>> C.chebder(cs)
+ array([ 14., 12., 24.])
+ >>> C.chebder(cs,3)
+ array([ 96.])
+ >>> C.chebder(cs,scl=-1)
+ array([-14., -12., -24.])
+ >>> C.chebder(cs,2,-1)
+ array([ 12., 96.])
"""
# cs is a trimmed copy
@@ -678,49 +865,80 @@ def chebder(cs, m=1, scl=1) :
def chebint(cs, m=1, k=[], lbnd=0, scl=1) :
- """Integrate a Chebyshev series.
-
- Returns the series integrated from `lbnd` to x `m` times. At each
- iteration the resulting series is multiplied by `scl` and an
- integration constant specified by `k` is added. The scaling factor is
- for use in a linear change of variable. The argument `cs` is a sequence
- of coefficients ordered from low to high. i.e., [1,2,3] is the series
- ``T_0 + 2*T_1 + 3*T_2``.
-
+ """
+ Integrate a Chebyshev series.
+
+ Returns, as a C-series, the input C-series `cs`, integrated `m` times
+ from `lbnd` to `x`. At each iteration the resulting series is
+ **multiplied** by `scl` and an integration constant, `k`, is added.
+ The scaling factor is for use in a linear change of variable. ("Buyer
+ beware": note that, depending on what one is doing, one may want `scl`
+ to be the reciprocal of what one might expect; for more information,
+ see the Notes section below.) The argument `cs` is a sequence of
+ coefficients, from lowest order C-series "term" to highest, e.g.,
+ [1,2,3] represents the series :math:`T_0(x) + 2T_1(x) + 3T_2(x)`.
Parameters
----------
- cs: array_like
- 1d array of chebyshev series coefficients ordered from low to high.
+ cs : array_like
+ 1-d array of C-series coefficients, ordered from low to high.
m : int, optional
- Order of integration, must be positeve. (default: 1)
+ Order of integration, must be positive. (Default: 1)
k : {[], list, scalar}, optional
- Integration constants. The value of the first integral at zero is
- the first value in the list, the value of the second integral at
- zero is the second value in the list, and so on. If ``[]``
- (default), all constants are set zero. If `m = 1`, a single scalar
- can be given instead of a list.
+ Integration constant(s). The value of the first integral at zero
+ is the first value in the list, the value of the second integral
+ at zero is the second value, etc. If ``k == []`` (the default),
+ all constants are set to zero. If ``m == 1``, a single scalar can
+ be given instead of a list.
lbnd : scalar, optional
- The lower bound of the integral. (default: 0)
+ The lower bound of the integral. (Default: 0)
scl : scalar, optional
- Following each integration the result is multiplied by `scl` before
- the integration constant is added. (default: 1)
+ Following each integration the result is *multiplied* by `scl`
+ before the integration constant is added. (Default: 1)
Returns
-------
- der : ndarray
- Chebyshev series of the integral.
+ S : ndarray
+ C-series coefficients of the integral.
Raises
------
ValueError
+ If ``m < 1``, ``len(k) > m``, ``np.isscalar(lbnd) == False``, or
+ ``np.isscalar(scl) == False``.
See Also
--------
chebder
+ Notes
+ -----
+ Note that the result of each integration is *multiplied* by `scl`.
+ Why is this important to note? Say one is making a linear change of
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
+ :math:`dx = du/a`, so one will need to set `scl` equal to :math:`1/a`
+ - perhaps not what one would have first thought.
+
+ Also note that, in general, the result of integrating a C-series needs
+ to be "re-projected" onto the C-series basis set. Thus, typically,
+ the result of this function is "un-intuitive," albeit correct; see
+ Examples section below.
+
Examples
--------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> cs = (1,2,3)
+ >>> C.chebint(cs)
+ array([ 0.5, -0.5, 0.5, 0.5])
+ >>> C.chebint(cs,3)
+ array([ 0.03125 , -0.1875 , 0.04166667, -0.05208333, 0.01041667,
+ 0.00625 ])
+ >>> C.chebint(cs, k=3)
+ array([ 3.5, -0.5, 0.5, 0.5])
+ >>> C.chebint(cs,lbnd=-2)
+ array([ 8.5, -0.5, 0.5, 0.5])
+ >>> C.chebint(cs,scl=-2)
+ array([-1., 1., -1., -1.])
"""
if np.isscalar(k) :
@@ -839,10 +1057,11 @@ def chebvander(x, deg) :
return v
def chebfit(x, y, deg, rcond=None, full=False):
- """Least squares fit of Chebyshev series to data.
+ """
+ Least squares fit of Chebyshev series to data.
- Fit a Chebyshev series ``p(x) = p[0] * T_{deq}(x) + ... + p[deg] *
- T_{0}(x)`` of degree `deg` to points `(x, y)`. Returns a vector of
+ Fit a Chebyshev series ``p(x) = p[0] * T_{0}(x) + ... + p[deg] *
+ T_{deg}(x)`` of degree `deg` to points `(x, y)`. Returns a vector of
coefficients `p` that minimises the squared error.
Parameters
@@ -900,7 +1119,7 @@ def chebfit(x, y, deg, rcond=None, full=False):
The solution are the coefficients ``c[i]`` of the Chebyshev series
``T(x)`` that minimizes the squared error
- ``E = \sum_j |y_j - T(x_j)|^2``.
+ ``E = \\sum_j |y_j - T(x_j)|^2``.
This problem is solved by setting up as the overdetermined matrix
equation
@@ -971,24 +1190,45 @@ def chebfit(x, y, deg, rcond=None, full=False):
def chebroots(cs):
- """Roots of a Chebyshev series.
+ """
+ Compute the roots of a Chebyshev series.
- Compute the roots of the Chebyshev series `cs`. The argument `cs` is a
- sequence of coefficients ordered from low to high. i.e., [1,2,3] is the
- series ``T_0 + 2*T_1 + 3*T_2``.
+ Return the roots (a.k.a "zeros") of the C-series represented by `cs`,
+ which is the sequence of the C-series' coefficients from lowest order
+ "term" to highest, e.g., [1,2,3] represents the C-series
+ ``T_0 + 2*T_1 + 3*T_2``.
Parameters
----------
cs : array_like
- 1D array of Chebyshev coefficients ordered from low to high.
+ 1-d array of C-series coefficients ordered from low to high.
Returns
-------
out : ndarray
- An array containing the complex roots of the chebyshev series.
+ Array of the roots. If all the roots are real, then so is the
+ dtype of ``out``; otherwise, ``out``'s dtype is complex.
+
+ See Also
+ --------
+ polyroots
+
+ Notes
+ -----
+ Algorithm(s) used:
+
+ Remember: because the C-series basis set is different from the
+ "standard" basis set, the results of this function *may* not be what
+ one is expecting.
Examples
--------
+ >>> import numpy.polynomial as P
+ >>> import numpy.polynomial.chebyshev as C
+ >>> P.polyroots((-1,1,-1,1)) # x^3 - x^2 + x - 1 has two complex roots
+ array([ -4.99600361e-16-1.j, -4.99600361e-16+1.j, 1.00000e+00+0.j])
+ >>> C.chebroots((-1,1,-1,1)) # T3 - T2 + T1 - T0 has only real roots
+ array([ -5.00000000e-01, 2.60860684e-17, 1.00000000e+00])
"""
# cs is a trimmed copy
diff --git a/numpy/polynomial/polynomial.py b/numpy/polynomial/polynomial.py
index d5681f9ce..60b28c41f 100644
--- a/numpy/polynomial/polynomial.py
+++ b/numpy/polynomial/polynomial.py
@@ -1,43 +1,49 @@
-"""Functions for dealing with polynomials.
+"""
+Objects for dealing with polynomials.
-This module provides a number of functions that are useful in dealing with
-polynomials as well as a ``Polynomial`` class that encapsuletes the usual
-arithmetic operations. All arrays of polynomial coefficients are assumed to
-be ordered from low to high degree, thus `array([1,2,3])` will be treated
-as the polynomial ``1 + 2*x + 3*x**2``
+This module provides a number of objects (mostly functions) useful for
+dealing with polynomials, including a `Polynomial` class that
+encapsulates the usual arithmetic operations. (General information
+on how this module represents and works with polynomial objects is in
+the docstring for its "parent" sub-package, `numpy.polynomial`).
Constants
---------
-- polydomain -- Polynomial default domain
-- polyzero -- Polynomial that evaluates to 0.
-- polyone -- Polynomial that evaluates to 1.
-- polyx -- Polynomial of the identity map (x).
+- `polydomain` -- Polynomial default domain, [-1,1].
+- `polyzero` -- (Coefficients of the) "zero polynomial."
+- `polyone` -- (Coefficients of the) constant polynomial 1.
+- `polyx` -- (Coefficients of the) identity map polynomial, ``f(x) = x``.
Arithmetic
----------
-- polyadd -- add a polynomial to another.
-- polysub -- subtract a polynomial from another.
-- polymul -- multiply a polynomial by another
-- polydiv -- divide one polynomial by another.
-- polyval -- evaluate a polynomial at given points.
+- `polyadd` -- add two polynomials.
+- `polysub` -- subtract one polynomial from another.
+- `polymul` -- multiply two polynomials.
+- `polydiv` -- divide one polynomial by another.
+- `polyval` -- evaluate a polynomial at given points.
Calculus
--------
-- polyder -- differentiate a polynomial.
-- polyint -- integrate a polynomial.
+- `polyder` -- differentiate a polynomial.
+- `polyint` -- integrate a polynomial.
Misc Functions
--------------
-- polyfromroots -- create a polynomial with specified roots.
-- polyroots -- find the roots of a polynomial.
-- polyvander -- Vandermode like matrix for powers.
-- polyfit -- least squares fit returning a polynomial.
-- polytrim -- trim leading coefficients from a polynomial.
-- polyline -- Polynomial of given straight line
+- `polyfromroots` -- create a polynomial with specified roots.
+- `polyroots` -- find the roots of a polynomial.
+- `polyvander` -- Vandermonde-like matrix for powers.
+- `polyfit` -- least-squares fit returning a polynomial.
+- `polytrim` -- trim leading coefficients from a polynomial.
+- `polyline` -- Given a straight line, return the equivalent polynomial
+ object.
Classes
-------
-- Polynomial -- polynomial class.
+- `Polynomial` -- polynomial class.
+
+See also
+--------
+`numpy.polynomial`
"""
from __future__ import division
@@ -77,19 +83,31 @@ polyx = np.array([0,1])
#
def polyline(off, scl) :
- """Polynomial whose graph is a straight line.
-
- The line has the formula ``off + scl*x``
+ """
+ Returns an array representing a linear polynomial.
- Parameters:
- -----------
+ Parameters
+ ----------
off, scl : scalars
- The specified line is given by ``off + scl*x``.
+ The "y-intercept" and "slope" of the line, respectively.
+
+ Returns
+ -------
+ y : ndarray
+ This module's representation of the linear polynomial ``off +
+ scl*x``.
- Returns:
+ See Also
+ --------
+ chebline
+
+ Examples
--------
- series : 1d ndarray
- The polynomial equal to ``off + scl*x``.
+ >>> from numpy import polynomial as P
+ >>> P.polyline(1,-1)
+ array([ 1, -1])
+ >>> P.polyval(1, P.polyline(1,-1)) # should be 0
+ 0.0
"""
if scl != 0 :
@@ -98,25 +116,53 @@ def polyline(off, scl) :
return np.array([off])
def polyfromroots(roots) :
- """Generate a polynomial with given roots.
+ """
+ Generate a polynomial with the given roots.
- Generate a polynomial whose roots are given by `roots`. The resulting
- series is the produet `(x - roots[0])*(x - roots[1])*...`
+ Return the array of coefficients for the polynomial whose leading
+ coefficient (i.e., that of the highest order term) is `1` and whose
+ roots (a.k.a. "zeros") are given by *roots*. The returned array of
+ coefficients is ordered from lowest order term to highest, and zeros
+ of multiplicity greater than one must be included in *roots* a number
+ of times equal to their multiplicity (e.g., if `2` is a root of
+ multiplicity three, then [2,2,2] must be in *roots*).
- Inputs
- ------
+ Parameters
+ ----------
roots : array_like
- 1-d array containing the roots in sorted order.
+ Sequence containing the roots.
Returns
-------
- series : ndarray
- 1-d array containing the coefficients of the Chebeshev series
- ordered from low to high.
+ out : ndarray
+ 1-d array of the polynomial's coefficients, ordered from low to
+ high. If all roots are real, ``out.dtype`` is a float type;
+ otherwise, ``out.dtype`` is a complex type, even if all the
+ coefficients in the result are real (see Examples below).
See Also
--------
- polyroots
+ chebfromroots
+
+ Notes
+ -----
+ What is returned are the :math:`a_i` such that:
+
+ .. math::
+
+ \\sum_{i=0}^{n} a_ix^i = \\prod_{i=0}^{n} (x - roots[i])
+
+ where ``n == len(roots)``; note that this implies that `1` is always
+ returned for :math:`a_n`.
+
+ Examples
+ --------
+ >>> import numpy.polynomial as P
+ >>> P.polyfromroots((-1,0,1)) # x(x - 1)(x + 1) = x^3 - x
+ array([ 0., -1., 0., 1.])
+ >>> j = complex(0,1)
+ >>> P.polyfromroots((-j,j)) # complex returned, though values are real
+ array([ 1.+0.j, 0.+0.j, 1.+0.j])
"""
if len(roots) == 0 :
@@ -131,27 +177,37 @@ def polyfromroots(roots) :
def polyadd(c1, c2):
- """Add one polynomial to another.
+ """
+ Add one polynomial to another.
- Returns the sum of two polynomials `c1` + `c2`. The arguments are
- sequences of coefficients ordered from low to high, i.e., [1,2,3] is
- the polynomial ``1 + 2*x + 3*x**2"``.
+ Returns the sum of two polynomials `c1` + `c2`. The arguments are
+ sequences of coefficients from lowest order term to highest, i.e.,
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2"``.
Parameters
----------
c1, c2 : array_like
- 1d arrays of polynomial coefficients ordered from low to
- high.
+ 1-d arrays of polynomial coefficients ordered from low to high.
Returns
-------
out : ndarray
- polynomial of the sum.
+ The coefficient array representing their sum.
See Also
--------
polysub, polymul, polydiv, polypow
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> sum = P.polyadd(c1,c2); sum
+ array([ 4., 4., 4.])
+ >>> P.polyval(2, sum) # 4 + 4(2) + 4(2**2)
+ 28.0
+
"""
# c1, c2 are trimmed copies
[c1, c2] = pu.as_series([c1, c2])
@@ -165,22 +221,23 @@ def polyadd(c1, c2):
def polysub(c1, c2):
- """Subtract one polynomial from another.
+ """
+ Subtract one polynomial from another.
- Returns the difference of two polynomials `c1` - `c2`. The arguments
- are sequences of coefficients ordered from low to high, i.e., [1,2,3]
- is the polynomial ``1 + 2*x + 3*x**2``.
+ Returns the difference of two polynomials `c1` - `c2`. The arguments
+ are sequences of coefficients from lowest order term to highest, i.e.,
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
Parameters
----------
c1, c2 : array_like
- 1d arrays of polynomial coefficients ordered from low to
+ 1-d arrays of polynomial coefficients ordered from low to
high.
Returns
-------
out : ndarray
- polynomial of the difference.
+ Of coefficients representing their difference.
See Also
--------
@@ -188,6 +245,13 @@ def polysub(c1, c2):
Examples
--------
+ >>> from numpy import polynomial as P
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> P.polysub(c1,c2)
+ array([-2., 0., 2.])
+ >>> P.polysub(c2,c1) # -P.polysub(c1,c2)
+ array([ 2., 0., -2.])
"""
# c1, c2 are trimmed copies
@@ -203,27 +267,36 @@ def polysub(c1, c2):
def polymul(c1, c2):
- """Multiply one polynomial by another.
+ """
+ Multiply one polynomial by another.
- Returns the product of two polynomials `c1` * `c2`. The arguments
- are sequences of coefficients ordered from low to high, i.e., [1,2,3]
- is the polynomial ``1 + 2*x + 3*x**2.``
+ Returns the product of two polynomials `c1` * `c2`. The arguments are
+ sequences of coefficients, from lowest order term to highest, e.g.,
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2.``
Parameters
----------
c1, c2 : array_like
- 1d arrays of polyyshev series coefficients ordered from low to
- high.
+ 1-d arrays of coefficients representing a polynomial, relative to the
+ "standard" basis, and ordered from lowest order term to highest.
Returns
-------
out : ndarray
- polynomial of the product.
+ Of the coefficients of their product.
See Also
--------
polyadd, polysub, polydiv, polypow
+ Examples
+ --------
+ >>> import numpy.polynomial as P
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> P.polymul(c1,c2)
+ array([ 3., 8., 14., 8., 3.])
+
"""
# c1, c2 are trimmed copies
[c1, c2] = pu.as_series([c1, c2])
@@ -232,22 +305,22 @@ def polymul(c1, c2):
def polydiv(c1, c2):
- """Divide one polynomial by another.
+ """
+ Divide one polynomial by another.
- Returns the quotient of two polynomials `c1` / `c2`. The arguments are
- sequences of coefficients ordered from low to high, i.e., [1,2,3] is
- the series ``1 + 2*x + 3*x**2.``
+ Returns the quotient-with-remainder of two polynomials `c1` / `c2`.
+ The arguments are sequences of coefficients, from lowest order term
+ to highest, e.g., [1,2,3] represents ``1 + 2*x + 3*x**2``.
Parameters
----------
c1, c2 : array_like
- 1d arrays of chebyshev series coefficients ordered from low to
- high.
+ 1-d arrays of polynomial coefficients ordered from low to high.
Returns
-------
- [quo, rem] : ndarray
- polynomial of the quotient and remainder.
+ [quo, rem] : ndarrays
+ Of coefficient series representing the quotient and remainder.
See Also
--------
@@ -255,6 +328,13 @@ def polydiv(c1, c2):
Examples
--------
+ >>> import numpy.polynomial as P
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> P.polydiv(c1,c2)
+ (array([ 3.]), array([-8., -4.]))
+ >>> P.polydiv(c2,c1)
+ (array([ 0.33333333]), array([ 2.66666667, 1.33333333]))
"""
# c1, c2 are trimmed copies
@@ -331,27 +411,30 @@ def polypow(cs, pow, maxpower=None) :
return prd
def polyder(cs, m=1, scl=1) :
- """Differentiate a polynomial.
+ """
+ Differentiate a polynomial.
- Returns the polynomial `cs` differentiated `m` times. The argument `cs`
- is a sequence of coefficients ordered from low to high. i.e., [1,2,3]
- is the series ``1 + 2*x + 3*x**2.``
+ Returns the polynomial `cs` differentiated `m` times. At each
+ iteration the result is multiplied by `scl` (the scaling factor is for
+ use in a linear change of variable). The argument `cs` is the sequence
+ of coefficients from lowest order term to highest, e.g., [1,2,3]
+ represents the polynomial ``1 + 2*x + 3*x**2``.
Parameters
----------
cs: array_like
- 1d array of chebyshev series coefficients ordered from low to high.
+ 1-d array of polynomial coefficients ordered from low to high.
m : int, optional
- Order of differentiation, must be non-negative. (default: 1)
+ Number of derivatives taken, must be non-negative. (Default: 1)
scl : scalar, optional
- The result of each derivation is multiplied by `scl`. The end
- result is multiplication by `scl`**`m`. This is for use in a linear
- change of variable. (default: 1)
+ Each differentiation is multiplied by `scl`. The end result is
+ multiplication by ``scl**m``. This is for use in a linear change
+ of variable. (Default: 1)
Returns
-------
der : ndarray
- polynomial of the derivative.
+ Polynomial of the derivative.
See Also
--------
@@ -359,6 +442,16 @@ def polyder(cs, m=1, scl=1) :
Examples
--------
+ >>> from numpy import polynomial as P
+ >>> cs = (1,2,3,4) # 1 + 2x + 3x**2 + 4x**3
+ >>> P.polyder(cs) # (d/dx)(cs) = 2 + 6x + 12x**2
+ array([ 2., 6., 12.])
+ >>> P.polyder(cs,3) # (d**3/dx**3)(cs) = 24
+ array([ 24.])
+ >>> P.polyder(cs,scl=-1) # (d/d(-x))(cs) = -2 - 6x - 12x**2
+ array([ -2., -6., -12.])
+ >>> P.polyder(cs,2,-1) # (d**2/d(-x)**2)(cs) = 6 + 24x
+ array([ 6., 24.])
"""
# cs is a trimmed copy
@@ -380,49 +473,75 @@ def polyder(cs, m=1, scl=1) :
return cs[i+1:].copy()
def polyint(cs, m=1, k=[], lbnd=0, scl=1) :
- """Integrate a polynomial.
-
- Returns the polynomial `cs` integrated from `lbnd` to x `m` times. At
- each iteration the resulting series is multiplied by `scl` and an
- integration constant specified by `k` is added. The scaling factor is
- for use in a linear change of variable. The argument `cs` is a sequence
- of coefficients ordered from low to high. i.e., [1,2,3] is the
- polynomial ``1 + 2*x + 3*x**2``.
-
+ """
+ Integrate a polynomial.
+
+ Returns the polynomial `cs`, integrated `m` times from `lbnd` to `x`.
+ At each iteration the resulting series is **multiplied** by `scl` and
+ an integration constant, `k`, is added. The scaling factor is for use
+ in a linear change of variable. ("Buyer beware": note that, depending
+ on what one is doing, one may want `scl` to be the reciprocal of what
+ one might expect; for more information, see the Notes section below.)
+ The argument `cs` is a sequence of coefficients, from lowest order
+ term to highest, e.g., [1,2,3] represents the polynomial
+ ``1 + 2*x + 3*x**2``.
Parameters
----------
cs : array_like
- 1d array of chebyshev series coefficients ordered from low to high.
+ 1-d array of polynomial coefficients, ordered from low to high.
m : int, optional
- Order of integration, must be positeve. (default: 1)
+ Order of integration, must be positive. (Default: 1)
k : {[], list, scalar}, optional
- Integration constants. The value of the first integral at zero is
- the first value in the list, the value of the second integral at
- zero is the second value in the list, and so on. If ``[]``
- (default), all constants are set zero. If `m = 1`, a single scalar
- can be given instead of a list.
+ Integration constant(s). The value of the first integral at zero
+ is the first value in the list, the value of the second integral
+ at zero is the second value, etc. If ``k == []`` (the default),
+ all constants are set to zero. If ``m == 1``, a single scalar can
+ be given instead of a list.
lbnd : scalar, optional
- The lower bound of the integral. (default: 0)
+ The lower bound of the integral. (Default: 0)
scl : scalar, optional
- Following each integration the result is multiplied by `scl` before
- the integration constant is added. (default: 1)
+ Following each integration the result is *multiplied* by `scl`
+ before the integration constant is added. (Default: 1)
Returns
-------
- der : ndarray
- polynomial of the integral.
+ S : ndarray
+ Coefficients of the integral.
Raises
------
ValueError
+ If ``m < 1``, ``len(k) > m``, ``np.isscalar(lbnd) == False``, or
+ ``np.isscalar(scl) == False``.
See Also
--------
polyder
+ Notes
+ -----
+ Note that the result of each integration is *multiplied* by `scl`.
+ Why is this important to note? Say one is making a linear change of
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
+ :math:`dx = du/a`, so one will need to set `scl` equal to :math:`1/a`
+ - perhaps not what one would have first thought.
+
Examples
--------
+ >>> from numpy import polynomial as P
+ >>> cs = (1,2,3)
+ >>> P.polyint(cs) # should return array([0, 1, 1, 1])
+ array([ 0., 1., 1., 1.])
+ >>> P.polyint(cs,3) # should return array([0, 0, 0, 1/6, 1/12, 1/20])
+ array([ 0. , 0. , 0. , 0.16666667, 0.08333333,
+ 0.05 ])
+ >>> P.polyint(cs,k=3) # should return array([3, 1, 1, 1])
+ array([ 3., 1., 1., 1.])
+ >>> P.polyint(cs,lbnd=-2) # should return array([6, 1, 1, 1])
+ array([ 6., 1., 1., 1.])
+ >>> P.polyint(cs,scl=-2) # should return array([0, -2, -2, -2])
+ array([ 0., -2., -2., -2.])
"""
if np.isscalar(k) :
@@ -448,7 +567,8 @@ def polyint(cs, m=1, k=[], lbnd=0, scl=1) :
return ret
def polyval(x, cs):
- """Evaluate a polynomial.
+ """
+ Evaluate a polynomial.
If `cs` is of length `n`, this function returns :
@@ -476,16 +596,10 @@ def polyval(x, cs):
--------
polyfit
- Examples
- --------
-
Notes
-----
The evaluation uses Horner's method.
- Examples
- --------
-
"""
# cs is a trimmed copy
[cs] = pu.as_series([cs])
@@ -529,50 +643,56 @@ def polyvander(x, deg) :
return v
def polyfit(x, y, deg, rcond=None, full=False):
- """Least squares fit of polynomial to data.
+ """
+ Least-squares fit of a polynomial to data.
- Fit a polynomial ``p(x) = p[0] * T_{deq}(x) + ... + p[deg] *
- T_{0}(x)`` of degree `deg` to points `(x, y)`. Returns a vector of
- coefficients `p` that minimises the squared error.
+ Fit a polynomial ``c0 + c1*x + c2*x**2 + ... + c[deg]*x**deg`` to
+ points (`x`, `y`). Returns a 1-d (if `y` is 1-d) or 2-d (if `y` is 2-d)
+ array of coefficients representing, from lowest order term to highest,
+ the polynomial(s) which minimize the total square error.
Parameters
----------
- x : array_like, shape (M,)
- x-coordinates of the M sample points ``(x[i], y[i])``.
- y : array_like, shape (M,) or (M, K)
- y-coordinates of the sample points. Several data sets of sample
- points sharing the same x-coordinates can be fitted at once by
- passing in a 2D-array that contains one dataset per column.
+ x : array_like, shape (`M`,)
+ x-coordinates of the `M` sample (data) points ``(x[i], y[i])``.
+ y : array_like, shape (`M`,) or (`M`, `K`)
+ y-coordinates of the sample points. Several sets of sample points
+ sharing the same x-coordinates can be (independently) fit with one
+ call to `polyfit` by passing in for `y` a 2-d array that contains
+ one data set per column.
deg : int
- Degree of the fitting polynomial
+ Degree of the polynomial(s) to be fit.
rcond : float, optional
- Relative condition number of the fit. Singular values smaller than
- this relative to the largest singular value will be ignored. The
- default value is len(x)*eps, where eps is the relative precision of
- the float type, about 2e-16 in most cases.
+ Relative condition number of the fit. Singular values smaller
+ than `rcond`, relative to the largest singular value, will be
+ ignored. The default value is ``len(x)*eps``, where `eps` is the
+ relative precision of the platform's float type, about 2e-16 in
+ most cases.
full : bool, optional
- Switch determining nature of return value. When it is False (the
- default) just the coefficients are returned, when True diagnostic
- information from the singular value decomposition is also returned.
+ Switch determining the nature of the return value. When ``False``
+ (the default) just the coefficients are returned; when ``True``,
+ diagnostic information from the singular value decomposition (used
+ to solve the fit's matrix equation) is also returned.
Returns
-------
- coef : ndarray, shape (M,) or (M, K)
- Polynomial coefficients ordered from low to high. If `y` was 2-D,
- the coefficients for the data in column k of `y` are in column
- `k`.
+ coef : ndarray, shape (`deg` + 1,) or (`deg` + 1, `K`)
+ Polynomial coefficients ordered from low to high. If `y` was 2-d,
+ the coefficients in column `k` of `coef` represent the polynomial
+ fit to the data in `y`'s `k`-th column.
- [residuals, rank, singular_values, rcond] : present when `full` = True
- Residuals of the least-squares fit, the effective rank of the
- scaled Vandermonde matrix and its singular values, and the
- specified value of `rcond`. For more details, see `linalg.lstsq`.
+ [residuals, rank, singular_values, rcond] : present when `full` == True
+ Sum of the squared residuals (SSR) of the least-squares fit; the
+ effective rank of the scaled Vandermonde matrix; its singular
+ values; and the specified value of `rcond`. For more information,
+ see `linalg.lstsq`.
- Warns
- -----
+ Raises
+ ------
RankWarning
- The rank of the coefficient matrix in the least-squares fit is
- deficient. The warning is only raised if `full` = False. The
- warnings can be turned off by
+ Raised if the matrix in the least-squares fit is rank deficient.
+ The warning is only raised if `full` == False. The warnings can
+ be turned off by:
>>> import warnings
>>> warnings.simplefilter('ignore', RankWarning)
@@ -587,41 +707,60 @@ def polyfit(x, y, deg, rcond=None, full=False):
Notes
-----
- The solution are the coefficients ``c[i]`` of the polynomial ``P(x)``
- that minimizes the squared error
-
- ``E = \sum_j |y_j - P(x_j)|^2``.
-
- This problem is solved by setting up as the overdetermined matrix
- equation
-
- ``V(x)*c = y``,
-
- where ``V`` is the Vandermonde matrix of `x`, the elements of ``c`` are
- the coefficients to be solved for, and the elements of `y` are the
- observed values. This equation is then solved using the singular value
- decomposition of ``V``.
-
- If some of the singular values of ``V`` are so small that they are
- neglected, then a `RankWarning` will be issued. This means that the
- coeficient values may be poorly determined. Using a lower order fit
- will usually get rid of the warning. The `rcond` parameter can also be
- set to a value smaller than its default, but the resulting fit may be
- spurious and have large contributions from roundoff error.
-
- Fits using double precision and polynomials tend to fail at about
- degree 20. Fits using Chebyshev series are generally better
- conditioned, but much can still depend on the distribution of the
- sample points and the smoothness of the data. If the quality of the fit
- is inadequate splines may be a good alternative.
-
- References
- ----------
- .. [1] Wikipedia, "Curve fitting",
- http://en.wikipedia.org/wiki/Curve_fitting
+ The solutions are the coefficients ``c[i]`` of the polynomial ``P(x)``
+ that minimizes the total squared error:
+
+ .. math :: E = \\sum_j (y_j - P(x_j))^2
+
+ This problem is solved by setting up the (typically) over-determined
+ matrix equation:
+
+ .. math :: V(x)*c = y
+
+ where `V` is the Vandermonde matrix of `x`, the elements of `c` are the
+ coefficients to be solved for, and the elements of `y` are the observed
+ values. This equation is then solved using the singular value
+ decomposition of `V`.
+
+ If some of the singular values of `V` are so small that they are
+ neglected (and `full` == ``False``), a `RankWarning` will be raised.
+ This means that the coefficient values may be poorly determined.
+ Fitting to a lower order polynomial will usually get rid of the warning
+ (but may not be what you want, of course; if you have independent
+ reason(s) for choosing the degree which isn't working, you may have to:
+ a) reconsider those reasons, and/or b) reconsider the quality of your
+ data). The `rcond` parameter can also be set to a value smaller than
+ its default, but the resulting fit may be spurious and have large
+ contributions from roundoff error.
+
+ Polynomial fits using double precision tend to "fail" at about
+ (polynomial) degree 20. Fits using Chebyshev series are generally
+ better conditioned, but much can still depend on the distribution of
+ the sample points and the smoothness of the data. If the quality of
+ the fit is inadequate, splines may be a good alternative.
Examples
--------
+ >>> from numpy import polynomial as P
+ >>> x = np.linspace(-1,1,51) # x "data": [-1, -0.96, ..., 0.96, 1]
+ >>> y = x**3 - x + np.random.randn(len(x)) # x^3 - x + N(0,1) "noise"
+ >>> c, stats = P.polyfit(x,y,3,full=True)
+ >>> c # c[0], c[2] should be approx. 0, c[1] approx. -1, c[3] approx. 1
+ array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286])
+ >>> stats # note the large SSR, explaining the rather poor results
+ [array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316,
+ 0.28853036]), 1.1324274851176597e-014]
+
+ Same thing without the added noise
+
+ >>> y = x**3 - x
+ >>> c, stats = P.polyfit(x,y,3,full=True)
+ >>> c # c[0], c[2] should be "very close to 0", c[1] ~= -1, c[3] ~= 1
+ array([ -1.73362882e-17, -1.00000000e+00, -2.67471909e-16,
+ 1.00000000e+00])
+ >>> stats # note the minuscule SSR
+ [array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158,
+ 0.50443316, 0.28853036]), 1.1324274851176597e-014]
"""
order = int(deg) + 1
@@ -662,24 +801,39 @@ def polyfit(x, y, deg, rcond=None, full=False):
def polyroots(cs):
- """Roots of a polynomial.
+ """
+ Compute the roots of a polynomial.
- Compute the roots of the Chebyshev series `cs`. The argument `cs` is a
- sequence of coefficients ordered from low to high. i.e., [1,2,3] is the
- polynomial ``1 + 2*x + 3*x**2``.
+ Return the roots (a.k.a. "zeros") of the "polynomial" `cs`, the
+ polynomial's coefficients from lowest order term to highest
+ (e.g., [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``).
Parameters
----------
- cs : array_like of shape(M,)
- 1D array of polynomial coefficients ordered from low to high.
+ cs : array_like of shape (M,)
+ 1-d array of polynomial coefficients ordered from low to high.
Returns
-------
out : ndarray
- An array containing the complex roots of the polynomial series.
+ Array of the roots of the polynomial. If all the roots are real,
+ then so is the dtype of ``out``; otherwise, ``out``'s dtype is
+ complex.
+
+ See Also
+ --------
+ chebroots
Examples
--------
+ >>> import numpy.polynomial as P
+ >>> P.polyroots(P.polyfromroots((-1,0,1)))
+ array([-1., 0., 1.])
+ >>> P.polyroots(P.polyfromroots((-1,0,1))).dtype
+ dtype('float64')
+ >>> j = complex(0,1)
+ >>> P.polyroots(P.polyfromroots((-j,0,j)))
+ array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j])
"""
# cs is a trimmed copy
diff --git a/numpy/polynomial/polytemplate.py b/numpy/polynomial/polytemplate.py
index 512fd9201..29691496b 100644
--- a/numpy/polynomial/polytemplate.py
+++ b/numpy/polynomial/polytemplate.py
@@ -1,4 +1,12 @@
-"""Template for the Chebyshev and Polynomial classes.
+"""
+Template for the Chebyshev and Polynomial classes.
+
+This module houses a Python string module Template object (see, e.g.,
+http://docs.python.org/library/string.html#template-strings) used by
+the `polynomial` and `chebyshev` modules to implement their respective
+`Polynomial` and `Chebyshev` classes. It provides a mechanism for easily
+creating additional specific polynomial classes (e.g., Legendre, Jacobi,
+etc.) in the future, such that all these classes will have a common API.
"""
import string
diff --git a/numpy/polynomial/polyutils.py b/numpy/polynomial/polyutils.py
index 4d9516a03..5c65e03c2 100644
--- a/numpy/polynomial/polyutils.py
+++ b/numpy/polynomial/polyutils.py
@@ -1,30 +1,34 @@
-"""Utililty functions for polynomial modules.
+"""
+Utililty objects for the polynomial modules.
-This modules provides errors, warnings, and a polynomial base class along
-with some common routines that are used in both the polynomial and
-chebyshev modules.
+This module provides: error and warning objects; a polynomial base class;
+and some routines used in both the `polynomial` and `chebyshev` modules.
-Errors
-------
-- PolyError -- base class for errors
-- PolyDomainError -- mismatched domains
+Error objects
+-------------
+- `PolyError` -- base class for this sub-package's errors.
+- `PolyDomainError` -- raised when domains are "mismatched."
-Warnings
---------
-- RankWarning -- issued by least squares fits to warn of deficient rank
+Warning objects
+---------------
+- `RankWarning` -- raised by a least-squares fit when a rank-deficient
+ matrix is encountered.
-Base Class
+Base class
----------
-- PolyBase -- Base class for the Polynomial and Chebyshev classes.
+- `PolyBase` -- The base class for the `Polynomial` and `Chebyshev`
+ classes.
Functions
---------
-- as_series -- turns list of array_like into 1d arrays of common type
-- trimseq -- removes trailing zeros
-- trimcoef -- removes trailing coefficients less than given magnitude
-- getdomain -- finds appropriate domain for collection of points
-- mapdomain -- maps points between domains
-- mapparms -- parameters of the linear map between domains
+- `as_series` -- turns a list of array_likes into 1-D arrays of common
+ type.
+- `trimseq` -- removes trailing zeros.
+- `trimcoef` -- removes trailing coefficients that are less than a given
+ magnitude (thereby removing the corresponding terms).
+- `getdomain` -- returns a domain appropriate for a given set of abscissae.
+- `mapdomain` -- maps points between domains.
+- `mapparms` -- parameters of the linear map between domains.
"""
from __future__ import division
@@ -109,29 +113,44 @@ def trimseq(seq) :
def as_series(alist, trim=True) :
- """Return arguments as a list of 1d arrays.
+ """
+ Return argument as a list of 1-d arrays.
- The return type will always be an array of double, complex double. or
- object.
+ The returned list contains array(s) of dtype double, complex double, or
+ object. A 1-d argument of shape ``(N,)`` is parsed into ``N`` arrays of
+ size one; a 2-d argument of shape ``(M,N)`` is parsed into ``M`` arrays
+ of size ``N`` (i.e., is "parsed by row"); and a higher dimensional array
+ raises a Value Error if it is not first reshaped into either a 1-d or 2-d
+ array.
Parameters
----------
- [a1, a2,...] : list of array_like.
- The arrays must have no more than one dimension when converted.
- trim : boolean
+ a : array_like
+ A 1- or 2-d array_like
+ trim : boolean, optional
When True, trailing zeros are removed from the inputs.
When False, the inputs are passed through intact.
Returns
-------
[a1, a2,...] : list of 1d-arrays
- A copy of the input data as a 1d-arrays.
+ A copy of the input data as a list of 1-d arrays.
Raises
------
ValueError :
- Raised when an input can not be coverted to 1-d array or the
- resulting array is empty.
+ Raised when `as_series` cannot convert its input to 1-d arrays, or at
+ least one of the resulting arrays is empty.
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> a = np.arange(4)
+ >>> P.as_series(a)
+ [array([ 0.]), array([ 1.]), array([ 2.]), array([ 3.])]
+ >>> b = np.arange(6).reshape((2,3))
+ >>> P.as_series(b)
+ [array([ 0., 1., 2.]), array([ 3., 4., 5.])]
"""
arrays = [np.array(a, ndmin=1, copy=0) for a in alist]
@@ -161,24 +180,47 @@ def as_series(alist, trim=True) :
def trimcoef(c, tol=0) :
- """Remove small trailing coefficients from a polynomial series.
+ """
+ Remove "small" "trailing" coefficients from a polynomial.
+
+ "Small" means "small in absolute value" and is controlled by the
+ parameter `tol`; "trailing" means highest order coefficient(s), e.g., in
+ ``[0, 1, 1, 0, 0]`` (which represents ``0 + x + x**2 + 0*x**3 + 0*x**4``)
+ both the 3-rd and 4-th order coefficients would be "trimmed."
Parameters
----------
c : array_like
- 1-d array of coefficients, ordered from low to high.
- tol : number
- Trailing elements with absolute value less than tol are removed.
+ 1-d array of coefficients, ordered from lowest order to highest.
+ tol : number, optional
+ Trailing (i.e., highest order) elements with absolute value less
+ than or equal to `tol` (default value is zero) are removed.
Returns
-------
trimmed : ndarray
- 1_d array with tailing zeros removed. If the resulting series would
- be empty, a series containing a singel zero is returned.
+ 1-d array with trailing zeros removed. If the resulting series
+ would be empty, a series containing a single zero is returned.
Raises
------
- ValueError : if tol < 0
+ ValueError
+ If `tol` < 0
+
+ See Also
+ --------
+ trimseq
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> P.trimcoef((0,0,3,0,5,0,0))
+ array([ 0., 0., 3., 0., 5.])
+ >>> P.trimcoef((0,0,1e-3,0,1e-5,0,0),1e-3) # item == tol is trimmed
+ array([ 0.])
+ >>> i = complex(0,1) # works for complex
+ >>> P.trimcoef((3e-4,1e-3*(1-i),5e-4,2e-5*(1+i)), 1e-3)
+ array([ 0.0003+0.j , 0.0010-0.001j])
"""
if tol < 0 :
@@ -192,29 +234,42 @@ def trimcoef(c, tol=0) :
return c[:ind[-1] + 1].copy()
def getdomain(x) :
- """Determine suitable domain for given points.
+ """
+ Return a domain suitable for given abscissae.
+
+ Find a domain suitable for a polynomial or Chebyshev series
+ defined at the values supplied.
- Find a suitable domain in which to fit a function defined at the points
- `x` with a polynomial or Chebyshev series.
-
Parameters
----------
x : array_like
- 1D array of points whose domain will be determined.
+ 1-d array of abscissae whose domain will be determined.
Returns
-------
domain : ndarray
- 1D ndarray containing two values. If the inputs are complex, then
- the two points are the corners of the smallest rectangle alinged
- with the axes in the complex plane containing the points `x`. If
- the inputs are real, then the two points are the ends of the
- smallest interval containing the points `x`,
+ 1-d array containing two values. If the inputs are complex, then
+ the two returned points are the lower left and upper right corners
+ of the smallest rectangle (aligned with the axes) in the complex
+ plane containing the points `x`. If the inputs are real, then the
+ two points are the ends of the smallest interval containing the
+ points `x`.
See Also
--------
mapparms, mapdomain
+ Examples
+ --------
+ >>> from numpy.polynomial import polyutils as pu
+ >>> points = np.arange(4)**2 - 5; points
+ array([-5, -4, -1, 4])
+ >>> pu.getdomain(points)
+ array([-5., 4.])
+ >>> c = np.exp(complex(0,1)*np.pi*np.arange(12)/6) # unit circle
+ >>> pu.getdomain(c)
+ array([-1.-1.j, 1.+1.j])
+
"""
[x] = as_series([x], trim=False)
if x.dtype.char in np.typecodes['Complex'] :
@@ -225,27 +280,45 @@ def getdomain(x) :
return np.array((x.min(), x.max()))
def mapparms(old, new) :
- """Linear map between domains.
+ """
+ Linear map parameters between domains.
- Return the parameters of the linear map ``off + scl*x`` that maps the
- `old` domain to the `new` domain. The map is defined by the requirement
- that the left end of the old domain map to the left end of the new
- domain, and similarly for the right ends.
+ Return the parameters of the linear map ``offset + scale*x`` that maps
+ `old` to `new` such that ``old[i] -> new[i]``, ``i = 0, 1``.
Parameters
----------
old, new : array_like
- The two domains should convert as 1D arrays containing two values.
+ Each domain must (successfully) convert to a 1-d array containing
+ precisely two values.
Returns
-------
- off, scl : scalars
- The map `=``off + scl*x`` maps the first domain to the second.
+ offset, scale : scalars
+ The map ``L(x) = offset + scale*x`` maps the first domain to the
+ second.
See Also
--------
getdomain, mapdomain
+ Notes
+ -----
+ Also works for complex numbers, and thus can be used to calculate the
+ parameters required to map any line in the complex plane to any other
+ line therein.
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> P.mapparms((-1,1),(-1,1))
+ (0.0, 1.0)
+ >>> P.mapparms((1,-1),(-1,1))
+ (0.0, -1.0)
+ >>> i = complex(0,1)
+ >>> P.mapparms((-i,-1),(1,i))
+ ((1+1j), (1+0j))
+
"""
oldlen = old[1] - old[0]
newlen = new[1] - new[0]
@@ -254,30 +327,66 @@ def mapparms(old, new) :
return off, scl
def mapdomain(x, old, new) :
- """Apply linear map to input points.
-
- The linear map of the form ``off + scl*x`` that takes the `old` domain
- to the `new` domain is applied to the points `x`.
+ """
+ Apply linear map to input points.
+
+ The linear map ``offset + scale*x`` that maps `old` to `new` is applied
+ to the points `x`.
Parameters
----------
x : array_like
- Points to be mapped
+ Points to be mapped.
old, new : array_like
- The two domains that determin the map. They should both convert as
- 1D arrays containing two values.
-
+ The two domains that determine the map. Each must (successfully)
+ convert to 1-d arrays containing precisely two values.
Returns
-------
- new_x : ndarray
- Array of points of the same shape as the input `x` after the linear
- map defined by the two domains is applied.
+ x_out : ndarray
+ Array of points of the same shape as `x`, after application of the
+ linear map between the two domains.
See Also
--------
getdomain, mapparms
+ Notes
+ -----
+ Effectively, this implements:
+
+ .. math ::
+ x\\_out = new[0] + m(x - old[0])
+
+ where
+
+ .. math ::
+ m = \\frac{new[1]-new[0]}{old[1]-old[0]}
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> old_domain = (-1,1)
+ >>> new_domain = (0,2*np.pi)
+ >>> x = np.linspace(-1,1,6); x
+ array([-1. , -0.6, -0.2, 0.2, 0.6, 1. ])
+ >>> x_out = P.mapdomain(x, old_domain, new_domain); x_out
+ array([ 0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825,
+ 6.28318531])
+ >>> x - P.mapdomain(x_out, new_domain, old_domain)
+ array([ 0., 0., 0., 0., 0., 0.])
+
+ Also works for complex numbers (and thus can be used to map any line in
+ the complex plane to any other line therein).
+
+ >>> i = complex(0,1)
+ >>> old = (-1 - i, 1 + i)
+ >>> new = (-1 + i, 1 - i)
+ >>> z = np.linspace(old[0], old[1], 6); z
+ array([-1.0-1.j , -0.6-0.6j, -0.2-0.2j, 0.2+0.2j, 0.6+0.6j, 1.0+1.j ])
+ >>> new_z = P.mapdomain(z, old, new); new_z
+ array([-1.0+1.j , -0.6+0.6j, -0.2+0.2j, 0.2-0.2j, 0.6-0.6j, 1.0-1.j ])
+
"""
[x] = as_series([x], trim=False)
off, scl = mapparms(old, new)