# [Numpy-svn] r8127 - in trunk/numpy: doc lib linalg ma polynomial testing

numpy-svn@scip... numpy-svn@scip...
Wed Feb 17 17:53:04 CST 2010

Author: jarrod.millman
Date: 2010-02-17 17:53:04 -0600 (Wed, 17 Feb 2010)
New Revision: 8127

Modified:
trunk/numpy/doc/basics.py
trunk/numpy/doc/creation.py
trunk/numpy/doc/indexing.py
trunk/numpy/doc/misc.py
trunk/numpy/doc/ufuncs.py
trunk/numpy/lib/financial.py
trunk/numpy/lib/function_base.py
trunk/numpy/lib/io.py
trunk/numpy/lib/shape_base.py
trunk/numpy/linalg/linalg.py
trunk/numpy/ma/core.py
trunk/numpy/polynomial/__init__.py
trunk/numpy/polynomial/chebyshev.py
trunk/numpy/polynomial/polynomial.py
trunk/numpy/polynomial/polytemplate.py
trunk/numpy/polynomial/polyutils.py
trunk/numpy/testing/utils.py
Log:
more docstring updates from pydoc website (thanks to everyone who contributed!)

Modified: trunk/numpy/doc/basics.py
===================================================================
--- trunk/numpy/doc/basics.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/doc/basics.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -44,7 +44,7 @@
the dtypes are available as np.bool, np.float32, etc.

Advanced types, not listed in the table above, are explored in
-section link_here.
+section :ref:structured_arrays.

There are 5 basic numerical types representing booleans (bool), integers (int),
unsigned integers (uint) floating point (float) and complex. Those with numbers
@@ -98,8 +98,8 @@
dtype('uint8')

dtype objects also contain information about the type, such as its bit-width
-and its byte-order. See xxx for details.  The data type can also be used
-indirectly to query properties of the type, such as whether it is an integer::
+and its byte-order.  The data type can also be used indirectly to query
+properties of the type, such as whether it is an integer::

>>> d = np.dtype(int)
>>> d

Modified: trunk/numpy/doc/creation.py
===================================================================
--- trunk/numpy/doc/creation.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/doc/creation.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -9,7 +9,8 @@
There are 5 general mechanisms for creating arrays:

1) Conversion from other Python structures (e.g., lists, tuples)
-2) Intrinsic numpy array array creation objects (e.g., arange, ones, zeros, etc.)
+2) Intrinsic numpy array array creation objects (e.g., arange, ones, zeros,
+   etc.)
3) Reading arrays from disk, either from standard or custom formats
4) Creating arrays from raw bytes through the use of strings or buffers
5) Use of special library functions (e.g., random)
@@ -22,17 +23,19 @@
====================================================

In general, numerical data arranged in an array-like structure in Python can
-be converted to arrays through the use of the array() function. The most obvious
-examples are lists and tuples. See the documentation for array() for details for
-its use. Some objects may support the array-protocol and allow conversion to arrays
-this way. A simple way to find out if the object can be converted to a numpy array
-using array() is simply to try it interactively and see if it works! (The Python Way).
+be converted to arrays through the use of the array() function. The most
+obvious examples are lists and tuples. See the documentation for array() for
+details for its use. Some objects may support the array-protocol and allow
+conversion to arrays this way. A simple way to find out if the object can be
+converted to a numpy array using array() is simply to try it interactively and
+see if it works! (The Python Way).

Examples: ::

>>> x = np.array([2,3,1,0])
>>> x = np.array([2, 3, 1, 0])
- >>> x = np.array([[1,2.0],[0,0],(1+1j,3.)]) # note mix of tuple and lists, and types
+ >>> x = np.array([[1,2.0],[0,0],(1+1j,3.)]) # note mix of tuple and lists,
+     and types
>>> x = np.array([[ 1.+0.j, 2.+0.j], [ 0.+0.j, 0.+0.j], [ 1.+1.j, 3.+0.j]])

Intrinsic Numpy Array Creation
@@ -102,7 +105,6 @@

HDF5: PyTables
FITS: PyFITS
- Others? xxx

Examples of formats that cannot be read directly but for which it is not hard
to convert are libraries like PIL (able to read and write many image formats
@@ -125,9 +127,9 @@
simple format then one can write a simple I/O library and use the numpy
fromfile() function and .tofile() method to read and write numpy arrays
directly (mind your byteorder though!) If a good C or C++ library exists that
-read the data, one can wrap that library with a variety of techniques (see
-xxx) though that certainly is much more work and requires significantly more
-advanced knowledge to interface with C or C++.
+read the data, one can wrap that library with a variety of techniques though
+that certainly is much more work and requires significantly more advanced
+knowledge to interface with C or C++.

Use of Special Libraries
------------------------
@@ -136,6 +138,6 @@
and it isn't possible to enumerate all of them. The most common uses are use
of the many array generation functions in random that can generate arrays of
random values, and some utility functions to generate special matrices (e.g.
-diagonal)
+diagonal).

