Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2================================================= 

3Power Series (:mod:`numpy.polynomial.polynomial`) 

4================================================= 

5 

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`). 

11 

12Classes 

13------- 

14.. autosummary:: 

15 :toctree: generated/ 

16 

17 Polynomial 

18 

19Constants 

20--------- 

21.. autosummary:: 

22 :toctree: generated/ 

23 

24 polydomain 

25 polyzero 

26 polyone 

27 polyx 

28 

29Arithmetic 

30---------- 

31.. autosummary:: 

32 :toctree: generated/ 

33 

34 polyadd 

35 polysub 

36 polymulx 

37 polymul 

38 polydiv 

39 polypow 

40 polyval 

41 polyval2d 

42 polyval3d 

43 polygrid2d 

44 polygrid3d 

45 

46Calculus 

47-------- 

48.. autosummary:: 

49 :toctree: generated/ 

50 

51 polyder 

52 polyint 

53 

54Misc Functions 

55-------------- 

56.. autosummary:: 

57 :toctree: generated/ 

58 

59 polyfromroots 

60 polyroots 

61 polyvalfromroots 

62 polyvander 

63 polyvander2d 

64 polyvander3d 

65 polycompanion 

66 polyfit 

67 polytrim 

68 polyline 

69 

70See Also 

71-------- 

72`numpy.polynomial` 

73 

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'] 

81 

82import numpy as np 

83import numpy.linalg as la 

84from numpy.core.multiarray import normalize_axis_index 

85 

86from . import polyutils as pu 

87from ._polybase import ABCPolyBase 

88 

89polytrim = pu.trimcoef 

90 

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# 

95 

96# Polynomial default domain. 

97polydomain = np.array([-1, 1]) 

98 

99# Polynomial coefficients representing zero. 

100polyzero = np.array([0]) 

101 

102# Polynomial coefficients representing one. 

103polyone = np.array([1]) 

104 

105# Polynomial coefficients representing the identity x. 

106polyx = np.array([0, 1]) 

107 

108# 

109# Polynomial series functions 

110# 

111 

112 

113def polyline(off, scl): 

114 """ 

115 Returns an array representing a linear polynomial. 

116 

117 Parameters 

118 ---------- 

119 off, scl : scalars 

120 The "y-intercept" and "slope" of the line, respectively. 

121 

122 Returns 

123 ------- 

124 y : ndarray 

125 This module's representation of the linear polynomial ``off + 

126 scl*x``. 

127 

128 See Also 

129 -------- 

130 chebline 

131 

132 Examples 

133 -------- 

134 >>> from numpy.polynomial import polynomial as P 

135 >>> P.polyline(1,-1) 

136 array([ 1, -1]) 

137 >>> P.polyval(1, P.polyline(1,-1)) # should be 0 

138 0.0 

139 

140 """ 

141 if scl != 0: 

142 return np.array([off, scl]) 

143 else: 

144 return np.array([off]) 

145 

146 

147def polyfromroots(roots): 

148 """ 

149 Generate a monic polynomial with given roots. 

150 

151 Return the coefficients of the polynomial 

152 

153 .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n), 

154 

155 where the `r_n` are the roots specified in `roots`. If a zero has 

156 multiplicity n, then it must appear in `roots` n times. For instance, 

157 if 2 is a root of multiplicity three and 3 is a root of multiplicity 2, 

158 then `roots` looks something like [2, 2, 2, 3, 3]. The roots can appear 

159 in any order. 

160 

161 If the returned coefficients are `c`, then 

162 

163 .. math:: p(x) = c_0 + c_1 * x + ... + x^n 

164 

165 The coefficient of the last term is 1 for monic polynomials in this 

166 form. 

167 

168 Parameters 

169 ---------- 

170 roots : array_like 

171 Sequence containing the roots. 

172 

173 Returns 

174 ------- 

175 out : ndarray 

176 1-D array of the polynomial's coefficients If all the roots are 

177 real, then `out` is also real, otherwise it is complex. (see 

178 Examples below). 

179 

180 See Also 

181 -------- 

182 chebfromroots, legfromroots, lagfromroots, hermfromroots 

183 hermefromroots 

184 

185 Notes 

186 ----- 

187 The coefficients are determined by multiplying together linear factors 

188 of the form `(x - r_i)`, i.e. 

189 

190 .. math:: p(x) = (x - r_0) (x - r_1) ... (x - r_n) 

191 

192 where ``n == len(roots) - 1``; note that this implies that `1` is always 

193 returned for :math:`a_n`. 

194 

195 Examples 

196 -------- 

197 >>> from numpy.polynomial import polynomial as P 

198 >>> P.polyfromroots((-1,0,1)) # x(x - 1)(x + 1) = x^3 - x 

199 array([ 0., -1., 0., 1.]) 

200 >>> j = complex(0,1) 

201 >>> P.polyfromroots((-j,j)) # complex returned, though values are real 

202 array([1.+0.j, 0.+0.j, 1.+0.j]) 

203 

204 """ 

205 return pu._fromroots(polyline, polymul, roots) 

206 

207 

208def polyadd(c1, c2): 

209 """ 

210 Add one polynomial to another. 

211 

212 Returns the sum of two polynomials `c1` + `c2`. The arguments are 

213 sequences of coefficients from lowest order term to highest, i.e., 

214 [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``. 

215 

216 Parameters 

217 ---------- 

218 c1, c2 : array_like 

219 1-D arrays of polynomial coefficients ordered from low to high. 

220 

221 Returns 

222 ------- 

223 out : ndarray 

224 The coefficient array representing their sum. 

225 

226 See Also 

227 -------- 

228 polysub, polymulx, polymul, polydiv, polypow 

229 

230 Examples 

231 -------- 

232 >>> from numpy.polynomial import polynomial as P 

233 >>> c1 = (1,2,3) 

234 >>> c2 = (3,2,1) 

235 >>> sum = P.polyadd(c1,c2); sum 

236 array([4., 4., 4.]) 

237 >>> P.polyval(2, sum) # 4 + 4(2) + 4(2**2) 

238 28.0 

239 

240 """ 

241 return pu._add(c1, c2) 

242 

243 

244def polysub(c1, c2): 

245 """ 

246 Subtract one polynomial from another. 

247 

248 Returns the difference of two polynomials `c1` - `c2`. The arguments 

249 are sequences of coefficients from lowest order term to highest, i.e., 

250 [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``. 

251 

252 Parameters 

253 ---------- 

254 c1, c2 : array_like 

255 1-D arrays of polynomial coefficients ordered from low to 

256 high. 

257 

258 Returns 

259 ------- 

260 out : ndarray 

261 Of coefficients representing their difference. 

262 

263 See Also 

264 -------- 

265 polyadd, polymulx, polymul, polydiv, polypow 

266 

267 Examples 

268 -------- 

269 >>> from numpy.polynomial import polynomial as P 

270 >>> c1 = (1,2,3) 

271 >>> c2 = (3,2,1) 

272 >>> P.polysub(c1,c2) 

273 array([-2., 0., 2.]) 

274 >>> P.polysub(c2,c1) # -P.polysub(c1,c2) 

275 array([ 2., 0., -2.]) 

276 

277 """ 

278 return pu._sub(c1, c2) 

279 

280 

281def polymulx(c): 

282 """Multiply a polynomial by x. 

283 

284 Multiply the polynomial `c` by x, where x is the independent 

285 variable. 

286 

287 

288 Parameters 

289 ---------- 

290 c : array_like 

291 1-D array of polynomial coefficients ordered from low to 

292 high. 

293 

294 Returns 

295 ------- 

296 out : ndarray 

297 Array representing the result of the multiplication. 

298 

299 See Also 

300 -------- 

301 polyadd, polysub, polymul, polydiv, polypow 

302 

303 Notes 

304 ----- 

305 

306 .. versionadded:: 1.5.0 

307 

308 """ 

309 # c is a trimmed copy 

310 [c] = pu.as_series([c]) 

311 # The zero series needs special treatment 

312 if len(c) == 1 and c[0] == 0: 

313 return c 

314 

315 prd = np.empty(len(c) + 1, dtype=c.dtype) 

316 prd[0] = c[0]*0 

317 prd[1:] = c 

318 return prd 

319 

320 

321def polymul(c1, c2): 

322 """ 

323 Multiply one polynomial by another. 

324 

325 Returns the product of two polynomials `c1` * `c2`. The arguments are 

326 sequences of coefficients, from lowest order term to highest, e.g., 

327 [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2.`` 

328 

329 Parameters 

330 ---------- 

331 c1, c2 : array_like 

332 1-D arrays of coefficients representing a polynomial, relative to the 

333 "standard" basis, and ordered from lowest order term to highest. 

334 

335 Returns 

336 ------- 

337 out : ndarray 

338 Of the coefficients of their product. 

339 

340 See Also 

341 -------- 

342 polyadd, polysub, polymulx, polydiv, polypow 

343 

344 Examples 

345 -------- 

346 >>> from numpy.polynomial import polynomial as P 

347 >>> c1 = (1,2,3) 

348 >>> c2 = (3,2,1) 

349 >>> P.polymul(c1,c2) 

350 array([ 3., 8., 14., 8., 3.]) 

351 

352 """ 

353 # c1, c2 are trimmed copies 

354 [c1, c2] = pu.as_series([c1, c2]) 

355 ret = np.convolve(c1, c2) 

356 return pu.trimseq(ret) 

357 

358 

359def polydiv(c1, c2): 

360 """ 

361 Divide one polynomial by another. 

362 

363 Returns the quotient-with-remainder of two polynomials `c1` / `c2`. 

364 The arguments are sequences of coefficients, from lowest order term 

365 to highest, e.g., [1,2,3] represents ``1 + 2*x + 3*x**2``. 

366 

367 Parameters 

368 ---------- 

369 c1, c2 : array_like 

370 1-D arrays of polynomial coefficients ordered from low to high. 

371 

372 Returns 

373 ------- 

374 [quo, rem] : ndarrays 

375 Of coefficient series representing the quotient and remainder. 

376 

377 See Also 

378 -------- 

379 polyadd, polysub, polymulx, polymul, polypow 

380 

381 Examples 

382 -------- 

383 >>> from numpy.polynomial import polynomial as P 

384 >>> c1 = (1,2,3) 

385 >>> c2 = (3,2,1) 

386 >>> P.polydiv(c1,c2) 

387 (array([3.]), array([-8., -4.])) 

388 >>> P.polydiv(c2,c1) 

389 (array([ 0.33333333]), array([ 2.66666667, 1.33333333])) # may vary 

390 

391 """ 

392 # c1, c2 are trimmed copies 

393 [c1, c2] = pu.as_series([c1, c2]) 

394 if c2[-1] == 0: 

395 raise ZeroDivisionError() 

396 

397 # note: this is more efficient than `pu._div(polymul, c1, c2)` 

398 lc1 = len(c1) 

399 lc2 = len(c2) 

400 if lc1 < lc2: 

401 return c1[:1]*0, c1 

402 elif lc2 == 1: 

403 return c1/c2[-1], c1[:1]*0 

404 else: 

405 dlen = lc1 - lc2 

406 scl = c2[-1] 

407 c2 = c2[:-1]/scl 

408 i = dlen 

409 j = lc1 - 1 

410 while i >= 0: 

411 c1[i:j] -= c2*c1[j] 

412 i -= 1 

413 j -= 1 

414 return c1[j+1:]/scl, pu.trimseq(c1[:j+1]) 

415 

416 

417def polypow(c, pow, maxpower=None): 

418 """Raise a polynomial to a power. 

419 

420 Returns the polynomial `c` raised to the power `pow`. The argument 

421 `c` is a sequence of coefficients ordered from low to high. i.e., 

422 [1,2,3] is the series ``1 + 2*x + 3*x**2.`` 

423 

424 Parameters 

425 ---------- 

426 c : array_like 

427 1-D array of array of series coefficients ordered from low to 

428 high degree. 

429 pow : integer 

430 Power to which the series will be raised 

431 maxpower : integer, optional 

432 Maximum power allowed. This is mainly to limit growth of the series 

433 to unmanageable size. Default is 16 

434 

435 Returns 

436 ------- 

437 coef : ndarray 

438 Power series of power. 

439 

440 See Also 

441 -------- 

442 polyadd, polysub, polymulx, polymul, polydiv 

443 

444 Examples 

445 -------- 

446 >>> from numpy.polynomial import polynomial as P 

447 >>> P.polypow([1,2,3], 2) 

448 array([ 1., 4., 10., 12., 9.]) 

449 

450 """ 

451 # note: this is more efficient than `pu._pow(polymul, c1, c2)`, as it 

452 # avoids calling `as_series` repeatedly 

453 return pu._pow(np.convolve, c, pow, maxpower) 

454 

455 

456def polyder(c, m=1, scl=1, axis=0): 

457 """ 

458 Differentiate a polynomial. 

459 

460 Returns the polynomial coefficients `c` differentiated `m` times along 

461 `axis`. At each iteration the result is multiplied by `scl` (the 

462 scaling factor is for use in a linear change of variable). The 

463 argument `c` is an array of coefficients from low to high degree along 

464 each axis, e.g., [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2`` 

465 while [[1,2],[1,2]] represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is 

466 ``x`` and axis=1 is ``y``. 

467 

468 Parameters 

469 ---------- 

470 c : array_like 

471 Array of polynomial coefficients. If c is multidimensional the 

472 different axis correspond to different variables with the degree 

473 in each axis given by the corresponding index. 

474 m : int, optional 

475 Number of derivatives taken, must be non-negative. (Default: 1) 

476 scl : scalar, optional 

477 Each differentiation is multiplied by `scl`. The end result is 

478 multiplication by ``scl**m``. This is for use in a linear change 

479 of variable. (Default: 1) 

480 axis : int, optional 

481 Axis over which the derivative is taken. (Default: 0). 

482 

483 .. versionadded:: 1.7.0 

484 

485 Returns 

486 ------- 

487 der : ndarray 

488 Polynomial coefficients of the derivative. 

489 

490 See Also 

491 -------- 

492 polyint 

493 

494 Examples 

495 -------- 

496 >>> from numpy.polynomial import polynomial as P 

497 >>> c = (1,2,3,4) # 1 + 2x + 3x**2 + 4x**3 

498 >>> P.polyder(c) # (d/dx)(c) = 2 + 6x + 12x**2 

499 array([ 2., 6., 12.]) 

500 >>> P.polyder(c,3) # (d**3/dx**3)(c) = 24 

501 array([24.]) 

502 >>> P.polyder(c,scl=-1) # (d/d(-x))(c) = -2 - 6x - 12x**2 

503 array([ -2., -6., -12.]) 

504 >>> P.polyder(c,2,-1) # (d**2/d(-x)**2)(c) = 6 + 24x 

505 array([ 6., 24.]) 

506 

507 """ 

508 c = np.array(c, ndmin=1, copy=True) 

509 if c.dtype.char in '?bBhHiIlLqQpP': 

510 # astype fails with NA 

511 c = c + 0.0 

512 cdt = c.dtype 

513 cnt = pu._deprecate_as_int(m, "the order of derivation") 

514 iaxis = pu._deprecate_as_int(axis, "the axis") 

515 if cnt < 0: 

516 raise ValueError("The order of derivation must be non-negative") 

517 iaxis = normalize_axis_index(iaxis, c.ndim) 

518 

519 if cnt == 0: 

520 return c 

521 

522 c = np.moveaxis(c, iaxis, 0) 

523 n = len(c) 

524 if cnt >= n: 

525 c = c[:1]*0 

526 else: 

527 for i in range(cnt): 

528 n = n - 1 

529 c *= scl 

530 der = np.empty((n,) + c.shape[1:], dtype=cdt) 

531 for j in range(n, 0, -1): 

532 der[j - 1] = j*c[j] 

533 c = der 

534 c = np.moveaxis(c, 0, iaxis) 

535 return c 

536 

537 

538def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0): 

539 """ 

540 Integrate a polynomial. 

541 

542 Returns the polynomial coefficients `c` integrated `m` times from 

543 `lbnd` along `axis`. At each iteration the resulting series is 

544 **multiplied** by `scl` and an integration constant, `k`, is added. 

545 The scaling factor is for use in a linear change of variable. ("Buyer 

546 beware": note that, depending on what one is doing, one may want `scl` 

547 to be the reciprocal of what one might expect; for more information, 

548 see the Notes section below.) The argument `c` is an array of 

549 coefficients, from low to high degree along each axis, e.g., [1,2,3] 

550 represents the polynomial ``1 + 2*x + 3*x**2`` while [[1,2],[1,2]] 

551 represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is ``x`` and axis=1 is 

552 ``y``. 

553 

554 Parameters 

555 ---------- 

556 c : array_like 

557 1-D array of polynomial coefficients, ordered from low to high. 

558 m : int, optional 

559 Order of integration, must be positive. (Default: 1) 

560 k : {[], list, scalar}, optional 

561 Integration constant(s). The value of the first integral at zero 

562 is the first value in the list, the value of the second integral 

563 at zero is the second value, etc. If ``k == []`` (the default), 

564 all constants are set to zero. If ``m == 1``, a single scalar can 

565 be given instead of a list. 

566 lbnd : scalar, optional 

567 The lower bound of the integral. (Default: 0) 

568 scl : scalar, optional 

569 Following each integration the result is *multiplied* by `scl` 

570 before the integration constant is added. (Default: 1) 

571 axis : int, optional 

572 Axis over which the integral is taken. (Default: 0). 

573 

574 .. versionadded:: 1.7.0 

575 

576 Returns 

577 ------- 

578 S : ndarray 

579 Coefficient array of the integral. 

580 

581 Raises 

582 ------ 

583 ValueError 

584 If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or 

585 ``np.ndim(scl) != 0``. 

586 

587 See Also 

588 -------- 

589 polyder 

590 

591 Notes 

592 ----- 

593 Note that the result of each integration is *multiplied* by `scl`. Why 

594 is this important to note? Say one is making a linear change of 

595 variable :math:`u = ax + b` in an integral relative to `x`. Then 

596 :math:`dx = du/a`, so one will need to set `scl` equal to 

597 :math:`1/a` - perhaps not what one would have first thought. 

598 

599 Examples 

600 -------- 

601 >>> from numpy.polynomial import polynomial as P 

602 >>> c = (1,2,3) 

603 >>> P.polyint(c) # should return array([0, 1, 1, 1]) 

604 array([0., 1., 1., 1.]) 

605 >>> P.polyint(c,3) # should return array([0, 0, 0, 1/6, 1/12, 1/20]) 

606 array([ 0. , 0. , 0. , 0.16666667, 0.08333333, # may vary 

607 0.05 ]) 

608 >>> P.polyint(c,k=3) # should return array([3, 1, 1, 1]) 

609 array([3., 1., 1., 1.]) 

610 >>> P.polyint(c,lbnd=-2) # should return array([6, 1, 1, 1]) 

611 array([6., 1., 1., 1.]) 

612 >>> P.polyint(c,scl=-2) # should return array([0, -2, -2, -2]) 

613 array([ 0., -2., -2., -2.]) 

614 

615 """ 

616 c = np.array(c, ndmin=1, copy=True) 

617 if c.dtype.char in '?bBhHiIlLqQpP': 

618 # astype doesn't preserve mask attribute. 

619 c = c + 0.0 

620 cdt = c.dtype 

621 if not np.iterable(k): 

622 k = [k] 

623 cnt = pu._deprecate_as_int(m, "the order of integration") 

624 iaxis = pu._deprecate_as_int(axis, "the axis") 

625 if cnt < 0: 

626 raise ValueError("The order of integration must be non-negative") 

627 if len(k) > cnt: 

628 raise ValueError("Too many integration constants") 

629 if np.ndim(lbnd) != 0: 

630 raise ValueError("lbnd must be a scalar.") 

631 if np.ndim(scl) != 0: 

632 raise ValueError("scl must be a scalar.") 

633 iaxis = normalize_axis_index(iaxis, c.ndim) 

634 

635 if cnt == 0: 

636 return c 

637 

638 k = list(k) + [0]*(cnt - len(k)) 

639 c = np.moveaxis(c, iaxis, 0) 

640 for i in range(cnt): 

641 n = len(c) 

642 c *= scl 

643 if n == 1 and np.all(c[0] == 0): 

644 c[0] += k[i] 

645 else: 

646 tmp = np.empty((n + 1,) + c.shape[1:], dtype=cdt) 

647 tmp[0] = c[0]*0 

648 tmp[1] = c[0] 

649 for j in range(1, n): 

650 tmp[j + 1] = c[j]/(j + 1) 

651 tmp[0] += k[i] - polyval(lbnd, tmp) 

652 c = tmp 

653 c = np.moveaxis(c, 0, iaxis) 

654 return c 

655 

656 

657def polyval(x, c, tensor=True): 

658 """ 

659 Evaluate a polynomial at points x. 

660 

661 If `c` is of length `n + 1`, this function returns the value 

662 

663 .. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n 

664 

665 The parameter `x` is converted to an array only if it is a tuple or a 

666 list, otherwise it is treated as a scalar. In either case, either `x` 

667 or its elements must support multiplication and addition both with 

668 themselves and with the elements of `c`. 

669 

670 If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If 

671 `c` is multidimensional, then the shape of the result depends on the 

672 value of `tensor`. If `tensor` is true the shape will be c.shape[1:] + 

673 x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that 

674 scalars have shape (,). 

675 

676 Trailing zeros in the coefficients will be used in the evaluation, so 

677 they should be avoided if efficiency is a concern. 

678 

679 Parameters 

680 ---------- 

681 x : array_like, compatible object 

682 If `x` is a list or tuple, it is converted to an ndarray, otherwise 

683 it is left unchanged and treated as a scalar. In either case, `x` 

684 or its elements must support addition and multiplication with 

685 with themselves and with the elements of `c`. 

686 c : array_like 

687 Array of coefficients ordered so that the coefficients for terms of 

688 degree n are contained in c[n]. If `c` is multidimensional the 

689 remaining indices enumerate multiple polynomials. In the two 

690 dimensional case the coefficients may be thought of as stored in 

691 the columns of `c`. 

692 tensor : boolean, optional 

693 If True, the shape of the coefficient array is extended with ones 

694 on the right, one for each dimension of `x`. Scalars have dimension 0 

695 for this action. The result is that every column of coefficients in 

696 `c` is evaluated for every element of `x`. If False, `x` is broadcast 

697 over the columns of `c` for the evaluation. This keyword is useful 

698 when `c` is multidimensional. The default value is True. 

699 

700 .. versionadded:: 1.7.0 

701 

702 Returns 

703 ------- 

704 values : ndarray, compatible object 

705 The shape of the returned array is described above. 

706 

707 See Also 

708 -------- 

709 polyval2d, polygrid2d, polyval3d, polygrid3d 

710 

711 Notes 

712 ----- 

713 The evaluation uses Horner's method. 

714 

715 Examples 

716 -------- 

717 >>> from numpy.polynomial.polynomial import polyval 

718 >>> polyval(1, [1,2,3]) 

719 6.0 

720 >>> a = np.arange(4).reshape(2,2) 

721 >>> a 

722 array([[0, 1], 

723 [2, 3]]) 

724 >>> polyval(a, [1,2,3]) 

725 array([[ 1., 6.], 

726 [17., 34.]]) 

727 >>> coef = np.arange(4).reshape(2,2) # multidimensional coefficients 

728 >>> coef 

729 array([[0, 1], 

730 [2, 3]]) 

731 >>> polyval([1,2], coef, tensor=True) 

732 array([[2., 4.], 

733 [4., 7.]]) 

734 >>> polyval([1,2], coef, tensor=False) 

735 array([2., 7.]) 

736 

737 """ 

738 c = np.array(c, ndmin=1, copy=False) 

739 if c.dtype.char in '?bBhHiIlLqQpP': 

740 # astype fails with NA 

741 c = c + 0.0 

742 if isinstance(x, (tuple, list)): 

743 x = np.asarray(x) 

744 if isinstance(x, np.ndarray) and tensor: 

745 c = c.reshape(c.shape + (1,)*x.ndim) 

746 

747 c0 = c[-1] + x*0 

748 for i in range(2, len(c) + 1): 

749 c0 = c[-i] + c0*x 

750 return c0 

751 

752 

753def polyvalfromroots(x, r, tensor=True): 

754 """ 

755 Evaluate a polynomial specified by its roots at points x. 

756 

757 If `r` is of length `N`, this function returns the value 

758 

759 .. math:: p(x) = \\prod_{n=1}^{N} (x - r_n) 

760 

761 The parameter `x` is converted to an array only if it is a tuple or a 

762 list, otherwise it is treated as a scalar. In either case, either `x` 

763 or its elements must support multiplication and addition both with 

764 themselves and with the elements of `r`. 

765 

766 If `r` is a 1-D array, then `p(x)` will have the same shape as `x`. If `r` 

767 is multidimensional, then the shape of the result depends on the value of 

768 `tensor`. If `tensor is ``True`` the shape will be r.shape[1:] + x.shape; 

