# Orthogonal polynomials#

## Chebyshev polynomials#

The Chebyshev polynomial of the first kind arises as a solution to the differential equation

$(1-x^2)\,y'' - x\,y' + n^2\,y = 0$

and those of the second kind as a solution to

$(1-x^2)\,y'' - 3x\,y' + n(n+2)\,y = 0.$

The Chebyshev polynomials of the first kind are defined by the recurrence relation

$T_0(x) = 1, \qquad T_1(x) = x, \qquad T_{n+1}(x) = 2xT_n(x) - T_{n-1}(x).$

The Chebyshev polynomials of the second kind are defined by the recurrence relation

$U_0(x) = 1, \qquad U_1(x) = 2x, \qquad U_{n+1}(x) = 2xU_n(x) - U_{n-1}(x).$

For integers $$m,n$$, they satisfy the orthogonality relations

$\begin{split}\int_{-1}^1 T_n(x)T_m(x)\,\frac{dx}{\sqrt{1-x^2}} = \left\{ \begin{array}{cl} 0 & \text{if } n\neq m, \\ \pi & \text{if } n=m=0, \\ \pi/2 & \text{if } n = m \neq 0, \end{array} \right.\end{split}$

and

$\int_{-1}^1 U_n(x)U_m(x)\sqrt{1-x^2}\,dx =\frac{\pi}{2}\delta_{m,n}.$

They are named after Pafnuty Chebyshev (1821-1894, alternative transliterations: Tchebyshef or Tschebyscheff).

## Hermite polynomials#

The Hermite polynomials are defined either by

$H_n(x) = (-1)^n e^{x^2/2} \frac{d^n}{dx^n} e^{-x^2/2}$

(the “probabilists’ Hermite polynomials”), or by

$H_n(x) = (-1)^n e^{x^2}\frac{d^n}{dx^n}e^{-x^2}$

(the “physicists’ Hermite polynomials”). Sage (via Maxima) implements the latter flavor. These satisfy the orthogonality relation

$\int_{-\infty}^{\infty} H_n(x) H_m(x) \, e^{-x^2} \, dx = \sqrt{\pi} n! 2^n \delta_{nm}.$

They are named in honor of Charles Hermite (1822-1901), but were first introduced by Laplace in 1810 and also studied by Chebyshev in 1859.

## Legendre polynomials#

Each Legendre polynomial $$P_n(x)$$ is an $$n$$-th degree polynomial. It may be expressed using Rodrigues’ formula:

$P_n(x) = (2^n n!)^{-1} {\frac{d^n}{dx^n} } \left[ (x^2 -1)^n \right].$

These are solutions to Legendre’s differential equation:

$\frac{d}{dx} \left[ (1-x^2) {\frac{d}{dx}} P(x) \right] + n(n+1)P(x) = 0$

and satisfy the orthogonality relation

$\int_{-1}^{1} P_m(x) P_n(x)\,dx = {\frac{2}{2n + 1}} \delta_{mn}.$

The Legendre function of the second kind $$Q_n(x)$$ is another (linearly independent) solution to the Legendre differential equation. It is not an “orthogonal polynomial” however.

The associated Legendre functions of the first kind $$P_\ell^m(x)$$ can be given in terms of the “usual” Legendre polynomials by

\begin{split}\begin{aligned} P_{\ell}^m(x) &= (-1)^m(1-x^2)^{m/2}\frac{d^m}{dx^m}P_\ell(x) \\ & = \frac{(-1)^m}{2^\ell \ell!} (1-x^2)^{m/2}\frac{d^{\ell+m}}{dx^{\ell+m}}(x^2-1)^{\ell}. \end{aligned}\end{split}

Assuming $$0 \le m \le \ell$$, they satisfy the orthogonality relation:

$\int_{-1}^{1} P_k^{(m)} P_{\ell}^{(m)} dx = \frac{2(\ell+m)!}{(2\ell+1)(\ell-m)!}\ \delta _{k,\ell},$

where $$\delta _{k,\ell}$$ is the Kronecker delta.

The associated Legendre functions of the second kind $$Q_\ell^m(x)$$ can be given in terms of the “usual” Legendre polynomials by

$Q_{\ell}^m(x) = (-1)^m (1-x^2)^{m/2} \frac{d^m}{dx^m} Q_{\ell}(x).$

They are named after Adrien-Marie Legendre (1752-1833).

## Laguerre polynomials#

Laguerre polynomials may be defined by the Rodrigues formula

$L_n(x) = \frac{e^x}{n!} \frac{d^n}{dx^n} \left( e^{-x} x^n \right).$

They are solutions of Laguerre’s equation:

$x\,y'' + (1 - x)\,y' + n\,y = 0$

and satisfy the orthogonality relation

$\int_0^{\infty} L_m(x) L_n(x) e^{-x} \, dx = \delta_{mn}.$

The generalized Laguerre polynomials may be defined by the Rodrigues formula:

$L_n^{(\alpha)}(x) = \frac{x^{-\alpha} e^x}{n!} \frac{d^n}{dx^n} \left(e^{-x} x^{n+\alpha}\right).$

(These are also sometimes called the associated Laguerre polynomials.) The simple Laguerre polynomials are recovered from the generalized polynomials by setting $$\alpha = 0$$.

They are named after Edmond Laguerre (1834-1886).

## Jacobi polynomials#

Jacobi polynomials are a class of orthogonal polynomials. They are obtained from hypergeometric series in cases where the series is in fact finite:

$P_n^{(\alpha,\beta)}(z) = \frac{(\alpha+1)_n}{n!} \,_2F_1\left(-n,1+\alpha+\beta+n; \alpha+1; \frac{1-z}{2}\right),$

where $$()_n$$ is Pochhammer’s symbol (for the rising factorial), (Abramowitz and Stegun p561.) and thus have the explicit expression

$P_n^{(\alpha,\beta)} (z) = \frac{\Gamma(\alpha+n+1)}{n!\Gamma(\alpha+\beta+n+1)} \sum_{m=0}^n \binom{n}{m} \frac{\Gamma(\alpha+\beta+n+m+1)}{\Gamma(\alpha+m+1)} \left(\frac{z-1}{2}\right)^m.$

They are named after Carl Gustav Jaboc Jacobi (1804-1851).

## Gegenbauer polynomials#

Ultraspherical or Gegenbauer polynomials are given in terms of the Jacobi polynomials $$P_n^{(\alpha,\beta)}(x)$$ with $$\alpha = \beta = a - 1/2$$ by

$C_n^{(a)}(x) = \frac{\Gamma(a+1/2)}{\Gamma(2a)} \frac{\Gamma(n+2a)}{\Gamma(n+a+1/2)} P_n^{(a-1/2,a-1/2)}(x).$

They satisfy the orthogonality relation

$\int_{-1}^1(1-x^2)^{a-1/2}C_m^{(a)}(x)C_n^{(a)}(x)\, dx = \delta_{mn}2^{1-2a}\pi \frac{\Gamma(n+2a)}{(n+a)\Gamma^2(a)\Gamma(n+1)},$

for $$a > -1/2$$. They are obtained from hypergeometric series in cases where the series is in fact finite:

$C_n^{(a)}(z) = \frac{(2a)^{\underline{n}}}{n!} \,_2F_1\left(-n,2a+n; a+\frac{1}{2}; \frac{1-z}{2}\right)$

where $$\underline{n}$$ is the falling factorial. (See Abramowitz and Stegun p561.)

They are named for Leopold Gegenbauer (1849-1903).

## Krawtchouk polynomials#

The Krawtchouk polynomials are discrete orthogonal polynomials that are given by the hypergeometric series

$K_j(x; n, p) = (-1)^j \binom{n}{j} p^j \,_{2}F_1\left(-j,-x; -n; p^{-1}\right).$

Since they are discrete orthogonal polynomials, they satisfy an orthogonality relation defined on a discrete (in this case finite) set of points:

$\sum_{m=0}^n K_i(m; n, p) K_j(m; n, p) \, \binom{n}{m} p^m q^{n-m} = \binom{n}{j} (pq)^j \delta_{ij},$

where $$q = 1 - p$$. They can also be described by the recurrence relation

$j K_j(x; n, p) = (x - (n-j+1) p - (j-1) q) K_{j-1}(x; n, p) - p q (n - j + 2) K_{j-2}(x; n, p),$

where $$K_0(x; n, p) = 1$$ and $$K_1(x; n, p) = x - n p$$.

They are named for Mykhailo Krawtchouk (1892-1942).

## Meixner polynomials#

The Meixner polynomials are discrete orthogonal polynomials that are given by the hypergeometric series

$M_n(x; n, p) = (-1)^j \binom{n}{j} p^j \,_{2}F_1\left(-j,-x; -n; p^{-1}\right).$

They satisfy an orthogonality relation:

$\sum_{k=0}^{\infty} \tilde{M}_n(k; b, c) \tilde{M}_m(k; b, c) \, \frac{(b)_k}{k!} c^k = \frac{c^{-n} n!}{(b)_n (1-c)^b} \delta_{mn},$

where $$\tilde{M}_n(x; b, c) = M_n(x; b, c) / (b)_x$$, for $$b > 0  and 0 < c < 1$$. They can also be described by the recurrence relation

\begin{split}\begin{aligned} c (n-1+b) M_n(x; b, c) & = ((c-1) x + n-1 + c (n-1+b)) (b+n-1) M_{n-1}(x; b, c) \\ & \qquad - (b+n-1) (b+n-2) (n-1) M_{n-2}(x; b, c), \end{aligned}\end{split}

where $$M_0(x; b, c) = 0$$ and $$M_1(x; b, c) = (1 - c^{-1}) x + b$$.

They are named for Josef Meixner (1908-1994).

## Hahn polynomials#

The Hahn polynomials are discrete orthogonal polynomials that are given by the hypergeometric series

$Q_k(x; a, b, n) = \,_{3}F_2\left(-k,k+a+b+1,-x; a+1,-n; 1\right).$

They satisfy an orthogonality relation:

$\sum_{k=0}^{n-1} Q_i(k; a, b, n) Q_j(k; a, b, n) \, \rho(k) = \frac{\delta_{ij}}{\pi_i},$

where

\begin{split}\begin{aligned} \rho(k) &= \binom{a+k}{k} \binom{b+n-k}{n-k}, \\ \pi_i &= \delta_{ij} \frac{(-1)^i i! (b+1)_i (i+a+b+1)_{n+1}}{n! (2i+a+b+1) (-n)_i (a+1)_i}. \end{aligned}\end{split}

They can also be described by the recurrence relation

$A Q_k(x; a,b,n) = (-x + A + C) Q_{k-1}(x; a,b,n) - C Q_{k-2}(x; a,b,n),$

where $$Q_0(x; a,b,n) = 1$$ and $$Q_1(x; a,b,n) = 1 - \frac{a+b+2}{(a+1)n} x$$ and

$A = \frac{(k+a+b) (k+a) (n-k+1)}{(2k+a+b-1) (2k+a+b)}, \qquad C = \frac{(k-1) (k+b-1) (k+a+b+n)}{(2k+a+b-2) (2k+a+b-1)}.$

They are named for Wolfgang Hahn (1911-1998), although they were first introduced by Chebyshev in 1875.

## Pochhammer symbol#

For completeness, the Pochhammer symbol, introduced by Leo August Pochhammer, $$(x)_n$$, is used in the theory of special functions to represent the “rising factorial” or “upper factorial”

$(x)_n = x(x+1)(x+2) \cdots (x+n-1) = \frac{(x+n-1)!}{(x-1)!}.$

On the other hand, the falling factorial or lower factorial is

$x^{\underline{n}} = \frac{x!}{(x-n)!},$

in the notation of Ronald L. Graham, Donald E. Knuth and Oren Patashnik in their book Concrete Mathematics.

Todo

Implement Zernike polynomials. Wikipedia article Zernike_polynomials

REFERENCES:

AUTHORS:

• David Joyner (2006-06)

• Stefan Reiterer (2010-)

• Ralf Stephan (2015-)

The original module wrapped some of the orthogonal/special functions in the Maxima package “orthopoly” and was written by Barton Willis of the University of Nebraska at Kearney.

class sage.functions.orthogonal_polys.ChebyshevFunction(name, nargs=2, latex_name=None, conversions=None)[source]#

Abstract base class for Chebyshev polynomials of the first and second kind.

EXAMPLES:

sage: chebyshev_T(3, x)                                                         # needs sage.symbolic
4*x^3 - 3*x

>>> from sage.all import *
>>> chebyshev_T(Integer(3), x)                                                         # needs sage.symbolic
4*x^3 - 3*x

class sage.functions.orthogonal_polys.Func_assoc_legendre_P[source]#

Return the Ferrers function $$\mathtt{P}_n^m(x)$$ of first kind for $$x \in (-1,1)$$ with general order $$m$$ and general degree $$n$$.

Ferrers functions of first kind are one of two linearly independent solutions of the associated Legendre differential equation

$(1-x^2) \frac{\mathrm{d}^2 w}{\mathrm{d}x^2} - 2x \frac{\mathrm{d} w}{\mathrm{d}x} + \left(n(n+1) - \frac{m^2}{1-x^2}\right) w = 0$

on the interval $$x \in (-1, 1)$$ and are usually denoted by $$\mathtt{P}_n^m(x)$$.

The other linearly independent solution is called Ferrers function of second kind and denoted by $$\mathtt{Q}_n^m(x)$$, see Func_assoc_legendre_Q.

Warning

Ferrers functions must be carefully distinguished from associated Legendre functions which are defined on $$\CC \setminus (- \infty, 1]$$ and have not yet been implemented.

EXAMPLES:

We give the first Ferrers functions for non-negative integers $$n$$ and $$m$$ in the interval $$-1<x<1$$:

sage: for n in range(4):                                                        # needs sage.symbolic
....:     for m in range(n+1):
....:         print(f"P_{n}^{m}({x}) = {gen_legendre_P(n, m, x)}")
P_0^0(x) = 1
P_1^0(x) = x
P_1^1(x) = -sqrt(-x^2 + 1)
P_2^0(x) = 3/2*x^2 - 1/2
P_2^1(x) = -3*sqrt(-x^2 + 1)*x
P_2^2(x) = -3*x^2 + 3
P_3^0(x) = 5/2*x^3 - 3/2*x
P_3^1(x) = -3/2*(5*x^2 - 1)*sqrt(-x^2 + 1)
P_3^2(x) = -15*(x^2 - 1)*x
P_3^3(x) = -15*(-x^2 + 1)^(3/2)

>>> from sage.all import *
>>> for n in range(Integer(4)):                                                        # needs sage.symbolic
...     for m in range(n+Integer(1)):
...         print(f"P_{n}^{m}({x}) = {gen_legendre_P(n, m, x)}")
P_0^0(x) = 1
P_1^0(x) = x
P_1^1(x) = -sqrt(-x^2 + 1)
P_2^0(x) = 3/2*x^2 - 1/2
P_2^1(x) = -3*sqrt(-x^2 + 1)*x
P_2^2(x) = -3*x^2 + 3
P_3^0(x) = 5/2*x^3 - 3/2*x
P_3^1(x) = -3/2*(5*x^2 - 1)*sqrt(-x^2 + 1)
P_3^2(x) = -15*(x^2 - 1)*x
P_3^3(x) = -15*(-x^2 + 1)^(3/2)


These expressions for non-negative integers are computed by the Rodrigues-type given in eval_gen_poly(). Negative values for $$n$$ are obtained by the following identity:

$P^{m}_{-n}(x) = P^{m}_{n-1}(x).$

For $$n$$ being a non-negative integer, negative values for $$m$$ are obtained by

$P^{-|m|}_n(x) = (-1)^{|m|} \frac{(n-|m|)!}{(n+|m|)!} P_n^{|m|}(x),$

where $$|m| \leq n$$.

Here are some specific values with negative integers:

sage: # needs sage.symbolic
sage: gen_legendre_P(-2, -1, x)
1/2*sqrt(-x^2 + 1)
sage: gen_legendre_P(2, -2, x)
-1/8*x^2 + 1/8
sage: gen_legendre_P(3, -2, x)
-1/8*(x^2 - 1)*x
sage: gen_legendre_P(1, -2, x)
0

>>> from sage.all import *
>>> # needs sage.symbolic
>>> gen_legendre_P(-Integer(2), -Integer(1), x)
1/2*sqrt(-x^2 + 1)
>>> gen_legendre_P(Integer(2), -Integer(2), x)
-1/8*x^2 + 1/8
>>> gen_legendre_P(Integer(3), -Integer(2), x)
-1/8*(x^2 - 1)*x
>>> gen_legendre_P(Integer(1), -Integer(2), x)
0


Here are some other random values with floating numbers:

sage: # needs sage.symbolic
sage: m = var('m'); assume(m, 'integer')
sage: gen_legendre_P(m, m, .2)
0.960000000000000^(1/2*m)*(-1)^m*factorial(2*m)/(2^m*factorial(m))
sage: gen_legendre_P(.2, m, 0)
sqrt(pi)*2^m/(gamma(-1/2*m + 1.10000000000000)*gamma(-1/2*m + 0.400000000000000))
sage: gen_legendre_P(.2, .2, .2)
0.757714892929573

>>> from sage.all import *
>>> # needs sage.symbolic
>>> m = var('m'); assume(m, 'integer')
>>> gen_legendre_P(m, m, RealNumber('.2'))
0.960000000000000^(1/2*m)*(-1)^m*factorial(2*m)/(2^m*factorial(m))
>>> gen_legendre_P(RealNumber('.2'), m, Integer(0))
sqrt(pi)*2^m/(gamma(-1/2*m + 1.10000000000000)*gamma(-1/2*m + 0.400000000000000))
>>> gen_legendre_P(RealNumber('.2'), RealNumber('.2'), RealNumber('.2'))
0.757714892929573


REFERENCES:

deprecated_function_alias(issue_number, func)[source]#

Create an aliased version of a function or a method which raises a deprecation warning message.

If f is a function or a method, write g = deprecated_function_alias(issue_number, f) to make a deprecated aliased version of f.

INPUT:

• issue_number – integer. The github issue number where the deprecation is introduced.

• func – the function or method to be aliased

EXAMPLES:

sage: from sage.misc.superseded import deprecated_function_alias
sage: g = deprecated_function_alias(13109, number_of_partitions)                # needs sage.combinat sage.libs.flint
sage: g(5)                                                                      # needs sage.combinat sage.libs.flint
doctest:...: DeprecationWarning: g is deprecated.
See https://github.com/sagemath/sage/issues/13109 for details.
7

>>> from sage.all import *
>>> from sage.misc.superseded import deprecated_function_alias
>>> g = deprecated_function_alias(Integer(13109), number_of_partitions)                # needs sage.combinat sage.libs.flint
>>> g(Integer(5))                                                                      # needs sage.combinat sage.libs.flint
doctest:...: DeprecationWarning: g is deprecated.
See https://github.com/sagemath/sage/issues/13109 for details.
7


This also works for methods:

sage: class cls():
....:    def new_meth(self): return 42
....:    old_meth = deprecated_function_alias(13109, new_meth)
sage: cls().old_meth()
See https://github.com/sagemath/sage/issues/13109 for details.
42

>>> from sage.all import *
>>> class cls():
...    def new_meth(self): return Integer(42)
...    old_meth = deprecated_function_alias(Integer(13109), new_meth)
>>> cls().old_meth()
See https://github.com/sagemath/sage/issues/13109 for details.
42

sage: def a(): pass
sage: b = deprecated_function_alias(13109, a)
sage: b()
See https://github.com/sagemath/sage/issues/13109 for details.

>>> from sage.all import *
>>> def a(): pass
>>> b = deprecated_function_alias(Integer(13109), a)
>>> b()
See https://github.com/sagemath/sage/issues/13109 for details.


AUTHORS:

• Florent Hivert (2009-11-23), with the help of Mike Hansen.

• Luca De Feo (2011-07-11), printing the full module path when different from old path

eval_gen_poly(n, m, arg, **kwds)[source]#

Return the Ferrers function of first kind $$\mathtt{P}_n^m(x)$$ for integers $$n > -1, m > -1$$ given by the following Rodrigues-type formula:

$\mathtt{P}_n^m(x) = (-1)^{m+n} \frac{(1-x^2)^{m/2}}{2^n n!} \frac{\mathrm{d}^{m+n}}{\mathrm{d}x^{m+n}} (1-x^2)^n.$

INPUT:

• n – an integer degree

• m – an integer order

• x – either an integer or a non-numerical symbolic expression

EXAMPLES:

sage: gen_legendre_P(7, 4, x)                                               # needs sage.symbolic
3465/2*(13*x^3 - 3*x)*(x^2 - 1)^2
sage: gen_legendre_P(3, 1, sqrt(x))                                         # needs sage.symbolic
-3/2*(5*x - 1)*sqrt(-x + 1)

>>> from sage.all import *
>>> gen_legendre_P(Integer(7), Integer(4), x)                                               # needs sage.symbolic
3465/2*(13*x^3 - 3*x)*(x^2 - 1)^2
>>> gen_legendre_P(Integer(3), Integer(1), sqrt(x))                                         # needs sage.symbolic
-3/2*(5*x - 1)*sqrt(-x + 1)


REFERENCE:

eval_poly(*args, **kwds)[source]#

Deprecated: Use eval_gen_poly() instead. See Issue #25034 for details.

class sage.functions.orthogonal_polys.Func_assoc_legendre_Q[source]#

EXAMPLES:

sage: loads(dumps(gen_legendre_Q))
gen_legendre_Q
sage: maxima(gen_legendre_Q(2, 1, 3, hold=True))._sage_().simplify_full()   # needs sage.symbolic
1/4*sqrt(2)*(36*pi - 36*I*log(2) + 25*I)

>>> from sage.all import *
gen_legendre_Q
>>> maxima(gen_legendre_Q(Integer(2), Integer(1), Integer(3), hold=True))._sage_().simplify_full()   # needs sage.symbolic
1/4*sqrt(2)*(36*pi - 36*I*log(2) + 25*I)

eval_recursive(n, m, x, **kwds)[source]#

Return the associated Legendre Q(n, m, arg) function for integers $$n > -1, m > -1$$.

EXAMPLES:

sage: # needs sage.symbolic
sage: gen_legendre_Q(3, 4, x)
48/(x^2 - 1)^2
sage: gen_legendre_Q(4, 5, x)
-384/((x^2 - 1)^2*sqrt(-x^2 + 1))
sage: gen_legendre_Q(0, 1, x)
-1/sqrt(-x^2 + 1)
sage: gen_legendre_Q(0, 2, x)
-1/2*((x + 1)^2 - (x - 1)^2)/(x^2 - 1)
sage: gen_legendre_Q(2, 2, x).subs(x=2).expand()
9/2*I*pi - 9/2*log(3) + 14/3

>>> from sage.all import *
>>> # needs sage.symbolic
>>> gen_legendre_Q(Integer(3), Integer(4), x)
48/(x^2 - 1)^2
>>> gen_legendre_Q(Integer(4), Integer(5), x)
-384/((x^2 - 1)^2*sqrt(-x^2 + 1))
>>> gen_legendre_Q(Integer(0), Integer(1), x)
-1/sqrt(-x^2 + 1)
>>> gen_legendre_Q(Integer(0), Integer(2), x)
-1/2*((x + 1)^2 - (x - 1)^2)/(x^2 - 1)
>>> gen_legendre_Q(Integer(2), Integer(2), x).subs(x=Integer(2)).expand()
9/2*I*pi - 9/2*log(3) + 14/3

class sage.functions.orthogonal_polys.Func_chebyshev_T[source]#

Chebyshev polynomials of the first kind.

REFERENCE:

• [AS1964] 22.5.31 page 778 and 6.1.22 page 256.

EXAMPLES:

sage: chebyshev_T(5, x)                                                          # needs sage.symbolic
16*x^5 - 20*x^3 + 5*x
sage: var('k')                                                                   # needs sage.symbolic
k
sage: test = chebyshev_T(k, x); test                                             # needs sage.symbolic
chebyshev_T(k, x)

>>> from sage.all import *
>>> chebyshev_T(Integer(5), x)                                                          # needs sage.symbolic
16*x^5 - 20*x^3 + 5*x
>>> var('k')                                                                   # needs sage.symbolic
k
>>> test = chebyshev_T(k, x); test                                             # needs sage.symbolic
chebyshev_T(k, x)

eval_algebraic(n, x)[source]#

Evaluate chebyshev_T as polynomial, using a recursive formula.

INPUT:

• n – an integer

• x – a value to evaluate the polynomial at (this can be any ring element)

EXAMPLES:

sage: chebyshev_T.eval_algebraic(5, x)                                      # needs sage.symbolic
2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x
sage: chebyshev_T(-7, x) - chebyshev_T(7, x)                                # needs sage.symbolic
0
sage: R.<t> = ZZ[]
sage: chebyshev_T.eval_algebraic(-1, t)
t
sage: chebyshev_T.eval_algebraic(0, t)
1
sage: chebyshev_T.eval_algebraic(1, t)
t
sage: chebyshev_T(7^100, 1/2)
1/2
sage: chebyshev_T(7^100, Mod(2,3))
2
sage: n = 97; x = RIF(pi/2/n)                                               # needs sage.symbolic
sage: chebyshev_T(n, cos(x)).contains_zero()                                # needs sage.symbolic
True

sage: R.<t> = Zp(2, 8, 'capped-abs')[]
sage: chebyshev_T(10^6 + 1, t)
(2^7 + O(2^8))*t^5 + O(2^8)*t^4 + (2^6 + O(2^8))*t^3 + O(2^8)*t^2
+ (1 + 2^6 + O(2^8))*t + O(2^8)

>>> from sage.all import *
>>> chebyshev_T.eval_algebraic(Integer(5), x)                                      # needs sage.symbolic
2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x
>>> chebyshev_T(-Integer(7), x) - chebyshev_T(Integer(7), x)                                # needs sage.symbolic
0
>>> R = ZZ['t']; (t,) = R._first_ngens(1)
>>> chebyshev_T.eval_algebraic(-Integer(1), t)
t
>>> chebyshev_T.eval_algebraic(Integer(0), t)
1
>>> chebyshev_T.eval_algebraic(Integer(1), t)
t
>>> chebyshev_T(Integer(7)**Integer(100), Integer(1)/Integer(2))
1/2
>>> chebyshev_T(Integer(7)**Integer(100), Mod(Integer(2),Integer(3)))
2
>>> n = Integer(97); x = RIF(pi/Integer(2)/n)                                               # needs sage.symbolic
>>> chebyshev_T(n, cos(x)).contains_zero()                                # needs sage.symbolic
True

>>> R = Zp(Integer(2), Integer(8), 'capped-abs')['t']; (t,) = R._first_ngens(1)
>>> chebyshev_T(Integer(10)**Integer(6) + Integer(1), t)
(2^7 + O(2^8))*t^5 + O(2^8)*t^4 + (2^6 + O(2^8))*t^3 + O(2^8)*t^2
+ (1 + 2^6 + O(2^8))*t + O(2^8)

eval_formula(n, x)[source]#

Evaluate chebyshev_T using an explicit formula. See [AS1964] 227 (p. 782) for details for the recursions. See also [Koe1999] for fast evaluation techniques.

INPUT:

• n – an integer

• x – a value to evaluate the polynomial at (this can be any ring element)

EXAMPLES:

sage: # needs sage.symbolic
sage: chebyshev_T.eval_formula(-1, x)
x
sage: chebyshev_T.eval_formula(0, x)
1
sage: chebyshev_T.eval_formula(1, x)
x
sage: chebyshev_T.eval_formula(10, x)
512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1
sage: chebyshev_T.eval_algebraic(10, x).expand()
512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1

sage: chebyshev_T.eval_formula(2, 0.1) == chebyshev_T._evalf_(2, 0.1)       # needs sage.rings.complex_double
True

>>> from sage.all import *
>>> # needs sage.symbolic
>>> chebyshev_T.eval_formula(-Integer(1), x)
x
>>> chebyshev_T.eval_formula(Integer(0), x)
1
>>> chebyshev_T.eval_formula(Integer(1), x)
x
>>> chebyshev_T.eval_formula(Integer(10), x)
512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1
>>> chebyshev_T.eval_algebraic(Integer(10), x).expand()
512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1

>>> chebyshev_T.eval_formula(Integer(2), RealNumber('0.1')) == chebyshev_T._evalf_(Integer(2), RealNumber('0.1'))       # needs sage.rings.complex_double
True

class sage.functions.orthogonal_polys.Func_chebyshev_U[source]#

Class for the Chebyshev polynomial of the second kind.

REFERENCE:

• [AS1964] 22.8.3 page 783 and 6.1.22 page 256.

EXAMPLES:

sage: R.<t> = QQ[]
sage: chebyshev_U(2, t)
4*t^2 - 1
sage: chebyshev_U(3, t)
8*t^3 - 4*t

>>> from sage.all import *
>>> R = QQ['t']; (t,) = R._first_ngens(1)
>>> chebyshev_U(Integer(2), t)
4*t^2 - 1
>>> chebyshev_U(Integer(3), t)
8*t^3 - 4*t

eval_algebraic(n, x)[source]#

Evaluate chebyshev_U as polynomial, using a recursive formula.

INPUT:

• n – an integer

• x – a value to evaluate the polynomial at (this can be any ring element)

EXAMPLES:

sage: chebyshev_U.eval_algebraic(5, x)                                      # needs sage.symbolic
-2*((2*x + 1)*(2*x - 1)*x - 4*(2*x^2 - 1)*x)*(2*x + 1)*(2*x - 1)
sage: parent(chebyshev_U(3, Mod(8,9)))
Ring of integers modulo 9
sage: parent(chebyshev_U(3, Mod(1,9)))
Ring of integers modulo 9
sage: chebyshev_U(-3, x) + chebyshev_U(1, x)                                # needs sage.symbolic
0
sage: chebyshev_U(-1, Mod(5,8))
0
sage: parent(chebyshev_U(-1, Mod(5,8)))
Ring of integers modulo 8
sage: R.<t> = ZZ[]
sage: chebyshev_U.eval_algebraic(-2, t)
-1
sage: chebyshev_U.eval_algebraic(-1, t)
0
sage: chebyshev_U.eval_algebraic(0, t)
1
sage: chebyshev_U.eval_algebraic(1, t)
2*t
sage: n = 97; x = RIF(pi/n)                                                 # needs sage.symbolic
sage: chebyshev_U(n - 1, cos(x)).contains_zero()                            # needs sage.symbolic
True

sage: R.<t> = Zp(2, 6, 'capped-abs')[]
sage: chebyshev_U(10^6 + 1, t)
(2 + O(2^6))*t + O(2^6)

>>> from sage.all import *
>>> chebyshev_U.eval_algebraic(Integer(5), x)                                      # needs sage.symbolic
-2*((2*x + 1)*(2*x - 1)*x - 4*(2*x^2 - 1)*x)*(2*x + 1)*(2*x - 1)
>>> parent(chebyshev_U(Integer(3), Mod(Integer(8),Integer(9))))
Ring of integers modulo 9
>>> parent(chebyshev_U(Integer(3), Mod(Integer(1),Integer(9))))
Ring of integers modulo 9
>>> chebyshev_U(-Integer(3), x) + chebyshev_U(Integer(1), x)                                # needs sage.symbolic
0
>>> chebyshev_U(-Integer(1), Mod(Integer(5),Integer(8)))
0
>>> parent(chebyshev_U(-Integer(1), Mod(Integer(5),Integer(8))))
Ring of integers modulo 8
>>> R = ZZ['t']; (t,) = R._first_ngens(1)
>>> chebyshev_U.eval_algebraic(-Integer(2), t)
-1
>>> chebyshev_U.eval_algebraic(-Integer(1), t)
0
>>> chebyshev_U.eval_algebraic(Integer(0), t)
1
>>> chebyshev_U.eval_algebraic(Integer(1), t)
2*t
>>> n = Integer(97); x = RIF(pi/n)                                                 # needs sage.symbolic
>>> chebyshev_U(n - Integer(1), cos(x)).contains_zero()                            # needs sage.symbolic
True

>>> R = Zp(Integer(2), Integer(6), 'capped-abs')['t']; (t,) = R._first_ngens(1)
>>> chebyshev_U(Integer(10)**Integer(6) + Integer(1), t)
(2 + O(2^6))*t + O(2^6)

eval_formula(n, x)[source]#

Evaluate chebyshev_U using an explicit formula.

See [AS1964] 227 (p. 782) for details on the recursions. See also [Koe1999] for the recursion formulas.

INPUT:

• n – an integer

• x – a value to evaluate the polynomial at (this can be any ring element)

EXAMPLES:

sage: # needs sage.symbolic
sage: chebyshev_U.eval_formula(10, x)
1024*x^10 - 2304*x^8 + 1792*x^6 - 560*x^4 + 60*x^2 - 1
sage: chebyshev_U.eval_formula(-2, x)
-1
sage: chebyshev_U.eval_formula(-1, x)
0
sage: chebyshev_U.eval_formula(0, x)
1
sage: chebyshev_U.eval_formula(1, x)
2*x
sage: chebyshev_U.eval_formula(2, 0.1) == chebyshev_U._evalf_(2, 0.1)
True

>>> from sage.all import *
>>> # needs sage.symbolic
>>> chebyshev_U.eval_formula(Integer(10), x)
1024*x^10 - 2304*x^8 + 1792*x^6 - 560*x^4 + 60*x^2 - 1
>>> chebyshev_U.eval_formula(-Integer(2), x)
-1
>>> chebyshev_U.eval_formula(-Integer(1), x)
0
>>> chebyshev_U.eval_formula(Integer(0), x)
1
>>> chebyshev_U.eval_formula(Integer(1), x)
2*x
>>> chebyshev_U.eval_formula(Integer(2), RealNumber('0.1')) == chebyshev_U._evalf_(Integer(2), RealNumber('0.1'))
True

class sage.functions.orthogonal_polys.Func_gen_laguerre[source]#

REFERENCE:

• [AS1964] 22.5.16, page 778 and page 789.

class sage.functions.orthogonal_polys.Func_hahn[source]#

Hahn polynomials $$Q_k(x; a, b, n)$$.

INPUT:

• k – the degree

• x – the independent variable $$x$$

• a, b – the parameters $$a$$, $$b$$

• n – the number of discrete points

EXAMPLES:

We verify the orthogonality for $$n = 3$$:

sage: # needs sage.symbolic
sage: n = 2
sage: a, b = SR.var('a,b')
sage: def rho(k, a, b, n):
....:     return binomial(a + k, k) * binomial(b + n - k, n - k)
sage: M = matrix([[sum(rho(k, a, b, n)
....:                  * hahn(i, k, a, b, n) * hahn(j, k, a, b, n)
....:                  for k in range(n + 1)).expand().factor()
....:              for i in range(n+1)] for j in range(n+1)])
sage: M = M.factor()
sage: P = rising_factorial
sage: def diag(i, a, b, n):
....:    return ((-1)^i * factorial(i) * P(b + 1, i) * P(i + a + b + 1, n + 1)
....:            / (factorial(n) * (2*i + a + b + 1) * P(-n, i) * P(a + 1, i)))
sage: all(M[i,i] == diag(i, a, b, n) for i in range(3))
True
sage: all(M[i,j] == 0 for i in range(3) for j in range(3) if i != j)
True

>>> from sage.all import *
>>> # needs sage.symbolic
>>> n = Integer(2)
>>> a, b = SR.var('a,b')
>>> def rho(k, a, b, n):
...     return binomial(a + k, k) * binomial(b + n - k, n - k)
>>> M = matrix([[sum(rho(k, a, b, n)
...                  * hahn(i, k, a, b, n) * hahn(j, k, a, b, n)
...                  for k in range(n + Integer(1))).expand().factor()
...              for i in range(n+Integer(1))] for j in range(n+Integer(1))])
>>> M = M.factor()
>>> P = rising_factorial
>>> def diag(i, a, b, n):
...    return ((-Integer(1))**i * factorial(i) * P(b + Integer(1), i) * P(i + a + b + Integer(1), n + Integer(1))
...            / (factorial(n) * (Integer(2)*i + a + b + Integer(1)) * P(-n, i) * P(a + Integer(1), i)))
>>> all(M[i,i] == diag(i, a, b, n) for i in range(Integer(3)))
True
>>> all(M[i,j] == Integer(0) for i in range(Integer(3)) for j in range(Integer(3)) if i != j)
True

eval_formula(k, x, a, b, n)[source]#

Evaluate self using an explicit formula.

EXAMPLES:

sage: # needs sage.symbolic
sage: k, x, a, b, n = var('k,x,a,b,n')
sage: Q2 = hahn.eval_formula(2, x, a, b, n).simplify_full()
sage: Q2.coefficient(x^2).factor()
(a + b + 4)*(a + b + 3)/((a + 2)*(a + 1)*(n - 1)*n)
sage: Q2.coefficient(x).factor()
-(2*a*n - a + b + 4*n)*(a + b + 3)/((a + 2)*(a + 1)*(n - 1)*n)
sage: Q2(x=0)
1

>>> from sage.all import *
>>> # needs sage.symbolic
>>> k, x, a, b, n = var('k,x,a,b,n')
>>> Q2 = hahn.eval_formula(Integer(2), x, a, b, n).simplify_full()
>>> Q2.coefficient(x**Integer(2)).factor()
(a + b + 4)*(a + b + 3)/((a + 2)*(a + 1)*(n - 1)*n)
>>> Q2.coefficient(x).factor()
-(2*a*n - a + b + 4*n)*(a + b + 3)/((a + 2)*(a + 1)*(n - 1)*n)
>>> Q2(x=Integer(0))
1

eval_recursive(k, x, a, b, n, *args, **kwds)[source]#

Return the Hahn polynomial $$Q_k(x; a, b, n)$$ using the recursive formula.

EXAMPLES:

sage: # needs sage.symbolic
sage: x, a, b, n = var('x,a,b,n')
sage: hahn.eval_recursive(0, x, a, b, n)
1
sage: hahn.eval_recursive(1, x, a, b, n)
-(a + b + 2)*x/((a + 1)*n) + 1
sage: bool(hahn(2, x, a, b, n) == hahn.eval_recursive(2, x, a, b, n))
True
sage: bool(hahn(3, x, a, b, n) == hahn.eval_recursive(3, x, a, b, n))
True
sage: bool(hahn(4, x, a, b, n) == hahn.eval_recursive(4, x, a, b, n))
True
sage: M = matrix([[-1/2, -1], [1, 0]])                                      # needs sage.modules
sage: ret = hahn.eval_recursive(2, M, 1, 2, n).simplify_full().factor()     # needs sage.modules
sage: ret                                                                   # needs sage.modules
[1/4*(4*n^2 + 8*n - 19)/((n - 1)*n)          3/2*(4*n + 3)/((n - 1)*n)]
[        -3/2*(4*n + 3)/((n - 1)*n)          (n^2 - n - 7)/((n - 1)*n)]

>>> from sage.all import *
>>> # needs sage.symbolic
>>> x, a, b, n = var('x,a,b,n')
>>> hahn.eval_recursive(Integer(0), x, a, b, n)
1
>>> hahn.eval_recursive(Integer(1), x, a, b, n)
-(a + b + 2)*x/((a + 1)*n) + 1
>>> bool(hahn(Integer(2), x, a, b, n) == hahn.eval_recursive(Integer(2), x, a, b, n))
True
>>> bool(hahn(Integer(3), x, a, b, n) == hahn.eval_recursive(Integer(3), x, a, b, n))
True
>>> bool(hahn(Integer(4), x, a, b, n) == hahn.eval_recursive(Integer(4), x, a, b, n))
True
>>> M = matrix([[-Integer(1)/Integer(2), -Integer(1)], [Integer(1), Integer(0)]])                                      # needs sage.modules
>>> ret = hahn.eval_recursive(Integer(2), M, Integer(1), Integer(2), n).simplify_full().factor()     # needs sage.modules
>>> ret                                                                   # needs sage.modules
[1/4*(4*n^2 + 8*n - 19)/((n - 1)*n)          3/2*(4*n + 3)/((n - 1)*n)]
[        -3/2*(4*n + 3)/((n - 1)*n)          (n^2 - n - 7)/((n - 1)*n)]

class sage.functions.orthogonal_polys.Func_hermite[source]#

Bases: GinacFunction

Return the Hermite polynomial for integers $$n > -1$$.

REFERENCE:

• [AS1964] 22.5.40 and 22.5.41, page 779.

EXAMPLES:

sage: # needs sage.symbolic
sage: x = PolynomialRing(QQ, 'x').gen()
sage: hermite(2, x)
4*x^2 - 2
sage: hermite(3, x)
8*x^3 - 12*x
sage: hermite(3, 2)
40
sage: S.<y> = PolynomialRing(RR)
sage: hermite(3, y)
8.00000000000000*y^3 - 12.0000000000000*y
sage: R.<x,y> = QQ[]
sage: hermite(3, y^2)
8*y^6 - 12*y^2
sage: w = var('w')
sage: hermite(3, 2*w)
64*w^3 - 24*w
sage: hermite(5, 3.1416)
5208.69733891963
sage: hermite(5, RealField(100)(pi))
5208.6167627118104649470287166

>>> from sage.all import *
>>> # needs sage.symbolic
>>> x = PolynomialRing(QQ, 'x').gen()
>>> hermite(Integer(2), x)
4*x^2 - 2
>>> hermite(Integer(3), x)
8*x^3 - 12*x
>>> hermite(Integer(3), Integer(2))
40
>>> S = PolynomialRing(RR, names=('y',)); (y,) = S._first_ngens(1)
>>> hermite(Integer(3), y)
8.00000000000000*y^3 - 12.0000000000000*y
>>> R = QQ['x, y']; (x, y,) = R._first_ngens(2)
>>> hermite(Integer(3), y**Integer(2))
8*y^6 - 12*y^2
>>> w = var('w')
>>> hermite(Integer(3), Integer(2)*w)
64*w^3 - 24*w
>>> hermite(Integer(5), RealNumber('3.1416'))
5208.69733891963
>>> hermite(Integer(5), RealField(Integer(100))(pi))
5208.6167627118104649470287166


Check that Issue #17192 is fixed:

sage: # needs sage.symbolic
sage: x = PolynomialRing(QQ, 'x').gen()
sage: hermite(0, x)
1
sage: hermite(-1, x)
Traceback (most recent call last):
...
RuntimeError: hermite_eval: The index n must be a nonnegative integer
sage: hermite(-7, x)
Traceback (most recent call last):
...
RuntimeError: hermite_eval: The index n must be a nonnegative integer
sage: m, x = SR.var('m,x')
sage: hermite(m, x).diff(m)
Traceback (most recent call last):
...
RuntimeError: derivative w.r.t. to the index is not supported yet

>>> from sage.all import *
>>> # needs sage.symbolic
>>> x = PolynomialRing(QQ, 'x').gen()
>>> hermite(Integer(0), x)
1
>>> hermite(-Integer(1), x)
Traceback (most recent call last):
...
RuntimeError: hermite_eval: The index n must be a nonnegative integer
>>> hermite(-Integer(7), x)
Traceback (most recent call last):
...
RuntimeError: hermite_eval: The index n must be a nonnegative integer
>>> m, x = SR.var('m,x')
>>> hermite(m, x).diff(m)
Traceback (most recent call last):
...
RuntimeError: derivative w.r.t. to the index is not supported yet

class sage.functions.orthogonal_polys.Func_jacobi_P[source]#

Return the Jacobi polynomial $$P_n^{(a,b)}(x)$$ for integers $$n > -1$$ and a and b symbolic or $$a > -1$$ and $$b > -1$$.

The Jacobi polynomials are actually defined for all $$a$$ and $$b$$. However, the Jacobi polynomial weight $$(1-x)^a(1+x)^b$$ is not integrable for $$a \leq -1$$ or $$b \leq -1$$.

REFERENCE:

EXAMPLES:

sage: x = PolynomialRing(QQ, 'x').gen()
sage: jacobi_P(2, 0, 0, x)                                                      # needs sage.libs.flint sage.symbolic
3/2*x^2 - 1/2
sage: jacobi_P(2, 1, 2, 1.2)                                                    # needs sage.libs.flint
5.01000000000000

>>> from sage.all import *
>>> x = PolynomialRing(QQ, 'x').gen()
>>> jacobi_P(Integer(2), Integer(0), Integer(0), x)                                                      # needs sage.libs.flint sage.symbolic
3/2*x^2 - 1/2
>>> jacobi_P(Integer(2), Integer(1), Integer(2), RealNumber('1.2'))                                                    # needs sage.libs.flint
5.01000000000000

class sage.functions.orthogonal_polys.Func_krawtchouk[source]#

Krawtchouk polynomials $$K_j(x; n, p)$$.

INPUT:

• j – the degree

• x – the independent variable $$x$$

• n – the number of discrete points

• p – the parameter $$p$$

sage.coding.delsarte_bounds.krawtchouk() $$\bar{K}^{n,q}_l(x)$$, which are related by

$(-q)^j \bar{K}^{n,q^{-1}}_j(x) = K_j(x; n, 1-q).$

EXAMPLES:

We verify the orthogonality for $$n = 4$$:

sage: n = 4
sage: p = SR.var('p')                                                           # needs sage.symbolic
sage: matrix([[sum(binomial(n,m) * p**m * (1-p)**(n-m)                          # needs sage.symbolic
....:              * krawtchouk(i,m,n,p) * krawtchouk(j,m,n,p)
....:              for m in range(n+1)).expand().factor()
....:          for i in range(n+1)] for j in range(n+1)])
[               1                0                0                0                0]
[               0     -4*(p - 1)*p                0                0                0]
[               0                0  6*(p - 1)^2*p^2                0                0]
[               0                0                0 -4*(p - 1)^3*p^3                0]
[               0                0                0                0    (p - 1)^4*p^4]

>>> from sage.all import *
>>> n = Integer(4)
>>> p = SR.var('p')                                                           # needs sage.symbolic
>>> matrix([[sum(binomial(n,m) * p**m * (Integer(1)-p)**(n-m)                          # needs sage.symbolic
...              * krawtchouk(i,m,n,p) * krawtchouk(j,m,n,p)
...              for m in range(n+Integer(1))).expand().factor()
...          for i in range(n+Integer(1))] for j in range(n+Integer(1))])
[               1                0                0                0                0]
[               0     -4*(p - 1)*p                0                0                0]
[               0                0  6*(p - 1)^2*p^2                0                0]
[               0                0                0 -4*(p - 1)^3*p^3                0]
[               0                0                0                0    (p - 1)^4*p^4]


We verify the relationship between the Krawtchouk implementations:

sage: q = SR.var('q')                                                           # needs sage.symbolic
sage: all(codes.bounds.krawtchouk(n, 1/q, j, x)*(-q)^j                          # needs sage.symbolic
....:     == krawtchouk(j, x, n, 1-q) for j in range(n+1))
True

>>> from sage.all import *
>>> q = SR.var('q')                                                           # needs sage.symbolic
>>> all(codes.bounds.krawtchouk(n, Integer(1)/q, j, x)*(-q)**j                          # needs sage.symbolic
...     == krawtchouk(j, x, n, Integer(1)-q) for j in range(n+Integer(1)))
True

eval_formula(k, x, n, p)[source]#

Evaluate self using an explicit formula.

EXAMPLES:

sage: x, n, p = var('x,n,p')                                                # needs sage.symbolic
sage: krawtchouk.eval_formula(3, x, n, p).expand().collect(x)               # needs sage.symbolic
-1/6*n^3*p^3 + 1/2*n^2*p^3 - 1/3*n*p^3 - 1/2*(n*p - 2*p + 1)*x^2
+ 1/6*x^3 + 1/6*(3*n^2*p^2 - 9*n*p^2 + 3*n*p + 6*p^2 - 6*p + 2)*x

>>> from sage.all import *
>>> x, n, p = var('x,n,p')                                                # needs sage.symbolic
>>> krawtchouk.eval_formula(Integer(3), x, n, p).expand().collect(x)               # needs sage.symbolic
-1/6*n^3*p^3 + 1/2*n^2*p^3 - 1/3*n*p^3 - 1/2*(n*p - 2*p + 1)*x^2
+ 1/6*x^3 + 1/6*(3*n^2*p^2 - 9*n*p^2 + 3*n*p + 6*p^2 - 6*p + 2)*x

eval_recursive(j, x, n, p, *args, **kwds)[source]#

Return the Krawtchouk polynomial $$K_j(x; n, p)$$ using the recursive formula.

EXAMPLES:

sage: # needs sage.symbolic
sage: x, n, p = var('x,n,p')
sage: krawtchouk.eval_recursive(0, x, n, p)
1
sage: krawtchouk.eval_recursive(1, x, n, p)
-n*p + x
sage: krawtchouk.eval_recursive(2, x, n, p).collect(x)
1/2*n^2*p^2 + 1/2*n*(p - 1)*p - n*p^2 + 1/2*n*p
- 1/2*(2*n*p - 2*p + 1)*x + 1/2*x^2
sage: bool(krawtchouk.eval_recursive(2, x, n, p) == krawtchouk(2, x, n, p))
True
sage: bool(krawtchouk.eval_recursive(3, x, n, p) == krawtchouk(3, x, n, p))
True
sage: bool(krawtchouk.eval_recursive(4, x, n, p) == krawtchouk(4, x, n, p))
True

sage: M = matrix([[-1/2, -1], [1, 0]])                                      # needs sage.modules
sage: krawtchouk.eval_recursive(2, M, 3, 1/2)                               # needs sage.modules
[ 9/8  7/4]
[-7/4  1/4]

>>> from sage.all import *
>>> # needs sage.symbolic
>>> x, n, p = var('x,n,p')
>>> krawtchouk.eval_recursive(Integer(0), x, n, p)
1
>>> krawtchouk.eval_recursive(Integer(1), x, n, p)
-n*p + x
>>> krawtchouk.eval_recursive(Integer(2), x, n, p).collect(x)
1/2*n^2*p^2 + 1/2*n*(p - 1)*p - n*p^2 + 1/2*n*p
- 1/2*(2*n*p - 2*p + 1)*x + 1/2*x^2
>>> bool(krawtchouk.eval_recursive(Integer(2), x, n, p) == krawtchouk(Integer(2), x, n, p))
True
>>> bool(krawtchouk.eval_recursive(Integer(3), x, n, p) == krawtchouk(Integer(3), x, n, p))
True
>>> bool(krawtchouk.eval_recursive(Integer(4), x, n, p) == krawtchouk(Integer(4), x, n, p))
True

>>> M = matrix([[-Integer(1)/Integer(2), -Integer(1)], [Integer(1), Integer(0)]])                                      # needs sage.modules
>>> krawtchouk.eval_recursive(Integer(2), M, Integer(3), Integer(1)/Integer(2))                               # needs sage.modules
[ 9/8  7/4]
[-7/4  1/4]

class sage.functions.orthogonal_polys.Func_laguerre[source]#

REFERENCE:

• [AS1964] 22.5.16, page 778 and page 789.

class sage.functions.orthogonal_polys.Func_legendre_P[source]#

Bases: GinacFunction

EXAMPLES:

sage: # needs sage.symbolic
sage: legendre_P(4, 2.0)
55.3750000000000
sage: legendre_P(1, x)
x
sage: legendre_P(4, x + 1)
35/8*(x + 1)^4 - 15/4*(x + 1)^2 + 3/8
sage: legendre_P(1/2, I+1.)
1.05338240025858 + 0.359890322109665*I
sage: legendre_P(0, SR(1)).parent()
Symbolic Ring

sage: legendre_P(0, 0)                                                          # needs sage.symbolic
1
sage: legendre_P(1, x)                                                          # needs sage.symbolic
x

sage: # needs sage.symbolic
sage: legendre_P(4, 2.)
55.3750000000000
sage: legendre_P(5.5, 1.00001)
1.00017875754114
sage: legendre_P(1/2, I + 1).n()
1.05338240025858 + 0.359890322109665*I
sage: legendre_P(1/2, I + 1).n(59)
1.0533824002585801 + 0.35989032210966539*I
sage: legendre_P(42, RR(12345678))
2.66314881466753e309
sage: legendre_P(42, Reals(20)(12345678))
2.6632e309
sage: legendre_P(201/2, 0).n()
0.0561386178630179
sage: legendre_P(201/2, 0).n(100)
0.056138617863017877699963095883

sage: # needs sage.symbolic
sage: R.<x> = QQ[]
sage: legendre_P(4, x)
35/8*x^4 - 15/4*x^2 + 3/8
sage: legendre_P(10000, x).coefficient(x, 1)
0
sage: var('t,x')
(t, x)
sage: legendre_P(-5, t)
35/8*t^4 - 15/4*t^2 + 3/8
sage: legendre_P(4, x + 1)
35/8*(x + 1)^4 - 15/4*(x + 1)^2 + 3/8
sage: legendre_P(4, sqrt(2))
83/8
sage: legendre_P(4, I*e)
35/8*e^4 + 15/4*e^2 + 3/8

sage: # needs sage.symbolic
sage: n = var('n')
sage: derivative(legendre_P(n,x), x)
(n*x*legendre_P(n, x) - n*legendre_P(n - 1, x))/(x^2 - 1)
sage: derivative(legendre_P(3,x), x)
15/2*x^2 - 3/2
sage: derivative(legendre_P(n,x), n)
Traceback (most recent call last):
...
RuntimeError: derivative w.r.t. to the index is not supported yet

>>> from sage.all import *
>>> # needs sage.symbolic
>>> legendre_P(Integer(4), RealNumber('2.0'))
55.3750000000000
>>> legendre_P(Integer(1), x)
x
>>> legendre_P(Integer(4), x + Integer(1))
35/8*(x + 1)^4 - 15/4*(x + 1)^2 + 3/8
>>> legendre_P(Integer(1)/Integer(2), I+RealNumber('1.'))
1.05338240025858 + 0.359890322109665*I
>>> legendre_P(Integer(0), SR(Integer(1))).parent()
Symbolic Ring

>>> legendre_P(Integer(0), Integer(0))                                                          # needs sage.symbolic
1
>>> legendre_P(Integer(1), x)                                                          # needs sage.symbolic
x

>>> # needs sage.symbolic
>>> legendre_P(Integer(4), RealNumber('2.'))
55.3750000000000
>>> legendre_P(RealNumber('5.5'), RealNumber('1.00001'))
1.00017875754114
>>> legendre_P(Integer(1)/Integer(2), I + Integer(1)).n()
1.05338240025858 + 0.359890322109665*I
>>> legendre_P(Integer(1)/Integer(2), I + Integer(1)).n(Integer(59))
1.0533824002585801 + 0.35989032210966539*I
>>> legendre_P(Integer(42), RR(Integer(12345678)))
2.66314881466753e309
>>> legendre_P(Integer(42), Reals(Integer(20))(Integer(12345678)))
2.6632e309
>>> legendre_P(Integer(201)/Integer(2), Integer(0)).n()
0.0561386178630179
>>> legendre_P(Integer(201)/Integer(2), Integer(0)).n(Integer(100))
0.056138617863017877699963095883

>>> # needs sage.symbolic
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> legendre_P(Integer(4), x)
35/8*x^4 - 15/4*x^2 + 3/8
>>> legendre_P(Integer(10000), x).coefficient(x, Integer(1))
0
>>> var('t,x')
(t, x)
>>> legendre_P(-Integer(5), t)
35/8*t^4 - 15/4*t^2 + 3/8
>>> legendre_P(Integer(4), x + Integer(1))
35/8*(x + 1)^4 - 15/4*(x + 1)^2 + 3/8
>>> legendre_P(Integer(4), sqrt(Integer(2)))
83/8
>>> legendre_P(Integer(4), I*e)
35/8*e^4 + 15/4*e^2 + 3/8

>>> # needs sage.symbolic
>>> n = var('n')
>>> derivative(legendre_P(n,x), x)
(n*x*legendre_P(n, x) - n*legendre_P(n - 1, x))/(x^2 - 1)
>>> derivative(legendre_P(Integer(3),x), x)
15/2*x^2 - 3/2
>>> derivative(legendre_P(n,x), n)
Traceback (most recent call last):
...
RuntimeError: derivative w.r.t. to the index is not supported yet

class sage.functions.orthogonal_polys.Func_legendre_Q[source]#

EXAMPLES:

sage: loads(dumps(legendre_Q))
legendre_Q
sage: maxima(legendre_Q(20, x, hold=True))._sage_().coefficient(x, 10)      # needs sage.symbolic
-29113619535/131072*log(-(x + 1)/(x - 1))

>>> from sage.all import *
legendre_Q
>>> maxima(legendre_Q(Integer(20), x, hold=True))._sage_().coefficient(x, Integer(10))      # needs sage.symbolic
-29113619535/131072*log(-(x + 1)/(x - 1))

eval_formula(n, arg, **kwds)[source]#

Return expanded Legendre Q(n, arg) function expression.

REFERENCE:

EXAMPLES:

sage: # needs sage.symbolic
sage: legendre_Q.eval_formula(1, x)
1/2*x*(log(x + 1) - log(-x + 1)) - 1
sage: legendre_Q.eval_formula(2, x).expand().collect(log(1+x)).collect(log(1-x))
1/4*(3*x^2 - 1)*log(x + 1) - 1/4*(3*x^2 - 1)*log(-x + 1) - 3/2*x
sage: legendre_Q.eval_formula(20, x).coefficient(x, 10)
-29113619535/131072*log(x + 1) + 29113619535/131072*log(-x + 1)
sage: legendre_Q(0, 2)
-1/2*I*pi + 1/2*log(3)

sage: legendre_Q(0, 2.)                                                     # needs mpmath
0.549306144334055 - 1.57079632679490*I

>>> from sage.all import *
>>> # needs sage.symbolic
>>> legendre_Q.eval_formula(Integer(1), x)
1/2*x*(log(x + 1) - log(-x + 1)) - 1
>>> legendre_Q.eval_formula(Integer(2), x).expand().collect(log(Integer(1)+x)).collect(log(Integer(1)-x))
1/4*(3*x^2 - 1)*log(x + 1) - 1/4*(3*x^2 - 1)*log(-x + 1) - 3/2*x
>>> legendre_Q.eval_formula(Integer(20), x).coefficient(x, Integer(10))
-29113619535/131072*log(x + 1) + 29113619535/131072*log(-x + 1)
>>> legendre_Q(Integer(0), Integer(2))
-1/2*I*pi + 1/2*log(3)

>>> legendre_Q(Integer(0), RealNumber('2.'))                                                     # needs mpmath
0.549306144334055 - 1.57079632679490*I

eval_recursive(n, arg, **kwds)[source]#

Return expanded Legendre Q(n, arg) function expression.

EXAMPLES:

sage: legendre_Q.eval_recursive(2, x)                                       # needs sage.symbolic
3/4*x^2*(log(x + 1) - log(-x + 1)) - 3/2*x - 1/4*log(x + 1) + 1/4*log(-x + 1)
sage: legendre_Q.eval_recursive(20, x).expand().coefficient(x, 10)          # needs sage.symbolic
-29113619535/131072*log(x + 1) + 29113619535/131072*log(-x + 1)

>>> from sage.all import *
>>> legendre_Q.eval_recursive(Integer(2), x)                                       # needs sage.symbolic
3/4*x^2*(log(x + 1) - log(-x + 1)) - 3/2*x - 1/4*log(x + 1) + 1/4*log(-x + 1)
>>> legendre_Q.eval_recursive(Integer(20), x).expand().coefficient(x, Integer(10))          # needs sage.symbolic
-29113619535/131072*log(x + 1) + 29113619535/131072*log(-x + 1)

class sage.functions.orthogonal_polys.Func_meixner[source]#

Meixner polynomials $$M_n(x; b, c)$$.

INPUT:

• n – the degree

• x – the independent variable $$x$$

• b, c – the parameters $$b$$, $$c$$

eval_formula(n, x, b, c)[source]#

Evaluate self using an explicit formula.

EXAMPLES:

sage: x, b, c = var('x,b,c')                                                # needs sage.symbolic
sage: meixner.eval_formula(3, x, b, c).expand().collect(x)                  # needs sage.symbolic
-x^3*(3/c - 3/c^2 + 1/c^3 - 1) + b^3
+ 3*(b - 2*b/c + b/c^2 - 1/c - 1/c^2 + 1/c^3 + 1)*x^2 + 3*b^2
+ (3*b^2 + 6*b - 3*b^2/c - 3*b/c - 3*b/c^2 - 2/c^3 + 2)*x + 2*b

>>> from sage.all import *
>>> x, b, c = var('x,b,c')                                                # needs sage.symbolic
>>> meixner.eval_formula(Integer(3), x, b, c).expand().collect(x)                  # needs sage.symbolic
-x^3*(3/c - 3/c^2 + 1/c^3 - 1) + b^3
+ 3*(b - 2*b/c + b/c^2 - 1/c - 1/c^2 + 1/c^3 + 1)*x^2 + 3*b^2
+ (3*b^2 + 6*b - 3*b^2/c - 3*b/c - 3*b/c^2 - 2/c^3 + 2)*x + 2*b

eval_recursive(n, x, b, c, *args, **kwds)[source]#

Return the Meixner polynomial $$M_n(x; b, c)$$ using the recursive formula.

EXAMPLES:

sage: # needs sage.symbolic
sage: x, b, c = var('x,b,c')
sage: meixner.eval_recursive(0, x, b, c)
1
sage: meixner.eval_recursive(1, x, b, c)
-x*(1/c - 1) + b
sage: meixner.eval_recursive(2, x, b, c).simplify_full().collect(x)
-x^2*(2/c - 1/c^2 - 1) + b^2 + (2*b - 2*b/c - 1/c^2 + 1)*x + b
sage: bool(meixner(2, x, b, c) == meixner.eval_recursive(2, x, b, c))
True
sage: bool(meixner(3, x, b, c) == meixner.eval_recursive(3, x, b, c))
True
sage: bool(meixner(4, x, b, c) == meixner.eval_recursive(4, x, b, c))
True
sage: M = matrix([[-1/2, -1], [1, 0]])
sage: ret = meixner.eval_recursive(2, M, b, c).simplify_full().factor()
sage: for i in range(2):  # make the output polynomials in 1/c
....:     for j in range(2):
....:         ret[i, j] = ret[i, j].collect(c)
sage: ret
[b^2 + 1/2*(2*b + 3)/c - 1/4/c^2 - 5/4    -2*b + (2*b - 1)/c + 3/2/c^2 - 1/2]
[    2*b - (2*b - 1)/c - 3/2/c^2 + 1/2             b^2 + b + 2/c - 1/c^2 - 1]

>>> from sage.all import *
>>> # needs sage.symbolic
>>> x, b, c = var('x,b,c')
>>> meixner.eval_recursive(Integer(0), x, b, c)
1
>>> meixner.eval_recursive(Integer(1), x, b, c)
-x*(1/c - 1) + b
>>> meixner.eval_recursive(Integer(2), x, b, c).simplify_full().collect(x)
-x^2*(2/c - 1/c^2 - 1) + b^2 + (2*b - 2*b/c - 1/c^2 + 1)*x + b
>>> bool(meixner(Integer(2), x, b, c) == meixner.eval_recursive(Integer(2), x, b, c))
True
>>> bool(meixner(Integer(3), x, b, c) == meixner.eval_recursive(Integer(3), x, b, c))
True
>>> bool(meixner(Integer(4), x, b, c) == meixner.eval_recursive(Integer(4), x, b, c))
True
>>> M = matrix([[-Integer(1)/Integer(2), -Integer(1)], [Integer(1), Integer(0)]])
>>> ret = meixner.eval_recursive(Integer(2), M, b, c).simplify_full().factor()
>>> for i in range(Integer(2)):  # make the output polynomials in 1/c
...     for j in range(Integer(2)):
...         ret[i, j] = ret[i, j].collect(c)
>>> ret
[b^2 + 1/2*(2*b + 3)/c - 1/4/c^2 - 5/4    -2*b + (2*b - 1)/c + 3/2/c^2 - 1/2]
[    2*b - (2*b - 1)/c - 3/2/c^2 + 1/2             b^2 + b + 2/c - 1/c^2 - 1]

class sage.functions.orthogonal_polys.Func_ultraspherical[source]#

Bases: GinacFunction

Return the ultraspherical (or Gegenbauer) polynomial gegenbauer(n,a,x),

$C_n^{a}(x) = \sum_{k=0}^{\lfloor n/2\rfloor} (-1)^k \frac{\Gamma(n-k+a)}{\Gamma(a)k!(n-2k)!} (2x)^{n-2k}.$

When $$n$$ is a nonnegative integer, this formula gives a polynomial in $$z$$ of degree $$n$$, but all parameters are permitted to be complex numbers. When $$a = 1/2$$, the Gegenbauer polynomial reduces to a Legendre polynomial.

Computed using Pynac.

For numerical evaluation, consider using the mpmath library, as it also allows complex numbers (and negative $$n$$ as well); see the examples below.

REFERENCE:

EXAMPLES:

sage: # needs sage.symbolic
sage: ultraspherical(8, 101/11, x)
795972057547264/214358881*x^8 - 62604543852032/19487171*x^6...
sage: x = PolynomialRing(QQ, 'x').gen()
sage: ultraspherical(2, 3/2, x)
15/2*x^2 - 3/2
sage: ultraspherical(1, 1, x)
2*x
sage: t = PolynomialRing(RationalField(), "t").gen()
sage: gegenbauer(3, 2, t)
32*t^3 - 12*t
sage: x = SR.var('x')
sage: n = ZZ.random_element(5, 5001)
sage: a = QQ.random_element().abs() + 5
sage: s = (  (n + 1)*ultraspherical(n + 1, a, x)
....:      - 2*x*(n + a)*ultraspherical(n, a, x)
....:      + (n + 2*a - 1)*ultraspherical(n - 1, a, x) )
sage: s.expand().is_zero()
True
sage: ultraspherical(5, 9/10, 3.1416)
6949.55439044240
sage: ultraspherical(5, 9/10, RealField(100)(pi))                               # needs sage.rings.real_mpfr
6949.4695419382702451843080687

sage: # needs sage.symbolic
sage: a, n = SR.var('a,n')
sage: gegenbauer(2, a, x)
2*(a + 1)*a*x^2 - a
sage: gegenbauer(3, a, x)
4/3*(a + 2)*(a + 1)*a*x^3 - 2*(a + 1)*a*x
sage: gegenbauer(3, a, x).expand()
4/3*a^3*x^3 + 4*a^2*x^3 + 8/3*a*x^3 - 2*a^2*x - 2*a*x
sage: gegenbauer(10, a, x).expand().coefficient(x, 2)
1/12*a^6 + 5/4*a^5 + 85/12*a^4 + 75/4*a^3 + 137/6*a^2 + 10*a
sage: ex = gegenbauer(100, a, x)
sage: (ex.subs(a==55/98) - gegenbauer(100, 55/98, x)).is_trivial_zero()
True

sage: # needs sage.symbolic
sage: gegenbauer(2, -3, x)
12*x^2 + 3
sage: gegenbauer(120, -99/2, 3)
1654502372608570682112687530178328494861923493372493824
sage: gegenbauer(5, 9/2, x)
21879/8*x^5 - 6435/4*x^3 + 1287/8*x
sage: gegenbauer(15, 3/2, 5)
3903412392243800

sage: derivative(gegenbauer(n, a, x), x)                                        # needs sage.symbolic
2*a*gegenbauer(n - 1, a + 1, x)
sage: derivative(gegenbauer(3, a, x), x)                                        # needs sage.symbolic
4*(a + 2)*(a + 1)*a*x^2 - 2*(a + 1)*a
sage: derivative(gegenbauer(n, a, x), a)                                        # needs sage.symbolic
Traceback (most recent call last):
...
RuntimeError: derivative w.r.t. to the second index is not supported yet

>>> from sage.all import *
>>> # needs sage.symbolic
>>> ultraspherical(Integer(8), Integer(101)/Integer(11), x)
795972057547264/214358881*x^8 - 62604543852032/19487171*x^6...
>>> x = PolynomialRing(QQ, 'x').gen()
>>> ultraspherical(Integer(2), Integer(3)/Integer(2), x)
15/2*x^2 - 3/2
>>> ultraspherical(Integer(1), Integer(1), x)
2*x
>>> t = PolynomialRing(RationalField(), "t").gen()
>>> gegenbauer(Integer(3), Integer(2), t)
32*t^3 - 12*t
>>> x = SR.var('x')
>>> n = ZZ.random_element(Integer(5), Integer(5001))
>>> a = QQ.random_element().abs() + Integer(5)
>>> s = (  (n + Integer(1))*ultraspherical(n + Integer(1), a, x)
...      - Integer(2)*x*(n + a)*ultraspherical(n, a, x)
...      + (n + Integer(2)*a - Integer(1))*ultraspherical(n - Integer(1), a, x) )
>>> s.expand().is_zero()
True
>>> ultraspherical(Integer(5), Integer(9)/Integer(10), RealNumber('3.1416'))
6949.55439044240
>>> ultraspherical(Integer(5), Integer(9)/Integer(10), RealField(Integer(100))(pi))                               # needs sage.rings.real_mpfr
6949.4695419382702451843080687

>>> # needs sage.symbolic
>>> a, n = SR.var('a,n')
>>> gegenbauer(Integer(2), a, x)
2*(a + 1)*a*x^2 - a
>>> gegenbauer(Integer(3), a, x)
4/3*(a + 2)*(a + 1)*a*x^3 - 2*(a + 1)*a*x
>>> gegenbauer(Integer(3), a, x).expand()
4/3*a^3*x^3 + 4*a^2*x^3 + 8/3*a*x^3 - 2*a^2*x - 2*a*x
>>> gegenbauer(Integer(10), a, x).expand().coefficient(x, Integer(2))
1/12*a^6 + 5/4*a^5 + 85/12*a^4 + 75/4*a^3 + 137/6*a^2 + 10*a
>>> ex = gegenbauer(Integer(100), a, x)
>>> (ex.subs(a==Integer(55)/Integer(98)) - gegenbauer(Integer(100), Integer(55)/Integer(98), x)).is_trivial_zero()
True

>>> # needs sage.symbolic
>>> gegenbauer(Integer(2), -Integer(3), x)
12*x^2 + 3
>>> gegenbauer(Integer(120), -Integer(99)/Integer(2), Integer(3))
1654502372608570682112687530178328494861923493372493824
>>> gegenbauer(Integer(5), Integer(9)/Integer(2), x)
21879/8*x^5 - 6435/4*x^3 + 1287/8*x
>>> gegenbauer(Integer(15), Integer(3)/Integer(2), Integer(5))
3903412392243800

>>> derivative(gegenbauer(n, a, x), x)                                        # needs sage.symbolic
2*a*gegenbauer(n - 1, a + 1, x)
>>> derivative(gegenbauer(Integer(3), a, x), x)                                        # needs sage.symbolic
4*(a + 2)*(a + 1)*a*x^2 - 2*(a + 1)*a
>>> derivative(gegenbauer(n, a, x), a)                                        # needs sage.symbolic
Traceback (most recent call last):
...
RuntimeError: derivative w.r.t. to the second index is not supported yet


Numerical evaluation with the mpmath library:

sage: # needs mpmath
sage: from mpmath import gegenbauer as gegenbauer_mp
sage: from mpmath import mp
sage: mp.pretty = True; mp.dps=25
sage: gegenbauer_mp(-7,0.5,0.3)
0.1291811875
sage: gegenbauer_mp(2+3j, -0.75, -1000j)
(-5038991.358609026523401901 + 9414549.285447104177860806j)

>>> from sage.all import *
>>> # needs mpmath
>>> from mpmath import gegenbauer as gegenbauer_mp
>>> from mpmath import mp
>>> mp.pretty = True; mp.dps=Integer(25)
>>> gegenbauer_mp(-Integer(7),RealNumber('0.5'),RealNumber('0.3'))
0.1291811875
>>> gegenbauer_mp(Integer(2)+ComplexNumber(0, '3'), -RealNumber('0.75'), -ComplexNumber(0, '1000'))
(-5038991.358609026523401901 + 9414549.285447104177860806j)

class sage.functions.orthogonal_polys.OrthogonalFunction(name, nargs=2, latex_name=None, conversions=None)[source]#

Base class for orthogonal polynomials.

This class is an abstract base class for all orthogonal polynomials since they share similar properties. The evaluation as a polynomial is either done via maxima, or with pynac.

Convention: The first argument is always the order of the polynomial, the others are other values or parameters where the polynomial is evaluated.

eval_formula(*args)[source]#

Evaluate this polynomial using an explicit formula.

EXAMPLES:

sage: from sage.functions.orthogonal_polys import OrthogonalFunction
sage: P = OrthogonalFunction('testo_P')
sage: P.eval_formula(1, 2.0)
Traceback (most recent call last):
...
NotImplementedError: no explicit calculation of values implemented

>>> from sage.all import *
>>> from sage.functions.orthogonal_polys import OrthogonalFunction
>>> P = OrthogonalFunction('testo_P')
>>> P.eval_formula(Integer(1), RealNumber('2.0'))
Traceback (most recent call last):
...
NotImplementedError: no explicit calculation of values implemented