diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2020-12-13 14:14:49 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-13 14:14:49 -0700 |
commit | 3fe2d9d2627fc0f84aeed293ff8afa7c1f08d899 (patch) | |
tree | 2ea27fe06a19c39e8d7a5fe2f87cb7e05363247d /numpy/polynomial | |
parent | 7d7e446fcbeeff70d905bde2eb0264a797488280 (diff) | |
parent | eff302e5e8678fa17fb3d8156d49eb585b0876d9 (diff) | |
download | numpy-3fe2d9d2627fc0f84aeed293ff8afa7c1f08d899.tar.gz |
Merge branch 'master' into fix-issue-10244
Diffstat (limited to 'numpy/polynomial')
-rw-r--r-- | numpy/polynomial/__init__.py | 101 | ||||
-rw-r--r-- | numpy/polynomial/__init__.pyi | 9 | ||||
-rw-r--r-- | numpy/polynomial/_polybase.py | 8 | ||||
-rw-r--r-- | numpy/polynomial/chebyshev.py | 32 | ||||
-rw-r--r-- | numpy/polynomial/hermite.py | 28 | ||||
-rw-r--r-- | numpy/polynomial/hermite_e.py | 30 | ||||
-rw-r--r-- | numpy/polynomial/laguerre.py | 30 | ||||
-rw-r--r-- | numpy/polynomial/legendre.py | 28 | ||||
-rw-r--r-- | numpy/polynomial/polynomial.py | 29 | ||||
-rw-r--r-- | numpy/polynomial/setup.py | 1 | ||||
-rw-r--r-- | numpy/polynomial/tests/test_printing.py | 13 |
11 files changed, 256 insertions, 53 deletions
diff --git a/numpy/polynomial/__init__.py b/numpy/polynomial/__init__.py index 43b2caba3..c832094e2 100644 --- a/numpy/polynomial/__init__.py +++ b/numpy/polynomial/__init__.py @@ -12,6 +12,107 @@ 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 Power series + Chebyshev Chebyshev series + Legendre Legendre series + Laguerre Laguerre series + Hermite Hermite series + HermiteE HermiteE series + ============ ================ + +These *convenience classes* provide a consistent interface for creating, +manipulating, and fitting data with polynomials of different bases. +The convenience classes are the preferred interface for the `~numpy.polynomial` +package, and are available from the `numpy.polynomial` namespace. +This eliminates the need to +navigate to the corresponding submodules, e.g. ``np.polynomial.Polynomial`` +or ``np.polynomial.Chebyshev`` instead of +``np.polynomial.polynomial.Polynomial`` or +``np.polynomial.chebyshev.Chebyshev``, respectively. +The classes provide a more consistent and concise interface than the +type-specific functions defined in the submodules for each type of polynomial. +For example, to fit a Chebyshev polynomial with degree ``1`` to data given +by arrays ``xdata`` and ``ydata``, the +`~chebyshev.Chebyshev.fit` class method:: + + >>> from numpy.polynomial import Chebyshev + >>> c = Chebyshev.fit(xdata, ydata, deg=1) + +is preferred over the `chebyshev.chebfit` function from the +`numpy.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``, ``Chebyshev``, ``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 diff --git a/numpy/polynomial/__init__.pyi b/numpy/polynomial/__init__.pyi new file mode 100644 index 000000000..817ba22ac --- /dev/null +++ b/numpy/polynomial/__init__.pyi @@ -0,0 +1,9 @@ +from typing import Any + +Polynomial: Any +Chebyshev: Any +Legendre: Any +Hermite: Any +HermiteE: Any +Laguerre: Any +set_default_printstyle: Any diff --git a/numpy/polynomial/_polybase.py b/numpy/polynomial/_polybase.py index f4a67a222..59c380f10 100644 --- a/numpy/polynomial/_polybase.py +++ b/numpy/polynomial/_polybase.py @@ -547,8 +547,8 @@ class ABCPolyBase(abc.ABC): othercoef = self._get_coefficients(other) try: quo, rem = self._div(self.coef, othercoef) - except ZeroDivisionError as e: - raise e + except ZeroDivisionError: + raise except Exception: return NotImplemented quo = self.__class__(quo, self.domain, self.window) @@ -605,8 +605,8 @@ class ABCPolyBase(abc.ABC): def __rdivmod__(self, other): try: quo, rem = self._div(other, self.coef) - except ZeroDivisionError as e: - raise e + except ZeroDivisionError: + raise except Exception: return NotImplemented quo = self.__class__(quo, self.domain, self.window) diff --git a/numpy/polynomial/chebyshev.py b/numpy/polynomial/chebyshev.py index d99fd98f5..6745c9371 100644 --- a/numpy/polynomial/chebyshev.py +++ b/numpy/polynomial/chebyshev.py @@ -477,8 +477,6 @@ def chebline(off, scl): """ Chebyshev series whose graph is a straight line. - - Parameters ---------- off, scl : scalars @@ -492,7 +490,11 @@ def chebline(off, scl): See Also -------- - polyline + numpy.polynomial.polynomial.polyline + numpy.polynomial.legendre.legline + numpy.polynomial.laguerre.lagline + numpy.polynomial.hermite.hermline + numpy.polynomial.hermite_e.hermeline Examples -------- @@ -545,7 +547,11 @@ def chebfromroots(roots): See Also -------- - polyfromroots, legfromroots, lagfromroots, hermfromroots, hermefromroots + numpy.polynomial.polynomial.polyfromroots + numpy.polynomial.legendre.legfromroots + numpy.polynomial.laguerre.lagfromroots + numpy.polynomial.hermite.hermfromroots + numpy.polynomial.hermite_e.hermefromroots Examples -------- @@ -764,7 +770,7 @@ def chebdiv(c1, c2): See Also -------- - chebadd, chebsub, chemulx, chebmul, chebpow + chebadd, chebsub, chebmulx, chebmul, chebpow Notes ----- @@ -1601,7 +1607,7 @@ def chebfit(x, y, deg, rcond=None, full=False, w=None): sv -- singular values of the scaled Vandermonde matrix rcond -- value of `rcond`. - For more details, see `linalg.lstsq`. + For more details, see `numpy.linalg.lstsq`. Warns ----- @@ -1615,11 +1621,15 @@ def chebfit(x, y, deg, rcond=None, full=False, w=None): See Also -------- - polyfit, legfit, lagfit, hermfit, hermefit + numpy.polynomial.polynomial.polyfit + numpy.polynomial.legendre.legfit + numpy.polynomial.laguerre.lagfit + numpy.polynomial.hermite.hermfit + numpy.polynomial.hermite_e.hermefit chebval : Evaluates a Chebyshev series. chebvander : Vandermonde matrix of Chebyshev series. chebweight : Chebyshev weight function. - linalg.lstsq : Computes a least-squares fit from the matrix. + numpy.linalg.lstsq : Computes a least-squares fit from the matrix. scipy.interpolate.UnivariateSpline : Computes spline fits. Notes @@ -1729,7 +1739,11 @@ def chebroots(c): See Also -------- - polyroots, legroots, lagroots, hermroots, hermeroots + numpy.polynomial.polynomial.polyroots + numpy.polynomial.legendre.legroots + numpy.polynomial.laguerre.lagroots + numpy.polynomial.hermite.hermroots + numpy.polynomial.hermite_e.hermeroots Notes ----- diff --git a/numpy/polynomial/hermite.py b/numpy/polynomial/hermite.py index 280cad39e..c679c5298 100644 --- a/numpy/polynomial/hermite.py +++ b/numpy/polynomial/hermite.py @@ -233,7 +233,11 @@ def hermline(off, scl): See Also -------- - polyline, chebline + numpy.polynomial.polynomial.polyline + numpy.polynomial.chebyshev.chebline + numpy.polynomial.legendre.legline + numpy.polynomial.laguerre.lagline + numpy.polynomial.hermite_e.hermeline Examples -------- @@ -286,7 +290,11 @@ def hermfromroots(roots): See Also -------- - polyfromroots, legfromroots, lagfromroots, chebfromroots, hermefromroots + numpy.polynomial.polynomial.polyfromroots + numpy.polynomial.legendre.legfromroots + numpy.polynomial.laguerre.lagfromroots + numpy.polynomial.chebyshev.chebfromroots + numpy.polynomial.hermite_e.hermefromroots Examples -------- @@ -1322,7 +1330,7 @@ def hermfit(x, y, deg, rcond=None, full=False, w=None): sv -- singular values of the scaled Vandermonde matrix rcond -- value of `rcond`. - For more details, see `linalg.lstsq`. + For more details, see `numpy.linalg.lstsq`. Warns ----- @@ -1336,11 +1344,15 @@ def hermfit(x, y, deg, rcond=None, full=False, w=None): See Also -------- - chebfit, legfit, lagfit, polyfit, hermefit + numpy.polynomial.chebyshev.chebfit + numpy.polynomial.legendre.legfit + numpy.polynomial.laguerre.lagfit + numpy.polynomial.polynomial.polyfit + numpy.polynomial.hermite_e.hermefit hermval : Evaluates a Hermite series. hermvander : Vandermonde matrix of Hermite series. hermweight : Hermite weight function - linalg.lstsq : Computes a least-squares fit from the matrix. + numpy.linalg.lstsq : Computes a least-squares fit from the matrix. scipy.interpolate.UnivariateSpline : Computes spline fits. Notes @@ -1457,7 +1469,11 @@ def hermroots(c): See Also -------- - polyroots, legroots, lagroots, chebroots, hermeroots + numpy.polynomial.polynomial.polyroots + numpy.polynomial.legendre.legroots + numpy.polynomial.laguerre.lagroots + numpy.polynomial.chebyshev.chebroots + numpy.polynomial.hermite_e.hermeroots Notes ----- diff --git a/numpy/polynomial/hermite_e.py b/numpy/polynomial/hermite_e.py index 9b3b25105..1ce8ebe04 100644 --- a/numpy/polynomial/hermite_e.py +++ b/numpy/polynomial/hermite_e.py @@ -218,8 +218,6 @@ def hermeline(off, scl): """ Hermite series whose graph is a straight line. - - Parameters ---------- off, scl : scalars @@ -233,7 +231,11 @@ def hermeline(off, scl): See Also -------- - polyline, chebline + numpy.polynomial.polynomial.polyline + numpy.polynomial.chebyshev.chebline + numpy.polynomial.legendre.legline + numpy.polynomial.laguerre.lagline + numpy.polynomial.hermite.hermline Examples -------- @@ -287,7 +289,11 @@ def hermefromroots(roots): See Also -------- - polyfromroots, legfromroots, lagfromroots, hermfromroots, chebfromroots + numpy.polynomial.polynomial.polyfromroots + numpy.polynomial.legendre.legfromroots + numpy.polynomial.laguerre.lagfromroots + numpy.polynomial.hermite.hermfromroots + numpy.polynomial.chebyshev.chebfromroots Examples -------- @@ -1315,7 +1321,7 @@ def hermefit(x, y, deg, rcond=None, full=False, w=None): sv -- singular values of the scaled Vandermonde matrix rcond -- value of `rcond`. - For more details, see `linalg.lstsq`. + For more details, see `numpy.linalg.lstsq`. Warns ----- @@ -1329,11 +1335,15 @@ def hermefit(x, y, deg, rcond=None, full=False, w=None): See Also -------- - chebfit, legfit, polyfit, hermfit, polyfit + numpy.polynomial.chebyshev.chebfit + numpy.polynomial.legendre.legfit + numpy.polynomial.polynomial.polyfit + numpy.polynomial.hermite.hermfit + numpy.polynomial.laguerre.lagfit hermeval : Evaluates a Hermite series. hermevander : pseudo Vandermonde matrix of Hermite series. hermeweight : HermiteE weight function. - linalg.lstsq : Computes a least-squares fit from the matrix. + numpy.linalg.lstsq : Computes a least-squares fit from the matrix. scipy.interpolate.UnivariateSpline : Computes spline fits. Notes @@ -1452,7 +1462,11 @@ def hermeroots(c): See Also -------- - polyroots, legroots, lagroots, hermroots, chebroots + numpy.polynomial.polynomial.polyroots + numpy.polynomial.legendre.legroots + numpy.polynomial.laguerre.lagroots + numpy.polynomial.hermite.hermroots + numpy.polynomial.chebyshev.chebroots Notes ----- diff --git a/numpy/polynomial/laguerre.py b/numpy/polynomial/laguerre.py index c1db13215..9cff0b71c 100644 --- a/numpy/polynomial/laguerre.py +++ b/numpy/polynomial/laguerre.py @@ -214,8 +214,6 @@ def lagline(off, scl): """ Laguerre series whose graph is a straight line. - - Parameters ---------- off, scl : scalars @@ -229,7 +227,11 @@ def lagline(off, scl): See Also -------- - polyline, chebline + numpy.polynomial.polynomial.polyline + numpy.polynomial.chebyshev.chebline + numpy.polynomial.legendre.legline + numpy.polynomial.hermite.hermline + numpy.polynomial.hermite_e.hermeline Examples -------- @@ -282,7 +284,11 @@ def lagfromroots(roots): See Also -------- - polyfromroots, legfromroots, chebfromroots, hermfromroots, hermefromroots + numpy.polynomial.polynomial.polyfromroots + numpy.polynomial.legendre.legfromroots + numpy.polynomial.chebyshev.chebfromroots + numpy.polynomial.hermite.hermfromroots + numpy.polynomial.hermite_e.hermefromroots Examples -------- @@ -1321,7 +1327,7 @@ def lagfit(x, y, deg, rcond=None, full=False, w=None): sv -- singular values of the scaled Vandermonde matrix rcond -- value of `rcond`. - For more details, see `linalg.lstsq`. + For more details, see `numpy.linalg.lstsq`. Warns ----- @@ -1335,11 +1341,15 @@ def lagfit(x, y, deg, rcond=None, full=False, w=None): See Also -------- - chebfit, legfit, polyfit, hermfit, hermefit + numpy.polynomial.polynomial.polyfit + numpy.polynomial.legendre.legfit + numpy.polynomial.chebyshev.chebfit + numpy.polynomial.hermite.hermfit + numpy.polynomial.hermite_e.hermefit lagval : Evaluates a Laguerre series. lagvander : pseudo Vandermonde matrix of Laguerre series. lagweight : Laguerre weight function. - linalg.lstsq : Computes a least-squares fit from the matrix. + numpy.linalg.lstsq : Computes a least-squares fit from the matrix. scipy.interpolate.UnivariateSpline : Computes spline fits. Notes @@ -1455,7 +1465,11 @@ def lagroots(c): See Also -------- - polyroots, legroots, chebroots, hermroots, hermeroots + numpy.polynomial.polynomial.polyroots + numpy.polynomial.legendre.legroots + numpy.polynomial.chebyshev.chebroots + numpy.polynomial.hermite.hermroots + numpy.polynomial.hermite_e.hermeroots Notes ----- diff --git a/numpy/polynomial/legendre.py b/numpy/polynomial/legendre.py index 7b5b665f2..427f9f82f 100644 --- a/numpy/polynomial/legendre.py +++ b/numpy/polynomial/legendre.py @@ -243,7 +243,11 @@ def legline(off, scl): See Also -------- - polyline, chebline + numpy.polynomial.polynomial.polyline + numpy.polynomial.chebyshev.chebline + numpy.polynomial.laguerre.lagline + numpy.polynomial.hermite.hermline + numpy.polynomial.hermite_e.hermeline Examples -------- @@ -296,7 +300,11 @@ def legfromroots(roots): See Also -------- - polyfromroots, chebfromroots, lagfromroots, hermfromroots, hermefromroots + numpy.polynomial.polynomial.polyfromroots + numpy.polynomial.chebyshev.chebfromroots + numpy.polynomial.laguerre.lagfromroots + numpy.polynomial.hermite.hermfromroots + numpy.polynomial.hermite_e.hermefromroots Examples -------- @@ -1343,7 +1351,7 @@ def legfit(x, y, deg, rcond=None, full=False, w=None): sv -- singular values of the scaled Vandermonde matrix rcond -- value of `rcond`. - For more details, see `linalg.lstsq`. + For more details, see `numpy.linalg.lstsq`. Warns ----- @@ -1357,11 +1365,15 @@ def legfit(x, y, deg, rcond=None, full=False, w=None): See Also -------- - chebfit, polyfit, lagfit, hermfit, hermefit + numpy.polynomial.polynomial.polyfit + numpy.polynomial.chebyshev.chebfit + numpy.polynomial.laguerre.lagfit + numpy.polynomial.hermite.hermfit + numpy.polynomial.hermite_e.hermefit legval : Evaluates a Legendre series. legvander : Vandermonde matrix of Legendre series. legweight : Legendre weight function (= 1). - linalg.lstsq : Computes a least-squares fit from the matrix. + numpy.linalg.lstsq : Computes a least-squares fit from the matrix. scipy.interpolate.UnivariateSpline : Computes spline fits. Notes @@ -1470,7 +1482,11 @@ def legroots(c): See Also -------- - polyroots, chebroots, lagroots, hermroots, hermeroots + numpy.polynomial.polynomial.polyroots + numpy.polynomial.chebyshev.chebroots + numpy.polynomial.laguerre.lagroots + numpy.polynomial.hermite.hermroots + numpy.polynomial.hermite_e.hermeroots Notes ----- diff --git a/numpy/polynomial/polynomial.py b/numpy/polynomial/polynomial.py index 83693441f..1baa7d870 100644 --- a/numpy/polynomial/polynomial.py +++ b/numpy/polynomial/polynomial.py @@ -127,7 +127,11 @@ def polyline(off, scl): See Also -------- - chebline + numpy.polynomial.chebyshev.chebline + numpy.polynomial.legendre.legline + numpy.polynomial.laguerre.lagline + numpy.polynomial.hermite.hermline + numpy.polynomial.hermite_e.hermeline Examples -------- @@ -179,8 +183,11 @@ def polyfromroots(roots): See Also -------- - chebfromroots, legfromroots, lagfromroots, hermfromroots - hermefromroots + numpy.polynomial.chebyshev.chebfromroots + numpy.polynomial.legendre.legfromroots + numpy.polynomial.laguerre.lagfromroots + numpy.polynomial.hermite.hermfromroots + numpy.polynomial.hermite_e.hermefromroots Notes ----- @@ -1267,7 +1274,7 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None): sv -- singular values of the scaled Vandermonde matrix rcond -- value of `rcond`. - For more details, see `linalg.lstsq`. + For more details, see `numpy.linalg.lstsq`. Raises ------ @@ -1281,10 +1288,14 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None): See Also -------- - chebfit, legfit, lagfit, hermfit, hermefit + numpy.polynomial.chebyshev.chebfit + numpy.polynomial.legendre.legfit + numpy.polynomial.laguerre.lagfit + numpy.polynomial.hermite.hermfit + numpy.polynomial.hermite_e.hermefit polyval : Evaluates a polynomial. polyvander : Vandermonde matrix for powers. - linalg.lstsq : Computes a least-squares fit from the matrix. + numpy.linalg.lstsq : Computes a least-squares fit from the matrix. scipy.interpolate.UnivariateSpline : Computes spline fits. Notes @@ -1411,7 +1422,11 @@ def polyroots(c): See Also -------- - chebroots + numpy.polynomial.chebyshev.chebroots + numpy.polynomial.legendre.legroots + numpy.polynomial.laguerre.lagroots + numpy.polynomial.hermite.hermroots + numpy.polynomial.hermite_e.hermeroots Notes ----- diff --git a/numpy/polynomial/setup.py b/numpy/polynomial/setup.py index 641464518..b58e867a1 100644 --- a/numpy/polynomial/setup.py +++ b/numpy/polynomial/setup.py @@ -2,6 +2,7 @@ def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration config = Configuration('polynomial', parent_package, top_path) config.add_subpackage('tests') + config.add_data_files('*.pyi') return config if __name__ == '__main__': diff --git a/numpy/polynomial/tests/test_printing.py b/numpy/polynomial/tests/test_printing.py index 27a8ab9f2..4e9902a69 100644 --- a/numpy/polynomial/tests/test_printing.py +++ b/numpy/polynomial/tests/test_printing.py @@ -85,7 +85,7 @@ class TestStrUnicodeSuperSubscripts: class TestStrAscii: @pytest.fixture(scope='class', autouse=True) - def use_unicode(self): + def use_ascii(self): poly.set_default_printstyle('ascii') @pytest.mark.parametrize(('inp', 'tgt'), ( @@ -161,7 +161,10 @@ class TestStrAscii: class TestLinebreaking: - poly.set_default_printstyle('ascii') + + @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) @@ -283,19 +286,19 @@ def test_nonnumeric_object_coefficients(coefs, tgt): class TestFormat: def test_format_unicode(self): - poly.Polynomial._use_unicode = False + 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.Polynomial._use_unicode = True + poly.set_default_printstyle('unicode') p = poly.Polynomial([1, 2, 0, -1]) assert_equal( format(p, 'ascii'), "1.0 + 2.0 x**1 + 0.0 x**2 - 1.0 x**3" ) def test_empty_formatstr(self): - poly.Polynomial._use_unicode = False + poly.set_default_printstyle('ascii') p = poly.Polynomial([1, 2, 3]) assert_equal(format(p), "1.0 + 2.0 x**1 + 3.0 x**2") assert_equal(f"{p}", "1.0 + 2.0 x**1 + 3.0 x**2") |