769 that is, each polynomial is evaluated at every value of `x`. If `tensor` is 

770 ``False``, the shape will be r.shape[1:]; that is, each polynomial is 

771 evaluated only for the corresponding broadcast value of `x`. Note that 

772 scalars have shape (,). 

773 

774 .. versionadded:: 1.12 

775 

776 Parameters 

777 ---------- 

778 x : array_like, compatible object 

779 If `x` is a list or tuple, it is converted to an ndarray, otherwise 

780 it is left unchanged and treated as a scalar. In either case, `x` 

781 or its elements must support addition and multiplication with 

782 with themselves and with the elements of `r`. 

783 r : array_like 

784 Array of roots. If `r` is multidimensional the first index is the 

785 root index, while the remaining indices enumerate multiple 

786 polynomials. For instance, in the two dimensional case the roots 

787 of each polynomial may be thought of as stored in the columns of `r`. 

788 tensor : boolean, optional 

789 If True, the shape of the roots array is extended with ones on the 

790 right, one for each dimension of `x`. Scalars have dimension 0 for this 

791 action. The result is that every column of coefficients in `r` is 

792 evaluated for every element of `x`. If False, `x` is broadcast over the 

793 columns of `r` for the evaluation. This keyword is useful when `r` is 

794 multidimensional. The default value is True. 