"""

Modified: trunk/numpy/doc/indexing.py
===================================================================
--- trunk/numpy/doc/indexing.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/doc/indexing.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -14,10 +14,10 @@
Assignment vs referencing
=========================

-Most of the following examples show the use of indexing when referencing
-data in an array. The examples work just as well when assigning to an
-array. See the section at the end for specific examples and explanations
-on how assignments work.
+Most of the following examples show the use of indexing when
+referencing data in an array. The examples work just as well
+when assigning to an array. See the section at the end for
+specific examples and explanations on how assignments work.

Single element indexing
=======================
@@ -48,39 +48,38 @@
>>> x[0]
array([0, 1, 2, 3, 4])

-That is, each index specified selects the array corresponding to the rest
-of the dimensions selected. In the above example, choosing 0 means that
-remaining dimension of lenth 5 is being left unspecified, and that what
-is returned is an array of that dimensionality and size. It must be noted
-that the returned array is not a copy of the original, but points to the
-same values in memory as does the original array (a new view of the same
-data in other words, see xxx for details). In this case,
-the 1-D array at the first position (0) is returned. So using a single
-index on the returned array, results in a single element being returned.
-That is: ::
+That is, each index specified selects the array corresponding to the
+rest of the dimensions selected. In the above example, choosing 0
+means that remaining dimension of lenth 5 is being left unspecified,
+and that what is returned is an array of that dimensionality and size.
+It must be noted that the returned array is not a copy of the original,
+but points to the same values in memory as does the original array.
+In  this case, the 1-D array at the first position (0) is returned.
+So using a single index on the returned array, results in a single
+element being returned. That is: ::

>>> x[0][2]
2

-So note that x[0,2] = x[0][2] though the second case is more inefficient
-a new temporary array is created after the first index that is subsequently
-indexed by 2.
+So note that x[0,2] = x[0][2] though the second case is more
+inefficient a new temporary array is created after the first index
+that is subsequently indexed by 2.

-Note to those used to IDL or Fortran memory order as it relates to indexing.
-Numpy uses C-order indexing. That means that the last index usually (see
-xxx for exceptions) represents the most rapidly changing memory location,
-unlike Fortran or IDL, where the first index represents the most rapidly
-changing location in memory. This difference represents a great potential
-for confusion.
+Note to those used to IDL or Fortran memory order as it relates to
+indexing.  Numpy uses C-order indexing. That means that the last
+index usually represents the most rapidly changing memory location,
+unlike Fortran or IDL, where the first index represents the most
+rapidly changing location in memory. This difference represents a
+great potential for confusion.

Other indexing options
======================

-It is possible to slice and stride arrays to extract arrays of the same
-number of dimensions, but of different sizes than the original. The slicing
-and striding works exactly the same way it does for lists and tuples except
-that they can be applied to multiple dimensions as well. A few
-examples illustrates best: ::
+It is possible to slice and stride arrays to extract arrays of the
+same number of dimensions, but of different sizes than the original.
+The slicing and striding works exactly the same way it does for lists
+and tuples except that they can be applied to multiple dimensions as
+well. A few examples illustrates best: ::

>>> x = np.arange(10)
>>> x[2:5]
@@ -95,35 +94,34 @@
[21, 24, 27]])

Note that slices of arrays do not copy the internal array data but
-also produce new views of the original data (see xxx for more
-explanation of this issue).
+also produce new views of the original data.

It is possible to index arrays with other arrays for the purposes of
-selecting lists of values out of arrays into new arrays. There are two
-different ways of accomplishing this. One uses one or more arrays of
-index values (see xxx for details). The other involves giving a boolean
-array of the proper shape to indicate the values to be selected.
-Index arrays are a very powerful tool that allow one to avoid looping
-over individual elements in arrays and thus greatly improve performance
-(see xxx for examples)
+selecting lists of values out of arrays into new arrays. There are
+two different ways of accomplishing this. One uses one or more arrays
+of index values. The other involves giving a boolean array of the proper
+shape to indicate the values to be selected. Index arrays are a very
+powerful tool that allow one to avoid looping over individual elements in
+arrays and thus greatly improve performance.

It is possible to use special features to effectively increase the
number of dimensions in an array through indexing so the resulting
array aquires the shape needed for use in an expression or with a
-specific function. See xxx.
+specific function.

Index arrays
============

-Numpy arrays may be indexed with other arrays (or any other sequence-like
-object that can be converted to an array, such as lists, with the exception
-of tuples; see the end of this document for why this is). The use of index
-arrays ranges from simple, straightforward cases to complex, hard-to-understand
-cases. For all cases of index arrays, what is returned is a copy of the
-original data, not a view as one gets for slices.
+Numpy arrays may be indexed with other arrays (or any other sequence-
+like object that can be converted to an array, such as lists, with the
+exception of tuples; see the end of this document for why this is). The
+use of index arrays ranges from simple, straightforward cases to
+complex, hard-to-understand cases. For all cases of index arrays, what
+is returned is a copy of the original data, not a view as one gets for
+slices.

-Index arrays must be of integer type. Each value in the array indicates which
-value in the array to use in place of the index. To illustrate: ::
+Index arrays must be of integer type. Each value in the array indicates
+which value in the array to use in place of the index. To illustrate: ::

>>> x = np.arange(10,1,-1)
>>> x
@@ -132,11 +130,12 @@
array([7, 7, 9, 2])

-The index array consisting of the values 3, 3, 1 and 8 correspondingly create
-an array of length 4 (same as the index array) where each index is replaced by
-the value the index array has in the array being indexed.
+The index array consisting of the values 3, 3, 1 and 8 correspondingly
+create an array of length 4 (same as the index array) where each index
+is replaced by the value the index array has in the array being indexed.

-Negative values are permitted and work as they do with single indices or slices: ::
+Negative values are permitted and work as they do with single indices
+or slices: ::

>>> x[np.array([3,3,-3,8])]
array([7, 7, 4, 2])
@@ -146,9 +145,10 @@
>>> x[np.array([3, 3, 20, 8])]
<type 'exceptions.IndexError'>: index 20 out of bounds 0<=index<9

-Generally speaking, what is returned when index arrays are used is an array with
-the same shape as the index array, but with the type and values of the array being
-indexed. As an example, we can use a multidimensional index array instead: ::
+Generally speaking, what is returned when index arrays are used is
+an array with the same shape as the index array, but with the type
+and values of the array being indexed. As an example, we can use a

>>> x[np.array([[1,1],[2,3]])]
array([[9, 9],
@@ -157,77 +157,85 @@
Indexing Multi-dimensional arrays
=================================

-Things become more complex when multidimensional arrays are indexed, particularly
-with multidimensional index arrays. These tend to be more unusal uses, but they
-are permitted, and they are useful for some problems. We'll  start with the
-simplest multidimensional case (using the array y from the previous examples): ::
+Things become more complex when multidimensional arrays are indexed,
+particularly with multidimensional index arrays. These tend to be
+more unusal uses, but theyare permitted, and they are useful for some
+the array y from the previous examples): ::

>>> y[np.array([0,2,4]), np.array([0,1,2])]
array([ 0, 15, 30])

-In this case, if the index arrays have a matching shape, and there is an index
-array for each dimension of the array being indexed, the resultant array has the
-same shape as the index arrays, and the values correspond to the index set for each
-position in the index arrays. In this example, the first index value is 0 for both
-index arrays, and thus the first value of the resultant array is y[0,0]. The next
-value is y[2,1], and the last is y[4,2].
+In this case, if the index arrays have a matching shape, and there is
+an index array for each dimension of the array being indexed, the
+resultant array has the same shape as the index arrays, and the values
+correspond to the index set for each position in the index arrays. In
+this example, the first index value is 0 for both index arrays, and
+thus the first value of the resultant array is y[0,0]. The next value
+is y[2,1], and the last is y[4,2].

-If the index arrays do not have the same shape, there is an attempt to broadcast
-them to the same shape. Broadcasting won't be discussed here but is discussed in
-detail in xxx. If they cannot be broadcast to the same shape, an exception is
-raised: ::
+If the index arrays do not have the same shape, there is an attempt to
+broadcast them to the same shape.  If they cannot be broadcast to the
+same shape, an exception is raised: ::

>>> y[np.array([0,2,4]), np.array([0,1])]
- <type 'exceptions.ValueError'>: shape mismatch: objects cannot be broadcast to a single shape
+ <type 'exceptions.ValueError'>: shape mismatch: objects cannot be
+ broadcast to a single shape

-The broadcasting mechanism permits index arrays to be combined with scalars for
-other indices. The effect is that the scalar value is used for all the corresponding
-values of the index arrays: ::
+The broadcasting mechanism permits index arrays to be combined with
+scalars for other indices. The effect is that the scalar value is used
+for all the corresponding values of the index arrays: ::

>>> y[np.array([0,2,4]), 1]
array([ 1, 15, 29])

-Jumping to the next level of complexity, it is possible to only partially index an array
-with index arrays. It takes a bit of thought to understand what happens in such cases.
-For example if we just use one index array with y: ::
+Jumping to the next level of complexity, it is possible to only
+partially index an array with index arrays. It takes a bit of thought
+to understand what happens in such cases. For example if we just use
+one index array with y: ::

>>> y[np.array([0,2,4])]
array([[ 0,  1,  2,  3,  4,  5,  6],
[14, 15, 16, 17, 18, 19, 20],
[28, 29, 30, 31, 32, 33, 34]])

-What results is the construction of a new array where each value of the index array
-selects one row from the array being indexed and the resultant array has the resulting
-shape (size of row, number index elements).
+What results is the construction of a new array where each value of
+the index array selects one row from the array being indexed and the
+resultant array has the resulting shape (size of row, number index
+elements).

-An example of where this may be useful is for a color lookup table where we want to map
-the values of an image into RGB triples for display. The lookup table could have a shape
-(nlookup, 3). Indexing such an array with an image with shape (ny, nx) with dtype=np.uint8
-(or any integer type so long as values are with the bounds of the lookup table) will
-result in an array of shape (ny, nx, 3) where a triple of RGB values is associated with
-each pixel location.
+An example of where this may be useful is for a color lookup table
+where we want to map the values of an image into RGB triples for
+display. The lookup table could have a shape (nlookup, 3). Indexing
+such an array with an image with shape (ny, nx) with dtype=np.uint8
+(or any integer type so long as values are with the bounds of the
+lookup table) will result in an array of shape (ny, nx, 3) where a
+triple of RGB values is associated with each pixel location.

-In general, the shape of the resulant array will be the concatenation of the shape of
-the index array (or the shape that all the index arrays were broadcast to) with the
-shape of any unused dimensions (those not indexed) in the array being indexed.
+In general, the shape of the resulant array will be the concatenation
+of the shape of the index array (or the shape that all the index arrays
+were broadcast to) with the shape of any unused dimensions (those not
+indexed) in the array being indexed.

==============================

-Boolean arrays used as indices are treated in a different manner entirely than index
-arrays. Boolean arrays must be of the same shape as the array being indexed, or
-broadcastable to the same shape. In the most straightforward case, the boolean array
-has the same shape: ::
+Boolean arrays used as indices are treated in a different manner
+entirely than index arrays. Boolean arrays must be of the same shape
+as the array being indexed, or broadcastable to the same shape. In the
+most straightforward case, the boolean array has the same shape: ::

>>> b = y>20
>>> y[b]
array([21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34])

-The result is a 1-D array containing all the elements in the indexed array corresponding
-to all the true elements in the boolean array. As with index arrays, what is returned
-is a copy of the data, not a view as one gets with slices.
+The result is a 1-D array containing all the elements in the indexed
+array corresponding to all the true elements in the boolean array. As
+with index arrays, what is returned is a copy of the data, not a view
+as one gets with slices.

-With broadcasting, multidimesional arrays may be the result. For example: ::
+With broadcasting, multidimensional arrays may be the result. For
+example: ::

>>> b[:,5] # use a 1-D boolean that broadcasts with y
array([False, False, False,  True,  True], dtype=bool)
@@ -235,8 +243,8 @@
array([[21, 22, 23, 24, 25, 26, 27],
[28, 29, 30, 31, 32, 33, 34]])

-Here the 4th and 5th rows are selected from the indexed array and combined to make a
-2-D array.
+Here the 4th and 5th rows are selected from the indexed array and
+combined to make a 2-D array.

Combining index arrays with slices
==================================
@@ -248,8 +256,9 @@
[15, 16],
[29, 30]])

-In effect, the slice is converted to an index array np.array([[1,2]]) (shape (1,2)) that is
-broadcast with the index array to produce a resultant array of shape (3,2).
+In effect, the slice is converted to an index array
+np.array([[1,2]]) (shape (1,2)) that is broadcast with the index array
+to produce a resultant array of shape (3,2).

Likewise, slicing can be combined with broadcasted boolean indices: ::

@@ -322,7 +331,8 @@
>>> x[1]
1
>>> x[1] = 1.2j
- <type 'exceptions.TypeError'>: can't convert complex to long; use long(abs(z))
+ <type 'exceptions.TypeError'>: can't convert complex to long; use
+ long(abs(z))

Unlike some of the references (such as array and mask indices)
@@ -331,7 +341,12 @@
actions may not work as one may naively expect. This particular
example is often surprising to people: ::

+ >>> x = np.arange(0, 50, 10)
+ >>> x
+ array([ 0, 10, 20, 30, 40])
>>> x[np.array([1, 1, 3, 1])] += 1
+ >>> x
+ array([ 0, 11, 20, 31, 40])

Where people expect that the 1st location will be incremented by 3.
In fact, it will only be incremented by 1. The reason is because
@@ -367,7 +382,8 @@
>>> z[indices]
array([39, 40])

-Likewise, ellipsis can be specified by code by using the Ellipsis object: ::
+Likewise, ellipsis can be specified by code by using the Ellipsis
+object: ::

>>> indices = (1, Ellipsis, 1) # same as [1,...,1]
>>> z[indices]
@@ -376,10 +392,11 @@
[46, 49, 52]])

For this reason it is possible to use the output from the np.where()
-function directly as an index since it always returns a tuple of index arrays.
+function directly as an index since it always returns a tuple of index
+arrays.

-Because the special treatment of tuples, they are not automatically converted
-to an array as a list would be. As an example: ::
+Because the special treatment of tuples, they are not automatically
+converted to an array as a list would be. As an example: ::

>>> z[[1,1,1,1]] # produces a large array
array([[[[27, 28, 29],

Modified: trunk/numpy/doc/misc.py
===================================================================
--- trunk/numpy/doc/misc.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/doc/misc.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -30,8 +30,8 @@
isfinite(): True if not nan or inf
nan_to_num(): Map nan to 0, inf to max float, -inf to min float

-The following corresponds to the usual functions except that nans are excluded from
-the results: ::
+The following corresponds to the usual functions except that nans are excluded
+from the results: ::

nansum()
nanmax()
@@ -160,7 +160,8 @@

- Minuses:

-   - can't use for writing code to be turned into C extensions, only a wrapper tool.
+   - can't use for writing code to be turned into C extensions, only a wrapper
+     tool.

5) SWIG (automatic wrapper generator)

@@ -174,11 +175,11 @@
- Minuses:

- generates lots of code between Python and the C code
-
-     - can cause performance problems that are nearly impossible to optimize out
-
+   - can cause performance problems that are nearly impossible to optimize
+       out
- interface files can be hard to write
-   - doesn't necessarily avoid reference counting issues or needing to know API's
+   - doesn't necessarily avoid reference counting issues or needing to know
+     API's

7) Weave

@@ -187,8 +188,8 @@
- Phenomenal tool
- can turn many numpy expressions into C code
-   - can embed pure C code in Python module and have weave extract, generate interfaces
-     and compile, etc.
+   - can embed pure C code in Python module and have weave extract, generate
+     interfaces and compile, etc.

- Minuses:

@@ -198,7 +199,8 @@

- Plusses:

-   - Turns pure python into efficient machine code through jit-like optimizations
+   - Turns pure python into efficient machine code through jit-like
+     optimizations
- very fast when it optimizes well

- Minuses:
@@ -208,15 +210,15 @@

Interfacing to Fortran:
-----------------------
-Fortran: Clear choice is f2py. (Pyfort is an older alternative, but not supported
-any longer)
+Fortran: Clear choice is f2py. (Pyfort is an older alternative, but not
+supported any longer)

Interfacing to C++:
-------------------
-1) CXX
-2) Boost.python
-3) SWIG
-4) Sage has used cython to wrap C++ (not pretty, but it can be done)
-5) SIP (used mainly in PyQT)
+ 1) CXX
+ 2) Boost.python
+ 3) SWIG
+ 4) Sage has used cython to wrap C++ (not pretty, but it can be done)
+ 5) SIP (used mainly in PyQT)

"""

