/* * This file is part of libsharp. * * libsharp is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libsharp is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libsharp; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * libsharp is being developed at the Max-Planck-Institut fuer Astrophysik * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt * (DLR). */ /* * Helper code for efficient calculation of Y_lm(theta,phi=0) * * Copyright (C) 2005-2012 Max-Planck-Society * Author: Martin Reinecke */ #include #include #include "sharp_ylmgen_c.h" #include "c_utils.h" static inline void normalize (double *val, int *scale, double xfmax) { while (fabs(*val)>xfmax) { *val*=sharp_fsmall; ++*scale; } if (*val!=0.) while (fabs(*val)lmax = l_max; gen->mmax = m_max; UTIL_ASSERT(spin>=0,"incorrect spin"); gen->s = spin; UTIL_ASSERT((sharp_minscale<=0)&&(sharp_maxscale>0), "bad value for min/maxscale"); gen->cf=RALLOC(double,sharp_maxscale-sharp_minscale+1); gen->cf[-sharp_minscale]=1.; for (int m=-sharp_minscale-1; m>=0; --m) gen->cf[m]=gen->cf[m+1]*sharp_fsmall; for (int m=-sharp_minscale+1; m<(sharp_maxscale-sharp_minscale+1); ++m) gen->cf[m]=gen->cf[m-1]*sharp_fbig; gen->m = -1; if (spin==0) { gen->rf = RALLOC(sharp_ylmgen_dbl2,gen->lmax+1); gen->mfac = RALLOC(double,gen->mmax+1); gen->mfac[0] = inv_sqrt4pi; for (int m=1; m<=gen->mmax; ++m) gen->mfac[m] = gen->mfac[m-1]*sqrt((2*m+1.)/(2*m)); gen->root = RALLOC(double,2*gen->lmax+5); gen->iroot = RALLOC(double,2*gen->lmax+5); for (int m=0; m<2*gen->lmax+5; ++m) { gen->root[m] = sqrt(m); gen->iroot[m] = (m==0) ? 0. : 1./gen->root[m]; } } else { gen->m=gen->mlo=gen->mhi=-1234567890; ALLOC(gen->fx,sharp_ylmgen_dbl3,gen->lmax+2); for (int m=0; mlmax+2; ++m) gen->fx[m].f[0]=gen->fx[m].f[1]=gen->fx[m].f[2]=0.; ALLOC(gen->inv,double,gen->lmax+1); gen->inv[0]=0; for (int m=1; mlmax+1; ++m) gen->inv[m]=1./m; ALLOC(gen->flm1,double,2*gen->lmax+1); ALLOC(gen->flm2,double,2*gen->lmax+1); for (int m=0; m<2*gen->lmax+1; ++m) { gen->flm1[m] = sqrt(1./(m+1.)); gen->flm2[m] = sqrt(m/(m+1.)); } ALLOC(gen->prefac,double,gen->mmax+1); ALLOC(gen->fscale,int,gen->mmax+1); double *fac = RALLOC(double,2*gen->lmax+1); int *facscale = RALLOC(int,2*gen->lmax+1); fac[0]=1; facscale[0]=0; for (int m=1; m<2*gen->lmax+1; ++m) { fac[m]=fac[m-1]*sqrt(m); facscale[m]=facscale[m-1]; normalize(&fac[m],&facscale[m],sharp_fbighalf); } for (int m=0; m<=gen->mmax; ++m) { int mlo=gen->s, mhi=m; if (mhiprefac[m]=tfac; gen->fscale[m]=tscale; } DEALLOC(fac); DEALLOC(facscale); } } void sharp_Ylmgen_destroy (sharp_Ylmgen_C *gen) { DEALLOC(gen->cf); if (gen->s==0) { DEALLOC(gen->rf); DEALLOC(gen->mfac); DEALLOC(gen->root); DEALLOC(gen->iroot); } else { DEALLOC(gen->fx); DEALLOC(gen->prefac); DEALLOC(gen->fscale); DEALLOC(gen->flm1); DEALLOC(gen->flm2); DEALLOC(gen->inv); } } void sharp_Ylmgen_prepare (sharp_Ylmgen_C *gen, int m) { if (m==gen->m) return; UTIL_ASSERT(m>=0,"incorrect m"); gen->m = m; if (gen->s==0) { gen->rf[m].f[0] = gen->root[2*m+3]; gen->rf[m].f[1] = 0.; for (int l=m+1; l<=gen->lmax; ++l) { double tmp=gen->root[2*l+3]*gen->iroot[l+1+m]*gen->iroot[l+1-m]; gen->rf[l].f[0] = tmp*gen->root[2*l+1]; gen->rf[l].f[1] = tmp*gen->root[l+m]*gen->root[l-m]*gen->iroot[2*l-1]; } } else { int mlo_=m, mhi_=gen->s; if (mhi_mhi==mhi_) && (gen->mlo==mlo_)); gen->mlo = mlo_; gen->mhi = mhi_; if (!ms_similar) { for (int l=gen->mhi; llmax; ++l) { double t = gen->flm1[l+gen->m]*gen->flm1[l-gen->m] *gen->flm1[l+gen->s]*gen->flm1[l-gen->s]; double lt = 2*l+1; double l1 = l+1; gen->fx[l+1].f[0]=l1*lt*t; gen->fx[l+1].f[1]=gen->m*gen->s*gen->inv[l]*gen->inv[l+1]; t = gen->flm2[l+gen->m]*gen->flm2[l-gen->m] *gen->flm2[l+gen->s]*gen->flm2[l-gen->s]; gen->fx[l+1].f[2]=t*l1*gen->inv[l]; } } gen->preMinus_p = gen->preMinus_m = 0; if (gen->mhi==gen->m) { gen->cosPow = gen->mhi+gen->s; gen->sinPow = gen->mhi-gen->s; gen->preMinus_p = gen->preMinus_m = ((gen->mhi-gen->s)&1); } else { gen->cosPow = gen->mhi+gen->m; gen->sinPow = gen->mhi-gen->m; gen->preMinus_m = ((gen->mhi+gen->m)&1); } } } double *sharp_Ylmgen_get_norm (int lmax, int spin) { const double pi = 3.141592653589793238462643383279502884197; double *res=RALLOC(double,lmax+1); /* sign convention for H=1 (LensPix paper) */ #if 1 double spinsign = (spin>0) ? -1.0 : 1.0; #else double spinsign = 1.0; #endif if (spin==0) { for (int l=0; l<=lmax; ++l) res[l]=1.; return res; } spinsign = (spin&1) ? -spinsign : spinsign; for (int l=0; l<=lmax; ++l) res[l] = (l