Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
chebyshev.py2002 linesDownload Raw Back to polynomial
1"""
2====================================================
3Chebyshev Series (:mod:`numpy.polynomial.chebyshev`)
4====================================================
5
6This module provides a number of objects (mostly functions) useful for
7dealing with Chebyshev series, including a `Chebyshev` class that
8encapsulates the usual arithmetic operations.  (General information
9on how this module represents and works with such polynomials is in the
10docstring for its "parent" sub-package, `numpy.polynomial`).
11
12Classes
13-------
14
15.. autosummary::
16   :toctree: generated/
17
18   Chebyshev
19
20
21Constants
22---------
23
24.. autosummary::
25   :toctree: generated/
26
27   chebdomain
28   chebzero
29   chebone
30   chebx
31
32Arithmetic
33----------
34
35.. autosummary::
36   :toctree: generated/
37
38   chebadd
39   chebsub
40   chebmulx
41   chebmul
42   chebdiv
43   chebpow
44   chebval
45   chebval2d
46   chebval3d
47   chebgrid2d
48   chebgrid3d
49
50Calculus
51--------
52
53.. autosummary::
54   :toctree: generated/
55
56   chebder
57   chebint
58
59Misc Functions
60--------------
61
62.. autosummary::
63   :toctree: generated/
64
65   chebfromroots
66   chebroots
67   chebvander
68   chebvander2d
69   chebvander3d
70   chebgauss
71   chebweight
72   chebcompanion
73   chebfit
74   chebpts1
75   chebpts2
76   chebtrim
77   chebline
78   cheb2poly
79   poly2cheb
80   chebinterpolate
81
82See also
83--------
84`numpy.polynomial`
85
86Notes
87-----
88The implementations of multiplication, division, integration, and
89differentiation use the algebraic identities [1]_:
90
91.. math::
92    T_n(x) = \\frac{z^n + z^{-n}}{2} \\\\
93    z\\frac{dx}{dz} = \\frac{z - z^{-1}}{2}.
94
95where
96
97.. math:: x = \\frac{z + z^{-1}}{2}.
98
99These identities allow a Chebyshev series to be expressed as a finite,
100symmetric Laurent series.  In this module, this sort of Laurent series
101is referred to as a "z-series."
102
103References
104----------
105.. [1] A. T. Benjamin, et al., "Combinatorial Trigonometry with Chebyshev
106  Polynomials," *Journal of Statistical Planning and Inference 14*, 2008
107  (https://web.archive.org/web/20080221202153/https://www.math.hmc.edu/~benjamin/papers/CombTrig.pdf, pg. 4)
108
109"""  # noqa: E501
110import numpy as np
111
112from . import polyutils as pu
113from ._polybase import ABCPolyBase
114
115__all__ = [
116    'chebzero', 'chebone', 'chebx', 'chebdomain', 'chebline', 'chebadd',
117    'chebsub', 'chebmulx', 'chebmul', 'chebdiv', 'chebpow', 'chebval',
118    'chebder', 'chebint', 'cheb2poly', 'poly2cheb', 'chebfromroots',
119    'chebvander', 'chebfit', 'chebtrim', 'chebroots', 'chebpts1',
120    'chebpts2', 'Chebyshev', 'chebval2d', 'chebval3d', 'chebgrid2d',
121    'chebgrid3d', 'chebvander2d', 'chebvander3d', 'chebcompanion',
122    'chebgauss', 'chebweight', 'chebinterpolate']
123
124chebtrim = pu.trimcoef
125
126#
127# A collection of functions for manipulating z-series. These are private
128# functions and do minimal error checking.
129#
130
131def _cseries_to_zseries(c):
132    """Convert Chebyshev series to z-series.
133
134    Convert a Chebyshev series to the equivalent z-series. The result is
135    never an empty array. The dtype of the return is the same as that of
136    the input. No checks are run on the arguments as this routine is for
137    internal use.
138
139    Parameters
140    ----------
141    c : 1-D ndarray
142        Chebyshev coefficients, ordered from low to high
143
144    Returns
145    -------
146    zs : 1-D ndarray
147        Odd length symmetric z-series, ordered from  low to high.
148
149    """
150    n = c.size
151    zs = np.zeros(2 * n - 1, dtype=c.dtype)
152    zs[n - 1:] = c / 2
153    return zs + zs[::-1]
154
155
156def _zseries_to_cseries(zs):
157    """Convert z-series to a Chebyshev series.
158
159    Convert a z series to the equivalent Chebyshev series. The result is
160    never an empty array. The dtype of the return is the same as that of
161    the input. No checks are run on the arguments as this routine is for
162    internal use.
163
164    Parameters
165    ----------
166    zs : 1-D ndarray
167        Odd length symmetric z-series, ordered from  low to high.
168
169    Returns
170    -------
171    c : 1-D ndarray
172        Chebyshev coefficients, ordered from  low to high.
173
174    """
175    n = (zs.size + 1) // 2
176    c = zs[n - 1:].copy()
177    c[1:n] *= 2
178    return c
179
180
181def _zseries_mul(z1, z2):
182    """Multiply two z-series.
183
184    Multiply two z-series to produce a z-series.
185
186    Parameters
187    ----------
188    z1, z2 : 1-D ndarray
189        The arrays must be 1-D but this is not checked.
190
191    Returns
192    -------
193    product : 1-D ndarray
194        The product z-series.
195
196    Notes
197    -----
198    This is simply convolution. If symmetric/anti-symmetric z-series are
199    denoted by S/A then the following rules apply:
200
201    S*S, A*A -> S
202    S*A, A*S -> A
203
204    """
205    return np.convolve(z1, z2)
206
207
208def _zseries_div(z1, z2):
209    """Divide the first z-series by the second.
210
211    Divide `z1` by `z2` and return the quotient and remainder as z-series.
212    Warning: this implementation only applies when both z1 and z2 have the
213    same symmetry, which is sufficient for present purposes.
214
215    Parameters
216    ----------
217    z1, z2 : 1-D ndarray
218        The arrays must be 1-D and have the same symmetry, but this is not
219        checked.
220
221    Returns
222    -------
223
224    (quotient, remainder) : 1-D ndarrays
225        Quotient and remainder as z-series.
226
227    Notes
228    -----
229    This is not the same as polynomial division on account of the desired form
230    of the remainder. If symmetric/anti-symmetric z-series are denoted by S/A
231    then the following rules apply:
232
233    S/S -> S,S
234    A/A -> S,A
235
236    The restriction to types of the same symmetry could be fixed but seems like
237    unneeded generality. There is no natural form for the remainder in the case
238    where there is no symmetry.
239
240    """
241    z1 = z1.copy()
242    z2 = z2.copy()
243    lc1 = len(z1)
244    lc2 = len(z2)
245    if lc2 == 1:
246        z1 /= z2
247        return z1, z1[:1] * 0
248    elif lc1 < lc2:
249        return z1[:1] * 0, z1
250    else:
251        dlen = lc1 - lc2
252        scl = z2[0]
253        z2 /= scl
254        quo = np.empty(dlen + 1, dtype=z1.dtype)
255        i = 0
256        j = dlen
257        while i < j:
258            r = z1[i]
259            quo[i] = z1[i]
260            quo[dlen - i] = r
261            tmp = r * z2
262            z1[i:i + lc2] -= tmp
263            z1[j:j + lc2] -= tmp
264            i += 1
265            j -= 1
266        r = z1[i]
267        quo[i] = r
268        tmp = r * z2
269        z1[i:i + lc2] -= tmp
270        quo /= scl
271        rem = z1[i + 1:i - 1 + lc2].copy()
272        return quo, rem
273
274
275def _zseries_der(zs):
276    """Differentiate a z-series.
277
278    The derivative is with respect to x, not z. This is achieved using the
279    chain rule and the value of dx/dz given in the module notes.
280
281    Parameters
282    ----------
283    zs : z-series
284        The z-series to differentiate.
285
286    Returns
287    -------
288    derivative : z-series
289        The derivative
290
291    Notes
292    -----
293    The zseries for x (ns) has been multiplied by two in order to avoid
294    using floats that are incompatible with Decimal and likely other
295    specialized scalar types. This scaling has been compensated by
296    multiplying the value of zs by two also so that the two cancels in the
297    division.
298
299    """
300    n = len(zs) // 2
301    ns = np.array([-1, 0, 1], dtype=zs.dtype)
302    zs *= np.arange(-n, n + 1) * 2
303    d, r = _zseries_div(zs, ns)
304    return d
305
306
307def _zseries_int(zs):
308    """Integrate a z-series.
309
310    The integral is with respect to x, not z. This is achieved by a change
311    of variable using dx/dz given in the module notes.
312
313    Parameters
314    ----------
315    zs : z-series
316        The z-series to integrate
317
318    Returns
319    -------
320    integral : z-series
321        The indefinite integral
322
323    Notes
324    -----
325    The zseries for x (ns) has been multiplied by two in order to avoid
326    using floats that are incompatible with Decimal and likely other
327    specialized scalar types. This scaling has been compensated by
328    dividing the resulting zs by two.
329
330    """
331    n = 1 + len(zs) // 2
332    ns = np.array([-1, 0, 1], dtype=zs.dtype)
333    zs = _zseries_mul(zs, ns)
334    div = np.arange(-n, n + 1) * 2
335    zs[:n] /= div[:n]
336    zs[n + 1:] /= div[n + 1:]
337    zs[n] = 0
338    return zs
339
340#
341# Chebyshev series functions
342#
343
344
345def poly2cheb(pol):
346    """
347    Convert a polynomial to a Chebyshev series.
348
349    Convert an array representing the coefficients of a polynomial (relative
350    to the "standard" basis) ordered from lowest degree to highest, to an
351    array of the coefficients of the equivalent Chebyshev series, ordered
352    from lowest to highest degree.
353
354    Parameters
355    ----------
356    pol : array_like
357        1-D array containing the polynomial coefficients
358
359    Returns
360    -------
361    c : ndarray
362        1-D array containing the coefficients of the equivalent Chebyshev
363        series.
364
365    See Also
366    --------
367    cheb2poly
368
369    Notes
370    -----
371    The easy way to do conversions between polynomial basis sets
372    is to use the convert method of a class instance.
373
374    Examples
375    --------
376    >>> from numpy import polynomial as P
377    >>> p = P.Polynomial(range(4))
378    >>> p
379    Polynomial([0., 1., 2., 3.], domain=[-1.,  1.], window=[-1.,  1.], symbol='x')
380    >>> c = p.convert(kind=P.Chebyshev)
381    >>> c
382    Chebyshev([1.  , 3.25, 1.  , 0.75], domain=[-1.,  1.], window=[-1., ...
383    >>> P.chebyshev.poly2cheb(range(4))
384    array([1.  , 3.25, 1.  , 0.75])
385
386    """
387    [pol] = pu.as_series([pol])
388    deg = len(pol) - 1
389    res = 0
390    for i in range(deg, -1, -1):
391        res = chebadd(chebmulx(res), pol[i])
392    return res
393
394
395def cheb2poly(c):
396    """
397    Convert a Chebyshev series to a polynomial.
398
399    Convert an array representing the coefficients of a Chebyshev series,
400    ordered from lowest degree to highest, to an array of the coefficients
401    of the equivalent polynomial (relative to the "standard" basis) ordered
402    from lowest to highest degree.
403
404    Parameters
405    ----------
406    c : array_like
407        1-D array containing the Chebyshev series coefficients, ordered
408        from lowest order term to highest.
409
410    Returns
411    -------
412    pol : ndarray
413        1-D array containing the coefficients of the equivalent polynomial
414        (relative to the "standard" basis) ordered from lowest order term
415        to highest.
416
417    See Also
418    --------
419    poly2cheb
420
421    Notes
422    -----
423    The easy way to do conversions between polynomial basis sets
424    is to use the convert method of a class instance.
425
426    Examples
427    --------
428    >>> from numpy import polynomial as P
429    >>> c = P.Chebyshev(range(4))
430    >>> c
431    Chebyshev([0., 1., 2., 3.], domain=[-1.,  1.], window=[-1.,  1.], symbol='x')
432    >>> p = c.convert(kind=P.Polynomial)
433    >>> p
434    Polynomial([-2., -8.,  4., 12.], domain=[-1.,  1.], window=[-1.,  1.], ...
435    >>> P.chebyshev.cheb2poly(range(4))
436    array([-2.,  -8.,   4.,  12.])
437
438    """
439    from .polynomial import polyadd, polymulx, polysub
440
441    [c] = pu.as_series([c])
442    n = len(c)
443    if n < 3:
444        return c
445    else:
446        c0 = c[-2]
447        c1 = c[-1]
448        # i is the current degree of c1
449        for i in range(n - 1, 1, -1):
450            tmp = c0
451            c0 = polysub(c[i - 2], c1)
452            c1 = polyadd(tmp, polymulx(c1) * 2)
453        return polyadd(c0, polymulx(c1))
454
455
456#
457# These are constant arrays are of integer type so as to be compatible
458# with the widest range of other types, such as Decimal.
459#
460
461# Chebyshev default domain.
462chebdomain = np.array([-1., 1.])
463
464# Chebyshev coefficients representing zero.
465chebzero = np.array([0])
466
467# Chebyshev coefficients representing one.
468chebone = np.array([1])
469
470# Chebyshev coefficients representing the identity x.
471chebx = np.array([0, 1])
472
473
474def chebline(off, scl):
475    """
476    Chebyshev series whose graph is a straight line.
477
478    Parameters
479    ----------
480    off, scl : scalars
481        The specified line is given by ``off + scl*x``.
482
483    Returns
484    -------
485    y : ndarray
486        This module's representation of the Chebyshev series for
487        ``off + scl*x``.
488
489    See Also
490    --------
491    numpy.polynomial.polynomial.polyline
492    numpy.polynomial.legendre.legline
493    numpy.polynomial.laguerre.lagline
494    numpy.polynomial.hermite.hermline
495    numpy.polynomial.hermite_e.hermeline
496
497    Examples
498    --------
499    >>> import numpy.polynomial.chebyshev as C
500    >>> C.chebline(3,2)
501    array([3, 2])
502    >>> C.chebval(-3, C.chebline(3,2)) # should be -3
503    -3.0
504
505    """
506    if scl != 0:
507        return np.array([off, scl])
508    else:
509        return np.array([off])
510
511
512def chebfromroots(roots):
513    """
514    Generate a Chebyshev series with given roots.
515
516    The function returns the coefficients of the polynomial
517
518    .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
519
520    in Chebyshev form, where the :math:`r_n` are the roots specified in
521    `roots`.  If a zero has multiplicity n, then it must appear in `roots`
522    n times.  For instance, if 2 is a root of multiplicity three and 3 is a
523    root of multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3].
524    The roots can appear in any order.
525
526    If the returned coefficients are `c`, then
527
528    .. math:: p(x) = c_0 + c_1 * T_1(x) + ... +  c_n * T_n(x)
529
530    The coefficient of the last term is not generally 1 for monic
531    polynomials in Chebyshev form.
532
533    Parameters
534    ----------
535    roots : array_like
536        Sequence containing the roots.
537
538    Returns
539    -------
540    out : ndarray
541        1-D array of coefficients.  If all roots are real then `out` is a
542        real array, if some of the roots are complex, then `out` is complex
543        even if all the coefficients in the result are real (see Examples
544        below).
545
546    See Also
547    --------
548    numpy.polynomial.polynomial.polyfromroots
549    numpy.polynomial.legendre.legfromroots
550    numpy.polynomial.laguerre.lagfromroots
551    numpy.polynomial.hermite.hermfromroots
552    numpy.polynomial.hermite_e.hermefromroots
553
554    Examples
555    --------
556    >>> import numpy.polynomial.chebyshev as C
557    >>> C.chebfromroots((-1,0,1)) # x^3 - x relative to the standard basis
558    array([ 0.  , -0.25,  0.  ,  0.25])
559    >>> j = complex(0,1)
560    >>> C.chebfromroots((-j,j)) # x^2 + 1 relative to the standard basis
561    array([1.5+0.j, 0. +0.j, 0.5+0.j])
562
563    """
564    return pu._fromroots(chebline, chebmul, roots)
565
566
567def chebadd(c1, c2):
568    """
569    Add one Chebyshev series to another.
570
571    Returns the sum of two Chebyshev series `c1` + `c2`.  The arguments
572    are sequences of coefficients ordered from lowest order term to
573    highest, i.e., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
574
575    Parameters
576    ----------
577    c1, c2 : array_like
578        1-D arrays of Chebyshev series coefficients ordered from low to
579        high.
580
581    Returns
582    -------
583    out : ndarray
584        Array representing the Chebyshev series of their sum.
585
586    See Also
587    --------
588    chebsub, chebmulx, chebmul, chebdiv, chebpow
589
590    Notes
591    -----
592    Unlike multiplication, division, etc., the sum of two Chebyshev series
593    is a Chebyshev series (without having to "reproject" the result onto
594    the basis set) so addition, just like that of "standard" polynomials,
595    is simply "component-wise."
596
597    Examples
598    --------
599    >>> from numpy.polynomial import chebyshev as C
600    >>> c1 = (1,2,3)
601    >>> c2 = (3,2,1)
602    >>> C.chebadd(c1,c2)
603    array([4., 4., 4.])
604
605    """
606    return pu._add(c1, c2)
607
608
609def chebsub(c1, c2):
610    """
611    Subtract one Chebyshev series from another.
612
613    Returns the difference of two Chebyshev series `c1` - `c2`.  The
614    sequences of coefficients are from lowest order term to highest, i.e.,
615    [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
616
617    Parameters
618    ----------
619    c1, c2 : array_like
620        1-D arrays of Chebyshev series coefficients ordered from low to
621        high.
622
623    Returns
624    -------
625    out : ndarray
626        Of Chebyshev series coefficients representing their difference.
627
628    See Also
629    --------
630    chebadd, chebmulx, chebmul, chebdiv, chebpow
631
632    Notes
633    -----
634    Unlike multiplication, division, etc., the difference of two Chebyshev
635    series is a Chebyshev series (without having to "reproject" the result
636    onto the basis set) so subtraction, just like that of "standard"
637    polynomials, is simply "component-wise."
638
639    Examples
640    --------
641    >>> from numpy.polynomial import chebyshev as C
642    >>> c1 = (1,2,3)
643    >>> c2 = (3,2,1)
644    >>> C.chebsub(c1,c2)
645    array([-2.,  0.,  2.])
646    >>> C.chebsub(c2,c1) # -C.chebsub(c1,c2)
647    array([ 2.,  0., -2.])
648
649    """
650    return pu._sub(c1, c2)
651
652
653def chebmulx(c):
654    """Multiply a Chebyshev series by x.
655
656    Multiply the polynomial `c` by x, where x is the independent
657    variable.
658
659
660    Parameters
661    ----------
662    c : array_like
663        1-D array of Chebyshev series coefficients ordered from low to
664        high.
665
666    Returns
667    -------
668    out : ndarray
669        Array representing the result of the multiplication.
670
671    See Also
672    --------
673    chebadd, chebsub, chebmul, chebdiv, chebpow
674
675    Examples
676    --------
677    >>> from numpy.polynomial import chebyshev as C
678    >>> C.chebmulx([1,2,3])
679    array([1. , 2.5, 1. , 1.5])
680
681    """
682    # c is a trimmed copy
683    [c] = pu.as_series([c])
684    # The zero series needs special treatment
685    if len(c) == 1 and c[0] == 0:
686        return c
687
688    prd = np.empty(len(c) + 1, dtype=c.dtype)
689    prd[0] = c[0] * 0
690    prd[1] = c[0]
691    if len(c) > 1:
692        tmp = c[1:] / 2
693        prd[2:] = tmp
694        prd[0:-2] += tmp
695    return prd
696
697
698def chebmul(c1, c2):
699    """
700    Multiply one Chebyshev series by another.
701
702    Returns the product of two Chebyshev series `c1` * `c2`.  The arguments
703    are sequences of coefficients, from lowest order "term" to highest,
704    e.g., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
705
706    Parameters
707    ----------
708    c1, c2 : array_like
709        1-D arrays of Chebyshev series coefficients ordered from low to
710        high.
711
712    Returns
713    -------
714    out : ndarray
715        Of Chebyshev series coefficients representing their product.
716
717    See Also
718    --------
719    chebadd, chebsub, chebmulx, chebdiv, chebpow
720
721    Notes
722    -----
723    In general, the (polynomial) product of two C-series results in terms
724    that are not in the Chebyshev polynomial basis set.  Thus, to express
725    the product as a C-series, it is typically necessary to "reproject"
726    the product onto said basis set, which typically produces
727    "unintuitive live" (but correct) results; see Examples section below.
728
729    Examples
730    --------
731    >>> from numpy.polynomial import chebyshev as C
732    >>> c1 = (1,2,3)
733    >>> c2 = (3,2,1)
734    >>> C.chebmul(c1,c2) # multiplication requires "reprojection"
735    array([  6.5,  12. ,  12. ,   4. ,   1.5])
736
737    """
738    # c1, c2 are trimmed copies
739    [c1, c2] = pu.as_series([c1, c2])
740    z1 = _cseries_to_zseries(c1)
741    z2 = _cseries_to_zseries(c2)
742    prd = _zseries_mul(z1, z2)
743    ret = _zseries_to_cseries(prd)
744    return pu.trimseq(ret)
745
746
747def chebdiv(c1, c2):
748    """
749    Divide one Chebyshev series by another.
750
751    Returns the quotient-with-remainder of two Chebyshev series
752    `c1` / `c2`.  The arguments are sequences of coefficients from lowest
753    order "term" to highest, e.g., [1,2,3] represents the series
754    ``T_0 + 2*T_1 + 3*T_2``.
755
756    Parameters
757    ----------
758    c1, c2 : array_like
759        1-D arrays of Chebyshev series coefficients ordered from low to
760        high.
761
762    Returns
763    -------
764    [quo, rem] : ndarrays
765        Of Chebyshev series coefficients representing the quotient and
766        remainder.
767
768    See Also
769    --------
770    chebadd, chebsub, chebmulx, chebmul, chebpow
771
772    Notes
773    -----
774    In general, the (polynomial) division of one C-series by another
775    results in quotient and remainder terms that are not in the Chebyshev
776    polynomial basis set.  Thus, to express these results as C-series, it
777    is typically necessary to "reproject" the results onto said basis
778    set, which typically produces "unintuitive" (but correct) results;
779    see Examples section below.
780
781    Examples
782    --------
783    >>> from numpy.polynomial import chebyshev as C
784    >>> c1 = (1,2,3)
785    >>> c2 = (3,2,1)
786    >>> C.chebdiv(c1,c2) # quotient "intuitive," remainder not
787    (array([3.]), array([-8., -4.]))
788    >>> c2 = (0,1,2,3)
789    >>> C.chebdiv(c2,c1) # neither "intuitive"
790    (array([0., 2.]), array([-2., -4.]))
791
792    """
793    # c1, c2 are trimmed copies
794    [c1, c2] = pu.as_series([c1, c2])
795    if c2[-1] == 0:
796        raise ZeroDivisionError  # FIXME: add message with details to exception
797
798    # note: this is more efficient than `pu._div(chebmul, c1, c2)`
799    lc1 = len(c1)
800    lc2 = len(c2)
801    if lc1 < lc2:
802        return c1[:1] * 0, c1
803    elif lc2 == 1:
804        return c1 / c2[-1], c1[:1] * 0
805    else:
806        z1 = _cseries_to_zseries(c1)
807        z2 = _cseries_to_zseries(c2)
808        quo, rem = _zseries_div(z1, z2)
809        quo = pu.trimseq(_zseries_to_cseries(quo))
810        rem = pu.trimseq(_zseries_to_cseries(rem))
811        return quo, rem
812
813
814def chebpow(c, pow, maxpower=16):
815    """Raise a Chebyshev series to a power.
816
817    Returns the Chebyshev series `c` raised to the power `pow`. The
818    argument `c` is a sequence of coefficients ordered from low to high.
819    i.e., [1,2,3] is the series  ``T_0 + 2*T_1 + 3*T_2.``
820
821    Parameters
822    ----------
823    c : array_like
824        1-D array of Chebyshev series coefficients ordered from low to
825        high.
826    pow : integer
827        Power to which the series will be raised
828    maxpower : integer, optional
829        Maximum power allowed. This is mainly to limit growth of the series
830        to unmanageable size. Default is 16
831
832    Returns
833    -------
834    coef : ndarray
835        Chebyshev series of power.
836
837    See Also
838    --------
839    chebadd, chebsub, chebmulx, chebmul, chebdiv
840
841    Examples
842    --------
843    >>> from numpy.polynomial import chebyshev as C
844    >>> C.chebpow([1, 2, 3, 4], 2)
845    array([15.5, 22. , 16. , ..., 12.5, 12. ,  8. ])
846
847    """
848    # note: this is more efficient than `pu._pow(chebmul, c1, c2)`, as it
849    # avoids converting between z and c series repeatedly
850
851    # c is a trimmed copy
852    [c] = pu.as_series([c])
853    power = int(pow)
854    if power != pow or power < 0:
855        raise ValueError("Power must be a non-negative integer.")
856    elif maxpower is not None and power > maxpower:
857        raise ValueError("Power is too large")
858    elif power == 0:
859        return np.array([1], dtype=c.dtype)
860    elif power == 1:
861        return c
862    else:
863        # This can be made more efficient by using powers of two
864        # in the usual way.
865        zs = _cseries_to_zseries(c)
866        prd = zs
867        for i in range(2, power + 1):
868            prd = np.convolve(prd, zs)
869        return _zseries_to_cseries(prd)
870
871
872def chebder(c, m=1, scl=1, axis=0):
873    """
874    Differentiate a Chebyshev series.
875
876    Returns the Chebyshev series coefficients `c` differentiated `m` times
877    along `axis`.  At each iteration the result is multiplied by `scl` (the
878    scaling factor is for use in a linear change of variable). The argument
879    `c` is an array of coefficients from low to high degree along each
880    axis, e.g., [1,2,3] represents the series ``1*T_0 + 2*T_1 + 3*T_2``
881    while [[1,2],[1,2]] represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) +
882    2*T_0(x)*T_1(y) + 2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is
883    ``y``.
884
885    Parameters
886    ----------
887    c : array_like
888        Array of Chebyshev series coefficients. If c is multidimensional
889        the different axis correspond to different variables with the
890        degree in each axis given by the corresponding index.
891    m : int, optional
892        Number of derivatives taken, must be non-negative. (Default: 1)
893    scl : scalar, optional
894        Each differentiation is multiplied by `scl`.  The end result is
895        multiplication by ``scl**m``.  This is for use in a linear change of
896        variable. (Default: 1)
897    axis : int, optional
898        Axis over which the derivative is taken. (Default: 0).
899
900    Returns
901    -------
902    der : ndarray
903        Chebyshev series of the derivative.
904
905    See Also
906    --------
907    chebint
908
909    Notes
910    -----
911    In general, the result of differentiating a C-series needs to be
912    "reprojected" onto the C-series basis set. Thus, typically, the
913    result of this function is "unintuitive," albeit correct; see Examples
914    section below.
915
916    Examples
917    --------
918    >>> from numpy.polynomial import chebyshev as C
919    >>> c = (1,2,3,4)
920    >>> C.chebder(c)
921    array([14., 12., 24.])
922    >>> C.chebder(c,3)
923    array([96.])
924    >>> C.chebder(c,scl=-1)
925    array([-14., -12., -24.])
926    >>> C.chebder(c,2,-1)
927    array([12.,  96.])
928
929    """
930    c = np.array(c, ndmin=1, copy=True)
931    if c.dtype.char in '?bBhHiIlLqQpP':
932        c = c.astype(np.double)
933    cnt = pu._as_int(m, "the order of derivation")
934    iaxis = pu._as_int(axis, "the axis")
935    if cnt < 0:
936        raise ValueError("The order of derivation must be non-negative")
937    iaxis = np.lib.array_utils.normalize_axis_index(iaxis, c.ndim)
938
939    if cnt == 0:
940        return c
941
942    c = np.moveaxis(c, iaxis, 0)
943    n = len(c)
944    if cnt >= n:
945        c = c[:1] * 0
946    else:
947        for i in range(cnt):
948            n = n - 1
949            c *= scl
950            der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
951            for j in range(n, 2, -1):
952                der[j - 1] = (2 * j) * c[j]
953                c[j - 2] += (j * c[j]) / (j - 2)
954            if n > 1:
955                der[1] = 4 * c[2]
956            der[0] = c[1]
957            c = der
958    c = np.moveaxis(c, 0, iaxis)
959    return c
960
961
962def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
963    """
964    Integrate a Chebyshev series.
965
966    Returns the Chebyshev series coefficients `c` integrated `m` times from
967    `lbnd` along `axis`. At each iteration the resulting series is
968    **multiplied** by `scl` and an integration constant, `k`, is added.
969    The scaling factor is for use in a linear change of variable.  ("Buyer
970    beware": note that, depending on what one is doing, one may want `scl`
971    to be the reciprocal of what one might expect; for more information,
972    see the Notes section below.)  The argument `c` is an array of
973    coefficients from low to high degree along each axis, e.g., [1,2,3]
974    represents the series ``T_0 + 2*T_1 + 3*T_2`` while [[1,2],[1,2]]
975    represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) + 2*T_0(x)*T_1(y) +
976    2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
977
978    Parameters
979    ----------
980    c : array_like
981        Array of Chebyshev series coefficients. If c is multidimensional
982        the different axis correspond to different variables with the
983        degree in each axis given by the corresponding index.
984    m : int, optional
985        Order of integration, must be positive. (Default: 1)
986    k : {[], list, scalar}, optional
987        Integration constant(s).  The value of the first integral at zero
988        is the first value in the list, the value of the second integral
989        at zero is the second value, etc.  If ``k == []`` (the default),
990        all constants are set to zero.  If ``m == 1``, a single scalar can
991        be given instead of a list.
992    lbnd : scalar, optional
993        The lower bound of the integral. (Default: 0)
994    scl : scalar, optional
995        Following each integration the result is *multiplied* by `scl`
996        before the integration constant is added. (Default: 1)
997    axis : int, optional
998        Axis over which the integral is taken. (Default: 0).
999
1000    Returns
1001    -------
1002    S : ndarray
1003        C-series coefficients of the integral.
1004
1005    Raises
1006    ------
1007    ValueError
1008        If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
1009        ``np.ndim(scl) != 0``.
1010
1011    See Also
1012    --------
1013    chebder
1014
1015    Notes
1016    -----
1017    Note that the result of each integration is *multiplied* by `scl`.
1018    Why is this important to note?  Say one is making a linear change of
1019    variable :math:`u = ax + b` in an integral relative to `x`.  Then
1020    :math:`dx = du/a`, so one will need to set `scl` equal to
1021    :math:`1/a`- perhaps not what one would have first thought.
1022
1023    Also note that, in general, the result of integrating a C-series needs
1024    to be "reprojected" onto the C-series basis set.  Thus, typically,
1025    the result of this function is "unintuitive," albeit correct; see
1026    Examples section below.
1027
1028    Examples
1029    --------
1030    >>> from numpy.polynomial import chebyshev as C
1031    >>> c = (1,2,3)
1032    >>> C.chebint(c)
1033    array([ 0.5, -0.5,  0.5,  0.5])
1034    >>> C.chebint(c,3)
1035    array([ 0.03125   , -0.1875    ,  0.04166667, -0.05208333,  0.01041667, # may vary
1036        0.00625   ])
1037    >>> C.chebint(c, k=3)
1038    array([ 3.5, -0.5,  0.5,  0.5])
1039    >>> C.chebint(c,lbnd=-2)
1040    array([ 8.5, -0.5,  0.5,  0.5])
1041    >>> C.chebint(c,scl=-2)
1042    array([-1.,  1., -1., -1.])
1043
1044    """
1045    c = np.array(c, ndmin=1, copy=True)
1046    if c.dtype.char in '?bBhHiIlLqQpP':
1047        c = c.astype(np.double)
1048    if not np.iterable(k):
1049        k = [k]
1050    cnt = pu._as_int(m, "the order of integration")
1051    iaxis = pu._as_int(axis, "the axis")
1052    if cnt < 0:
1053        raise ValueError("The order of integration must be non-negative")
1054    if len(k) > cnt:
1055        raise ValueError("Too many integration constants")
1056    if np.ndim(lbnd) != 0:
1057        raise ValueError("lbnd must be a scalar.")
1058    if np.ndim(scl) != 0:
1059        raise ValueError("scl must be a scalar.")
1060    iaxis = np.lib.array_utils.normalize_axis_index(iaxis, c.ndim)
1061
1062    if cnt == 0:
1063        return c
1064
1065    c = np.moveaxis(c, iaxis, 0)
1066    k = list(k) + [0] * (cnt - len(k))
1067    for i in range(cnt):
1068        n = len(c)
1069        c *= scl
1070        if n == 1 and np.all(c[0] == 0):
1071            c[0] += k[i]
1072        else:
1073            tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
1074            tmp[0] = c[0] * 0
1075            tmp[1] = c[0]
1076            if n > 1:
1077                tmp[2] = c[1] / 4
1078            for j in range(2, n):
1079                tmp[j + 1] = c[j] / (2 * (j + 1))
1080                tmp[j - 1] -= c[j] / (2 * (j - 1))
1081            tmp[0] += k[i] - chebval(lbnd, tmp)
1082            c = tmp
1083    c = np.moveaxis(c, 0, iaxis)
1084    return c
1085
1086
1087def chebval(x, c, tensor=True):
1088    """
1089    Evaluate a Chebyshev series at points x.
1090
1091    If `c` is of length `n + 1`, this function returns the value:
1092
1093    .. math:: p(x) = c_0 * T_0(x) + c_1 * T_1(x) + ... + c_n * T_n(x)
1094
1095    The parameter `x` is converted to an array only if it is a tuple or a
1096    list, otherwise it is treated as a scalar. In either case, either `x`
1097    or its elements must support multiplication and addition both with
1098    themselves and with the elements of `c`.
1099
1100    If `c` is a 1-D array, then ``p(x)`` will have the same shape as `x`.  If
1101    `c` is multidimensional, then the shape of the result depends on the
1102    value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
1103    x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
1104    scalars have shape (,).
1105
1106    Trailing zeros in the coefficients will be used in the evaluation, so
1107    they should be avoided if efficiency is a concern.
1108
1109    Parameters
1110    ----------
1111    x : array_like, compatible object
1112        If `x` is a list or tuple, it is converted to an ndarray, otherwise
1113        it is left unchanged and treated as a scalar. In either case, `x`
1114        or its elements must support addition and multiplication with
1115        themselves and with the elements of `c`.
1116    c : array_like
1117        Array of coefficients ordered so that the coefficients for terms of
1118        degree n are contained in c[n]. If `c` is multidimensional the
1119        remaining indices enumerate multiple polynomials. In the two
1120        dimensional case the coefficients may be thought of as stored in
1121        the columns of `c`.
1122    tensor : boolean, optional
1123        If True, the shape of the coefficient array is extended with ones
1124        on the right, one for each dimension of `x`. Scalars have dimension 0
1125        for this action. The result is that every column of coefficients in
1126        `c` is evaluated for every element of `x`. If False, `x` is broadcast
1127        over the columns of `c` for the evaluation.  This keyword is useful
1128        when `c` is multidimensional. The default value is True.
1129
1130    Returns
1131    -------
1132    values : ndarray, algebra_like
1133        The shape of the return value is described above.
1134
1135    See Also
1136    --------
1137    chebval2d, chebgrid2d, chebval3d, chebgrid3d
1138
1139    Notes
1140    -----
1141    The evaluation uses Clenshaw recursion, aka synthetic division.
1142
1143    """
1144    c = np.array(c, ndmin=1, copy=True)
1145    if c.dtype.char in '?bBhHiIlLqQpP':
1146        c = c.astype(np.double)
1147    if isinstance(x, (tuple, list)):
1148        x = np.asarray(x)
1149    if isinstance(x, np.ndarray) and tensor:
1150        c = c.reshape(c.shape + (1,) * x.ndim)
1151
1152    if len(c) == 1:
1153        c0 = c[0]
1154        c1 = 0
1155    elif len(c) == 2:
1156        c0 = c[0]
1157        c1 = c[1]
1158    else:
1159        x2 = 2 * x
1160        c0 = c[-2]
1161        c1 = c[-1]
1162        for i in range(3, len(c) + 1):
1163            tmp = c0
1164            c0 = c[-i] - c1
1165            c1 = tmp + c1 * x2
1166    return c0 + c1 * x
1167
1168
1169def chebval2d(x, y, c):
1170    """
1171    Evaluate a 2-D Chebyshev series at points (x, y).
1172
1173    This function returns the values:
1174
1175    .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * T_i(x) * T_j(y)
1176
1177    The parameters `x` and `y` are converted to arrays only if they are
1178    tuples or a lists, otherwise they are treated as a scalars and they
1179    must have the same shape after conversion. In either case, either `x`
1180    and `y` or their elements must support multiplication and addition both
1181    with themselves and with the elements of `c`.
1182
1183    If `c` is a 1-D array a one is implicitly appended to its shape to make
1184    it 2-D. The shape of the result will be c.shape[2:] + x.shape.
1185
1186    Parameters
1187    ----------
1188    x, y : array_like, compatible objects
1189        The two dimensional series is evaluated at the points ``(x, y)``,
1190        where `x` and `y` must have the same shape. If `x` or `y` is a list
1191        or tuple, it is first converted to an ndarray, otherwise it is left
1192        unchanged and if it isn't an ndarray it is treated as a scalar.
1193    c : array_like
1194        Array of coefficients ordered so that the coefficient of the term
1195        of multi-degree i,j is contained in ``c[i,j]``. If `c` has
1196        dimension greater than 2 the remaining indices enumerate multiple
1197        sets of coefficients.
1198
1199    Returns
1200    -------

Showing the first 1,200 of 2002 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai