Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/lib/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 Functions to operate on polynomials. | |
3 | |
4 """ | |
5 from __future__ import division, absolute_import, print_function | |
6 | |
7 __all__ = ['poly', 'roots', 'polyint', 'polyder', 'polyadd', | |
8 'polysub', 'polymul', 'polydiv', 'polyval', 'poly1d', | |
9 'polyfit', 'RankWarning'] | |
10 | |
11 import re | |
12 import warnings | |
13 import numpy.core.numeric as NX | |
14 | |
15 from numpy.core import isscalar, abs, finfo, atleast_1d, hstack, dot | |
16 from numpy.lib.twodim_base import diag, vander | |
17 from numpy.lib.function_base import trim_zeros, sort_complex | |
18 from numpy.lib.type_check import iscomplex, real, imag | |
19 from numpy.linalg import eigvals, lstsq, inv | |
20 | |
21 class RankWarning(UserWarning): | |
22 """ | |
23 Issued by `polyfit` when the Vandermonde matrix is rank deficient. | |
24 | |
25 For more information, a way to suppress the warning, and an example of | |
26 `RankWarning` being issued, see `polyfit`. | |
27 | |
28 """ | |
29 pass | |
30 | |
31 def poly(seq_of_zeros): | |
32 """ | |
33 Find the coefficients of a polynomial with the given sequence of roots. | |
34 | |
35 Returns the coefficients of the polynomial whose leading coefficient | |
36 is one for the given sequence of zeros (multiple roots must be included | |
37 in the sequence as many times as their multiplicity; see Examples). | |
38 A square matrix (or array, which will be treated as a matrix) can also | |
39 be given, in which case the coefficients of the characteristic polynomial | |
40 of the matrix are returned. | |
41 | |
42 Parameters | |
43 ---------- | |
44 seq_of_zeros : array_like, shape (N,) or (N, N) | |
45 A sequence of polynomial roots, or a square array or matrix object. | |
46 | |
47 Returns | |
48 ------- | |
49 c : ndarray | |
50 1D array of polynomial coefficients from highest to lowest degree: | |
51 | |
52 ``c[0] * x**(N) + c[1] * x**(N-1) + ... + c[N-1] * x + c[N]`` | |
53 where c[0] always equals 1. | |
54 | |
55 Raises | |
56 ------ | |
57 ValueError | |
58 If input is the wrong shape (the input must be a 1-D or square | |
59 2-D array). | |
60 | |
61 See Also | |
62 -------- | |
63 polyval : Evaluate a polynomial at a point. | |
64 roots : Return the roots of a polynomial. | |
65 polyfit : Least squares polynomial fit. | |
66 poly1d : A one-dimensional polynomial class. | |
67 | |
68 Notes | |
69 ----- | |
70 Specifying the roots of a polynomial still leaves one degree of | |
71 freedom, typically represented by an undetermined leading | |
72 coefficient. [1]_ In the case of this function, that coefficient - | |
73 the first one in the returned array - is always taken as one. (If | |
74 for some reason you have one other point, the only automatic way | |
75 presently to leverage that information is to use ``polyfit``.) | |
76 | |
77 The characteristic polynomial, :math:`p_a(t)`, of an `n`-by-`n` | |
78 matrix **A** is given by | |
79 | |
80 :math:`p_a(t) = \\mathrm{det}(t\\, \\mathbf{I} - \\mathbf{A})`, | |
81 | |
82 where **I** is the `n`-by-`n` identity matrix. [2]_ | |
83 | |
84 References | |
85 ---------- | |
86 .. [1] M. Sullivan and M. Sullivan, III, "Algebra and Trignometry, | |
87 Enhanced With Graphing Utilities," Prentice-Hall, pg. 318, 1996. | |
88 | |
89 .. [2] G. Strang, "Linear Algebra and Its Applications, 2nd Edition," | |
90 Academic Press, pg. 182, 1980. | |
91 | |
92 Examples | |
93 -------- | |
94 Given a sequence of a polynomial's zeros: | |
95 | |
96 >>> np.poly((0, 0, 0)) # Multiple root example | |
97 array([1, 0, 0, 0]) | |
98 | |
99 The line above represents z**3 + 0*z**2 + 0*z + 0. | |
100 | |
101 >>> np.poly((-1./2, 0, 1./2)) | |
102 array([ 1. , 0. , -0.25, 0. ]) | |
103 | |
104 The line above represents z**3 - z/4 | |
105 | |
106 >>> np.poly((np.random.random(1.)[0], 0, np.random.random(1.)[0])) | |
107 array([ 1. , -0.77086955, 0.08618131, 0. ]) #random | |
108 | |
109 Given a square array object: | |
110 | |
111 >>> P = np.array([[0, 1./3], [-1./2, 0]]) | |
112 >>> np.poly(P) | |
113 array([ 1. , 0. , 0.16666667]) | |
114 | |
115 Or a square matrix object: | |
116 | |
117 >>> np.poly(np.matrix(P)) | |
118 array([ 1. , 0. , 0.16666667]) | |
119 | |
120 Note how in all cases the leading coefficient is always 1. | |
121 | |
122 """ | |
123 seq_of_zeros = atleast_1d(seq_of_zeros) | |
124 sh = seq_of_zeros.shape | |
125 if len(sh) == 2 and sh[0] == sh[1] and sh[0] != 0: | |
126 seq_of_zeros = eigvals(seq_of_zeros) | |
127 elif len(sh) == 1: | |
128 pass | |
129 else: | |
130 raise ValueError("input must be 1d or non-empty square 2d array.") | |
131 | |
132 if len(seq_of_zeros) == 0: | |
133 return 1.0 | |
134 | |
135 a = [1] | |
136 for k in range(len(seq_of_zeros)): | |
137 a = NX.convolve(a, [1, -seq_of_zeros[k]], mode='full') | |
138 | |
139 if issubclass(a.dtype.type, NX.complexfloating): | |
140 # if complex roots are all complex conjugates, the roots are real. | |
141 roots = NX.asarray(seq_of_zeros, complex) | |
142 pos_roots = sort_complex(NX.compress(roots.imag > 0, roots)) | |
143 neg_roots = NX.conjugate(sort_complex( | |
144 NX.compress(roots.imag < 0, roots))) | |
145 if (len(pos_roots) == len(neg_roots) and | |
146 NX.alltrue(neg_roots == pos_roots)): | |
147 a = a.real.copy() | |
148 | |
149 return a | |
150 | |
151 def roots(p): | |
152 """ | |
153 Return the roots of a polynomial with coefficients given in p. | |
154 | |
155 The values in the rank-1 array `p` are coefficients of a polynomial. | |
156 If the length of `p` is n+1 then the polynomial is described by:: | |
157 | |
158 p[0] * x**n + p[1] * x**(n-1) + ... + p[n-1]*x + p[n] | |
159 | |
160 Parameters | |
161 ---------- | |
162 p : array_like | |
163 Rank-1 array of polynomial coefficients. | |
164 | |
165 Returns | |
166 ------- | |
167 out : ndarray | |
168 An array containing the complex roots of the polynomial. | |
169 | |
170 Raises | |
171 ------ | |
172 ValueError | |
173 When `p` cannot be converted to a rank-1 array. | |
174 | |
175 See also | |
176 -------- | |
177 poly : Find the coefficients of a polynomial with a given sequence | |
178 of roots. | |
179 polyval : Evaluate a polynomial at a point. | |
180 polyfit : Least squares polynomial fit. | |
181 poly1d : A one-dimensional polynomial class. | |
182 | |
183 Notes | |
184 ----- | |
185 The algorithm relies on computing the eigenvalues of the | |
186 companion matrix [1]_. | |
187 | |
188 References | |
189 ---------- | |
190 .. [1] R. A. Horn & C. R. Johnson, *Matrix Analysis*. Cambridge, UK: | |
191 Cambridge University Press, 1999, pp. 146-7. | |
192 | |
193 Examples | |
194 -------- | |
195 >>> coeff = [3.2, 2, 1] | |
196 >>> np.roots(coeff) | |
197 array([-0.3125+0.46351241j, -0.3125-0.46351241j]) | |
198 | |
199 """ | |
200 # If input is scalar, this makes it an array | |
201 p = atleast_1d(p) | |
202 if len(p.shape) != 1: | |
203 raise ValueError("Input must be a rank-1 array.") | |
204 | |
205 # find non-zero array entries | |
206 non_zero = NX.nonzero(NX.ravel(p))[0] | |
207 | |
208 # Return an empty array if polynomial is all zeros | |
209 if len(non_zero) == 0: | |
210 return NX.array([]) | |
211 | |
212 # find the number of trailing zeros -- this is the number of roots at 0. | |
213 trailing_zeros = len(p) - non_zero[-1] - 1 | |
214 | |
215 # strip leading and trailing zeros | |
216 p = p[int(non_zero[0]):int(non_zero[-1])+1] | |
217 | |
218 # casting: if incoming array isn't floating point, make it floating point. | |
219 if not issubclass(p.dtype.type, (NX.floating, NX.complexfloating)): | |
220 p = p.astype(float) | |
221 | |
222 N = len(p) | |
223 if N > 1: | |
224 # build companion matrix and find its eigenvalues (the roots) | |
225 A = diag(NX.ones((N-2,), p.dtype), -1) | |
226 A[0,:] = -p[1:] / p[0] | |
227 roots = eigvals(A) | |
228 else: | |
229 roots = NX.array([]) | |
230 | |
231 # tack any zeros onto the back of the array | |
232 roots = hstack((roots, NX.zeros(trailing_zeros, roots.dtype))) | |
233 return roots | |
234 | |
235 def polyint(p, m=1, k=None): | |
236 """ | |
237 Return an antiderivative (indefinite integral) of a polynomial. | |
238 | |
239 The returned order `m` antiderivative `P` of polynomial `p` satisfies | |
240 :math:`\\frac{d^m}{dx^m}P(x) = p(x)` and is defined up to `m - 1` | |
241 integration constants `k`. The constants determine the low-order | |
242 polynomial part | |
243 | |
244 .. math:: \\frac{k_{m-1}}{0!} x^0 + \\ldots + \\frac{k_0}{(m-1)!}x^{m-1} | |
245 | |
246 of `P` so that :math:`P^{(j)}(0) = k_{m-j-1}`. | |
247 | |
248 Parameters | |
249 ---------- | |
250 p : {array_like, poly1d} | |
251 Polynomial to differentiate. | |
252 A sequence is interpreted as polynomial coefficients, see `poly1d`. | |
253 m : int, optional | |
254 Order of the antiderivative. (Default: 1) | |
255 k : {None, list of `m` scalars, scalar}, optional | |
256 Integration constants. They are given in the order of integration: | |
257 those corresponding to highest-order terms come first. | |
258 | |
259 If ``None`` (default), all constants are assumed to be zero. | |
260 If `m = 1`, a single scalar can be given instead of a list. | |
261 | |
262 See Also | |
263 -------- | |
264 polyder : derivative of a polynomial | |
265 poly1d.integ : equivalent method | |
266 | |
267 Examples | |
268 -------- | |
269 The defining property of the antiderivative: | |
270 | |
271 >>> p = np.poly1d([1,1,1]) | |
272 >>> P = np.polyint(p) | |
273 >>> P | |
274 poly1d([ 0.33333333, 0.5 , 1. , 0. ]) | |
275 >>> np.polyder(P) == p | |
276 True | |
277 | |
278 The integration constants default to zero, but can be specified: | |
279 | |
280 >>> P = np.polyint(p, 3) | |
281 >>> P(0) | |
282 0.0 | |
283 >>> np.polyder(P)(0) | |
284 0.0 | |
285 >>> np.polyder(P, 2)(0) | |
286 0.0 | |
287 >>> P = np.polyint(p, 3, k=[6,5,3]) | |
288 >>> P | |
289 poly1d([ 0.01666667, 0.04166667, 0.16666667, 3. , 5. , 3. ]) | |
290 | |
291 Note that 3 = 6 / 2!, and that the constants are given in the order of | |
292 integrations. Constant of the highest-order polynomial term comes first: | |
293 | |
294 >>> np.polyder(P, 2)(0) | |
295 6.0 | |
296 >>> np.polyder(P, 1)(0) | |
297 5.0 | |
298 >>> P(0) | |
299 3.0 | |
300 | |
301 """ | |
302 m = int(m) | |
303 if m < 0: | |
304 raise ValueError("Order of integral must be positive (see polyder)") | |
305 if k is None: | |
306 k = NX.zeros(m, float) | |
307 k = atleast_1d(k) | |
308 if len(k) == 1 and m > 1: | |
309 k = k[0]*NX.ones(m, float) | |
310 if len(k) < m: | |
311 raise ValueError( | |
312 "k must be a scalar or a rank-1 array of length 1 or >m.") | |
313 | |
314 truepoly = isinstance(p, poly1d) | |
315 p = NX.asarray(p) | |
316 if m == 0: | |
317 if truepoly: | |
318 return poly1d(p) | |
319 return p | |
320 else: | |
321 # Note: this must work also with object and integer arrays | |
322 y = NX.concatenate((p.__truediv__(NX.arange(len(p), 0, -1)), [k[0]])) | |
323 val = polyint(y, m - 1, k=k[1:]) | |
324 if truepoly: | |
325 return poly1d(val) | |
326 return val | |
327 | |
328 def polyder(p, m=1): | |
329 """ | |
330 Return the derivative of the specified order of a polynomial. | |
331 | |
332 Parameters | |
333 ---------- | |
334 p : poly1d or sequence | |
335 Polynomial to differentiate. | |
336 A sequence is interpreted as polynomial coefficients, see `poly1d`. | |
337 m : int, optional | |
338 Order of differentiation (default: 1) | |
339 | |
340 Returns | |
341 ------- | |
342 der : poly1d | |
343 A new polynomial representing the derivative. | |
344 | |
345 See Also | |
346 -------- | |
347 polyint : Anti-derivative of a polynomial. | |
348 poly1d : Class for one-dimensional polynomials. | |
349 | |
350 Examples | |
351 -------- | |
352 The derivative of the polynomial :math:`x^3 + x^2 + x^1 + 1` is: | |
353 | |
354 >>> p = np.poly1d([1,1,1,1]) | |
355 >>> p2 = np.polyder(p) | |
356 >>> p2 | |
357 poly1d([3, 2, 1]) | |
358 | |
359 which evaluates to: | |
360 | |
361 >>> p2(2.) | |
362 17.0 | |
363 | |
364 We can verify this, approximating the derivative with | |
365 ``(f(x + h) - f(x))/h``: | |
366 | |
367 >>> (p(2. + 0.001) - p(2.)) / 0.001 | |
368 17.007000999997857 | |
369 | |
370 The fourth-order derivative of a 3rd-order polynomial is zero: | |
371 | |
372 >>> np.polyder(p, 2) | |
373 poly1d([6, 2]) | |
374 >>> np.polyder(p, 3) | |
375 poly1d([6]) | |
376 >>> np.polyder(p, 4) | |
377 poly1d([ 0.]) | |
378 | |
379 """ | |
380 m = int(m) | |
381 if m < 0: | |
382 raise ValueError("Order of derivative must be positive (see polyint)") | |
383 | |
384 truepoly = isinstance(p, poly1d) | |
385 p = NX.asarray(p) | |
386 n = len(p) - 1 | |
387 y = p[:-1] * NX.arange(n, 0, -1) | |
388 if m == 0: | |
389 val = p | |
390 else: | |
391 val = polyder(y, m - 1) | |
392 if truepoly: | |
393 val = poly1d(val) | |
394 return val | |
395 | |
396 def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False): | |
397 """ | |
398 Least squares polynomial fit. | |
399 | |
400 Fit a polynomial ``p(x) = p[0] * x**deg + ... + p[deg]`` of degree `deg` | |
401 to points `(x, y)`. Returns a vector of coefficients `p` that minimises | |
402 the squared error. | |
403 | |
404 Parameters | |
405 ---------- | |
406 x : array_like, shape (M,) | |
407 x-coordinates of the M sample points ``(x[i], y[i])``. | |
408 y : array_like, shape (M,) or (M, K) | |
409 y-coordinates of the sample points. Several data sets of sample | |
410 points sharing the same x-coordinates can be fitted at once by | |
411 passing in a 2D-array that contains one dataset per column. | |
412 deg : int | |
413 Degree of the fitting polynomial | |
414 rcond : float, optional | |
415 Relative condition number of the fit. Singular values smaller than | |
416 this relative to the largest singular value will be ignored. The | |
417 default value is len(x)*eps, where eps is the relative precision of | |
418 the float type, about 2e-16 in most cases. | |
419 full : bool, optional | |
420 Switch determining nature of return value. When it is False (the | |
421 default) just the coefficients are returned, when True diagnostic | |
422 information from the singular value decomposition is also returned. | |
423 w : array_like, shape (M,), optional | |
424 weights to apply to the y-coordinates of the sample points. | |
425 cov : bool, optional | |
426 Return the estimate and the covariance matrix of the estimate | |
427 If full is True, then cov is not returned. | |
428 | |
429 Returns | |
430 ------- | |
431 p : ndarray, shape (M,) or (M, K) | |
432 Polynomial coefficients, highest power first. If `y` was 2-D, the | |
433 coefficients for `k`-th data set are in ``p[:,k]``. | |
434 | |
435 residuals, rank, singular_values, rcond : | |
436 Present only if `full` = True. Residuals of the least-squares fit, | |
437 the effective rank of the scaled Vandermonde coefficient matrix, | |
438 its singular values, and the specified value of `rcond`. For more | |
439 details, see `linalg.lstsq`. | |
440 | |
441 V : ndarray, shape (M,M) or (M,M,K) | |
442 Present only if `full` = False and `cov`=True. The covariance | |
443 matrix of the polynomial coefficient estimates. The diagonal of | |
444 this matrix are the variance estimates for each coefficient. If y | |
445 is a 2-D array, then the covariance matrix for the `k`-th data set | |
446 are in ``V[:,:,k]`` | |
447 | |
448 | |
449 Warns | |
450 ----- | |
451 RankWarning | |
452 The rank of the coefficient matrix in the least-squares fit is | |
453 deficient. The warning is only raised if `full` = False. | |
454 | |
455 The warnings can be turned off by | |
456 | |
457 >>> import warnings | |
458 >>> warnings.simplefilter('ignore', np.RankWarning) | |
459 | |
460 See Also | |
461 -------- | |
462 polyval : Computes polynomial values. | |
463 linalg.lstsq : Computes a least-squares fit. | |
464 scipy.interpolate.UnivariateSpline : Computes spline fits. | |
465 | |
466 Notes | |
467 ----- | |
468 The solution minimizes the squared error | |
469 | |
470 .. math :: | |
471 E = \\sum_{j=0}^k |p(x_j) - y_j|^2 | |
472 | |
473 in the equations:: | |
474 | |
475 x[0]**n * p[0] + ... + x[0] * p[n-1] + p[n] = y[0] | |
476 x[1]**n * p[0] + ... + x[1] * p[n-1] + p[n] = y[1] | |
477 ... | |
478 x[k]**n * p[0] + ... + x[k] * p[n-1] + p[n] = y[k] | |
479 | |
480 The coefficient matrix of the coefficients `p` is a Vandermonde matrix. | |
481 | |
482 `polyfit` issues a `RankWarning` when the least-squares fit is badly | |
483 conditioned. This implies that the best fit is not well-defined due | |
484 to numerical error. The results may be improved by lowering the polynomial | |
485 degree or by replacing `x` by `x` - `x`.mean(). The `rcond` parameter | |
486 can also be set to a value smaller than its default, but the resulting | |
487 fit may be spurious: including contributions from the small singular | |
488 values can add numerical noise to the result. | |
489 | |
490 Note that fitting polynomial coefficients is inherently badly conditioned | |
491 when the degree of the polynomial is large or the interval of sample points | |
492 is badly centered. The quality of the fit should always be checked in these | |
493 cases. When polynomial fits are not satisfactory, splines may be a good | |
494 alternative. | |
495 | |
496 References | |
497 ---------- | |
498 .. [1] Wikipedia, "Curve fitting", | |
499 http://en.wikipedia.org/wiki/Curve_fitting | |
500 .. [2] Wikipedia, "Polynomial interpolation", | |
501 http://en.wikipedia.org/wiki/Polynomial_interpolation | |
502 | |
503 Examples | |
504 -------- | |
505 >>> x = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0]) | |
506 >>> y = np.array([0.0, 0.8, 0.9, 0.1, -0.8, -1.0]) | |
507 >>> z = np.polyfit(x, y, 3) | |
508 >>> z | |
509 array([ 0.08703704, -0.81349206, 1.69312169, -0.03968254]) | |
510 | |
511 It is convenient to use `poly1d` objects for dealing with polynomials: | |
512 | |
513 >>> p = np.poly1d(z) | |
514 >>> p(0.5) | |
515 0.6143849206349179 | |
516 >>> p(3.5) | |
517 -0.34732142857143039 | |
518 >>> p(10) | |
519 22.579365079365115 | |
520 | |
521 High-order polynomials may oscillate wildly: | |
522 | |
523 >>> p30 = np.poly1d(np.polyfit(x, y, 30)) | |
524 /... RankWarning: Polyfit may be poorly conditioned... | |
525 >>> p30(4) | |
526 -0.80000000000000204 | |
527 >>> p30(5) | |
528 -0.99999999999999445 | |
529 >>> p30(4.5) | |
530 -0.10547061179440398 | |
531 | |
532 Illustration: | |
533 | |
534 >>> import matplotlib.pyplot as plt | |
535 >>> xp = np.linspace(-2, 6, 100) | |
536 >>> _ = plt.plot(x, y, '.', xp, p(xp), '-', xp, p30(xp), '--') | |
537 >>> plt.ylim(-2,2) | |
538 (-2, 2) | |
539 >>> plt.show() | |
540 | |
541 """ | |
542 order = int(deg) + 1 | |
543 x = NX.asarray(x) + 0.0 | |
544 y = NX.asarray(y) + 0.0 | |
545 | |
546 # check arguments. | |
547 if deg < 0: | |
548 raise ValueError("expected deg >= 0") | |
549 if x.ndim != 1: | |
550 raise TypeError("expected 1D vector for x") | |
551 if x.size == 0: | |
552 raise TypeError("expected non-empty vector for x") | |
553 if y.ndim < 1 or y.ndim > 2: | |
554 raise TypeError("expected 1D or 2D array for y") | |
555 if x.shape[0] != y.shape[0]: | |
556 raise TypeError("expected x and y to have same length") | |
557 | |
558 # set rcond | |
559 if rcond is None: | |
560 rcond = len(x)*finfo(x.dtype).eps | |
561 | |
562 # set up least squares equation for powers of x | |
563 lhs = vander(x, order) | |
564 rhs = y | |
565 | |
566 # apply weighting | |
567 if w is not None: | |
568 w = NX.asarray(w) + 0.0 | |
569 if w.ndim != 1: | |
570 raise TypeError("expected a 1-d array for weights") | |
571 if w.shape[0] != y.shape[0]: | |
572 raise TypeError("expected w and y to have the same length") | |
573 lhs *= w[:, NX.newaxis] | |
574 if rhs.ndim == 2: | |
575 rhs *= w[:, NX.newaxis] | |
576 else: | |
577 rhs *= w | |
578 | |
579 # scale lhs to improve condition number and solve | |
580 scale = NX.sqrt((lhs*lhs).sum(axis=0)) | |
581 lhs /= scale | |
582 c, resids, rank, s = lstsq(lhs, rhs, rcond) | |
583 c = (c.T/scale).T # broadcast scale coefficients | |
584 | |
585 # warn on rank reduction, which indicates an ill conditioned matrix | |
586 if rank != order and not full: | |
587 msg = "Polyfit may be poorly conditioned" | |
588 warnings.warn(msg, RankWarning) | |
589 | |
590 if full: | |
591 return c, resids, rank, s, rcond | |
592 elif cov: | |
593 Vbase = inv(dot(lhs.T, lhs)) | |
594 Vbase /= NX.outer(scale, scale) | |
595 # Some literature ignores the extra -2.0 factor in the denominator, but | |
596 # it is included here because the covariance of Multivariate Student-T | |
597 # (which is implied by a Bayesian uncertainty analysis) includes it. | |
598 # Plus, it gives a slightly more conservative estimate of uncertainty. | |
599 fac = resids / (len(x) - order - 2.0) | |
600 if y.ndim == 1: | |
601 return c, Vbase * fac | |
602 else: | |
603 return c, Vbase[:,:, NX.newaxis] * fac | |
604 else: | |
605 return c | |
606 | |
607 | |
608 def polyval(p, x): | |
609 """ | |
610 Evaluate a polynomial at specific values. | |
611 | |
612 If `p` is of length N, this function returns the value: | |
613 | |
614 ``p[0]*x**(N-1) + p[1]*x**(N-2) + ... + p[N-2]*x + p[N-1]`` | |
615 | |
616 If `x` is a sequence, then `p(x)` is returned for each element of `x`. | |
617 If `x` is another polynomial then the composite polynomial `p(x(t))` | |
618 is returned. | |
619 | |
620 Parameters | |
621 ---------- | |
622 p : array_like or poly1d object | |
623 1D array of polynomial coefficients (including coefficients equal | |
624 to zero) from highest degree to the constant term, or an | |
625 instance of poly1d. | |
626 x : array_like or poly1d object | |
627 A number, a 1D array of numbers, or an instance of poly1d, "at" | |
628 which to evaluate `p`. | |
629 | |
630 Returns | |
631 ------- | |
632 values : ndarray or poly1d | |
633 If `x` is a poly1d instance, the result is the composition of the two | |
634 polynomials, i.e., `x` is "substituted" in `p` and the simplified | |
635 result is returned. In addition, the type of `x` - array_like or | |
636 poly1d - governs the type of the output: `x` array_like => `values` | |
637 array_like, `x` a poly1d object => `values` is also. | |
638 | |
639 See Also | |
640 -------- | |
641 poly1d: A polynomial class. | |
642 | |
643 Notes | |
644 ----- | |
645 Horner's scheme [1]_ is used to evaluate the polynomial. Even so, | |
646 for polynomials of high degree the values may be inaccurate due to | |
647 rounding errors. Use carefully. | |
648 | |
649 References | |
650 ---------- | |
651 .. [1] I. N. Bronshtein, K. A. Semendyayev, and K. A. Hirsch (Eng. | |
652 trans. Ed.), *Handbook of Mathematics*, New York, Van Nostrand | |
653 Reinhold Co., 1985, pg. 720. | |
654 | |
655 Examples | |
656 -------- | |
657 >>> np.polyval([3,0,1], 5) # 3 * 5**2 + 0 * 5**1 + 1 | |
658 76 | |
659 >>> np.polyval([3,0,1], np.poly1d(5)) | |
660 poly1d([ 76.]) | |
661 >>> np.polyval(np.poly1d([3,0,1]), 5) | |
662 76 | |
663 >>> np.polyval(np.poly1d([3,0,1]), np.poly1d(5)) | |
664 poly1d([ 76.]) | |
665 | |
666 """ | |
667 p = NX.asarray(p) | |
668 if isinstance(x, poly1d): | |
669 y = 0 | |
670 else: | |
671 x = NX.asarray(x) | |
672 y = NX.zeros_like(x) | |
673 for i in range(len(p)): | |
674 y = x * y + p[i] | |
675 return y | |
676 | |
677 def polyadd(a1, a2): | |
678 """ | |
679 Find the sum of two polynomials. | |
680 | |
681 Returns the polynomial resulting from the sum of two input polynomials. | |
682 Each input must be either a poly1d object or a 1D sequence of polynomial | |
683 coefficients, from highest to lowest degree. | |
684 | |
685 Parameters | |
686 ---------- | |
687 a1, a2 : array_like or poly1d object | |
688 Input polynomials. | |
689 | |
690 Returns | |
691 ------- | |
692 out : ndarray or poly1d object | |
693 The sum of the inputs. If either input is a poly1d object, then the | |
694 output is also a poly1d object. Otherwise, it is a 1D array of | |
695 polynomial coefficients from highest to lowest degree. | |
696 | |
697 See Also | |
698 -------- | |
699 poly1d : A one-dimensional polynomial class. | |
700 poly, polyadd, polyder, polydiv, polyfit, polyint, polysub, polyval | |
701 | |
702 Examples | |
703 -------- | |
704 >>> np.polyadd([1, 2], [9, 5, 4]) | |
705 array([9, 6, 6]) | |
706 | |
707 Using poly1d objects: | |
708 | |
709 >>> p1 = np.poly1d([1, 2]) | |
710 >>> p2 = np.poly1d([9, 5, 4]) | |
711 >>> print p1 | |
712 1 x + 2 | |
713 >>> print p2 | |
714 2 | |
715 9 x + 5 x + 4 | |
716 >>> print np.polyadd(p1, p2) | |
717 2 | |
718 9 x + 6 x + 6 | |
719 | |
720 """ | |
721 truepoly = (isinstance(a1, poly1d) or isinstance(a2, poly1d)) | |
722 a1 = atleast_1d(a1) | |
723 a2 = atleast_1d(a2) | |
724 diff = len(a2) - len(a1) | |
725 if diff == 0: | |
726 val = a1 + a2 | |
727 elif diff > 0: | |
728 zr = NX.zeros(diff, a1.dtype) | |
729 val = NX.concatenate((zr, a1)) + a2 | |
730 else: | |
731 zr = NX.zeros(abs(diff), a2.dtype) | |
732 val = a1 + NX.concatenate((zr, a2)) | |
733 if truepoly: | |
734 val = poly1d(val) | |
735 return val | |
736 | |
737 def polysub(a1, a2): | |
738 """ | |
739 Difference (subtraction) of two polynomials. | |
740 | |
741 Given two polynomials `a1` and `a2`, returns ``a1 - a2``. | |
742 `a1` and `a2` can be either array_like sequences of the polynomials' | |
743 coefficients (including coefficients equal to zero), or `poly1d` objects. | |
744 | |
745 Parameters | |
746 ---------- | |
747 a1, a2 : array_like or poly1d | |
748 Minuend and subtrahend polynomials, respectively. | |
749 | |
750 Returns | |
751 ------- | |
752 out : ndarray or poly1d | |
753 Array or `poly1d` object of the difference polynomial's coefficients. | |
754 | |
755 See Also | |
756 -------- | |
757 polyval, polydiv, polymul, polyadd | |
758 | |
759 Examples | |
760 -------- | |
761 .. math:: (2 x^2 + 10 x - 2) - (3 x^2 + 10 x -4) = (-x^2 + 2) | |
762 | |
763 >>> np.polysub([2, 10, -2], [3, 10, -4]) | |
764 array([-1, 0, 2]) | |
765 | |
766 """ | |
767 truepoly = (isinstance(a1, poly1d) or isinstance(a2, poly1d)) | |
768 a1 = atleast_1d(a1) | |
769 a2 = atleast_1d(a2) | |
770 diff = len(a2) - len(a1) | |
771 if diff == 0: | |
772 val = a1 - a2 | |
773 elif diff > 0: | |
774 zr = NX.zeros(diff, a1.dtype) | |
775 val = NX.concatenate((zr, a1)) - a2 | |
776 else: | |
777 zr = NX.zeros(abs(diff), a2.dtype) | |
778 val = a1 - NX.concatenate((zr, a2)) | |
779 if truepoly: | |
780 val = poly1d(val) | |
781 return val | |
782 | |
783 | |
784 def polymul(a1, a2): | |
785 """ | |
786 Find the product of two polynomials. | |
787 | |
788 Finds the polynomial resulting from the multiplication of the two input | |
789 polynomials. Each input must be either a poly1d object or a 1D sequence | |
790 of polynomial coefficients, from highest to lowest degree. | |
791 | |
792 Parameters | |
793 ---------- | |
794 a1, a2 : array_like or poly1d object | |
795 Input polynomials. | |
796 | |
797 Returns | |
798 ------- | |
799 out : ndarray or poly1d object | |
800 The polynomial resulting from the multiplication of the inputs. If | |
801 either inputs is a poly1d object, then the output is also a poly1d | |
802 object. Otherwise, it is a 1D array of polynomial coefficients from | |
803 highest to lowest degree. | |
804 | |
805 See Also | |
806 -------- | |
807 poly1d : A one-dimensional polynomial class. | |
808 poly, polyadd, polyder, polydiv, polyfit, polyint, polysub, | |
809 polyval | |
810 convolve : Array convolution. Same output as polymul, but has parameter | |
811 for overlap mode. | |
812 | |
813 Examples | |
814 -------- | |
815 >>> np.polymul([1, 2, 3], [9, 5, 1]) | |
816 array([ 9, 23, 38, 17, 3]) | |
817 | |
818 Using poly1d objects: | |
819 | |
820 >>> p1 = np.poly1d([1, 2, 3]) | |
821 >>> p2 = np.poly1d([9, 5, 1]) | |
822 >>> print p1 | |
823 2 | |
824 1 x + 2 x + 3 | |
825 >>> print p2 | |
826 2 | |
827 9 x + 5 x + 1 | |
828 >>> print np.polymul(p1, p2) | |
829 4 3 2 | |
830 9 x + 23 x + 38 x + 17 x + 3 | |
831 | |
832 """ | |
833 truepoly = (isinstance(a1, poly1d) or isinstance(a2, poly1d)) | |
834 a1, a2 = poly1d(a1), poly1d(a2) | |
835 val = NX.convolve(a1, a2) | |
836 if truepoly: | |
837 val = poly1d(val) | |
838 return val | |
839 | |
840 def polydiv(u, v): | |
841 """ | |
842 Returns the quotient and remainder of polynomial division. | |
843 | |
844 The input arrays are the coefficients (including any coefficients | |
845 equal to zero) of the "numerator" (dividend) and "denominator" | |
846 (divisor) polynomials, respectively. | |
847 | |
848 Parameters | |
849 ---------- | |
850 u : array_like or poly1d | |
851 Dividend polynomial's coefficients. | |
852 | |
853 v : array_like or poly1d | |
854 Divisor polynomial's coefficients. | |
855 | |
856 Returns | |
857 ------- | |
858 q : ndarray | |
859 Coefficients, including those equal to zero, of the quotient. | |
860 r : ndarray | |
861 Coefficients, including those equal to zero, of the remainder. | |
862 | |
863 See Also | |
864 -------- | |
865 poly, polyadd, polyder, polydiv, polyfit, polyint, polymul, polysub, | |
866 polyval | |
867 | |
868 Notes | |
869 ----- | |
870 Both `u` and `v` must be 0-d or 1-d (ndim = 0 or 1), but `u.ndim` need | |
871 not equal `v.ndim`. In other words, all four possible combinations - | |
872 ``u.ndim = v.ndim = 0``, ``u.ndim = v.ndim = 1``, | |
873 ``u.ndim = 1, v.ndim = 0``, and ``u.ndim = 0, v.ndim = 1`` - work. | |
874 | |
875 Examples | |
876 -------- | |
877 .. math:: \\frac{3x^2 + 5x + 2}{2x + 1} = 1.5x + 1.75, remainder 0.25 | |
878 | |
879 >>> x = np.array([3.0, 5.0, 2.0]) | |
880 >>> y = np.array([2.0, 1.0]) | |
881 >>> np.polydiv(x, y) | |
882 (array([ 1.5 , 1.75]), array([ 0.25])) | |
883 | |
884 """ | |
885 truepoly = (isinstance(u, poly1d) or isinstance(u, poly1d)) | |
886 u = atleast_1d(u) + 0.0 | |
887 v = atleast_1d(v) + 0.0 | |
888 # w has the common type | |
889 w = u[0] + v[0] | |
890 m = len(u) - 1 | |
891 n = len(v) - 1 | |
892 scale = 1. / v[0] | |
893 q = NX.zeros((max(m - n + 1, 1),), w.dtype) | |
894 r = u.copy() | |
895 for k in range(0, m-n+1): | |
896 d = scale * r[k] | |
897 q[k] = d | |
898 r[k:k+n+1] -= d*v | |
899 while NX.allclose(r[0], 0, rtol=1e-14) and (r.shape[-1] > 1): | |
900 r = r[1:] | |
901 if truepoly: | |
902 return poly1d(q), poly1d(r) | |
903 return q, r | |
904 | |
905 _poly_mat = re.compile(r"[*][*]([0-9]*)") | |
906 def _raise_power(astr, wrap=70): | |
907 n = 0 | |
908 line1 = '' | |
909 line2 = '' | |
910 output = ' ' | |
911 while True: | |
912 mat = _poly_mat.search(astr, n) | |
913 if mat is None: | |
914 break | |
915 span = mat.span() | |
916 power = mat.groups()[0] | |
917 partstr = astr[n:span[0]] | |
918 n = span[1] | |
919 toadd2 = partstr + ' '*(len(power)-1) | |
920 toadd1 = ' '*(len(partstr)-1) + power | |
921 if ((len(line2) + len(toadd2) > wrap) or | |
922 (len(line1) + len(toadd1) > wrap)): | |
923 output += line1 + "\n" + line2 + "\n " | |
924 line1 = toadd1 | |
925 line2 = toadd2 | |
926 else: | |
927 line2 += partstr + ' '*(len(power)-1) | |
928 line1 += ' '*(len(partstr)-1) + power | |
929 output += line1 + "\n" + line2 | |
930 return output + astr[n:] | |
931 | |
932 | |
933 class poly1d(object): | |
934 """ | |
935 A one-dimensional polynomial class. | |
936 | |
937 A convenience class, used to encapsulate "natural" operations on | |
938 polynomials so that said operations may take on their customary | |
939 form in code (see Examples). | |
940 | |
941 Parameters | |
942 ---------- | |
943 c_or_r : array_like | |
944 The polynomial's coefficients, in decreasing powers, or if | |
945 the value of the second parameter is True, the polynomial's | |
946 roots (values where the polynomial evaluates to 0). For example, | |
947 ``poly1d([1, 2, 3])`` returns an object that represents | |
948 :math:`x^2 + 2x + 3`, whereas ``poly1d([1, 2, 3], True)`` returns | |
949 one that represents :math:`(x-1)(x-2)(x-3) = x^3 - 6x^2 + 11x -6`. | |
950 r : bool, optional | |
951 If True, `c_or_r` specifies the polynomial's roots; the default | |
952 is False. | |
953 variable : str, optional | |
954 Changes the variable used when printing `p` from `x` to `variable` | |
955 (see Examples). | |
956 | |
957 Examples | |
958 -------- | |
959 Construct the polynomial :math:`x^2 + 2x + 3`: | |
960 | |
961 >>> p = np.poly1d([1, 2, 3]) | |
962 >>> print np.poly1d(p) | |
963 2 | |
964 1 x + 2 x + 3 | |
965 | |
966 Evaluate the polynomial at :math:`x = 0.5`: | |
967 | |
968 >>> p(0.5) | |
969 4.25 | |
970 | |
971 Find the roots: | |
972 | |
973 >>> p.r | |
974 array([-1.+1.41421356j, -1.-1.41421356j]) | |
975 >>> p(p.r) | |
976 array([ -4.44089210e-16+0.j, -4.44089210e-16+0.j]) | |
977 | |
978 These numbers in the previous line represent (0, 0) to machine precision | |
979 | |
980 Show the coefficients: | |
981 | |
982 >>> p.c | |
983 array([1, 2, 3]) | |
984 | |
985 Display the order (the leading zero-coefficients are removed): | |
986 | |
987 >>> p.order | |
988 2 | |
989 | |
990 Show the coefficient of the k-th power in the polynomial | |
991 (which is equivalent to ``p.c[-(i+1)]``): | |
992 | |
993 >>> p[1] | |
994 2 | |
995 | |
996 Polynomials can be added, subtracted, multiplied, and divided | |
997 (returns quotient and remainder): | |
998 | |
999 >>> p * p | |
1000 poly1d([ 1, 4, 10, 12, 9]) | |
1001 | |
1002 >>> (p**3 + 4) / p | |
1003 (poly1d([ 1., 4., 10., 12., 9.]), poly1d([ 4.])) | |
1004 | |
1005 ``asarray(p)`` gives the coefficient array, so polynomials can be | |
1006 used in all functions that accept arrays: | |
1007 | |
1008 >>> p**2 # square of polynomial | |
1009 poly1d([ 1, 4, 10, 12, 9]) | |
1010 | |
1011 >>> np.square(p) # square of individual coefficients | |
1012 array([1, 4, 9]) | |
1013 | |
1014 The variable used in the string representation of `p` can be modified, | |
1015 using the `variable` parameter: | |
1016 | |
1017 >>> p = np.poly1d([1,2,3], variable='z') | |
1018 >>> print p | |
1019 2 | |
1020 1 z + 2 z + 3 | |
1021 | |
1022 Construct a polynomial from its roots: | |
1023 | |
1024 >>> np.poly1d([1, 2], True) | |
1025 poly1d([ 1, -3, 2]) | |
1026 | |
1027 This is the same polynomial as obtained by: | |
1028 | |
1029 >>> np.poly1d([1, -1]) * np.poly1d([1, -2]) | |
1030 poly1d([ 1, -3, 2]) | |
1031 | |
1032 """ | |
1033 coeffs = None | |
1034 order = None | |
1035 variable = None | |
1036 __hash__ = None | |
1037 | |
1038 def __init__(self, c_or_r, r=0, variable=None): | |
1039 if isinstance(c_or_r, poly1d): | |
1040 for key in c_or_r.__dict__.keys(): | |
1041 self.__dict__[key] = c_or_r.__dict__[key] | |
1042 if variable is not None: | |
1043 self.__dict__['variable'] = variable | |
1044 return | |
1045 if r: | |
1046 c_or_r = poly(c_or_r) | |
1047 c_or_r = atleast_1d(c_or_r) | |
1048 if len(c_or_r.shape) > 1: | |
1049 raise ValueError("Polynomial must be 1d only.") | |
1050 c_or_r = trim_zeros(c_or_r, trim='f') | |
1051 if len(c_or_r) == 0: | |
1052 c_or_r = NX.array([0.]) | |
1053 self.__dict__['coeffs'] = c_or_r | |
1054 self.__dict__['order'] = len(c_or_r) - 1 | |
1055 if variable is None: | |
1056 variable = 'x' | |
1057 self.__dict__['variable'] = variable | |
1058 | |
1059 def __array__(self, t=None): | |
1060 if t: | |
1061 return NX.asarray(self.coeffs, t) | |
1062 else: | |
1063 return NX.asarray(self.coeffs) | |
1064 | |
1065 def __repr__(self): | |
1066 vals = repr(self.coeffs) | |
1067 vals = vals[6:-1] | |
1068 return "poly1d(%s)" % vals | |
1069 | |
1070 def __len__(self): | |
1071 return self.order | |
1072 | |
1073 def __str__(self): | |
1074 thestr = "0" | |
1075 var = self.variable | |
1076 | |
1077 # Remove leading zeros | |
1078 coeffs = self.coeffs[NX.logical_or.accumulate(self.coeffs != 0)] | |
1079 N = len(coeffs)-1 | |
1080 | |
1081 def fmt_float(q): | |
1082 s = '%.4g' % q | |
1083 if s.endswith('.0000'): | |
1084 s = s[:-5] | |
1085 return s | |
1086 | |
1087 for k in range(len(coeffs)): | |
1088 if not iscomplex(coeffs[k]): | |
1089 coefstr = fmt_float(real(coeffs[k])) | |
1090 elif real(coeffs[k]) == 0: | |
1091 coefstr = '%sj' % fmt_float(imag(coeffs[k])) | |
1092 else: | |
1093 coefstr = '(%s + %sj)' % (fmt_float(real(coeffs[k])), | |
1094 fmt_float(imag(coeffs[k]))) | |
1095 | |
1096 power = (N-k) | |
1097 if power == 0: | |
1098 if coefstr != '0': | |
1099 newstr = '%s' % (coefstr,) | |
1100 else: | |
1101 if k == 0: | |
1102 newstr = '0' | |
1103 else: | |
1104 newstr = '' | |
1105 elif power == 1: | |
1106 if coefstr == '0': | |
1107 newstr = '' | |
1108 elif coefstr == 'b': | |
1109 newstr = var | |
1110 else: | |
1111 newstr = '%s %s' % (coefstr, var) | |
1112 else: | |
1113 if coefstr == '0': | |
1114 newstr = '' | |
1115 elif coefstr == 'b': | |
1116 newstr = '%s**%d' % (var, power,) | |
1117 else: | |
1118 newstr = '%s %s**%d' % (coefstr, var, power) | |
1119 | |
1120 if k > 0: | |
1121 if newstr != '': | |
1122 if newstr.startswith('-'): | |
1123 thestr = "%s - %s" % (thestr, newstr[1:]) | |
1124 else: | |
1125 thestr = "%s + %s" % (thestr, newstr) | |
1126 else: | |
1127 thestr = newstr | |
1128 return _raise_power(thestr) | |
1129 | |
1130 def __call__(self, val): | |
1131 return polyval(self.coeffs, val) | |
1132 | |
1133 def __neg__(self): | |
1134 return poly1d(-self.coeffs) | |
1135 | |
1136 def __pos__(self): | |
1137 return self | |
1138 | |
1139 def __mul__(self, other): | |
1140 if isscalar(other): | |
1141 return poly1d(self.coeffs * other) | |
1142 else: | |
1143 other = poly1d(other) | |
1144 return poly1d(polymul(self.coeffs, other.coeffs)) | |
1145 | |
1146 def __rmul__(self, other): | |
1147 if isscalar(other): | |
1148 return poly1d(other * self.coeffs) | |
1149 else: | |
1150 other = poly1d(other) | |
1151 return poly1d(polymul(self.coeffs, other.coeffs)) | |
1152 | |
1153 def __add__(self, other): | |
1154 other = poly1d(other) | |
1155 return poly1d(polyadd(self.coeffs, other.coeffs)) | |
1156 | |
1157 def __radd__(self, other): | |
1158 other = poly1d(other) | |
1159 return poly1d(polyadd(self.coeffs, other.coeffs)) | |
1160 | |
1161 def __pow__(self, val): | |
1162 if not isscalar(val) or int(val) != val or val < 0: | |
1163 raise ValueError("Power to non-negative integers only.") | |
1164 res = [1] | |
1165 for _ in range(val): | |
1166 res = polymul(self.coeffs, res) | |
1167 return poly1d(res) | |
1168 | |
1169 def __sub__(self, other): | |
1170 other = poly1d(other) | |
1171 return poly1d(polysub(self.coeffs, other.coeffs)) | |
1172 | |
1173 def __rsub__(self, other): | |
1174 other = poly1d(other) | |
1175 return poly1d(polysub(other.coeffs, self.coeffs)) | |
1176 | |
1177 def __div__(self, other): | |
1178 if isscalar(other): | |
1179 return poly1d(self.coeffs/other) | |
1180 else: | |
1181 other = poly1d(other) | |
1182 return polydiv(self, other) | |
1183 | |
1184 __truediv__ = __div__ | |
1185 | |
1186 def __rdiv__(self, other): | |
1187 if isscalar(other): | |
1188 return poly1d(other/self.coeffs) | |
1189 else: | |
1190 other = poly1d(other) | |
1191 return polydiv(other, self) | |
1192 | |
1193 __rtruediv__ = __rdiv__ | |
1194 | |
1195 def __eq__(self, other): | |
1196 if self.coeffs.shape != other.coeffs.shape: | |
1197 return False | |
1198 return (self.coeffs == other.coeffs).all() | |
1199 | |
1200 def __ne__(self, other): | |
1201 return not self.__eq__(other) | |
1202 | |
1203 def __setattr__(self, key, val): | |
1204 raise ValueError("Attributes cannot be changed this way.") | |
1205 | |
1206 def __getattr__(self, key): | |
1207 if key in ['r', 'roots']: | |
1208 return roots(self.coeffs) | |
1209 elif key in ['c', 'coef', 'coefficients']: | |
1210 return self.coeffs | |
1211 elif key in ['o']: | |
1212 return self.order | |
1213 else: | |
1214 try: | |
1215 return self.__dict__[key] | |
1216 except KeyError: | |
1217 raise AttributeError( | |
1218 "'%s' has no attribute '%s'" % (self.__class__, key)) | |
1219 | |
1220 def __getitem__(self, val): | |
1221 ind = self.order - val | |
1222 if val > self.order: | |
1223 return 0 | |
1224 if val < 0: | |
1225 return 0 | |
1226 return self.coeffs[ind] | |
1227 | |
1228 def __setitem__(self, key, val): | |
1229 ind = self.order - key | |
1230 if key < 0: | |
1231 raise ValueError("Does not support negative powers.") | |
1232 if key > self.order: | |
1233 zr = NX.zeros(key-self.order, self.coeffs.dtype) | |
1234 self.__dict__['coeffs'] = NX.concatenate((zr, self.coeffs)) | |
1235 self.__dict__['order'] = key | |
1236 ind = 0 | |
1237 self.__dict__['coeffs'][ind] = val | |
1238 return | |
1239 | |
1240 def __iter__(self): | |
1241 return iter(self.coeffs) | |
1242 | |
1243 def integ(self, m=1, k=0): | |
1244 """ | |
1245 Return an antiderivative (indefinite integral) of this polynomial. | |
1246 | |
1247 Refer to `polyint` for full documentation. | |
1248 | |
1249 See Also | |
1250 -------- | |
1251 polyint : equivalent function | |
1252 | |
1253 """ | |
1254 return poly1d(polyint(self.coeffs, m=m, k=k)) | |
1255 | |
1256 def deriv(self, m=1): | |
1257 """ | |
1258 Return a derivative of this polynomial. | |
1259 | |
1260 Refer to `polyder` for full documentation. | |
1261 | |
1262 See Also | |
1263 -------- | |
1264 polyder : equivalent function | |
1265 | |
1266 """ | |
1267 return poly1d(polyder(self.coeffs, m=m)) | |
1268 | |
1269 # Stuff to do on module import | |
1270 | |
1271 warnings.simplefilter('always', RankWarning) |