Modified: trunk/numpy/doc/ufuncs.py
===================================================================
--- trunk/numpy/doc/ufuncs.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/doc/ufuncs.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -13,12 +13,11 @@
>>> np.array([0,2,3,4]) + np.array([1,1,-1,2])
array([1, 3, 2, 6])

-The unfunc module lists all the available ufuncs in numpy. Additional ufuncts
-available in xxx in scipy. Documentation on the specific ufuncs may be found
-in those modules. This documentation is intended to address the more general
-aspects of unfuncs common to most of them. All of the ufuncs that make use of
-Python operators (e.g., +, -, etc.) have equivalent functions defined
+The unfunc module lists all the available ufuncs in numpy. Documentation on
+the specific ufuncs may be found in those modules. This documentation is
+intended to address the more general aspects of unfuncs common to most of
+them. All of the ufuncs that make use of Python operators (e.g., +, -, etc.)
+have equivalent functions defined (e.g. add() for +)

Type coercion
=============
@@ -58,10 +57,10 @@
ufunc methods
=============

-Binary ufuncs support 4 methods. These methods are explained in detail in xxx
-(or are they, I don't see anything in the ufunc docstring that is useful?).
+Binary ufuncs support 4 methods.

-**.reduce(arr)** applies the binary operator to elements of the array in sequence. For example: ::
+**.reduce(arr)** applies the binary operator to elements of the array in
+  sequence. For example: ::

45
@@ -76,22 +75,25 @@
array([10, 35])

-**.accumulate(arr)** applies the binary operator and generates an an equivalently
-shaped array that includes the accumulated amount for each element of the
-array. A couple examples: ::
+**.accumulate(arr)** applies the binary operator and generates an an
+equivalently shaped array that includes the accumulated amount for each
+element of the array. A couple examples: ::

array([ 0,  1,  3,  6, 10, 15, 21, 28, 36, 45])
>>> np.multiply.accumulate(np.arange(1,9))
array([    1,     2,     6,    24,   120,   720,  5040, 40320])

-The behavior for multidimensional arrays is the same as for .reduce(), as is the use of the axis keyword).
+The behavior for multidimensional arrays is the same as for .reduce(),
+as is the use of the axis keyword).

