Initial commit: Masina-Dock Vehicle Management System
This commit is contained in:
commit
ae923e2c41
4999 changed files with 1607266 additions and 0 deletions
|
|
@ -0,0 +1,185 @@
|
|||
"""
|
||||
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.
|
||||
|
||||
This package provides *convenience classes* for each of six different kinds
|
||||
of polynomials:
|
||||
|
||||
======================== ================
|
||||
**Name** **Provides**
|
||||
======================== ================
|
||||
`~polynomial.Polynomial` Power series
|
||||
`~chebyshev.Chebyshev` Chebyshev series
|
||||
`~legendre.Legendre` Legendre series
|
||||
`~laguerre.Laguerre` Laguerre series
|
||||
`~hermite.Hermite` Hermite series
|
||||
`~hermite_e.HermiteE` HermiteE series
|
||||
======================== ================
|
||||
|
||||
These *convenience classes* provide a consistent interface for creating,
|
||||
manipulating, and fitting data with polynomials of different bases.
|
||||
The convenience classes are the preferred interface for the `~numpy.polynomial`
|
||||
package, and are available from the ``numpy.polynomial`` namespace.
|
||||
This eliminates the need to navigate to the corresponding submodules, e.g.
|
||||
``np.polynomial.Polynomial`` or ``np.polynomial.Chebyshev`` instead of
|
||||
``np.polynomial.polynomial.Polynomial`` or
|
||||
``np.polynomial.chebyshev.Chebyshev``, respectively.
|
||||
The classes provide a more consistent and concise interface than the
|
||||
type-specific functions defined in the submodules for each type of polynomial.
|
||||
For example, to fit a Chebyshev polynomial with degree ``1`` to data given
|
||||
by arrays ``xdata`` and ``ydata``, the
|
||||
`~chebyshev.Chebyshev.fit` class method::
|
||||
|
||||
>>> from numpy.polynomial import Chebyshev
|
||||
>>> c = Chebyshev.fit(xdata, ydata, deg=1)
|
||||
|
||||
is preferred over the `chebyshev.chebfit` function from the
|
||||
``np.polynomial.chebyshev`` module::
|
||||
|
||||
>>> from numpy.polynomial.chebyshev import chebfit
|
||||
>>> c = chebfit(xdata, ydata, deg=1)
|
||||
|
||||
See :doc:`routines.polynomials.classes` for more details.
|
||||
|
||||
Convenience Classes
|
||||
===================
|
||||
|
||||
The following lists the various constants and methods common to all of
|
||||
the classes representing the various kinds of polynomials. In the following,
|
||||
the term ``Poly`` represents any one of the convenience classes (e.g.
|
||||
`~polynomial.Polynomial`, `~chebyshev.Chebyshev`, `~hermite.Hermite`, etc.)
|
||||
while the lowercase ``p`` represents an **instance** of a polynomial class.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
- ``Poly.domain`` -- Default domain
|
||||
- ``Poly.window`` -- Default window
|
||||
- ``Poly.basis_name`` -- String used to represent the basis
|
||||
- ``Poly.maxpower`` -- Maximum value ``n`` such that ``p**n`` is allowed
|
||||
- ``Poly.nickname`` -- String used in printing
|
||||
|
||||
Creation
|
||||
--------
|
||||
|
||||
Methods for creating polynomial instances.
|
||||
|
||||
- ``Poly.basis(degree)`` -- Basis polynomial of given degree
|
||||
- ``Poly.identity()`` -- ``p`` where ``p(x) = x`` for all ``x``
|
||||
- ``Poly.fit(x, y, deg)`` -- ``p`` of degree ``deg`` with coefficients
|
||||
determined by the least-squares fit to the data ``x``, ``y``
|
||||
- ``Poly.fromroots(roots)`` -- ``p`` with specified roots
|
||||
- ``p.copy()`` -- Create a copy of ``p``
|
||||
|
||||
Conversion
|
||||
----------
|
||||
|
||||
Methods for converting a polynomial instance of one kind to another.
|
||||
|
||||
- ``p.cast(Poly)`` -- Convert ``p`` to instance of kind ``Poly``
|
||||
- ``p.convert(Poly)`` -- Convert ``p`` to instance of kind ``Poly`` or map
|
||||
between ``domain`` and ``window``
|
||||
|
||||
Calculus
|
||||
--------
|
||||
- ``p.deriv()`` -- Take the derivative of ``p``
|
||||
- ``p.integ()`` -- Integrate ``p``
|
||||
|
||||
Validation
|
||||
----------
|
||||
- ``Poly.has_samecoef(p1, p2)`` -- Check if coefficients match
|
||||
- ``Poly.has_samedomain(p1, p2)`` -- Check if domains match
|
||||
- ``Poly.has_sametype(p1, p2)`` -- Check if types match
|
||||
- ``Poly.has_samewindow(p1, p2)`` -- Check if windows match
|
||||
|
||||
Misc
|
||||
----
|
||||
- ``p.linspace()`` -- Return ``x, p(x)`` at equally-spaced points in ``domain``
|
||||
- ``p.mapparms()`` -- Return the parameters for the linear mapping between
|
||||
``domain`` and ``window``.
|
||||
- ``p.roots()`` -- Return the roots of `p`.
|
||||
- ``p.trim()`` -- Remove trailing coefficients.
|
||||
- ``p.cutdeg(degree)`` -- Truncate p to given degree
|
||||
- ``p.truncate(size)`` -- Truncate p to given size
|
||||
|
||||
"""
|
||||
from .polynomial import Polynomial
|
||||
from .chebyshev import Chebyshev
|
||||
from .legendre import Legendre
|
||||
from .hermite import Hermite
|
||||
from .hermite_e import HermiteE
|
||||
from .laguerre import Laguerre
|
||||
|
||||
__all__ = [
|
||||
"set_default_printstyle",
|
||||
"polynomial", "Polynomial",
|
||||
"chebyshev", "Chebyshev",
|
||||
"legendre", "Legendre",
|
||||
"hermite", "Hermite",
|
||||
"hermite_e", "HermiteE",
|
||||
"laguerre", "Laguerre",
|
||||
]
|
||||
|
||||
|
||||
def set_default_printstyle(style):
|
||||
"""
|
||||
Set the default format for the string representation of polynomials.
|
||||
|
||||
Values for ``style`` must be valid inputs to ``__format__``, i.e. 'ascii'
|
||||
or 'unicode'.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
style : str
|
||||
Format string for default printing style. Must be either 'ascii' or
|
||||
'unicode'.
|
||||
|
||||
Notes
|
||||
-----
|
||||
The default format depends on the platform: 'unicode' is used on
|
||||
Unix-based systems and 'ascii' on Windows. This determination is based on
|
||||
default font support for the unicode superscript and subscript ranges.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> p = np.polynomial.Polynomial([1, 2, 3])
|
||||
>>> c = np.polynomial.Chebyshev([1, 2, 3])
|
||||
>>> np.polynomial.set_default_printstyle('unicode')
|
||||
>>> print(p)
|
||||
1.0 + 2.0·x + 3.0·x²
|
||||
>>> print(c)
|
||||
1.0 + 2.0·T₁(x) + 3.0·T₂(x)
|
||||
>>> np.polynomial.set_default_printstyle('ascii')
|
||||
>>> print(p)
|
||||
1.0 + 2.0 x + 3.0 x**2
|
||||
>>> print(c)
|
||||
1.0 + 2.0 T_1(x) + 3.0 T_2(x)
|
||||
>>> # Formatting supersedes all class/package-level defaults
|
||||
>>> print(f"{p:unicode}")
|
||||
1.0 + 2.0·x + 3.0·x²
|
||||
"""
|
||||
if style not in ('unicode', 'ascii'):
|
||||
raise ValueError(
|
||||
f"Unsupported format string '{style}'. Valid options are 'ascii' "
|
||||
f"and 'unicode'"
|
||||
)
|
||||
_use_unicode = True
|
||||
if style == 'ascii':
|
||||
_use_unicode = False
|
||||
from ._polybase import ABCPolyBase
|
||||
ABCPolyBase._use_unicode = _use_unicode
|
||||
|
||||
|
||||
from numpy._pytesttester import PytestTester
|
||||
test = PytestTester(__name__)
|
||||
del PytestTester
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
from numpy._pytesttester import PytestTester
|
||||
|
||||
from numpy.polynomial import (
|
||||
chebyshev as chebyshev,
|
||||
hermite as hermite,
|
||||
hermite_e as hermite_e,
|
||||
laguerre as laguerre,
|
||||
legendre as legendre,
|
||||
polynomial as polynomial,
|
||||
)
|
||||
from numpy.polynomial.chebyshev import Chebyshev as Chebyshev
|
||||
from numpy.polynomial.hermite import Hermite as Hermite
|
||||
from numpy.polynomial.hermite_e import HermiteE as HermiteE
|
||||
from numpy.polynomial.laguerre import Laguerre as Laguerre
|
||||
from numpy.polynomial.legendre import Legendre as Legendre
|
||||
from numpy.polynomial.polynomial import Polynomial as Polynomial
|
||||
|
||||
__all__: list[str]
|
||||
__path__: list[str]
|
||||
test: PytestTester
|
||||
|
||||
def set_default_printstyle(style): ...
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,71 @@
|
|||
import abc
|
||||
from typing import Any, ClassVar
|
||||
|
||||
__all__: list[str]
|
||||
|
||||
class ABCPolyBase(abc.ABC):
|
||||
__hash__: ClassVar[None] # type: ignore[assignment]
|
||||
__array_ufunc__: ClassVar[None]
|
||||
maxpower: ClassVar[int]
|
||||
coef: Any
|
||||
@property
|
||||
def symbol(self) -> str: ...
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def domain(self): ...
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def window(self): ...
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def basis_name(self): ...
|
||||
def has_samecoef(self, other): ...
|
||||
def has_samedomain(self, other): ...
|
||||
def has_samewindow(self, other): ...
|
||||
def has_sametype(self, other): ...
|
||||
def __init__(self, coef, domain=..., window=..., symbol: str = ...) -> None: ...
|
||||
def __format__(self, fmt_str): ...
|
||||
def __call__(self, arg): ...
|
||||
def __iter__(self): ...
|
||||
def __len__(self): ...
|
||||
def __neg__(self): ...
|
||||
def __pos__(self): ...
|
||||
def __add__(self, other): ...
|
||||
def __sub__(self, other): ...
|
||||
def __mul__(self, other): ...
|
||||
def __truediv__(self, other): ...
|
||||
def __floordiv__(self, other): ...
|
||||
def __mod__(self, other): ...
|
||||
def __divmod__(self, other): ...
|
||||
def __pow__(self, other): ...
|
||||
def __radd__(self, other): ...
|
||||
def __rsub__(self, other): ...
|
||||
def __rmul__(self, other): ...
|
||||
def __rdiv__(self, other): ...
|
||||
def __rtruediv__(self, other): ...
|
||||
def __rfloordiv__(self, other): ...
|
||||
def __rmod__(self, other): ...
|
||||
def __rdivmod__(self, other): ...
|
||||
def __eq__(self, other): ...
|
||||
def __ne__(self, other): ...
|
||||
def copy(self): ...
|
||||
def degree(self): ...
|
||||
def cutdeg(self, deg): ...
|
||||
def trim(self, tol=...): ...
|
||||
def truncate(self, size): ...
|
||||
def convert(self, domain=..., kind=..., window=...): ...
|
||||
def mapparms(self): ...
|
||||
def integ(self, m=..., k = ..., lbnd=...): ...
|
||||
def deriv(self, m=...): ...
|
||||
def roots(self): ...
|
||||
def linspace(self, n=..., domain=...): ...
|
||||
@classmethod
|
||||
def fit(cls, x, y, deg, domain=..., rcond=..., full=..., w=..., window=...): ...
|
||||
@classmethod
|
||||
def fromroots(cls, roots, domain = ..., window=...): ...
|
||||
@classmethod
|
||||
def identity(cls, domain=..., window=...): ...
|
||||
@classmethod
|
||||
def basis(cls, deg, domain=..., window=...): ...
|
||||
@classmethod
|
||||
def cast(cls, series, domain=..., window=...): ...
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,51 @@
|
|||
from typing import Any
|
||||
|
||||
from numpy import ndarray, dtype, int_
|
||||
from numpy.polynomial._polybase import ABCPolyBase
|
||||
from numpy.polynomial.polyutils import trimcoef
|
||||
|
||||
__all__: list[str]
|
||||
|
||||
chebtrim = trimcoef
|
||||
|
||||
def poly2cheb(pol): ...
|
||||
def cheb2poly(c): ...
|
||||
|
||||
chebdomain: ndarray[Any, dtype[int_]]
|
||||
chebzero: ndarray[Any, dtype[int_]]
|
||||
chebone: ndarray[Any, dtype[int_]]
|
||||
chebx: ndarray[Any, dtype[int_]]
|
||||
|
||||
def chebline(off, scl): ...
|
||||
def chebfromroots(roots): ...
|
||||
def chebadd(c1, c2): ...
|
||||
def chebsub(c1, c2): ...
|
||||
def chebmulx(c): ...
|
||||
def chebmul(c1, c2): ...
|
||||
def chebdiv(c1, c2): ...
|
||||
def chebpow(c, pow, maxpower=...): ...
|
||||
def chebder(c, m=..., scl=..., axis=...): ...
|
||||
def chebint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
|
||||
def chebval(x, c, tensor=...): ...
|
||||
def chebval2d(x, y, c): ...
|
||||
def chebgrid2d(x, y, c): ...
|
||||
def chebval3d(x, y, z, c): ...
|
||||
def chebgrid3d(x, y, z, c): ...
|
||||
def chebvander(x, deg): ...
|
||||
def chebvander2d(x, y, deg): ...
|
||||
def chebvander3d(x, y, z, deg): ...
|
||||
def chebfit(x, y, deg, rcond=..., full=..., w=...): ...
|
||||
def chebcompanion(c): ...
|
||||
def chebroots(c): ...
|
||||
def chebinterpolate(func, deg, args = ...): ...
|
||||
def chebgauss(deg): ...
|
||||
def chebweight(x): ...
|
||||
def chebpts1(npts): ...
|
||||
def chebpts2(npts): ...
|
||||
|
||||
class Chebyshev(ABCPolyBase):
|
||||
@classmethod
|
||||
def interpolate(cls, func, deg, domain=..., args = ...): ...
|
||||
domain: Any
|
||||
window: Any
|
||||
basis_name: Any
|
||||
1703
AppDir/usr/lib/python3.12/site-packages/numpy/polynomial/hermite.py
Normal file
1703
AppDir/usr/lib/python3.12/site-packages/numpy/polynomial/hermite.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,46 @@
|
|||
from typing import Any
|
||||
|
||||
from numpy import ndarray, dtype, int_, float_
|
||||
from numpy.polynomial._polybase import ABCPolyBase
|
||||
from numpy.polynomial.polyutils import trimcoef
|
||||
|
||||
__all__: list[str]
|
||||
|
||||
hermtrim = trimcoef
|
||||
|
||||
def poly2herm(pol): ...
|
||||
def herm2poly(c): ...
|
||||
|
||||
hermdomain: ndarray[Any, dtype[int_]]
|
||||
hermzero: ndarray[Any, dtype[int_]]
|
||||
hermone: ndarray[Any, dtype[int_]]
|
||||
hermx: ndarray[Any, dtype[float_]]
|
||||
|
||||
def hermline(off, scl): ...
|
||||
def hermfromroots(roots): ...
|
||||
def hermadd(c1, c2): ...
|
||||
def hermsub(c1, c2): ...
|
||||
def hermmulx(c): ...
|
||||
def hermmul(c1, c2): ...
|
||||
def hermdiv(c1, c2): ...
|
||||
def hermpow(c, pow, maxpower=...): ...
|
||||
def hermder(c, m=..., scl=..., axis=...): ...
|
||||
def hermint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
|
||||
def hermval(x, c, tensor=...): ...
|
||||
def hermval2d(x, y, c): ...
|
||||
def hermgrid2d(x, y, c): ...
|
||||
def hermval3d(x, y, z, c): ...
|
||||
def hermgrid3d(x, y, z, c): ...
|
||||
def hermvander(x, deg): ...
|
||||
def hermvander2d(x, y, deg): ...
|
||||
def hermvander3d(x, y, z, deg): ...
|
||||
def hermfit(x, y, deg, rcond=..., full=..., w=...): ...
|
||||
def hermcompanion(c): ...
|
||||
def hermroots(c): ...
|
||||
def hermgauss(deg): ...
|
||||
def hermweight(x): ...
|
||||
|
||||
class Hermite(ABCPolyBase):
|
||||
domain: Any
|
||||
window: Any
|
||||
basis_name: Any
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,46 @@
|
|||
from typing import Any
|
||||
|
||||
from numpy import ndarray, dtype, int_
|
||||
from numpy.polynomial._polybase import ABCPolyBase
|
||||
from numpy.polynomial.polyutils import trimcoef
|
||||
|
||||
__all__: list[str]
|
||||
|
||||
hermetrim = trimcoef
|
||||
|
||||
def poly2herme(pol): ...
|
||||
def herme2poly(c): ...
|
||||
|
||||
hermedomain: ndarray[Any, dtype[int_]]
|
||||
hermezero: ndarray[Any, dtype[int_]]
|
||||
hermeone: ndarray[Any, dtype[int_]]
|
||||
hermex: ndarray[Any, dtype[int_]]
|
||||
|
||||
def hermeline(off, scl): ...
|
||||
def hermefromroots(roots): ...
|
||||
def hermeadd(c1, c2): ...
|
||||
def hermesub(c1, c2): ...
|
||||
def hermemulx(c): ...
|
||||
def hermemul(c1, c2): ...
|
||||
def hermediv(c1, c2): ...
|
||||
def hermepow(c, pow, maxpower=...): ...
|
||||
def hermeder(c, m=..., scl=..., axis=...): ...
|
||||
def hermeint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
|
||||
def hermeval(x, c, tensor=...): ...
|
||||
def hermeval2d(x, y, c): ...
|
||||
def hermegrid2d(x, y, c): ...
|
||||
def hermeval3d(x, y, z, c): ...
|
||||
def hermegrid3d(x, y, z, c): ...
|
||||
def hermevander(x, deg): ...
|
||||
def hermevander2d(x, y, deg): ...
|
||||
def hermevander3d(x, y, z, deg): ...
|
||||
def hermefit(x, y, deg, rcond=..., full=..., w=...): ...
|
||||
def hermecompanion(c): ...
|
||||
def hermeroots(c): ...
|
||||
def hermegauss(deg): ...
|
||||
def hermeweight(x): ...
|
||||
|
||||
class HermiteE(ABCPolyBase):
|
||||
domain: Any
|
||||
window: Any
|
||||
basis_name: Any
|
||||
1651
AppDir/usr/lib/python3.12/site-packages/numpy/polynomial/laguerre.py
Normal file
1651
AppDir/usr/lib/python3.12/site-packages/numpy/polynomial/laguerre.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,46 @@
|
|||
from typing import Any
|
||||
|
||||
from numpy import ndarray, dtype, int_
|
||||
from numpy.polynomial._polybase import ABCPolyBase
|
||||
from numpy.polynomial.polyutils import trimcoef
|
||||
|
||||
__all__: list[str]
|
||||
|
||||
lagtrim = trimcoef
|
||||
|
||||
def poly2lag(pol): ...
|
||||
def lag2poly(c): ...
|
||||
|
||||
lagdomain: ndarray[Any, dtype[int_]]
|
||||
lagzero: ndarray[Any, dtype[int_]]
|
||||
lagone: ndarray[Any, dtype[int_]]
|
||||
lagx: ndarray[Any, dtype[int_]]
|
||||
|
||||
def lagline(off, scl): ...
|
||||
def lagfromroots(roots): ...
|
||||
def lagadd(c1, c2): ...
|
||||
def lagsub(c1, c2): ...
|
||||
def lagmulx(c): ...
|
||||
def lagmul(c1, c2): ...
|
||||
def lagdiv(c1, c2): ...
|
||||
def lagpow(c, pow, maxpower=...): ...
|
||||
def lagder(c, m=..., scl=..., axis=...): ...
|
||||
def lagint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
|
||||
def lagval(x, c, tensor=...): ...
|
||||
def lagval2d(x, y, c): ...
|
||||
def laggrid2d(x, y, c): ...
|
||||
def lagval3d(x, y, z, c): ...
|
||||
def laggrid3d(x, y, z, c): ...
|
||||
def lagvander(x, deg): ...
|
||||
def lagvander2d(x, y, deg): ...
|
||||
def lagvander3d(x, y, z, deg): ...
|
||||
def lagfit(x, y, deg, rcond=..., full=..., w=...): ...
|
||||
def lagcompanion(c): ...
|
||||
def lagroots(c): ...
|
||||
def laggauss(deg): ...
|
||||
def lagweight(x): ...
|
||||
|
||||
class Laguerre(ABCPolyBase):
|
||||
domain: Any
|
||||
window: Any
|
||||
basis_name: Any
|
||||
1664
AppDir/usr/lib/python3.12/site-packages/numpy/polynomial/legendre.py
Normal file
1664
AppDir/usr/lib/python3.12/site-packages/numpy/polynomial/legendre.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,46 @@
|
|||
from typing import Any
|
||||
|
||||
from numpy import ndarray, dtype, int_
|
||||
from numpy.polynomial._polybase import ABCPolyBase
|
||||
from numpy.polynomial.polyutils import trimcoef
|
||||
|
||||
__all__: list[str]
|
||||
|
||||
legtrim = trimcoef
|
||||
|
||||
def poly2leg(pol): ...
|
||||
def leg2poly(c): ...
|
||||
|
||||
legdomain: ndarray[Any, dtype[int_]]
|
||||
legzero: ndarray[Any, dtype[int_]]
|
||||
legone: ndarray[Any, dtype[int_]]
|
||||
legx: ndarray[Any, dtype[int_]]
|
||||
|
||||
def legline(off, scl): ...
|
||||
def legfromroots(roots): ...
|
||||
def legadd(c1, c2): ...
|
||||
def legsub(c1, c2): ...
|
||||
def legmulx(c): ...
|
||||
def legmul(c1, c2): ...
|
||||
def legdiv(c1, c2): ...
|
||||
def legpow(c, pow, maxpower=...): ...
|
||||
def legder(c, m=..., scl=..., axis=...): ...
|
||||
def legint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
|
||||
def legval(x, c, tensor=...): ...
|
||||
def legval2d(x, y, c): ...
|
||||
def leggrid2d(x, y, c): ...
|
||||
def legval3d(x, y, z, c): ...
|
||||
def leggrid3d(x, y, z, c): ...
|
||||
def legvander(x, deg): ...
|
||||
def legvander2d(x, y, deg): ...
|
||||
def legvander3d(x, y, z, deg): ...
|
||||
def legfit(x, y, deg, rcond=..., full=..., w=...): ...
|
||||
def legcompanion(c): ...
|
||||
def legroots(c): ...
|
||||
def leggauss(deg): ...
|
||||
def legweight(x): ...
|
||||
|
||||
class Legendre(ABCPolyBase):
|
||||
domain: Any
|
||||
window: Any
|
||||
basis_name: Any
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,41 @@
|
|||
from typing import Any
|
||||
|
||||
from numpy import ndarray, dtype, int_
|
||||
from numpy.polynomial._polybase import ABCPolyBase
|
||||
from numpy.polynomial.polyutils import trimcoef
|
||||
|
||||
__all__: list[str]
|
||||
|
||||
polytrim = trimcoef
|
||||
|
||||
polydomain: ndarray[Any, dtype[int_]]
|
||||
polyzero: ndarray[Any, dtype[int_]]
|
||||
polyone: ndarray[Any, dtype[int_]]
|
||||
polyx: ndarray[Any, dtype[int_]]
|
||||
|
||||
def polyline(off, scl): ...
|
||||
def polyfromroots(roots): ...
|
||||
def polyadd(c1, c2): ...
|
||||
def polysub(c1, c2): ...
|
||||
def polymulx(c): ...
|
||||
def polymul(c1, c2): ...
|
||||
def polydiv(c1, c2): ...
|
||||
def polypow(c, pow, maxpower=...): ...
|
||||
def polyder(c, m=..., scl=..., axis=...): ...
|
||||
def polyint(c, m=..., k=..., lbnd=..., scl=..., axis=...): ...
|
||||
def polyval(x, c, tensor=...): ...
|
||||
def polyvalfromroots(x, r, tensor=...): ...
|
||||
def polyval2d(x, y, c): ...
|
||||
def polygrid2d(x, y, c): ...
|
||||
def polyval3d(x, y, z, c): ...
|
||||
def polygrid3d(x, y, z, c): ...
|
||||
def polyvander(x, deg): ...
|
||||
def polyvander2d(x, y, deg): ...
|
||||
def polyvander3d(x, y, z, deg): ...
|
||||
def polyfit(x, y, deg, rcond=..., full=..., w=...): ...
|
||||
def polyroots(c): ...
|
||||
|
||||
class Polynomial(ABCPolyBase):
|
||||
domain: Any
|
||||
window: Any
|
||||
basis_name: Any
|
||||
|
|
@ -0,0 +1,789 @@
|
|||
"""
|
||||
Utility classes and functions for the polynomial modules.
|
||||
|
||||
This module provides: error and warning objects; a polynomial base class;
|
||||
and some routines used in both the `polynomial` and `chebyshev` modules.
|
||||
|
||||
Warning objects
|
||||
---------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
RankWarning raised in least-squares fit for rank-deficient matrix.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
|
||||
as_series convert list of array_likes into 1-D arrays of common type.
|
||||
trimseq remove trailing zeros.
|
||||
trimcoef remove small trailing coefficients.
|
||||
getdomain return the domain appropriate for a given set of abscissae.
|
||||
mapdomain maps points between domains.
|
||||
mapparms parameters of the linear map between domains.
|
||||
|
||||
"""
|
||||
import operator
|
||||
import functools
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
from numpy.core.multiarray import dragon4_positional, dragon4_scientific
|
||||
from numpy.core.umath import absolute
|
||||
|
||||
__all__ = [
|
||||
'RankWarning', 'as_series', 'trimseq',
|
||||
'trimcoef', 'getdomain', 'mapdomain', 'mapparms',
|
||||
'format_float']
|
||||
|
||||
#
|
||||
# Warnings and Exceptions
|
||||
#
|
||||
|
||||
class RankWarning(UserWarning):
|
||||
"""Issued by chebfit when the design matrix is rank deficient."""
|
||||
pass
|
||||
|
||||
#
|
||||
# Helper functions to convert inputs to 1-D arrays
|
||||
#
|
||||
def trimseq(seq):
|
||||
"""Remove small Poly series coefficients.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
seq : sequence
|
||||
Sequence of Poly series coefficients. This routine fails for
|
||||
empty sequences.
|
||||
|
||||
Returns
|
||||
-------
|
||||
series : sequence
|
||||
Subsequence with trailing zeros removed. If the resulting sequence
|
||||
would be empty, return the first element. The returned sequence may
|
||||
or may not be a view.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Do not lose the type info if the sequence contains unknown objects.
|
||||
|
||||
"""
|
||||
if len(seq) == 0:
|
||||
return seq
|
||||
else:
|
||||
for i in range(len(seq) - 1, -1, -1):
|
||||
if seq[i] != 0:
|
||||
break
|
||||
return seq[:i+1]
|
||||
|
||||
|
||||
def as_series(alist, trim=True):
|
||||
"""
|
||||
Return argument as a list of 1-d arrays.
|
||||
|
||||
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
|
||||
----------
|
||||
alist : 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 1-D arrays
|
||||
A copy of the input data as a list of 1-d arrays.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
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.polynomial import polyutils as pu
|
||||
>>> a = np.arange(4)
|
||||
>>> pu.as_series(a)
|
||||
[array([0.]), array([1.]), array([2.]), array([3.])]
|
||||
>>> b = np.arange(6).reshape((2,3))
|
||||
>>> pu.as_series(b)
|
||||
[array([0., 1., 2.]), array([3., 4., 5.])]
|
||||
|
||||
>>> pu.as_series((1, np.arange(3), np.arange(2, dtype=np.float16)))
|
||||
[array([1.]), array([0., 1., 2.]), array([0., 1.])]
|
||||
|
||||
>>> pu.as_series([2, [1.1, 0.]])
|
||||
[array([2.]), array([1.1])]
|
||||
|
||||
>>> pu.as_series([2, [1.1, 0.]], trim=False)
|
||||
[array([2.]), array([1.1, 0. ])]
|
||||
|
||||
"""
|
||||
arrays = [np.array(a, ndmin=1, copy=False) for a in alist]
|
||||
if min([a.size for a in arrays]) == 0:
|
||||
raise ValueError("Coefficient array is empty")
|
||||
if any(a.ndim != 1 for a in arrays):
|
||||
raise ValueError("Coefficient array is not 1-d")
|
||||
if trim:
|
||||
arrays = [trimseq(a) for a in arrays]
|
||||
|
||||
if any(a.dtype == np.dtype(object) for a in arrays):
|
||||
ret = []
|
||||
for a in arrays:
|
||||
if a.dtype != np.dtype(object):
|
||||
tmp = np.empty(len(a), dtype=np.dtype(object))
|
||||
tmp[:] = a[:]
|
||||
ret.append(tmp)
|
||||
else:
|
||||
ret.append(a.copy())
|
||||
else:
|
||||
try:
|
||||
dtype = np.common_type(*arrays)
|
||||
except Exception as e:
|
||||
raise ValueError("Coefficient arrays have no common type") from e
|
||||
ret = [np.array(a, copy=True, dtype=dtype) for a in arrays]
|
||||
return ret
|
||||
|
||||
|
||||
def trimcoef(c, tol=0):
|
||||
"""
|
||||
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 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 trailing zeros removed. If the resulting series
|
||||
would be empty, a series containing a single zero is returned.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If `tol` < 0
|
||||
|
||||
See Also
|
||||
--------
|
||||
trimseq
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from numpy.polynomial import polyutils as pu
|
||||
>>> pu.trimcoef((0,0,3,0,5,0,0))
|
||||
array([0., 0., 3., 0., 5.])
|
||||
>>> pu.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
|
||||
>>> pu.trimcoef((3e-4,1e-3*(1-i),5e-4,2e-5*(1+i)), 1e-3)
|
||||
array([0.0003+0.j , 0.001 -0.001j])
|
||||
|
||||
"""
|
||||
if tol < 0:
|
||||
raise ValueError("tol must be non-negative")
|
||||
|
||||
[c] = as_series([c])
|
||||
[ind] = np.nonzero(np.abs(c) > tol)
|
||||
if len(ind) == 0:
|
||||
return c[:1]*0
|
||||
else:
|
||||
return c[:ind[-1] + 1].copy()
|
||||
|
||||
def getdomain(x):
|
||||
"""
|
||||
Return a domain suitable for given abscissae.
|
||||
|
||||
Find a domain suitable for a polynomial or Chebyshev series
|
||||
defined at the values supplied.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
1-d array of abscissae whose domain will be determined.
|
||||
|
||||
Returns
|
||||
-------
|
||||
domain : ndarray
|
||||
1-d array containing two values. If the inputs are complex, then
|
||||
the two returned points are the lower left and upper right corners
|
||||
of the smallest rectangle (aligned with the axes) in the complex
|
||||
plane containing the points `x`. If the inputs are real, then the
|
||||
two points are the ends of the smallest interval containing the
|
||||
points `x`.
|
||||
|
||||
See Also
|
||||
--------
|
||||
mapparms, mapdomain
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from numpy.polynomial import polyutils as pu
|
||||
>>> points = np.arange(4)**2 - 5; points
|
||||
array([-5, -4, -1, 4])
|
||||
>>> pu.getdomain(points)
|
||||
array([-5., 4.])
|
||||
>>> c = np.exp(complex(0,1)*np.pi*np.arange(12)/6) # unit circle
|
||||
>>> pu.getdomain(c)
|
||||
array([-1.-1.j, 1.+1.j])
|
||||
|
||||
"""
|
||||
[x] = as_series([x], trim=False)
|
||||
if x.dtype.char in np.typecodes['Complex']:
|
||||
rmin, rmax = x.real.min(), x.real.max()
|
||||
imin, imax = x.imag.min(), x.imag.max()
|
||||
return np.array((complex(rmin, imin), complex(rmax, imax)))
|
||||
else:
|
||||
return np.array((x.min(), x.max()))
|
||||
|
||||
def mapparms(old, new):
|
||||
"""
|
||||
Linear map parameters between domains.
|
||||
|
||||
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
|
||||
Domains. Each domain must (successfully) convert to a 1-d array
|
||||
containing precisely two values.
|
||||
|
||||
Returns
|
||||
-------
|
||||
offset, scale : scalars
|
||||
The map ``L(x) = offset + scale*x`` maps the first domain to the
|
||||
second.
|
||||
|
||||
See Also
|
||||
--------
|
||||
getdomain, mapdomain
|
||||
|
||||
Notes
|
||||
-----
|
||||
Also works for complex numbers, and thus can be used to calculate the
|
||||
parameters required to map any line in the complex plane to any other
|
||||
line therein.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from numpy.polynomial import polyutils as pu
|
||||
>>> pu.mapparms((-1,1),(-1,1))
|
||||
(0.0, 1.0)
|
||||
>>> pu.mapparms((1,-1),(-1,1))
|
||||
(-0.0, -1.0)
|
||||
>>> i = complex(0,1)
|
||||
>>> pu.mapparms((-i,-1),(1,i))
|
||||
((1+1j), (1-0j))
|
||||
|
||||
"""
|
||||
oldlen = old[1] - old[0]
|
||||
newlen = new[1] - new[0]
|
||||
off = (old[1]*new[0] - old[0]*new[1])/oldlen
|
||||
scl = newlen/oldlen
|
||||
return off, scl
|
||||
|
||||
def mapdomain(x, old, new):
|
||||
"""
|
||||
Apply linear map to input points.
|
||||
|
||||
The linear map ``offset + scale*x`` that maps the domain `old` to
|
||||
the domain `new` is applied to the points `x`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like
|
||||
Points to be mapped. If `x` is a subtype of ndarray the subtype
|
||||
will be preserved.
|
||||
old, new : array_like
|
||||
The two domains that determine the map. Each must (successfully)
|
||||
convert to 1-d arrays containing precisely two values.
|
||||
|
||||
Returns
|
||||
-------
|
||||
x_out : ndarray
|
||||
Array of points of the same shape as `x`, after application of the
|
||||
linear map between the two domains.
|
||||
|
||||
See Also
|
||||
--------
|
||||
getdomain, mapparms
|
||||
|
||||
Notes
|
||||
-----
|
||||
Effectively, this implements:
|
||||
|
||||
.. math::
|
||||
x\\_out = new[0] + m(x - old[0])
|
||||
|
||||
where
|
||||
|
||||
.. math::
|
||||
m = \\frac{new[1]-new[0]}{old[1]-old[0]}
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from numpy.polynomial import polyutils as pu
|
||||
>>> 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 = pu.mapdomain(x, old_domain, new_domain); x_out
|
||||
array([ 0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825, # may vary
|
||||
6.28318531])
|
||||
>>> x - pu.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. -1.j , -0.6-0.6j, -0.2-0.2j, 0.2+0.2j, 0.6+0.6j, 1. +1.j ])
|
||||
>>> new_z = pu.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 ]) # may vary
|
||||
|
||||
"""
|
||||
x = np.asanyarray(x)
|
||||
off, scl = mapparms(old, new)
|
||||
return off + scl*x
|
||||
|
||||
|
||||
def _nth_slice(i, ndim):
|
||||
sl = [np.newaxis] * ndim
|
||||
sl[i] = slice(None)
|
||||
return tuple(sl)
|
||||
|
||||
|
||||
def _vander_nd(vander_fs, points, degrees):
|
||||
r"""
|
||||
A generalization of the Vandermonde matrix for N dimensions
|
||||
|
||||
The result is built by combining the results of 1d Vandermonde matrices,
|
||||
|
||||
.. math::
|
||||
W[i_0, \ldots, i_M, j_0, \ldots, j_N] = \prod_{k=0}^N{V_k(x_k)[i_0, \ldots, i_M, j_k]}
|
||||
|
||||
where
|
||||
|
||||
.. math::
|
||||
N &= \texttt{len(points)} = \texttt{len(degrees)} = \texttt{len(vander\_fs)} \\
|
||||
M &= \texttt{points[k].ndim} \\
|
||||
V_k &= \texttt{vander\_fs[k]} \\
|
||||
x_k &= \texttt{points[k]} \\
|
||||
0 \le j_k &\le \texttt{degrees[k]}
|
||||
|
||||
Expanding the one-dimensional :math:`V_k` functions gives:
|
||||
|
||||
.. math::
|
||||
W[i_0, \ldots, i_M, j_0, \ldots, j_N] = \prod_{k=0}^N{B_{k, j_k}(x_k[i_0, \ldots, i_M])}
|
||||
|
||||
where :math:`B_{k,m}` is the m'th basis of the polynomial construction used along
|
||||
dimension :math:`k`. For a regular polynomial, :math:`B_{k, m}(x) = P_m(x) = x^m`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
vander_fs : Sequence[function(array_like, int) -> ndarray]
|
||||
The 1d vander function to use for each axis, such as ``polyvander``
|
||||
points : Sequence[array_like]
|
||||
Arrays of point coordinates, all of the same shape. The dtypes
|
||||
will be converted to either float64 or complex128 depending on
|
||||
whether any of the elements are complex. Scalars are converted to
|
||||
1-D arrays.
|
||||
This must be the same length as `vander_fs`.
|
||||
degrees : Sequence[int]
|
||||
The maximum degree (inclusive) to use for each axis.
|
||||
This must be the same length as `vander_fs`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
vander_nd : ndarray
|
||||
An array of shape ``points[0].shape + tuple(d + 1 for d in degrees)``.
|
||||
"""
|
||||
n_dims = len(vander_fs)
|
||||
if n_dims != len(points):
|
||||
raise ValueError(
|
||||
f"Expected {n_dims} dimensions of sample points, got {len(points)}")
|
||||
if n_dims != len(degrees):
|
||||
raise ValueError(
|
||||
f"Expected {n_dims} dimensions of degrees, got {len(degrees)}")
|
||||
if n_dims == 0:
|
||||
raise ValueError("Unable to guess a dtype or shape when no points are given")
|
||||
|
||||
# convert to the same shape and type
|
||||
points = tuple(np.array(tuple(points), copy=False) + 0.0)
|
||||
|
||||
# produce the vandermonde matrix for each dimension, placing the last
|
||||
# axis of each in an independent trailing axis of the output
|
||||
vander_arrays = (
|
||||
vander_fs[i](points[i], degrees[i])[(...,) + _nth_slice(i, n_dims)]
|
||||
for i in range(n_dims)
|
||||
)
|
||||
|
||||
# we checked this wasn't empty already, so no `initial` needed
|
||||
return functools.reduce(operator.mul, vander_arrays)
|
||||
|
||||
|
||||
def _vander_nd_flat(vander_fs, points, degrees):
|
||||
"""
|
||||
Like `_vander_nd`, but flattens the last ``len(degrees)`` axes into a single axis
|
||||
|
||||
Used to implement the public ``<type>vander<n>d`` functions.
|
||||
"""
|
||||
v = _vander_nd(vander_fs, points, degrees)
|
||||
return v.reshape(v.shape[:-len(degrees)] + (-1,))
|
||||
|
||||
|
||||
def _fromroots(line_f, mul_f, roots):
|
||||
"""
|
||||
Helper function used to implement the ``<type>fromroots`` functions.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
line_f : function(float, float) -> ndarray
|
||||
The ``<type>line`` function, such as ``polyline``
|
||||
mul_f : function(array_like, array_like) -> ndarray
|
||||
The ``<type>mul`` function, such as ``polymul``
|
||||
roots
|
||||
See the ``<type>fromroots`` functions for more detail
|
||||
"""
|
||||
if len(roots) == 0:
|
||||
return np.ones(1)
|
||||
else:
|
||||
[roots] = as_series([roots], trim=False)
|
||||
roots.sort()
|
||||
p = [line_f(-r, 1) for r in roots]
|
||||
n = len(p)
|
||||
while n > 1:
|
||||
m, r = divmod(n, 2)
|
||||
tmp = [mul_f(p[i], p[i+m]) for i in range(m)]
|
||||
if r:
|
||||
tmp[0] = mul_f(tmp[0], p[-1])
|
||||
p = tmp
|
||||
n = m
|
||||
return p[0]
|
||||
|
||||
|
||||
def _valnd(val_f, c, *args):
|
||||
"""
|
||||
Helper function used to implement the ``<type>val<n>d`` functions.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
val_f : function(array_like, array_like, tensor: bool) -> array_like
|
||||
The ``<type>val`` function, such as ``polyval``
|
||||
c, args
|
||||
See the ``<type>val<n>d`` functions for more detail
|
||||
"""
|
||||
args = [np.asanyarray(a) for a in args]
|
||||
shape0 = args[0].shape
|
||||
if not all((a.shape == shape0 for a in args[1:])):
|
||||
if len(args) == 3:
|
||||
raise ValueError('x, y, z are incompatible')
|
||||
elif len(args) == 2:
|
||||
raise ValueError('x, y are incompatible')
|
||||
else:
|
||||
raise ValueError('ordinates are incompatible')
|
||||
it = iter(args)
|
||||
x0 = next(it)
|
||||
|
||||
# use tensor on only the first
|
||||
c = val_f(x0, c)
|
||||
for xi in it:
|
||||
c = val_f(xi, c, tensor=False)
|
||||
return c
|
||||
|
||||
|
||||
def _gridnd(val_f, c, *args):
|
||||
"""
|
||||
Helper function used to implement the ``<type>grid<n>d`` functions.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
val_f : function(array_like, array_like, tensor: bool) -> array_like
|
||||
The ``<type>val`` function, such as ``polyval``
|
||||
c, args
|
||||
See the ``<type>grid<n>d`` functions for more detail
|
||||
"""
|
||||
for xi in args:
|
||||
c = val_f(xi, c)
|
||||
return c
|
||||
|
||||
|
||||
def _div(mul_f, c1, c2):
|
||||
"""
|
||||
Helper function used to implement the ``<type>div`` functions.
|
||||
|
||||
Implementation uses repeated subtraction of c2 multiplied by the nth basis.
|
||||
For some polynomial types, a more efficient approach may be possible.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mul_f : function(array_like, array_like) -> array_like
|
||||
The ``<type>mul`` function, such as ``polymul``
|
||||
c1, c2
|
||||
See the ``<type>div`` functions for more detail
|
||||
"""
|
||||
# c1, c2 are trimmed copies
|
||||
[c1, c2] = as_series([c1, c2])
|
||||
if c2[-1] == 0:
|
||||
raise ZeroDivisionError()
|
||||
|
||||
lc1 = len(c1)
|
||||
lc2 = len(c2)
|
||||
if lc1 < lc2:
|
||||
return c1[:1]*0, c1
|
||||
elif lc2 == 1:
|
||||
return c1/c2[-1], c1[:1]*0
|
||||
else:
|
||||
quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
|
||||
rem = c1
|
||||
for i in range(lc1 - lc2, - 1, -1):
|
||||
p = mul_f([0]*i + [1], c2)
|
||||
q = rem[-1]/p[-1]
|
||||
rem = rem[:-1] - q*p[:-1]
|
||||
quo[i] = q
|
||||
return quo, trimseq(rem)
|
||||
|
||||
|
||||
def _add(c1, c2):
|
||||
""" Helper function used to implement the ``<type>add`` functions. """
|
||||
# c1, c2 are trimmed copies
|
||||
[c1, c2] = as_series([c1, c2])
|
||||
if len(c1) > len(c2):
|
||||
c1[:c2.size] += c2
|
||||
ret = c1
|
||||
else:
|
||||
c2[:c1.size] += c1
|
||||
ret = c2
|
||||
return trimseq(ret)
|
||||
|
||||
|
||||
def _sub(c1, c2):
|
||||
""" Helper function used to implement the ``<type>sub`` functions. """
|
||||
# c1, c2 are trimmed copies
|
||||
[c1, c2] = as_series([c1, c2])
|
||||
if len(c1) > len(c2):
|
||||
c1[:c2.size] -= c2
|
||||
ret = c1
|
||||
else:
|
||||
c2 = -c2
|
||||
c2[:c1.size] += c1
|
||||
ret = c2
|
||||
return trimseq(ret)
|
||||
|
||||
|
||||
def _fit(vander_f, x, y, deg, rcond=None, full=False, w=None):
|
||||
"""
|
||||
Helper function used to implement the ``<type>fit`` functions.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
vander_f : function(array_like, int) -> ndarray
|
||||
The 1d vander function, such as ``polyvander``
|
||||
c1, c2
|
||||
See the ``<type>fit`` functions for more detail
|
||||
"""
|
||||
x = np.asarray(x) + 0.0
|
||||
y = np.asarray(y) + 0.0
|
||||
deg = np.asarray(deg)
|
||||
|
||||
# check arguments.
|
||||
if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
|
||||
raise TypeError("deg must be an int or non-empty 1-D array of int")
|
||||
if deg.min() < 0:
|
||||
raise ValueError("expected deg >= 0")
|
||||
if x.ndim != 1:
|
||||
raise TypeError("expected 1D vector for x")
|
||||
if x.size == 0:
|
||||
raise TypeError("expected non-empty vector for x")
|
||||
if y.ndim < 1 or y.ndim > 2:
|
||||
raise TypeError("expected 1D or 2D array for y")
|
||||
if len(x) != len(y):
|
||||
raise TypeError("expected x and y to have same length")
|
||||
|
||||
if deg.ndim == 0:
|
||||
lmax = deg
|
||||
order = lmax + 1
|
||||
van = vander_f(x, lmax)
|
||||
else:
|
||||
deg = np.sort(deg)
|
||||
lmax = deg[-1]
|
||||
order = len(deg)
|
||||
van = vander_f(x, lmax)[:, deg]
|
||||
|
||||
# set up the least squares matrices in transposed form
|
||||
lhs = van.T
|
||||
rhs = y.T
|
||||
if w is not None:
|
||||
w = np.asarray(w) + 0.0
|
||||
if w.ndim != 1:
|
||||
raise TypeError("expected 1D vector for w")
|
||||
if len(x) != len(w):
|
||||
raise TypeError("expected x and w to have same length")
|
||||
# apply weights. Don't use inplace operations as they
|
||||
# can cause problems with NA.
|
||||
lhs = lhs * w
|
||||
rhs = rhs * w
|
||||
|
||||
# set rcond
|
||||
if rcond is None:
|
||||
rcond = len(x)*np.finfo(x.dtype).eps
|
||||
|
||||
# Determine the norms of the design matrix columns.
|
||||
if issubclass(lhs.dtype.type, np.complexfloating):
|
||||
scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
|
||||
else:
|
||||
scl = np.sqrt(np.square(lhs).sum(1))
|
||||
scl[scl == 0] = 1
|
||||
|
||||
# Solve the least squares problem.
|
||||
c, resids, rank, s = np.linalg.lstsq(lhs.T/scl, rhs.T, rcond)
|
||||
c = (c.T/scl).T
|
||||
|
||||
# Expand c to include non-fitted coefficients which are set to zero
|
||||
if deg.ndim > 0:
|
||||
if c.ndim == 2:
|
||||
cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
|
||||
else:
|
||||
cc = np.zeros(lmax+1, dtype=c.dtype)
|
||||
cc[deg] = c
|
||||
c = cc
|
||||
|
||||
# warn on rank reduction
|
||||
if rank != order and not full:
|
||||
msg = "The fit may be poorly conditioned"
|
||||
warnings.warn(msg, RankWarning, stacklevel=2)
|
||||
|
||||
if full:
|
||||
return c, [resids, rank, s, rcond]
|
||||
else:
|
||||
return c
|
||||
|
||||
|
||||
def _pow(mul_f, c, pow, maxpower):
|
||||
"""
|
||||
Helper function used to implement the ``<type>pow`` functions.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mul_f : function(array_like, array_like) -> ndarray
|
||||
The ``<type>mul`` function, such as ``polymul``
|
||||
c : array_like
|
||||
1-D array of array of series coefficients
|
||||
pow, maxpower
|
||||
See the ``<type>pow`` functions for more detail
|
||||
"""
|
||||
# c is a trimmed copy
|
||||
[c] = as_series([c])
|
||||
power = int(pow)
|
||||
if power != pow or power < 0:
|
||||
raise ValueError("Power must be a non-negative integer.")
|
||||
elif maxpower is not None and power > maxpower:
|
||||
raise ValueError("Power is too large")
|
||||
elif power == 0:
|
||||
return np.array([1], dtype=c.dtype)
|
||||
elif power == 1:
|
||||
return c
|
||||
else:
|
||||
# This can be made more efficient by using powers of two
|
||||
# in the usual way.
|
||||
prd = c
|
||||
for i in range(2, power + 1):
|
||||
prd = mul_f(prd, c)
|
||||
return prd
|
||||
|
||||
|
||||
def _deprecate_as_int(x, desc):
|
||||
"""
|
||||
Like `operator.index`, but emits a deprecation warning when passed a float
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : int-like, or float with integral value
|
||||
Value to interpret as an integer
|
||||
desc : str
|
||||
description to include in any error message
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError : if x is a non-integral float or non-numeric
|
||||
DeprecationWarning : if x is an integral float
|
||||
"""
|
||||
try:
|
||||
return operator.index(x)
|
||||
except TypeError as e:
|
||||
# Numpy 1.17.0, 2019-03-11
|
||||
try:
|
||||
ix = int(x)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
if ix == x:
|
||||
warnings.warn(
|
||||
f"In future, this will raise TypeError, as {desc} will "
|
||||
"need to be an integer not just an integral float.",
|
||||
DeprecationWarning,
|
||||
stacklevel=3
|
||||
)
|
||||
return ix
|
||||
|
||||
raise TypeError(f"{desc} must be an integer") from e
|
||||
|
||||
|
||||
def format_float(x, parens=False):
|
||||
if not np.issubdtype(type(x), np.floating):
|
||||
return str(x)
|
||||
|
||||
opts = np.get_printoptions()
|
||||
|
||||
if np.isnan(x):
|
||||
return opts['nanstr']
|
||||
elif np.isinf(x):
|
||||
return opts['infstr']
|
||||
|
||||
exp_format = False
|
||||
if x != 0:
|
||||
a = absolute(x)
|
||||
if a >= 1.e8 or a < 10**min(0, -(opts['precision']-1)//2):
|
||||
exp_format = True
|
||||
|
||||
trim, unique = '0', True
|
||||
if opts['floatmode'] == 'fixed':
|
||||
trim, unique = 'k', False
|
||||
|
||||
if exp_format:
|
||||
s = dragon4_scientific(x, precision=opts['precision'],
|
||||
unique=unique, trim=trim,
|
||||
sign=opts['sign'] == '+')
|
||||
if parens:
|
||||
s = '(' + s + ')'
|
||||
else:
|
||||
s = dragon4_positional(x, precision=opts['precision'],
|
||||
fractional=True,
|
||||
unique=unique, trim=trim,
|
||||
sign=opts['sign'] == '+')
|
||||
return s
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
__all__: list[str]
|
||||
|
||||
class RankWarning(UserWarning): ...
|
||||
|
||||
def trimseq(seq): ...
|
||||
def as_series(alist, trim=...): ...
|
||||
def trimcoef(c, tol=...): ...
|
||||
def getdomain(x): ...
|
||||
def mapparms(old, new): ...
|
||||
def mapdomain(x, old, new): ...
|
||||
def format_float(x, parens=...): ...
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
def configuration(parent_package='',top_path=None):
|
||||
from numpy.distutils.misc_util import Configuration
|
||||
config = Configuration('polynomial', parent_package, top_path)
|
||||
config.add_subpackage('tests')
|
||||
config.add_data_files('*.pyi')
|
||||
return config
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(configuration=configuration)
|
||||
|
|
@ -0,0 +1,619 @@
|
|||
"""Tests for chebyshev module.
|
||||
|
||||
"""
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
import numpy.polynomial.chebyshev as cheb
|
||||
from numpy.polynomial.polynomial import polyval
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
)
|
||||
|
||||
|
||||
def trim(x):
|
||||
return cheb.chebtrim(x, tol=1e-6)
|
||||
|
||||
T0 = [1]
|
||||
T1 = [0, 1]
|
||||
T2 = [-1, 0, 2]
|
||||
T3 = [0, -3, 0, 4]
|
||||
T4 = [1, 0, -8, 0, 8]
|
||||
T5 = [0, 5, 0, -20, 0, 16]
|
||||
T6 = [-1, 0, 18, 0, -48, 0, 32]
|
||||
T7 = [0, -7, 0, 56, 0, -112, 0, 64]
|
||||
T8 = [1, 0, -32, 0, 160, 0, -256, 0, 128]
|
||||
T9 = [0, 9, 0, -120, 0, 432, 0, -576, 0, 256]
|
||||
|
||||
Tlist = [T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]
|
||||
|
||||
|
||||
class TestPrivate:
|
||||
|
||||
def test__cseries_to_zseries(self):
|
||||
for i in range(5):
|
||||
inp = np.array([2] + [1]*i, np.double)
|
||||
tgt = np.array([.5]*i + [2] + [.5]*i, np.double)
|
||||
res = cheb._cseries_to_zseries(inp)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test__zseries_to_cseries(self):
|
||||
for i in range(5):
|
||||
inp = np.array([.5]*i + [2] + [.5]*i, np.double)
|
||||
tgt = np.array([2] + [1]*i, np.double)
|
||||
res = cheb._zseries_to_cseries(inp)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
|
||||
class TestConstants:
|
||||
|
||||
def test_chebdomain(self):
|
||||
assert_equal(cheb.chebdomain, [-1, 1])
|
||||
|
||||
def test_chebzero(self):
|
||||
assert_equal(cheb.chebzero, [0])
|
||||
|
||||
def test_chebone(self):
|
||||
assert_equal(cheb.chebone, [1])
|
||||
|
||||
def test_chebx(self):
|
||||
assert_equal(cheb.chebx, [0, 1])
|
||||
|
||||
|
||||
class TestArithmetic:
|
||||
|
||||
def test_chebadd(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] += 1
|
||||
res = cheb.chebadd([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_chebsub(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] -= 1
|
||||
res = cheb.chebsub([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_chebmulx(self):
|
||||
assert_equal(cheb.chebmulx([0]), [0])
|
||||
assert_equal(cheb.chebmulx([1]), [0, 1])
|
||||
for i in range(1, 5):
|
||||
ser = [0]*i + [1]
|
||||
tgt = [0]*(i - 1) + [.5, 0, .5]
|
||||
assert_equal(cheb.chebmulx(ser), tgt)
|
||||
|
||||
def test_chebmul(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(i + j + 1)
|
||||
tgt[i + j] += .5
|
||||
tgt[abs(i - j)] += .5
|
||||
res = cheb.chebmul([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_chebdiv(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
ci = [0]*i + [1]
|
||||
cj = [0]*j + [1]
|
||||
tgt = cheb.chebadd(ci, cj)
|
||||
quo, rem = cheb.chebdiv(tgt, ci)
|
||||
res = cheb.chebadd(cheb.chebmul(quo, ci), rem)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_chebpow(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
c = np.arange(i + 1)
|
||||
tgt = reduce(cheb.chebmul, [c]*j, np.array([1]))
|
||||
res = cheb.chebpow(c, j)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
|
||||
class TestEvaluation:
|
||||
# coefficients of 1 + 2*x + 3*x**2
|
||||
c1d = np.array([2.5, 2., 1.5])
|
||||
c2d = np.einsum('i,j->ij', c1d, c1d)
|
||||
c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
|
||||
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
y = polyval(x, [1., 2., 3.])
|
||||
|
||||
def test_chebval(self):
|
||||
#check empty input
|
||||
assert_equal(cheb.chebval([], [1]).size, 0)
|
||||
|
||||
#check normal input)
|
||||
x = np.linspace(-1, 1)
|
||||
y = [polyval(x, c) for c in Tlist]
|
||||
for i in range(10):
|
||||
msg = f"At i={i}"
|
||||
tgt = y[i]
|
||||
res = cheb.chebval(x, [0]*i + [1])
|
||||
assert_almost_equal(res, tgt, err_msg=msg)
|
||||
|
||||
#check that shape is preserved
|
||||
for i in range(3):
|
||||
dims = [2]*i
|
||||
x = np.zeros(dims)
|
||||
assert_equal(cheb.chebval(x, [1]).shape, dims)
|
||||
assert_equal(cheb.chebval(x, [1, 0]).shape, dims)
|
||||
assert_equal(cheb.chebval(x, [1, 0, 0]).shape, dims)
|
||||
|
||||
def test_chebval2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, cheb.chebval2d, x1, x2[:2], self.c2d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2
|
||||
res = cheb.chebval2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = cheb.chebval2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_chebval3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, cheb.chebval3d, x1, x2, x3[:2], self.c3d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2*y3
|
||||
res = cheb.chebval3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = cheb.chebval3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_chebgrid2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j->ij', y1, y2)
|
||||
res = cheb.chebgrid2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = cheb.chebgrid2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3)*2)
|
||||
|
||||
def test_chebgrid3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
|
||||
res = cheb.chebgrid3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = cheb.chebgrid3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3)*3)
|
||||
|
||||
|
||||
class TestIntegral:
|
||||
|
||||
def test_chebint(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, cheb.chebint, [0], .5)
|
||||
assert_raises(ValueError, cheb.chebint, [0], -1)
|
||||
assert_raises(ValueError, cheb.chebint, [0], 1, [0, 0])
|
||||
assert_raises(ValueError, cheb.chebint, [0], lbnd=[0])
|
||||
assert_raises(ValueError, cheb.chebint, [0], scl=[0])
|
||||
assert_raises(TypeError, cheb.chebint, [0], axis=.5)
|
||||
|
||||
# test integration of zero polynomial
|
||||
for i in range(2, 5):
|
||||
k = [0]*(i - 2) + [1]
|
||||
res = cheb.chebint([0], m=i, k=k)
|
||||
assert_almost_equal(res, [0, 1])
|
||||
|
||||
# check single integration with integration constant
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [1/scl]
|
||||
chebpol = cheb.poly2cheb(pol)
|
||||
chebint = cheb.chebint(chebpol, m=1, k=[i])
|
||||
res = cheb.cheb2poly(chebint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check single integration with integration constant and lbnd
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
chebpol = cheb.poly2cheb(pol)
|
||||
chebint = cheb.chebint(chebpol, m=1, k=[i], lbnd=-1)
|
||||
assert_almost_equal(cheb.chebval(-1, chebint), i)
|
||||
|
||||
# check single integration with integration constant and scaling
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [2/scl]
|
||||
chebpol = cheb.poly2cheb(pol)
|
||||
chebint = cheb.chebint(chebpol, m=1, k=[i], scl=2)
|
||||
res = cheb.cheb2poly(chebint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with default k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = cheb.chebint(tgt, m=1)
|
||||
res = cheb.chebint(pol, m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with defined k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = cheb.chebint(tgt, m=1, k=[k])
|
||||
res = cheb.chebint(pol, m=j, k=list(range(j)))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with lbnd
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = cheb.chebint(tgt, m=1, k=[k], lbnd=-1)
|
||||
res = cheb.chebint(pol, m=j, k=list(range(j)), lbnd=-1)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = cheb.chebint(tgt, m=1, k=[k], scl=2)
|
||||
res = cheb.chebint(pol, m=j, k=list(range(j)), scl=2)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_chebint_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([cheb.chebint(c) for c in c2d.T]).T
|
||||
res = cheb.chebint(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([cheb.chebint(c) for c in c2d])
|
||||
res = cheb.chebint(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([cheb.chebint(c, k=3) for c in c2d])
|
||||
res = cheb.chebint(c2d, k=3, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestDerivative:
|
||||
|
||||
def test_chebder(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, cheb.chebder, [0], .5)
|
||||
assert_raises(ValueError, cheb.chebder, [0], -1)
|
||||
|
||||
# check that zeroth derivative does nothing
|
||||
for i in range(5):
|
||||
tgt = [0]*i + [1]
|
||||
res = cheb.chebder(tgt, m=0)
|
||||
assert_equal(trim(res), trim(tgt))
|
||||
|
||||
# check that derivation is the inverse of integration
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = cheb.chebder(cheb.chebint(tgt, m=j), m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check derivation with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = cheb.chebder(cheb.chebint(tgt, m=j, scl=2), m=j, scl=.5)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_chebder_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([cheb.chebder(c) for c in c2d.T]).T
|
||||
res = cheb.chebder(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([cheb.chebder(c) for c in c2d])
|
||||
res = cheb.chebder(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestVander:
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
|
||||
def test_chebvander(self):
|
||||
# check for 1d x
|
||||
x = np.arange(3)
|
||||
v = cheb.chebvander(x, 3)
|
||||
assert_(v.shape == (3, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], cheb.chebval(x, coef))
|
||||
|
||||
# check for 2d x
|
||||
x = np.array([[1, 2], [3, 4], [5, 6]])
|
||||
v = cheb.chebvander(x, 3)
|
||||
assert_(v.shape == (3, 2, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], cheb.chebval(x, coef))
|
||||
|
||||
def test_chebvander2d(self):
|
||||
# also tests chebval2d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3))
|
||||
van = cheb.chebvander2d(x1, x2, [1, 2])
|
||||
tgt = cheb.chebval2d(x1, x2, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = cheb.chebvander2d([x1], [x2], [1, 2])
|
||||
assert_(van.shape == (1, 5, 6))
|
||||
|
||||
def test_chebvander3d(self):
|
||||
# also tests chebval3d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3, 4))
|
||||
van = cheb.chebvander3d(x1, x2, x3, [1, 2, 3])
|
||||
tgt = cheb.chebval3d(x1, x2, x3, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = cheb.chebvander3d([x1], [x2], [x3], [1, 2, 3])
|
||||
assert_(van.shape == (1, 5, 24))
|
||||
|
||||
|
||||
class TestFitting:
|
||||
|
||||
def test_chebfit(self):
|
||||
def f(x):
|
||||
return x*(x - 1)*(x - 2)
|
||||
|
||||
def f2(x):
|
||||
return x**4 + x**2 + 1
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, cheb.chebfit, [1], [1], -1)
|
||||
assert_raises(TypeError, cheb.chebfit, [[1]], [1], 0)
|
||||
assert_raises(TypeError, cheb.chebfit, [], [1], 0)
|
||||
assert_raises(TypeError, cheb.chebfit, [1], [[[1]]], 0)
|
||||
assert_raises(TypeError, cheb.chebfit, [1, 2], [1], 0)
|
||||
assert_raises(TypeError, cheb.chebfit, [1], [1, 2], 0)
|
||||
assert_raises(TypeError, cheb.chebfit, [1], [1], 0, w=[[1]])
|
||||
assert_raises(TypeError, cheb.chebfit, [1], [1], 0, w=[1, 1])
|
||||
assert_raises(ValueError, cheb.chebfit, [1], [1], [-1,])
|
||||
assert_raises(ValueError, cheb.chebfit, [1], [1], [2, -1, 6])
|
||||
assert_raises(TypeError, cheb.chebfit, [1], [1], [])
|
||||
|
||||
# Test fit
|
||||
x = np.linspace(0, 2)
|
||||
y = f(x)
|
||||
#
|
||||
coef3 = cheb.chebfit(x, y, 3)
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(cheb.chebval(x, coef3), y)
|
||||
coef3 = cheb.chebfit(x, y, [0, 1, 2, 3])
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(cheb.chebval(x, coef3), y)
|
||||
#
|
||||
coef4 = cheb.chebfit(x, y, 4)
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(cheb.chebval(x, coef4), y)
|
||||
coef4 = cheb.chebfit(x, y, [0, 1, 2, 3, 4])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(cheb.chebval(x, coef4), y)
|
||||
# check things still work if deg is not in strict increasing
|
||||
coef4 = cheb.chebfit(x, y, [2, 3, 4, 1, 0])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(cheb.chebval(x, coef4), y)
|
||||
#
|
||||
coef2d = cheb.chebfit(x, np.array([y, y]).T, 3)
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
coef2d = cheb.chebfit(x, np.array([y, y]).T, [0, 1, 2, 3])
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
# test weighting
|
||||
w = np.zeros_like(x)
|
||||
yw = y.copy()
|
||||
w[1::2] = 1
|
||||
y[0::2] = 0
|
||||
wcoef3 = cheb.chebfit(x, yw, 3, w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
wcoef3 = cheb.chebfit(x, yw, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
#
|
||||
wcoef2d = cheb.chebfit(x, np.array([yw, yw]).T, 3, w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
wcoef2d = cheb.chebfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
# test scaling with complex values x points whose square
|
||||
# is zero when summed.
|
||||
x = [1, 1j, -1, -1j]
|
||||
assert_almost_equal(cheb.chebfit(x, x, 1), [0, 1])
|
||||
assert_almost_equal(cheb.chebfit(x, x, [0, 1]), [0, 1])
|
||||
# test fitting only even polynomials
|
||||
x = np.linspace(-1, 1)
|
||||
y = f2(x)
|
||||
coef1 = cheb.chebfit(x, y, 4)
|
||||
assert_almost_equal(cheb.chebval(x, coef1), y)
|
||||
coef2 = cheb.chebfit(x, y, [0, 2, 4])
|
||||
assert_almost_equal(cheb.chebval(x, coef2), y)
|
||||
assert_almost_equal(coef1, coef2)
|
||||
|
||||
|
||||
class TestInterpolate:
|
||||
|
||||
def f(self, x):
|
||||
return x * (x - 1) * (x - 2)
|
||||
|
||||
def test_raises(self):
|
||||
assert_raises(ValueError, cheb.chebinterpolate, self.f, -1)
|
||||
assert_raises(TypeError, cheb.chebinterpolate, self.f, 10.)
|
||||
|
||||
def test_dimensions(self):
|
||||
for deg in range(1, 5):
|
||||
assert_(cheb.chebinterpolate(self.f, deg).shape == (deg + 1,))
|
||||
|
||||
def test_approximation(self):
|
||||
|
||||
def powx(x, p):
|
||||
return x**p
|
||||
|
||||
x = np.linspace(-1, 1, 10)
|
||||
for deg in range(0, 10):
|
||||
for p in range(0, deg + 1):
|
||||
c = cheb.chebinterpolate(powx, deg, (p,))
|
||||
assert_almost_equal(cheb.chebval(x, c), powx(x, p), decimal=12)
|
||||
|
||||
|
||||
class TestCompanion:
|
||||
|
||||
def test_raises(self):
|
||||
assert_raises(ValueError, cheb.chebcompanion, [])
|
||||
assert_raises(ValueError, cheb.chebcompanion, [1])
|
||||
|
||||
def test_dimensions(self):
|
||||
for i in range(1, 5):
|
||||
coef = [0]*i + [1]
|
||||
assert_(cheb.chebcompanion(coef).shape == (i, i))
|
||||
|
||||
def test_linear_root(self):
|
||||
assert_(cheb.chebcompanion([1, 2])[0, 0] == -.5)
|
||||
|
||||
|
||||
class TestGauss:
|
||||
|
||||
def test_100(self):
|
||||
x, w = cheb.chebgauss(100)
|
||||
|
||||
# test orthogonality. Note that the results need to be normalized,
|
||||
# otherwise the huge values that can arise from fast growing
|
||||
# functions like Laguerre can be very confusing.
|
||||
v = cheb.chebvander(x, 99)
|
||||
vv = np.dot(v.T * w, v)
|
||||
vd = 1/np.sqrt(vv.diagonal())
|
||||
vv = vd[:, None] * vv * vd
|
||||
assert_almost_equal(vv, np.eye(100))
|
||||
|
||||
# check that the integral of 1 is correct
|
||||
tgt = np.pi
|
||||
assert_almost_equal(w.sum(), tgt)
|
||||
|
||||
|
||||
class TestMisc:
|
||||
|
||||
def test_chebfromroots(self):
|
||||
res = cheb.chebfromroots([])
|
||||
assert_almost_equal(trim(res), [1])
|
||||
for i in range(1, 5):
|
||||
roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
|
||||
tgt = [0]*i + [1]
|
||||
res = cheb.chebfromroots(roots)*2**(i-1)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_chebroots(self):
|
||||
assert_almost_equal(cheb.chebroots([1]), [])
|
||||
assert_almost_equal(cheb.chebroots([1, 2]), [-.5])
|
||||
for i in range(2, 5):
|
||||
tgt = np.linspace(-1, 1, i)
|
||||
res = cheb.chebroots(cheb.chebfromroots(tgt))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_chebtrim(self):
|
||||
coef = [2, -1, 1, 0]
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, cheb.chebtrim, coef, -1)
|
||||
|
||||
# Test results
|
||||
assert_equal(cheb.chebtrim(coef), coef[:-1])
|
||||
assert_equal(cheb.chebtrim(coef, 1), coef[:-3])
|
||||
assert_equal(cheb.chebtrim(coef, 2), [0])
|
||||
|
||||
def test_chebline(self):
|
||||
assert_equal(cheb.chebline(3, 4), [3, 4])
|
||||
|
||||
def test_cheb2poly(self):
|
||||
for i in range(10):
|
||||
assert_almost_equal(cheb.cheb2poly([0]*i + [1]), Tlist[i])
|
||||
|
||||
def test_poly2cheb(self):
|
||||
for i in range(10):
|
||||
assert_almost_equal(cheb.poly2cheb(Tlist[i]), [0]*i + [1])
|
||||
|
||||
def test_weight(self):
|
||||
x = np.linspace(-1, 1, 11)[1:-1]
|
||||
tgt = 1./(np.sqrt(1 + x) * np.sqrt(1 - x))
|
||||
res = cheb.chebweight(x)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
def test_chebpts1(self):
|
||||
#test exceptions
|
||||
assert_raises(ValueError, cheb.chebpts1, 1.5)
|
||||
assert_raises(ValueError, cheb.chebpts1, 0)
|
||||
|
||||
#test points
|
||||
tgt = [0]
|
||||
assert_almost_equal(cheb.chebpts1(1), tgt)
|
||||
tgt = [-0.70710678118654746, 0.70710678118654746]
|
||||
assert_almost_equal(cheb.chebpts1(2), tgt)
|
||||
tgt = [-0.86602540378443871, 0, 0.86602540378443871]
|
||||
assert_almost_equal(cheb.chebpts1(3), tgt)
|
||||
tgt = [-0.9238795325, -0.3826834323, 0.3826834323, 0.9238795325]
|
||||
assert_almost_equal(cheb.chebpts1(4), tgt)
|
||||
|
||||
def test_chebpts2(self):
|
||||
#test exceptions
|
||||
assert_raises(ValueError, cheb.chebpts2, 1.5)
|
||||
assert_raises(ValueError, cheb.chebpts2, 1)
|
||||
|
||||
#test points
|
||||
tgt = [-1, 1]
|
||||
assert_almost_equal(cheb.chebpts2(2), tgt)
|
||||
tgt = [-1, 0, 1]
|
||||
assert_almost_equal(cheb.chebpts2(3), tgt)
|
||||
tgt = [-1, -0.5, .5, 1]
|
||||
assert_almost_equal(cheb.chebpts2(4), tgt)
|
||||
tgt = [-1.0, -0.707106781187, 0, 0.707106781187, 1.0]
|
||||
assert_almost_equal(cheb.chebpts2(5), tgt)
|
||||
|
|
@ -0,0 +1,600 @@
|
|||
"""Test inter-conversion of different polynomial classes.
|
||||
|
||||
This tests the convert and cast methods of all the polynomial classes.
|
||||
|
||||
"""
|
||||
import operator as op
|
||||
from numbers import Number
|
||||
|
||||
import pytest
|
||||
import numpy as np
|
||||
from numpy.polynomial import (
|
||||
Polynomial, Legendre, Chebyshev, Laguerre, Hermite, HermiteE)
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
)
|
||||
from numpy.polynomial.polyutils import RankWarning
|
||||
|
||||
#
|
||||
# fixtures
|
||||
#
|
||||
|
||||
classes = (
|
||||
Polynomial, Legendre, Chebyshev, Laguerre,
|
||||
Hermite, HermiteE
|
||||
)
|
||||
classids = tuple(cls.__name__ for cls in classes)
|
||||
|
||||
@pytest.fixture(params=classes, ids=classids)
|
||||
def Poly(request):
|
||||
return request.param
|
||||
|
||||
#
|
||||
# helper functions
|
||||
#
|
||||
random = np.random.random
|
||||
|
||||
|
||||
def assert_poly_almost_equal(p1, p2, msg=""):
|
||||
try:
|
||||
assert_(np.all(p1.domain == p2.domain))
|
||||
assert_(np.all(p1.window == p2.window))
|
||||
assert_almost_equal(p1.coef, p2.coef)
|
||||
except AssertionError:
|
||||
msg = f"Result: {p1}\nTarget: {p2}"
|
||||
raise AssertionError(msg)
|
||||
|
||||
|
||||
#
|
||||
# Test conversion methods that depend on combinations of two classes.
|
||||
#
|
||||
|
||||
Poly1 = Poly
|
||||
Poly2 = Poly
|
||||
|
||||
|
||||
def test_conversion(Poly1, Poly2):
|
||||
x = np.linspace(0, 1, 10)
|
||||
coef = random((3,))
|
||||
|
||||
d1 = Poly1.domain + random((2,))*.25
|
||||
w1 = Poly1.window + random((2,))*.25
|
||||
p1 = Poly1(coef, domain=d1, window=w1)
|
||||
|
||||
d2 = Poly2.domain + random((2,))*.25
|
||||
w2 = Poly2.window + random((2,))*.25
|
||||
p2 = p1.convert(kind=Poly2, domain=d2, window=w2)
|
||||
|
||||
assert_almost_equal(p2.domain, d2)
|
||||
assert_almost_equal(p2.window, w2)
|
||||
assert_almost_equal(p2(x), p1(x))
|
||||
|
||||
|
||||
def test_cast(Poly1, Poly2):
|
||||
x = np.linspace(0, 1, 10)
|
||||
coef = random((3,))
|
||||
|
||||
d1 = Poly1.domain + random((2,))*.25
|
||||
w1 = Poly1.window + random((2,))*.25
|
||||
p1 = Poly1(coef, domain=d1, window=w1)
|
||||
|
||||
d2 = Poly2.domain + random((2,))*.25
|
||||
w2 = Poly2.window + random((2,))*.25
|
||||
p2 = Poly2.cast(p1, domain=d2, window=w2)
|
||||
|
||||
assert_almost_equal(p2.domain, d2)
|
||||
assert_almost_equal(p2.window, w2)
|
||||
assert_almost_equal(p2(x), p1(x))
|
||||
|
||||
|
||||
#
|
||||
# test methods that depend on one class
|
||||
#
|
||||
|
||||
|
||||
def test_identity(Poly):
|
||||
d = Poly.domain + random((2,))*.25
|
||||
w = Poly.window + random((2,))*.25
|
||||
x = np.linspace(d[0], d[1], 11)
|
||||
p = Poly.identity(domain=d, window=w)
|
||||
assert_equal(p.domain, d)
|
||||
assert_equal(p.window, w)
|
||||
assert_almost_equal(p(x), x)
|
||||
|
||||
|
||||
def test_basis(Poly):
|
||||
d = Poly.domain + random((2,))*.25
|
||||
w = Poly.window + random((2,))*.25
|
||||
p = Poly.basis(5, domain=d, window=w)
|
||||
assert_equal(p.domain, d)
|
||||
assert_equal(p.window, w)
|
||||
assert_equal(p.coef, [0]*5 + [1])
|
||||
|
||||
|
||||
def test_fromroots(Poly):
|
||||
# check that requested roots are zeros of a polynomial
|
||||
# of correct degree, domain, and window.
|
||||
d = Poly.domain + random((2,))*.25
|
||||
w = Poly.window + random((2,))*.25
|
||||
r = random((5,))
|
||||
p1 = Poly.fromroots(r, domain=d, window=w)
|
||||
assert_equal(p1.degree(), len(r))
|
||||
assert_equal(p1.domain, d)
|
||||
assert_equal(p1.window, w)
|
||||
assert_almost_equal(p1(r), 0)
|
||||
|
||||
# check that polynomial is monic
|
||||
pdom = Polynomial.domain
|
||||
pwin = Polynomial.window
|
||||
p2 = Polynomial.cast(p1, domain=pdom, window=pwin)
|
||||
assert_almost_equal(p2.coef[-1], 1)
|
||||
|
||||
|
||||
def test_bad_conditioned_fit(Poly):
|
||||
|
||||
x = [0., 0., 1.]
|
||||
y = [1., 2., 3.]
|
||||
|
||||
# check RankWarning is raised
|
||||
with pytest.warns(RankWarning) as record:
|
||||
Poly.fit(x, y, 2)
|
||||
assert record[0].message.args[0] == "The fit may be poorly conditioned"
|
||||
|
||||
|
||||
def test_fit(Poly):
|
||||
|
||||
def f(x):
|
||||
return x*(x - 1)*(x - 2)
|
||||
x = np.linspace(0, 3)
|
||||
y = f(x)
|
||||
|
||||
# check default value of domain and window
|
||||
p = Poly.fit(x, y, 3)
|
||||
assert_almost_equal(p.domain, [0, 3])
|
||||
assert_almost_equal(p(x), y)
|
||||
assert_equal(p.degree(), 3)
|
||||
|
||||
# check with given domains and window
|
||||
d = Poly.domain + random((2,))*.25
|
||||
w = Poly.window + random((2,))*.25
|
||||
p = Poly.fit(x, y, 3, domain=d, window=w)
|
||||
assert_almost_equal(p(x), y)
|
||||
assert_almost_equal(p.domain, d)
|
||||
assert_almost_equal(p.window, w)
|
||||
p = Poly.fit(x, y, [0, 1, 2, 3], domain=d, window=w)
|
||||
assert_almost_equal(p(x), y)
|
||||
assert_almost_equal(p.domain, d)
|
||||
assert_almost_equal(p.window, w)
|
||||
|
||||
# check with class domain default
|
||||
p = Poly.fit(x, y, 3, [])
|
||||
assert_equal(p.domain, Poly.domain)
|
||||
assert_equal(p.window, Poly.window)
|
||||
p = Poly.fit(x, y, [0, 1, 2, 3], [])
|
||||
assert_equal(p.domain, Poly.domain)
|
||||
assert_equal(p.window, Poly.window)
|
||||
|
||||
# check that fit accepts weights.
|
||||
w = np.zeros_like(x)
|
||||
z = y + random(y.shape)*.25
|
||||
w[::2] = 1
|
||||
p1 = Poly.fit(x[::2], z[::2], 3)
|
||||
p2 = Poly.fit(x, z, 3, w=w)
|
||||
p3 = Poly.fit(x, z, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(p1(x), p2(x))
|
||||
assert_almost_equal(p2(x), p3(x))
|
||||
|
||||
|
||||
def test_equal(Poly):
|
||||
p1 = Poly([1, 2, 3], domain=[0, 1], window=[2, 3])
|
||||
p2 = Poly([1, 1, 1], domain=[0, 1], window=[2, 3])
|
||||
p3 = Poly([1, 2, 3], domain=[1, 2], window=[2, 3])
|
||||
p4 = Poly([1, 2, 3], domain=[0, 1], window=[1, 2])
|
||||
assert_(p1 == p1)
|
||||
assert_(not p1 == p2)
|
||||
assert_(not p1 == p3)
|
||||
assert_(not p1 == p4)
|
||||
|
||||
|
||||
def test_not_equal(Poly):
|
||||
p1 = Poly([1, 2, 3], domain=[0, 1], window=[2, 3])
|
||||
p2 = Poly([1, 1, 1], domain=[0, 1], window=[2, 3])
|
||||
p3 = Poly([1, 2, 3], domain=[1, 2], window=[2, 3])
|
||||
p4 = Poly([1, 2, 3], domain=[0, 1], window=[1, 2])
|
||||
assert_(not p1 != p1)
|
||||
assert_(p1 != p2)
|
||||
assert_(p1 != p3)
|
||||
assert_(p1 != p4)
|
||||
|
||||
|
||||
def test_add(Poly):
|
||||
# This checks commutation, not numerical correctness
|
||||
c1 = list(random((4,)) + .5)
|
||||
c2 = list(random((3,)) + .5)
|
||||
p1 = Poly(c1)
|
||||
p2 = Poly(c2)
|
||||
p3 = p1 + p2
|
||||
assert_poly_almost_equal(p2 + p1, p3)
|
||||
assert_poly_almost_equal(p1 + c2, p3)
|
||||
assert_poly_almost_equal(c2 + p1, p3)
|
||||
assert_poly_almost_equal(p1 + tuple(c2), p3)
|
||||
assert_poly_almost_equal(tuple(c2) + p1, p3)
|
||||
assert_poly_almost_equal(p1 + np.array(c2), p3)
|
||||
assert_poly_almost_equal(np.array(c2) + p1, p3)
|
||||
assert_raises(TypeError, op.add, p1, Poly([0], domain=Poly.domain + 1))
|
||||
assert_raises(TypeError, op.add, p1, Poly([0], window=Poly.window + 1))
|
||||
if Poly is Polynomial:
|
||||
assert_raises(TypeError, op.add, p1, Chebyshev([0]))
|
||||
else:
|
||||
assert_raises(TypeError, op.add, p1, Polynomial([0]))
|
||||
|
||||
|
||||
def test_sub(Poly):
|
||||
# This checks commutation, not numerical correctness
|
||||
c1 = list(random((4,)) + .5)
|
||||
c2 = list(random((3,)) + .5)
|
||||
p1 = Poly(c1)
|
||||
p2 = Poly(c2)
|
||||
p3 = p1 - p2
|
||||
assert_poly_almost_equal(p2 - p1, -p3)
|
||||
assert_poly_almost_equal(p1 - c2, p3)
|
||||
assert_poly_almost_equal(c2 - p1, -p3)
|
||||
assert_poly_almost_equal(p1 - tuple(c2), p3)
|
||||
assert_poly_almost_equal(tuple(c2) - p1, -p3)
|
||||
assert_poly_almost_equal(p1 - np.array(c2), p3)
|
||||
assert_poly_almost_equal(np.array(c2) - p1, -p3)
|
||||
assert_raises(TypeError, op.sub, p1, Poly([0], domain=Poly.domain + 1))
|
||||
assert_raises(TypeError, op.sub, p1, Poly([0], window=Poly.window + 1))
|
||||
if Poly is Polynomial:
|
||||
assert_raises(TypeError, op.sub, p1, Chebyshev([0]))
|
||||
else:
|
||||
assert_raises(TypeError, op.sub, p1, Polynomial([0]))
|
||||
|
||||
|
||||
def test_mul(Poly):
|
||||
c1 = list(random((4,)) + .5)
|
||||
c2 = list(random((3,)) + .5)
|
||||
p1 = Poly(c1)
|
||||
p2 = Poly(c2)
|
||||
p3 = p1 * p2
|
||||
assert_poly_almost_equal(p2 * p1, p3)
|
||||
assert_poly_almost_equal(p1 * c2, p3)
|
||||
assert_poly_almost_equal(c2 * p1, p3)
|
||||
assert_poly_almost_equal(p1 * tuple(c2), p3)
|
||||
assert_poly_almost_equal(tuple(c2) * p1, p3)
|
||||
assert_poly_almost_equal(p1 * np.array(c2), p3)
|
||||
assert_poly_almost_equal(np.array(c2) * p1, p3)
|
||||
assert_poly_almost_equal(p1 * 2, p1 * Poly([2]))
|
||||
assert_poly_almost_equal(2 * p1, p1 * Poly([2]))
|
||||
assert_raises(TypeError, op.mul, p1, Poly([0], domain=Poly.domain + 1))
|
||||
assert_raises(TypeError, op.mul, p1, Poly([0], window=Poly.window + 1))
|
||||
if Poly is Polynomial:
|
||||
assert_raises(TypeError, op.mul, p1, Chebyshev([0]))
|
||||
else:
|
||||
assert_raises(TypeError, op.mul, p1, Polynomial([0]))
|
||||
|
||||
|
||||
def test_floordiv(Poly):
|
||||
c1 = list(random((4,)) + .5)
|
||||
c2 = list(random((3,)) + .5)
|
||||
c3 = list(random((2,)) + .5)
|
||||
p1 = Poly(c1)
|
||||
p2 = Poly(c2)
|
||||
p3 = Poly(c3)
|
||||
p4 = p1 * p2 + p3
|
||||
c4 = list(p4.coef)
|
||||
assert_poly_almost_equal(p4 // p2, p1)
|
||||
assert_poly_almost_equal(p4 // c2, p1)
|
||||
assert_poly_almost_equal(c4 // p2, p1)
|
||||
assert_poly_almost_equal(p4 // tuple(c2), p1)
|
||||
assert_poly_almost_equal(tuple(c4) // p2, p1)
|
||||
assert_poly_almost_equal(p4 // np.array(c2), p1)
|
||||
assert_poly_almost_equal(np.array(c4) // p2, p1)
|
||||
assert_poly_almost_equal(2 // p2, Poly([0]))
|
||||
assert_poly_almost_equal(p2 // 2, 0.5*p2)
|
||||
assert_raises(
|
||||
TypeError, op.floordiv, p1, Poly([0], domain=Poly.domain + 1))
|
||||
assert_raises(
|
||||
TypeError, op.floordiv, p1, Poly([0], window=Poly.window + 1))
|
||||
if Poly is Polynomial:
|
||||
assert_raises(TypeError, op.floordiv, p1, Chebyshev([0]))
|
||||
else:
|
||||
assert_raises(TypeError, op.floordiv, p1, Polynomial([0]))
|
||||
|
||||
|
||||
def test_truediv(Poly):
|
||||
# true division is valid only if the denominator is a Number and
|
||||
# not a python bool.
|
||||
p1 = Poly([1,2,3])
|
||||
p2 = p1 * 5
|
||||
|
||||
for stype in np.ScalarType:
|
||||
if not issubclass(stype, Number) or issubclass(stype, bool):
|
||||
continue
|
||||
s = stype(5)
|
||||
assert_poly_almost_equal(op.truediv(p2, s), p1)
|
||||
assert_raises(TypeError, op.truediv, s, p2)
|
||||
for stype in (int, float):
|
||||
s = stype(5)
|
||||
assert_poly_almost_equal(op.truediv(p2, s), p1)
|
||||
assert_raises(TypeError, op.truediv, s, p2)
|
||||
for stype in [complex]:
|
||||
s = stype(5, 0)
|
||||
assert_poly_almost_equal(op.truediv(p2, s), p1)
|
||||
assert_raises(TypeError, op.truediv, s, p2)
|
||||
for s in [tuple(), list(), dict(), bool(), np.array([1])]:
|
||||
assert_raises(TypeError, op.truediv, p2, s)
|
||||
assert_raises(TypeError, op.truediv, s, p2)
|
||||
for ptype in classes:
|
||||
assert_raises(TypeError, op.truediv, p2, ptype(1))
|
||||
|
||||
|
||||
def test_mod(Poly):
|
||||
# This checks commutation, not numerical correctness
|
||||
c1 = list(random((4,)) + .5)
|
||||
c2 = list(random((3,)) + .5)
|
||||
c3 = list(random((2,)) + .5)
|
||||
p1 = Poly(c1)
|
||||
p2 = Poly(c2)
|
||||
p3 = Poly(c3)
|
||||
p4 = p1 * p2 + p3
|
||||
c4 = list(p4.coef)
|
||||
assert_poly_almost_equal(p4 % p2, p3)
|
||||
assert_poly_almost_equal(p4 % c2, p3)
|
||||
assert_poly_almost_equal(c4 % p2, p3)
|
||||
assert_poly_almost_equal(p4 % tuple(c2), p3)
|
||||
assert_poly_almost_equal(tuple(c4) % p2, p3)
|
||||
assert_poly_almost_equal(p4 % np.array(c2), p3)
|
||||
assert_poly_almost_equal(np.array(c4) % p2, p3)
|
||||
assert_poly_almost_equal(2 % p2, Poly([2]))
|
||||
assert_poly_almost_equal(p2 % 2, Poly([0]))
|
||||
assert_raises(TypeError, op.mod, p1, Poly([0], domain=Poly.domain + 1))
|
||||
assert_raises(TypeError, op.mod, p1, Poly([0], window=Poly.window + 1))
|
||||
if Poly is Polynomial:
|
||||
assert_raises(TypeError, op.mod, p1, Chebyshev([0]))
|
||||
else:
|
||||
assert_raises(TypeError, op.mod, p1, Polynomial([0]))
|
||||
|
||||
|
||||
def test_divmod(Poly):
|
||||
# This checks commutation, not numerical correctness
|
||||
c1 = list(random((4,)) + .5)
|
||||
c2 = list(random((3,)) + .5)
|
||||
c3 = list(random((2,)) + .5)
|
||||
p1 = Poly(c1)
|
||||
p2 = Poly(c2)
|
||||
p3 = Poly(c3)
|
||||
p4 = p1 * p2 + p3
|
||||
c4 = list(p4.coef)
|
||||
quo, rem = divmod(p4, p2)
|
||||
assert_poly_almost_equal(quo, p1)
|
||||
assert_poly_almost_equal(rem, p3)
|
||||
quo, rem = divmod(p4, c2)
|
||||
assert_poly_almost_equal(quo, p1)
|
||||
assert_poly_almost_equal(rem, p3)
|
||||
quo, rem = divmod(c4, p2)
|
||||
assert_poly_almost_equal(quo, p1)
|
||||
assert_poly_almost_equal(rem, p3)
|
||||
quo, rem = divmod(p4, tuple(c2))
|
||||
assert_poly_almost_equal(quo, p1)
|
||||
assert_poly_almost_equal(rem, p3)
|
||||
quo, rem = divmod(tuple(c4), p2)
|
||||
assert_poly_almost_equal(quo, p1)
|
||||
assert_poly_almost_equal(rem, p3)
|
||||
quo, rem = divmod(p4, np.array(c2))
|
||||
assert_poly_almost_equal(quo, p1)
|
||||
assert_poly_almost_equal(rem, p3)
|
||||
quo, rem = divmod(np.array(c4), p2)
|
||||
assert_poly_almost_equal(quo, p1)
|
||||
assert_poly_almost_equal(rem, p3)
|
||||
quo, rem = divmod(p2, 2)
|
||||
assert_poly_almost_equal(quo, 0.5*p2)
|
||||
assert_poly_almost_equal(rem, Poly([0]))
|
||||
quo, rem = divmod(2, p2)
|
||||
assert_poly_almost_equal(quo, Poly([0]))
|
||||
assert_poly_almost_equal(rem, Poly([2]))
|
||||
assert_raises(TypeError, divmod, p1, Poly([0], domain=Poly.domain + 1))
|
||||
assert_raises(TypeError, divmod, p1, Poly([0], window=Poly.window + 1))
|
||||
if Poly is Polynomial:
|
||||
assert_raises(TypeError, divmod, p1, Chebyshev([0]))
|
||||
else:
|
||||
assert_raises(TypeError, divmod, p1, Polynomial([0]))
|
||||
|
||||
|
||||
def test_roots(Poly):
|
||||
d = Poly.domain * 1.25 + .25
|
||||
w = Poly.window
|
||||
tgt = np.linspace(d[0], d[1], 5)
|
||||
res = np.sort(Poly.fromroots(tgt, domain=d, window=w).roots())
|
||||
assert_almost_equal(res, tgt)
|
||||
# default domain and window
|
||||
res = np.sort(Poly.fromroots(tgt).roots())
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
def test_degree(Poly):
|
||||
p = Poly.basis(5)
|
||||
assert_equal(p.degree(), 5)
|
||||
|
||||
|
||||
def test_copy(Poly):
|
||||
p1 = Poly.basis(5)
|
||||
p2 = p1.copy()
|
||||
assert_(p1 == p2)
|
||||
assert_(p1 is not p2)
|
||||
assert_(p1.coef is not p2.coef)
|
||||
assert_(p1.domain is not p2.domain)
|
||||
assert_(p1.window is not p2.window)
|
||||
|
||||
|
||||
def test_integ(Poly):
|
||||
P = Polynomial
|
||||
# Check defaults
|
||||
p0 = Poly.cast(P([1*2, 2*3, 3*4]))
|
||||
p1 = P.cast(p0.integ())
|
||||
p2 = P.cast(p0.integ(2))
|
||||
assert_poly_almost_equal(p1, P([0, 2, 3, 4]))
|
||||
assert_poly_almost_equal(p2, P([0, 0, 1, 1, 1]))
|
||||
# Check with k
|
||||
p0 = Poly.cast(P([1*2, 2*3, 3*4]))
|
||||
p1 = P.cast(p0.integ(k=1))
|
||||
p2 = P.cast(p0.integ(2, k=[1, 1]))
|
||||
assert_poly_almost_equal(p1, P([1, 2, 3, 4]))
|
||||
assert_poly_almost_equal(p2, P([1, 1, 1, 1, 1]))
|
||||
# Check with lbnd
|
||||
p0 = Poly.cast(P([1*2, 2*3, 3*4]))
|
||||
p1 = P.cast(p0.integ(lbnd=1))
|
||||
p2 = P.cast(p0.integ(2, lbnd=1))
|
||||
assert_poly_almost_equal(p1, P([-9, 2, 3, 4]))
|
||||
assert_poly_almost_equal(p2, P([6, -9, 1, 1, 1]))
|
||||
# Check scaling
|
||||
d = 2*Poly.domain
|
||||
p0 = Poly.cast(P([1*2, 2*3, 3*4]), domain=d)
|
||||
p1 = P.cast(p0.integ())
|
||||
p2 = P.cast(p0.integ(2))
|
||||
assert_poly_almost_equal(p1, P([0, 2, 3, 4]))
|
||||
assert_poly_almost_equal(p2, P([0, 0, 1, 1, 1]))
|
||||
|
||||
|
||||
def test_deriv(Poly):
|
||||
# Check that the derivative is the inverse of integration. It is
|
||||
# assumes that the integration has been checked elsewhere.
|
||||
d = Poly.domain + random((2,))*.25
|
||||
w = Poly.window + random((2,))*.25
|
||||
p1 = Poly([1, 2, 3], domain=d, window=w)
|
||||
p2 = p1.integ(2, k=[1, 2])
|
||||
p3 = p1.integ(1, k=[1])
|
||||
assert_almost_equal(p2.deriv(1).coef, p3.coef)
|
||||
assert_almost_equal(p2.deriv(2).coef, p1.coef)
|
||||
# default domain and window
|
||||
p1 = Poly([1, 2, 3])
|
||||
p2 = p1.integ(2, k=[1, 2])
|
||||
p3 = p1.integ(1, k=[1])
|
||||
assert_almost_equal(p2.deriv(1).coef, p3.coef)
|
||||
assert_almost_equal(p2.deriv(2).coef, p1.coef)
|
||||
|
||||
|
||||
def test_linspace(Poly):
|
||||
d = Poly.domain + random((2,))*.25
|
||||
w = Poly.window + random((2,))*.25
|
||||
p = Poly([1, 2, 3], domain=d, window=w)
|
||||
# check default domain
|
||||
xtgt = np.linspace(d[0], d[1], 20)
|
||||
ytgt = p(xtgt)
|
||||
xres, yres = p.linspace(20)
|
||||
assert_almost_equal(xres, xtgt)
|
||||
assert_almost_equal(yres, ytgt)
|
||||
# check specified domain
|
||||
xtgt = np.linspace(0, 2, 20)
|
||||
ytgt = p(xtgt)
|
||||
xres, yres = p.linspace(20, domain=[0, 2])
|
||||
assert_almost_equal(xres, xtgt)
|
||||
assert_almost_equal(yres, ytgt)
|
||||
|
||||
|
||||
def test_pow(Poly):
|
||||
d = Poly.domain + random((2,))*.25
|
||||
w = Poly.window + random((2,))*.25
|
||||
tgt = Poly([1], domain=d, window=w)
|
||||
tst = Poly([1, 2, 3], domain=d, window=w)
|
||||
for i in range(5):
|
||||
assert_poly_almost_equal(tst**i, tgt)
|
||||
tgt = tgt * tst
|
||||
# default domain and window
|
||||
tgt = Poly([1])
|
||||
tst = Poly([1, 2, 3])
|
||||
for i in range(5):
|
||||
assert_poly_almost_equal(tst**i, tgt)
|
||||
tgt = tgt * tst
|
||||
# check error for invalid powers
|
||||
assert_raises(ValueError, op.pow, tgt, 1.5)
|
||||
assert_raises(ValueError, op.pow, tgt, -1)
|
||||
|
||||
|
||||
def test_call(Poly):
|
||||
P = Polynomial
|
||||
d = Poly.domain
|
||||
x = np.linspace(d[0], d[1], 11)
|
||||
|
||||
# Check defaults
|
||||
p = Poly.cast(P([1, 2, 3]))
|
||||
tgt = 1 + x*(2 + 3*x)
|
||||
res = p(x)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
def test_cutdeg(Poly):
|
||||
p = Poly([1, 2, 3])
|
||||
assert_raises(ValueError, p.cutdeg, .5)
|
||||
assert_raises(ValueError, p.cutdeg, -1)
|
||||
assert_equal(len(p.cutdeg(3)), 3)
|
||||
assert_equal(len(p.cutdeg(2)), 3)
|
||||
assert_equal(len(p.cutdeg(1)), 2)
|
||||
assert_equal(len(p.cutdeg(0)), 1)
|
||||
|
||||
|
||||
def test_truncate(Poly):
|
||||
p = Poly([1, 2, 3])
|
||||
assert_raises(ValueError, p.truncate, .5)
|
||||
assert_raises(ValueError, p.truncate, 0)
|
||||
assert_equal(len(p.truncate(4)), 3)
|
||||
assert_equal(len(p.truncate(3)), 3)
|
||||
assert_equal(len(p.truncate(2)), 2)
|
||||
assert_equal(len(p.truncate(1)), 1)
|
||||
|
||||
|
||||
def test_trim(Poly):
|
||||
c = [1, 1e-6, 1e-12, 0]
|
||||
p = Poly(c)
|
||||
assert_equal(p.trim().coef, c[:3])
|
||||
assert_equal(p.trim(1e-10).coef, c[:2])
|
||||
assert_equal(p.trim(1e-5).coef, c[:1])
|
||||
|
||||
|
||||
def test_mapparms(Poly):
|
||||
# check with defaults. Should be identity.
|
||||
d = Poly.domain
|
||||
w = Poly.window
|
||||
p = Poly([1], domain=d, window=w)
|
||||
assert_almost_equal([0, 1], p.mapparms())
|
||||
#
|
||||
w = 2*d + 1
|
||||
p = Poly([1], domain=d, window=w)
|
||||
assert_almost_equal([1, 2], p.mapparms())
|
||||
|
||||
|
||||
def test_ufunc_override(Poly):
|
||||
p = Poly([1, 2, 3])
|
||||
x = np.ones(3)
|
||||
assert_raises(TypeError, np.add, p, x)
|
||||
assert_raises(TypeError, np.add, x, p)
|
||||
|
||||
|
||||
#
|
||||
# Test class method that only exists for some classes
|
||||
#
|
||||
|
||||
|
||||
class TestInterpolate:
|
||||
|
||||
def f(self, x):
|
||||
return x * (x - 1) * (x - 2)
|
||||
|
||||
def test_raises(self):
|
||||
assert_raises(ValueError, Chebyshev.interpolate, self.f, -1)
|
||||
assert_raises(TypeError, Chebyshev.interpolate, self.f, 10.)
|
||||
|
||||
def test_dimensions(self):
|
||||
for deg in range(1, 5):
|
||||
assert_(Chebyshev.interpolate(self.f, deg).degree() == deg)
|
||||
|
||||
def test_approximation(self):
|
||||
|
||||
def powx(x, p):
|
||||
return x**p
|
||||
|
||||
x = np.linspace(0, 2, 10)
|
||||
for deg in range(0, 10):
|
||||
for t in range(0, deg + 1):
|
||||
p = Chebyshev.interpolate(powx, deg, domain=[0, 2], args=(t,))
|
||||
assert_almost_equal(p(x), powx(x, t), decimal=11)
|
||||
|
|
@ -0,0 +1,555 @@
|
|||
"""Tests for hermite module.
|
||||
|
||||
"""
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
import numpy.polynomial.hermite as herm
|
||||
from numpy.polynomial.polynomial import polyval
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
)
|
||||
|
||||
H0 = np.array([1])
|
||||
H1 = np.array([0, 2])
|
||||
H2 = np.array([-2, 0, 4])
|
||||
H3 = np.array([0, -12, 0, 8])
|
||||
H4 = np.array([12, 0, -48, 0, 16])
|
||||
H5 = np.array([0, 120, 0, -160, 0, 32])
|
||||
H6 = np.array([-120, 0, 720, 0, -480, 0, 64])
|
||||
H7 = np.array([0, -1680, 0, 3360, 0, -1344, 0, 128])
|
||||
H8 = np.array([1680, 0, -13440, 0, 13440, 0, -3584, 0, 256])
|
||||
H9 = np.array([0, 30240, 0, -80640, 0, 48384, 0, -9216, 0, 512])
|
||||
|
||||
Hlist = [H0, H1, H2, H3, H4, H5, H6, H7, H8, H9]
|
||||
|
||||
|
||||
def trim(x):
|
||||
return herm.hermtrim(x, tol=1e-6)
|
||||
|
||||
|
||||
class TestConstants:
|
||||
|
||||
def test_hermdomain(self):
|
||||
assert_equal(herm.hermdomain, [-1, 1])
|
||||
|
||||
def test_hermzero(self):
|
||||
assert_equal(herm.hermzero, [0])
|
||||
|
||||
def test_hermone(self):
|
||||
assert_equal(herm.hermone, [1])
|
||||
|
||||
def test_hermx(self):
|
||||
assert_equal(herm.hermx, [0, .5])
|
||||
|
||||
|
||||
class TestArithmetic:
|
||||
x = np.linspace(-3, 3, 100)
|
||||
|
||||
def test_hermadd(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] += 1
|
||||
res = herm.hermadd([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_hermsub(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] -= 1
|
||||
res = herm.hermsub([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_hermmulx(self):
|
||||
assert_equal(herm.hermmulx([0]), [0])
|
||||
assert_equal(herm.hermmulx([1]), [0, .5])
|
||||
for i in range(1, 5):
|
||||
ser = [0]*i + [1]
|
||||
tgt = [0]*(i - 1) + [i, 0, .5]
|
||||
assert_equal(herm.hermmulx(ser), tgt)
|
||||
|
||||
def test_hermmul(self):
|
||||
# check values of result
|
||||
for i in range(5):
|
||||
pol1 = [0]*i + [1]
|
||||
val1 = herm.hermval(self.x, pol1)
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
pol2 = [0]*j + [1]
|
||||
val2 = herm.hermval(self.x, pol2)
|
||||
pol3 = herm.hermmul(pol1, pol2)
|
||||
val3 = herm.hermval(self.x, pol3)
|
||||
assert_(len(pol3) == i + j + 1, msg)
|
||||
assert_almost_equal(val3, val1*val2, err_msg=msg)
|
||||
|
||||
def test_hermdiv(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
ci = [0]*i + [1]
|
||||
cj = [0]*j + [1]
|
||||
tgt = herm.hermadd(ci, cj)
|
||||
quo, rem = herm.hermdiv(tgt, ci)
|
||||
res = herm.hermadd(herm.hermmul(quo, ci), rem)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_hermpow(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
c = np.arange(i + 1)
|
||||
tgt = reduce(herm.hermmul, [c]*j, np.array([1]))
|
||||
res = herm.hermpow(c, j)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
|
||||
class TestEvaluation:
|
||||
# coefficients of 1 + 2*x + 3*x**2
|
||||
c1d = np.array([2.5, 1., .75])
|
||||
c2d = np.einsum('i,j->ij', c1d, c1d)
|
||||
c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
|
||||
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
y = polyval(x, [1., 2., 3.])
|
||||
|
||||
def test_hermval(self):
|
||||
#check empty input
|
||||
assert_equal(herm.hermval([], [1]).size, 0)
|
||||
|
||||
#check normal input)
|
||||
x = np.linspace(-1, 1)
|
||||
y = [polyval(x, c) for c in Hlist]
|
||||
for i in range(10):
|
||||
msg = f"At i={i}"
|
||||
tgt = y[i]
|
||||
res = herm.hermval(x, [0]*i + [1])
|
||||
assert_almost_equal(res, tgt, err_msg=msg)
|
||||
|
||||
#check that shape is preserved
|
||||
for i in range(3):
|
||||
dims = [2]*i
|
||||
x = np.zeros(dims)
|
||||
assert_equal(herm.hermval(x, [1]).shape, dims)
|
||||
assert_equal(herm.hermval(x, [1, 0]).shape, dims)
|
||||
assert_equal(herm.hermval(x, [1, 0, 0]).shape, dims)
|
||||
|
||||
def test_hermval2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, herm.hermval2d, x1, x2[:2], self.c2d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2
|
||||
res = herm.hermval2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = herm.hermval2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_hermval3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, herm.hermval3d, x1, x2, x3[:2], self.c3d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2*y3
|
||||
res = herm.hermval3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = herm.hermval3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_hermgrid2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j->ij', y1, y2)
|
||||
res = herm.hermgrid2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = herm.hermgrid2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3)*2)
|
||||
|
||||
def test_hermgrid3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
|
||||
res = herm.hermgrid3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = herm.hermgrid3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3)*3)
|
||||
|
||||
|
||||
class TestIntegral:
|
||||
|
||||
def test_hermint(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, herm.hermint, [0], .5)
|
||||
assert_raises(ValueError, herm.hermint, [0], -1)
|
||||
assert_raises(ValueError, herm.hermint, [0], 1, [0, 0])
|
||||
assert_raises(ValueError, herm.hermint, [0], lbnd=[0])
|
||||
assert_raises(ValueError, herm.hermint, [0], scl=[0])
|
||||
assert_raises(TypeError, herm.hermint, [0], axis=.5)
|
||||
|
||||
# test integration of zero polynomial
|
||||
for i in range(2, 5):
|
||||
k = [0]*(i - 2) + [1]
|
||||
res = herm.hermint([0], m=i, k=k)
|
||||
assert_almost_equal(res, [0, .5])
|
||||
|
||||
# check single integration with integration constant
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [1/scl]
|
||||
hermpol = herm.poly2herm(pol)
|
||||
hermint = herm.hermint(hermpol, m=1, k=[i])
|
||||
res = herm.herm2poly(hermint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check single integration with integration constant and lbnd
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
hermpol = herm.poly2herm(pol)
|
||||
hermint = herm.hermint(hermpol, m=1, k=[i], lbnd=-1)
|
||||
assert_almost_equal(herm.hermval(-1, hermint), i)
|
||||
|
||||
# check single integration with integration constant and scaling
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [2/scl]
|
||||
hermpol = herm.poly2herm(pol)
|
||||
hermint = herm.hermint(hermpol, m=1, k=[i], scl=2)
|
||||
res = herm.herm2poly(hermint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with default k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = herm.hermint(tgt, m=1)
|
||||
res = herm.hermint(pol, m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with defined k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = herm.hermint(tgt, m=1, k=[k])
|
||||
res = herm.hermint(pol, m=j, k=list(range(j)))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with lbnd
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = herm.hermint(tgt, m=1, k=[k], lbnd=-1)
|
||||
res = herm.hermint(pol, m=j, k=list(range(j)), lbnd=-1)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = herm.hermint(tgt, m=1, k=[k], scl=2)
|
||||
res = herm.hermint(pol, m=j, k=list(range(j)), scl=2)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_hermint_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([herm.hermint(c) for c in c2d.T]).T
|
||||
res = herm.hermint(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([herm.hermint(c) for c in c2d])
|
||||
res = herm.hermint(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([herm.hermint(c, k=3) for c in c2d])
|
||||
res = herm.hermint(c2d, k=3, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestDerivative:
|
||||
|
||||
def test_hermder(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, herm.hermder, [0], .5)
|
||||
assert_raises(ValueError, herm.hermder, [0], -1)
|
||||
|
||||
# check that zeroth derivative does nothing
|
||||
for i in range(5):
|
||||
tgt = [0]*i + [1]
|
||||
res = herm.hermder(tgt, m=0)
|
||||
assert_equal(trim(res), trim(tgt))
|
||||
|
||||
# check that derivation is the inverse of integration
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = herm.hermder(herm.hermint(tgt, m=j), m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check derivation with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = herm.hermder(herm.hermint(tgt, m=j, scl=2), m=j, scl=.5)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_hermder_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([herm.hermder(c) for c in c2d.T]).T
|
||||
res = herm.hermder(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([herm.hermder(c) for c in c2d])
|
||||
res = herm.hermder(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestVander:
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
|
||||
def test_hermvander(self):
|
||||
# check for 1d x
|
||||
x = np.arange(3)
|
||||
v = herm.hermvander(x, 3)
|
||||
assert_(v.shape == (3, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], herm.hermval(x, coef))
|
||||
|
||||
# check for 2d x
|
||||
x = np.array([[1, 2], [3, 4], [5, 6]])
|
||||
v = herm.hermvander(x, 3)
|
||||
assert_(v.shape == (3, 2, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], herm.hermval(x, coef))
|
||||
|
||||
def test_hermvander2d(self):
|
||||
# also tests hermval2d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3))
|
||||
van = herm.hermvander2d(x1, x2, [1, 2])
|
||||
tgt = herm.hermval2d(x1, x2, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = herm.hermvander2d([x1], [x2], [1, 2])
|
||||
assert_(van.shape == (1, 5, 6))
|
||||
|
||||
def test_hermvander3d(self):
|
||||
# also tests hermval3d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3, 4))
|
||||
van = herm.hermvander3d(x1, x2, x3, [1, 2, 3])
|
||||
tgt = herm.hermval3d(x1, x2, x3, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = herm.hermvander3d([x1], [x2], [x3], [1, 2, 3])
|
||||
assert_(van.shape == (1, 5, 24))
|
||||
|
||||
|
||||
class TestFitting:
|
||||
|
||||
def test_hermfit(self):
|
||||
def f(x):
|
||||
return x*(x - 1)*(x - 2)
|
||||
|
||||
def f2(x):
|
||||
return x**4 + x**2 + 1
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, herm.hermfit, [1], [1], -1)
|
||||
assert_raises(TypeError, herm.hermfit, [[1]], [1], 0)
|
||||
assert_raises(TypeError, herm.hermfit, [], [1], 0)
|
||||
assert_raises(TypeError, herm.hermfit, [1], [[[1]]], 0)
|
||||
assert_raises(TypeError, herm.hermfit, [1, 2], [1], 0)
|
||||
assert_raises(TypeError, herm.hermfit, [1], [1, 2], 0)
|
||||
assert_raises(TypeError, herm.hermfit, [1], [1], 0, w=[[1]])
|
||||
assert_raises(TypeError, herm.hermfit, [1], [1], 0, w=[1, 1])
|
||||
assert_raises(ValueError, herm.hermfit, [1], [1], [-1,])
|
||||
assert_raises(ValueError, herm.hermfit, [1], [1], [2, -1, 6])
|
||||
assert_raises(TypeError, herm.hermfit, [1], [1], [])
|
||||
|
||||
# Test fit
|
||||
x = np.linspace(0, 2)
|
||||
y = f(x)
|
||||
#
|
||||
coef3 = herm.hermfit(x, y, 3)
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(herm.hermval(x, coef3), y)
|
||||
coef3 = herm.hermfit(x, y, [0, 1, 2, 3])
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(herm.hermval(x, coef3), y)
|
||||
#
|
||||
coef4 = herm.hermfit(x, y, 4)
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(herm.hermval(x, coef4), y)
|
||||
coef4 = herm.hermfit(x, y, [0, 1, 2, 3, 4])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(herm.hermval(x, coef4), y)
|
||||
# check things still work if deg is not in strict increasing
|
||||
coef4 = herm.hermfit(x, y, [2, 3, 4, 1, 0])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(herm.hermval(x, coef4), y)
|
||||
#
|
||||
coef2d = herm.hermfit(x, np.array([y, y]).T, 3)
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
coef2d = herm.hermfit(x, np.array([y, y]).T, [0, 1, 2, 3])
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
# test weighting
|
||||
w = np.zeros_like(x)
|
||||
yw = y.copy()
|
||||
w[1::2] = 1
|
||||
y[0::2] = 0
|
||||
wcoef3 = herm.hermfit(x, yw, 3, w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
wcoef3 = herm.hermfit(x, yw, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
#
|
||||
wcoef2d = herm.hermfit(x, np.array([yw, yw]).T, 3, w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
wcoef2d = herm.hermfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
# test scaling with complex values x points whose square
|
||||
# is zero when summed.
|
||||
x = [1, 1j, -1, -1j]
|
||||
assert_almost_equal(herm.hermfit(x, x, 1), [0, .5])
|
||||
assert_almost_equal(herm.hermfit(x, x, [0, 1]), [0, .5])
|
||||
# test fitting only even Legendre polynomials
|
||||
x = np.linspace(-1, 1)
|
||||
y = f2(x)
|
||||
coef1 = herm.hermfit(x, y, 4)
|
||||
assert_almost_equal(herm.hermval(x, coef1), y)
|
||||
coef2 = herm.hermfit(x, y, [0, 2, 4])
|
||||
assert_almost_equal(herm.hermval(x, coef2), y)
|
||||
assert_almost_equal(coef1, coef2)
|
||||
|
||||
|
||||
class TestCompanion:
|
||||
|
||||
def test_raises(self):
|
||||
assert_raises(ValueError, herm.hermcompanion, [])
|
||||
assert_raises(ValueError, herm.hermcompanion, [1])
|
||||
|
||||
def test_dimensions(self):
|
||||
for i in range(1, 5):
|
||||
coef = [0]*i + [1]
|
||||
assert_(herm.hermcompanion(coef).shape == (i, i))
|
||||
|
||||
def test_linear_root(self):
|
||||
assert_(herm.hermcompanion([1, 2])[0, 0] == -.25)
|
||||
|
||||
|
||||
class TestGauss:
|
||||
|
||||
def test_100(self):
|
||||
x, w = herm.hermgauss(100)
|
||||
|
||||
# test orthogonality. Note that the results need to be normalized,
|
||||
# otherwise the huge values that can arise from fast growing
|
||||
# functions like Laguerre can be very confusing.
|
||||
v = herm.hermvander(x, 99)
|
||||
vv = np.dot(v.T * w, v)
|
||||
vd = 1/np.sqrt(vv.diagonal())
|
||||
vv = vd[:, None] * vv * vd
|
||||
assert_almost_equal(vv, np.eye(100))
|
||||
|
||||
# check that the integral of 1 is correct
|
||||
tgt = np.sqrt(np.pi)
|
||||
assert_almost_equal(w.sum(), tgt)
|
||||
|
||||
|
||||
class TestMisc:
|
||||
|
||||
def test_hermfromroots(self):
|
||||
res = herm.hermfromroots([])
|
||||
assert_almost_equal(trim(res), [1])
|
||||
for i in range(1, 5):
|
||||
roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
|
||||
pol = herm.hermfromroots(roots)
|
||||
res = herm.hermval(roots, pol)
|
||||
tgt = 0
|
||||
assert_(len(pol) == i + 1)
|
||||
assert_almost_equal(herm.herm2poly(pol)[-1], 1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
def test_hermroots(self):
|
||||
assert_almost_equal(herm.hermroots([1]), [])
|
||||
assert_almost_equal(herm.hermroots([1, 1]), [-.5])
|
||||
for i in range(2, 5):
|
||||
tgt = np.linspace(-1, 1, i)
|
||||
res = herm.hermroots(herm.hermfromroots(tgt))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_hermtrim(self):
|
||||
coef = [2, -1, 1, 0]
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, herm.hermtrim, coef, -1)
|
||||
|
||||
# Test results
|
||||
assert_equal(herm.hermtrim(coef), coef[:-1])
|
||||
assert_equal(herm.hermtrim(coef, 1), coef[:-3])
|
||||
assert_equal(herm.hermtrim(coef, 2), [0])
|
||||
|
||||
def test_hermline(self):
|
||||
assert_equal(herm.hermline(3, 4), [3, 2])
|
||||
|
||||
def test_herm2poly(self):
|
||||
for i in range(10):
|
||||
assert_almost_equal(herm.herm2poly([0]*i + [1]), Hlist[i])
|
||||
|
||||
def test_poly2herm(self):
|
||||
for i in range(10):
|
||||
assert_almost_equal(herm.poly2herm(Hlist[i]), [0]*i + [1])
|
||||
|
||||
def test_weight(self):
|
||||
x = np.linspace(-5, 5, 11)
|
||||
tgt = np.exp(-x**2)
|
||||
res = herm.hermweight(x)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
|
@ -0,0 +1,556 @@
|
|||
"""Tests for hermite_e module.
|
||||
|
||||
"""
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
import numpy.polynomial.hermite_e as herme
|
||||
from numpy.polynomial.polynomial import polyval
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
)
|
||||
|
||||
He0 = np.array([1])
|
||||
He1 = np.array([0, 1])
|
||||
He2 = np.array([-1, 0, 1])
|
||||
He3 = np.array([0, -3, 0, 1])
|
||||
He4 = np.array([3, 0, -6, 0, 1])
|
||||
He5 = np.array([0, 15, 0, -10, 0, 1])
|
||||
He6 = np.array([-15, 0, 45, 0, -15, 0, 1])
|
||||
He7 = np.array([0, -105, 0, 105, 0, -21, 0, 1])
|
||||
He8 = np.array([105, 0, -420, 0, 210, 0, -28, 0, 1])
|
||||
He9 = np.array([0, 945, 0, -1260, 0, 378, 0, -36, 0, 1])
|
||||
|
||||
Helist = [He0, He1, He2, He3, He4, He5, He6, He7, He8, He9]
|
||||
|
||||
|
||||
def trim(x):
|
||||
return herme.hermetrim(x, tol=1e-6)
|
||||
|
||||
|
||||
class TestConstants:
|
||||
|
||||
def test_hermedomain(self):
|
||||
assert_equal(herme.hermedomain, [-1, 1])
|
||||
|
||||
def test_hermezero(self):
|
||||
assert_equal(herme.hermezero, [0])
|
||||
|
||||
def test_hermeone(self):
|
||||
assert_equal(herme.hermeone, [1])
|
||||
|
||||
def test_hermex(self):
|
||||
assert_equal(herme.hermex, [0, 1])
|
||||
|
||||
|
||||
class TestArithmetic:
|
||||
x = np.linspace(-3, 3, 100)
|
||||
|
||||
def test_hermeadd(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] += 1
|
||||
res = herme.hermeadd([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_hermesub(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] -= 1
|
||||
res = herme.hermesub([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_hermemulx(self):
|
||||
assert_equal(herme.hermemulx([0]), [0])
|
||||
assert_equal(herme.hermemulx([1]), [0, 1])
|
||||
for i in range(1, 5):
|
||||
ser = [0]*i + [1]
|
||||
tgt = [0]*(i - 1) + [i, 0, 1]
|
||||
assert_equal(herme.hermemulx(ser), tgt)
|
||||
|
||||
def test_hermemul(self):
|
||||
# check values of result
|
||||
for i in range(5):
|
||||
pol1 = [0]*i + [1]
|
||||
val1 = herme.hermeval(self.x, pol1)
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
pol2 = [0]*j + [1]
|
||||
val2 = herme.hermeval(self.x, pol2)
|
||||
pol3 = herme.hermemul(pol1, pol2)
|
||||
val3 = herme.hermeval(self.x, pol3)
|
||||
assert_(len(pol3) == i + j + 1, msg)
|
||||
assert_almost_equal(val3, val1*val2, err_msg=msg)
|
||||
|
||||
def test_hermediv(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
ci = [0]*i + [1]
|
||||
cj = [0]*j + [1]
|
||||
tgt = herme.hermeadd(ci, cj)
|
||||
quo, rem = herme.hermediv(tgt, ci)
|
||||
res = herme.hermeadd(herme.hermemul(quo, ci), rem)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_hermepow(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
c = np.arange(i + 1)
|
||||
tgt = reduce(herme.hermemul, [c]*j, np.array([1]))
|
||||
res = herme.hermepow(c, j)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
|
||||
class TestEvaluation:
|
||||
# coefficients of 1 + 2*x + 3*x**2
|
||||
c1d = np.array([4., 2., 3.])
|
||||
c2d = np.einsum('i,j->ij', c1d, c1d)
|
||||
c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
|
||||
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
y = polyval(x, [1., 2., 3.])
|
||||
|
||||
def test_hermeval(self):
|
||||
#check empty input
|
||||
assert_equal(herme.hermeval([], [1]).size, 0)
|
||||
|
||||
#check normal input)
|
||||
x = np.linspace(-1, 1)
|
||||
y = [polyval(x, c) for c in Helist]
|
||||
for i in range(10):
|
||||
msg = f"At i={i}"
|
||||
tgt = y[i]
|
||||
res = herme.hermeval(x, [0]*i + [1])
|
||||
assert_almost_equal(res, tgt, err_msg=msg)
|
||||
|
||||
#check that shape is preserved
|
||||
for i in range(3):
|
||||
dims = [2]*i
|
||||
x = np.zeros(dims)
|
||||
assert_equal(herme.hermeval(x, [1]).shape, dims)
|
||||
assert_equal(herme.hermeval(x, [1, 0]).shape, dims)
|
||||
assert_equal(herme.hermeval(x, [1, 0, 0]).shape, dims)
|
||||
|
||||
def test_hermeval2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, herme.hermeval2d, x1, x2[:2], self.c2d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2
|
||||
res = herme.hermeval2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = herme.hermeval2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_hermeval3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, herme.hermeval3d, x1, x2, x3[:2], self.c3d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2*y3
|
||||
res = herme.hermeval3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = herme.hermeval3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_hermegrid2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j->ij', y1, y2)
|
||||
res = herme.hermegrid2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = herme.hermegrid2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3)*2)
|
||||
|
||||
def test_hermegrid3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
|
||||
res = herme.hermegrid3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = herme.hermegrid3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3)*3)
|
||||
|
||||
|
||||
class TestIntegral:
|
||||
|
||||
def test_hermeint(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, herme.hermeint, [0], .5)
|
||||
assert_raises(ValueError, herme.hermeint, [0], -1)
|
||||
assert_raises(ValueError, herme.hermeint, [0], 1, [0, 0])
|
||||
assert_raises(ValueError, herme.hermeint, [0], lbnd=[0])
|
||||
assert_raises(ValueError, herme.hermeint, [0], scl=[0])
|
||||
assert_raises(TypeError, herme.hermeint, [0], axis=.5)
|
||||
|
||||
# test integration of zero polynomial
|
||||
for i in range(2, 5):
|
||||
k = [0]*(i - 2) + [1]
|
||||
res = herme.hermeint([0], m=i, k=k)
|
||||
assert_almost_equal(res, [0, 1])
|
||||
|
||||
# check single integration with integration constant
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [1/scl]
|
||||
hermepol = herme.poly2herme(pol)
|
||||
hermeint = herme.hermeint(hermepol, m=1, k=[i])
|
||||
res = herme.herme2poly(hermeint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check single integration with integration constant and lbnd
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
hermepol = herme.poly2herme(pol)
|
||||
hermeint = herme.hermeint(hermepol, m=1, k=[i], lbnd=-1)
|
||||
assert_almost_equal(herme.hermeval(-1, hermeint), i)
|
||||
|
||||
# check single integration with integration constant and scaling
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [2/scl]
|
||||
hermepol = herme.poly2herme(pol)
|
||||
hermeint = herme.hermeint(hermepol, m=1, k=[i], scl=2)
|
||||
res = herme.herme2poly(hermeint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with default k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = herme.hermeint(tgt, m=1)
|
||||
res = herme.hermeint(pol, m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with defined k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = herme.hermeint(tgt, m=1, k=[k])
|
||||
res = herme.hermeint(pol, m=j, k=list(range(j)))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with lbnd
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = herme.hermeint(tgt, m=1, k=[k], lbnd=-1)
|
||||
res = herme.hermeint(pol, m=j, k=list(range(j)), lbnd=-1)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = herme.hermeint(tgt, m=1, k=[k], scl=2)
|
||||
res = herme.hermeint(pol, m=j, k=list(range(j)), scl=2)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_hermeint_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([herme.hermeint(c) for c in c2d.T]).T
|
||||
res = herme.hermeint(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([herme.hermeint(c) for c in c2d])
|
||||
res = herme.hermeint(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([herme.hermeint(c, k=3) for c in c2d])
|
||||
res = herme.hermeint(c2d, k=3, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestDerivative:
|
||||
|
||||
def test_hermeder(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, herme.hermeder, [0], .5)
|
||||
assert_raises(ValueError, herme.hermeder, [0], -1)
|
||||
|
||||
# check that zeroth derivative does nothing
|
||||
for i in range(5):
|
||||
tgt = [0]*i + [1]
|
||||
res = herme.hermeder(tgt, m=0)
|
||||
assert_equal(trim(res), trim(tgt))
|
||||
|
||||
# check that derivation is the inverse of integration
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = herme.hermeder(herme.hermeint(tgt, m=j), m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check derivation with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = herme.hermeder(
|
||||
herme.hermeint(tgt, m=j, scl=2), m=j, scl=.5)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_hermeder_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([herme.hermeder(c) for c in c2d.T]).T
|
||||
res = herme.hermeder(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([herme.hermeder(c) for c in c2d])
|
||||
res = herme.hermeder(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestVander:
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
|
||||
def test_hermevander(self):
|
||||
# check for 1d x
|
||||
x = np.arange(3)
|
||||
v = herme.hermevander(x, 3)
|
||||
assert_(v.shape == (3, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], herme.hermeval(x, coef))
|
||||
|
||||
# check for 2d x
|
||||
x = np.array([[1, 2], [3, 4], [5, 6]])
|
||||
v = herme.hermevander(x, 3)
|
||||
assert_(v.shape == (3, 2, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], herme.hermeval(x, coef))
|
||||
|
||||
def test_hermevander2d(self):
|
||||
# also tests hermeval2d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3))
|
||||
van = herme.hermevander2d(x1, x2, [1, 2])
|
||||
tgt = herme.hermeval2d(x1, x2, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = herme.hermevander2d([x1], [x2], [1, 2])
|
||||
assert_(van.shape == (1, 5, 6))
|
||||
|
||||
def test_hermevander3d(self):
|
||||
# also tests hermeval3d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3, 4))
|
||||
van = herme.hermevander3d(x1, x2, x3, [1, 2, 3])
|
||||
tgt = herme.hermeval3d(x1, x2, x3, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = herme.hermevander3d([x1], [x2], [x3], [1, 2, 3])
|
||||
assert_(van.shape == (1, 5, 24))
|
||||
|
||||
|
||||
class TestFitting:
|
||||
|
||||
def test_hermefit(self):
|
||||
def f(x):
|
||||
return x*(x - 1)*(x - 2)
|
||||
|
||||
def f2(x):
|
||||
return x**4 + x**2 + 1
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, herme.hermefit, [1], [1], -1)
|
||||
assert_raises(TypeError, herme.hermefit, [[1]], [1], 0)
|
||||
assert_raises(TypeError, herme.hermefit, [], [1], 0)
|
||||
assert_raises(TypeError, herme.hermefit, [1], [[[1]]], 0)
|
||||
assert_raises(TypeError, herme.hermefit, [1, 2], [1], 0)
|
||||
assert_raises(TypeError, herme.hermefit, [1], [1, 2], 0)
|
||||
assert_raises(TypeError, herme.hermefit, [1], [1], 0, w=[[1]])
|
||||
assert_raises(TypeError, herme.hermefit, [1], [1], 0, w=[1, 1])
|
||||
assert_raises(ValueError, herme.hermefit, [1], [1], [-1,])
|
||||
assert_raises(ValueError, herme.hermefit, [1], [1], [2, -1, 6])
|
||||
assert_raises(TypeError, herme.hermefit, [1], [1], [])
|
||||
|
||||
# Test fit
|
||||
x = np.linspace(0, 2)
|
||||
y = f(x)
|
||||
#
|
||||
coef3 = herme.hermefit(x, y, 3)
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(herme.hermeval(x, coef3), y)
|
||||
coef3 = herme.hermefit(x, y, [0, 1, 2, 3])
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(herme.hermeval(x, coef3), y)
|
||||
#
|
||||
coef4 = herme.hermefit(x, y, 4)
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(herme.hermeval(x, coef4), y)
|
||||
coef4 = herme.hermefit(x, y, [0, 1, 2, 3, 4])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(herme.hermeval(x, coef4), y)
|
||||
# check things still work if deg is not in strict increasing
|
||||
coef4 = herme.hermefit(x, y, [2, 3, 4, 1, 0])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(herme.hermeval(x, coef4), y)
|
||||
#
|
||||
coef2d = herme.hermefit(x, np.array([y, y]).T, 3)
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
coef2d = herme.hermefit(x, np.array([y, y]).T, [0, 1, 2, 3])
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
# test weighting
|
||||
w = np.zeros_like(x)
|
||||
yw = y.copy()
|
||||
w[1::2] = 1
|
||||
y[0::2] = 0
|
||||
wcoef3 = herme.hermefit(x, yw, 3, w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
wcoef3 = herme.hermefit(x, yw, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
#
|
||||
wcoef2d = herme.hermefit(x, np.array([yw, yw]).T, 3, w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
wcoef2d = herme.hermefit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
# test scaling with complex values x points whose square
|
||||
# is zero when summed.
|
||||
x = [1, 1j, -1, -1j]
|
||||
assert_almost_equal(herme.hermefit(x, x, 1), [0, 1])
|
||||
assert_almost_equal(herme.hermefit(x, x, [0, 1]), [0, 1])
|
||||
# test fitting only even Legendre polynomials
|
||||
x = np.linspace(-1, 1)
|
||||
y = f2(x)
|
||||
coef1 = herme.hermefit(x, y, 4)
|
||||
assert_almost_equal(herme.hermeval(x, coef1), y)
|
||||
coef2 = herme.hermefit(x, y, [0, 2, 4])
|
||||
assert_almost_equal(herme.hermeval(x, coef2), y)
|
||||
assert_almost_equal(coef1, coef2)
|
||||
|
||||
|
||||
class TestCompanion:
|
||||
|
||||
def test_raises(self):
|
||||
assert_raises(ValueError, herme.hermecompanion, [])
|
||||
assert_raises(ValueError, herme.hermecompanion, [1])
|
||||
|
||||
def test_dimensions(self):
|
||||
for i in range(1, 5):
|
||||
coef = [0]*i + [1]
|
||||
assert_(herme.hermecompanion(coef).shape == (i, i))
|
||||
|
||||
def test_linear_root(self):
|
||||
assert_(herme.hermecompanion([1, 2])[0, 0] == -.5)
|
||||
|
||||
|
||||
class TestGauss:
|
||||
|
||||
def test_100(self):
|
||||
x, w = herme.hermegauss(100)
|
||||
|
||||
# test orthogonality. Note that the results need to be normalized,
|
||||
# otherwise the huge values that can arise from fast growing
|
||||
# functions like Laguerre can be very confusing.
|
||||
v = herme.hermevander(x, 99)
|
||||
vv = np.dot(v.T * w, v)
|
||||
vd = 1/np.sqrt(vv.diagonal())
|
||||
vv = vd[:, None] * vv * vd
|
||||
assert_almost_equal(vv, np.eye(100))
|
||||
|
||||
# check that the integral of 1 is correct
|
||||
tgt = np.sqrt(2*np.pi)
|
||||
assert_almost_equal(w.sum(), tgt)
|
||||
|
||||
|
||||
class TestMisc:
|
||||
|
||||
def test_hermefromroots(self):
|
||||
res = herme.hermefromroots([])
|
||||
assert_almost_equal(trim(res), [1])
|
||||
for i in range(1, 5):
|
||||
roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
|
||||
pol = herme.hermefromroots(roots)
|
||||
res = herme.hermeval(roots, pol)
|
||||
tgt = 0
|
||||
assert_(len(pol) == i + 1)
|
||||
assert_almost_equal(herme.herme2poly(pol)[-1], 1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
def test_hermeroots(self):
|
||||
assert_almost_equal(herme.hermeroots([1]), [])
|
||||
assert_almost_equal(herme.hermeroots([1, 1]), [-1])
|
||||
for i in range(2, 5):
|
||||
tgt = np.linspace(-1, 1, i)
|
||||
res = herme.hermeroots(herme.hermefromroots(tgt))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_hermetrim(self):
|
||||
coef = [2, -1, 1, 0]
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, herme.hermetrim, coef, -1)
|
||||
|
||||
# Test results
|
||||
assert_equal(herme.hermetrim(coef), coef[:-1])
|
||||
assert_equal(herme.hermetrim(coef, 1), coef[:-3])
|
||||
assert_equal(herme.hermetrim(coef, 2), [0])
|
||||
|
||||
def test_hermeline(self):
|
||||
assert_equal(herme.hermeline(3, 4), [3, 4])
|
||||
|
||||
def test_herme2poly(self):
|
||||
for i in range(10):
|
||||
assert_almost_equal(herme.herme2poly([0]*i + [1]), Helist[i])
|
||||
|
||||
def test_poly2herme(self):
|
||||
for i in range(10):
|
||||
assert_almost_equal(herme.poly2herme(Helist[i]), [0]*i + [1])
|
||||
|
||||
def test_weight(self):
|
||||
x = np.linspace(-5, 5, 11)
|
||||
tgt = np.exp(-.5*x**2)
|
||||
res = herme.hermeweight(x)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
|
@ -0,0 +1,537 @@
|
|||
"""Tests for laguerre module.
|
||||
|
||||
"""
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
import numpy.polynomial.laguerre as lag
|
||||
from numpy.polynomial.polynomial import polyval
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
)
|
||||
|
||||
L0 = np.array([1])/1
|
||||
L1 = np.array([1, -1])/1
|
||||
L2 = np.array([2, -4, 1])/2
|
||||
L3 = np.array([6, -18, 9, -1])/6
|
||||
L4 = np.array([24, -96, 72, -16, 1])/24
|
||||
L5 = np.array([120, -600, 600, -200, 25, -1])/120
|
||||
L6 = np.array([720, -4320, 5400, -2400, 450, -36, 1])/720
|
||||
|
||||
Llist = [L0, L1, L2, L3, L4, L5, L6]
|
||||
|
||||
|
||||
def trim(x):
|
||||
return lag.lagtrim(x, tol=1e-6)
|
||||
|
||||
|
||||
class TestConstants:
|
||||
|
||||
def test_lagdomain(self):
|
||||
assert_equal(lag.lagdomain, [0, 1])
|
||||
|
||||
def test_lagzero(self):
|
||||
assert_equal(lag.lagzero, [0])
|
||||
|
||||
def test_lagone(self):
|
||||
assert_equal(lag.lagone, [1])
|
||||
|
||||
def test_lagx(self):
|
||||
assert_equal(lag.lagx, [1, -1])
|
||||
|
||||
|
||||
class TestArithmetic:
|
||||
x = np.linspace(-3, 3, 100)
|
||||
|
||||
def test_lagadd(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] += 1
|
||||
res = lag.lagadd([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_lagsub(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] -= 1
|
||||
res = lag.lagsub([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_lagmulx(self):
|
||||
assert_equal(lag.lagmulx([0]), [0])
|
||||
assert_equal(lag.lagmulx([1]), [1, -1])
|
||||
for i in range(1, 5):
|
||||
ser = [0]*i + [1]
|
||||
tgt = [0]*(i - 1) + [-i, 2*i + 1, -(i + 1)]
|
||||
assert_almost_equal(lag.lagmulx(ser), tgt)
|
||||
|
||||
def test_lagmul(self):
|
||||
# check values of result
|
||||
for i in range(5):
|
||||
pol1 = [0]*i + [1]
|
||||
val1 = lag.lagval(self.x, pol1)
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
pol2 = [0]*j + [1]
|
||||
val2 = lag.lagval(self.x, pol2)
|
||||
pol3 = lag.lagmul(pol1, pol2)
|
||||
val3 = lag.lagval(self.x, pol3)
|
||||
assert_(len(pol3) == i + j + 1, msg)
|
||||
assert_almost_equal(val3, val1*val2, err_msg=msg)
|
||||
|
||||
def test_lagdiv(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
ci = [0]*i + [1]
|
||||
cj = [0]*j + [1]
|
||||
tgt = lag.lagadd(ci, cj)
|
||||
quo, rem = lag.lagdiv(tgt, ci)
|
||||
res = lag.lagadd(lag.lagmul(quo, ci), rem)
|
||||
assert_almost_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_lagpow(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
c = np.arange(i + 1)
|
||||
tgt = reduce(lag.lagmul, [c]*j, np.array([1]))
|
||||
res = lag.lagpow(c, j)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
|
||||
class TestEvaluation:
|
||||
# coefficients of 1 + 2*x + 3*x**2
|
||||
c1d = np.array([9., -14., 6.])
|
||||
c2d = np.einsum('i,j->ij', c1d, c1d)
|
||||
c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
|
||||
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
y = polyval(x, [1., 2., 3.])
|
||||
|
||||
def test_lagval(self):
|
||||
#check empty input
|
||||
assert_equal(lag.lagval([], [1]).size, 0)
|
||||
|
||||
#check normal input)
|
||||
x = np.linspace(-1, 1)
|
||||
y = [polyval(x, c) for c in Llist]
|
||||
for i in range(7):
|
||||
msg = f"At i={i}"
|
||||
tgt = y[i]
|
||||
res = lag.lagval(x, [0]*i + [1])
|
||||
assert_almost_equal(res, tgt, err_msg=msg)
|
||||
|
||||
#check that shape is preserved
|
||||
for i in range(3):
|
||||
dims = [2]*i
|
||||
x = np.zeros(dims)
|
||||
assert_equal(lag.lagval(x, [1]).shape, dims)
|
||||
assert_equal(lag.lagval(x, [1, 0]).shape, dims)
|
||||
assert_equal(lag.lagval(x, [1, 0, 0]).shape, dims)
|
||||
|
||||
def test_lagval2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, lag.lagval2d, x1, x2[:2], self.c2d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2
|
||||
res = lag.lagval2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = lag.lagval2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_lagval3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, lag.lagval3d, x1, x2, x3[:2], self.c3d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2*y3
|
||||
res = lag.lagval3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = lag.lagval3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_laggrid2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j->ij', y1, y2)
|
||||
res = lag.laggrid2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = lag.laggrid2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3)*2)
|
||||
|
||||
def test_laggrid3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
|
||||
res = lag.laggrid3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = lag.laggrid3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3)*3)
|
||||
|
||||
|
||||
class TestIntegral:
|
||||
|
||||
def test_lagint(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, lag.lagint, [0], .5)
|
||||
assert_raises(ValueError, lag.lagint, [0], -1)
|
||||
assert_raises(ValueError, lag.lagint, [0], 1, [0, 0])
|
||||
assert_raises(ValueError, lag.lagint, [0], lbnd=[0])
|
||||
assert_raises(ValueError, lag.lagint, [0], scl=[0])
|
||||
assert_raises(TypeError, lag.lagint, [0], axis=.5)
|
||||
|
||||
# test integration of zero polynomial
|
||||
for i in range(2, 5):
|
||||
k = [0]*(i - 2) + [1]
|
||||
res = lag.lagint([0], m=i, k=k)
|
||||
assert_almost_equal(res, [1, -1])
|
||||
|
||||
# check single integration with integration constant
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [1/scl]
|
||||
lagpol = lag.poly2lag(pol)
|
||||
lagint = lag.lagint(lagpol, m=1, k=[i])
|
||||
res = lag.lag2poly(lagint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check single integration with integration constant and lbnd
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
lagpol = lag.poly2lag(pol)
|
||||
lagint = lag.lagint(lagpol, m=1, k=[i], lbnd=-1)
|
||||
assert_almost_equal(lag.lagval(-1, lagint), i)
|
||||
|
||||
# check single integration with integration constant and scaling
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [2/scl]
|
||||
lagpol = lag.poly2lag(pol)
|
||||
lagint = lag.lagint(lagpol, m=1, k=[i], scl=2)
|
||||
res = lag.lag2poly(lagint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with default k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = lag.lagint(tgt, m=1)
|
||||
res = lag.lagint(pol, m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with defined k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = lag.lagint(tgt, m=1, k=[k])
|
||||
res = lag.lagint(pol, m=j, k=list(range(j)))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with lbnd
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = lag.lagint(tgt, m=1, k=[k], lbnd=-1)
|
||||
res = lag.lagint(pol, m=j, k=list(range(j)), lbnd=-1)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = lag.lagint(tgt, m=1, k=[k], scl=2)
|
||||
res = lag.lagint(pol, m=j, k=list(range(j)), scl=2)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_lagint_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([lag.lagint(c) for c in c2d.T]).T
|
||||
res = lag.lagint(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([lag.lagint(c) for c in c2d])
|
||||
res = lag.lagint(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([lag.lagint(c, k=3) for c in c2d])
|
||||
res = lag.lagint(c2d, k=3, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestDerivative:
|
||||
|
||||
def test_lagder(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, lag.lagder, [0], .5)
|
||||
assert_raises(ValueError, lag.lagder, [0], -1)
|
||||
|
||||
# check that zeroth derivative does nothing
|
||||
for i in range(5):
|
||||
tgt = [0]*i + [1]
|
||||
res = lag.lagder(tgt, m=0)
|
||||
assert_equal(trim(res), trim(tgt))
|
||||
|
||||
# check that derivation is the inverse of integration
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = lag.lagder(lag.lagint(tgt, m=j), m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check derivation with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = lag.lagder(lag.lagint(tgt, m=j, scl=2), m=j, scl=.5)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_lagder_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([lag.lagder(c) for c in c2d.T]).T
|
||||
res = lag.lagder(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([lag.lagder(c) for c in c2d])
|
||||
res = lag.lagder(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestVander:
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
|
||||
def test_lagvander(self):
|
||||
# check for 1d x
|
||||
x = np.arange(3)
|
||||
v = lag.lagvander(x, 3)
|
||||
assert_(v.shape == (3, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], lag.lagval(x, coef))
|
||||
|
||||
# check for 2d x
|
||||
x = np.array([[1, 2], [3, 4], [5, 6]])
|
||||
v = lag.lagvander(x, 3)
|
||||
assert_(v.shape == (3, 2, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], lag.lagval(x, coef))
|
||||
|
||||
def test_lagvander2d(self):
|
||||
# also tests lagval2d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3))
|
||||
van = lag.lagvander2d(x1, x2, [1, 2])
|
||||
tgt = lag.lagval2d(x1, x2, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = lag.lagvander2d([x1], [x2], [1, 2])
|
||||
assert_(van.shape == (1, 5, 6))
|
||||
|
||||
def test_lagvander3d(self):
|
||||
# also tests lagval3d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3, 4))
|
||||
van = lag.lagvander3d(x1, x2, x3, [1, 2, 3])
|
||||
tgt = lag.lagval3d(x1, x2, x3, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = lag.lagvander3d([x1], [x2], [x3], [1, 2, 3])
|
||||
assert_(van.shape == (1, 5, 24))
|
||||
|
||||
|
||||
class TestFitting:
|
||||
|
||||
def test_lagfit(self):
|
||||
def f(x):
|
||||
return x*(x - 1)*(x - 2)
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, lag.lagfit, [1], [1], -1)
|
||||
assert_raises(TypeError, lag.lagfit, [[1]], [1], 0)
|
||||
assert_raises(TypeError, lag.lagfit, [], [1], 0)
|
||||
assert_raises(TypeError, lag.lagfit, [1], [[[1]]], 0)
|
||||
assert_raises(TypeError, lag.lagfit, [1, 2], [1], 0)
|
||||
assert_raises(TypeError, lag.lagfit, [1], [1, 2], 0)
|
||||
assert_raises(TypeError, lag.lagfit, [1], [1], 0, w=[[1]])
|
||||
assert_raises(TypeError, lag.lagfit, [1], [1], 0, w=[1, 1])
|
||||
assert_raises(ValueError, lag.lagfit, [1], [1], [-1,])
|
||||
assert_raises(ValueError, lag.lagfit, [1], [1], [2, -1, 6])
|
||||
assert_raises(TypeError, lag.lagfit, [1], [1], [])
|
||||
|
||||
# Test fit
|
||||
x = np.linspace(0, 2)
|
||||
y = f(x)
|
||||
#
|
||||
coef3 = lag.lagfit(x, y, 3)
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(lag.lagval(x, coef3), y)
|
||||
coef3 = lag.lagfit(x, y, [0, 1, 2, 3])
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(lag.lagval(x, coef3), y)
|
||||
#
|
||||
coef4 = lag.lagfit(x, y, 4)
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(lag.lagval(x, coef4), y)
|
||||
coef4 = lag.lagfit(x, y, [0, 1, 2, 3, 4])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(lag.lagval(x, coef4), y)
|
||||
#
|
||||
coef2d = lag.lagfit(x, np.array([y, y]).T, 3)
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
coef2d = lag.lagfit(x, np.array([y, y]).T, [0, 1, 2, 3])
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
# test weighting
|
||||
w = np.zeros_like(x)
|
||||
yw = y.copy()
|
||||
w[1::2] = 1
|
||||
y[0::2] = 0
|
||||
wcoef3 = lag.lagfit(x, yw, 3, w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
wcoef3 = lag.lagfit(x, yw, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
#
|
||||
wcoef2d = lag.lagfit(x, np.array([yw, yw]).T, 3, w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
wcoef2d = lag.lagfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
# test scaling with complex values x points whose square
|
||||
# is zero when summed.
|
||||
x = [1, 1j, -1, -1j]
|
||||
assert_almost_equal(lag.lagfit(x, x, 1), [1, -1])
|
||||
assert_almost_equal(lag.lagfit(x, x, [0, 1]), [1, -1])
|
||||
|
||||
|
||||
class TestCompanion:
|
||||
|
||||
def test_raises(self):
|
||||
assert_raises(ValueError, lag.lagcompanion, [])
|
||||
assert_raises(ValueError, lag.lagcompanion, [1])
|
||||
|
||||
def test_dimensions(self):
|
||||
for i in range(1, 5):
|
||||
coef = [0]*i + [1]
|
||||
assert_(lag.lagcompanion(coef).shape == (i, i))
|
||||
|
||||
def test_linear_root(self):
|
||||
assert_(lag.lagcompanion([1, 2])[0, 0] == 1.5)
|
||||
|
||||
|
||||
class TestGauss:
|
||||
|
||||
def test_100(self):
|
||||
x, w = lag.laggauss(100)
|
||||
|
||||
# test orthogonality. Note that the results need to be normalized,
|
||||
# otherwise the huge values that can arise from fast growing
|
||||
# functions like Laguerre can be very confusing.
|
||||
v = lag.lagvander(x, 99)
|
||||
vv = np.dot(v.T * w, v)
|
||||
vd = 1/np.sqrt(vv.diagonal())
|
||||
vv = vd[:, None] * vv * vd
|
||||
assert_almost_equal(vv, np.eye(100))
|
||||
|
||||
# check that the integral of 1 is correct
|
||||
tgt = 1.0
|
||||
assert_almost_equal(w.sum(), tgt)
|
||||
|
||||
|
||||
class TestMisc:
|
||||
|
||||
def test_lagfromroots(self):
|
||||
res = lag.lagfromroots([])
|
||||
assert_almost_equal(trim(res), [1])
|
||||
for i in range(1, 5):
|
||||
roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
|
||||
pol = lag.lagfromroots(roots)
|
||||
res = lag.lagval(roots, pol)
|
||||
tgt = 0
|
||||
assert_(len(pol) == i + 1)
|
||||
assert_almost_equal(lag.lag2poly(pol)[-1], 1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
def test_lagroots(self):
|
||||
assert_almost_equal(lag.lagroots([1]), [])
|
||||
assert_almost_equal(lag.lagroots([0, 1]), [1])
|
||||
for i in range(2, 5):
|
||||
tgt = np.linspace(0, 3, i)
|
||||
res = lag.lagroots(lag.lagfromroots(tgt))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_lagtrim(self):
|
||||
coef = [2, -1, 1, 0]
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, lag.lagtrim, coef, -1)
|
||||
|
||||
# Test results
|
||||
assert_equal(lag.lagtrim(coef), coef[:-1])
|
||||
assert_equal(lag.lagtrim(coef, 1), coef[:-3])
|
||||
assert_equal(lag.lagtrim(coef, 2), [0])
|
||||
|
||||
def test_lagline(self):
|
||||
assert_equal(lag.lagline(3, 4), [7, -4])
|
||||
|
||||
def test_lag2poly(self):
|
||||
for i in range(7):
|
||||
assert_almost_equal(lag.lag2poly([0]*i + [1]), Llist[i])
|
||||
|
||||
def test_poly2lag(self):
|
||||
for i in range(7):
|
||||
assert_almost_equal(lag.poly2lag(Llist[i]), [0]*i + [1])
|
||||
|
||||
def test_weight(self):
|
||||
x = np.linspace(0, 10, 11)
|
||||
tgt = np.exp(-x)
|
||||
res = lag.lagweight(x)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
|
@ -0,0 +1,568 @@
|
|||
"""Tests for legendre module.
|
||||
|
||||
"""
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
import numpy.polynomial.legendre as leg
|
||||
from numpy.polynomial.polynomial import polyval
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
)
|
||||
|
||||
L0 = np.array([1])
|
||||
L1 = np.array([0, 1])
|
||||
L2 = np.array([-1, 0, 3])/2
|
||||
L3 = np.array([0, -3, 0, 5])/2
|
||||
L4 = np.array([3, 0, -30, 0, 35])/8
|
||||
L5 = np.array([0, 15, 0, -70, 0, 63])/8
|
||||
L6 = np.array([-5, 0, 105, 0, -315, 0, 231])/16
|
||||
L7 = np.array([0, -35, 0, 315, 0, -693, 0, 429])/16
|
||||
L8 = np.array([35, 0, -1260, 0, 6930, 0, -12012, 0, 6435])/128
|
||||
L9 = np.array([0, 315, 0, -4620, 0, 18018, 0, -25740, 0, 12155])/128
|
||||
|
||||
Llist = [L0, L1, L2, L3, L4, L5, L6, L7, L8, L9]
|
||||
|
||||
|
||||
def trim(x):
|
||||
return leg.legtrim(x, tol=1e-6)
|
||||
|
||||
|
||||
class TestConstants:
|
||||
|
||||
def test_legdomain(self):
|
||||
assert_equal(leg.legdomain, [-1, 1])
|
||||
|
||||
def test_legzero(self):
|
||||
assert_equal(leg.legzero, [0])
|
||||
|
||||
def test_legone(self):
|
||||
assert_equal(leg.legone, [1])
|
||||
|
||||
def test_legx(self):
|
||||
assert_equal(leg.legx, [0, 1])
|
||||
|
||||
|
||||
class TestArithmetic:
|
||||
x = np.linspace(-1, 1, 100)
|
||||
|
||||
def test_legadd(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] += 1
|
||||
res = leg.legadd([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_legsub(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] -= 1
|
||||
res = leg.legsub([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_legmulx(self):
|
||||
assert_equal(leg.legmulx([0]), [0])
|
||||
assert_equal(leg.legmulx([1]), [0, 1])
|
||||
for i in range(1, 5):
|
||||
tmp = 2*i + 1
|
||||
ser = [0]*i + [1]
|
||||
tgt = [0]*(i - 1) + [i/tmp, 0, (i + 1)/tmp]
|
||||
assert_equal(leg.legmulx(ser), tgt)
|
||||
|
||||
def test_legmul(self):
|
||||
# check values of result
|
||||
for i in range(5):
|
||||
pol1 = [0]*i + [1]
|
||||
val1 = leg.legval(self.x, pol1)
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
pol2 = [0]*j + [1]
|
||||
val2 = leg.legval(self.x, pol2)
|
||||
pol3 = leg.legmul(pol1, pol2)
|
||||
val3 = leg.legval(self.x, pol3)
|
||||
assert_(len(pol3) == i + j + 1, msg)
|
||||
assert_almost_equal(val3, val1*val2, err_msg=msg)
|
||||
|
||||
def test_legdiv(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
ci = [0]*i + [1]
|
||||
cj = [0]*j + [1]
|
||||
tgt = leg.legadd(ci, cj)
|
||||
quo, rem = leg.legdiv(tgt, ci)
|
||||
res = leg.legadd(leg.legmul(quo, ci), rem)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_legpow(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
c = np.arange(i + 1)
|
||||
tgt = reduce(leg.legmul, [c]*j, np.array([1]))
|
||||
res = leg.legpow(c, j)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
|
||||
class TestEvaluation:
|
||||
# coefficients of 1 + 2*x + 3*x**2
|
||||
c1d = np.array([2., 2., 2.])
|
||||
c2d = np.einsum('i,j->ij', c1d, c1d)
|
||||
c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
|
||||
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
y = polyval(x, [1., 2., 3.])
|
||||
|
||||
def test_legval(self):
|
||||
#check empty input
|
||||
assert_equal(leg.legval([], [1]).size, 0)
|
||||
|
||||
#check normal input)
|
||||
x = np.linspace(-1, 1)
|
||||
y = [polyval(x, c) for c in Llist]
|
||||
for i in range(10):
|
||||
msg = f"At i={i}"
|
||||
tgt = y[i]
|
||||
res = leg.legval(x, [0]*i + [1])
|
||||
assert_almost_equal(res, tgt, err_msg=msg)
|
||||
|
||||
#check that shape is preserved
|
||||
for i in range(3):
|
||||
dims = [2]*i
|
||||
x = np.zeros(dims)
|
||||
assert_equal(leg.legval(x, [1]).shape, dims)
|
||||
assert_equal(leg.legval(x, [1, 0]).shape, dims)
|
||||
assert_equal(leg.legval(x, [1, 0, 0]).shape, dims)
|
||||
|
||||
def test_legval2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, leg.legval2d, x1, x2[:2], self.c2d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2
|
||||
res = leg.legval2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = leg.legval2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_legval3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises(ValueError, leg.legval3d, x1, x2, x3[:2], self.c3d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2*y3
|
||||
res = leg.legval3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = leg.legval3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_leggrid2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j->ij', y1, y2)
|
||||
res = leg.leggrid2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = leg.leggrid2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3)*2)
|
||||
|
||||
def test_leggrid3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
|
||||
res = leg.leggrid3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = leg.leggrid3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3)*3)
|
||||
|
||||
|
||||
class TestIntegral:
|
||||
|
||||
def test_legint(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, leg.legint, [0], .5)
|
||||
assert_raises(ValueError, leg.legint, [0], -1)
|
||||
assert_raises(ValueError, leg.legint, [0], 1, [0, 0])
|
||||
assert_raises(ValueError, leg.legint, [0], lbnd=[0])
|
||||
assert_raises(ValueError, leg.legint, [0], scl=[0])
|
||||
assert_raises(TypeError, leg.legint, [0], axis=.5)
|
||||
|
||||
# test integration of zero polynomial
|
||||
for i in range(2, 5):
|
||||
k = [0]*(i - 2) + [1]
|
||||
res = leg.legint([0], m=i, k=k)
|
||||
assert_almost_equal(res, [0, 1])
|
||||
|
||||
# check single integration with integration constant
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [1/scl]
|
||||
legpol = leg.poly2leg(pol)
|
||||
legint = leg.legint(legpol, m=1, k=[i])
|
||||
res = leg.leg2poly(legint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check single integration with integration constant and lbnd
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
legpol = leg.poly2leg(pol)
|
||||
legint = leg.legint(legpol, m=1, k=[i], lbnd=-1)
|
||||
assert_almost_equal(leg.legval(-1, legint), i)
|
||||
|
||||
# check single integration with integration constant and scaling
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [2/scl]
|
||||
legpol = leg.poly2leg(pol)
|
||||
legint = leg.legint(legpol, m=1, k=[i], scl=2)
|
||||
res = leg.leg2poly(legint)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with default k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = leg.legint(tgt, m=1)
|
||||
res = leg.legint(pol, m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with defined k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = leg.legint(tgt, m=1, k=[k])
|
||||
res = leg.legint(pol, m=j, k=list(range(j)))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with lbnd
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = leg.legint(tgt, m=1, k=[k], lbnd=-1)
|
||||
res = leg.legint(pol, m=j, k=list(range(j)), lbnd=-1)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = leg.legint(tgt, m=1, k=[k], scl=2)
|
||||
res = leg.legint(pol, m=j, k=list(range(j)), scl=2)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_legint_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([leg.legint(c) for c in c2d.T]).T
|
||||
res = leg.legint(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([leg.legint(c) for c in c2d])
|
||||
res = leg.legint(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([leg.legint(c, k=3) for c in c2d])
|
||||
res = leg.legint(c2d, k=3, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
def test_legint_zerointord(self):
|
||||
assert_equal(leg.legint((1, 2, 3), 0), (1, 2, 3))
|
||||
|
||||
|
||||
class TestDerivative:
|
||||
|
||||
def test_legder(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, leg.legder, [0], .5)
|
||||
assert_raises(ValueError, leg.legder, [0], -1)
|
||||
|
||||
# check that zeroth derivative does nothing
|
||||
for i in range(5):
|
||||
tgt = [0]*i + [1]
|
||||
res = leg.legder(tgt, m=0)
|
||||
assert_equal(trim(res), trim(tgt))
|
||||
|
||||
# check that derivation is the inverse of integration
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = leg.legder(leg.legint(tgt, m=j), m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check derivation with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = leg.legder(leg.legint(tgt, m=j, scl=2), m=j, scl=.5)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_legder_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([leg.legder(c) for c in c2d.T]).T
|
||||
res = leg.legder(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([leg.legder(c) for c in c2d])
|
||||
res = leg.legder(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
def test_legder_orderhigherthancoeff(self):
|
||||
c = (1, 2, 3, 4)
|
||||
assert_equal(leg.legder(c, 4), [0])
|
||||
|
||||
class TestVander:
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
|
||||
def test_legvander(self):
|
||||
# check for 1d x
|
||||
x = np.arange(3)
|
||||
v = leg.legvander(x, 3)
|
||||
assert_(v.shape == (3, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], leg.legval(x, coef))
|
||||
|
||||
# check for 2d x
|
||||
x = np.array([[1, 2], [3, 4], [5, 6]])
|
||||
v = leg.legvander(x, 3)
|
||||
assert_(v.shape == (3, 2, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], leg.legval(x, coef))
|
||||
|
||||
def test_legvander2d(self):
|
||||
# also tests polyval2d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3))
|
||||
van = leg.legvander2d(x1, x2, [1, 2])
|
||||
tgt = leg.legval2d(x1, x2, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = leg.legvander2d([x1], [x2], [1, 2])
|
||||
assert_(van.shape == (1, 5, 6))
|
||||
|
||||
def test_legvander3d(self):
|
||||
# also tests polyval3d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3, 4))
|
||||
van = leg.legvander3d(x1, x2, x3, [1, 2, 3])
|
||||
tgt = leg.legval3d(x1, x2, x3, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = leg.legvander3d([x1], [x2], [x3], [1, 2, 3])
|
||||
assert_(van.shape == (1, 5, 24))
|
||||
|
||||
def test_legvander_negdeg(self):
|
||||
assert_raises(ValueError, leg.legvander, (1, 2, 3), -1)
|
||||
|
||||
|
||||
class TestFitting:
|
||||
|
||||
def test_legfit(self):
|
||||
def f(x):
|
||||
return x*(x - 1)*(x - 2)
|
||||
|
||||
def f2(x):
|
||||
return x**4 + x**2 + 1
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, leg.legfit, [1], [1], -1)
|
||||
assert_raises(TypeError, leg.legfit, [[1]], [1], 0)
|
||||
assert_raises(TypeError, leg.legfit, [], [1], 0)
|
||||
assert_raises(TypeError, leg.legfit, [1], [[[1]]], 0)
|
||||
assert_raises(TypeError, leg.legfit, [1, 2], [1], 0)
|
||||
assert_raises(TypeError, leg.legfit, [1], [1, 2], 0)
|
||||
assert_raises(TypeError, leg.legfit, [1], [1], 0, w=[[1]])
|
||||
assert_raises(TypeError, leg.legfit, [1], [1], 0, w=[1, 1])
|
||||
assert_raises(ValueError, leg.legfit, [1], [1], [-1,])
|
||||
assert_raises(ValueError, leg.legfit, [1], [1], [2, -1, 6])
|
||||
assert_raises(TypeError, leg.legfit, [1], [1], [])
|
||||
|
||||
# Test fit
|
||||
x = np.linspace(0, 2)
|
||||
y = f(x)
|
||||
#
|
||||
coef3 = leg.legfit(x, y, 3)
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(leg.legval(x, coef3), y)
|
||||
coef3 = leg.legfit(x, y, [0, 1, 2, 3])
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(leg.legval(x, coef3), y)
|
||||
#
|
||||
coef4 = leg.legfit(x, y, 4)
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(leg.legval(x, coef4), y)
|
||||
coef4 = leg.legfit(x, y, [0, 1, 2, 3, 4])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(leg.legval(x, coef4), y)
|
||||
# check things still work if deg is not in strict increasing
|
||||
coef4 = leg.legfit(x, y, [2, 3, 4, 1, 0])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(leg.legval(x, coef4), y)
|
||||
#
|
||||
coef2d = leg.legfit(x, np.array([y, y]).T, 3)
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
coef2d = leg.legfit(x, np.array([y, y]).T, [0, 1, 2, 3])
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
# test weighting
|
||||
w = np.zeros_like(x)
|
||||
yw = y.copy()
|
||||
w[1::2] = 1
|
||||
y[0::2] = 0
|
||||
wcoef3 = leg.legfit(x, yw, 3, w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
wcoef3 = leg.legfit(x, yw, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
#
|
||||
wcoef2d = leg.legfit(x, np.array([yw, yw]).T, 3, w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
wcoef2d = leg.legfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
# test scaling with complex values x points whose square
|
||||
# is zero when summed.
|
||||
x = [1, 1j, -1, -1j]
|
||||
assert_almost_equal(leg.legfit(x, x, 1), [0, 1])
|
||||
assert_almost_equal(leg.legfit(x, x, [0, 1]), [0, 1])
|
||||
# test fitting only even Legendre polynomials
|
||||
x = np.linspace(-1, 1)
|
||||
y = f2(x)
|
||||
coef1 = leg.legfit(x, y, 4)
|
||||
assert_almost_equal(leg.legval(x, coef1), y)
|
||||
coef2 = leg.legfit(x, y, [0, 2, 4])
|
||||
assert_almost_equal(leg.legval(x, coef2), y)
|
||||
assert_almost_equal(coef1, coef2)
|
||||
|
||||
|
||||
class TestCompanion:
|
||||
|
||||
def test_raises(self):
|
||||
assert_raises(ValueError, leg.legcompanion, [])
|
||||
assert_raises(ValueError, leg.legcompanion, [1])
|
||||
|
||||
def test_dimensions(self):
|
||||
for i in range(1, 5):
|
||||
coef = [0]*i + [1]
|
||||
assert_(leg.legcompanion(coef).shape == (i, i))
|
||||
|
||||
def test_linear_root(self):
|
||||
assert_(leg.legcompanion([1, 2])[0, 0] == -.5)
|
||||
|
||||
|
||||
class TestGauss:
|
||||
|
||||
def test_100(self):
|
||||
x, w = leg.leggauss(100)
|
||||
|
||||
# test orthogonality. Note that the results need to be normalized,
|
||||
# otherwise the huge values that can arise from fast growing
|
||||
# functions like Laguerre can be very confusing.
|
||||
v = leg.legvander(x, 99)
|
||||
vv = np.dot(v.T * w, v)
|
||||
vd = 1/np.sqrt(vv.diagonal())
|
||||
vv = vd[:, None] * vv * vd
|
||||
assert_almost_equal(vv, np.eye(100))
|
||||
|
||||
# check that the integral of 1 is correct
|
||||
tgt = 2.0
|
||||
assert_almost_equal(w.sum(), tgt)
|
||||
|
||||
|
||||
class TestMisc:
|
||||
|
||||
def test_legfromroots(self):
|
||||
res = leg.legfromroots([])
|
||||
assert_almost_equal(trim(res), [1])
|
||||
for i in range(1, 5):
|
||||
roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
|
||||
pol = leg.legfromroots(roots)
|
||||
res = leg.legval(roots, pol)
|
||||
tgt = 0
|
||||
assert_(len(pol) == i + 1)
|
||||
assert_almost_equal(leg.leg2poly(pol)[-1], 1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
def test_legroots(self):
|
||||
assert_almost_equal(leg.legroots([1]), [])
|
||||
assert_almost_equal(leg.legroots([1, 2]), [-.5])
|
||||
for i in range(2, 5):
|
||||
tgt = np.linspace(-1, 1, i)
|
||||
res = leg.legroots(leg.legfromroots(tgt))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_legtrim(self):
|
||||
coef = [2, -1, 1, 0]
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, leg.legtrim, coef, -1)
|
||||
|
||||
# Test results
|
||||
assert_equal(leg.legtrim(coef), coef[:-1])
|
||||
assert_equal(leg.legtrim(coef, 1), coef[:-3])
|
||||
assert_equal(leg.legtrim(coef, 2), [0])
|
||||
|
||||
def test_legline(self):
|
||||
assert_equal(leg.legline(3, 4), [3, 4])
|
||||
|
||||
def test_legline_zeroscl(self):
|
||||
assert_equal(leg.legline(3, 0), [3])
|
||||
|
||||
def test_leg2poly(self):
|
||||
for i in range(10):
|
||||
assert_almost_equal(leg.leg2poly([0]*i + [1]), Llist[i])
|
||||
|
||||
def test_poly2leg(self):
|
||||
for i in range(10):
|
||||
assert_almost_equal(leg.poly2leg(Llist[i]), [0]*i + [1])
|
||||
|
||||
def test_weight(self):
|
||||
x = np.linspace(-1, 1, 11)
|
||||
tgt = 1.
|
||||
res = leg.legweight(x)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
|
@ -0,0 +1,611 @@
|
|||
"""Tests for polynomial module.
|
||||
|
||||
"""
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
import numpy.polynomial.polynomial as poly
|
||||
import pickle
|
||||
from copy import deepcopy
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
assert_warns, assert_array_equal, assert_raises_regex)
|
||||
|
||||
|
||||
def trim(x):
|
||||
return poly.polytrim(x, tol=1e-6)
|
||||
|
||||
T0 = [1]
|
||||
T1 = [0, 1]
|
||||
T2 = [-1, 0, 2]
|
||||
T3 = [0, -3, 0, 4]
|
||||
T4 = [1, 0, -8, 0, 8]
|
||||
T5 = [0, 5, 0, -20, 0, 16]
|
||||
T6 = [-1, 0, 18, 0, -48, 0, 32]
|
||||
T7 = [0, -7, 0, 56, 0, -112, 0, 64]
|
||||
T8 = [1, 0, -32, 0, 160, 0, -256, 0, 128]
|
||||
T9 = [0, 9, 0, -120, 0, 432, 0, -576, 0, 256]
|
||||
|
||||
Tlist = [T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]
|
||||
|
||||
|
||||
class TestConstants:
|
||||
|
||||
def test_polydomain(self):
|
||||
assert_equal(poly.polydomain, [-1, 1])
|
||||
|
||||
def test_polyzero(self):
|
||||
assert_equal(poly.polyzero, [0])
|
||||
|
||||
def test_polyone(self):
|
||||
assert_equal(poly.polyone, [1])
|
||||
|
||||
def test_polyx(self):
|
||||
assert_equal(poly.polyx, [0, 1])
|
||||
|
||||
def test_copy(self):
|
||||
x = poly.Polynomial([1, 2, 3])
|
||||
y = deepcopy(x)
|
||||
assert_equal(x, y)
|
||||
|
||||
def test_pickle(self):
|
||||
x = poly.Polynomial([1, 2, 3])
|
||||
y = pickle.loads(pickle.dumps(x))
|
||||
assert_equal(x, y)
|
||||
|
||||
class TestArithmetic:
|
||||
|
||||
def test_polyadd(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] += 1
|
||||
res = poly.polyadd([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_polysub(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(max(i, j) + 1)
|
||||
tgt[i] += 1
|
||||
tgt[j] -= 1
|
||||
res = poly.polysub([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_polymulx(self):
|
||||
assert_equal(poly.polymulx([0]), [0])
|
||||
assert_equal(poly.polymulx([1]), [0, 1])
|
||||
for i in range(1, 5):
|
||||
ser = [0]*i + [1]
|
||||
tgt = [0]*(i + 1) + [1]
|
||||
assert_equal(poly.polymulx(ser), tgt)
|
||||
|
||||
def test_polymul(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
tgt = np.zeros(i + j + 1)
|
||||
tgt[i + j] += 1
|
||||
res = poly.polymul([0]*i + [1], [0]*j + [1])
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
def test_polydiv(self):
|
||||
# check zero division
|
||||
assert_raises(ZeroDivisionError, poly.polydiv, [1], [0])
|
||||
|
||||
# check scalar division
|
||||
quo, rem = poly.polydiv([2], [2])
|
||||
assert_equal((quo, rem), (1, 0))
|
||||
quo, rem = poly.polydiv([2, 2], [2])
|
||||
assert_equal((quo, rem), ((1, 1), 0))
|
||||
|
||||
# check rest.
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
ci = [0]*i + [1, 2]
|
||||
cj = [0]*j + [1, 2]
|
||||
tgt = poly.polyadd(ci, cj)
|
||||
quo, rem = poly.polydiv(tgt, ci)
|
||||
res = poly.polyadd(poly.polymul(quo, ci), rem)
|
||||
assert_equal(res, tgt, err_msg=msg)
|
||||
|
||||
def test_polypow(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
msg = f"At i={i}, j={j}"
|
||||
c = np.arange(i + 1)
|
||||
tgt = reduce(poly.polymul, [c]*j, np.array([1]))
|
||||
res = poly.polypow(c, j)
|
||||
assert_equal(trim(res), trim(tgt), err_msg=msg)
|
||||
|
||||
|
||||
class TestEvaluation:
|
||||
# coefficients of 1 + 2*x + 3*x**2
|
||||
c1d = np.array([1., 2., 3.])
|
||||
c2d = np.einsum('i,j->ij', c1d, c1d)
|
||||
c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
|
||||
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
y = poly.polyval(x, [1., 2., 3.])
|
||||
|
||||
def test_polyval(self):
|
||||
#check empty input
|
||||
assert_equal(poly.polyval([], [1]).size, 0)
|
||||
|
||||
#check normal input)
|
||||
x = np.linspace(-1, 1)
|
||||
y = [x**i for i in range(5)]
|
||||
for i in range(5):
|
||||
tgt = y[i]
|
||||
res = poly.polyval(x, [0]*i + [1])
|
||||
assert_almost_equal(res, tgt)
|
||||
tgt = x*(x**2 - 1)
|
||||
res = poly.polyval(x, [0, -1, 0, 1])
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#check that shape is preserved
|
||||
for i in range(3):
|
||||
dims = [2]*i
|
||||
x = np.zeros(dims)
|
||||
assert_equal(poly.polyval(x, [1]).shape, dims)
|
||||
assert_equal(poly.polyval(x, [1, 0]).shape, dims)
|
||||
assert_equal(poly.polyval(x, [1, 0, 0]).shape, dims)
|
||||
|
||||
#check masked arrays are processed correctly
|
||||
mask = [False, True, False]
|
||||
mx = np.ma.array([1, 2, 3], mask=mask)
|
||||
res = np.polyval([7, 5, 3], mx)
|
||||
assert_array_equal(res.mask, mask)
|
||||
|
||||
#check subtypes of ndarray are preserved
|
||||
class C(np.ndarray):
|
||||
pass
|
||||
|
||||
cx = np.array([1, 2, 3]).view(C)
|
||||
assert_equal(type(np.polyval([2, 3, 4], cx)), C)
|
||||
|
||||
def test_polyvalfromroots(self):
|
||||
# check exception for broadcasting x values over root array with
|
||||
# too few dimensions
|
||||
assert_raises(ValueError, poly.polyvalfromroots,
|
||||
[1], [1], tensor=False)
|
||||
|
||||
# check empty input
|
||||
assert_equal(poly.polyvalfromroots([], [1]).size, 0)
|
||||
assert_(poly.polyvalfromroots([], [1]).shape == (0,))
|
||||
|
||||
# check empty input + multidimensional roots
|
||||
assert_equal(poly.polyvalfromroots([], [[1] * 5]).size, 0)
|
||||
assert_(poly.polyvalfromroots([], [[1] * 5]).shape == (5, 0))
|
||||
|
||||
# check scalar input
|
||||
assert_equal(poly.polyvalfromroots(1, 1), 0)
|
||||
assert_(poly.polyvalfromroots(1, np.ones((3, 3))).shape == (3,))
|
||||
|
||||
# check normal input)
|
||||
x = np.linspace(-1, 1)
|
||||
y = [x**i for i in range(5)]
|
||||
for i in range(1, 5):
|
||||
tgt = y[i]
|
||||
res = poly.polyvalfromroots(x, [0]*i)
|
||||
assert_almost_equal(res, tgt)
|
||||
tgt = x*(x - 1)*(x + 1)
|
||||
res = poly.polyvalfromroots(x, [-1, 0, 1])
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check that shape is preserved
|
||||
for i in range(3):
|
||||
dims = [2]*i
|
||||
x = np.zeros(dims)
|
||||
assert_equal(poly.polyvalfromroots(x, [1]).shape, dims)
|
||||
assert_equal(poly.polyvalfromroots(x, [1, 0]).shape, dims)
|
||||
assert_equal(poly.polyvalfromroots(x, [1, 0, 0]).shape, dims)
|
||||
|
||||
# check compatibility with factorization
|
||||
ptest = [15, 2, -16, -2, 1]
|
||||
r = poly.polyroots(ptest)
|
||||
x = np.linspace(-1, 1)
|
||||
assert_almost_equal(poly.polyval(x, ptest),
|
||||
poly.polyvalfromroots(x, r))
|
||||
|
||||
# check multidimensional arrays of roots and values
|
||||
# check tensor=False
|
||||
rshape = (3, 5)
|
||||
x = np.arange(-3, 2)
|
||||
r = np.random.randint(-5, 5, size=rshape)
|
||||
res = poly.polyvalfromroots(x, r, tensor=False)
|
||||
tgt = np.empty(r.shape[1:])
|
||||
for ii in range(tgt.size):
|
||||
tgt[ii] = poly.polyvalfromroots(x[ii], r[:, ii])
|
||||
assert_equal(res, tgt)
|
||||
|
||||
# check tensor=True
|
||||
x = np.vstack([x, 2*x])
|
||||
res = poly.polyvalfromroots(x, r, tensor=True)
|
||||
tgt = np.empty(r.shape[1:] + x.shape)
|
||||
for ii in range(r.shape[1]):
|
||||
for jj in range(x.shape[0]):
|
||||
tgt[ii, jj, :] = poly.polyvalfromroots(x[jj], r[:, ii])
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test_polyval2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises_regex(ValueError, 'incompatible',
|
||||
poly.polyval2d, x1, x2[:2], self.c2d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2
|
||||
res = poly.polyval2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = poly.polyval2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_polyval3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test exceptions
|
||||
assert_raises_regex(ValueError, 'incompatible',
|
||||
poly.polyval3d, x1, x2, x3[:2], self.c3d)
|
||||
|
||||
#test values
|
||||
tgt = y1*y2*y3
|
||||
res = poly.polyval3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = poly.polyval3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3))
|
||||
|
||||
def test_polygrid2d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j->ij', y1, y2)
|
||||
res = poly.polygrid2d(x1, x2, self.c2d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = poly.polygrid2d(z, z, self.c2d)
|
||||
assert_(res.shape == (2, 3)*2)
|
||||
|
||||
def test_polygrid3d(self):
|
||||
x1, x2, x3 = self.x
|
||||
y1, y2, y3 = self.y
|
||||
|
||||
#test values
|
||||
tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
|
||||
res = poly.polygrid3d(x1, x2, x3, self.c3d)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
#test shape
|
||||
z = np.ones((2, 3))
|
||||
res = poly.polygrid3d(z, z, z, self.c3d)
|
||||
assert_(res.shape == (2, 3)*3)
|
||||
|
||||
|
||||
class TestIntegral:
|
||||
|
||||
def test_polyint(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, poly.polyint, [0], .5)
|
||||
assert_raises(ValueError, poly.polyint, [0], -1)
|
||||
assert_raises(ValueError, poly.polyint, [0], 1, [0, 0])
|
||||
assert_raises(ValueError, poly.polyint, [0], lbnd=[0])
|
||||
assert_raises(ValueError, poly.polyint, [0], scl=[0])
|
||||
assert_raises(TypeError, poly.polyint, [0], axis=.5)
|
||||
with assert_warns(DeprecationWarning):
|
||||
poly.polyint([1, 1], 1.)
|
||||
|
||||
# test integration of zero polynomial
|
||||
for i in range(2, 5):
|
||||
k = [0]*(i - 2) + [1]
|
||||
res = poly.polyint([0], m=i, k=k)
|
||||
assert_almost_equal(res, [0, 1])
|
||||
|
||||
# check single integration with integration constant
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [1/scl]
|
||||
res = poly.polyint(pol, m=1, k=[i])
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check single integration with integration constant and lbnd
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
res = poly.polyint(pol, m=1, k=[i], lbnd=-1)
|
||||
assert_almost_equal(poly.polyval(-1, res), i)
|
||||
|
||||
# check single integration with integration constant and scaling
|
||||
for i in range(5):
|
||||
scl = i + 1
|
||||
pol = [0]*i + [1]
|
||||
tgt = [i] + [0]*i + [2/scl]
|
||||
res = poly.polyint(pol, m=1, k=[i], scl=2)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with default k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = poly.polyint(tgt, m=1)
|
||||
res = poly.polyint(pol, m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with defined k
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = poly.polyint(tgt, m=1, k=[k])
|
||||
res = poly.polyint(pol, m=j, k=list(range(j)))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with lbnd
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = poly.polyint(tgt, m=1, k=[k], lbnd=-1)
|
||||
res = poly.polyint(pol, m=j, k=list(range(j)), lbnd=-1)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check multiple integrations with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
pol = [0]*i + [1]
|
||||
tgt = pol[:]
|
||||
for k in range(j):
|
||||
tgt = poly.polyint(tgt, m=1, k=[k], scl=2)
|
||||
res = poly.polyint(pol, m=j, k=list(range(j)), scl=2)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_polyint_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([poly.polyint(c) for c in c2d.T]).T
|
||||
res = poly.polyint(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([poly.polyint(c) for c in c2d])
|
||||
res = poly.polyint(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([poly.polyint(c, k=3) for c in c2d])
|
||||
res = poly.polyint(c2d, k=3, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestDerivative:
|
||||
|
||||
def test_polyder(self):
|
||||
# check exceptions
|
||||
assert_raises(TypeError, poly.polyder, [0], .5)
|
||||
assert_raises(ValueError, poly.polyder, [0], -1)
|
||||
|
||||
# check that zeroth derivative does nothing
|
||||
for i in range(5):
|
||||
tgt = [0]*i + [1]
|
||||
res = poly.polyder(tgt, m=0)
|
||||
assert_equal(trim(res), trim(tgt))
|
||||
|
||||
# check that derivation is the inverse of integration
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = poly.polyder(poly.polyint(tgt, m=j), m=j)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
# check derivation with scaling
|
||||
for i in range(5):
|
||||
for j in range(2, 5):
|
||||
tgt = [0]*i + [1]
|
||||
res = poly.polyder(poly.polyint(tgt, m=j, scl=2), m=j, scl=.5)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_polyder_axis(self):
|
||||
# check that axis keyword works
|
||||
c2d = np.random.random((3, 4))
|
||||
|
||||
tgt = np.vstack([poly.polyder(c) for c in c2d.T]).T
|
||||
res = poly.polyder(c2d, axis=0)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
tgt = np.vstack([poly.polyder(c) for c in c2d])
|
||||
res = poly.polyder(c2d, axis=1)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
|
||||
class TestVander:
|
||||
# some random values in [-1, 1)
|
||||
x = np.random.random((3, 5))*2 - 1
|
||||
|
||||
def test_polyvander(self):
|
||||
# check for 1d x
|
||||
x = np.arange(3)
|
||||
v = poly.polyvander(x, 3)
|
||||
assert_(v.shape == (3, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], poly.polyval(x, coef))
|
||||
|
||||
# check for 2d x
|
||||
x = np.array([[1, 2], [3, 4], [5, 6]])
|
||||
v = poly.polyvander(x, 3)
|
||||
assert_(v.shape == (3, 2, 4))
|
||||
for i in range(4):
|
||||
coef = [0]*i + [1]
|
||||
assert_almost_equal(v[..., i], poly.polyval(x, coef))
|
||||
|
||||
def test_polyvander2d(self):
|
||||
# also tests polyval2d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3))
|
||||
van = poly.polyvander2d(x1, x2, [1, 2])
|
||||
tgt = poly.polyval2d(x1, x2, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = poly.polyvander2d([x1], [x2], [1, 2])
|
||||
assert_(van.shape == (1, 5, 6))
|
||||
|
||||
def test_polyvander3d(self):
|
||||
# also tests polyval3d for non-square coefficient array
|
||||
x1, x2, x3 = self.x
|
||||
c = np.random.random((2, 3, 4))
|
||||
van = poly.polyvander3d(x1, x2, x3, [1, 2, 3])
|
||||
tgt = poly.polyval3d(x1, x2, x3, c)
|
||||
res = np.dot(van, c.flat)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# check shape
|
||||
van = poly.polyvander3d([x1], [x2], [x3], [1, 2, 3])
|
||||
assert_(van.shape == (1, 5, 24))
|
||||
|
||||
def test_polyvandernegdeg(self):
|
||||
x = np.arange(3)
|
||||
assert_raises(ValueError, poly.polyvander, x, -1)
|
||||
|
||||
|
||||
class TestCompanion:
|
||||
|
||||
def test_raises(self):
|
||||
assert_raises(ValueError, poly.polycompanion, [])
|
||||
assert_raises(ValueError, poly.polycompanion, [1])
|
||||
|
||||
def test_dimensions(self):
|
||||
for i in range(1, 5):
|
||||
coef = [0]*i + [1]
|
||||
assert_(poly.polycompanion(coef).shape == (i, i))
|
||||
|
||||
def test_linear_root(self):
|
||||
assert_(poly.polycompanion([1, 2])[0, 0] == -.5)
|
||||
|
||||
|
||||
class TestMisc:
|
||||
|
||||
def test_polyfromroots(self):
|
||||
res = poly.polyfromroots([])
|
||||
assert_almost_equal(trim(res), [1])
|
||||
for i in range(1, 5):
|
||||
roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
|
||||
tgt = Tlist[i]
|
||||
res = poly.polyfromroots(roots)*2**(i-1)
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_polyroots(self):
|
||||
assert_almost_equal(poly.polyroots([1]), [])
|
||||
assert_almost_equal(poly.polyroots([1, 2]), [-.5])
|
||||
for i in range(2, 5):
|
||||
tgt = np.linspace(-1, 1, i)
|
||||
res = poly.polyroots(poly.polyfromroots(tgt))
|
||||
assert_almost_equal(trim(res), trim(tgt))
|
||||
|
||||
def test_polyfit(self):
|
||||
def f(x):
|
||||
return x*(x - 1)*(x - 2)
|
||||
|
||||
def f2(x):
|
||||
return x**4 + x**2 + 1
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, poly.polyfit, [1], [1], -1)
|
||||
assert_raises(TypeError, poly.polyfit, [[1]], [1], 0)
|
||||
assert_raises(TypeError, poly.polyfit, [], [1], 0)
|
||||
assert_raises(TypeError, poly.polyfit, [1], [[[1]]], 0)
|
||||
assert_raises(TypeError, poly.polyfit, [1, 2], [1], 0)
|
||||
assert_raises(TypeError, poly.polyfit, [1], [1, 2], 0)
|
||||
assert_raises(TypeError, poly.polyfit, [1], [1], 0, w=[[1]])
|
||||
assert_raises(TypeError, poly.polyfit, [1], [1], 0, w=[1, 1])
|
||||
assert_raises(ValueError, poly.polyfit, [1], [1], [-1,])
|
||||
assert_raises(ValueError, poly.polyfit, [1], [1], [2, -1, 6])
|
||||
assert_raises(TypeError, poly.polyfit, [1], [1], [])
|
||||
|
||||
# Test fit
|
||||
x = np.linspace(0, 2)
|
||||
y = f(x)
|
||||
#
|
||||
coef3 = poly.polyfit(x, y, 3)
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(poly.polyval(x, coef3), y)
|
||||
coef3 = poly.polyfit(x, y, [0, 1, 2, 3])
|
||||
assert_equal(len(coef3), 4)
|
||||
assert_almost_equal(poly.polyval(x, coef3), y)
|
||||
#
|
||||
coef4 = poly.polyfit(x, y, 4)
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(poly.polyval(x, coef4), y)
|
||||
coef4 = poly.polyfit(x, y, [0, 1, 2, 3, 4])
|
||||
assert_equal(len(coef4), 5)
|
||||
assert_almost_equal(poly.polyval(x, coef4), y)
|
||||
#
|
||||
coef2d = poly.polyfit(x, np.array([y, y]).T, 3)
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
coef2d = poly.polyfit(x, np.array([y, y]).T, [0, 1, 2, 3])
|
||||
assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
|
||||
# test weighting
|
||||
w = np.zeros_like(x)
|
||||
yw = y.copy()
|
||||
w[1::2] = 1
|
||||
yw[0::2] = 0
|
||||
wcoef3 = poly.polyfit(x, yw, 3, w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
wcoef3 = poly.polyfit(x, yw, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef3, coef3)
|
||||
#
|
||||
wcoef2d = poly.polyfit(x, np.array([yw, yw]).T, 3, w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
wcoef2d = poly.polyfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
|
||||
assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
|
||||
# test scaling with complex values x points whose square
|
||||
# is zero when summed.
|
||||
x = [1, 1j, -1, -1j]
|
||||
assert_almost_equal(poly.polyfit(x, x, 1), [0, 1])
|
||||
assert_almost_equal(poly.polyfit(x, x, [0, 1]), [0, 1])
|
||||
# test fitting only even Polyendre polynomials
|
||||
x = np.linspace(-1, 1)
|
||||
y = f2(x)
|
||||
coef1 = poly.polyfit(x, y, 4)
|
||||
assert_almost_equal(poly.polyval(x, coef1), y)
|
||||
coef2 = poly.polyfit(x, y, [0, 2, 4])
|
||||
assert_almost_equal(poly.polyval(x, coef2), y)
|
||||
assert_almost_equal(coef1, coef2)
|
||||
|
||||
def test_polytrim(self):
|
||||
coef = [2, -1, 1, 0]
|
||||
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, poly.polytrim, coef, -1)
|
||||
|
||||
# Test results
|
||||
assert_equal(poly.polytrim(coef), coef[:-1])
|
||||
assert_equal(poly.polytrim(coef, 1), coef[:-3])
|
||||
assert_equal(poly.polytrim(coef, 2), [0])
|
||||
|
||||
def test_polyline(self):
|
||||
assert_equal(poly.polyline(3, 4), [3, 4])
|
||||
|
||||
def test_polyline_zero(self):
|
||||
assert_equal(poly.polyline(3, 0), [3])
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
"""Tests for polyutils module.
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
import numpy.polynomial.polyutils as pu
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
)
|
||||
|
||||
|
||||
class TestMisc:
|
||||
|
||||
def test_trimseq(self):
|
||||
for i in range(5):
|
||||
tgt = [1]
|
||||
res = pu.trimseq([1] + [0]*5)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test_as_series(self):
|
||||
# check exceptions
|
||||
assert_raises(ValueError, pu.as_series, [[]])
|
||||
assert_raises(ValueError, pu.as_series, [[[1, 2]]])
|
||||
assert_raises(ValueError, pu.as_series, [[1], ['a']])
|
||||
# check common types
|
||||
types = ['i', 'd', 'O']
|
||||
for i in range(len(types)):
|
||||
for j in range(i):
|
||||
ci = np.ones(1, types[i])
|
||||
cj = np.ones(1, types[j])
|
||||
[resi, resj] = pu.as_series([ci, cj])
|
||||
assert_(resi.dtype.char == resj.dtype.char)
|
||||
assert_(resj.dtype.char == types[i])
|
||||
|
||||
def test_trimcoef(self):
|
||||
coef = [2, -1, 1, 0]
|
||||
# Test exceptions
|
||||
assert_raises(ValueError, pu.trimcoef, coef, -1)
|
||||
# Test results
|
||||
assert_equal(pu.trimcoef(coef), coef[:-1])
|
||||
assert_equal(pu.trimcoef(coef, 1), coef[:-3])
|
||||
assert_equal(pu.trimcoef(coef, 2), [0])
|
||||
|
||||
def test_vander_nd_exception(self):
|
||||
# n_dims != len(points)
|
||||
assert_raises(ValueError, pu._vander_nd, (), (1, 2, 3), [90])
|
||||
# n_dims != len(degrees)
|
||||
assert_raises(ValueError, pu._vander_nd, (), (), [90.65])
|
||||
# n_dims == 0
|
||||
assert_raises(ValueError, pu._vander_nd, (), (), [])
|
||||
|
||||
def test_div_zerodiv(self):
|
||||
# c2[-1] == 0
|
||||
assert_raises(ZeroDivisionError, pu._div, pu._div, (1, 2, 3), [0])
|
||||
|
||||
def test_pow_too_large(self):
|
||||
# power > maxpower
|
||||
assert_raises(ValueError, pu._pow, (), [1, 2, 3], 5, 4)
|
||||
|
||||
class TestDomain:
|
||||
|
||||
def test_getdomain(self):
|
||||
# test for real values
|
||||
x = [1, 10, 3, -1]
|
||||
tgt = [-1, 10]
|
||||
res = pu.getdomain(x)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# test for complex values
|
||||
x = [1 + 1j, 1 - 1j, 0, 2]
|
||||
tgt = [-1j, 2 + 1j]
|
||||
res = pu.getdomain(x)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
def test_mapdomain(self):
|
||||
# test for real values
|
||||
dom1 = [0, 4]
|
||||
dom2 = [1, 3]
|
||||
tgt = dom2
|
||||
res = pu.mapdomain(dom1, dom1, dom2)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# test for complex values
|
||||
dom1 = [0 - 1j, 2 + 1j]
|
||||
dom2 = [-2, 2]
|
||||
tgt = dom2
|
||||
x = dom1
|
||||
res = pu.mapdomain(x, dom1, dom2)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# test for multidimensional arrays
|
||||
dom1 = [0, 4]
|
||||
dom2 = [1, 3]
|
||||
tgt = np.array([dom2, dom2])
|
||||
x = np.array([dom1, dom1])
|
||||
res = pu.mapdomain(x, dom1, dom2)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# test that subtypes are preserved.
|
||||
class MyNDArray(np.ndarray):
|
||||
pass
|
||||
|
||||
dom1 = [0, 4]
|
||||
dom2 = [1, 3]
|
||||
x = np.array([dom1, dom1]).view(MyNDArray)
|
||||
res = pu.mapdomain(x, dom1, dom2)
|
||||
assert_(isinstance(res, MyNDArray))
|
||||
|
||||
def test_mapparms(self):
|
||||
# test for real values
|
||||
dom1 = [0, 4]
|
||||
dom2 = [1, 3]
|
||||
tgt = [1, .5]
|
||||
res = pu. mapparms(dom1, dom2)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
||||
# test for complex values
|
||||
dom1 = [0 - 1j, 2 + 1j]
|
||||
dom2 = [-2, 2]
|
||||
tgt = [-1 + 1j, 1 - 1j]
|
||||
res = pu.mapparms(dom1, dom2)
|
||||
assert_almost_equal(res, tgt)
|
||||
|
|
@ -0,0 +1,530 @@
|
|||
from math import nan, inf
|
||||
import pytest
|
||||
from numpy.core import array, arange, printoptions
|
||||
import numpy.polynomial as poly
|
||||
from numpy.testing import assert_equal, assert_
|
||||
|
||||
# For testing polynomial printing with object arrays
|
||||
from fractions import Fraction
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
class TestStrUnicodeSuperSubscripts:
|
||||
|
||||
@pytest.fixture(scope='class', autouse=True)
|
||||
def use_unicode(self):
|
||||
poly.set_default_printstyle('unicode')
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0·x + 3.0·x²"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0·x + 3.0·x² - 1.0·x³"),
|
||||
(arange(12), ("0.0 + 1.0·x + 2.0·x² + 3.0·x³ + 4.0·x⁴ + 5.0·x⁵ + "
|
||||
"6.0·x⁶ + 7.0·x⁷ +\n8.0·x⁸ + 9.0·x⁹ + 10.0·x¹⁰ + "
|
||||
"11.0·x¹¹")),
|
||||
))
|
||||
def test_polynomial_str(self, inp, tgt):
|
||||
res = str(poly.Polynomial(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0·T₁(x) + 3.0·T₂(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0·T₁(x) + 3.0·T₂(x) - 1.0·T₃(x)"),
|
||||
(arange(12), ("0.0 + 1.0·T₁(x) + 2.0·T₂(x) + 3.0·T₃(x) + 4.0·T₄(x) + "
|
||||
"5.0·T₅(x) +\n6.0·T₆(x) + 7.0·T₇(x) + 8.0·T₈(x) + "
|
||||
"9.0·T₉(x) + 10.0·T₁₀(x) + 11.0·T₁₁(x)")),
|
||||
))
|
||||
def test_chebyshev_str(self, inp, tgt):
|
||||
res = str(poly.Chebyshev(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0·P₁(x) + 3.0·P₂(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0·P₁(x) + 3.0·P₂(x) - 1.0·P₃(x)"),
|
||||
(arange(12), ("0.0 + 1.0·P₁(x) + 2.0·P₂(x) + 3.0·P₃(x) + 4.0·P₄(x) + "
|
||||
"5.0·P₅(x) +\n6.0·P₆(x) + 7.0·P₇(x) + 8.0·P₈(x) + "
|
||||
"9.0·P₉(x) + 10.0·P₁₀(x) + 11.0·P₁₁(x)")),
|
||||
))
|
||||
def test_legendre_str(self, inp, tgt):
|
||||
res = str(poly.Legendre(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0·H₁(x) + 3.0·H₂(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0·H₁(x) + 3.0·H₂(x) - 1.0·H₃(x)"),
|
||||
(arange(12), ("0.0 + 1.0·H₁(x) + 2.0·H₂(x) + 3.0·H₃(x) + 4.0·H₄(x) + "
|
||||
"5.0·H₅(x) +\n6.0·H₆(x) + 7.0·H₇(x) + 8.0·H₈(x) + "
|
||||
"9.0·H₉(x) + 10.0·H₁₀(x) + 11.0·H₁₁(x)")),
|
||||
))
|
||||
def test_hermite_str(self, inp, tgt):
|
||||
res = str(poly.Hermite(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0·He₁(x) + 3.0·He₂(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0·He₁(x) + 3.0·He₂(x) - 1.0·He₃(x)"),
|
||||
(arange(12), ("0.0 + 1.0·He₁(x) + 2.0·He₂(x) + 3.0·He₃(x) + "
|
||||
"4.0·He₄(x) + 5.0·He₅(x) +\n6.0·He₆(x) + 7.0·He₇(x) + "
|
||||
"8.0·He₈(x) + 9.0·He₉(x) + 10.0·He₁₀(x) +\n"
|
||||
"11.0·He₁₁(x)")),
|
||||
))
|
||||
def test_hermiteE_str(self, inp, tgt):
|
||||
res = str(poly.HermiteE(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0·L₁(x) + 3.0·L₂(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0·L₁(x) + 3.0·L₂(x) - 1.0·L₃(x)"),
|
||||
(arange(12), ("0.0 + 1.0·L₁(x) + 2.0·L₂(x) + 3.0·L₃(x) + 4.0·L₄(x) + "
|
||||
"5.0·L₅(x) +\n6.0·L₆(x) + 7.0·L₇(x) + 8.0·L₈(x) + "
|
||||
"9.0·L₉(x) + 10.0·L₁₀(x) + 11.0·L₁₁(x)")),
|
||||
))
|
||||
def test_laguerre_str(self, inp, tgt):
|
||||
res = str(poly.Laguerre(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
|
||||
class TestStrAscii:
|
||||
|
||||
@pytest.fixture(scope='class', autouse=True)
|
||||
def use_ascii(self):
|
||||
poly.set_default_printstyle('ascii')
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0 x + 3.0 x**2"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0 x + 3.0 x**2 - 1.0 x**3"),
|
||||
(arange(12), ("0.0 + 1.0 x + 2.0 x**2 + 3.0 x**3 + 4.0 x**4 + "
|
||||
"5.0 x**5 + 6.0 x**6 +\n7.0 x**7 + 8.0 x**8 + "
|
||||
"9.0 x**9 + 10.0 x**10 + 11.0 x**11")),
|
||||
))
|
||||
def test_polynomial_str(self, inp, tgt):
|
||||
res = str(poly.Polynomial(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0 T_1(x) + 3.0 T_2(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0 T_1(x) + 3.0 T_2(x) - 1.0 T_3(x)"),
|
||||
(arange(12), ("0.0 + 1.0 T_1(x) + 2.0 T_2(x) + 3.0 T_3(x) + "
|
||||
"4.0 T_4(x) + 5.0 T_5(x) +\n6.0 T_6(x) + 7.0 T_7(x) + "
|
||||
"8.0 T_8(x) + 9.0 T_9(x) + 10.0 T_10(x) +\n"
|
||||
"11.0 T_11(x)")),
|
||||
))
|
||||
def test_chebyshev_str(self, inp, tgt):
|
||||
res = str(poly.Chebyshev(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0 P_1(x) + 3.0 P_2(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0 P_1(x) + 3.0 P_2(x) - 1.0 P_3(x)"),
|
||||
(arange(12), ("0.0 + 1.0 P_1(x) + 2.0 P_2(x) + 3.0 P_3(x) + "
|
||||
"4.0 P_4(x) + 5.0 P_5(x) +\n6.0 P_6(x) + 7.0 P_7(x) + "
|
||||
"8.0 P_8(x) + 9.0 P_9(x) + 10.0 P_10(x) +\n"
|
||||
"11.0 P_11(x)")),
|
||||
))
|
||||
def test_legendre_str(self, inp, tgt):
|
||||
res = str(poly.Legendre(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0 H_1(x) + 3.0 H_2(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0 H_1(x) + 3.0 H_2(x) - 1.0 H_3(x)"),
|
||||
(arange(12), ("0.0 + 1.0 H_1(x) + 2.0 H_2(x) + 3.0 H_3(x) + "
|
||||
"4.0 H_4(x) + 5.0 H_5(x) +\n6.0 H_6(x) + 7.0 H_7(x) + "
|
||||
"8.0 H_8(x) + 9.0 H_9(x) + 10.0 H_10(x) +\n"
|
||||
"11.0 H_11(x)")),
|
||||
))
|
||||
def test_hermite_str(self, inp, tgt):
|
||||
res = str(poly.Hermite(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0 He_1(x) + 3.0 He_2(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0 He_1(x) + 3.0 He_2(x) - 1.0 He_3(x)"),
|
||||
(arange(12), ("0.0 + 1.0 He_1(x) + 2.0 He_2(x) + 3.0 He_3(x) + "
|
||||
"4.0 He_4(x) +\n5.0 He_5(x) + 6.0 He_6(x) + "
|
||||
"7.0 He_7(x) + 8.0 He_8(x) + 9.0 He_9(x) +\n"
|
||||
"10.0 He_10(x) + 11.0 He_11(x)")),
|
||||
))
|
||||
def test_hermiteE_str(self, inp, tgt):
|
||||
res = str(poly.HermiteE(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
@pytest.mark.parametrize(('inp', 'tgt'), (
|
||||
([1, 2, 3], "1.0 + 2.0 L_1(x) + 3.0 L_2(x)"),
|
||||
([-1, 0, 3, -1], "-1.0 + 0.0 L_1(x) + 3.0 L_2(x) - 1.0 L_3(x)"),
|
||||
(arange(12), ("0.0 + 1.0 L_1(x) + 2.0 L_2(x) + 3.0 L_3(x) + "
|
||||
"4.0 L_4(x) + 5.0 L_5(x) +\n6.0 L_6(x) + 7.0 L_7(x) + "
|
||||
"8.0 L_8(x) + 9.0 L_9(x) + 10.0 L_10(x) +\n"
|
||||
"11.0 L_11(x)")),
|
||||
))
|
||||
def test_laguerre_str(self, inp, tgt):
|
||||
res = str(poly.Laguerre(inp))
|
||||
assert_equal(res, tgt)
|
||||
|
||||
|
||||
class TestLinebreaking:
|
||||
|
||||
@pytest.fixture(scope='class', autouse=True)
|
||||
def use_ascii(self):
|
||||
poly.set_default_printstyle('ascii')
|
||||
|
||||
def test_single_line_one_less(self):
|
||||
# With 'ascii' style, len(str(p)) is default linewidth - 1 (i.e. 74)
|
||||
p = poly.Polynomial([12345678, 12345678, 12345678, 12345678, 123])
|
||||
assert_equal(len(str(p)), 74)
|
||||
assert_equal(str(p), (
|
||||
'12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
|
||||
'12345678.0 x**3 + 123.0 x**4'
|
||||
))
|
||||
|
||||
def test_num_chars_is_linewidth(self):
|
||||
# len(str(p)) == default linewidth == 75
|
||||
p = poly.Polynomial([12345678, 12345678, 12345678, 12345678, 1234])
|
||||
assert_equal(len(str(p)), 75)
|
||||
assert_equal(str(p), (
|
||||
'12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
|
||||
'12345678.0 x**3 +\n1234.0 x**4'
|
||||
))
|
||||
|
||||
def test_first_linebreak_multiline_one_less_than_linewidth(self):
|
||||
# Multiline str where len(first_line) + len(next_term) == lw - 1 == 74
|
||||
p = poly.Polynomial(
|
||||
[12345678, 12345678, 12345678, 12345678, 1, 12345678]
|
||||
)
|
||||
assert_equal(len(str(p).split('\n')[0]), 74)
|
||||
assert_equal(str(p), (
|
||||
'12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
|
||||
'12345678.0 x**3 + 1.0 x**4 +\n12345678.0 x**5'
|
||||
))
|
||||
|
||||
def test_first_linebreak_multiline_on_linewidth(self):
|
||||
# First line is one character longer than previous test
|
||||
p = poly.Polynomial(
|
||||
[12345678, 12345678, 12345678, 12345678.12, 1, 12345678]
|
||||
)
|
||||
assert_equal(str(p), (
|
||||
'12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
|
||||
'12345678.12 x**3 +\n1.0 x**4 + 12345678.0 x**5'
|
||||
))
|
||||
|
||||
@pytest.mark.parametrize(('lw', 'tgt'), (
|
||||
(75, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 + 40000.0 x**4 + '
|
||||
'500000.0 x**5 +\n600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 + '
|
||||
'900.0 x**9')),
|
||||
(45, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 +\n40000.0 x**4 + '
|
||||
'500000.0 x**5 +\n600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 +\n'
|
||||
'900.0 x**9')),
|
||||
(132, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 + 40000.0 x**4 + '
|
||||
'500000.0 x**5 + 600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 + '
|
||||
'900.0 x**9')),
|
||||
))
|
||||
def test_linewidth_printoption(self, lw, tgt):
|
||||
p = poly.Polynomial(
|
||||
[0, 10, 200, 3000, 40000, 500000, 600000, 70000, 8000, 900]
|
||||
)
|
||||
with printoptions(linewidth=lw):
|
||||
assert_equal(str(p), tgt)
|
||||
for line in str(p).split('\n'):
|
||||
assert_(len(line) < lw)
|
||||
|
||||
|
||||
def test_set_default_printoptions():
|
||||
p = poly.Polynomial([1, 2, 3])
|
||||
c = poly.Chebyshev([1, 2, 3])
|
||||
poly.set_default_printstyle('ascii')
|
||||
assert_equal(str(p), "1.0 + 2.0 x + 3.0 x**2")
|
||||
assert_equal(str(c), "1.0 + 2.0 T_1(x) + 3.0 T_2(x)")
|
||||
poly.set_default_printstyle('unicode')
|
||||
assert_equal(str(p), "1.0 + 2.0·x + 3.0·x²")
|
||||
assert_equal(str(c), "1.0 + 2.0·T₁(x) + 3.0·T₂(x)")
|
||||
with pytest.raises(ValueError):
|
||||
poly.set_default_printstyle('invalid_input')
|
||||
|
||||
|
||||
def test_complex_coefficients():
|
||||
"""Test both numpy and built-in complex."""
|
||||
coefs = [0+1j, 1+1j, -2+2j, 3+0j]
|
||||
# numpy complex
|
||||
p1 = poly.Polynomial(coefs)
|
||||
# Python complex
|
||||
p2 = poly.Polynomial(array(coefs, dtype=object))
|
||||
poly.set_default_printstyle('unicode')
|
||||
assert_equal(str(p1), "1j + (1+1j)·x - (2-2j)·x² + (3+0j)·x³")
|
||||
assert_equal(str(p2), "1j + (1+1j)·x + (-2+2j)·x² + (3+0j)·x³")
|
||||
poly.set_default_printstyle('ascii')
|
||||
assert_equal(str(p1), "1j + (1+1j) x - (2-2j) x**2 + (3+0j) x**3")
|
||||
assert_equal(str(p2), "1j + (1+1j) x + (-2+2j) x**2 + (3+0j) x**3")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('coefs', 'tgt'), (
|
||||
(array([Fraction(1, 2), Fraction(3, 4)], dtype=object), (
|
||||
"1/2 + 3/4·x"
|
||||
)),
|
||||
(array([1, 2, Fraction(5, 7)], dtype=object), (
|
||||
"1 + 2·x + 5/7·x²"
|
||||
)),
|
||||
(array([Decimal('1.00'), Decimal('2.2'), 3], dtype=object), (
|
||||
"1.00 + 2.2·x + 3·x²"
|
||||
)),
|
||||
))
|
||||
def test_numeric_object_coefficients(coefs, tgt):
|
||||
p = poly.Polynomial(coefs)
|
||||
poly.set_default_printstyle('unicode')
|
||||
assert_equal(str(p), tgt)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('coefs', 'tgt'), (
|
||||
(array([1, 2, 'f'], dtype=object), '1 + 2·x + f·x²'),
|
||||
(array([1, 2, [3, 4]], dtype=object), '1 + 2·x + [3, 4]·x²'),
|
||||
))
|
||||
def test_nonnumeric_object_coefficients(coefs, tgt):
|
||||
"""
|
||||
Test coef fallback for object arrays of non-numeric coefficients.
|
||||
"""
|
||||
p = poly.Polynomial(coefs)
|
||||
poly.set_default_printstyle('unicode')
|
||||
assert_equal(str(p), tgt)
|
||||
|
||||
|
||||
class TestFormat:
|
||||
def test_format_unicode(self):
|
||||
poly.set_default_printstyle('ascii')
|
||||
p = poly.Polynomial([1, 2, 0, -1])
|
||||
assert_equal(format(p, 'unicode'), "1.0 + 2.0·x + 0.0·x² - 1.0·x³")
|
||||
|
||||
def test_format_ascii(self):
|
||||
poly.set_default_printstyle('unicode')
|
||||
p = poly.Polynomial([1, 2, 0, -1])
|
||||
assert_equal(
|
||||
format(p, 'ascii'), "1.0 + 2.0 x + 0.0 x**2 - 1.0 x**3"
|
||||
)
|
||||
|
||||
def test_empty_formatstr(self):
|
||||
poly.set_default_printstyle('ascii')
|
||||
p = poly.Polynomial([1, 2, 3])
|
||||
assert_equal(format(p), "1.0 + 2.0 x + 3.0 x**2")
|
||||
assert_equal(f"{p}", "1.0 + 2.0 x + 3.0 x**2")
|
||||
|
||||
def test_bad_formatstr(self):
|
||||
p = poly.Polynomial([1, 2, 0, -1])
|
||||
with pytest.raises(ValueError):
|
||||
format(p, '.2f')
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('poly', 'tgt'), (
|
||||
(poly.Polynomial, '1.0 + 2.0·z + 3.0·z²'),
|
||||
(poly.Chebyshev, '1.0 + 2.0·T₁(z) + 3.0·T₂(z)'),
|
||||
(poly.Hermite, '1.0 + 2.0·H₁(z) + 3.0·H₂(z)'),
|
||||
(poly.HermiteE, '1.0 + 2.0·He₁(z) + 3.0·He₂(z)'),
|
||||
(poly.Laguerre, '1.0 + 2.0·L₁(z) + 3.0·L₂(z)'),
|
||||
(poly.Legendre, '1.0 + 2.0·P₁(z) + 3.0·P₂(z)'),
|
||||
))
|
||||
def test_symbol(poly, tgt):
|
||||
p = poly([1, 2, 3], symbol='z')
|
||||
assert_equal(f"{p:unicode}", tgt)
|
||||
|
||||
|
||||
class TestRepr:
|
||||
def test_polynomial_str(self):
|
||||
res = repr(poly.Polynomial([0, 1]))
|
||||
tgt = (
|
||||
"Polynomial([0., 1.], domain=[-1, 1], window=[-1, 1], "
|
||||
"symbol='x')"
|
||||
)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test_chebyshev_str(self):
|
||||
res = repr(poly.Chebyshev([0, 1]))
|
||||
tgt = (
|
||||
"Chebyshev([0., 1.], domain=[-1, 1], window=[-1, 1], "
|
||||
"symbol='x')"
|
||||
)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test_legendre_repr(self):
|
||||
res = repr(poly.Legendre([0, 1]))
|
||||
tgt = (
|
||||
"Legendre([0., 1.], domain=[-1, 1], window=[-1, 1], "
|
||||
"symbol='x')"
|
||||
)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test_hermite_repr(self):
|
||||
res = repr(poly.Hermite([0, 1]))
|
||||
tgt = (
|
||||
"Hermite([0., 1.], domain=[-1, 1], window=[-1, 1], "
|
||||
"symbol='x')"
|
||||
)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test_hermiteE_repr(self):
|
||||
res = repr(poly.HermiteE([0, 1]))
|
||||
tgt = (
|
||||
"HermiteE([0., 1.], domain=[-1, 1], window=[-1, 1], "
|
||||
"symbol='x')"
|
||||
)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test_laguerre_repr(self):
|
||||
res = repr(poly.Laguerre([0, 1]))
|
||||
tgt = (
|
||||
"Laguerre([0., 1.], domain=[0, 1], window=[0, 1], "
|
||||
"symbol='x')"
|
||||
)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
|
||||
class TestLatexRepr:
|
||||
"""Test the latex repr used by Jupyter"""
|
||||
|
||||
def as_latex(self, obj):
|
||||
# right now we ignore the formatting of scalars in our tests, since
|
||||
# it makes them too verbose. Ideally, the formatting of scalars will
|
||||
# be fixed such that tests below continue to pass
|
||||
obj._repr_latex_scalar = lambda x, parens=False: str(x)
|
||||
try:
|
||||
return obj._repr_latex_()
|
||||
finally:
|
||||
del obj._repr_latex_scalar
|
||||
|
||||
def test_simple_polynomial(self):
|
||||
# default input
|
||||
p = poly.Polynomial([1, 2, 3])
|
||||
assert_equal(self.as_latex(p),
|
||||
r'$x \mapsto 1.0 + 2.0\,x + 3.0\,x^{2}$')
|
||||
|
||||
# translated input
|
||||
p = poly.Polynomial([1, 2, 3], domain=[-2, 0])
|
||||
assert_equal(self.as_latex(p),
|
||||
r'$x \mapsto 1.0 + 2.0\,\left(1.0 + x\right) + 3.0\,\left(1.0 + x\right)^{2}$')
|
||||
|
||||
# scaled input
|
||||
p = poly.Polynomial([1, 2, 3], domain=[-0.5, 0.5])
|
||||
assert_equal(self.as_latex(p),
|
||||
r'$x \mapsto 1.0 + 2.0\,\left(2.0x\right) + 3.0\,\left(2.0x\right)^{2}$')
|
||||
|
||||
# affine input
|
||||
p = poly.Polynomial([1, 2, 3], domain=[-1, 0])
|
||||
assert_equal(self.as_latex(p),
|
||||
r'$x \mapsto 1.0 + 2.0\,\left(1.0 + 2.0x\right) + 3.0\,\left(1.0 + 2.0x\right)^{2}$')
|
||||
|
||||
def test_basis_func(self):
|
||||
p = poly.Chebyshev([1, 2, 3])
|
||||
assert_equal(self.as_latex(p),
|
||||
r'$x \mapsto 1.0\,{T}_{0}(x) + 2.0\,{T}_{1}(x) + 3.0\,{T}_{2}(x)$')
|
||||
# affine input - check no surplus parens are added
|
||||
p = poly.Chebyshev([1, 2, 3], domain=[-1, 0])
|
||||
assert_equal(self.as_latex(p),
|
||||
r'$x \mapsto 1.0\,{T}_{0}(1.0 + 2.0x) + 2.0\,{T}_{1}(1.0 + 2.0x) + 3.0\,{T}_{2}(1.0 + 2.0x)$')
|
||||
|
||||
def test_multichar_basis_func(self):
|
||||
p = poly.HermiteE([1, 2, 3])
|
||||
assert_equal(self.as_latex(p),
|
||||
r'$x \mapsto 1.0\,{He}_{0}(x) + 2.0\,{He}_{1}(x) + 3.0\,{He}_{2}(x)$')
|
||||
|
||||
def test_symbol_basic(self):
|
||||
# default input
|
||||
p = poly.Polynomial([1, 2, 3], symbol='z')
|
||||
assert_equal(self.as_latex(p),
|
||||
r'$z \mapsto 1.0 + 2.0\,z + 3.0\,z^{2}$')
|
||||
|
||||
# translated input
|
||||
p = poly.Polynomial([1, 2, 3], domain=[-2, 0], symbol='z')
|
||||
assert_equal(
|
||||
self.as_latex(p),
|
||||
(
|
||||
r'$z \mapsto 1.0 + 2.0\,\left(1.0 + z\right) + 3.0\,'
|
||||
r'\left(1.0 + z\right)^{2}$'
|
||||
),
|
||||
)
|
||||
|
||||
# scaled input
|
||||
p = poly.Polynomial([1, 2, 3], domain=[-0.5, 0.5], symbol='z')
|
||||
assert_equal(
|
||||
self.as_latex(p),
|
||||
(
|
||||
r'$z \mapsto 1.0 + 2.0\,\left(2.0z\right) + 3.0\,'
|
||||
r'\left(2.0z\right)^{2}$'
|
||||
),
|
||||
)
|
||||
|
||||
# affine input
|
||||
p = poly.Polynomial([1, 2, 3], domain=[-1, 0], symbol='z')
|
||||
assert_equal(
|
||||
self.as_latex(p),
|
||||
(
|
||||
r'$z \mapsto 1.0 + 2.0\,\left(1.0 + 2.0z\right) + 3.0\,'
|
||||
r'\left(1.0 + 2.0z\right)^{2}$'
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
SWITCH_TO_EXP = (
|
||||
'1.0 + (1.0e-01) x + (1.0e-02) x**2',
|
||||
'1.2 + (1.2e-01) x + (1.2e-02) x**2',
|
||||
'1.23 + 0.12 x + (1.23e-02) x**2 + (1.23e-03) x**3',
|
||||
'1.235 + 0.123 x + (1.235e-02) x**2 + (1.235e-03) x**3',
|
||||
'1.2346 + 0.1235 x + 0.0123 x**2 + (1.2346e-03) x**3 + (1.2346e-04) x**4',
|
||||
'1.23457 + 0.12346 x + 0.01235 x**2 + (1.23457e-03) x**3 + '
|
||||
'(1.23457e-04) x**4',
|
||||
'1.234568 + 0.123457 x + 0.012346 x**2 + 0.001235 x**3 + '
|
||||
'(1.234568e-04) x**4 + (1.234568e-05) x**5',
|
||||
'1.2345679 + 0.1234568 x + 0.0123457 x**2 + 0.0012346 x**3 + '
|
||||
'(1.2345679e-04) x**4 + (1.2345679e-05) x**5')
|
||||
|
||||
class TestPrintOptions:
|
||||
"""
|
||||
Test the output is properly configured via printoptions.
|
||||
The exponential notation is enabled automatically when the values
|
||||
are too small or too large.
|
||||
"""
|
||||
|
||||
@pytest.fixture(scope='class', autouse=True)
|
||||
def use_ascii(self):
|
||||
poly.set_default_printstyle('ascii')
|
||||
|
||||
def test_str(self):
|
||||
p = poly.Polynomial([1/2, 1/7, 1/7*10**8, 1/7*10**9])
|
||||
assert_equal(str(p), '0.5 + 0.14285714 x + 14285714.28571429 x**2 '
|
||||
'+ (1.42857143e+08) x**3')
|
||||
|
||||
with printoptions(precision=3):
|
||||
assert_equal(str(p), '0.5 + 0.143 x + 14285714.286 x**2 '
|
||||
'+ (1.429e+08) x**3')
|
||||
|
||||
def test_latex(self):
|
||||
p = poly.Polynomial([1/2, 1/7, 1/7*10**8, 1/7*10**9])
|
||||
assert_equal(p._repr_latex_(),
|
||||
r'$x \mapsto \text{0.5} + \text{0.14285714}\,x + '
|
||||
r'\text{14285714.28571429}\,x^{2} + '
|
||||
r'\text{(1.42857143e+08)}\,x^{3}$')
|
||||
|
||||
with printoptions(precision=3):
|
||||
assert_equal(p._repr_latex_(),
|
||||
r'$x \mapsto \text{0.5} + \text{0.143}\,x + '
|
||||
r'\text{14285714.286}\,x^{2} + \text{(1.429e+08)}\,x^{3}$')
|
||||
|
||||
def test_fixed(self):
|
||||
p = poly.Polynomial([1/2])
|
||||
assert_equal(str(p), '0.5')
|
||||
|
||||
with printoptions(floatmode='fixed'):
|
||||
assert_equal(str(p), '0.50000000')
|
||||
|
||||
with printoptions(floatmode='fixed', precision=4):
|
||||
assert_equal(str(p), '0.5000')
|
||||
|
||||
def test_switch_to_exp(self):
|
||||
for i, s in enumerate(SWITCH_TO_EXP):
|
||||
with printoptions(precision=i):
|
||||
p = poly.Polynomial([1.23456789*10**-i
|
||||
for i in range(i//2+3)])
|
||||
assert str(p).replace('\n', ' ') == s
|
||||
|
||||
def test_non_finite(self):
|
||||
p = poly.Polynomial([nan, inf])
|
||||
assert str(p) == 'nan + inf x'
|
||||
assert p._repr_latex_() == r'$x \mapsto \text{nan} + \text{inf}\,x$'
|
||||
with printoptions(nanstr='NAN', infstr='INF'):
|
||||
assert str(p) == 'NAN + INF x'
|
||||
assert p._repr_latex_() == \
|
||||
r'$x \mapsto \text{NAN} + \text{INF}\,x$'
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
"""
|
||||
Tests related to the ``symbol`` attribute of the ABCPolyBase class.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import numpy.polynomial as poly
|
||||
from numpy.core import array
|
||||
from numpy.testing import assert_equal, assert_raises, assert_
|
||||
|
||||
|
||||
class TestInit:
|
||||
"""
|
||||
Test polynomial creation with symbol kwarg.
|
||||
"""
|
||||
c = [1, 2, 3]
|
||||
|
||||
def test_default_symbol(self):
|
||||
p = poly.Polynomial(self.c)
|
||||
assert_equal(p.symbol, 'x')
|
||||
|
||||
@pytest.mark.parametrize(('bad_input', 'exception'), (
|
||||
('', ValueError),
|
||||
('3', ValueError),
|
||||
(None, TypeError),
|
||||
(1, TypeError),
|
||||
))
|
||||
def test_symbol_bad_input(self, bad_input, exception):
|
||||
with pytest.raises(exception):
|
||||
p = poly.Polynomial(self.c, symbol=bad_input)
|
||||
|
||||
@pytest.mark.parametrize('symbol', (
|
||||
'x',
|
||||
'x_1',
|
||||
'A',
|
||||
'xyz',
|
||||
'β',
|
||||
))
|
||||
def test_valid_symbols(self, symbol):
|
||||
"""
|
||||
Values for symbol that should pass input validation.
|
||||
"""
|
||||
p = poly.Polynomial(self.c, symbol=symbol)
|
||||
assert_equal(p.symbol, symbol)
|
||||
|
||||
def test_property(self):
|
||||
"""
|
||||
'symbol' attribute is read only.
|
||||
"""
|
||||
p = poly.Polynomial(self.c, symbol='x')
|
||||
with pytest.raises(AttributeError):
|
||||
p.symbol = 'z'
|
||||
|
||||
def test_change_symbol(self):
|
||||
p = poly.Polynomial(self.c, symbol='y')
|
||||
# Create new polynomial from p with different symbol
|
||||
pt = poly.Polynomial(p.coef, symbol='t')
|
||||
assert_equal(pt.symbol, 't')
|
||||
|
||||
|
||||
class TestUnaryOperators:
|
||||
p = poly.Polynomial([1, 2, 3], symbol='z')
|
||||
|
||||
def test_neg(self):
|
||||
n = -self.p
|
||||
assert_equal(n.symbol, 'z')
|
||||
|
||||
def test_scalarmul(self):
|
||||
out = self.p * 10
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_rscalarmul(self):
|
||||
out = 10 * self.p
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_pow(self):
|
||||
out = self.p ** 3
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'rhs',
|
||||
(
|
||||
poly.Polynomial([4, 5, 6], symbol='z'),
|
||||
array([4, 5, 6]),
|
||||
),
|
||||
)
|
||||
class TestBinaryOperatorsSameSymbol:
|
||||
"""
|
||||
Ensure symbol is preserved for numeric operations on polynomials with
|
||||
the same symbol
|
||||
"""
|
||||
p = poly.Polynomial([1, 2, 3], symbol='z')
|
||||
|
||||
def test_add(self, rhs):
|
||||
out = self.p + rhs
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_sub(self, rhs):
|
||||
out = self.p - rhs
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_polymul(self, rhs):
|
||||
out = self.p * rhs
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_divmod(self, rhs):
|
||||
for out in divmod(self.p, rhs):
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_radd(self, rhs):
|
||||
out = rhs + self.p
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_rsub(self, rhs):
|
||||
out = rhs - self.p
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_rmul(self, rhs):
|
||||
out = rhs * self.p
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
def test_rdivmod(self, rhs):
|
||||
for out in divmod(rhs, self.p):
|
||||
assert_equal(out.symbol, 'z')
|
||||
|
||||
|
||||
class TestBinaryOperatorsDifferentSymbol:
|
||||
p = poly.Polynomial([1, 2, 3], symbol='x')
|
||||
other = poly.Polynomial([4, 5, 6], symbol='y')
|
||||
ops = (p.__add__, p.__sub__, p.__mul__, p.__floordiv__, p.__mod__)
|
||||
|
||||
@pytest.mark.parametrize('f', ops)
|
||||
def test_binops_fails(self, f):
|
||||
assert_raises(ValueError, f, self.other)
|
||||
|
||||
|
||||
class TestEquality:
|
||||
p = poly.Polynomial([1, 2, 3], symbol='x')
|
||||
|
||||
def test_eq(self):
|
||||
other = poly.Polynomial([1, 2, 3], symbol='x')
|
||||
assert_(self.p == other)
|
||||
|
||||
def test_neq(self):
|
||||
other = poly.Polynomial([1, 2, 3], symbol='y')
|
||||
assert_(not self.p == other)
|
||||
|
||||
|
||||
class TestExtraMethods:
|
||||
"""
|
||||
Test other methods for manipulating/creating polynomial objects.
|
||||
"""
|
||||
p = poly.Polynomial([1, 2, 3, 0], symbol='z')
|
||||
|
||||
def test_copy(self):
|
||||
other = self.p.copy()
|
||||
assert_equal(other.symbol, 'z')
|
||||
|
||||
def test_trim(self):
|
||||
other = self.p.trim()
|
||||
assert_equal(other.symbol, 'z')
|
||||
|
||||
def test_truncate(self):
|
||||
other = self.p.truncate(2)
|
||||
assert_equal(other.symbol, 'z')
|
||||
|
||||
@pytest.mark.parametrize('kwarg', (
|
||||
{'domain': [-10, 10]},
|
||||
{'window': [-10, 10]},
|
||||
{'kind': poly.Chebyshev},
|
||||
))
|
||||
def test_convert(self, kwarg):
|
||||
other = self.p.convert(**kwarg)
|
||||
assert_equal(other.symbol, 'z')
|
||||
|
||||
def test_integ(self):
|
||||
other = self.p.integ()
|
||||
assert_equal(other.symbol, 'z')
|
||||
|
||||
def test_deriv(self):
|
||||
other = self.p.deriv()
|
||||
assert_equal(other.symbol, 'z')
|
||||
|
||||
|
||||
def test_composition():
|
||||
p = poly.Polynomial([3, 2, 1], symbol="t")
|
||||
q = poly.Polynomial([5, 1, 0, -1], symbol="λ_1")
|
||||
r = p(q)
|
||||
assert r.symbol == "λ_1"
|
||||
|
||||
|
||||
#
|
||||
# Class methods that result in new polynomial class instances
|
||||
#
|
||||
|
||||
|
||||
def test_fit():
|
||||
x, y = (range(10),)*2
|
||||
p = poly.Polynomial.fit(x, y, deg=1, symbol='z')
|
||||
assert_equal(p.symbol, 'z')
|
||||
|
||||
|
||||
def test_froomroots():
|
||||
roots = [-2, 2]
|
||||
p = poly.Polynomial.fromroots(roots, symbol='z')
|
||||
assert_equal(p.symbol, 'z')
|
||||
|
||||
|
||||
def test_identity():
|
||||
p = poly.Polynomial.identity(domain=[-1, 1], window=[5, 20], symbol='z')
|
||||
assert_equal(p.symbol, 'z')
|
||||
|
||||
|
||||
def test_basis():
|
||||
p = poly.Polynomial.basis(3, symbol='z')
|
||||
assert_equal(p.symbol, 'z')
|
||||
Loading…
Add table
Add a link
Reference in a new issue