module lib_legendre
!函数默认逐元
Implicit None
private
public::legendre,associated_legendre,mod_legendre!求模函数输出为双精度
interface legendre
module procedure legendre_sp!勒让德多项式,输入输出均为单精度
module procedure legendre_dp!双精度
end interface
interface associated_legendre!未除模进行归一化,值会比较大
module procedure associated_legendre_sp!单精度连带勒让德
module procedure associated_legendre_dp!双精度
end interface
contains
elemental function combination(m,n)!组合数
!C(m,n)=m!/n!(m-n)!=exp(SIGMA(i=m-n+1,m)(ln(m_i))-SIGMA(ln(n)))
integer,intent(in)::m,n
integer::combination
integer::counter
real(kind=8),allocatable::top(:),bottom(:)!在逐元函数中,虚参不能用于声明变量,除非是查询函数
allocate(top(n),bottom(n))!只能这样手动配置
top=[(counter,counter=m-n+1,m,1)]
bottom=[(counter,counter=1,n,1)]
combination=nint(exp(sum(dlog(top))-sum(dlog(bottom))))
end function combination
pure function mod_legendre(l,m) result(ans)!勒让德多项式的模
integer,intent(in)::l
integer,intent(in),optional::m
integer::counter
real(kind=8)::ans
if (present(m)) then
ans=sqrt(product([(counter,counter=l-m+1,l+m,1)])*2/real(2*l+1))
else
ans=sqrt(2/real(2*l+1))
end if
end function mod_legendre
elemental function legendre_sp(x,n) result(ans)!P_{n}(x)!n阶勒让德函数,输入-1<x<1
real(kind=4),intent(in)::x
integer,intent(in)::n
integer::limit,counter
real(kind=4),allocatable::x_vector(:),l_vector(:)
integer,allocatable::m(:)
real(kind=4)::ans
limit=floor(real(n)/2)
allocate(x_vector(0:limit),l_vector(0:limit),m(0:limit))
m=[(counter,counter=0,limit,1)] !求和指标
l_vector=real(((-1)**m)*combination(n,m)*combination(2*(n-m),n))/real(2**n)!系数,注意要用real函数把整型变实型
x_vector=x**(n-2*m)!自变量
ans=dot_product(l_vector,x_vector)
end function legendre_sp
elemental function associated_legendre_sp(x,n,m) result(ans) !P_{n}^{m}(x)=-1^{m}(1-x^{2})^{m/2}\frac{d^{m}}{dx^{m}}P_{n}(x)
real::ans !n阶连带勒让德
real , intent(in)::x
integer,intent(in)::n,m
integer::limit,counter
real(kind=4),allocatable::x_vector(:),l_vector(:)
integer,allocatable::k(:)
if (m == 0) then
ans=legendre_sp(x,n)
else
limit=floor(real(n)/2)
allocate(x_vector(0:limit),l_vector(0:limit),k(0:limit))
k=[(counter,counter=0,limit,1)] !求和指标
l_vector=real(((-1)**k)*combination(n,k)*combination(2*(n-k),n))/real(2**n)!系数
x_vector=product(reshape([(n-2*k-counter,counter=0,m-1,1)],[limit+1,m]),dim=2)*(x**(n-2*k-m))!自变量
where (n-2*k-m < 0) x_vector=0
ans=dot_product(l_vector,x_vector)*((1-x**2)**(real(m)/2))*((-1)**m)
end if
end function associated_legendre_sp
elemental function legendre_dp(x,n) result(ans)!P_{n}(x)!n阶勒让德函数,输入-1<x<1
real(kind=8),intent(in)::x
integer,intent(in)::n
integer::limit,counter
real(kind=8),allocatable::x_vector(:),l_vector(:)
integer,allocatable::m(:)
real(kind=8)::ans
limit=floor(real(n)/2)
allocate(x_vector(0:limit),l_vector(0:limit),m(0:limit))
m=[(counter,counter=0,limit,1)] !求和指标
l_vector=real(((-1)**m)*combination(n,m)*combination(2*(n-m),n))/real(2**n)!系数,注意要用real函数把整型变实型
x_vector=x**(n-2*m)!自变量
ans=dot_product(l_vector,x_vector)
end function legendre_dp
elemental function associated_legendre_dp(x,n,m) result(ans) !P_{n}^{m}(x)=-1^{m}(1-x^{2})^{m/2}\frac{d^{m}}{dx^{m}}P_{n}(x)
real(kind=8)::ans !n阶连带勒让德
real(kind=8),intent(in)::x
integer,intent(in)::n,m
integer::limit,counter
real(kind=8),allocatable::x_vector(:),l_vector(:)
integer,allocatable::k(:)
if ( m == 0 ) then
ans=legendre_dp(x,n)
else
limit=floor(real(n)/2)
allocate(x_vector(0:limit),l_vector(0:limit),k(0:limit))
k=[(counter,counter=0,limit,1)] !求和指标
l_vector=real(((-1)**k)*combination(n,k)*combination(2*(n-k),n))/real(2**n)!系数
x_vector=product(reshape([(n-2*k-counter,counter=0,m-1,1)],[limit+1,m]),dim=2)*(x**(n-2*k-m))!自变量
where (n-2*k-m < 0) x_vector=0
ans=dot_product(l_vector,x_vector)*((1-x**2)**(real(m)/2))*((-1)**m)
end if
end function associated_legendre_dp
end module lib_legendre