00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <math.h>
00033 #include <stdlib.h>
00034 #include "sharp_ylmgen_c.h"
00035 #include "c_utils.h"
00036
00037 static inline void normalize (double *val, int *scale, double xfmax)
00038 {
00039 while (fabs(*val)>xfmax) { *val*=sharp_fsmall; ++*scale; }
00040 if (*val!=0.)
00041 while (fabs(*val)<xfmax*sharp_fsmall) { *val*=sharp_fbig; --*scale; }
00042 }
00043
00044 void sharp_Ylmgen_init (sharp_Ylmgen_C *gen, int l_max, int m_max, int spin)
00045 {
00046 const double inv_sqrt4pi = 0.2820947917738781434740397257803862929220;
00047
00048 gen->lmax = l_max;
00049 gen->mmax = m_max;
00050 UTIL_ASSERT(spin>=0,"incorrect spin: must be nonnegative");
00051 UTIL_ASSERT(l_max>=spin,"incorrect l_max: must be >= spin");
00052 UTIL_ASSERT(l_max>=m_max,"incorrect l_max: must be >= m_max");
00053 gen->s = spin;
00054 UTIL_ASSERT((sharp_minscale<=0)&&(sharp_maxscale>0),
00055 "bad value for min/maxscale");
00056 gen->cf=RALLOC(double,sharp_maxscale-sharp_minscale+1);
00057 gen->cf[-sharp_minscale]=1.;
00058 for (int m=-sharp_minscale-1; m>=0; --m)
00059 gen->cf[m]=gen->cf[m+1]*sharp_fsmall;
00060 for (int m=-sharp_minscale+1; m<(sharp_maxscale-sharp_minscale+1); ++m)
00061 gen->cf[m]=gen->cf[m-1]*sharp_fbig;
00062
00063 gen->m = -1;
00064 if (spin==0)
00065 {
00066 gen->rf = RALLOC(sharp_ylmgen_dbl2,gen->lmax+1);
00067 gen->mfac = RALLOC(double,gen->mmax+1);
00068 gen->mfac[0] = inv_sqrt4pi;
00069 for (int m=1; m<=gen->mmax; ++m)
00070 gen->mfac[m] = gen->mfac[m-1]*sqrt((2*m+1.)/(2*m));
00071 gen->root = RALLOC(double,2*gen->lmax+5);
00072 gen->iroot = RALLOC(double,2*gen->lmax+5);
00073 for (int m=0; m<2*gen->lmax+5; ++m)
00074 {
00075 gen->root[m] = sqrt(m);
00076 gen->iroot[m] = (m==0) ? 0. : 1./gen->root[m];
00077 }
00078 }
00079 else
00080 {
00081 gen->m=gen->mlo=gen->mhi=-1234567890;
00082 ALLOC(gen->fx,sharp_ylmgen_dbl3,gen->lmax+2);
00083 for (int m=0; m<gen->lmax+2; ++m)
00084 gen->fx[m].f[0]=gen->fx[m].f[1]=gen->fx[m].f[2]=0.;
00085 ALLOC(gen->inv,double,gen->lmax+1);
00086 gen->inv[0]=0;
00087 for (int m=1; m<gen->lmax+1; ++m) gen->inv[m]=1./m;
00088 ALLOC(gen->flm1,double,2*gen->lmax+1);
00089 ALLOC(gen->flm2,double,2*gen->lmax+1);
00090 for (int m=0; m<2*gen->lmax+1; ++m)
00091 {
00092 gen->flm1[m] = sqrt(1./(m+1.));
00093 gen->flm2[m] = sqrt(m/(m+1.));
00094 }
00095 ALLOC(gen->prefac,double,gen->mmax+1);
00096 ALLOC(gen->fscale,int,gen->mmax+1);
00097 double *fac = RALLOC(double,2*gen->lmax+1);
00098 int *facscale = RALLOC(int,2*gen->lmax+1);
00099 fac[0]=1; facscale[0]=0;
00100 for (int m=1; m<2*gen->lmax+1; ++m)
00101 {
00102 fac[m]=fac[m-1]*sqrt(m);
00103 facscale[m]=facscale[m-1];
00104 normalize(&fac[m],&facscale[m],sharp_fbighalf);
00105 }
00106 for (int m=0; m<=gen->mmax; ++m)
00107 {
00108 int mlo=gen->s, mhi=m;
00109 if (mhi<mlo) SWAP(mhi,mlo,int);
00110 double tfac=fac[2*mhi]/fac[mhi+mlo];
00111 int tscale=facscale[2*mhi]-facscale[mhi+mlo];
00112 normalize(&tfac,&tscale,sharp_fbighalf);
00113 tfac/=fac[mhi-mlo];
00114 tscale-=facscale[mhi-mlo];
00115 normalize(&tfac,&tscale,sharp_fbighalf);
00116 gen->prefac[m]=tfac;
00117 gen->fscale[m]=tscale;
00118 }
00119 DEALLOC(fac);
00120 DEALLOC(facscale);
00121 }
00122 }
00123
00124 void sharp_Ylmgen_destroy (sharp_Ylmgen_C *gen)
00125 {
00126 DEALLOC(gen->cf);
00127 if (gen->s==0)
00128 {
00129 DEALLOC(gen->rf);
00130 DEALLOC(gen->mfac);
00131 DEALLOC(gen->root);
00132 DEALLOC(gen->iroot);
00133 }
00134 else
00135 {
00136 DEALLOC(gen->fx);
00137 DEALLOC(gen->prefac);
00138 DEALLOC(gen->fscale);
00139 DEALLOC(gen->flm1);
00140 DEALLOC(gen->flm2);
00141 DEALLOC(gen->inv);
00142 }
00143 }
00144
00145 void sharp_Ylmgen_prepare (sharp_Ylmgen_C *gen, int m)
00146 {
00147 if (m==gen->m) return;
00148 UTIL_ASSERT(m>=0,"incorrect m");
00149 gen->m = m;
00150
00151 if (gen->s==0)
00152 {
00153 gen->rf[m].f[0] = gen->root[2*m+3];
00154 gen->rf[m].f[1] = 0.;
00155 for (int l=m+1; l<=gen->lmax; ++l)
00156 {
00157 double tmp=gen->root[2*l+3]*gen->iroot[l+1+m]*gen->iroot[l+1-m];
00158 gen->rf[l].f[0] = tmp*gen->root[2*l+1];
00159 gen->rf[l].f[1] = tmp*gen->root[l+m]*gen->root[l-m]*gen->iroot[2*l-1];
00160 }
00161 }
00162 else
00163 {
00164 int mlo_=m, mhi_=gen->s;
00165 if (mhi_<mlo_) SWAP(mhi_,mlo_,int);
00166 int ms_similar = ((gen->mhi==mhi_) && (gen->mlo==mlo_));
00167
00168 gen->mlo = mlo_; gen->mhi = mhi_;
00169
00170 if (!ms_similar)
00171 {
00172 for (int l=gen->mhi; l<gen->lmax; ++l)
00173 {
00174 double t = gen->flm1[l+gen->m]*gen->flm1[l-gen->m]
00175 *gen->flm1[l+gen->s]*gen->flm1[l-gen->s];
00176 double lt = 2*l+1;
00177 double l1 = l+1;
00178 gen->fx[l+1].f[0]=l1*lt*t;
00179 gen->fx[l+1].f[1]=gen->m*gen->s*gen->inv[l]*gen->inv[l+1];
00180 t = gen->flm2[l+gen->m]*gen->flm2[l-gen->m]
00181 *gen->flm2[l+gen->s]*gen->flm2[l-gen->s];
00182 gen->fx[l+1].f[2]=t*l1*gen->inv[l];
00183 }
00184 }
00185
00186 gen->preMinus_p = gen->preMinus_m = 0;
00187 if (gen->mhi==gen->m)
00188 {
00189 gen->cosPow = gen->mhi+gen->s; gen->sinPow = gen->mhi-gen->s;
00190 gen->preMinus_p = gen->preMinus_m = ((gen->mhi-gen->s)&1);
00191 }
00192 else
00193 {
00194 gen->cosPow = gen->mhi+gen->m; gen->sinPow = gen->mhi-gen->m;
00195 gen->preMinus_m = ((gen->mhi+gen->m)&1);
00196 }
00197 }
00198 }
00199
00200 double *sharp_Ylmgen_get_norm (int lmax, int spin)
00201 {
00202 const double pi = 3.141592653589793238462643383279502884197;
00203 double *res=RALLOC(double,lmax+1);
00204
00205 #if 1
00206 double spinsign = (spin>0) ? -1.0 : 1.0;
00207 #else
00208 double spinsign = 1.0;
00209 #endif
00210
00211 if (spin==0)
00212 {
00213 for (int l=0; l<=lmax; ++l)
00214 res[l]=1.;
00215 return res;
00216 }
00217
00218 spinsign = (spin&1) ? -spinsign : spinsign;
00219 for (int l=0; l<=lmax; ++l)
00220 res[l] = (l<spin) ? 0. : spinsign*0.5*sqrt((2*l+1)/(4*pi));
00221 return res;
00222 }
00223
00224 double *sharp_Ylmgen_get_d1norm (int lmax)
00225 {
00226 const double pi = 3.141592653589793238462643383279502884197;
00227 double *res=RALLOC(double,lmax+1);
00228
00229 for (int l=0; l<=lmax; ++l)
00230 res[l] = (l<1) ? 0. : 0.5*sqrt(l*(l+1.)*(2*l+1.)/(4*pi));
00231 return res;
00232 }