795 

796 Returns 

797 ------- 

798 values : ndarray, compatible object 

799 The shape of the returned array is described above. 

800 

801 See Also 

802 -------- 

803 polyroots, polyfromroots, polyval 

804 

805 Examples 

806 -------- 

807 >>> from numpy.polynomial.polynomial import polyvalfromroots 

808 >>> polyvalfromroots(1, [1,2,3]) 

809 0.0 

810 >>> a = np.arange(4).reshape(2,2) 

811 >>> a 

812 array([[0, 1], 

813 [2, 3]]) 

814 >>> polyvalfromroots(a, [-1, 0, 1]) 

815 array([[-0., 0.], 

816 [ 6., 24.]]) 

817 >>> r = np.arange(-2, 2).reshape(2,2) # multidimensional coefficients 

818 >>> r # each column of r defines one polynomial 

819 array([[-2, -1], 

820 [ 0, 1]]) 

821 >>> b = [-2, 1] 

822 >>> polyvalfromroots(b, r, tensor=True) 

823 array([[-0., 3.], 

824 [ 3., 0.]]) 

825 >>> polyvalfromroots(b, r, tensor=False) 

826 array([-0., 0.]) 

827 """ 

828 r = np.array(r, ndmin=1, copy=False) 

829 if r.dtype.char in '?bBhHiIlLqQpP': 

830 r = r.astype(np.double) 

831 if isinstance(x, (tuple, list)): 

832 x = np.asarray(x) 

833 if isinstance(x, np.ndarray): 

834 if tensor: 

835 r = r.reshape(r.shape + (1,)*x.ndim) 

836 elif x.ndim >= r.ndim: 

837 raise ValueError("x.ndim must be < r.ndim when tensor == False") 

838 return np.prod(x - r, axis=0) 

839 

840 

841def polyval2d(x, y, c): 

842 """ 

