Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/numpy/polynomial/polynomial.py: 19%
221 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1"""
2=================================================
3Power Series (:mod:`numpy.polynomial.polynomial`)
4=================================================
6This module provides a number of objects (mostly functions) useful for
7dealing with polynomials, including a `Polynomial` class that
8encapsulates the usual arithmetic operations. (General information
9on how this module represents and works with polynomial objects is in
10the docstring for its "parent" sub-package, `numpy.polynomial`).
12Classes
13-------
14.. autosummary::
15 :toctree: generated/
17 Polynomial
19Constants
20---------
21.. autosummary::
22 :toctree: generated/
24 polydomain
25 polyzero
26 polyone
27 polyx
29Arithmetic
30----------
31.. autosummary::
32 :toctree: generated/
34 polyadd
35 polysub
36 polymulx
37 polymul
38 polydiv
39 polypow
40 polyval
41 polyval2d
42 polyval3d
43 polygrid2d
44 polygrid3d
46Calculus
47--------
48.. autosummary::
49 :toctree: generated/
51 polyder
52 polyint
54Misc Functions
55--------------
56.. autosummary::
57 :toctree: generated/
59 polyfromroots
60 polyroots
61 polyvalfromroots
62 polyvander
63 polyvander2d
64 polyvander3d
65 polycompanion
66 polyfit
67 polytrim
68 polyline
70See Also
71--------
72`numpy.polynomial`
74"""
75__all__ = [
76 'polyzero', 'polyone', 'polyx', 'polydomain', 'polyline', 'polyadd',
77 'polysub', 'polymulx', 'polymul', 'polydiv', 'polypow', 'polyval',
78 'polyvalfromroots', 'polyder', 'polyint', 'polyfromroots', 'polyvander',
79 'polyfit', 'polytrim', 'polyroots', 'Polynomial', 'polyval2d', 'polyval3d',
80 'polygrid2d', 'polygrid3d', 'polyvander2d', 'polyvander3d']
82import numpy as np
83import numpy.linalg as la
84from numpy.core.multiarray import normalize_axis_index
86from . import polyutils as pu
87from ._polybase import ABCPolyBase
89polytrim = pu.trimcoef
91#
92# These are constant arrays are of integer type so as to be compatible
93# with the widest range of other types, such as Decimal.
94#
96# Polynomial default domain.
97polydomain = np.array([-1, 1])
99# Polynomial coefficients representing zero.
100polyzero = np.array([0])
102# Polynomial coefficients representing one.
103polyone = np.array([1])
105# Polynomial coefficients representing the identity x.
106polyx = np.array([0, 1])
108#
109# Polynomial series functions
110#
113def polyline(off, scl):
114 """
115 Returns an array representing a linear polynomial.
117 Parameters
118 ----------
119 off, scl : scalars
120 The "y-intercept" and "slope" of the line, respectively.
122 Returns
123 -------
124 y : ndarray
125 This module's representation of the linear polynomial ``off +
126 scl*x``.
128 See Also
129 --------
130 numpy.polynomial.chebyshev.chebline
131 numpy.polynomial.legendre.legline
132 numpy.polynomial.laguerre.lagline
133 numpy.polynomial.hermite.hermline
134 numpy.polynomial.hermite_e.hermeline
136 Examples
137 --------
138 >>> from numpy.polynomial import polynomial as P
139 >>> P.polyline(1,-1)
140 array([ 1, -1])
141 >>> P.polyval(1, P.polyline(1,-1)) # should be 0
142 0.0
144 """
145 if scl != 0:
146 return np.array([off, scl])
147 else:
148 return np.array([off])
151def polyfromroots(roots):
152 """
153 Generate a monic polynomial with given roots.
155 Return the coefficients of the polynomial
157 .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
159 where the ``r_n`` are the roots specified in `roots`. If a zero has
160 multiplicity n, then it must appear in `roots` n times. For instance,
161 if 2 is a root of multiplicity three and 3 is a root of multiplicity 2,
162 then `roots` looks something like [2, 2, 2, 3, 3]. The roots can appear
163 in any order.
165 If the returned coefficients are `c`, then
167 .. math:: p(x) = c_0 + c_1 * x + ... + x^n
169 The coefficient of the last term is 1 for monic polynomials in this
170 form.
172 Parameters
173 ----------
174 roots : array_like
175 Sequence containing the roots.
177 Returns
178 -------
179 out : ndarray
180 1-D array of the polynomial's coefficients If all the roots are
181 real, then `out` is also real, otherwise it is complex. (see
182 Examples below).
184 See Also
185 --------
186 numpy.polynomial.chebyshev.chebfromroots
187 numpy.polynomial.legendre.legfromroots
188 numpy.polynomial.laguerre.lagfromroots
189 numpy.polynomial.hermite.hermfromroots
190 numpy.polynomial.hermite_e.hermefromroots
192 Notes
193 -----
194 The coefficients are determined by multiplying together linear factors
195 of the form ``(x - r_i)``, i.e.
197 .. math:: p(x) = (x - r_0) (x - r_1) ... (x - r_n)
199 where ``n == len(roots) - 1``; note that this implies that ``1`` is always
200 returned for :math:`a_n`.
202 Examples
203 --------
204 >>> from numpy.polynomial import polynomial as P
205 >>> P.polyfromroots((-1,0,1)) # x(x - 1)(x + 1) = x^3 - x
206 array([ 0., -1., 0., 1.])
207 >>> j = complex(0,1)
208 >>> P.polyfromroots((-j,j)) # complex returned, though values are real
209 array([1.+0.j, 0.+0.j, 1.+0.j])
211 """
212 return pu._fromroots(polyline, polymul, roots)
215def polyadd(c1, c2):
216 """
217 Add one polynomial to another.
219 Returns the sum of two polynomials `c1` + `c2`. The arguments are
220 sequences of coefficients from lowest order term to highest, i.e.,
221 [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
223 Parameters
224 ----------
225 c1, c2 : array_like
226 1-D arrays of polynomial coefficients ordered from low to high.
228 Returns
229 -------
230 out : ndarray
231 The coefficient array representing their sum.
233 See Also
234 --------
235 polysub, polymulx, polymul, polydiv, polypow
237 Examples
238 --------
239 >>> from numpy.polynomial import polynomial as P
240 >>> c1 = (1,2,3)
241 >>> c2 = (3,2,1)
242 >>> sum = P.polyadd(c1,c2); sum
243 array([4., 4., 4.])
244 >>> P.polyval(2, sum) # 4 + 4(2) + 4(2**2)
245 28.0
247 """
248 return pu._add(c1, c2)
251def polysub(c1, c2):
252 """
253 Subtract one polynomial from another.
255 Returns the difference of two polynomials `c1` - `c2`. The arguments
256 are sequences of coefficients from lowest order term to highest, i.e.,
257 [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
259 Parameters
260 ----------
261 c1, c2 : array_like
262 1-D arrays of polynomial coefficients ordered from low to
263 high.
265 Returns
266 -------
267 out : ndarray
268 Of coefficients representing their difference.
270 See Also
271 --------
272 polyadd, polymulx, polymul, polydiv, polypow
274 Examples
275 --------
276 >>> from numpy.polynomial import polynomial as P
277 >>> c1 = (1,2,3)
278 >>> c2 = (3,2,1)
279 >>> P.polysub(c1,c2)
280 array([-2., 0., 2.])
281 >>> P.polysub(c2,c1) # -P.polysub(c1,c2)
282 array([ 2., 0., -2.])
284 """
285 return pu._sub(c1, c2)
288def polymulx(c):
289 """Multiply a polynomial by x.
291 Multiply the polynomial `c` by x, where x is the independent
292 variable.
295 Parameters
296 ----------
297 c : array_like
298 1-D array of polynomial coefficients ordered from low to
299 high.
301 Returns
302 -------
303 out : ndarray
304 Array representing the result of the multiplication.
306 See Also
307 --------
308 polyadd, polysub, polymul, polydiv, polypow
310 Notes
311 -----
313 .. versionadded:: 1.5.0
315 """
316 # c is a trimmed copy
317 [c] = pu.as_series([c])
318 # The zero series needs special treatment
319 if len(c) == 1 and c[0] == 0:
320 return c
322 prd = np.empty(len(c) + 1, dtype=c.dtype)
323 prd[0] = c[0]*0
324 prd[1:] = c
325 return prd
328def polymul(c1, c2):
329 """
330 Multiply one polynomial by another.
332 Returns the product of two polynomials `c1` * `c2`. The arguments are
333 sequences of coefficients, from lowest order term to highest, e.g.,
334 [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2.``
336 Parameters
337 ----------
338 c1, c2 : array_like
339 1-D arrays of coefficients representing a polynomial, relative to the
340 "standard" basis, and ordered from lowest order term to highest.
342 Returns
343 -------
344 out : ndarray
345 Of the coefficients of their product.
347 See Also
348 --------
349 polyadd, polysub, polymulx, polydiv, polypow
351 Examples
352 --------
353 >>> from numpy.polynomial import polynomial as P
354 >>> c1 = (1,2,3)
355 >>> c2 = (3,2,1)
356 >>> P.polymul(c1,c2)
357 array([ 3., 8., 14., 8., 3.])
359 """
360 # c1, c2 are trimmed copies
361 [c1, c2] = pu.as_series([c1, c2])
362 ret = np.convolve(c1, c2)
363 return pu.trimseq(ret)
366def polydiv(c1, c2):
367 """
368 Divide one polynomial by another.
370 Returns the quotient-with-remainder of two polynomials `c1` / `c2`.
371 The arguments are sequences of coefficients, from lowest order term
372 to highest, e.g., [1,2,3] represents ``1 + 2*x + 3*x**2``.
374 Parameters
375 ----------
376 c1, c2 : array_like
377 1-D arrays of polynomial coefficients ordered from low to high.
379 Returns
380 -------
381 [quo, rem] : ndarrays
382 Of coefficient series representing the quotient and remainder.
384 See Also
385 --------
386 polyadd, polysub, polymulx, polymul, polypow
388 Examples
389 --------
390 >>> from numpy.polynomial import polynomial as P
391 >>> c1 = (1,2,3)
392 >>> c2 = (3,2,1)
393 >>> P.polydiv(c1,c2)
394 (array([3.]), array([-8., -4.]))
395 >>> P.polydiv(c2,c1)
396 (array([ 0.33333333]), array([ 2.66666667, 1.33333333])) # may vary
398 """
399 # c1, c2 are trimmed copies
400 [c1, c2] = pu.as_series([c1, c2])
401 if c2[-1] == 0:
402 raise ZeroDivisionError()
404 # note: this is more efficient than `pu._div(polymul, c1, c2)`
405 lc1 = len(c1)
406 lc2 = len(c2)
407 if lc1 < lc2:
408 return c1[:1]*0, c1
409 elif lc2 == 1:
410 return c1/c2[-1], c1[:1]*0
411 else:
412 dlen = lc1 - lc2
413 scl = c2[-1]
414 c2 = c2[:-1]/scl
415 i = dlen
416 j = lc1 - 1
417 while i >= 0:
418 c1[i:j] -= c2*c1[j]
419 i -= 1
420 j -= 1
421 return c1[j+1:]/scl, pu.trimseq(c1[:j+1])
424def polypow(c, pow, maxpower=None):
425 """Raise a polynomial to a power.
427 Returns the polynomial `c` raised to the power `pow`. The argument
428 `c` is a sequence of coefficients ordered from low to high. i.e.,
429 [1,2,3] is the series ``1 + 2*x + 3*x**2.``
431 Parameters
432 ----------
433 c : array_like
434 1-D array of array of series coefficients ordered from low to
435 high degree.
436 pow : integer
437 Power to which the series will be raised
438 maxpower : integer, optional
439 Maximum power allowed. This is mainly to limit growth of the series
440 to unmanageable size. Default is 16
442 Returns
443 -------
444 coef : ndarray
445 Power series of power.
447 See Also
448 --------
449 polyadd, polysub, polymulx, polymul, polydiv
451 Examples
452 --------
453 >>> from numpy.polynomial import polynomial as P
454 >>> P.polypow([1,2,3], 2)
455 array([ 1., 4., 10., 12., 9.])
457 """
458 # note: this is more efficient than `pu._pow(polymul, c1, c2)`, as it
459 # avoids calling `as_series` repeatedly
460 return pu._pow(np.convolve, c, pow, maxpower)
463def polyder(c, m=1, scl=1, axis=0):
464 """
465 Differentiate a polynomial.
467 Returns the polynomial coefficients `c` differentiated `m` times along
468 `axis`. At each iteration the result is multiplied by `scl` (the
469 scaling factor is for use in a linear change of variable). The
470 argument `c` is an array of coefficients from low to high degree along
471 each axis, e.g., [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``
472 while [[1,2],[1,2]] represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is
473 ``x`` and axis=1 is ``y``.
475 Parameters
476 ----------
477 c : array_like
478 Array of polynomial coefficients. If c is multidimensional the
479 different axis correspond to different variables with the degree
480 in each axis given by the corresponding index.
481 m : int, optional
482 Number of derivatives taken, must be non-negative. (Default: 1)
483 scl : scalar, optional
484 Each differentiation is multiplied by `scl`. The end result is
485 multiplication by ``scl**m``. This is for use in a linear change
486 of variable. (Default: 1)
487 axis : int, optional
488 Axis over which the derivative is taken. (Default: 0).
490 .. versionadded:: 1.7.0
492 Returns
493 -------
494 der : ndarray
495 Polynomial coefficients of the derivative.
497 See Also
498 --------
499 polyint
501 Examples
502 --------
503 >>> from numpy.polynomial import polynomial as P
504 >>> c = (1,2,3,4) # 1 + 2x + 3x**2 + 4x**3
505 >>> P.polyder(c) # (d/dx)(c) = 2 + 6x + 12x**2
506 array([ 2., 6., 12.])
507 >>> P.polyder(c,3) # (d**3/dx**3)(c) = 24
508 array([24.])
509 >>> P.polyder(c,scl=-1) # (d/d(-x))(c) = -2 - 6x - 12x**2
510 array([ -2., -6., -12.])
511 >>> P.polyder(c,2,-1) # (d**2/d(-x)**2)(c) = 6 + 24x
512 array([ 6., 24.])
514 """
515 c = np.array(c, ndmin=1, copy=True)
516 if c.dtype.char in '?bBhHiIlLqQpP':
517 # astype fails with NA
518 c = c + 0.0
519 cdt = c.dtype
520 cnt = pu._deprecate_as_int(m, "the order of derivation")
521 iaxis = pu._deprecate_as_int(axis, "the axis")
522 if cnt < 0:
523 raise ValueError("The order of derivation must be non-negative")
524 iaxis = normalize_axis_index(iaxis, c.ndim)
526 if cnt == 0:
527 return c
529 c = np.moveaxis(c, iaxis, 0)
530 n = len(c)
531 if cnt >= n:
532 c = c[:1]*0
533 else:
534 for i in range(cnt):
535 n = n - 1
536 c *= scl
537 der = np.empty((n,) + c.shape[1:], dtype=cdt)
538 for j in range(n, 0, -1):
539 der[j - 1] = j*c[j]
540 c = der
541 c = np.moveaxis(c, 0, iaxis)
542 return c
545def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
546 """
547 Integrate a polynomial.
549 Returns the polynomial coefficients `c` integrated `m` times from
550 `lbnd` along `axis`. At each iteration the resulting series is
551 **multiplied** by `scl` and an integration constant, `k`, is added.
552 The scaling factor is for use in a linear change of variable. ("Buyer
553 beware": note that, depending on what one is doing, one may want `scl`
554 to be the reciprocal of what one might expect; for more information,
555 see the Notes section below.) The argument `c` is an array of
556 coefficients, from low to high degree along each axis, e.g., [1,2,3]
557 represents the polynomial ``1 + 2*x + 3*x**2`` while [[1,2],[1,2]]
558 represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is ``x`` and axis=1 is
559 ``y``.
561 Parameters
562 ----------
563 c : array_like
564 1-D array of polynomial coefficients, ordered from low to high.
565 m : int, optional
566 Order of integration, must be positive. (Default: 1)
567 k : {[], list, scalar}, optional
568 Integration constant(s). The value of the first integral at zero
569 is the first value in the list, the value of the second integral
570 at zero is the second value, etc. If ``k == []`` (the default),
571 all constants are set to zero. If ``m == 1``, a single scalar can
572 be given instead of a list.
573 lbnd : scalar, optional
574 The lower bound of the integral. (Default: 0)
575 scl : scalar, optional
576 Following each integration the result is *multiplied* by `scl`
577 before the integration constant is added. (Default: 1)
578 axis : int, optional
579 Axis over which the integral is taken. (Default: 0).
581 .. versionadded:: 1.7.0
583 Returns
584 -------
585 S : ndarray
586 Coefficient array of the integral.
588 Raises
589 ------
590 ValueError
591 If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
592 ``np.ndim(scl) != 0``.
594 See Also
595 --------
596 polyder
598 Notes
599 -----
600 Note that the result of each integration is *multiplied* by `scl`. Why
601 is this important to note? Say one is making a linear change of
602 variable :math:`u = ax + b` in an integral relative to `x`. Then
603 :math:`dx = du/a`, so one will need to set `scl` equal to
604 :math:`1/a` - perhaps not what one would have first thought.
606 Examples
607 --------
608 >>> from numpy.polynomial import polynomial as P
609 >>> c = (1,2,3)
610 >>> P.polyint(c) # should return array([0, 1, 1, 1])
611 array([0., 1., 1., 1.])
612 >>> P.polyint(c,3) # should return array([0, 0, 0, 1/6, 1/12, 1/20])
613 array([ 0. , 0. , 0. , 0.16666667, 0.08333333, # may vary
614 0.05 ])
615 >>> P.polyint(c,k=3) # should return array([3, 1, 1, 1])
616 array([3., 1., 1., 1.])
617 >>> P.polyint(c,lbnd=-2) # should return array([6, 1, 1, 1])
618 array([6., 1., 1., 1.])
619 >>> P.polyint(c,scl=-2) # should return array([0, -2, -2, -2])
620 array([ 0., -2., -2., -2.])
622 """
623 c = np.array(c, ndmin=1, copy=True)
624 if c.dtype.char in '?bBhHiIlLqQpP':
625 # astype doesn't preserve mask attribute.
626 c = c + 0.0
627 cdt = c.dtype
628 if not np.iterable(k):
629 k = [k]
630 cnt = pu._deprecate_as_int(m, "the order of integration")
631 iaxis = pu._deprecate_as_int(axis, "the axis")
632 if cnt < 0:
633 raise ValueError("The order of integration must be non-negative")
634 if len(k) > cnt:
635 raise ValueError("Too many integration constants")
636 if np.ndim(lbnd) != 0:
637 raise ValueError("lbnd must be a scalar.")
638 if np.ndim(scl) != 0:
639 raise ValueError("scl must be a scalar.")
640 iaxis = normalize_axis_index(iaxis, c.ndim)
642 if cnt == 0:
643 return c
645 k = list(k) + [0]*(cnt - len(k))
646 c = np.moveaxis(c, iaxis, 0)
647 for i in range(cnt):
648 n = len(c)
649 c *= scl
650 if n == 1 and np.all(c[0] == 0):
651 c[0] += k[i]
652 else:
653 tmp = np.empty((n + 1,) + c.shape[1:], dtype=cdt)
654 tmp[0] = c[0]*0
655 tmp[1] = c[0]
656 for j in range(1, n):
657 tmp[j + 1] = c[j]/(j + 1)
658 tmp[0] += k[i] - polyval(lbnd, tmp)
659 c = tmp
660 c = np.moveaxis(c, 0, iaxis)
661 return c
664def polyval(x, c, tensor=True):
665 """
666 Evaluate a polynomial at points x.
668 If `c` is of length `n + 1`, this function returns the value
670 .. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n
672 The parameter `x` is converted to an array only if it is a tuple or a
673 list, otherwise it is treated as a scalar. In either case, either `x`
674 or its elements must support multiplication and addition both with
675 themselves and with the elements of `c`.
677 If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
678 `c` is multidimensional, then the shape of the result depends on the
679 value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
680 x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
681 scalars have shape (,).
683 Trailing zeros in the coefficients will be used in the evaluation, so
684 they should be avoided if efficiency is a concern.
686 Parameters
687 ----------
688 x : array_like, compatible object
689 If `x` is a list or tuple, it is converted to an ndarray, otherwise
690 it is left unchanged and treated as a scalar. In either case, `x`
691 or its elements must support addition and multiplication with
692 with themselves and with the elements of `c`.
693 c : array_like
694 Array of coefficients ordered so that the coefficients for terms of
695 degree n are contained in c[n]. If `c` is multidimensional the
696 remaining indices enumerate multiple polynomials. In the two
697 dimensional case the coefficients may be thought of as stored in
698 the columns of `c`.
699 tensor : boolean, optional
700 If True, the shape of the coefficient array is extended with ones
701 on the right, one for each dimension of `x`. Scalars have dimension 0
702 for this action. The result is that every column of coefficients in
703 `c` is evaluated for every element of `x`. If False, `x` is broadcast
704 over the columns of `c` for the evaluation. This keyword is useful
705 when `c` is multidimensional. The default value is True.
707 .. versionadded:: 1.7.0
709 Returns
710 -------
711 values : ndarray, compatible object
712 The shape of the returned array is described above.
714 See Also
715 --------
716 polyval2d, polygrid2d, polyval3d, polygrid3d
718 Notes
719 -----
720 The evaluation uses Horner's method.
722 Examples
723 --------
724 >>> from numpy.polynomial.polynomial import polyval
725 >>> polyval(1, [1,2,3])
726 6.0
727 >>> a = np.arange(4).reshape(2,2)
728 >>> a
729 array([[0, 1],
730 [2, 3]])
731 >>> polyval(a, [1,2,3])
732 array([[ 1., 6.],
733 [17., 34.]])
734 >>> coef = np.arange(4).reshape(2,2) # multidimensional coefficients
735 >>> coef
736 array([[0, 1],
737 [2, 3]])
738 >>> polyval([1,2], coef, tensor=True)
739 array([[2., 4.],
740 [4., 7.]])
741 >>> polyval([1,2], coef, tensor=False)
742 array([2., 7.])
744 """
745 c = np.array(c, ndmin=1, copy=False)
746 if c.dtype.char in '?bBhHiIlLqQpP':
747 # astype fails with NA
748 c = c + 0.0
749 if isinstance(x, (tuple, list)):
750 x = np.asarray(x)
751 if isinstance(x, np.ndarray) and tensor:
752 c = c.reshape(c.shape + (1,)*x.ndim)
754 c0 = c[-1] + x*0
755 for i in range(2, len(c) + 1):
756 c0 = c[-i] + c0*x
757 return c0
760def polyvalfromroots(x, r, tensor=True):
761 """
762 Evaluate a polynomial specified by its roots at points x.
764 If `r` is of length `N`, this function returns the value
766 .. math:: p(x) = \\prod_{n=1}^{N} (x - r_n)
768 The parameter `x` is converted to an array only if it is a tuple or a
769 list, otherwise it is treated as a scalar. In either case, either `x`
770 or its elements must support multiplication and addition both with
771 themselves and with the elements of `r`.
773 If `r` is a 1-D array, then `p(x)` will have the same shape as `x`. If `r`
774 is multidimensional, then the shape of the result depends on the value of
775 `tensor`. If `tensor` is ``True`` the shape will be r.shape[1:] + x.shape;
776 that is, each polynomial is evaluated at every value of `x`. If `tensor` is
777 ``False``, the shape will be r.shape[1:]; that is, each polynomial is
778 evaluated only for the corresponding broadcast value of `x`. Note that
779 scalars have shape (,).
781 .. versionadded:: 1.12
783 Parameters
784 ----------
785 x : array_like, compatible object
786 If `x` is a list or tuple, it is converted to an ndarray, otherwise
787 it is left unchanged and treated as a scalar. In either case, `x`
788 or its elements must support addition and multiplication with
789 with themselves and with the elements of `r`.
790 r : array_like
791 Array of roots. If `r` is multidimensional the first index is the
792 root index, while the remaining indices enumerate multiple
793 polynomials. For instance, in the two dimensional case the roots
794 of each polynomial may be thought of as stored in the columns of `r`.
795 tensor : boolean, optional
796 If True, the shape of the roots array is extended with ones on the
797 right, one for each dimension of `x`. Scalars have dimension 0 for this
798 action. The result is that every column of coefficients in `r` is
799 evaluated for every element of `x`. If False, `x` is broadcast over the
800 columns of `r` for the evaluation. This keyword is useful when `r` is
801 multidimensional. The default value is True.
803 Returns
804 -------
805 values : ndarray, compatible object
806 The shape of the returned array is described above.
808 See Also
809 --------
810 polyroots, polyfromroots, polyval
812 Examples
813 --------
814 >>> from numpy.polynomial.polynomial import polyvalfromroots
815 >>> polyvalfromroots(1, [1,2,3])
816 0.0
817 >>> a = np.arange(4).reshape(2,2)
818 >>> a
819 array([[0, 1],
820 [2, 3]])
821 >>> polyvalfromroots(a, [-1, 0, 1])
822 array([[-0., 0.],
823 [ 6., 24.]])
824 >>> r = np.arange(-2, 2).reshape(2,2) # multidimensional coefficients
825 >>> r # each column of r defines one polynomial
826 array([[-2, -1],
827 [ 0, 1]])
828 >>> b = [-2, 1]
829 >>> polyvalfromroots(b, r, tensor=True)
830 array([[-0., 3.],
831 [ 3., 0.]])
832 >>> polyvalfromroots(b, r, tensor=False)
833 array([-0., 0.])
834 """
835 r = np.array(r, ndmin=1, copy=False)
836 if r.dtype.char in '?bBhHiIlLqQpP':
837 r = r.astype(np.double)
838 if isinstance(x, (tuple, list)):
839 x = np.asarray(x)
840 if isinstance(x, np.ndarray):
841 if tensor:
842 r = r.reshape(r.shape + (1,)*x.ndim)
843 elif x.ndim >= r.ndim:
844 raise ValueError("x.ndim must be < r.ndim when tensor == False")
845 return np.prod(x - r, axis=0)
848def polyval2d(x, y, c):
849 """
850 Evaluate a 2-D polynomial at points (x, y).
852 This function returns the value
854 .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * x^i * y^j
856 The parameters `x` and `y` are converted to arrays only if they are
857 tuples or a lists, otherwise they are treated as a scalars and they
858 must have the same shape after conversion. In either case, either `x`
859 and `y` or their elements must support multiplication and addition both
860 with themselves and with the elements of `c`.
862 If `c` has fewer than two dimensions, ones are implicitly appended to
863 its shape to make it 2-D. The shape of the result will be c.shape[2:] +
864 x.shape.
866 Parameters
867 ----------
868 x, y : array_like, compatible objects
869 The two dimensional series is evaluated at the points `(x, y)`,
870 where `x` and `y` must have the same shape. If `x` or `y` is a list
871 or tuple, it is first converted to an ndarray, otherwise it is left
872 unchanged and, if it isn't an ndarray, it is treated as a scalar.
873 c : array_like
874 Array of coefficients ordered so that the coefficient of the term
875 of multi-degree i,j is contained in `c[i,j]`. If `c` has
876 dimension greater than two the remaining indices enumerate multiple
877 sets of coefficients.
879 Returns
880 -------
881 values : ndarray, compatible object
882 The values of the two dimensional polynomial at points formed with
883 pairs of corresponding values from `x` and `y`.
885 See Also
886 --------
887 polyval, polygrid2d, polyval3d, polygrid3d
889 Notes
890 -----
892 .. versionadded:: 1.7.0
894 """
895 return pu._valnd(polyval, c, x, y)
898def polygrid2d(x, y, c):
899 """
900 Evaluate a 2-D polynomial on the Cartesian product of x and y.
902 This function returns the values:
904 .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * a^i * b^j
906 where the points `(a, b)` consist of all pairs formed by taking
907 `a` from `x` and `b` from `y`. The resulting points form a grid with
908 `x` in the first dimension and `y` in the second.
910 The parameters `x` and `y` are converted to arrays only if they are
911 tuples or a lists, otherwise they are treated as a scalars. In either
912 case, either `x` and `y` or their elements must support multiplication
913 and addition both with themselves and with the elements of `c`.
915 If `c` has fewer than two dimensions, ones are implicitly appended to
916 its shape to make it 2-D. The shape of the result will be c.shape[2:] +
917 x.shape + y.shape.
919 Parameters
920 ----------
921 x, y : array_like, compatible objects
922 The two dimensional series is evaluated at the points in the
923 Cartesian product of `x` and `y`. If `x` or `y` is a list or
924 tuple, it is first converted to an ndarray, otherwise it is left
925 unchanged and, if it isn't an ndarray, it is treated as a scalar.
926 c : array_like
927 Array of coefficients ordered so that the coefficients for terms of
928 degree i,j are contained in ``c[i,j]``. If `c` has dimension
929 greater than two the remaining indices enumerate multiple sets of
930 coefficients.
932 Returns
933 -------
934 values : ndarray, compatible object
935 The values of the two dimensional polynomial at points in the Cartesian
936 product of `x` and `y`.
938 See Also
939 --------
940 polyval, polyval2d, polyval3d, polygrid3d
942 Notes
943 -----
945 .. versionadded:: 1.7.0
947 """
948 return pu._gridnd(polyval, c, x, y)
951def polyval3d(x, y, z, c):
952 """
953 Evaluate a 3-D polynomial at points (x, y, z).
955 This function returns the values:
957 .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * x^i * y^j * z^k
959 The parameters `x`, `y`, and `z` are converted to arrays only if
960 they are tuples or a lists, otherwise they are treated as a scalars and
961 they must have the same shape after conversion. In either case, either
962 `x`, `y`, and `z` or their elements must support multiplication and
963 addition both with themselves and with the elements of `c`.
965 If `c` has fewer than 3 dimensions, ones are implicitly appended to its
966 shape to make it 3-D. The shape of the result will be c.shape[3:] +
967 x.shape.
969 Parameters
970 ----------
971 x, y, z : array_like, compatible object
972 The three dimensional series is evaluated at the points
973 `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
974 any of `x`, `y`, or `z` is a list or tuple, it is first converted
975 to an ndarray, otherwise it is left unchanged and if it isn't an
976 ndarray it is treated as a scalar.
977 c : array_like
978 Array of coefficients ordered so that the coefficient of the term of
979 multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
980 greater than 3 the remaining indices enumerate multiple sets of
981 coefficients.
983 Returns
984 -------
985 values : ndarray, compatible object
986 The values of the multidimensional polynomial on points formed with
987 triples of corresponding values from `x`, `y`, and `z`.
989 See Also
990 --------
991 polyval, polyval2d, polygrid2d, polygrid3d
993 Notes
994 -----
996 .. versionadded:: 1.7.0
998 """
999 return pu._valnd(polyval, c, x, y, z)
1002def polygrid3d(x, y, z, c):
1003 """
1004 Evaluate a 3-D polynomial on the Cartesian product of x, y and z.
1006 This function returns the values:
1008 .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * a^i * b^j * c^k
1010 where the points `(a, b, c)` consist of all triples formed by taking
1011 `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
1012 a grid with `x` in the first dimension, `y` in the second, and `z` in
1013 the third.
1015 The parameters `x`, `y`, and `z` are converted to arrays only if they
1016 are tuples or a lists, otherwise they are treated as a scalars. In
1017 either case, either `x`, `y`, and `z` or their elements must support
1018 multiplication and addition both with themselves and with the elements
1019 of `c`.
1021 If `c` has fewer than three dimensions, ones are implicitly appended to
1022 its shape to make it 3-D. The shape of the result will be c.shape[3:] +
1023 x.shape + y.shape + z.shape.
1025 Parameters
1026 ----------
1027 x, y, z : array_like, compatible objects
1028 The three dimensional series is evaluated at the points in the
1029 Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
1030 list or tuple, it is first converted to an ndarray, otherwise it is
1031 left unchanged and, if it isn't an ndarray, it is treated as a
1032 scalar.
1033 c : array_like
1034 Array of coefficients ordered so that the coefficients for terms of
1035 degree i,j are contained in ``c[i,j]``. If `c` has dimension
1036 greater than two the remaining indices enumerate multiple sets of
1037 coefficients.
1039 Returns
1040 -------
1041 values : ndarray, compatible object
1042 The values of the two dimensional polynomial at points in the Cartesian
1043 product of `x` and `y`.
1045 See Also
1046 --------
1047 polyval, polyval2d, polygrid2d, polyval3d
1049 Notes
1050 -----
1052 .. versionadded:: 1.7.0
1054 """
1055 return pu._gridnd(polyval, c, x, y, z)
1058def polyvander(x, deg):
1059 """Vandermonde matrix of given degree.
1061 Returns the Vandermonde matrix of degree `deg` and sample points
1062 `x`. The Vandermonde matrix is defined by
1064 .. math:: V[..., i] = x^i,
1066 where `0 <= i <= deg`. The leading indices of `V` index the elements of
1067 `x` and the last index is the power of `x`.
1069 If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
1070 matrix ``V = polyvander(x, n)``, then ``np.dot(V, c)`` and
1071 ``polyval(x, c)`` are the same up to roundoff. This equivalence is
1072 useful both for least squares fitting and for the evaluation of a large
1073 number of polynomials of the same degree and sample points.
1075 Parameters
1076 ----------
1077 x : array_like
1078 Array of points. The dtype is converted to float64 or complex128
1079 depending on whether any of the elements are complex. If `x` is
1080 scalar it is converted to a 1-D array.
1081 deg : int
1082 Degree of the resulting matrix.
1084 Returns
1085 -------
1086 vander : ndarray.
1087 The Vandermonde matrix. The shape of the returned matrix is
1088 ``x.shape + (deg + 1,)``, where the last index is the power of `x`.
1089 The dtype will be the same as the converted `x`.
1091 See Also
1092 --------
1093 polyvander2d, polyvander3d
1095 """
1096 ideg = pu._deprecate_as_int(deg, "deg")
1097 if ideg < 0:
1098 raise ValueError("deg must be non-negative")
1100 x = np.array(x, copy=False, ndmin=1) + 0.0
1101 dims = (ideg + 1,) + x.shape
1102 dtyp = x.dtype
1103 v = np.empty(dims, dtype=dtyp)
1104 v[0] = x*0 + 1
1105 if ideg > 0:
1106 v[1] = x
1107 for i in range(2, ideg + 1):
1108 v[i] = v[i-1]*x
1109 return np.moveaxis(v, 0, -1)
1112def polyvander2d(x, y, deg):
1113 """Pseudo-Vandermonde matrix of given degrees.
1115 Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1116 points `(x, y)`. The pseudo-Vandermonde matrix is defined by
1118 .. math:: V[..., (deg[1] + 1)*i + j] = x^i * y^j,
1120 where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
1121 `V` index the points `(x, y)` and the last index encodes the powers of
1122 `x` and `y`.
1124 If ``V = polyvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
1125 correspond to the elements of a 2-D coefficient array `c` of shape
1126 (xdeg + 1, ydeg + 1) in the order
1128 .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
1130 and ``np.dot(V, c.flat)`` and ``polyval2d(x, y, c)`` will be the same
1131 up to roundoff. This equivalence is useful both for least squares
1132 fitting and for the evaluation of a large number of 2-D polynomials
1133 of the same degrees and sample points.
1135 Parameters
1136 ----------
1137 x, y : array_like
1138 Arrays of point coordinates, all of the same shape. The dtypes
1139 will be converted to either float64 or complex128 depending on
1140 whether any of the elements are complex. Scalars are converted to
1141 1-D arrays.
1142 deg : list of ints
1143 List of maximum degrees of the form [x_deg, y_deg].
1145 Returns
1146 -------
1147 vander2d : ndarray
1148 The shape of the returned matrix is ``x.shape + (order,)``, where
1149 :math:`order = (deg[0]+1)*(deg([1]+1)`. The dtype will be the same
1150 as the converted `x` and `y`.
1152 See Also
1153 --------
1154 polyvander, polyvander3d, polyval2d, polyval3d
1156 """
1157 return pu._vander_nd_flat((polyvander, polyvander), (x, y), deg)
1160def polyvander3d(x, y, z, deg):
1161 """Pseudo-Vandermonde matrix of given degrees.
1163 Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1164 points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
1165 then The pseudo-Vandermonde matrix is defined by
1167 .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = x^i * y^j * z^k,
1169 where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
1170 indices of `V` index the points `(x, y, z)` and the last index encodes
1171 the powers of `x`, `y`, and `z`.
1173 If ``V = polyvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
1174 of `V` correspond to the elements of a 3-D coefficient array `c` of
1175 shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
1177 .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
1179 and ``np.dot(V, c.flat)`` and ``polyval3d(x, y, z, c)`` will be the
1180 same up to roundoff. This equivalence is useful both for least squares
1181 fitting and for the evaluation of a large number of 3-D polynomials
1182 of the same degrees and sample points.
1184 Parameters
1185 ----------
1186 x, y, z : array_like
1187 Arrays of point coordinates, all of the same shape. The dtypes will
1188 be converted to either float64 or complex128 depending on whether
1189 any of the elements are complex. Scalars are converted to 1-D
1190 arrays.
1191 deg : list of ints
1192 List of maximum degrees of the form [x_deg, y_deg, z_deg].
1194 Returns
1195 -------
1196 vander3d : ndarray
1197 The shape of the returned matrix is ``x.shape + (order,)``, where
1198 :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`. The dtype will
1199 be the same as the converted `x`, `y`, and `z`.
1201 See Also
1202 --------
1203 polyvander, polyvander3d, polyval2d, polyval3d
1205 Notes
1206 -----
1208 .. versionadded:: 1.7.0
1210 """
1211 return pu._vander_nd_flat((polyvander, polyvander, polyvander), (x, y, z), deg)
1214def polyfit(x, y, deg, rcond=None, full=False, w=None):
1215 """
1216 Least-squares fit of a polynomial to data.
1218 Return the coefficients of a polynomial of degree `deg` that is the
1219 least squares fit to the data values `y` given at points `x`. If `y` is
1220 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
1221 fits are done, one for each column of `y`, and the resulting
1222 coefficients are stored in the corresponding columns of a 2-D return.
1223 The fitted polynomial(s) are in the form
1225 .. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n,
1227 where `n` is `deg`.
1229 Parameters
1230 ----------
1231 x : array_like, shape (`M`,)
1232 x-coordinates of the `M` sample (data) points ``(x[i], y[i])``.
1233 y : array_like, shape (`M`,) or (`M`, `K`)
1234 y-coordinates of the sample points. Several sets of sample points
1235 sharing the same x-coordinates can be (independently) fit with one
1236 call to `polyfit` by passing in for `y` a 2-D array that contains
1237 one data set per column.
1238 deg : int or 1-D array_like
1239 Degree(s) of the fitting polynomials. If `deg` is a single integer
1240 all terms up to and including the `deg`'th term are included in the
1241 fit. For NumPy versions >= 1.11.0 a list of integers specifying the
1242 degrees of the terms to include may be used instead.
1243 rcond : float, optional
1244 Relative condition number of the fit. Singular values smaller
1245 than `rcond`, relative to the largest singular value, will be
1246 ignored. The default value is ``len(x)*eps``, where `eps` is the
1247 relative precision of the platform's float type, about 2e-16 in
1248 most cases.
1249 full : bool, optional
1250 Switch determining the nature of the return value. When ``False``
1251 (the default) just the coefficients are returned; when ``True``,
1252 diagnostic information from the singular value decomposition (used
1253 to solve the fit's matrix equation) is also returned.
1254 w : array_like, shape (`M`,), optional
1255 Weights. If not None, the weight ``w[i]`` applies to the unsquared
1256 residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
1257 chosen so that the errors of the products ``w[i]*y[i]`` all have the
1258 same variance. When using inverse-variance weighting, use
1259 ``w[i] = 1/sigma(y[i])``. The default value is None.
1261 .. versionadded:: 1.5.0
1263 Returns
1264 -------
1265 coef : ndarray, shape (`deg` + 1,) or (`deg` + 1, `K`)
1266 Polynomial coefficients ordered from low to high. If `y` was 2-D,
1267 the coefficients in column `k` of `coef` represent the polynomial
1268 fit to the data in `y`'s `k`-th column.
1270 [residuals, rank, singular_values, rcond] : list
1271 These values are only returned if ``full == True``
1273 - residuals -- sum of squared residuals of the least squares fit
1274 - rank -- the numerical rank of the scaled Vandermonde matrix
1275 - singular_values -- singular values of the scaled Vandermonde matrix
1276 - rcond -- value of `rcond`.
1278 For more details, see `numpy.linalg.lstsq`.
1280 Raises
1281 ------
1282 RankWarning
1283 Raised if the matrix in the least-squares fit is rank deficient.
1284 The warning is only raised if ``full == False``. The warnings can
1285 be turned off by:
1287 >>> import warnings
1288 >>> warnings.simplefilter('ignore', np.RankWarning)
1290 See Also
1291 --------
1292 numpy.polynomial.chebyshev.chebfit
1293 numpy.polynomial.legendre.legfit
1294 numpy.polynomial.laguerre.lagfit
1295 numpy.polynomial.hermite.hermfit
1296 numpy.polynomial.hermite_e.hermefit
1297 polyval : Evaluates a polynomial.
1298 polyvander : Vandermonde matrix for powers.
1299 numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
1300 scipy.interpolate.UnivariateSpline : Computes spline fits.
1302 Notes
1303 -----
1304 The solution is the coefficients of the polynomial `p` that minimizes
1305 the sum of the weighted squared errors
1307 .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
1309 where the :math:`w_j` are the weights. This problem is solved by
1310 setting up the (typically) over-determined matrix equation:
1312 .. math:: V(x) * c = w * y,
1314 where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
1315 coefficients to be solved for, `w` are the weights, and `y` are the
1316 observed values. This equation is then solved using the singular value
1317 decomposition of `V`.
1319 If some of the singular values of `V` are so small that they are
1320 neglected (and `full` == ``False``), a `RankWarning` will be raised.
1321 This means that the coefficient values may be poorly determined.
1322 Fitting to a lower order polynomial will usually get rid of the warning
1323 (but may not be what you want, of course; if you have independent
1324 reason(s) for choosing the degree which isn't working, you may have to:
1325 a) reconsider those reasons, and/or b) reconsider the quality of your
1326 data). The `rcond` parameter can also be set to a value smaller than
1327 its default, but the resulting fit may be spurious and have large
1328 contributions from roundoff error.
1330 Polynomial fits using double precision tend to "fail" at about
1331 (polynomial) degree 20. Fits using Chebyshev or Legendre series are
1332 generally better conditioned, but much can still depend on the
1333 distribution of the sample points and the smoothness of the data. If
1334 the quality of the fit is inadequate, splines may be a good
1335 alternative.
1337 Examples
1338 --------
1339 >>> np.random.seed(123)
1340 >>> from numpy.polynomial import polynomial as P
1341 >>> x = np.linspace(-1,1,51) # x "data": [-1, -0.96, ..., 0.96, 1]
1342 >>> y = x**3 - x + np.random.randn(len(x)) # x^3 - x + N(0,1) "noise"
1343 >>> c, stats = P.polyfit(x,y,3,full=True)
1344 >>> np.random.seed(123)
1345 >>> c # c[0], c[2] should be approx. 0, c[1] approx. -1, c[3] approx. 1
1346 array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286]) # may vary
1347 >>> stats # note the large SSR, explaining the rather poor results
1348 [array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316, # may vary
1349 0.28853036]), 1.1324274851176597e-014]
1351 Same thing without the added noise
1353 >>> y = x**3 - x
1354 >>> c, stats = P.polyfit(x,y,3,full=True)
1355 >>> c # c[0], c[2] should be "very close to 0", c[1] ~= -1, c[3] ~= 1
1356 array([-6.36925336e-18, -1.00000000e+00, -4.08053781e-16, 1.00000000e+00])
1357 >>> stats # note the minuscule SSR
1358 [array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158, # may vary
1359 0.50443316, 0.28853036]), 1.1324274851176597e-014]
1361 """
1362 return pu._fit(polyvander, x, y, deg, rcond, full, w)
1365def polycompanion(c):
1366 """
1367 Return the companion matrix of c.
1369 The companion matrix for power series cannot be made symmetric by
1370 scaling the basis, so this function differs from those for the
1371 orthogonal polynomials.
1373 Parameters
1374 ----------
1375 c : array_like
1376 1-D array of polynomial coefficients ordered from low to high
1377 degree.
1379 Returns
1380 -------
1381 mat : ndarray
1382 Companion matrix of dimensions (deg, deg).
1384 Notes
1385 -----
1387 .. versionadded:: 1.7.0
1389 """
1390 # c is a trimmed copy
1391 [c] = pu.as_series([c])
1392 if len(c) < 2:
1393 raise ValueError('Series must have maximum degree of at least 1.')
1394 if len(c) == 2:
1395 return np.array([[-c[0]/c[1]]])
1397 n = len(c) - 1
1398 mat = np.zeros((n, n), dtype=c.dtype)
1399 bot = mat.reshape(-1)[n::n+1]
1400 bot[...] = 1
1401 mat[:, -1] -= c[:-1]/c[-1]
1402 return mat
1405def polyroots(c):
1406 """
1407 Compute the roots of a polynomial.
1409 Return the roots (a.k.a. "zeros") of the polynomial
1411 .. math:: p(x) = \\sum_i c[i] * x^i.
1413 Parameters
1414 ----------
1415 c : 1-D array_like
1416 1-D array of polynomial coefficients.
1418 Returns
1419 -------
1420 out : ndarray
1421 Array of the roots of the polynomial. If all the roots are real,
1422 then `out` is also real, otherwise it is complex.
1424 See Also
1425 --------
1426 numpy.polynomial.chebyshev.chebroots
1427 numpy.polynomial.legendre.legroots
1428 numpy.polynomial.laguerre.lagroots
1429 numpy.polynomial.hermite.hermroots
1430 numpy.polynomial.hermite_e.hermeroots
1432 Notes
1433 -----
1434 The root estimates are obtained as the eigenvalues of the companion
1435 matrix, Roots far from the origin of the complex plane may have large
1436 errors due to the numerical instability of the power series for such
1437 values. Roots with multiplicity greater than 1 will also show larger
1438 errors as the value of the series near such points is relatively
1439 insensitive to errors in the roots. Isolated roots near the origin can
1440 be improved by a few iterations of Newton's method.
1442 Examples
1443 --------
1444 >>> import numpy.polynomial.polynomial as poly
1445 >>> poly.polyroots(poly.polyfromroots((-1,0,1)))
1446 array([-1., 0., 1.])
1447 >>> poly.polyroots(poly.polyfromroots((-1,0,1))).dtype
1448 dtype('float64')
1449 >>> j = complex(0,1)
1450 >>> poly.polyroots(poly.polyfromroots((-j,0,j)))
1451 array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j]) # may vary
1453 """
1454 # c is a trimmed copy
1455 [c] = pu.as_series([c])
1456 if len(c) < 2:
1457 return np.array([], dtype=c.dtype)
1458 if len(c) == 2:
1459 return np.array([-c[0]/c[1]])
1461 # rotated companion matrix reduces error
1462 m = polycompanion(c)[::-1,::-1]
1463 r = la.eigvals(m)
1464 r.sort()
1465 return r
1468#
1469# polynomial class
1470#
1472class Polynomial(ABCPolyBase):
1473 """A power series class.
1475 The Polynomial class provides the standard Python numerical methods
1476 '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
1477 attributes and methods listed in the `ABCPolyBase` documentation.
1479 Parameters
1480 ----------
1481 coef : array_like
1482 Polynomial coefficients in order of increasing degree, i.e.,
1483 ``(1, 2, 3)`` give ``1 + 2*x + 3*x**2``.
1484 domain : (2,) array_like, optional
1485 Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
1486 to the interval ``[window[0], window[1]]`` by shifting and scaling.
1487 The default value is [-1, 1].
1488 window : (2,) array_like, optional
1489 Window, see `domain` for its use. The default value is [-1, 1].
1491 .. versionadded:: 1.6.0
1493 """
1494 # Virtual Functions
1495 _add = staticmethod(polyadd)
1496 _sub = staticmethod(polysub)
1497 _mul = staticmethod(polymul)
1498 _div = staticmethod(polydiv)
1499 _pow = staticmethod(polypow)
1500 _val = staticmethod(polyval)
1501 _int = staticmethod(polyint)
1502 _der = staticmethod(polyder)
1503 _fit = staticmethod(polyfit)
1504 _line = staticmethod(polyline)
1505 _roots = staticmethod(polyroots)
1506 _fromroots = staticmethod(polyfromroots)
1508 # Virtual properties
1509 domain = np.array(polydomain)
1510 window = np.array(polydomain)
1511 basis_name = None
1513 @classmethod
1514 def _str_term_unicode(cls, i, arg_str):
1515 return f"·{arg_str}{i.translate(cls._superscript_mapping)}"
1517 @staticmethod
1518 def _str_term_ascii(i, arg_str):
1519 return f" {arg_str}**{i}"
1521 @staticmethod
1522 def _repr_latex_term(i, arg_str, needs_parens):
1523 if needs_parens:
1524 arg_str = rf"\left({arg_str}\right)"
1525 if i == 0:
1526 return '1'
1527 elif i == 1:
1528 return arg_str
1529 else:
1530 return f"{arg_str}^{{{i}}}"