Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Trac #25034: formula for n=m fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
mjungmath committed Apr 10, 2021
1 parent a89f81d commit 4fcc574
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 8 deletions.
82 changes: 74 additions & 8 deletions src/sage/functions/orthogonal_polys.py
Expand Up @@ -1424,6 +1424,65 @@ def _derivative_(self, n, x, *args,**kwds):
legendre_Q = Func_legendre_Q()

class Func_assoc_legendre_P(BuiltinFunction):
r"""
Return the associated Legendre polynomial for integers `n > -1` and `-n \leq m \leq n`.
REFERENCE:
- Weisstein, Eric W. "Associated Legendre Polynomial." From MathWorld--A Wolfram Web Resource.
https://mathworld.wolfram.com/AssociatedLegendrePolynomial.html
EXAMPLES:
Print the first associated Legendre polynomials::
sage: for n in range(4):
....: 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)
Associated Legendre polynomials can be extended to negative valued `m`
according to the following formula:
.. MATH::
P^{-m}_n(x) = (-1)^{m} \frac{(n-m)!}{(n+m)!} P_n^m(x),
where `|m| \leq n`. Otherwise, if `|m|` exceeds `n`, `P^{-m}_n(x)`
vanishes.
Here are some values::
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
TESTS:
Some consistency checks::
sage: gen_legendre_P.eval_poly(1, 1, x)
-sqrt(-x^2 + 1)
sage: gen_legendre_P(1, 1, x)
-sqrt(-x^2 + 1)
sage: gen_legendre_P.eval_poly(1, 1, 0.5) # abs tol 1e-14
-0.866025403784439
sage: gen_legendre_P(1, 1, 0.5) # abs tol 1e-14
-0.866025403784439
"""
def __init__(self):
r"""
EXAMPLES::
Expand Down Expand Up @@ -1455,10 +1514,13 @@ def _eval_(self, n, m, x, *args, **kwds):
ret = self._eval_special_values_(n, m, x)
if ret is not None:
return ret
if (n in ZZ and m in ZZ
and n >= 0 and m >= 0
and (x in ZZ or not SR(x).is_numeric())):
return self.eval_poly(n, m, x)
if n in ZZ and m in ZZ and (x in ZZ or not SR(x).is_numeric()) and n >= 0:
if m >= 0:
return self.eval_poly(n, m, x)
elif -m <= n:
return (-1)**(-m)*factorial(n+m)/factorial(n-m)*self.eval_poly(n, -m, x)
else:
return ZZ(0)

def _eval_special_values_(self, n, m, x):
"""
Expand All @@ -1471,9 +1533,9 @@ def _eval_special_values_(self, n, m, x):
sage: gen_legendre_P(2,0,4)==legendre_P(2,4)
True
sage: gen_legendre_P(2,2,4)
45
-45
sage: gen_legendre_P(2,2,x)
3*x^2 - 3
-3*x^2 + 3
sage: gen_legendre_P(13/2,2,0)
2*sqrt(2)*gamma(19/4)/(sqrt(pi)*gamma(13/4))
sage: (m,n) = var('m,n')
Expand All @@ -1489,7 +1551,10 @@ def _eval_special_values_(self, n, m, x):
if m == 0:
return legendre_P(n, x)
if n == m:
return factorial(2*m)/2**m/factorial(m) * (x**2-1)**(m/2)
return (-1)**m*factorial(2*m)/(2**m*factorial(m)) * (1-x**2)**(m/2)
if n == m+1:
return x*(2*m+1)*gen_legendre_P(m, m, x)
# TODO: do the following lines respect the same convention?
if x == 0:
from .gamma import gamma
from .other import sqrt
Expand All @@ -1516,6 +1581,7 @@ def _evalf_(self, n, m, x, parent=None, **kwds):
if ret is not None:
return ret

# TODO: do the following lines respect the same convention?
import mpmath
from sage.libs.mpmath.all import call as mpcall
return mpcall(mpmath.legenp, n, m, x, parent=parent)
Expand Down Expand Up @@ -1547,7 +1613,7 @@ def eval_poly(self, n, m, arg, **kwds):
ex2 = sum(b * arg**a for a, b in enumerate(p))
return (-1)**(m+n)*ex1*ex2

def _derivative_(self, n, m, x, *args,**kwds):
def _derivative_(self, n, m, x, *args, **kwds):
"""
Return the derivative of ``gen_legendre_P(n,m,x)``.
Expand Down
12 changes: 12 additions & 0 deletions src/sage/functions/special.py
Expand Up @@ -228,6 +228,18 @@ def _eval_(self, n, m, theta, phi, **kwargs):
sage: ex = spherical_harmonic(3,2,1,2*pi/3)
sage: QQbar(ex * sqrt(pi)/cos(1)/sin(1)^2).minpoly()
x^4 + 105/32*x^2 + 11025/1024
Check whether :trac:`25034` yields correct results compared to Maxima::
sage: spherical_harmonic(1,1,pi/3,pi/6).n()
0.259120612103502 + 0.149603355150537*I
sage: maxima.spherical_harmonic(1,1,pi/3,pi/6).n()
0.259120612103502 + 0.149603355150537*I
sage: spherical_harmonic(1,-1,pi/3,pi/6).n()
-0.259120612103502 + 0.149603355150537*I
sage: maxima.spherical_harmonic(1,-1,pi/3,pi/6).n()
-0.259120612103502 + 0.149603355150537*I
"""
if n in ZZ and m in ZZ and n > -1:
if abs(m) > n:
Expand Down

0 comments on commit 4fcc574

Please sign in to comment.