843 Evaluate a 2-D polynomial at points (x, y). 

844 

845 This function returns the value 

846 

847 .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * x^i * y^j 

848 

849 The parameters `x` and `y` are converted to arrays only if they are 

850 tuples or a lists, otherwise they are treated as a scalars and they 

851 must have the same shape after conversion. In either case, either `x` 

852 and `y` or their elements must support multiplication and addition both 

853 with themselves and with the elements of `c`. 

854 

855 If `c` has fewer than two dimensions, ones are implicitly appended to 

856 its shape to make it 2-D. The shape of the result will be c.shape[2:] + 

857 x.shape. 

858 

859 Parameters 

860 ---------- 

861 x, y : array_like, compatible objects 

862 The two dimensional series is evaluated at the points `(x, y)`, 

863 where `x` and `y` must have the same shape. If `x` or `y` is a list 

864 or tuple, it is first converted to an ndarray, otherwise it is left 

865 unchanged and, if it isn't an ndarray, it is treated as a scalar. 

866 c : array_like 

867 Array of coefficients ordered so that the coefficient of the term 

868 of multi-degree i,j is contained in `c[i,j]`. If `c` has 

869 dimension greater than two the remaining indices enumerate multiple 

870 sets of coefficients. 

871 

872 Returns 

873 ------- 