-**.reduceat(arr,indices)** allows one to apply reduce to selected parts of an array.
-It is a difficult method to understand. See the documentation at:
+**.reduceat(arr,indices)** allows one to apply reduce to selected parts
+  of an array. It is a difficult method to understand. See the documentation
+  at:

-**.outer(arr1,arr2)** generates an outer operation on the two arrays arr1 and arr2. It will work on multidimensional arrays (the shape of the result is the
-concatenation of the two input shapes.: ::
+**.outer(arr1,arr2)** generates an outer operation on the two arrays arr1 and
+  arr2. It will work on multidimensional arrays (the shape of the result is
+  the concatenation of the two input shapes.: ::

>>> np.multiply.outer(np.arange(3),np.arange(4))
array([[0, 0, 0, 0],
@@ -101,14 +103,14 @@
Output arguments
================

-All ufuncs accept an optional output array. The array must be of the expected output shape. Beware that if the type of the output array is of a
-different (and lower) type than the output result, the results may be silently
-truncated or otherwise corrupted in the downcast to the lower type. This usage
-is useful when one wants to avoid creating large temporary arrays and instead
-allows one to reuse the same array memory repeatedly (at the expense of not
-being able to use more convenient operator notation in expressions). Note that
-when the output argument is used, the ufunc still returns a reference to the
-result.
+All ufuncs accept an optional output array. The array must be of the expected
+output shape. Beware that if the type of the output array is of a different
+(and lower) type than the output result, the results may be silently truncated
+or otherwise corrupted in the downcast to the lower type. This usage is useful
+when one wants to avoid creating large temporary arrays and instead allows one
+to reuse the same array memory repeatedly (at the expense of not being able to
+use more convenient operator notation in expressions). Note that when the
+output argument is used, the ufunc still returns a reference to the result.

>>> x = np.arange(2)

Modified: trunk/numpy/lib/financial.py
===================================================================
--- trunk/numpy/lib/financial.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/lib/financial.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -206,7 +206,7 @@

def nper(rate, pmt, pv, fv=0, when='end'):
"""
-    Compute the number of periods.
+    Compute the number of periodic payments.

Parameters
----------
@@ -225,16 +225,16 @@
-----
The number of periods nper is computed by solving the equation::

-      fv + pv*(1+rate)**nper + pmt*(1+rate*when)/rate * ((1+rate)**nper - 1) == 0
+     fv + pv*(1+rate)**nper + pmt*(1+rate*when)/rate*((1+rate)**nper-1) = 0

-    or, when rate == 0::
+    but if rate = 0 then::

-      fv + pv + pmt * nper == 0
+     fv + pv + pmt*nper = 0

Examples
--------
-    If you only had $150 to spend as payment, how long would it take to pay-off - a loan of$8,000 at 7% annual interest?
+    If you only had $150/month to pay towards the loan, how long would it take + to pay-off a loan of$8,000 at 7% annual interest?

>>> np.nper(0.07/12, -150, 8000)
64.073348770661852
@@ -244,11 +244,13 @@
The same analysis could be done with several different interest rates
and/or payments and/or total amounts to produce an entire table.

-    >>> np.nper(*(np.ogrid[0.06/12:0.071/12:0.01/12, -200:-99:100, 6000:7001:1000]))
-    array([[[ 32.58497782,  38.57048452],
-            [ 71.51317802,  86.37179563]],
-           [[ 33.07413144,  39.26244268],
-            [ 74.06368256,  90.22989997]]])
+    >>> np.nper(*(np.ogrid[0.07/12: 0.08/12: 0.01/12,
+    ...                    -150   : -99     : 50    ,
+    ...                    8000   : 9001    : 1000]))
+    array([[[  64.07334877,   74.06368256],
+            [ 108.07548412,  127.99022654]],
+           [[  66.12443902,   76.87897353],
+            [ 114.70165583,  137.90124779]]])

"""
when = _convert_when(when)

Modified: trunk/numpy/lib/function_base.py
===================================================================
--- trunk/numpy/lib/function_base.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/lib/function_base.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -1366,25 +1366,21 @@

def nanmin(a, axis=None):
"""
-    Return the minimum of array elements over the given axis ignoring any NaNs.
+    Return the minimum of an array or minimum along an axis ignoring any NaNs.

Parameters
----------
a : array_like
-        Array containing numbers whose sum is desired. If a is not
-        an array, a conversion is attempted.
+        Array containing numbers whose minimum is desired.
axis : int, optional
Axis along which the minimum is computed.The default is to compute
the minimum of the flattened array.

Returns
-------
-    y : {ndarray, scalar}
-        An array with the same shape as a, with the specified axis removed.
-        If a is a 0-d array, or if axis is None, a scalar is returned. The
-        the same dtype as a is returned.
+    nanmin : ndarray
+        A new array or a scalar array with the result.

-
--------
numpy.amin : Minimum across array including any Not a Numbers.
@@ -1461,7 +1457,7 @@

def nanmax(a, axis=None):
"""
-    Return the maximum of array elements over the given axis ignoring any NaNs.
+    Return the maximum of an array or maximum along an axis ignoring any NaNs.

Parameters
----------
@@ -1469,15 +1465,15 @@
Array containing numbers whose maximum is desired. If a is not
an array, a conversion is attempted.
axis : int, optional
-        Axis along which the maximum is computed.The default is to compute
+        Axis along which the maximum is computed. The default is to compute
the maximum of the flattened array.

Returns
-------
-    y : ndarray
+    nanmax : ndarray
An array with the same shape as a, with the specified axis removed.
-        If a is a 0-d array, or if axis is None, a scalar is returned. The
-        the same dtype as a is returned.
+        If a is a 0-d array, or if axis is None, a ndarray scalar is
+        returned.  The the same dtype as a is returned.

--------

Modified: trunk/numpy/lib/io.py
===================================================================
--- trunk/numpy/lib/io.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/lib/io.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -306,9 +306,11 @@

Parameters
----------
-    file : file or string
-        File or filename to which the data is saved.  If the filename
-        does not already have a .npy extension, it is added.
+    file : file or str
+        File or filename to which the data is saved.  If file is a file-object,
+        then the filename is unchanged.  If file is a string, a .npy
+        extension will be appended to the file name if it does not already
+        have one.
arr : array_like
Array data to be saved.

@@ -329,7 +331,7 @@
>>> x = np.arange(10)
>>> np.save(outfile, x)

-    >>> outfile.seek(0) # only necessary in this example (with tempfile)
+    >>> outfile.seek(0) # Only needed here to simulate closing & reopening file
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

@@ -348,26 +350,30 @@
"""
Save several arrays into a single, compressed file in .npz format.

-    If keyword arguments are given, the names for variables assigned to the
-    keywords are the keyword names (not the variable names in the caller).
If arguments are passed in with no keywords, the corresponding variable
-    names are arr_0, arr_1, etc.
+    names, in the .npz file, are 'arr_0', 'arr_1', etc. If keyword arguments
+    are given, the corresponding variable names, in the .npz file will
+    match the keyword names.

Parameters
----------
file : str or file
Either the file name (string) or an open file (file-like object)
-        If file is a string, it names the output file.  ".npz" will be appended
-        to the file name if it is not already there.
-    args : Arguments
-        Any function arguments other than the file name are variables to save.
-        Since it is not possible for Python to know their names outside
-        savez, they will be saved with names "arr_0", "arr_1", and so on.
-        These arguments can be any expression.
-    kwds : Keyword arguments
-        All keyword=value pairs cause the value to be saved with the name of
-        the keyword.
+        where the data will be saved. If file is a string, the .npz
+        extension will be appended to the file name if it is not already there.
+    \\*args : Arguments, optional
+        Arrays to save to the file. Since it is not possible for Python to
+        know the names of the arrays outside savez, the arrays will be saved
+        with names "arr_0", "arr_1", and so on. These arguments can be any
+        expression.
+    \\*\\*kwds : Keyword arguments, optional
+        Arrays to save to the file. Arrays will be saved in the file with the
+        keyword names.

+    Returns
+    -------
+    None
+
--------
save : Save a single array to a binary file in NumPy format.
@@ -379,6 +385,11 @@
variables they contain.  Each file contains one variable in .npy
format. For a description of the .npy format, see format.

+    When opening the saved .npz file with load a NpzFile object is
+    returned. This is a dictionary-like object which can be queried for
+    its list of arrays (with the .files attribute), and for the arrays
+    themselves.
+
Examples
--------
>>> from tempfile import TemporaryFile
@@ -389,11 +400,11 @@
Using savez with \\*args, the arrays are saved with default names.

>>> np.savez(outfile, x, y)
-    >>> outfile.seek(0)  # only necessary in this example (with tempfile)
-    >>> npz.files
+    >>> outfile.seek(0) # Only needed here to simulate closing & reopening file
+    >>> npzfile.files
['arr_1', 'arr_0']
-    >>> npz['arr_0']
+    >>> npzfile['arr_0']
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Using savez with \\*\\*kwds, the arrays are saved with the keyword names.
@@ -401,10 +412,10 @@
>>> outfile = TemporaryFile()
>>> np.savez(outfile, x=x, y=y)
>>> outfile.seek(0)
-    >>> npz.files
+    >>> npzfile.files
['y', 'x']
-    >>> npz['x']
+    >>> npzfile['x']
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

"""
@@ -510,8 +521,15 @@
--------
+    genfromtxt : Load data with missing values handled as specified.

+    Notes
+    -----
+    This function aims to be a fast reader for simply formatted files. The
+    genfromtxt function provides more sophisticated handling of, e.g.,
+    lines with missing values.
+
Examples
--------
>>> from StringIO import StringIO   # StringIO behaves like a file object

Modified: trunk/numpy/lib/shape_base.py
===================================================================
--- trunk/numpy/lib/shape_base.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/lib/shape_base.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -301,7 +301,7 @@
Stack arrays in sequence depth wise (along third axis).

Takes a sequence of arrays and stack them along the third axis
-    to make a single array. Rebuilds arrays divided by dsplit.
+    to make a single array. Rebuilds arrays divided by dsplit.
This is a simple way to stack 2D arrays (images) into a single
3D array for processing.

@@ -325,7 +325,7 @@

Notes
-----
-    Equivalent to np.concatenate(tup, axis=2)
+    Equivalent to np.concatenate(tup, axis=2).

Examples
--------
@@ -420,7 +420,7 @@

If indices_or_sections is a 1-D array of sorted integers, the entries
indicate where along axis the array is split.  For example,
-        [2, 3] would, for axis = 0, result in
+        [2, 3] would, for axis=0, result in

- ary[:2]
- ary[2:3]
@@ -483,8 +483,8 @@
"""
Split an array into multiple sub-arrays horizontally (column-wise).

-    Please refer to the split documentation.  hsplit is equivalent
-    to split with axis=1, the array is always split along the second
+    Please refer to the split documentation.  hsplit is equivalent
+    to split with axis=1, the array is always split along the second
axis regardless of the array dimension.

@@ -596,8 +596,8 @@
"""
Split array into multiple sub-arrays along the 3rd axis (depth).

-    Please refer to the split documentation.  dsplit is equivalent
-    to split with axis=2, the array is always split along the third
+    Please refer to the split documentation.  dsplit is equivalent
+    to split with axis=2, the array is always split along the third
axis provided the array dimension is greater than or equal to 3.

Modified: trunk/numpy/linalg/linalg.py
===================================================================
--- trunk/numpy/linalg/linalg.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/linalg/linalg.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -1175,34 +1175,38 @@
"""
Singular Value Decomposition.

-    Factors the matrix a into u * np.diag(s) * v.H, where u and v
-    are unitary (i.e., u.H = inv(u) and similarly for v), .H is the
-    conjugate transpose operator (which is the ordinary transpose for
-    real-valued matrices), and s is a 1-D array of a's singular values.
+    Factors the matrix a into u * np.diag(s) * v, where u and
+    v are unitary (i.e., u.H = inv(u) and similarly for v) and
+    s is a 1-D array of a's singular values.  Note that, in the
+    literature, it is common to see this decomposition expressed as (in
+    NumPy notation) a = u * np.diag(s) * v.H, whereas the v this
+    function returns is such that a would be reconstructed as above; in
+    other words, "our" v is the Hermitian (conjugate transpose) of that
+    commonly seen in the literature.

Parameters
----------
a : array_like
Matrix of shape (M, N) to decompose.
full_matrices : bool, optional
-        If True (default), u and v.H have the shapes
-        (M, M) and (N, N), respectively.  Otherwise, the shapes
-        are (M, K) and (K, N), resp., where K = min(M, N).
+        If True (default), u and v have the shapes (M, M)
+        and (N, N), respectively.  Otherwise, the shapes are (M, K)
+        and (K, N), resp., where K = min(M, N).
compute_uv : bool, optional
-        Whether or not to compute u and v.H in addition to s.
+        Whether or not to compute u and v in addition to s.
True by default.

Returns
-------
u : ndarray
-        Unitary matrix. The shape of U is (M, M) or (M, K)
-        depending on value of full_matrices.
+        Unitary matrix. The shape of U is (M, M) or (M, K)
+        depending on value of full_matrices.
s : ndarray
The singular values, sorted so that s[i] >= s[i+1].
-        S is a 1-D array of length min(M, N)
-    v.H : ndarray
+        S is a 1-D array of length min(M, N)
+    v : ndarray
Unitary matrix of shape (N, N) or (K, N), depending
-        on full_matrices.
+        on full_matrices.

Raises
------
@@ -1211,21 +1215,21 @@

Notes
-----
-    If a is a matrix object (as opposed to an ndarray), then so are all
-    the return values.
+    If a is a matrix object (as opposed to an ndarray), then so are
+    all the return values.

Examples
--------
>>> a = np.random.randn(9, 6) + 1j*np.random.randn(9, 6)
-    >>> U, s, Vh = np.linalg.svd(a)
-    >>> U.shape, Vh.shape, s.shape
+    >>> U, s, V = np.linalg.svd(a)
+    >>> U.shape, V.shape, s.shape
((9, 9), (6, 6), (6,))

-    >>> U, s, Vh = np.linalg.svd(a, full_matrices=False)
-    >>> U.shape, Vh.shape, s.shape
+    >>> U, s, V = np.linalg.svd(a, full_matrices=False)
+    >>> U.shape, V.shape, s.shape
((9, 6), (6, 6), (6,))
>>> S = np.diag(s)
-    >>> np.allclose(a, np.dot(U, np.dot(S, Vh)))
+    >>> np.allclose(a, np.dot(U, np.dot(S, V)))
True

>>> s2 = np.linalg.svd(a, compute_uv=False)

Modified: trunk/numpy/ma/core.py
===================================================================
--- trunk/numpy/ma/core.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/ma/core.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -545,6 +545,10 @@
a : ndarray
The filled array.

+    --------
+    compressed
+
Examples
--------
>>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],

Modified: trunk/numpy/polynomial/__init__.py
===================================================================
--- trunk/numpy/polynomial/__init__.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/polynomial/__init__.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -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 *

Modified: trunk/numpy/polynomial/chebyshev.py
===================================================================
--- trunk/numpy/polynomial/chebyshev.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/polynomial/chebyshev.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -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
----------
-- 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.

+--------
+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,9 +63,15 @@
.. 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 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 @@
--------
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 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.

--------
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,20 +430,34 @@
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.
+
--------
-    series : 1d ndarray
-        The Chebyshev series representation of off + scl*x.
+    polyline

+    Examples
+    --------
+    >>> 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 :
return np.array([off,scl])
@@ -394,26 +465,56 @@
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).

--------
-    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 :
return np.ones(1)
@@ -427,27 +528,43 @@

-    """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.

--------
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)
+    array([ 4.,  4.,  4.])
+
"""
# c1, c2 are trimmed copies
[c1, c2] = pu.as_series([c1, c2])
@@ -461,29 +578,44 @@

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.

--------

+    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 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.

--------

+    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 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.

--------

+    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 @@
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 @@
--------
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 chebint(cs, m=1, k=[], lbnd=0, scl=1) :
-    """Integrate a Chebyshev series.
+    """
+    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.
+    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.

--------
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 @@
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 @@
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 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.

+    --------
+    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

Modified: trunk/numpy/polynomial/polynomial.py
===================================================================
--- trunk/numpy/polynomial/polynomial.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/polynomial/polynomial.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -1,44 +1,50 @@
-"""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
----------
-- 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.

+--------
+numpy.polynomial
+
"""
from __future__ import division

@@ -77,20 +83,32 @@
#

def polyline(off, scl) :
-    """Polynomial whose graph is a straight line.
+    """
+    Returns an array representing a linear polynomial.

-    The line has the formula off + scl*x
-
-    Parameters:
-    -----------
+    Parameters
+    ----------
off, scl : scalars
-        The specified line is given by off + scl*x.
+        The "y-intercept" and "slope" of the line, respectively.

-    Returns:
+    Returns
+    -------
+    y : ndarray
+        This module's representation of the linear polynomial off +
+        scl*x.
+
--------
-    series : 1d ndarray
-        The polynomial equal to off + scl*x.
+    chebline

+    Examples
+    --------
+    >>> 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 :
return np.array([off,scl])
@@ -98,26 +116,54 @@
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).

--------
-    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 :
return np.ones(1)
@@ -131,27 +177,37 @@

-    """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.

--------
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 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.

--------
@@ -188,6 +245,13 @@

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 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.

--------

+    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 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.

--------
@@ -255,6 +328,13 @@

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 @@
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.

--------
@@ -359,6 +442,16 @@

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 @@
return cs[i+1:].copy()

def polyint(cs, m=1, k=[], lbnd=0, scl=1) :
-    """Integrate a polynomial.
+    """
+    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.
+    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.

--------
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 @@
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 @@
--------
polyfit

-    Examples
-    --------
-
Notes
-----
The evaluation uses Horner's method.

-    Examples
-    --------
-
"""
# cs is a trimmed copy
[cs] = pu.as_series([cs])
@@ -529,50 +643,56 @@
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,42 +707,61 @@

Notes
-----
-    The solution are the coefficients c[i] of the polynomial P(x)
-    that minimizes the squared error
+    The solutions are the coefficients c[i] of the polynomial P(x)
+    that minimizes the total squared error:

-    E = \sum_j |y_j - P(x_j)|^2.
+    .. math :: E = \\sum_j (y_j - P(x_j))^2

-    This problem is solved by setting up as the overdetermined matrix
-    equation
+    This problem is solved by setting up the (typically) over-determined
+    matrix equation:

-    V(x)*c = y,
+    .. 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.
+    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.
+    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.

-    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.
+    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.

-    References
-    ----------
-    .. [1] Wikipedia, "Curve fitting",
-           http://en.wikipedia.org/wiki/Curve_fitting
-
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
x = np.asarray(x) + 0.0
@@ -662,24 +801,39 @@

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.

+    --------
+    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

Modified: trunk/numpy/polynomial/polytemplate.py
===================================================================
--- trunk/numpy/polynomial/polytemplate.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/polynomial/polytemplate.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -1,5 +1,13 @@
-"""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
import sys

Modified: trunk/numpy/polynomial/polyutils.py
===================================================================
--- trunk/numpy/polynomial/polyutils.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/polynomial/polyutils.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -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,30 +113,45 @@

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]
if min([a.size for a in arrays]) == 0 :
@@ -161,25 +180,48 @@

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

+    --------
+    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 :
raise ValueError("tol must be non-negative")
@@ -192,29 +234,42 @@
return c[:ind[-1] + 1].copy()

def getdomain(x) :
-    """Determine suitable domain for given points.
+    """
+    Return a domain suitable for given abscissae.

-    Find a suitable domain in which to fit a function defined at the points
-    x with a polynomial or Chebyshev series.
-
+    Find a domain suitable for a polynomial or Chebyshev series
+    defined at the values supplied.
+
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.

--------
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 @@
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.

--------
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 @@
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.

--------
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)

Modified: trunk/numpy/testing/utils.py
===================================================================
--- trunk/numpy/testing/utils.py	2010-02-17 23:42:42 UTC (rev 8126)
+++ trunk/numpy/testing/utils.py	2010-02-17 23:53:04 UTC (rev 8127)
@@ -1081,23 +1081,54 @@
assert(sys.getrefcount(i) >= rc)

def assert_array_almost_equal_nulp(x, y, nulp=1):
-    """Compare two arrays relatively to their spacing. It is a relatively
-    robust method to compare two arrays whose amplitude is variable.
+    """
+    Compare two arrays relatively to their spacing.

-    Note
-    ----
-    An assertion is raised if the following condition is not met:
+    This is a relatively robust method to compare two arrays whose amplitude
+    is variable.

+    Parameters
+    ----------
+    x, y : array_like
+        Input arrays.
+    nulp : int, optional
+        The maximum number of unit in the last place for tolerance (see Notes).
+        Default is 1.
+
+    Returns
+    -------
+    None
+
+    Raises
+    ------
+    AssertionError
+        If the spacing between x and y for one or more elements is larger
+        than nulp.
+
+    --------
+    assert_array_max_ulp : Check that all items of arrays differ in at most
+        N Units in the Last Place.
+    spacing : Return the distance between x and the nearest adjacent number.
+
+    Notes
+    -----
+    An assertion is raised if the following condition is not met::
+
abs(x - y) <= nulps * spacing(max(abs(x), abs(y)))

-    Parameters
-    ----------
-    x: array_like
-        first input array
-    y: array_like
-        second input array
-    nulp: int
-        max number of unit in the last place for tolerance (see Note)
+    Examples
+    --------
+    >>> x = np.array([1., 1e-10, 1e-20])
+    >>> eps = np.finfo(x.dtype).eps
+    >>> np.testing.assert_array_almost_equal_nulp(x, x*eps/2 + x)
+
+    >>> np.testing.assert_array_almost_equal_nulp(x, x*eps + x)
+    ------------------------------------------------------------
+    Traceback (most recent call last):
+      ...
+    AssertionError: X and Y are not equal to 1 ULP (max is 2)
+
"""
import numpy as np
ax = np.abs(x)
@@ -1112,8 +1143,41 @@
raise AssertionError(msg)

def assert_array_max_ulp(a, b, maxulp=1, dtype=None):
-    """Given two arrays a and b, check that every item differs in at most N
-    Unit in the Last Place."""
+    """
+    Check that all items of arrays differ in at most N Units in the Last Place.
+
+    Parameters
+    ----------
+    a, b : array_like
+        Input arrays to be compared.
+    maxulp : int, optional
+        The maximum number of units in the last place that elements of a and
+        b can differ. Default is 1.
+    dtype : dtype, optional
+        Data-type to convert a and b to if given. Default is None.
+
+    Returns
+    -------
+    ret : ndarray
+        Array containing number of representable floating point numbers between
+        items in a and b.
+
+    Raises
+    ------
+    AssertionError
+        If one or more elements differ by more than maxulp.
+
+    --------
+    assert_array_almost_equal_nulp : Compare two arrays relatively to their
+        spacing.
+
+    Examples
+    --------
+    >>> a = np.linspace(0., 1., 100)
+    >>> res = np.testing.assert_array_max_ulp(a, np.arcsin(np.sin(a)))
+
+    """
import numpy as np
ret = nulp_diff(a, b, dtype)
if not np.all(ret <= maxulp):
@@ -1282,11 +1346,29 @@
self._module.showwarning = self._showwarning

def assert_warns(warning_class, func, *args, **kw):
-    """Fail unless a warning of class warning_class is thrown by callable when
+    """
+    Fail unless the given callable throws the specified warning.
+
+    A warning of class warning_class should be thrown by the callable when
invoked with arguments args and keyword arguments kwargs.
-
If a different type of warning is thrown, it will not be caught, and the
test case will be deemed to have suffered an error.
+
+    Parameters
+    ----------
+    warning_class : class
+        The class defining the warning that func is expected to throw.
+    func : callable
+        The callable to test.
+    \\*args : Arguments
+        Arguments passed to func.
+    \\*\\*kwargs : Kwargs
+        Keyword arguments passed to func.
+
+    Returns
+    -------
+    None
+
"""

# XXX: once we may depend on python >= 2.6, this can be replaced by the

`