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

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