Updated script that can be controled by Nodejs web app
This commit is contained in:
187
lib/python3.13/site-packages/numpy/polynomial/__init__.py
Normal file
187
lib/python3.13/site-packages/numpy/polynomial/__init__.py
Normal file
@ -0,0 +1,187 @@
|
||||
"""
|
||||
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
|
||||
>>> xdata = [1, 2, 3, 4]
|
||||
>>> ydata = [1, 4, 9, 16]
|
||||
>>> 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
|
23
lib/python3.13/site-packages/numpy/polynomial/__init__.pyi
Normal file
23
lib/python3.13/site-packages/numpy/polynomial/__init__.pyi
Normal file
@ -0,0 +1,23 @@
|
||||
from typing import Final, Literal
|
||||
|
||||
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: Literal["ascii", "unicode"]) -> None: ...
|
||||
|
||||
from numpy._pytesttester import PytestTester as _PytestTester
|
||||
test: Final[_PytestTester]
|
1223
lib/python3.13/site-packages/numpy/polynomial/_polybase.py
Normal file
1223
lib/python3.13/site-packages/numpy/polynomial/_polybase.py
Normal file
File diff suppressed because it is too large
Load Diff
297
lib/python3.13/site-packages/numpy/polynomial/_polybase.pyi
Normal file
297
lib/python3.13/site-packages/numpy/polynomial/_polybase.pyi
Normal file
@ -0,0 +1,297 @@
|
||||
import abc
|
||||
import decimal
|
||||
import numbers
|
||||
import sys
|
||||
from collections.abc import Iterator, Mapping, Sequence
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
ClassVar,
|
||||
Final,
|
||||
Generic,
|
||||
Literal,
|
||||
SupportsIndex,
|
||||
TypeAlias,
|
||||
TypeGuard,
|
||||
TypeVar,
|
||||
overload,
|
||||
)
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
from numpy._typing import (
|
||||
_FloatLike_co,
|
||||
_NumberLike_co,
|
||||
|
||||
_ArrayLikeFloat_co,
|
||||
_ArrayLikeComplex_co,
|
||||
)
|
||||
|
||||
from ._polytypes import (
|
||||
_AnyInt,
|
||||
_CoefLike_co,
|
||||
|
||||
_Array2,
|
||||
_Tuple2,
|
||||
|
||||
_Series,
|
||||
_CoefSeries,
|
||||
|
||||
_SeriesLikeInt_co,
|
||||
_SeriesLikeCoef_co,
|
||||
|
||||
_ArrayLikeCoefObject_co,
|
||||
_ArrayLikeCoef_co,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from typing import LiteralString
|
||||
elif TYPE_CHECKING:
|
||||
from typing_extensions import LiteralString
|
||||
else:
|
||||
LiteralString: TypeAlias = str
|
||||
|
||||
|
||||
__all__: Final[Sequence[str]] = ("ABCPolyBase",)
|
||||
|
||||
|
||||
_NameCo = TypeVar("_NameCo", bound=None | LiteralString, covariant=True)
|
||||
_Self = TypeVar("_Self", bound="ABCPolyBase")
|
||||
_Other = TypeVar("_Other", bound="ABCPolyBase")
|
||||
|
||||
_AnyOther: TypeAlias = ABCPolyBase | _CoefLike_co | _SeriesLikeCoef_co
|
||||
_Hundred: TypeAlias = Literal[100]
|
||||
|
||||
|
||||
class ABCPolyBase(Generic[_NameCo], metaclass=abc.ABCMeta):
|
||||
__hash__: ClassVar[None] # type: ignore[assignment]
|
||||
__array_ufunc__: ClassVar[None]
|
||||
|
||||
maxpower: ClassVar[_Hundred]
|
||||
_superscript_mapping: ClassVar[Mapping[int, str]]
|
||||
_subscript_mapping: ClassVar[Mapping[int, str]]
|
||||
_use_unicode: ClassVar[bool]
|
||||
|
||||
basis_name: _NameCo
|
||||
coef: _CoefSeries
|
||||
domain: _Array2[np.inexact[Any] | np.object_]
|
||||
window: _Array2[np.inexact[Any] | np.object_]
|
||||
|
||||
_symbol: LiteralString
|
||||
@property
|
||||
def symbol(self, /) -> LiteralString: ...
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
/,
|
||||
coef: _SeriesLikeCoef_co,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
symbol: str = ...,
|
||||
) -> None: ...
|
||||
|
||||
@overload
|
||||
def __call__(self, /, arg: _Other) -> _Other: ...
|
||||
# TODO: Once `_ShapeType@ndarray` is covariant and bounded (see #26081),
|
||||
# additionally include 0-d arrays as input types with scalar return type.
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
arg: _FloatLike_co | decimal.Decimal | numbers.Real | np.object_,
|
||||
) -> np.float64 | np.complex128: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
arg: _NumberLike_co | numbers.Complex,
|
||||
) -> np.complex128: ...
|
||||
@overload
|
||||
def __call__(self, /, arg: _ArrayLikeFloat_co) -> (
|
||||
npt.NDArray[np.float64]
|
||||
| npt.NDArray[np.complex128]
|
||||
| npt.NDArray[np.object_]
|
||||
): ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
arg: _ArrayLikeComplex_co,
|
||||
) -> npt.NDArray[np.complex128] | npt.NDArray[np.object_]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
arg: _ArrayLikeCoefObject_co,
|
||||
) -> npt.NDArray[np.object_]: ...
|
||||
|
||||
def __str__(self, /) -> str: ...
|
||||
def __repr__(self, /) -> str: ...
|
||||
def __format__(self, fmt_str: str, /) -> str: ...
|
||||
def __eq__(self, x: object, /) -> bool: ...
|
||||
def __ne__(self, x: object, /) -> bool: ...
|
||||
def __neg__(self: _Self, /) -> _Self: ...
|
||||
def __pos__(self: _Self, /) -> _Self: ...
|
||||
def __add__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __sub__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __mul__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __truediv__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __floordiv__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __mod__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __divmod__(self: _Self, x: _AnyOther, /) -> _Tuple2[_Self]: ...
|
||||
def __pow__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __radd__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __rsub__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __rmul__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __rtruediv__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __rfloordiv__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __rmod__(self: _Self, x: _AnyOther, /) -> _Self: ...
|
||||
def __rdivmod__(self: _Self, x: _AnyOther, /) -> _Tuple2[_Self]: ...
|
||||
def __len__(self, /) -> int: ...
|
||||
def __iter__(self, /) -> Iterator[np.inexact[Any] | object]: ...
|
||||
def __getstate__(self, /) -> dict[str, Any]: ...
|
||||
def __setstate__(self, dict: dict[str, Any], /) -> None: ...
|
||||
|
||||
def has_samecoef(self, /, other: ABCPolyBase) -> bool: ...
|
||||
def has_samedomain(self, /, other: ABCPolyBase) -> bool: ...
|
||||
def has_samewindow(self, /, other: ABCPolyBase) -> bool: ...
|
||||
@overload
|
||||
def has_sametype(self: _Self, /, other: ABCPolyBase) -> TypeGuard[_Self]: ...
|
||||
@overload
|
||||
def has_sametype(self, /, other: object) -> Literal[False]: ...
|
||||
|
||||
def copy(self: _Self, /) -> _Self: ...
|
||||
def degree(self, /) -> int: ...
|
||||
def cutdeg(self: _Self, /) -> _Self: ...
|
||||
def trim(self: _Self, /, tol: _FloatLike_co = ...) -> _Self: ...
|
||||
def truncate(self: _Self, /, size: _AnyInt) -> _Self: ...
|
||||
|
||||
@overload
|
||||
def convert(
|
||||
self,
|
||||
domain: None | _SeriesLikeCoef_co,
|
||||
kind: type[_Other],
|
||||
/,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
) -> _Other: ...
|
||||
@overload
|
||||
def convert(
|
||||
self,
|
||||
/,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
*,
|
||||
kind: type[_Other],
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
) -> _Other: ...
|
||||
@overload
|
||||
def convert(
|
||||
self: _Self,
|
||||
/,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
kind: type[_Self] = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
) -> _Self: ...
|
||||
|
||||
def mapparms(self, /) -> _Tuple2[Any]: ...
|
||||
|
||||
def integ(
|
||||
self: _Self, /,
|
||||
m: SupportsIndex = ...,
|
||||
k: _CoefLike_co | _SeriesLikeCoef_co = ...,
|
||||
lbnd: None | _CoefLike_co = ...,
|
||||
) -> _Self: ...
|
||||
|
||||
def deriv(self: _Self, /, m: SupportsIndex = ...) -> _Self: ...
|
||||
|
||||
def roots(self, /) -> _CoefSeries: ...
|
||||
|
||||
def linspace(
|
||||
self, /,
|
||||
n: SupportsIndex = ...,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
) -> _Tuple2[_Series[np.float64 | np.complex128]]: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
def fit(
|
||||
cls: type[_Self], /,
|
||||
x: _SeriesLikeCoef_co,
|
||||
y: _SeriesLikeCoef_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
rcond: _FloatLike_co = ...,
|
||||
full: Literal[False] = ...,
|
||||
w: None | _SeriesLikeCoef_co = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
symbol: str = ...,
|
||||
) -> _Self: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def fit(
|
||||
cls: type[_Self], /,
|
||||
x: _SeriesLikeCoef_co,
|
||||
y: _SeriesLikeCoef_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
rcond: _FloatLike_co = ...,
|
||||
*,
|
||||
full: Literal[True],
|
||||
w: None | _SeriesLikeCoef_co = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
symbol: str = ...,
|
||||
) -> tuple[_Self, Sequence[np.inexact[Any] | np.int32]]: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def fit(
|
||||
cls: type[_Self],
|
||||
x: _SeriesLikeCoef_co,
|
||||
y: _SeriesLikeCoef_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
domain: None | _SeriesLikeCoef_co,
|
||||
rcond: _FloatLike_co,
|
||||
full: Literal[True], /,
|
||||
w: None | _SeriesLikeCoef_co = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
symbol: str = ...,
|
||||
) -> tuple[_Self, Sequence[np.inexact[Any] | np.int32]]: ...
|
||||
|
||||
@classmethod
|
||||
def fromroots(
|
||||
cls: type[_Self], /,
|
||||
roots: _ArrayLikeCoef_co,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
symbol: str = ...,
|
||||
) -> _Self: ...
|
||||
|
||||
@classmethod
|
||||
def identity(
|
||||
cls: type[_Self], /,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
symbol: str = ...,
|
||||
) -> _Self: ...
|
||||
|
||||
@classmethod
|
||||
def basis(
|
||||
cls: type[_Self], /,
|
||||
deg: _AnyInt,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
symbol: str = ...,
|
||||
) -> _Self: ...
|
||||
|
||||
@classmethod
|
||||
def cast(
|
||||
cls: type[_Self], /,
|
||||
series: ABCPolyBase,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
window: None | _SeriesLikeCoef_co = ...,
|
||||
) -> _Self: ...
|
||||
|
||||
@classmethod
|
||||
def _str_term_unicode(cls, i: str, arg_str: str) -> str: ...
|
||||
@staticmethod
|
||||
def _str_term_ascii(i: str, arg_str: str) -> str: ...
|
||||
@staticmethod
|
||||
def _repr_latex_term(i: str, arg_str: str, needs_parens: bool) -> str: ...
|
912
lib/python3.13/site-packages/numpy/polynomial/_polytypes.pyi
Normal file
912
lib/python3.13/site-packages/numpy/polynomial/_polytypes.pyi
Normal file
@ -0,0 +1,912 @@
|
||||
import sys
|
||||
from collections.abc import Callable, Sequence
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Literal,
|
||||
NoReturn,
|
||||
Protocol,
|
||||
SupportsIndex,
|
||||
SupportsInt,
|
||||
TypeAlias,
|
||||
TypeVar,
|
||||
final,
|
||||
overload,
|
||||
)
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
from numpy._typing import (
|
||||
# array-likes
|
||||
_ArrayLikeFloat_co,
|
||||
_ArrayLikeComplex_co,
|
||||
_ArrayLikeNumber_co,
|
||||
_ArrayLikeObject_co,
|
||||
_NestedSequence,
|
||||
|
||||
# scalar-likes
|
||||
_IntLike_co,
|
||||
_FloatLike_co,
|
||||
_ComplexLike_co,
|
||||
_NumberLike_co,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from typing import LiteralString
|
||||
elif TYPE_CHECKING:
|
||||
from typing_extensions import LiteralString
|
||||
else:
|
||||
LiteralString: TypeAlias = str
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_T_contra = TypeVar("_T_contra", contravariant=True)
|
||||
|
||||
_Tuple2: TypeAlias = tuple[_T, _T]
|
||||
|
||||
_V = TypeVar("_V")
|
||||
_V_co = TypeVar("_V_co", covariant=True)
|
||||
_Self = TypeVar("_Self", bound=object)
|
||||
|
||||
_SCT = TypeVar("_SCT", bound=np.number[Any] | np.bool | np.object_)
|
||||
_SCT_co = TypeVar(
|
||||
"_SCT_co",
|
||||
bound=np.number[Any] | np.bool | np.object_,
|
||||
covariant=True,
|
||||
)
|
||||
|
||||
@final
|
||||
class _SupportsArray(Protocol[_SCT_co]):
|
||||
def __array__(self ,) -> npt.NDArray[_SCT_co]: ...
|
||||
|
||||
@final
|
||||
class _SupportsCoefOps(Protocol[_T_contra]):
|
||||
# compatible with e.g. `int`, `float`, `complex`, `Decimal`, `Fraction`,
|
||||
# and `ABCPolyBase`
|
||||
def __eq__(self, x: object, /) -> bool: ...
|
||||
def __ne__(self, x: object, /) -> bool: ...
|
||||
|
||||
def __neg__(self: _Self, /) -> _Self: ...
|
||||
def __pos__(self: _Self, /) -> _Self: ...
|
||||
|
||||
def __add__(self: _Self, x: _T_contra, /) -> _Self: ...
|
||||
def __sub__(self: _Self, x: _T_contra, /) -> _Self: ...
|
||||
def __mul__(self: _Self, x: _T_contra, /) -> _Self: ...
|
||||
def __truediv__(self: _Self, x: _T_contra, /) -> _Self | float: ...
|
||||
def __pow__(self: _Self, x: _T_contra, /) -> _Self | float: ...
|
||||
|
||||
def __radd__(self: _Self, x: _T_contra, /) -> _Self: ...
|
||||
def __rsub__(self: _Self, x: _T_contra, /) -> _Self: ...
|
||||
def __rmul__(self: _Self, x: _T_contra, /) -> _Self: ...
|
||||
def __rtruediv__(self: _Self, x: _T_contra, /) -> _Self | float: ...
|
||||
|
||||
_Series: TypeAlias = np.ndarray[tuple[int], np.dtype[_SCT]]
|
||||
|
||||
_FloatSeries: TypeAlias = _Series[np.floating[Any]]
|
||||
_ComplexSeries: TypeAlias = _Series[np.complexfloating[Any, Any]]
|
||||
_NumberSeries: TypeAlias = _Series[np.number[Any]]
|
||||
_ObjectSeries: TypeAlias = _Series[np.object_]
|
||||
_CoefSeries: TypeAlias = _Series[np.inexact[Any] | np.object_]
|
||||
|
||||
_FloatArray: TypeAlias = npt.NDArray[np.floating[Any]]
|
||||
_ComplexArray: TypeAlias = npt.NDArray[np.complexfloating[Any, Any]]
|
||||
_ObjectArray: TypeAlias = npt.NDArray[np.object_]
|
||||
_CoefArray: TypeAlias = npt.NDArray[np.inexact[Any] | np.object_]
|
||||
|
||||
_Array1: TypeAlias = np.ndarray[tuple[Literal[1]], np.dtype[_SCT]]
|
||||
_Array2: TypeAlias = np.ndarray[tuple[Literal[2]], np.dtype[_SCT]]
|
||||
|
||||
_AnyInt: TypeAlias = SupportsInt | SupportsIndex
|
||||
|
||||
_CoefObjectLike_co: TypeAlias = np.object_ | _SupportsCoefOps
|
||||
_CoefLike_co: TypeAlias = _NumberLike_co | _CoefObjectLike_co
|
||||
|
||||
# The term "series" is used here to refer to 1-d arrays of numeric scalars.
|
||||
_SeriesLikeBool_co: TypeAlias = (
|
||||
_SupportsArray[np.bool]
|
||||
| Sequence[bool | np.bool]
|
||||
)
|
||||
_SeriesLikeInt_co: TypeAlias = (
|
||||
_SupportsArray[np.integer[Any] | np.bool]
|
||||
| Sequence[_IntLike_co]
|
||||
)
|
||||
_SeriesLikeFloat_co: TypeAlias = (
|
||||
_SupportsArray[np.floating[Any] | np.integer[Any] | np.bool]
|
||||
| Sequence[_FloatLike_co]
|
||||
)
|
||||
_SeriesLikeComplex_co: TypeAlias = (
|
||||
_SupportsArray[np.integer[Any] | np.inexact[Any] | np.bool]
|
||||
| Sequence[_ComplexLike_co]
|
||||
)
|
||||
_SeriesLikeObject_co: TypeAlias = (
|
||||
_SupportsArray[np.object_]
|
||||
| Sequence[_CoefObjectLike_co]
|
||||
)
|
||||
_SeriesLikeCoef_co: TypeAlias = (
|
||||
# npt.NDArray[np.number[Any] | np.bool | np.object_]
|
||||
_SupportsArray[np.number[Any] | np.bool | np.object_]
|
||||
| Sequence[_CoefLike_co]
|
||||
)
|
||||
|
||||
_ArrayLikeCoefObject_co: TypeAlias = (
|
||||
_CoefObjectLike_co
|
||||
| _SeriesLikeObject_co
|
||||
| _NestedSequence[_SeriesLikeObject_co]
|
||||
)
|
||||
_ArrayLikeCoef_co: TypeAlias = (
|
||||
npt.NDArray[np.number[Any] | np.bool | np.object_]
|
||||
| _ArrayLikeNumber_co
|
||||
| _ArrayLikeCoefObject_co
|
||||
)
|
||||
|
||||
_Name_co = TypeVar("_Name_co", bound=LiteralString, covariant=True)
|
||||
|
||||
class _Named(Protocol[_Name_co]):
|
||||
@property
|
||||
def __name__(self, /) -> _Name_co: ...
|
||||
|
||||
_Line: TypeAlias = np.ndarray[tuple[Literal[1, 2]], np.dtype[_SCT]]
|
||||
|
||||
@final
|
||||
class _FuncLine(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(self, /, off: _SCT, scl: _SCT) -> _Line[_SCT]: ...
|
||||
@overload
|
||||
def __call__(self, /, off: int, scl: int) -> _Line[np.int_] : ...
|
||||
@overload
|
||||
def __call__(self, /, off: float, scl: float) -> _Line[np.float64]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
off: complex,
|
||||
scl: complex,
|
||||
) -> _Line[np.complex128]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
off: _SupportsCoefOps,
|
||||
scl: _SupportsCoefOps,
|
||||
) -> _Line[np.object_]: ...
|
||||
|
||||
@final
|
||||
class _FuncFromRoots(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(self, /, roots: _SeriesLikeFloat_co) -> _FloatSeries: ...
|
||||
@overload
|
||||
def __call__(self, /, roots: _SeriesLikeComplex_co) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def __call__(self, /, roots: _SeriesLikeCoef_co) -> _ObjectSeries: ...
|
||||
|
||||
@final
|
||||
class _FuncBinOp(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c1: _SeriesLikeBool_co,
|
||||
c2: _SeriesLikeBool_co,
|
||||
) -> NoReturn: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c1: _SeriesLikeFloat_co,
|
||||
c2: _SeriesLikeFloat_co,
|
||||
) -> _FloatSeries: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c1: _SeriesLikeComplex_co,
|
||||
c2: _SeriesLikeComplex_co,
|
||||
) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c1: _SeriesLikeCoef_co,
|
||||
c2: _SeriesLikeCoef_co,
|
||||
) -> _ObjectSeries: ...
|
||||
|
||||
@final
|
||||
class _FuncUnOp(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(self, /, c: _SeriesLikeFloat_co) -> _FloatSeries: ...
|
||||
@overload
|
||||
def __call__(self, /, c: _SeriesLikeComplex_co) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def __call__(self, /, c: _SeriesLikeCoef_co) -> _ObjectSeries: ...
|
||||
|
||||
@final
|
||||
class _FuncPoly2Ortho(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(self, /, pol: _SeriesLikeFloat_co) -> _FloatSeries: ...
|
||||
@overload
|
||||
def __call__(self, /, pol: _SeriesLikeComplex_co) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def __call__(self, /, pol: _SeriesLikeCoef_co) -> _ObjectSeries: ...
|
||||
|
||||
@final
|
||||
class _FuncPow(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _SeriesLikeFloat_co,
|
||||
pow: _IntLike_co,
|
||||
maxpower: None | _IntLike_co = ...,
|
||||
) -> _FloatSeries: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _SeriesLikeComplex_co,
|
||||
pow: _IntLike_co,
|
||||
maxpower: None | _IntLike_co = ...,
|
||||
) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _SeriesLikeCoef_co,
|
||||
pow: _IntLike_co,
|
||||
maxpower: None | _IntLike_co = ...,
|
||||
) -> _ObjectSeries: ...
|
||||
|
||||
@final
|
||||
class _FuncDer(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _ArrayLikeFloat_co,
|
||||
m: SupportsIndex = ...,
|
||||
scl: _FloatLike_co = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _ArrayLikeComplex_co,
|
||||
m: SupportsIndex = ...,
|
||||
scl: _ComplexLike_co = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _ArrayLikeCoef_co,
|
||||
m: SupportsIndex = ...,
|
||||
scl: _CoefLike_co = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> _ObjectArray: ...
|
||||
|
||||
@final
|
||||
class _FuncInteg(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _ArrayLikeFloat_co,
|
||||
m: SupportsIndex = ...,
|
||||
k: _FloatLike_co | _SeriesLikeFloat_co = ...,
|
||||
lbnd: _FloatLike_co = ...,
|
||||
scl: _FloatLike_co = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _ArrayLikeComplex_co,
|
||||
m: SupportsIndex = ...,
|
||||
k: _ComplexLike_co | _SeriesLikeComplex_co = ...,
|
||||
lbnd: _ComplexLike_co = ...,
|
||||
scl: _ComplexLike_co = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _ArrayLikeCoef_co,
|
||||
m: SupportsIndex = ...,
|
||||
k: _SeriesLikeCoef_co | _SeriesLikeCoef_co = ...,
|
||||
lbnd: _CoefLike_co = ...,
|
||||
scl: _CoefLike_co = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> _ObjectArray: ...
|
||||
|
||||
@final
|
||||
class _FuncValFromRoots(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _FloatLike_co,
|
||||
r: _FloatLike_co,
|
||||
tensor: bool = ...,
|
||||
) -> np.floating[Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _NumberLike_co,
|
||||
r: _NumberLike_co,
|
||||
tensor: bool = ...,
|
||||
) -> np.complexfloating[Any, Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _FloatLike_co | _ArrayLikeFloat_co,
|
||||
r: _ArrayLikeFloat_co,
|
||||
tensor: bool = ...,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _NumberLike_co | _ArrayLikeComplex_co,
|
||||
r: _ArrayLikeComplex_co,
|
||||
tensor: bool = ...,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _CoefLike_co | _ArrayLikeCoef_co,
|
||||
r: _ArrayLikeCoef_co,
|
||||
tensor: bool = ...,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _CoefLike_co,
|
||||
r: _CoefLike_co,
|
||||
tensor: bool = ...,
|
||||
) -> _SupportsCoefOps: ...
|
||||
|
||||
@final
|
||||
class _FuncVal(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _FloatLike_co,
|
||||
c: _SeriesLikeFloat_co,
|
||||
tensor: bool = ...,
|
||||
) -> np.floating[Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _NumberLike_co,
|
||||
c: _SeriesLikeComplex_co,
|
||||
tensor: bool = ...,
|
||||
) -> np.complexfloating[Any, Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeFloat_co,
|
||||
c: _ArrayLikeFloat_co,
|
||||
tensor: bool = ...,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeComplex_co,
|
||||
c: _ArrayLikeComplex_co,
|
||||
tensor: bool = ...,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeCoef_co,
|
||||
c: _ArrayLikeCoef_co,
|
||||
tensor: bool = ...,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _CoefLike_co,
|
||||
c: _SeriesLikeObject_co,
|
||||
tensor: bool = ...,
|
||||
) -> _SupportsCoefOps: ...
|
||||
|
||||
@final
|
||||
class _FuncVal2D(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _FloatLike_co,
|
||||
y: _FloatLike_co,
|
||||
c: _SeriesLikeFloat_co,
|
||||
) -> np.floating[Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _NumberLike_co,
|
||||
y: _NumberLike_co,
|
||||
c: _SeriesLikeComplex_co,
|
||||
) -> np.complexfloating[Any, Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeFloat_co,
|
||||
y: _ArrayLikeFloat_co,
|
||||
c: _ArrayLikeFloat_co,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeComplex_co,
|
||||
y: _ArrayLikeComplex_co,
|
||||
c: _ArrayLikeComplex_co,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeCoef_co,
|
||||
y: _ArrayLikeCoef_co,
|
||||
c: _ArrayLikeCoef_co,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _CoefLike_co,
|
||||
y: _CoefLike_co,
|
||||
c: _SeriesLikeCoef_co,
|
||||
) -> _SupportsCoefOps: ...
|
||||
|
||||
@final
|
||||
class _FuncVal3D(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _FloatLike_co,
|
||||
y: _FloatLike_co,
|
||||
z: _FloatLike_co,
|
||||
c: _SeriesLikeFloat_co
|
||||
) -> np.floating[Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _NumberLike_co,
|
||||
y: _NumberLike_co,
|
||||
z: _NumberLike_co,
|
||||
c: _SeriesLikeComplex_co,
|
||||
) -> np.complexfloating[Any, Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeFloat_co,
|
||||
y: _ArrayLikeFloat_co,
|
||||
z: _ArrayLikeFloat_co,
|
||||
c: _ArrayLikeFloat_co,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeComplex_co,
|
||||
y: _ArrayLikeComplex_co,
|
||||
z: _ArrayLikeComplex_co,
|
||||
c: _ArrayLikeComplex_co,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeCoef_co,
|
||||
y: _ArrayLikeCoef_co,
|
||||
z: _ArrayLikeCoef_co,
|
||||
c: _ArrayLikeCoef_co,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _CoefLike_co,
|
||||
y: _CoefLike_co,
|
||||
z: _CoefLike_co,
|
||||
c: _SeriesLikeCoef_co,
|
||||
) -> _SupportsCoefOps: ...
|
||||
|
||||
_AnyValF: TypeAlias = Callable[
|
||||
[npt.ArrayLike, npt.ArrayLike, bool],
|
||||
_CoefArray,
|
||||
]
|
||||
|
||||
@final
|
||||
class _FuncValND(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
val_f: _AnyValF,
|
||||
c: _SeriesLikeFloat_co,
|
||||
/,
|
||||
*args: _FloatLike_co,
|
||||
) -> np.floating[Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
val_f: _AnyValF,
|
||||
c: _SeriesLikeComplex_co,
|
||||
/,
|
||||
*args: _NumberLike_co,
|
||||
) -> np.complexfloating[Any, Any]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
val_f: _AnyValF,
|
||||
c: _ArrayLikeFloat_co,
|
||||
/,
|
||||
*args: _ArrayLikeFloat_co,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
val_f: _AnyValF,
|
||||
c: _ArrayLikeComplex_co,
|
||||
/,
|
||||
*args: _ArrayLikeComplex_co,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
val_f: _AnyValF,
|
||||
c: _ArrayLikeCoef_co,
|
||||
/,
|
||||
*args: _ArrayLikeCoef_co,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
val_f: _AnyValF,
|
||||
c: _SeriesLikeObject_co,
|
||||
/,
|
||||
*args: _CoefObjectLike_co,
|
||||
) -> _SupportsCoefOps: ...
|
||||
|
||||
@final
|
||||
class _FuncVander(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeFloat_co,
|
||||
deg: SupportsIndex,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeComplex_co,
|
||||
deg: SupportsIndex,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeCoef_co,
|
||||
deg: SupportsIndex,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: npt.ArrayLike,
|
||||
deg: SupportsIndex,
|
||||
) -> _CoefArray: ...
|
||||
|
||||
_AnyDegrees: TypeAlias = Sequence[SupportsIndex]
|
||||
|
||||
@final
|
||||
class _FuncVander2D(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeFloat_co,
|
||||
y: _ArrayLikeFloat_co,
|
||||
deg: _AnyDegrees,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeComplex_co,
|
||||
y: _ArrayLikeComplex_co,
|
||||
deg: _AnyDegrees,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeCoef_co,
|
||||
y: _ArrayLikeCoef_co,
|
||||
deg: _AnyDegrees,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: npt.ArrayLike,
|
||||
y: npt.ArrayLike,
|
||||
deg: _AnyDegrees,
|
||||
) -> _CoefArray: ...
|
||||
|
||||
@final
|
||||
class _FuncVander3D(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeFloat_co,
|
||||
y: _ArrayLikeFloat_co,
|
||||
z: _ArrayLikeFloat_co,
|
||||
deg: _AnyDegrees,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeComplex_co,
|
||||
y: _ArrayLikeComplex_co,
|
||||
z: _ArrayLikeComplex_co,
|
||||
deg: _AnyDegrees,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _ArrayLikeCoef_co,
|
||||
y: _ArrayLikeCoef_co,
|
||||
z: _ArrayLikeCoef_co,
|
||||
deg: _AnyDegrees,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: npt.ArrayLike,
|
||||
y: npt.ArrayLike,
|
||||
z: npt.ArrayLike,
|
||||
deg: _AnyDegrees,
|
||||
) -> _CoefArray: ...
|
||||
|
||||
# keep in sync with the broadest overload of `._FuncVander`
|
||||
_AnyFuncVander: TypeAlias = Callable[
|
||||
[npt.ArrayLike, SupportsIndex],
|
||||
_CoefArray,
|
||||
]
|
||||
|
||||
@final
|
||||
class _FuncVanderND(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
vander_fs: Sequence[_AnyFuncVander],
|
||||
points: Sequence[_ArrayLikeFloat_co],
|
||||
degrees: Sequence[SupportsIndex],
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
vander_fs: Sequence[_AnyFuncVander],
|
||||
points: Sequence[_ArrayLikeComplex_co],
|
||||
degrees: Sequence[SupportsIndex],
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
vander_fs: Sequence[_AnyFuncVander],
|
||||
points: Sequence[
|
||||
_ArrayLikeObject_co | _ArrayLikeComplex_co,
|
||||
],
|
||||
degrees: Sequence[SupportsIndex],
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
vander_fs: Sequence[_AnyFuncVander],
|
||||
points: Sequence[npt.ArrayLike],
|
||||
degrees: Sequence[SupportsIndex],
|
||||
) -> _CoefArray: ...
|
||||
|
||||
_FullFitResult: TypeAlias = Sequence[np.inexact[Any] | np.int32]
|
||||
|
||||
@final
|
||||
class _FuncFit(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _SeriesLikeFloat_co,
|
||||
y: _ArrayLikeFloat_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float = ...,
|
||||
full: Literal[False] = ...,
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
x: _SeriesLikeFloat_co,
|
||||
y: _ArrayLikeFloat_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float,
|
||||
full: Literal[True],
|
||||
/,
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> tuple[_FloatArray, _FullFitResult]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _SeriesLikeFloat_co,
|
||||
y: _ArrayLikeFloat_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float = ...,
|
||||
*,
|
||||
full: Literal[True],
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> tuple[_FloatArray, _FullFitResult]: ...
|
||||
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _SeriesLikeComplex_co,
|
||||
y: _ArrayLikeComplex_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float = ...,
|
||||
full: Literal[False] = ...,
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
x: _SeriesLikeComplex_co,
|
||||
y: _ArrayLikeComplex_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float,
|
||||
full: Literal[True],
|
||||
/,
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> tuple[_ComplexArray, _FullFitResult]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _SeriesLikeComplex_co,
|
||||
y: _ArrayLikeComplex_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float = ...,
|
||||
*,
|
||||
full: Literal[True],
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> tuple[_ComplexArray, _FullFitResult]: ...
|
||||
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _SeriesLikeComplex_co,
|
||||
y: _ArrayLikeCoef_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float = ...,
|
||||
full: Literal[False] = ...,
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> _ObjectArray: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
x: _SeriesLikeComplex_co,
|
||||
y: _ArrayLikeCoef_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float,
|
||||
full: Literal[True],
|
||||
/,
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> tuple[_ObjectArray, _FullFitResult]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
x: _SeriesLikeComplex_co,
|
||||
y: _ArrayLikeCoef_co,
|
||||
deg: int | _SeriesLikeInt_co,
|
||||
rcond: None | float = ...,
|
||||
*,
|
||||
full: Literal[True],
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> tuple[_ObjectArray, _FullFitResult]: ...
|
||||
|
||||
@final
|
||||
class _FuncRoots(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _SeriesLikeFloat_co,
|
||||
) -> _Series[np.float64]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _SeriesLikeComplex_co,
|
||||
) -> _Series[np.complex128]: ...
|
||||
@overload
|
||||
def __call__(self, /, c: _SeriesLikeCoef_co) -> _ObjectSeries: ...
|
||||
|
||||
|
||||
_Companion: TypeAlias = np.ndarray[tuple[int, int], np.dtype[_SCT]]
|
||||
|
||||
@final
|
||||
class _FuncCompanion(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _SeriesLikeFloat_co,
|
||||
) -> _Companion[np.float64]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _SeriesLikeComplex_co,
|
||||
) -> _Companion[np.complex128]: ...
|
||||
@overload
|
||||
def __call__(self, /, c: _SeriesLikeCoef_co) -> _Companion[np.object_]: ...
|
||||
|
||||
@final
|
||||
class _FuncGauss(_Named[_Name_co], Protocol[_Name_co]):
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
deg: SupportsIndex,
|
||||
) -> _Tuple2[_Series[np.float64]]: ...
|
||||
|
||||
@final
|
||||
class _FuncWeight(_Named[_Name_co], Protocol[_Name_co]):
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _ArrayLikeFloat_co,
|
||||
) -> npt.NDArray[np.float64]: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
/,
|
||||
c: _ArrayLikeComplex_co,
|
||||
) -> npt.NDArray[np.complex128]: ...
|
||||
@overload
|
||||
def __call__(self, /, c: _ArrayLikeCoef_co) -> _ObjectArray: ...
|
||||
|
||||
@final
|
||||
class _FuncPts(_Named[_Name_co], Protocol[_Name_co]):
|
||||
def __call__(self, /, npts: _AnyInt) -> _Series[np.float64]: ...
|
2086
lib/python3.13/site-packages/numpy/polynomial/chebyshev.py
Normal file
2086
lib/python3.13/site-packages/numpy/polynomial/chebyshev.py
Normal file
File diff suppressed because it is too large
Load Diff
192
lib/python3.13/site-packages/numpy/polynomial/chebyshev.pyi
Normal file
192
lib/python3.13/site-packages/numpy/polynomial/chebyshev.pyi
Normal file
@ -0,0 +1,192 @@
|
||||
from collections.abc import Callable, Iterable
|
||||
from typing import (
|
||||
Any,
|
||||
Concatenate,
|
||||
Final,
|
||||
Literal as L,
|
||||
TypeVar,
|
||||
overload,
|
||||
)
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
from numpy._typing import _IntLike_co
|
||||
|
||||
from ._polybase import ABCPolyBase
|
||||
from ._polytypes import (
|
||||
_SeriesLikeCoef_co,
|
||||
_Array1,
|
||||
_Series,
|
||||
_Array2,
|
||||
_CoefSeries,
|
||||
_FuncBinOp,
|
||||
_FuncCompanion,
|
||||
_FuncDer,
|
||||
_FuncFit,
|
||||
_FuncFromRoots,
|
||||
_FuncGauss,
|
||||
_FuncInteg,
|
||||
_FuncLine,
|
||||
_FuncPoly2Ortho,
|
||||
_FuncPow,
|
||||
_FuncPts,
|
||||
_FuncRoots,
|
||||
_FuncUnOp,
|
||||
_FuncVal,
|
||||
_FuncVal2D,
|
||||
_FuncVal3D,
|
||||
_FuncValFromRoots,
|
||||
_FuncVander,
|
||||
_FuncVander2D,
|
||||
_FuncVander3D,
|
||||
_FuncWeight,
|
||||
)
|
||||
from .polyutils import trimcoef as chebtrim
|
||||
|
||||
__all__ = [
|
||||
"chebzero",
|
||||
"chebone",
|
||||
"chebx",
|
||||
"chebdomain",
|
||||
"chebline",
|
||||
"chebadd",
|
||||
"chebsub",
|
||||
"chebmulx",
|
||||
"chebmul",
|
||||
"chebdiv",
|
||||
"chebpow",
|
||||
"chebval",
|
||||
"chebder",
|
||||
"chebint",
|
||||
"cheb2poly",
|
||||
"poly2cheb",
|
||||
"chebfromroots",
|
||||
"chebvander",
|
||||
"chebfit",
|
||||
"chebtrim",
|
||||
"chebroots",
|
||||
"chebpts1",
|
||||
"chebpts2",
|
||||
"Chebyshev",
|
||||
"chebval2d",
|
||||
"chebval3d",
|
||||
"chebgrid2d",
|
||||
"chebgrid3d",
|
||||
"chebvander2d",
|
||||
"chebvander3d",
|
||||
"chebcompanion",
|
||||
"chebgauss",
|
||||
"chebweight",
|
||||
"chebinterpolate",
|
||||
]
|
||||
|
||||
_SCT = TypeVar("_SCT", bound=np.number[Any] | np.object_)
|
||||
def _cseries_to_zseries(c: npt.NDArray[_SCT]) -> _Series[_SCT]: ...
|
||||
def _zseries_to_cseries(zs: npt.NDArray[_SCT]) -> _Series[_SCT]: ...
|
||||
def _zseries_mul(
|
||||
z1: npt.NDArray[_SCT],
|
||||
z2: npt.NDArray[_SCT],
|
||||
) -> _Series[_SCT]: ...
|
||||
def _zseries_div(
|
||||
z1: npt.NDArray[_SCT],
|
||||
z2: npt.NDArray[_SCT],
|
||||
) -> _Series[_SCT]: ...
|
||||
def _zseries_der(zs: npt.NDArray[_SCT]) -> _Series[_SCT]: ...
|
||||
def _zseries_int(zs: npt.NDArray[_SCT]) -> _Series[_SCT]: ...
|
||||
|
||||
poly2cheb: _FuncPoly2Ortho[L["poly2cheb"]]
|
||||
cheb2poly: _FuncUnOp[L["cheb2poly"]]
|
||||
|
||||
chebdomain: Final[_Array2[np.float64]]
|
||||
chebzero: Final[_Array1[np.int_]]
|
||||
chebone: Final[_Array1[np.int_]]
|
||||
chebx: Final[_Array2[np.int_]]
|
||||
|
||||
chebline: _FuncLine[L["chebline"]]
|
||||
chebfromroots: _FuncFromRoots[L["chebfromroots"]]
|
||||
chebadd: _FuncBinOp[L["chebadd"]]
|
||||
chebsub: _FuncBinOp[L["chebsub"]]
|
||||
chebmulx: _FuncUnOp[L["chebmulx"]]
|
||||
chebmul: _FuncBinOp[L["chebmul"]]
|
||||
chebdiv: _FuncBinOp[L["chebdiv"]]
|
||||
chebpow: _FuncPow[L["chebpow"]]
|
||||
chebder: _FuncDer[L["chebder"]]
|
||||
chebint: _FuncInteg[L["chebint"]]
|
||||
chebval: _FuncVal[L["chebval"]]
|
||||
chebval2d: _FuncVal2D[L["chebval2d"]]
|
||||
chebval3d: _FuncVal3D[L["chebval3d"]]
|
||||
chebvalfromroots: _FuncValFromRoots[L["chebvalfromroots"]]
|
||||
chebgrid2d: _FuncVal2D[L["chebgrid2d"]]
|
||||
chebgrid3d: _FuncVal3D[L["chebgrid3d"]]
|
||||
chebvander: _FuncVander[L["chebvander"]]
|
||||
chebvander2d: _FuncVander2D[L["chebvander2d"]]
|
||||
chebvander3d: _FuncVander3D[L["chebvander3d"]]
|
||||
chebfit: _FuncFit[L["chebfit"]]
|
||||
chebcompanion: _FuncCompanion[L["chebcompanion"]]
|
||||
chebroots: _FuncRoots[L["chebroots"]]
|
||||
chebgauss: _FuncGauss[L["chebgauss"]]
|
||||
chebweight: _FuncWeight[L["chebweight"]]
|
||||
chebpts1: _FuncPts[L["chebpts1"]]
|
||||
chebpts2: _FuncPts[L["chebpts2"]]
|
||||
|
||||
# keep in sync with `Chebyshev.interpolate`
|
||||
_RT = TypeVar("_RT", bound=np.number[Any] | np.bool | np.object_)
|
||||
@overload
|
||||
def chebinterpolate(
|
||||
func: np.ufunc,
|
||||
deg: _IntLike_co,
|
||||
args: tuple[()] = ...,
|
||||
) -> npt.NDArray[np.float64 | np.complex128 | np.object_]: ...
|
||||
@overload
|
||||
def chebinterpolate(
|
||||
func: Callable[[npt.NDArray[np.float64]], _RT],
|
||||
deg: _IntLike_co,
|
||||
args: tuple[()] = ...,
|
||||
) -> npt.NDArray[_RT]: ...
|
||||
@overload
|
||||
def chebinterpolate(
|
||||
func: Callable[Concatenate[npt.NDArray[np.float64], ...], _RT],
|
||||
deg: _IntLike_co,
|
||||
args: Iterable[Any],
|
||||
) -> npt.NDArray[_RT]: ...
|
||||
|
||||
_Self = TypeVar("_Self", bound=object)
|
||||
|
||||
class Chebyshev(ABCPolyBase[L["T"]]):
|
||||
@overload
|
||||
@classmethod
|
||||
def interpolate(
|
||||
cls: type[_Self],
|
||||
/,
|
||||
func: Callable[[npt.NDArray[np.float64]], _CoefSeries],
|
||||
deg: _IntLike_co,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
args: tuple[()] = ...,
|
||||
) -> _Self: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def interpolate(
|
||||
cls: type[_Self],
|
||||
/,
|
||||
func: Callable[
|
||||
Concatenate[npt.NDArray[np.float64], ...],
|
||||
_CoefSeries,
|
||||
],
|
||||
deg: _IntLike_co,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
*,
|
||||
args: Iterable[Any],
|
||||
) -> _Self: ...
|
||||
@overload
|
||||
@classmethod
|
||||
def interpolate(
|
||||
cls: type[_Self],
|
||||
func: Callable[
|
||||
Concatenate[npt.NDArray[np.float64], ...],
|
||||
_CoefSeries,
|
||||
],
|
||||
deg: _IntLike_co,
|
||||
domain: None | _SeriesLikeCoef_co,
|
||||
args: Iterable[Any],
|
||||
/,
|
||||
) -> _Self: ...
|
1793
lib/python3.13/site-packages/numpy/polynomial/hermite.py
Normal file
1793
lib/python3.13/site-packages/numpy/polynomial/hermite.py
Normal file
File diff suppressed because it is too large
Load Diff
106
lib/python3.13/site-packages/numpy/polynomial/hermite.pyi
Normal file
106
lib/python3.13/site-packages/numpy/polynomial/hermite.pyi
Normal file
@ -0,0 +1,106 @@
|
||||
from typing import Any, Final, Literal as L, TypeVar
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ._polybase import ABCPolyBase
|
||||
from ._polytypes import (
|
||||
_Array1,
|
||||
_Array2,
|
||||
_FuncBinOp,
|
||||
_FuncCompanion,
|
||||
_FuncDer,
|
||||
_FuncFit,
|
||||
_FuncFromRoots,
|
||||
_FuncGauss,
|
||||
_FuncInteg,
|
||||
_FuncLine,
|
||||
_FuncPoly2Ortho,
|
||||
_FuncPow,
|
||||
_FuncRoots,
|
||||
_FuncUnOp,
|
||||
_FuncVal,
|
||||
_FuncVal2D,
|
||||
_FuncVal3D,
|
||||
_FuncValFromRoots,
|
||||
_FuncVander,
|
||||
_FuncVander2D,
|
||||
_FuncVander3D,
|
||||
_FuncWeight,
|
||||
)
|
||||
from .polyutils import trimcoef as hermtrim
|
||||
|
||||
__all__ = [
|
||||
"hermzero",
|
||||
"hermone",
|
||||
"hermx",
|
||||
"hermdomain",
|
||||
"hermline",
|
||||
"hermadd",
|
||||
"hermsub",
|
||||
"hermmulx",
|
||||
"hermmul",
|
||||
"hermdiv",
|
||||
"hermpow",
|
||||
"hermval",
|
||||
"hermder",
|
||||
"hermint",
|
||||
"herm2poly",
|
||||
"poly2herm",
|
||||
"hermfromroots",
|
||||
"hermvander",
|
||||
"hermfit",
|
||||
"hermtrim",
|
||||
"hermroots",
|
||||
"Hermite",
|
||||
"hermval2d",
|
||||
"hermval3d",
|
||||
"hermgrid2d",
|
||||
"hermgrid3d",
|
||||
"hermvander2d",
|
||||
"hermvander3d",
|
||||
"hermcompanion",
|
||||
"hermgauss",
|
||||
"hermweight",
|
||||
]
|
||||
|
||||
poly2herm: _FuncPoly2Ortho[L["poly2herm"]]
|
||||
herm2poly: _FuncUnOp[L["herm2poly"]]
|
||||
|
||||
hermdomain: Final[_Array2[np.float64]]
|
||||
hermzero: Final[_Array1[np.int_]]
|
||||
hermone: Final[_Array1[np.int_]]
|
||||
hermx: Final[_Array2[np.int_]]
|
||||
|
||||
hermline: _FuncLine[L["hermline"]]
|
||||
hermfromroots: _FuncFromRoots[L["hermfromroots"]]
|
||||
hermadd: _FuncBinOp[L["hermadd"]]
|
||||
hermsub: _FuncBinOp[L["hermsub"]]
|
||||
hermmulx: _FuncUnOp[L["hermmulx"]]
|
||||
hermmul: _FuncBinOp[L["hermmul"]]
|
||||
hermdiv: _FuncBinOp[L["hermdiv"]]
|
||||
hermpow: _FuncPow[L["hermpow"]]
|
||||
hermder: _FuncDer[L["hermder"]]
|
||||
hermint: _FuncInteg[L["hermint"]]
|
||||
hermval: _FuncVal[L["hermval"]]
|
||||
hermval2d: _FuncVal2D[L["hermval2d"]]
|
||||
hermval3d: _FuncVal3D[L["hermval3d"]]
|
||||
hermvalfromroots: _FuncValFromRoots[L["hermvalfromroots"]]
|
||||
hermgrid2d: _FuncVal2D[L["hermgrid2d"]]
|
||||
hermgrid3d: _FuncVal3D[L["hermgrid3d"]]
|
||||
hermvander: _FuncVander[L["hermvander"]]
|
||||
hermvander2d: _FuncVander2D[L["hermvander2d"]]
|
||||
hermvander3d: _FuncVander3D[L["hermvander3d"]]
|
||||
hermfit: _FuncFit[L["hermfit"]]
|
||||
hermcompanion: _FuncCompanion[L["hermcompanion"]]
|
||||
hermroots: _FuncRoots[L["hermroots"]]
|
||||
|
||||
_ND = TypeVar("_ND", bound=Any)
|
||||
def _normed_hermite_n(
|
||||
x: np.ndarray[_ND, np.dtype[np.float64]],
|
||||
n: int | np.intp,
|
||||
) -> np.ndarray[_ND, np.dtype[np.float64]]: ...
|
||||
|
||||
hermgauss: _FuncGauss[L["hermgauss"]]
|
||||
hermweight: _FuncWeight[L["hermweight"]]
|
||||
|
||||
class Hermite(ABCPolyBase[L["H"]]): ...
|
1703
lib/python3.13/site-packages/numpy/polynomial/hermite_e.py
Normal file
1703
lib/python3.13/site-packages/numpy/polynomial/hermite_e.py
Normal file
File diff suppressed because it is too large
Load Diff
106
lib/python3.13/site-packages/numpy/polynomial/hermite_e.pyi
Normal file
106
lib/python3.13/site-packages/numpy/polynomial/hermite_e.pyi
Normal file
@ -0,0 +1,106 @@
|
||||
from typing import Any, Final, Literal as L, TypeVar
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ._polybase import ABCPolyBase
|
||||
from ._polytypes import (
|
||||
_Array1,
|
||||
_Array2,
|
||||
_FuncBinOp,
|
||||
_FuncCompanion,
|
||||
_FuncDer,
|
||||
_FuncFit,
|
||||
_FuncFromRoots,
|
||||
_FuncGauss,
|
||||
_FuncInteg,
|
||||
_FuncLine,
|
||||
_FuncPoly2Ortho,
|
||||
_FuncPow,
|
||||
_FuncRoots,
|
||||
_FuncUnOp,
|
||||
_FuncVal,
|
||||
_FuncVal2D,
|
||||
_FuncVal3D,
|
||||
_FuncValFromRoots,
|
||||
_FuncVander,
|
||||
_FuncVander2D,
|
||||
_FuncVander3D,
|
||||
_FuncWeight,
|
||||
)
|
||||
from .polyutils import trimcoef as hermetrim
|
||||
|
||||
__all__ = [
|
||||
"hermezero",
|
||||
"hermeone",
|
||||
"hermex",
|
||||
"hermedomain",
|
||||
"hermeline",
|
||||
"hermeadd",
|
||||
"hermesub",
|
||||
"hermemulx",
|
||||
"hermemul",
|
||||
"hermediv",
|
||||
"hermepow",
|
||||
"hermeval",
|
||||
"hermeder",
|
||||
"hermeint",
|
||||
"herme2poly",
|
||||
"poly2herme",
|
||||
"hermefromroots",
|
||||
"hermevander",
|
||||
"hermefit",
|
||||
"hermetrim",
|
||||
"hermeroots",
|
||||
"HermiteE",
|
||||
"hermeval2d",
|
||||
"hermeval3d",
|
||||
"hermegrid2d",
|
||||
"hermegrid3d",
|
||||
"hermevander2d",
|
||||
"hermevander3d",
|
||||
"hermecompanion",
|
||||
"hermegauss",
|
||||
"hermeweight",
|
||||
]
|
||||
|
||||
poly2herme: _FuncPoly2Ortho[L["poly2herme"]]
|
||||
herme2poly: _FuncUnOp[L["herme2poly"]]
|
||||
|
||||
hermedomain: Final[_Array2[np.float64]]
|
||||
hermezero: Final[_Array1[np.int_]]
|
||||
hermeone: Final[_Array1[np.int_]]
|
||||
hermex: Final[_Array2[np.int_]]
|
||||
|
||||
hermeline: _FuncLine[L["hermeline"]]
|
||||
hermefromroots: _FuncFromRoots[L["hermefromroots"]]
|
||||
hermeadd: _FuncBinOp[L["hermeadd"]]
|
||||
hermesub: _FuncBinOp[L["hermesub"]]
|
||||
hermemulx: _FuncUnOp[L["hermemulx"]]
|
||||
hermemul: _FuncBinOp[L["hermemul"]]
|
||||
hermediv: _FuncBinOp[L["hermediv"]]
|
||||
hermepow: _FuncPow[L["hermepow"]]
|
||||
hermeder: _FuncDer[L["hermeder"]]
|
||||
hermeint: _FuncInteg[L["hermeint"]]
|
||||
hermeval: _FuncVal[L["hermeval"]]
|
||||
hermeval2d: _FuncVal2D[L["hermeval2d"]]
|
||||
hermeval3d: _FuncVal3D[L["hermeval3d"]]
|
||||
hermevalfromroots: _FuncValFromRoots[L["hermevalfromroots"]]
|
||||
hermegrid2d: _FuncVal2D[L["hermegrid2d"]]
|
||||
hermegrid3d: _FuncVal3D[L["hermegrid3d"]]
|
||||
hermevander: _FuncVander[L["hermevander"]]
|
||||
hermevander2d: _FuncVander2D[L["hermevander2d"]]
|
||||
hermevander3d: _FuncVander3D[L["hermevander3d"]]
|
||||
hermefit: _FuncFit[L["hermefit"]]
|
||||
hermecompanion: _FuncCompanion[L["hermecompanion"]]
|
||||
hermeroots: _FuncRoots[L["hermeroots"]]
|
||||
|
||||
_ND = TypeVar("_ND", bound=Any)
|
||||
def _normed_hermite_e_n(
|
||||
x: np.ndarray[_ND, np.dtype[np.float64]],
|
||||
n: int | np.intp,
|
||||
) -> np.ndarray[_ND, np.dtype[np.float64]]: ...
|
||||
|
||||
hermegauss: _FuncGauss[L["hermegauss"]]
|
||||
hermeweight: _FuncWeight[L["hermeweight"]]
|
||||
|
||||
class HermiteE(ABCPolyBase[L["He"]]): ...
|
1726
lib/python3.13/site-packages/numpy/polynomial/laguerre.py
Normal file
1726
lib/python3.13/site-packages/numpy/polynomial/laguerre.py
Normal file
File diff suppressed because it is too large
Load Diff
100
lib/python3.13/site-packages/numpy/polynomial/laguerre.pyi
Normal file
100
lib/python3.13/site-packages/numpy/polynomial/laguerre.pyi
Normal file
@ -0,0 +1,100 @@
|
||||
from typing import Final, Literal as L
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ._polybase import ABCPolyBase
|
||||
from ._polytypes import (
|
||||
_Array1,
|
||||
_Array2,
|
||||
_FuncBinOp,
|
||||
_FuncCompanion,
|
||||
_FuncDer,
|
||||
_FuncFit,
|
||||
_FuncFromRoots,
|
||||
_FuncGauss,
|
||||
_FuncInteg,
|
||||
_FuncLine,
|
||||
_FuncPoly2Ortho,
|
||||
_FuncPow,
|
||||
_FuncRoots,
|
||||
_FuncUnOp,
|
||||
_FuncVal,
|
||||
_FuncVal2D,
|
||||
_FuncVal3D,
|
||||
_FuncValFromRoots,
|
||||
_FuncVander,
|
||||
_FuncVander2D,
|
||||
_FuncVander3D,
|
||||
_FuncWeight,
|
||||
)
|
||||
from .polyutils import trimcoef as lagtrim
|
||||
|
||||
__all__ = [
|
||||
"lagzero",
|
||||
"lagone",
|
||||
"lagx",
|
||||
"lagdomain",
|
||||
"lagline",
|
||||
"lagadd",
|
||||
"lagsub",
|
||||
"lagmulx",
|
||||
"lagmul",
|
||||
"lagdiv",
|
||||
"lagpow",
|
||||
"lagval",
|
||||
"lagder",
|
||||
"lagint",
|
||||
"lag2poly",
|
||||
"poly2lag",
|
||||
"lagfromroots",
|
||||
"lagvander",
|
||||
"lagfit",
|
||||
"lagtrim",
|
||||
"lagroots",
|
||||
"Laguerre",
|
||||
"lagval2d",
|
||||
"lagval3d",
|
||||
"laggrid2d",
|
||||
"laggrid3d",
|
||||
"lagvander2d",
|
||||
"lagvander3d",
|
||||
"lagcompanion",
|
||||
"laggauss",
|
||||
"lagweight",
|
||||
]
|
||||
|
||||
poly2lag: _FuncPoly2Ortho[L["poly2lag"]]
|
||||
lag2poly: _FuncUnOp[L["lag2poly"]]
|
||||
|
||||
lagdomain: Final[_Array2[np.float64]]
|
||||
lagzero: Final[_Array1[np.int_]]
|
||||
lagone: Final[_Array1[np.int_]]
|
||||
lagx: Final[_Array2[np.int_]]
|
||||
|
||||
lagline: _FuncLine[L["lagline"]]
|
||||
lagfromroots: _FuncFromRoots[L["lagfromroots"]]
|
||||
lagadd: _FuncBinOp[L["lagadd"]]
|
||||
lagsub: _FuncBinOp[L["lagsub"]]
|
||||
lagmulx: _FuncUnOp[L["lagmulx"]]
|
||||
lagmul: _FuncBinOp[L["lagmul"]]
|
||||
lagdiv: _FuncBinOp[L["lagdiv"]]
|
||||
lagpow: _FuncPow[L["lagpow"]]
|
||||
lagder: _FuncDer[L["lagder"]]
|
||||
lagint: _FuncInteg[L["lagint"]]
|
||||
lagval: _FuncVal[L["lagval"]]
|
||||
lagval2d: _FuncVal2D[L["lagval2d"]]
|
||||
lagval3d: _FuncVal3D[L["lagval3d"]]
|
||||
lagvalfromroots: _FuncValFromRoots[L["lagvalfromroots"]]
|
||||
laggrid2d: _FuncVal2D[L["laggrid2d"]]
|
||||
laggrid3d: _FuncVal3D[L["laggrid3d"]]
|
||||
lagvander: _FuncVander[L["lagvander"]]
|
||||
lagvander2d: _FuncVander2D[L["lagvander2d"]]
|
||||
lagvander3d: _FuncVander3D[L["lagvander3d"]]
|
||||
lagfit: _FuncFit[L["lagfit"]]
|
||||
lagcompanion: _FuncCompanion[L["lagcompanion"]]
|
||||
lagroots: _FuncRoots[L["lagroots"]]
|
||||
laggauss: _FuncGauss[L["laggauss"]]
|
||||
lagweight: _FuncWeight[L["lagweight"]]
|
||||
|
||||
|
||||
class Laguerre(ABCPolyBase[L["L"]]): ...
|
1666
lib/python3.13/site-packages/numpy/polynomial/legendre.py
Normal file
1666
lib/python3.13/site-packages/numpy/polynomial/legendre.py
Normal file
File diff suppressed because it is too large
Load Diff
99
lib/python3.13/site-packages/numpy/polynomial/legendre.pyi
Normal file
99
lib/python3.13/site-packages/numpy/polynomial/legendre.pyi
Normal file
@ -0,0 +1,99 @@
|
||||
from typing import Final, Literal as L
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ._polybase import ABCPolyBase
|
||||
from ._polytypes import (
|
||||
_Array1,
|
||||
_Array2,
|
||||
_FuncBinOp,
|
||||
_FuncCompanion,
|
||||
_FuncDer,
|
||||
_FuncFit,
|
||||
_FuncFromRoots,
|
||||
_FuncGauss,
|
||||
_FuncInteg,
|
||||
_FuncLine,
|
||||
_FuncPoly2Ortho,
|
||||
_FuncPow,
|
||||
_FuncRoots,
|
||||
_FuncUnOp,
|
||||
_FuncVal,
|
||||
_FuncVal2D,
|
||||
_FuncVal3D,
|
||||
_FuncValFromRoots,
|
||||
_FuncVander,
|
||||
_FuncVander2D,
|
||||
_FuncVander3D,
|
||||
_FuncWeight,
|
||||
)
|
||||
from .polyutils import trimcoef as legtrim
|
||||
|
||||
__all__ = [
|
||||
"legzero",
|
||||
"legone",
|
||||
"legx",
|
||||
"legdomain",
|
||||
"legline",
|
||||
"legadd",
|
||||
"legsub",
|
||||
"legmulx",
|
||||
"legmul",
|
||||
"legdiv",
|
||||
"legpow",
|
||||
"legval",
|
||||
"legder",
|
||||
"legint",
|
||||
"leg2poly",
|
||||
"poly2leg",
|
||||
"legfromroots",
|
||||
"legvander",
|
||||
"legfit",
|
||||
"legtrim",
|
||||
"legroots",
|
||||
"Legendre",
|
||||
"legval2d",
|
||||
"legval3d",
|
||||
"leggrid2d",
|
||||
"leggrid3d",
|
||||
"legvander2d",
|
||||
"legvander3d",
|
||||
"legcompanion",
|
||||
"leggauss",
|
||||
"legweight",
|
||||
]
|
||||
|
||||
poly2leg: _FuncPoly2Ortho[L["poly2leg"]]
|
||||
leg2poly: _FuncUnOp[L["leg2poly"]]
|
||||
|
||||
legdomain: Final[_Array2[np.float64]]
|
||||
legzero: Final[_Array1[np.int_]]
|
||||
legone: Final[_Array1[np.int_]]
|
||||
legx: Final[_Array2[np.int_]]
|
||||
|
||||
legline: _FuncLine[L["legline"]]
|
||||
legfromroots: _FuncFromRoots[L["legfromroots"]]
|
||||
legadd: _FuncBinOp[L["legadd"]]
|
||||
legsub: _FuncBinOp[L["legsub"]]
|
||||
legmulx: _FuncUnOp[L["legmulx"]]
|
||||
legmul: _FuncBinOp[L["legmul"]]
|
||||
legdiv: _FuncBinOp[L["legdiv"]]
|
||||
legpow: _FuncPow[L["legpow"]]
|
||||
legder: _FuncDer[L["legder"]]
|
||||
legint: _FuncInteg[L["legint"]]
|
||||
legval: _FuncVal[L["legval"]]
|
||||
legval2d: _FuncVal2D[L["legval2d"]]
|
||||
legval3d: _FuncVal3D[L["legval3d"]]
|
||||
legvalfromroots: _FuncValFromRoots[L["legvalfromroots"]]
|
||||
leggrid2d: _FuncVal2D[L["leggrid2d"]]
|
||||
leggrid3d: _FuncVal3D[L["leggrid3d"]]
|
||||
legvander: _FuncVander[L["legvander"]]
|
||||
legvander2d: _FuncVander2D[L["legvander2d"]]
|
||||
legvander3d: _FuncVander3D[L["legvander3d"]]
|
||||
legfit: _FuncFit[L["legfit"]]
|
||||
legcompanion: _FuncCompanion[L["legcompanion"]]
|
||||
legroots: _FuncRoots[L["legroots"]]
|
||||
leggauss: _FuncGauss[L["leggauss"]]
|
||||
legweight: _FuncWeight[L["legweight"]]
|
||||
|
||||
class Legendre(ABCPolyBase[L["P"]]): ...
|
1664
lib/python3.13/site-packages/numpy/polynomial/polynomial.py
Normal file
1664
lib/python3.13/site-packages/numpy/polynomial/polynomial.py
Normal file
File diff suppressed because it is too large
Load Diff
87
lib/python3.13/site-packages/numpy/polynomial/polynomial.pyi
Normal file
87
lib/python3.13/site-packages/numpy/polynomial/polynomial.pyi
Normal file
@ -0,0 +1,87 @@
|
||||
from typing import Final, Literal as L
|
||||
|
||||
import numpy as np
|
||||
from ._polybase import ABCPolyBase
|
||||
from ._polytypes import (
|
||||
_Array1,
|
||||
_Array2,
|
||||
_FuncVal2D,
|
||||
_FuncVal3D,
|
||||
_FuncBinOp,
|
||||
_FuncCompanion,
|
||||
_FuncDer,
|
||||
_FuncFit,
|
||||
_FuncFromRoots,
|
||||
_FuncInteg,
|
||||
_FuncLine,
|
||||
_FuncPow,
|
||||
_FuncRoots,
|
||||
_FuncUnOp,
|
||||
_FuncVal,
|
||||
_FuncVander,
|
||||
_FuncVander2D,
|
||||
_FuncVander3D,
|
||||
_FuncValFromRoots,
|
||||
)
|
||||
from .polyutils import trimcoef as polytrim
|
||||
|
||||
__all__ = [
|
||||
"polyzero",
|
||||
"polyone",
|
||||
"polyx",
|
||||
"polydomain",
|
||||
"polyline",
|
||||
"polyadd",
|
||||
"polysub",
|
||||
"polymulx",
|
||||
"polymul",
|
||||
"polydiv",
|
||||
"polypow",
|
||||
"polyval",
|
||||
"polyvalfromroots",
|
||||
"polyder",
|
||||
"polyint",
|
||||
"polyfromroots",
|
||||
"polyvander",
|
||||
"polyfit",
|
||||
"polytrim",
|
||||
"polyroots",
|
||||
"Polynomial",
|
||||
"polyval2d",
|
||||
"polyval3d",
|
||||
"polygrid2d",
|
||||
"polygrid3d",
|
||||
"polyvander2d",
|
||||
"polyvander3d",
|
||||
"polycompanion",
|
||||
]
|
||||
|
||||
polydomain: Final[_Array2[np.float64]]
|
||||
polyzero: Final[_Array1[np.int_]]
|
||||
polyone: Final[_Array1[np.int_]]
|
||||
polyx: Final[_Array2[np.int_]]
|
||||
|
||||
polyline: _FuncLine[L["Polyline"]]
|
||||
polyfromroots: _FuncFromRoots[L["polyfromroots"]]
|
||||
polyadd: _FuncBinOp[L["polyadd"]]
|
||||
polysub: _FuncBinOp[L["polysub"]]
|
||||
polymulx: _FuncUnOp[L["polymulx"]]
|
||||
polymul: _FuncBinOp[L["polymul"]]
|
||||
polydiv: _FuncBinOp[L["polydiv"]]
|
||||
polypow: _FuncPow[L["polypow"]]
|
||||
polyder: _FuncDer[L["polyder"]]
|
||||
polyint: _FuncInteg[L["polyint"]]
|
||||
polyval: _FuncVal[L["polyval"]]
|
||||
polyval2d: _FuncVal2D[L["polyval2d"]]
|
||||
polyval3d: _FuncVal3D[L["polyval3d"]]
|
||||
polyvalfromroots: _FuncValFromRoots[L["polyvalfromroots"]]
|
||||
polygrid2d: _FuncVal2D[L["polygrid2d"]]
|
||||
polygrid3d: _FuncVal3D[L["polygrid3d"]]
|
||||
polyvander: _FuncVander[L["polyvander"]]
|
||||
polyvander2d: _FuncVander2D[L["polyvander2d"]]
|
||||
polyvander3d: _FuncVander3D[L["polyvander3d"]]
|
||||
polyfit: _FuncFit[L["polyfit"]]
|
||||
polycompanion: _FuncCompanion[L["polycompanion"]]
|
||||
polyroots: _FuncRoots[L["polyroots"]]
|
||||
|
||||
class Polynomial(ABCPolyBase[None]): ...
|
757
lib/python3.13/site-packages/numpy/polynomial/polyutils.py
Normal file
757
lib/python3.13/site-packages/numpy/polynomial/polyutils.py
Normal file
@ -0,0 +1,757 @@
|
||||
"""
|
||||
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.
|
||||
|
||||
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.exceptions import RankWarning
|
||||
|
||||
__all__ = [
|
||||
'as_series', 'trimseq', 'trimcoef', 'getdomain', 'mapdomain', 'mapparms',
|
||||
'format_float']
|
||||
|
||||
#
|
||||
# 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.
|
||||
|
||||
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 or seq[-1] != 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
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> 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=None) for a in alist]
|
||||
for a in arrays:
|
||||
if a.size == 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
|
||||
|
||||
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
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> 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
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> 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
|
||||
|
||||
"""
|
||||
if type(x) not in (int, float, complex) and not isinstance(x, np.generic):
|
||||
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.asarray(tuple(points)) + 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 _as_int(x, desc):
|
||||
"""
|
||||
Like `operator.index`, but emits a custom exception when passed an
|
||||
incorrect type
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : int-like
|
||||
Value to interpret as an integer
|
||||
desc : str
|
||||
description to include in any error message
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError : if x is a float or non-numeric
|
||||
"""
|
||||
try:
|
||||
return operator.index(x)
|
||||
except TypeError as e:
|
||||
raise TypeError(f"{desc} must be an integer, received {x}") 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 = np.abs(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
|
431
lib/python3.13/site-packages/numpy/polynomial/polyutils.pyi
Normal file
431
lib/python3.13/site-packages/numpy/polynomial/polyutils.pyi
Normal file
@ -0,0 +1,431 @@
|
||||
from collections.abc import Callable, Iterable, Sequence
|
||||
from typing import (
|
||||
Any,
|
||||
Final,
|
||||
Literal,
|
||||
SupportsIndex,
|
||||
TypeAlias,
|
||||
TypeVar,
|
||||
overload,
|
||||
)
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
from numpy._typing import (
|
||||
_FloatLike_co,
|
||||
_NumberLike_co,
|
||||
|
||||
_ArrayLikeFloat_co,
|
||||
_ArrayLikeComplex_co,
|
||||
)
|
||||
|
||||
from ._polytypes import (
|
||||
_AnyInt,
|
||||
_CoefLike_co,
|
||||
|
||||
_Array2,
|
||||
_Tuple2,
|
||||
|
||||
_FloatSeries,
|
||||
_CoefSeries,
|
||||
_ComplexSeries,
|
||||
_ObjectSeries,
|
||||
|
||||
_ComplexArray,
|
||||
_FloatArray,
|
||||
_CoefArray,
|
||||
_ObjectArray,
|
||||
|
||||
_SeriesLikeInt_co,
|
||||
_SeriesLikeFloat_co,
|
||||
_SeriesLikeComplex_co,
|
||||
_SeriesLikeCoef_co,
|
||||
|
||||
_ArrayLikeCoef_co,
|
||||
|
||||
_FuncBinOp,
|
||||
_FuncValND,
|
||||
_FuncVanderND,
|
||||
)
|
||||
|
||||
__all__: Final[Sequence[str]] = [
|
||||
"as_series",
|
||||
"format_float",
|
||||
"getdomain",
|
||||
"mapdomain",
|
||||
"mapparms",
|
||||
"trimcoef",
|
||||
"trimseq",
|
||||
]
|
||||
|
||||
_AnyLineF: TypeAlias = Callable[
|
||||
[_CoefLike_co, _CoefLike_co],
|
||||
_CoefArray,
|
||||
]
|
||||
_AnyMulF: TypeAlias = Callable[
|
||||
[npt.ArrayLike, npt.ArrayLike],
|
||||
_CoefArray,
|
||||
]
|
||||
_AnyVanderF: TypeAlias = Callable[
|
||||
[npt.ArrayLike, SupportsIndex],
|
||||
_CoefArray,
|
||||
]
|
||||
|
||||
@overload
|
||||
def as_series(
|
||||
alist: npt.NDArray[np.integer[Any]] | _FloatArray,
|
||||
trim: bool = ...,
|
||||
) -> list[_FloatSeries]: ...
|
||||
@overload
|
||||
def as_series(
|
||||
alist: _ComplexArray,
|
||||
trim: bool = ...,
|
||||
) -> list[_ComplexSeries]: ...
|
||||
@overload
|
||||
def as_series(
|
||||
alist: _ObjectArray,
|
||||
trim: bool = ...,
|
||||
) -> list[_ObjectSeries]: ...
|
||||
@overload
|
||||
def as_series( # type: ignore[overload-overlap]
|
||||
alist: Iterable[_FloatArray | npt.NDArray[np.integer[Any]]],
|
||||
trim: bool = ...,
|
||||
) -> list[_FloatSeries]: ...
|
||||
@overload
|
||||
def as_series(
|
||||
alist: Iterable[_ComplexArray],
|
||||
trim: bool = ...,
|
||||
) -> list[_ComplexSeries]: ...
|
||||
@overload
|
||||
def as_series(
|
||||
alist: Iterable[_ObjectArray],
|
||||
trim: bool = ...,
|
||||
) -> list[_ObjectSeries]: ...
|
||||
@overload
|
||||
def as_series( # type: ignore[overload-overlap]
|
||||
alist: Iterable[_SeriesLikeFloat_co | float],
|
||||
trim: bool = ...,
|
||||
) -> list[_FloatSeries]: ...
|
||||
@overload
|
||||
def as_series(
|
||||
alist: Iterable[_SeriesLikeComplex_co | complex],
|
||||
trim: bool = ...,
|
||||
) -> list[_ComplexSeries]: ...
|
||||
@overload
|
||||
def as_series(
|
||||
alist: Iterable[_SeriesLikeCoef_co | object],
|
||||
trim: bool = ...,
|
||||
) -> list[_ObjectSeries]: ...
|
||||
|
||||
_T_seq = TypeVar("_T_seq", bound=_CoefArray | Sequence[_CoefLike_co])
|
||||
def trimseq(seq: _T_seq) -> _T_seq: ...
|
||||
|
||||
@overload
|
||||
def trimcoef( # type: ignore[overload-overlap]
|
||||
c: npt.NDArray[np.integer[Any]] | _FloatArray,
|
||||
tol: _FloatLike_co = ...,
|
||||
) -> _FloatSeries: ...
|
||||
@overload
|
||||
def trimcoef(
|
||||
c: _ComplexArray,
|
||||
tol: _FloatLike_co = ...,
|
||||
) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def trimcoef(
|
||||
c: _ObjectArray,
|
||||
tol: _FloatLike_co = ...,
|
||||
) -> _ObjectSeries: ...
|
||||
@overload
|
||||
def trimcoef( # type: ignore[overload-overlap]
|
||||
c: _SeriesLikeFloat_co | float,
|
||||
tol: _FloatLike_co = ...,
|
||||
) -> _FloatSeries: ...
|
||||
@overload
|
||||
def trimcoef(
|
||||
c: _SeriesLikeComplex_co | complex,
|
||||
tol: _FloatLike_co = ...,
|
||||
) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def trimcoef(
|
||||
c: _SeriesLikeCoef_co | object,
|
||||
tol: _FloatLike_co = ...,
|
||||
) -> _ObjectSeries: ...
|
||||
|
||||
@overload
|
||||
def getdomain( # type: ignore[overload-overlap]
|
||||
x: _FloatArray | npt.NDArray[np.integer[Any]],
|
||||
) -> _Array2[np.float64]: ...
|
||||
@overload
|
||||
def getdomain(
|
||||
x: _ComplexArray,
|
||||
) -> _Array2[np.complex128]: ...
|
||||
@overload
|
||||
def getdomain(
|
||||
x: _ObjectArray,
|
||||
) -> _Array2[np.object_]: ...
|
||||
@overload
|
||||
def getdomain( # type: ignore[overload-overlap]
|
||||
x: _SeriesLikeFloat_co | float,
|
||||
) -> _Array2[np.float64]: ...
|
||||
@overload
|
||||
def getdomain(
|
||||
x: _SeriesLikeComplex_co | complex,
|
||||
) -> _Array2[np.complex128]: ...
|
||||
@overload
|
||||
def getdomain(
|
||||
x: _SeriesLikeCoef_co | object,
|
||||
) -> _Array2[np.object_]: ...
|
||||
|
||||
@overload
|
||||
def mapparms( # type: ignore[overload-overlap]
|
||||
old: npt.NDArray[np.floating[Any] | np.integer[Any]],
|
||||
new: npt.NDArray[np.floating[Any] | np.integer[Any]],
|
||||
) -> _Tuple2[np.floating[Any]]: ...
|
||||
@overload
|
||||
def mapparms(
|
||||
old: npt.NDArray[np.number[Any]],
|
||||
new: npt.NDArray[np.number[Any]],
|
||||
) -> _Tuple2[np.complexfloating[Any, Any]]: ...
|
||||
@overload
|
||||
def mapparms(
|
||||
old: npt.NDArray[np.object_ | np.number[Any]],
|
||||
new: npt.NDArray[np.object_ | np.number[Any]],
|
||||
) -> _Tuple2[object]: ...
|
||||
@overload
|
||||
def mapparms( # type: ignore[overload-overlap]
|
||||
old: Sequence[float],
|
||||
new: Sequence[float],
|
||||
) -> _Tuple2[float]: ...
|
||||
@overload
|
||||
def mapparms(
|
||||
old: Sequence[complex],
|
||||
new: Sequence[complex],
|
||||
) -> _Tuple2[complex]: ...
|
||||
@overload
|
||||
def mapparms(
|
||||
old: _SeriesLikeFloat_co,
|
||||
new: _SeriesLikeFloat_co,
|
||||
) -> _Tuple2[np.floating[Any]]: ...
|
||||
@overload
|
||||
def mapparms(
|
||||
old: _SeriesLikeComplex_co,
|
||||
new: _SeriesLikeComplex_co,
|
||||
) -> _Tuple2[np.complexfloating[Any, Any]]: ...
|
||||
@overload
|
||||
def mapparms(
|
||||
old: _SeriesLikeCoef_co,
|
||||
new: _SeriesLikeCoef_co,
|
||||
) -> _Tuple2[object]: ...
|
||||
|
||||
@overload
|
||||
def mapdomain( # type: ignore[overload-overlap]
|
||||
x: _FloatLike_co,
|
||||
old: _SeriesLikeFloat_co,
|
||||
new: _SeriesLikeFloat_co,
|
||||
) -> np.floating[Any]: ...
|
||||
@overload
|
||||
def mapdomain(
|
||||
x: _NumberLike_co,
|
||||
old: _SeriesLikeComplex_co,
|
||||
new: _SeriesLikeComplex_co,
|
||||
) -> np.complexfloating[Any, Any]: ...
|
||||
@overload
|
||||
def mapdomain( # type: ignore[overload-overlap]
|
||||
x: npt.NDArray[np.floating[Any] | np.integer[Any]],
|
||||
old: npt.NDArray[np.floating[Any] | np.integer[Any]],
|
||||
new: npt.NDArray[np.floating[Any] | np.integer[Any]],
|
||||
) -> _FloatSeries: ...
|
||||
@overload
|
||||
def mapdomain(
|
||||
x: npt.NDArray[np.number[Any]],
|
||||
old: npt.NDArray[np.number[Any]],
|
||||
new: npt.NDArray[np.number[Any]],
|
||||
) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def mapdomain(
|
||||
x: npt.NDArray[np.object_ | np.number[Any]],
|
||||
old: npt.NDArray[np.object_ | np.number[Any]],
|
||||
new: npt.NDArray[np.object_ | np.number[Any]],
|
||||
) -> _ObjectSeries: ...
|
||||
@overload
|
||||
def mapdomain( # type: ignore[overload-overlap]
|
||||
x: _SeriesLikeFloat_co,
|
||||
old: _SeriesLikeFloat_co,
|
||||
new: _SeriesLikeFloat_co,
|
||||
) -> _FloatSeries: ...
|
||||
@overload
|
||||
def mapdomain(
|
||||
x: _SeriesLikeComplex_co,
|
||||
old: _SeriesLikeComplex_co,
|
||||
new: _SeriesLikeComplex_co,
|
||||
) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def mapdomain(
|
||||
x: _SeriesLikeCoef_co,
|
||||
old:_SeriesLikeCoef_co,
|
||||
new: _SeriesLikeCoef_co,
|
||||
) -> _ObjectSeries: ...
|
||||
@overload
|
||||
def mapdomain(
|
||||
x: _CoefLike_co,
|
||||
old: _SeriesLikeCoef_co,
|
||||
new: _SeriesLikeCoef_co,
|
||||
) -> object: ...
|
||||
|
||||
def _nth_slice(
|
||||
i: SupportsIndex,
|
||||
ndim: SupportsIndex,
|
||||
) -> tuple[None | slice, ...]: ...
|
||||
|
||||
_vander_nd: _FuncVanderND[Literal["_vander_nd"]]
|
||||
_vander_nd_flat: _FuncVanderND[Literal["_vander_nd_flat"]]
|
||||
|
||||
# keep in sync with `._polytypes._FuncFromRoots`
|
||||
@overload
|
||||
def _fromroots( # type: ignore[overload-overlap]
|
||||
line_f: _AnyLineF,
|
||||
mul_f: _AnyMulF,
|
||||
roots: _SeriesLikeFloat_co,
|
||||
) -> _FloatSeries: ...
|
||||
@overload
|
||||
def _fromroots(
|
||||
line_f: _AnyLineF,
|
||||
mul_f: _AnyMulF,
|
||||
roots: _SeriesLikeComplex_co,
|
||||
) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def _fromroots(
|
||||
line_f: _AnyLineF,
|
||||
mul_f: _AnyMulF,
|
||||
roots: _SeriesLikeCoef_co,
|
||||
) -> _ObjectSeries: ...
|
||||
@overload
|
||||
def _fromroots(
|
||||
line_f: _AnyLineF,
|
||||
mul_f: _AnyMulF,
|
||||
roots: _SeriesLikeCoef_co,
|
||||
) -> _CoefSeries: ...
|
||||
|
||||
_valnd: _FuncValND[Literal["_valnd"]]
|
||||
_gridnd: _FuncValND[Literal["_gridnd"]]
|
||||
|
||||
# keep in sync with `_polytypes._FuncBinOp`
|
||||
@overload
|
||||
def _div( # type: ignore[overload-overlap]
|
||||
mul_f: _AnyMulF,
|
||||
c1: _SeriesLikeFloat_co,
|
||||
c2: _SeriesLikeFloat_co,
|
||||
) -> _Tuple2[_FloatSeries]: ...
|
||||
@overload
|
||||
def _div(
|
||||
mul_f: _AnyMulF,
|
||||
c1: _SeriesLikeComplex_co,
|
||||
c2: _SeriesLikeComplex_co,
|
||||
) -> _Tuple2[_ComplexSeries]: ...
|
||||
@overload
|
||||
def _div(
|
||||
mul_f: _AnyMulF,
|
||||
c1: _SeriesLikeCoef_co,
|
||||
c2: _SeriesLikeCoef_co,
|
||||
) -> _Tuple2[_ObjectSeries]: ...
|
||||
@overload
|
||||
def _div(
|
||||
mul_f: _AnyMulF,
|
||||
c1: _SeriesLikeCoef_co,
|
||||
c2: _SeriesLikeCoef_co,
|
||||
) -> _Tuple2[_CoefSeries]: ...
|
||||
|
||||
_add: Final[_FuncBinOp]
|
||||
_sub: Final[_FuncBinOp]
|
||||
|
||||
# keep in sync with `_polytypes._FuncPow`
|
||||
@overload
|
||||
def _pow( # type: ignore[overload-overlap]
|
||||
mul_f: _AnyMulF,
|
||||
c: _SeriesLikeFloat_co,
|
||||
pow: _AnyInt,
|
||||
maxpower: None | _AnyInt = ...,
|
||||
) -> _FloatSeries: ...
|
||||
@overload
|
||||
def _pow(
|
||||
mul_f: _AnyMulF,
|
||||
c: _SeriesLikeComplex_co,
|
||||
pow: _AnyInt,
|
||||
maxpower: None | _AnyInt = ...,
|
||||
) -> _ComplexSeries: ...
|
||||
@overload
|
||||
def _pow(
|
||||
mul_f: _AnyMulF,
|
||||
c: _SeriesLikeCoef_co,
|
||||
pow: _AnyInt,
|
||||
maxpower: None | _AnyInt = ...,
|
||||
) -> _ObjectSeries: ...
|
||||
@overload
|
||||
def _pow(
|
||||
mul_f: _AnyMulF,
|
||||
c: _SeriesLikeCoef_co,
|
||||
pow: _AnyInt,
|
||||
maxpower: None | _AnyInt = ...,
|
||||
) -> _CoefSeries: ...
|
||||
|
||||
# keep in sync with `_polytypes._FuncFit`
|
||||
@overload
|
||||
def _fit( # type: ignore[overload-overlap]
|
||||
vander_f: _AnyVanderF,
|
||||
x: _SeriesLikeFloat_co,
|
||||
y: _ArrayLikeFloat_co,
|
||||
deg: _SeriesLikeInt_co,
|
||||
domain: None | _SeriesLikeFloat_co = ...,
|
||||
rcond: None | _FloatLike_co = ...,
|
||||
full: Literal[False] = ...,
|
||||
w: None | _SeriesLikeFloat_co = ...,
|
||||
) -> _FloatArray: ...
|
||||
@overload
|
||||
def _fit(
|
||||
vander_f: _AnyVanderF,
|
||||
x: _SeriesLikeComplex_co,
|
||||
y: _ArrayLikeComplex_co,
|
||||
deg: _SeriesLikeInt_co,
|
||||
domain: None | _SeriesLikeComplex_co = ...,
|
||||
rcond: None | _FloatLike_co = ...,
|
||||
full: Literal[False] = ...,
|
||||
w: None | _SeriesLikeComplex_co = ...,
|
||||
) -> _ComplexArray: ...
|
||||
@overload
|
||||
def _fit(
|
||||
vander_f: _AnyVanderF,
|
||||
x: _SeriesLikeCoef_co,
|
||||
y: _ArrayLikeCoef_co,
|
||||
deg: _SeriesLikeInt_co,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
rcond: None | _FloatLike_co = ...,
|
||||
full: Literal[False] = ...,
|
||||
w: None | _SeriesLikeCoef_co = ...,
|
||||
) -> _CoefArray: ...
|
||||
@overload
|
||||
def _fit(
|
||||
vander_f: _AnyVanderF,
|
||||
x: _SeriesLikeCoef_co,
|
||||
y: _SeriesLikeCoef_co,
|
||||
deg: _SeriesLikeInt_co,
|
||||
domain: None | _SeriesLikeCoef_co,
|
||||
rcond: None | _FloatLike_co ,
|
||||
full: Literal[True],
|
||||
/,
|
||||
w: None | _SeriesLikeCoef_co = ...,
|
||||
) -> tuple[_CoefSeries, Sequence[np.inexact[Any] | np.int32]]: ...
|
||||
@overload
|
||||
def _fit(
|
||||
vander_f: _AnyVanderF,
|
||||
x: _SeriesLikeCoef_co,
|
||||
y: _SeriesLikeCoef_co,
|
||||
deg: _SeriesLikeInt_co,
|
||||
domain: None | _SeriesLikeCoef_co = ...,
|
||||
rcond: None | _FloatLike_co = ...,
|
||||
*,
|
||||
full: Literal[True],
|
||||
w: None | _SeriesLikeCoef_co = ...,
|
||||
) -> tuple[_CoefSeries, Sequence[np.inexact[Any] | np.int32]]: ...
|
||||
|
||||
def _as_int(x: SupportsIndex, desc: str) -> int: ...
|
||||
def format_float(x: _FloatLike_co, parens: bool = ...) -> str: ...
|
@ -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,607 @@
|
||||
"""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.exceptions 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_call_with_list(Poly):
|
||||
p = Poly([1, 2, 3])
|
||||
x = [-1, 0, 2]
|
||||
res = p(x)
|
||||
assert_equal(res, p(np.array(x)))
|
||||
|
||||
|
||||
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,647 @@
|
||||
"""Tests for polynomial module.
|
||||
|
||||
"""
|
||||
from functools import reduce
|
||||
from fractions import Fraction
|
||||
import numpy as np
|
||||
import numpy.polynomial.polynomial as poly
|
||||
import numpy.polynomial.polyutils as pu
|
||||
import pickle
|
||||
from copy import deepcopy
|
||||
from numpy.testing import (
|
||||
assert_almost_equal, assert_raises, assert_equal, assert_,
|
||||
assert_array_equal, assert_raises_regex, assert_warns)
|
||||
|
||||
|
||||
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 TestFraction:
|
||||
|
||||
def test_Fraction(self):
|
||||
# assert we can use Polynomials with coefficients of object dtype
|
||||
f = Fraction(2, 3)
|
||||
one = Fraction(1, 1)
|
||||
zero = Fraction(0, 1)
|
||||
p = poly.Polynomial([f, f], domain=[zero, one], window=[zero, one])
|
||||
|
||||
x = 2 * p + p ** 2
|
||||
assert_equal(x.coef, np.array([Fraction(16, 9), Fraction(20, 9),
|
||||
Fraction(4, 9)], dtype=object))
|
||||
assert_equal(p.domain, [zero, one])
|
||||
assert_equal(p.coef.dtype, np.dtypes.ObjectDType())
|
||||
assert_(isinstance(p(f), Fraction))
|
||||
assert_equal(p(f), Fraction(10, 9))
|
||||
p_deriv = poly.Polynomial([Fraction(2, 3)], domain=[zero, one],
|
||||
window=[zero, one])
|
||||
assert_equal(p.deriv(), p_deriv)
|
||||
|
||||
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)
|
||||
assert_raises(TypeError, 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])
|
||||
|
||||
def test_fit_degenerate_domain(self):
|
||||
p = poly.Polynomial.fit([1], [2], deg=0)
|
||||
assert_equal(p.coef, [2.])
|
||||
p = poly.Polynomial.fit([1, 1], [2, 2.1], deg=0)
|
||||
assert_almost_equal(p.coef, [2.05])
|
||||
with assert_warns(pu.RankWarning):
|
||||
p = poly.Polynomial.fit([1, 1], [2, 2.1], deg=1)
|
||||
|
||||
def test_result_type(self):
|
||||
w = np.array([-1, 1], dtype=np.float32)
|
||||
p = np.polynomial.Polynomial(w, domain=w, window=w)
|
||||
v = p(2)
|
||||
assert_equal(v.dtype, np.float32)
|
||||
|
||||
arr = np.polydiv(1, np.float32(1))
|
||||
assert_equal(arr[0].dtype, np.float64)
|
@ -0,0 +1,125 @@
|
||||
"""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):
|
||||
tgt = [1]
|
||||
for num_trailing_zeros in range(5):
|
||||
res = pu.trimseq([1] + [0] * num_trailing_zeros)
|
||||
assert_equal(res, tgt)
|
||||
|
||||
def test_trimseq_empty_input(self):
|
||||
for empty_seq in [[], np.array([], dtype=np.int32)]:
|
||||
assert_equal(pu.trimseq(empty_seq), empty_seq)
|
||||
|
||||
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,552 @@
|
||||
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):
|
||||
p = poly.Polynomial(inp)
|
||||
res = str(p)
|
||||
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)
|
||||
|
||||
def test_polynomial_str_domains(self):
|
||||
res = str(poly.Polynomial([0, 1]))
|
||||
tgt = '0.0 + 1.0·x'
|
||||
assert_equal(res, tgt)
|
||||
|
||||
res = str(poly.Polynomial([0, 1], domain=[1, 2]))
|
||||
tgt = '0.0 + 1.0·(-3.0 + 2.0x)'
|
||||
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)
|
||||
|
||||
def test_polynomial_str_domains(self):
|
||||
res = str(poly.Polynomial([0, 1]))
|
||||
tgt = '0.0 + 1.0 x'
|
||||
assert_equal(res, tgt)
|
||||
|
||||
res = str(poly.Polynomial([0, 1], domain=[1, 2]))
|
||||
tgt = '0.0 + 1.0 (-3.0 + 2.0x)'
|
||||
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_repr(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_repr(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"""
|
||||
|
||||
@staticmethod
|
||||
def as_latex(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}$'
|
||||
),
|
||||
)
|
||||
|
||||
def test_numeric_object_coefficients(self):
|
||||
coefs = array([Fraction(1, 2), Fraction(1)])
|
||||
p = poly.Polynomial(coefs)
|
||||
assert_equal(self.as_latex(p), '$x \\mapsto 1/2 + 1\\,x$')
|
||||
|
||||
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')
|
Reference in New Issue
Block a user