874 values : ndarray, compatible object 

875 The values of the two dimensional polynomial at points formed with 

876 pairs of corresponding values from `x` and `y`. 

877 

878 See Also 

879 -------- 

880 polyval, polygrid2d, polyval3d, polygrid3d 

881 

882 Notes 

883 ----- 

884 

885 .. versionadded:: 1.7.0 

886 

887 """ 

888 return pu._valnd(polyval, c, x, y) 

889 

890 

891def polygrid2d(x, y, c): 

892 """ 

893 Evaluate a 2-D polynomial on the Cartesian product of x and y. 

894 

895 This function returns the values: 

896 

897 .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * a^i * b^j 

898 

899 where the points `(a, b)` consist of all pairs formed by taking 

900 `a` from `x` and `b` from `y`. The resulting points form a grid with 

901 `x` in the first dimension and `y` in the second. 

902 

903 The parameters `x` and `y` are converted to arrays only if they are 

904 tuples or a lists, otherwise they are treated as a scalars. In either 

905 case, either `x` and `y` or their elements must support multiplication 

906 and addition both with themselves and with the elements of `c`. 

907 

908 If `c` has fewer than two dimensions, ones are implicitly appended to 

909 its shape to make it 2-D. The shape of the result will be c.shape[2:] + 

910 x.shape + y.shape. 

911 

912 Parameters 

913 ---------- 

914 x, y : array_like, compatible objects 

915 The two dimensional series is evaluated at the points in the 

916 Cartesian product of `x` and `y`. If `x` or `y` is a list or 

917 tuple, it is first converted to an ndarray, otherwise it is left 

918 unchanged and, if it isn't an ndarray, it is treated as a scalar. 

919 c : array_like 

920 Array of coefficients ordered so that the coefficients for terms of 

921 degree i,j are contained in ``c[i,j]``. If `c` has dimension 

922 greater than two the remaining indices enumerate multiple sets of 

923 coefficients. 

924 

925 Returns 

926 ------- 

927 values : ndarray, compatible object 

928 The values of the two dimensional polynomial at points in the Cartesian 

929 product of `x` and `y`. 

930 

931 See Also 

932 -------- 

933 polyval, polyval2d, polyval3d, polygrid3d 

934 

935 Notes 

936 ----- 

937 

938 .. versionadded:: 1.7.0 

939 

940 """ 

941 return pu._gridnd(polyval, c, x, y) 

942 

943 

944def polyval3d(x, y, z, c): 

945 """ 

946 Evaluate a 3-D polynomial at points (x, y, z). 

947 

948 This function returns the values: 

949 

950 .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * x^i * y^j * z^k 

951 

952 The parameters `x`, `y`, and `z` are converted to arrays only if 

953 they are tuples or a lists, otherwise they are treated as a scalars and 

954 they must have the same shape after conversion. In either case, either 

955 `x`, `y`, and `z` or their elements must support multiplication and 

956 addition both with themselves and with the elements of `c`. 

957 

958 If `c` has fewer than 3 dimensions, ones are implicitly appended to its 

959 shape to make it 3-D. The shape of the result will be c.shape[3:] + 

960 x.shape. 

961 

962 Parameters 

963 ---------- 

964 x, y, z : array_like, compatible object 

965 The three dimensional series is evaluated at the points 

966 `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If 

967 any of `x`, `y`, or `z` is a list or tuple, it is first converted 

968 to an ndarray, otherwise it is left unchanged and if it isn't an 

969 ndarray it is treated as a scalar. 

970 c : array_like 

971 Array of coefficients ordered so that the coefficient of the term of 

972 multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension 

973 greater than 3 the remaining indices enumerate multiple sets of 

974 coefficients. 

975 

976 Returns 

977 ------- 

978 values : ndarray, compatible object 

979 The values of the multidimensional polynomial on points formed with 

980 triples of corresponding values from `x`, `y`, and `z`. 

981 

982 See Also 

983 -------- 

984 polyval, polyval2d, polygrid2d, polygrid3d 

985 

986 Notes 

987 ----- 

988 

989 .. versionadded:: 1.7.0 

990 

991 """ 

992 return pu._valnd(polyval, c, x, y, z) 

993 

994 

995def polygrid3d(x, y, z, c): 

996 """ 

997 Evaluate a 3-D polynomial on the Cartesian product of x, y and z. 

998 

999 This function returns the values: 

1000 

1001 .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * a^i * b^j * c^k 

1002 

1003 where the points `(a, b, c)` consist of all triples formed by taking 

1004 `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form 

