268 lines
4.8 KiB
C
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;
|
|
}
|
|
|