Files
amspyigrf13/scratch/c_legendrefn.c
2025-07-18 11:25:48 -04:00

268 lines
4.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "c_legendrecoefs.c"
static const float amsleg_pif = 3.14159265359;
static const double amsleg_pi = 3.14159265359;
float amsleg_polyvalf(float x, const float *coefs, int polyorder)
{
float ret = 0.0f;
float xv = 1.0f;
int I;
for(I=0;I<=polyorder;I++)
{
//printf("debug: %d %1.6g\n",I,coefs[I]);
ret = ret + coefs[I]*xv;
xv = xv * x;
}
return ret;
}
double amsleg_polyval(double x, const double *coefs, int polyorder)
{
double ret = 0.0;
double xv = 1.0;
int I;
for(I=0;I<=polyorder;I++)
{
ret = ret + coefs[I]*xv;
xv = xv * x;
}
return ret;
}
//Schmidt Quasi-Normalized Legendre Function P^n_m(x)
//for degree n, and order m, m<=n
//n from 0 to 20
//m from 0 to n
float amsleg_legendref(float x, int n, int m)
{
float ret = 0.0f;
int I, mo2, mr, ind;
float mpart = 1.0f;
float ppart = 0.0f;
const float *coefptr = NULL;
if(x<-1.0f) x=-1.0f;
if(x>1.0f) x = 1.0f;
if(m<0)
{
m = -m;
}
if(m>n || n<0 || n>20)
{
ret = 0.0f;
return ret;
}
if(m>0)
{
mo2 = m/2;
mr = (m%2==1);
for(I=0;I<mo2;I++)
{
mpart = mpart*(1.0f-x*x);
}
if(mr==1)
{
mpart = mpart*sqrt(1.0f-x*x);
}
}
ind = n*(n+1)/2 + m;
//printf("debug: ind=%d\n",ind);
coefptr = &(amslegendrecoefsf[ind*(amslegendre_maxporder+1)]);
// printf("debug ");
// for(I=0;I<amslegendre_maxporder+1;I++)
// {
// printf("%1.6g,",coefptr[I]);
// }
// printf("\n");
ppart = amsleg_polyvalf(x,coefptr,amslegendre_maxporder);
ret = ppart*mpart;
return ret;
}
//Schmidt Quasi-Normalized Legendre Function P^n_m(x)
//for degree n, and order m, m<=n
//n from 0 to 20
//m from 0 to n
double amsleg_legendre(double x, int n, int m)
{
double ret = 0.0;
int I, mo2, mr, ind;
double mpart = 1.0;
double ppart = 0.0;
const double *coefptr = NULL;
if(x<-1.0f) x=-1.0f;
if(x>1.0f) x = 1.0f;
if(m<0)
{
m = -m;
}
if(m>n || n<0 || n>20)
{
ret = 0.0f;
return ret;
}
if(m>0)
{
mo2 = m/2;
mr = (m%2==1);
for(I=0;I<mo2;I++)
{
mpart = mpart*(1.0f-x*x);
}
if(mr==1)
{
mpart = mpart*sqrt(1.0f-x*x);
}
}
ind = n*(n+1)/2 + m;
coefptr = &(amslegendrecoefs[ind*(amslegendre_maxporder+1)]);
ppart = amsleg_polyval(x,coefptr,amslegendre_maxporder);
ret = ppart*mpart;
return ret;
}
float amsleg_rsphcosf(float theta,float phi,int n,int m)
{
float ret = 0.0f;
float p;
ret = amsleg_legendref(cosf(theta),n,m)*cosf(m*phi);
return ret;
}
float amsleg_rsphsinf(float theta,float phi,int n,int m)
{
float ret = 0.0f;
float p;
ret = amsleg_legendref(cosf(theta),n,m)*sinf(m*phi);
return ret;
}
float amsleg_dotprodf(int n1, int m1, int sc1, int n2, int m2, int sc2)
{
float ret = 0.0f;
float p1,p2;
int Ntheta = 360;
int Nphi = 720;
int I,J;
float dtheta,dphi,theta,phi;
float domega = 0.0f;
dtheta = amsleg_pif/(Ntheta);
dphi = 2.0f*amsleg_pif/(Nphi);
for(I=0;I<Ntheta;I++)
{
for(J=0;J<Nphi;J++)
{
theta = dtheta*I;
phi = dphi*J;
domega = dtheta*dphi*sin(theta);
if(sc1==0)
p1 = amsleg_rsphcosf(theta,phi,n1,m1);
else
p1 = amsleg_rsphsinf(theta,phi,n1,m1);
if(sc2==0)
p2 = amsleg_rsphcosf(theta,phi,n2,m2);
else
p2 = amsleg_rsphsinf(theta,phi,n2,m2);
ret = ret + p1*p2*domega;
//ret = ret + domega;
}
}
return ret;
}
void amsleg_test1()
{
int n = 20;
int m = 20;
float p;
float x;
printf("Test legendre fn %d %d \n",n,m);
for(x=-1.0f; x<=1.005f; x = x + 0.01f)
{
p = amsleg_legendref(x,n,m);
printf("%1.4g\t\t%1.4g\n",x,p);
}
return;
}
void amsleg_test2()
{
int n1 = 3;
int m1 = 1;
int n2;
int m2;
float dp;
//for Schmidt quasi normalized spherical harmonics:
// 1/4pi * integral( C_mn C_MN sin(th)dthdphi ) = 1/(2n+1) del_nN del_mM
// there is a factor of 1/(2n+1)
printf("dot products with (%d,%d).\n",n1,m1);
for(n2 = 0; n2<5; n2++)
{
for(m2 = 0; m2<=n2; m2++)
{
dp = amsleg_dotprodf(n2,m2,1,n2,m2,1);
if(dp<1E-4) dp = 0;
dp = dp/4.0f/amsleg_pif;
dp = dp * (2*n2+1);
printf("(%d,%d): %1.6g\n",n2,m2,dp);
}
}
}
int main(int argc, char* argv[])
{
printf("Legendre Function Tests\n");
amsleg_test2();
return 0;
}