1005 a grid with `x` in the first dimension, `y` in the second, and `z` in 

1006 the third. 

1007 

1008 The parameters `x`, `y`, and `z` are converted to arrays only if they 

1009 are tuples or a lists, otherwise they are treated as a scalars. In 

1010 either case, either `x`, `y`, and `z` or their elements must support 

1011 multiplication and addition both with themselves and with the elements 

1012 of `c`. 

1013 

1014 If `c` has fewer than three dimensions, ones are implicitly appended to 

1015 its shape to make it 3-D. The shape of the result will be c.shape[3:] + 

1016 x.shape + y.shape + z.shape. 

1017 

1018 Parameters 

1019 ---------- 

1020 x, y, z : array_like, compatible objects 

1021 The three dimensional series is evaluated at the points in the 

1022 Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a 

1023 list or tuple, it is first converted to an ndarray, otherwise it is 

1024 left unchanged and, if it isn't an ndarray, it is treated as a 

1025 scalar. 

1026 c : array_like 

1027 Array of coefficients ordered so that the coefficients for terms of 

1028 degree i,j are contained in ``c[i,j]``. If `c` has dimension 

1029 greater than two the remaining indices enumerate multiple sets of 

1030 coefficients. 

1031 

1032 Returns 

1033 ------- 

1034 values : ndarray, compatible object 

1035 The values of the two dimensional polynomial at points in the Cartesian 

1036 product of `x` and `y`. 

1037 

1038 See Also 

1039 -------- 

1040 polyval, polyval2d, polygrid2d, polyval3d 

1041 

1042 Notes 

1043 ----- 

1044 

1045 .. versionadded:: 1.7.0 

1046 

1047 """ 

1048 return pu._gridnd(polyval, c, x, y, z) 

1049 

1050 

1051def polyvander(x, deg): 

1052 """Vandermonde matrix of given degree. 

1053 

1054 Returns the Vandermonde matrix of degree `deg` and sample points 

1055 `x`. The Vandermonde matrix is defined by 

1056 

1057 .. math:: V[..., i] = x^i, 

1058 

1059 where `0 <= i <= deg`. The leading indices of `V` index the elements of 

1060 `x` and the last index is the power of `x`. 

1061 

1062 If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the 

1063 matrix ``V = polyvander(x, n)``, then ``np.dot(V, c)`` and 

1064 ``polyval(x, c)`` are the same up to roundoff. This equivalence is 

1065 useful both for least squares fitting and for the evaluation of a large 

1066 number of polynomials of the same degree and sample points. 

1067 

1068 Parameters 

1069 ---------- 

1070 x : array_like 

1071 Array of points. The dtype is converted to float64 or complex128 

1072 depending on whether any of the elements are complex. If `x` is 

1073 scalar it is converted to a 1-D array. 

1074 deg : int 

1075 Degree of the resulting matrix. 

1076 

1077 Returns 

1078 ------- 

1079 vander : ndarray. 

1080 The Vandermonde matrix. The shape of the returned matrix is 

1081 ``x.shape + (deg + 1,)``, where the last index is the power of `x`. 

1082 The dtype will be the same as the converted `x`. 

1083 

1084 See Also 

1085 -------- 

1086 polyvander2d, polyvander3d 

1087 

1088 """ 

1089 ideg = pu._deprecate_as_int(deg, "deg") 

1090 if ideg < 0: 

1091 raise ValueError("deg must be non-negative") 

1092 

1093 x = np.array(x, copy=False, ndmin=1) + 0.0 

1094 dims = (ideg + 1,) + x.shape 

1095 dtyp = x.dtype 

1096 v = np.empty(dims, dtype=dtyp) 

1097 v[0] = x*0 + 1 

1098 if ideg > 0: 

1099 v[1] = x 

1100 for i in range(2, ideg + 1): 

1101 v[i] = v[i-1]*x 

1102 return np.moveaxis(v, 0, -1) 

1103 

1104 

1105def polyvander2d(x, y, deg): 

1106 """Pseudo-Vandermonde matrix of given degrees. 

1107 

1108 Returns the pseudo-Vandermonde matrix of degrees `deg` and sample 

1109 points `(x, y)`. The pseudo-Vandermonde matrix is defined by 

1110 

1111 .. math:: V[..., (deg[1] + 1)*i + j] = x^i * y^j, 

1112 

1113 where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of 

1114 `V` index the points `(x, y)` and the last index encodes the powers of 

1115 `x` and `y`. 

1116 

1117 If ``V = polyvander2d(x, y, [xdeg, ydeg])``, then the columns of `V` 

1118 correspond to the elements of a 2-D coefficient array `c` of shape 

1119 (xdeg + 1, ydeg + 1) in the order 

1120 

1121 .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ... 

1122 

1123 and ``np.dot(V, c.flat)`` and ``polyval2d(x, y, c)`` will be the same 

1124 up to roundoff. This equivalence is useful both for least squares 

1125 fitting and for the evaluation of a large number of 2-D polynomials 

1126 of the same degrees and sample points. 

1127 

1128 Parameters 

1129 ---------- 

1130 x, y : array_like 

1131 Arrays of point coordinates, all of the same shape. The dtypes 

1132 will be converted to either float64 or complex128 depending on 

1133 whether any of the elements are complex. Scalars are converted to 

1134 1-D arrays. 

1135 deg : list of ints 

1136 List of maximum degrees of the form [x_deg, y_deg]. 

1137 

1138 Returns 

1139 ------- 

1140 vander2d : ndarray 

1141 The shape of the returned matrix is ``x.shape + (order,)``, where 

1142 :math:`order = (deg[0]+1)*(deg([1]+1)`. The dtype will be the same 

1143 as the converted `x` and `y`. 

1144 

1145 See Also 

1146 -------- 

1147 polyvander, polyvander3d, polyval2d, polyval3d 

1148 

1149 """ 

1150 return pu._vander_nd_flat((polyvander, polyvander), (x, y), deg) 

1151 

1152 

1153def polyvander3d(x, y, z, deg): 

1154 """Pseudo-Vandermonde matrix of given degrees. 

1155 

1156 Returns the pseudo-Vandermonde matrix of degrees `deg` and sample 

