comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/polynomial/polynomial.py @ 87:2a2c65a20a8b

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