1157 points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`, 

1158 then The pseudo-Vandermonde matrix is defined by 

1159 

1160 .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = x^i * y^j * z^k, 

1161 

1162 where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading 

1163 indices of `V` index the points `(x, y, z)` and the last index encodes 

1164 the powers of `x`, `y`, and `z`. 

1165 

1166 If ``V = polyvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns 

1167 of `V` correspond to the elements of a 3-D coefficient array `c` of 

1168 shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order 

1169 

1170 .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},... 

1171 

1172 and ``np.dot(V, c.flat)`` and ``polyval3d(x, y, z, c)`` will be the 

1173 same up to roundoff. This equivalence is useful both for least squares 

1174 fitting and for the evaluation of a large number of 3-D polynomials 

1175 of the same degrees and sample points. 

1176 

1177 Parameters 

1178 ---------- 

1179 x, y, z : array_like 

1180 Arrays of point coordinates, all of the same shape. The dtypes will 

1181 be converted to either float64 or complex128 depending on whether 

1182 any of the elements are complex. Scalars are converted to 1-D 

1183 arrays. 

1184 deg : list of ints 

1185 List of maximum degrees of the form [x_deg, y_deg, z_deg]. 

1186 

1187 Returns 

1188 ------- 

1189 vander3d : ndarray 

1190 The shape of the returned matrix is ``x.shape + (order,)``, where 

1191 :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`. The dtype will 

1192 be the same as the converted `x`, `y`, and `z`. 

1193 

1194 See Also 

1195 -------- 

1196 polyvander, polyvander3d, polyval2d, polyval3d 

1197 

1198 Notes 

1199 ----- 

1200 

1201 .. versionadded:: 1.7.0 

1202 

1203 """ 

1204 return pu._vander_nd_flat((polyvander, polyvander, polyvander), (x, y, z), deg) 

1205 

1206 

1207def polyfit(x, y, deg, rcond=None, full=False, w=None): 

1208 """ 

1209 Least-squares fit of a polynomial to data. 

1210 

1211 Return the coefficients of a polynomial of degree `deg` that is the 

1212 least squares fit to the data values `y` given at points `x`. If `y` is 

1213 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple 

1214 fits are done, one for each column of `y`, and the resulting 

1215 coefficients are stored in the corresponding columns of a 2-D return. 

1216 The fitted polynomial(s) are in the form 

1217 

1218 .. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n, 

1219 

1220 where `n` is `deg`. 

1221 

1222 Parameters 

1223 ---------- 

1224 x : array_like, shape (`M`,) 

1225 x-coordinates of the `M` sample (data) points ``(x[i], y[i])``. 

1226 y : array_like, shape (`M`,) or (`M`, `K`) 

1227 y-coordinates of the sample points. Several sets of sample points 

1228 sharing the same x-coordinates can be (independently) fit with one 

1229 call to `polyfit` by passing in for `y` a 2-D array that contains 

1230 one data set per column. 

1231 deg : int or 1-D array_like 

1232 Degree(s) of the fitting polynomials. If `deg` is a single integer 

1233 all terms up to and including the `deg`'th term are included in the 

1234 fit. For NumPy versions >= 1.11.0 a list of integers specifying the 

1235 degrees of the terms to include may be used instead. 

1236 rcond : float, optional 

1237 Relative condition number of the fit. Singular values smaller 

1238 than `rcond`, relative to the largest singular value, will be 

1239 ignored. The default value is ``len(x)*eps``, where `eps` is the 

1240 relative precision of the platform's float type, about 2e-16 in 

1241 most cases. 

1242 full : bool, optional 

1243 Switch determining the nature of the return value. When ``False`` 

1244 (the default) just the coefficients are returned; when ``True``, 

1245 diagnostic information from the singular value decomposition (used 

1246 to solve the fit's matrix equation) is also returned. 

1247 w : array_like, shape (`M`,), optional 

1248 Weights. If not None, the contribution of each point 

1249 ``(x[i],y[i])`` to the fit is weighted by `w[i]`. Ideally the 

1250 weights are chosen so that the errors of the products ``w[i]*y[i]`` 

1251 all have the same variance. The default value is None. 

1252 

1253 .. versionadded:: 1.5.0 

1254 

1255 Returns 

1256 ------- 

1257 coef : ndarray, shape (`deg` + 1,) or (`deg` + 1, `K`) 

1258 Polynomial coefficients ordered from low to high. If `y` was 2-D, 

1259 the coefficients in column `k` of `coef` represent the polynomial 

1260 fit to the data in `y`'s `k`-th column. 

1261 

1262 [residuals, rank, singular_values, rcond] : list 

1263 These values are only returned if `full` = True 

1264 

1265 resid -- sum of squared residuals of the least squares fit 

1266 rank -- the numerical rank of the scaled Vandermonde matrix 

1267 sv -- singular values of the scaled Vandermonde matrix 

1268 rcond -- value of `rcond`. 

1269 

1270 For more details, see `linalg.lstsq`. 

1271 

1272 Raises 

1273 ------ 

1274 RankWarning 

1275 Raised if the matrix in the least-squares fit is rank deficient. 

1276 The warning is only raised if `full` == False. The warnings can 

1277 be turned off by: 

1278 

1279 >>> import warnings 

1280 >>> warnings.simplefilter('ignore', np.RankWarning) 

1281 

1282 See Also 

1283 -------- 

1284 chebfit, legfit, lagfit, hermfit, hermefit 

1285 polyval : Evaluates a polynomial. 

1286 polyvander : Vandermonde matrix for powers. 

1287 linalg.lstsq : Computes a least-squares fit from the matrix. 

1288 scipy.interpolate.UnivariateSpline : Computes spline fits. 

1289 

1290 Notes 

1291 ----- 

1292 The solution is the coefficients of the polynomial `p` that minimizes 

1293 the sum of the weighted squared errors 

1294 

1295 .. math :: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2, 

1296 

1297 where the :math:`w_j` are the weights. This problem is solved by 

1298 setting up the (typically) over-determined matrix equation: 

1299 

1300 .. math :: V(x) * c = w * y, 

1301 

1302 where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the 

1303 coefficients to be solved for, `w` are the weights, and `y` are the 

1304 observed values. This equation is then solved using the singular value 

1305 decomposition of `V`. 

1306 

1307 If some of the singular values of `V` are so small that they are 

1308 neglected (and `full` == ``False``), a `RankWarning` will be raised. 

1309 This means that the coefficient values may be poorly determined. 

1310 Fitting to a lower order polynomial will usually get rid of the warning 

1311 (but may not be what you want, of course; if you have independent 

1312 reason(s) for choosing the degree which isn't working, you may have to: 

1313 a) reconsider those reasons, and/or b) reconsider the quality of your 

1314 data). The `rcond` parameter can also be set to a value smaller than 

1315 its default, but the resulting fit may be spurious and have large 

1316 contributions from roundoff error. 

1317 

1318 Polynomial fits using double precision tend to "fail" at about 

1319 (polynomial) degree 20. Fits using Chebyshev or Legendre series are 

1320 generally better conditioned, but much can still depend on the 

1321 distribution of the sample points and the smoothness of the data. If 

1322 the quality of the fit is inadequate, splines may be a good 

1323 alternative. 

1324 

1325 Examples 

1326 -------- 

1327 >>> np.random.seed(123) 

1328 >>> from numpy.polynomial import polynomial as P 

1329 >>> x = np.linspace(-1,1,51) # x "data": [-1, -0.96, ..., 0.96, 1] 

1330 >>> y = x**3 - x + np.random.randn(len(x)) # x^3 - x + N(0,1) "noise" 

1331 >>> c, stats = P.polyfit(x,y,3,full=True) 

1332 >>> np.random.seed(123) 

1333 >>> c # c[0], c[2] should be approx. 0, c[1] approx. -1, c[3] approx. 1 

1334 array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286]) # may vary 

1335 >>> stats # note the large SSR, explaining the rather poor results 

1336 [array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316, # may vary 

1337 0.28853036]), 1.1324274851176597e-014] 

1338 

1339 Same thing without the added noise 

1340 

1341 >>> y = x**3 - x 

1342 >>> c, stats = P.polyfit(x,y,3,full=True) 

1343 >>> c # c[0], c[2] should be "very close to 0", c[1] ~= -1, c[3] ~= 1 

1344 array([-6.36925336e-18, -1.00000000e+00, -4.08053781e-16, 1.00000000e+00]) 

1345 >>> stats # note the minuscule SSR 

1346 [array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158, # may vary 

1347 0.50443316, 0.28853036]), 1.1324274851176597e-014] 

1348 

1349 """ 

1350 return pu._fit(polyvander, x, y, deg, rcond, full, w) 

1351 

1352 

1353def polycompanion(c): 

1354 """ 

1355 Return the companion matrix of c. 

1356 

1357 The companion matrix for power series cannot be made symmetric by 

1358 scaling the basis, so this function differs from those for the 

1359 orthogonal polynomials. 

1360 

1361 Parameters 

1362 ---------- 

1363 c : array_like 

1364 1-D array of polynomial coefficients ordered from low to high 

1365 degree. 

1366 

1367 Returns 

1368 ------- 

1369 mat : ndarray 

1370 Companion matrix of dimensions (deg, deg). 

1371 

1372 Notes 

1373 ----- 

1374 

1375 .. versionadded:: 1.7.0 

1376 

1377 """ 

1378 # c is a trimmed copy 

1379 [c] = pu.as_series([c]) 

1380 if len(c) < 2: 

1381 raise ValueError('Series must have maximum degree of at least 1.') 

1382 if len(c) == 2: 

1383 return np.array([[-c[0]/c[1]]]) 

1384 

1385 n = len(c) - 1 

1386 mat = np.zeros((n, n), dtype=c.dtype) 

1387 bot = mat.reshape(-1)[n::n+1] 

1388 bot[...] = 1 

1389 mat[:, -1] -= c[:-1]/c[-1] 

1390 return mat 

1391 

1392 

1393def polyroots(c): 

1394 """ 

1395 Compute the roots of a polynomial. 

1396 

1397 Return the roots (a.k.a. "zeros") of the polynomial 

1398 

1399 .. math:: p(x) = \\sum_i c[i] * x^i. 

1400 

1401 Parameters 

1402 ---------- 

1403 c : 1-D array_like 

1404 1-D array of polynomial coefficients. 

1405 

1406 Returns 

1407 ------- 

1408 out : ndarray 

1409 Array of the roots of the polynomial. If all the roots are real, 

1410 then `out` is also real, otherwise it is complex. 

1411 

1412 See Also 

1413 -------- 

1414 chebroots 

1415 

1416 Notes 

1417 ----- 

1418 The root estimates are obtained as the eigenvalues of the companion 

1419 matrix, Roots far from the origin of the complex plane may have large 

1420 errors due to the numerical instability of the power series for such 

1421 values. Roots with multiplicity greater than 1 will also show larger 

1422 errors as the value of the series near such points is relatively 

1423 insensitive to errors in the roots. Isolated roots near the origin can 

1424 be improved by a few iterations of Newton's method. 

1425 

1426 Examples 

1427 -------- 

1428 >>> import numpy.polynomial.polynomial as poly 

1429 >>> poly.polyroots(poly.polyfromroots((-1,0,1))) 

1430 array([-1., 0., 1.]) 

1431 >>> poly.polyroots(poly.polyfromroots((-1,0,1))).dtype 

1432 dtype('float64') 

1433 >>> j = complex(0,1) 

1434 >>> poly.polyroots(poly.polyfromroots((-j,0,j))) 

1435 array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j]) # may vary 

1436 

1437 """ 

1438 # c is a trimmed copy 

1439 [c] = pu.as_series([c]) 

1440 if len(c) < 2: 

1441 return np.array([], dtype=c.dtype) 

1442 if len(c) == 2: 

1443 return np.array([-c[0]/c[1]]) 

1444 

1445 # rotated companion matrix reduces error 

1446 m = polycompanion(c)[::-1,::-1] 

1447 r = la.eigvals(m) 

1448 r.sort() 

1449 return r 

1450 

1451 

1452# 

1453# polynomial class 

1454# 

1455 

1456class Polynomial(ABCPolyBase): 

1457 """A power series class. 

1458 

1459 The Polynomial class provides the standard Python numerical methods 

1460 '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the 

1461 attributes and methods listed in the `ABCPolyBase` documentation. 

1462 

1463 Parameters 

1464 ---------- 

1465 coef : array_like 

1466 Polynomial coefficients in order of increasing degree, i.e., 

1467 ``(1, 2, 3)`` give ``1 + 2*x + 3*x**2``. 

1468 domain : (2,) array_like, optional 

1469 Domain to use. The interval ``[domain[0], domain[1]]`` is mapped 

1470 to the interval ``[window[0], window[1]]`` by shifting and scaling. 

1471 The default value is [-1, 1]. 

1472 window : (2,) array_like, optional 

1473 Window, see `domain` for its use. The default value is [-1, 1]. 

1474 

1475 .. versionadded:: 1.6.0 

1476 

1477 """ 

1478 # Virtual Functions 

1479 _add = staticmethod(polyadd) 

1480 _sub = staticmethod(polysub) 

1481 _mul = staticmethod(polymul) 

1482 _div = staticmethod(polydiv) 

1483 _pow = staticmethod(polypow) 

1484 _val = staticmethod(polyval) 

1485 _int = staticmethod(polyint) 

1486 _der = staticmethod(polyder) 

1487 _fit = staticmethod(polyfit) 

1488 _line = staticmethod(polyline) 

1489 _roots = staticmethod(polyroots) 

1490 _fromroots = staticmethod(polyfromroots) 

1491 

1492 # Virtual properties 

1493 nickname = 'poly' 

1494 domain = np.array(polydomain) 

1495 window = np.array(polydomain) 

1496 basis_name = None 

1497 

1498 @staticmethod 

1499 def _repr_latex_term(i, arg_str, needs_parens): 

1500 if needs_parens: 

1501 arg_str = rf"\left({arg_str}\right)" 

1502 if i == 0: 

1503 return '1' 

1504 elif i == 1: 

1505 return arg_str 

1506 else: 

1507 return f"{arg_str}^{{{i}}}"