NASA - Jet Propulsion Laboratory
    + View the NASA Portal
Search JPL
Jet Propulsion Laboratory Home Earth Solar System Stars & Galaxies Technology
Introduction Background Software Links

alm_powspec_tools.cc

00001 /*
00002  *  This file is part of Healpix_cxx.
00003  *
00004  *  Healpix_cxx is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  Healpix_cxx is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with Healpix_cxx; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  *
00018  *  For more information about HEALPix, see http://healpix.jpl.nasa.gov
00019  */
00020 
00021 /*
00022  *  Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik
00023  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00024  *  (DLR).
00025  */
00026 
00027 /*
00028  *  Copyright (C) 2003, 2004, 2005 Max-Planck-Society
00029  *  Author: Martin Reinecke
00030  */
00031 
00032 #include "alm_powspec_tools.h"
00033 #include "alm.h"
00034 #include "planck_rng.h"
00035 #include "powspec.h"
00036 #include "xcomplex.h"
00037 #include "rotmatrix.h"
00038 #include "openmp_support.h"
00039 
00040 using namespace std;
00041 template<typename T> void create_alm
00042   (const PowSpec &powspec, Alm<xcomplex<T> > &alm, planck_rng &rng)
00043   {
00044   int lmax = alm.Lmax();
00045   int mmax = alm.Mmax();
00046   const double hsqrt2 = 1/sqrt(2.);
00047 
00048   for (int l=0; l<=lmax; ++l)
00049     {
00050     double rms_tt = sqrt(powspec.tt(l));
00051     double zeta1_r = rng.rand_gauss();
00052     alm(l,0) = zeta1_r * rms_tt;
00053     for (int m=1; m<=min(l,mmax); ++m)
00054       {
00055       zeta1_r = rng.rand_gauss()*hsqrt2;
00056       double zeta1_i = rng.rand_gauss()*hsqrt2;
00057       alm(l,m).Set (zeta1_r*rms_tt, zeta1_i*rms_tt);
00058       }
00059     }
00060   }
00061 
00062 template void create_alm (const PowSpec &powspec,
00063   Alm<xcomplex<float> > &alm, planck_rng &rng);
00064 template void create_alm (const PowSpec &powspec,
00065   Alm<xcomplex<double> > &alm, planck_rng &rng);
00066 
00067 
00068 template<typename T> void create_alm_pol
00069   (const PowSpec &powspec,
00070    Alm<xcomplex<T> > &almT,
00071    Alm<xcomplex<T> > &almG,
00072    Alm<xcomplex<T> > &almC,
00073    planck_rng &rng)
00074   {
00075   int lmax = almT.Lmax();
00076   int mmax = almT.Mmax();
00077   const double hsqrt2 = 1/sqrt(2.);
00078 
00079   for (int l=0; l<=lmax; ++l)
00080     {
00081     double rms_tt=0, rms_g1=0;
00082     if (powspec.tt(l) != 0)
00083       {
00084       rms_tt = sqrt(powspec.tt(l));
00085       rms_g1 = powspec.tg(l)/rms_tt;
00086       }
00087 
00088     double zeta1_r = rng.rand_gauss();
00089     almT(l,0) = zeta1_r * rms_tt;
00090     almG(l,0) = zeta1_r * rms_g1;
00091     for (int m=1; m<=min(l,mmax); ++m)
00092       {
00093       zeta1_r = rng.rand_gauss()*hsqrt2;
00094       double zeta1_i = rng.rand_gauss()*hsqrt2;
00095       almT(l,m).Set (zeta1_r*rms_tt, zeta1_i*rms_tt);
00096       almG(l,m).Set (zeta1_r*rms_g1, zeta1_i*rms_g1);
00097       }
00098     }
00099 
00100   for (int l=0; l<=lmax; ++l)
00101     {
00102     double rms_g2 = 0;
00103     double rms_cc = 0;
00104     if (powspec.tt(l) != 0)
00105       {
00106       rms_g2 = powspec.gg(l) - (powspec.tg(l)/powspec.tt(l))*powspec.tg(l);
00107       if (rms_g2 <= 0)
00108         {
00109         planck_assert (abs(rms_g2) <= 1e-8*abs(powspec.gg(l)),
00110           "Inconsistent TT, GG and TG spectra at l="+dataToString(l));
00111         rms_g2 = 0;
00112         }
00113       rms_g2 = sqrt(rms_g2);
00114       rms_cc = sqrt(powspec.cc(l));
00115       }
00116     almG(l,0) += rng.rand_gauss()*rms_g2;
00117     almC(l,0)  = rng.rand_gauss()*rms_cc;
00118 
00119     for (int m=1; m<=min(l,mmax); ++m)
00120       {
00121       double zeta2_r = rng.rand_gauss()*hsqrt2;
00122       double zeta2_i = rng.rand_gauss()*hsqrt2;
00123       double zeta3_r = rng.rand_gauss()*hsqrt2;
00124       double zeta3_i = rng.rand_gauss()*hsqrt2;
00125 
00126       almG(l,m) += xcomplex<T> (zeta2_r*rms_g2,zeta2_i*rms_g2);
00127       almC(l,m).Set (zeta3_r*rms_cc,zeta3_i*rms_cc);
00128       }
00129     }
00130   }
00131 
00132 template void create_alm_pol
00133   (const PowSpec &powspec,
00134    Alm<xcomplex<float> > &almT,
00135    Alm<xcomplex<float> > &almG,
00136    Alm<xcomplex<float> > &almC,
00137    planck_rng &rng);
00138 template void create_alm_pol
00139   (const PowSpec &powspec,
00140    Alm<xcomplex<double> > &almT,
00141    Alm<xcomplex<double> > &almG,
00142    Alm<xcomplex<double> > &almC,
00143    planck_rng &rng);
00144 
00145 
00146 template<typename T> void extract_powspec
00147   (const Alm<xcomplex<T> > &alm, PowSpec &powspec)
00148   {
00149   arr<double> tt(alm.Lmax()+1);
00150   for (int l=0; l<=alm.Lmax(); ++l)
00151     {
00152     tt[l] = norm(alm(l,0));
00153     int limit = min(l,alm.Mmax());
00154     for (int m=1; m<=limit; ++m)
00155       tt[l] += 2*norm(alm(l,m));
00156     tt[l] /= (2*l+1);
00157     }
00158   powspec.Set(tt);
00159   }
00160 
00161 template void extract_powspec
00162   (const Alm<xcomplex<float> > &alm, PowSpec &powspec);
00163 template void extract_powspec
00164   (const Alm<xcomplex<double> > &alm, PowSpec &powspec);
00165 
00166 
00167 template<typename T> void extract_crosspowspec
00168   (const Alm<xcomplex<T> > &alm1,
00169    const Alm<xcomplex<T> > &alm2,PowSpec &powspec)
00170   {
00171   planck_assert (alm1.conformable(alm2),
00172     "extract_crosspowspec: a_lms are not conformable");
00173   arr<double> tt(alm1.Lmax()+1);
00174   for (int l=0; l<=alm1.Lmax(); ++l)
00175     {
00176     tt[l] = alm1(l,0).re*alm2(l,0).re;
00177     int limit = min(l,alm1.Mmax());
00178     for (int m=1; m<=limit; ++m)
00179       tt[l] += 2 * (alm1(l,m).re*alm2(l,m).re + alm1(l,m).im*alm2(l,m).im);
00180     tt[l] /= (2*l+1);
00181     }
00182   powspec.Set(tt);
00183   }
00184 
00185 template void extract_crosspowspec
00186   (const Alm<xcomplex<float> > &alm1,
00187    const Alm<xcomplex<float> > &alm2, PowSpec &powspec);
00188 template void extract_crosspowspec
00189   (const Alm<xcomplex<double> > &alm1,
00190    const Alm<xcomplex<double> > &alm2, PowSpec &powspec);
00191 
00192 
00193 template<typename T> void extract_powspec
00194   (const Alm<xcomplex<T> > &almT,
00195    const Alm<xcomplex<T> > &almG,
00196    const Alm<xcomplex<T> > &almC,
00197    PowSpec &powspec)
00198   {
00199   planck_assert (almT.conformable(almG) && almT.conformable(almC),
00200     "extract_powspec: a_lms are not conformable");
00201   int lmax = almT.Lmax();
00202   arr<double> tt(lmax+1), gg(lmax+1), cc(lmax+1), tg(lmax+1);
00203   for (int l=0; l<=lmax; ++l)
00204     {
00205     tt[l] = norm(almT(l,0));
00206     gg[l] = norm(almG(l,0));
00207     cc[l] = norm(almC(l,0));
00208     tg[l] = (almT(l,0)*conj(almG(l,0))).re;
00209     int limit = min(l,almT.Mmax());
00210     for (int m=1; m<=limit; ++m)
00211       {
00212       tt[l] += 2*norm(almT(l,m));
00213       gg[l] += 2*norm(almG(l,m));
00214       cc[l] += 2*norm(almC(l,m));
00215       tg[l] += 2*(almT(l,m)*conj(almG(l,m))).re;
00216       }
00217     tt[l] /= (2*l+1);
00218     gg[l] /= (2*l+1);
00219     cc[l] /= (2*l+1);
00220     tg[l] /= (2*l+1);
00221     }
00222   powspec.Set(tt,gg,cc,tg);
00223   }
00224 
00225 template void extract_powspec
00226   (const Alm<xcomplex<float> > &almT,
00227    const Alm<xcomplex<float> > &almG,
00228    const Alm<xcomplex<float> > &almC,
00229    PowSpec &powspec);
00230 template void extract_powspec
00231   (const Alm<xcomplex<double> > &almT,
00232    const Alm<xcomplex<double> > &almG,
00233    const Alm<xcomplex<double> > &almC,
00234    PowSpec &powspec);
00235 
00236 
00237 template<typename T> void smooth_with_Gauss
00238   (Alm<xcomplex<T> > &alm, double fwhm_arcmin)
00239   {
00240   int fct = (fwhm_arcmin>=0) ? 1 : -1;
00241   double sigma = fwhm_arcmin/60*degr2rad*fwhm2sigma;
00242   arr<double> gb(alm.Lmax()+1);
00243   for (int l=0; l<=alm.Lmax(); ++l)
00244     gb[l] = exp(-.5*fct*l*(l+1)*sigma*sigma);
00245   alm.ScaleL(gb);
00246   }
00247 
00248 template void smooth_with_Gauss
00249   (Alm<xcomplex<float> > &alm, double fwhm_arcmin);
00250 template void smooth_with_Gauss
00251   (Alm<xcomplex<double> > &alm, double fwhm_arcmin);
00252 
00253 
00254 template<typename T> void smooth_with_Gauss
00255   (Alm<xcomplex<T> > &almT,
00256    Alm<xcomplex<T> > &almG,
00257    Alm<xcomplex<T> > &almC,
00258    double fwhm_arcmin)
00259   {
00260   int fct = (fwhm_arcmin>=0) ? 1 : -1;
00261   double sigma = fwhm_arcmin/60*degr2rad*fwhm2sigma;
00262   double fact_pol = exp(2*fct*sigma*sigma);
00263   arr<double> gb(almT.Lmax()+1);
00264   for (int l=0; l<=almT.Lmax(); ++l)
00265     gb[l] = exp(-.5*fct*l*(l+1)*sigma*sigma);
00266   almT.ScaleL(gb);
00267   for (int l=0; l<=almT.Lmax(); ++l)
00268     gb[l] *= fact_pol;
00269   almG.ScaleL(gb); almC.ScaleL(gb);
00270   }
00271 
00272 template void smooth_with_Gauss
00273   (Alm<xcomplex<float> > &almT,
00274    Alm<xcomplex<float> > &almG,
00275    Alm<xcomplex<float> > &almC,
00276    double fwhm_arcmin);
00277 template void smooth_with_Gauss
00278   (Alm<xcomplex<double> > &almT,
00279    Alm<xcomplex<double> > &almG,
00280    Alm<xcomplex<double> > &almC,
00281    double fwhm_arcmin);
00282 
00283 namespace {
00284 
00285 #if 0
00286 
00287 class wigner_d
00288   {
00289   private:
00290     double p,q;
00291     arr<double> sqt;
00292     arr2<double> d;
00293     int n;
00294 
00295     void do_line0 (double *l1, int j)
00296       {
00297       double xj = 1./j;
00298       l1[j] = -p*l1[j-1];
00299       for (int i=j-1; i>=1; --i)
00300         l1[i] = xj*sqt[j]*(q*sqt[j-i]*l1[i] - p*sqt[i]*l1[i-1]);
00301       l1[0] = q*l1[0];
00302       }
00303     void do_line (const double *l1, double *l2, int j, int k)
00304       {
00305       double xj = 1./j;
00306       double t1 = xj*sqt[j-k]*q, t2 = xj*sqt[j-k]*p;
00307       double t3 = xj*sqt[k]*p,   t4 = xj*sqt[k]*q;
00308       l2[j] = sqt[j] * (t4*l1[j-1]-t2*l2[j-1]);
00309       for (int i=j-1; i>=1; --i)
00310         l2[i] = t1*sqt[j-i]*l2[i] - t2*sqt[i]*l2[i-1]
00311                +t3*sqt[j-i]*l1[i] + t4*sqt[i]*l1[i-1];
00312       l2[0] = sqt[j] * (t3*l1[0]+t1*l2[0]);
00313       }
00314 
00315   public:
00316     wigner_d(int lmax, double ang)
00317       : p(sin(ang/2)), q(cos(ang/2)), sqt(2*lmax+1), d(lmax+1,2*lmax+1), n(-1)
00318       { for (int m=0; m<sqt.size(); ++m) sqt[m] = sqrt(double(m)); }
00319 
00320     const arr2<double> &recurse ()
00321       {
00322       ++n;
00323       if (n==0)
00324         d[0][0] = 1;
00325       else if (n==1)
00326         {
00327         d[0][0] = q*q; d[0][1] = -p*q*sqt[2]; d[0][2] = p*p;
00328         d[1][0] = -d[0][1]; d[1][1] = q*q-p*p; d[1][2] = d[0][1];
00329         }
00330       else
00331         {
00332         // padding
00333         int sign = (n&1)? -1 : 1;
00334         for (int i=0; i<=2*n-2; ++i)
00335           {
00336           d[n][i] = sign*d[n-2][2*n-2-i];
00337           sign=-sign;
00338           }
00339         do_line (d[n-1],d[n],2*n-1,n);
00340         for (int k=n; k>=2; --k)
00341           {
00342           do_line (d[k-2],d[k-1],2*n-1,k-1);
00343           do_line (d[k-1],d[k],2*n,k);
00344           }
00345         do_line0 (d[0],2*n-1);
00346         do_line (d[0],d[1],2*n,1);
00347         do_line0 (d[0],2*n);
00348         }
00349       return d;
00350       }
00351   };
00352 
00353 #else
00354 
00355 class wigner_d
00356   {
00357   private:
00358     double p,q;
00359     arr<double> sqt;
00360     arr2<double> d, dd;
00361     int n;
00362 
00363   public:
00364     wigner_d(int lmax, double ang)
00365       : p(sin(ang/2)), q(cos(ang/2)), sqt(2*lmax+1), d(lmax+1,2*lmax+1),
00366         dd(lmax+1,2*lmax+1), n(-1)
00367       { for (int m=0; m<sqt.size(); ++m) sqt[m] = sqrt(double(m)); }
00368 
00369     const arr2<double> &recurse ()
00370       {
00371       ++n;
00372       if (n==0)
00373         d[0][0] = 1;
00374       else if (n==1)
00375         {
00376         d[0][0] = q*q; d[0][1] = -p*q*sqt[2]; d[0][2] = p*p;
00377         d[1][0] = -d[0][1]; d[1][1] = q*q-p*p; d[1][2] = d[0][1];
00378         }
00379       else
00380         {
00381         // padding
00382         int sign = (n&1)? -1 : 1;
00383         for (int i=0; i<=2*n-2; ++i)
00384           {
00385           d[n][i] = sign*d[n-2][2*n-2-i];
00386           sign=-sign;
00387           }
00388         for (int j=2*n-1; j<=2*n; ++j)
00389           {
00390           double xj = 1./j;
00391           dd[0][0] = q*d[0][0];
00392           for (int i=1;i<j; ++i)
00393             dd[0][i] = xj*sqt[j]*(q*sqt[j-i]*d[0][i] - p*sqt[i]*d[0][i-1]);
00394           dd[0][j] = -p*d[0][j-1];
00395 #pragma omp parallel
00396 {
00397           int k;
00398 #pragma omp for schedule(static)
00399           for (k=1; k<=n; ++k)
00400             {
00401             double t1 = xj*sqt[j-k]*q, t2 = xj*sqt[j-k]*p;
00402             double t3 = xj*sqt[k  ]*p, t4 = xj*sqt[k  ]*q;
00403             dd[k][0] = xj*sqt[j]*(q*sqt[j-k]*d[k][0] + p*sqt[k]*d[k-1][0]);
00404             for (int i=1; i<j; ++i)
00405               dd[k][i] = t1*sqt[j-i]*d[k  ][i] - t2*sqt[i]*d[k  ][i-1]
00406                        + t3*sqt[j-i]*d[k-1][i] + t4*sqt[i]*d[k-1][i-1];
00407             dd[k][j] = -t2*sqt[j]*d[k][j-1] + t4*sqt[j]*d[k-1][j-1];
00408             }
00409 }
00410           dd.swap(d);
00411           }
00412         }
00413       return d;
00414       }
00415   };
00416 
00417 #endif
00418 
00419 } // namespace
00420 
00421 template<typename T> void rotate_alm (Alm<xcomplex<T> > &alm,
00422   double psi, double theta, double phi)
00423   {
00424   planck_assert (alm.Lmax()==alm.Mmax(),
00425     "rotate_alm: lmax must be equal to mmax");
00426   int lmax=alm.Lmax();
00427   arr<xcomplex<double> > exppsi(lmax+1), expphi(lmax+1);
00428   for (int m=0; m<=lmax; ++m)
00429     {
00430     exppsi[m].Set (cos(psi*m),-sin(psi*m));
00431     expphi[m].Set (cos(phi*m),-sin(phi*m));
00432     }
00433 
00434   wigner_d rec(lmax,theta);
00435 
00436   arr<xcomplex<double> > almtmp(lmax+1);
00437 
00438   for (int l=0; l<=lmax; ++l)
00439     {
00440     announce_progress (pow(double(l),3),pow(l-1.,3),pow(double(lmax),3));
00441     const arr2<double> &d(rec.recurse());
00442 
00443     for (int m=0; m<=l; ++m)
00444       almtmp[m] = alm(l,0)*d[l][l+m];
00445 
00446 #pragma omp parallel
00447 {
00448     int lo,hi;
00449     openmp_calc_share(0,l+1,lo,hi);
00450 
00451     bool flip = true;
00452     for (int mm=1; mm<=l; ++mm)
00453       {
00454       xcomplex<double> t1 = alm(l,mm)*exppsi[mm];
00455       bool flip2 = ((mm+lo)&1) ? true : false;
00456       for (int m=lo; m<hi; ++m)
00457         {
00458         double d1 = flip2 ? -d[l-mm][l-m] : d[l-mm][l-m];
00459         double d2 = flip  ? -d[l-mm][l+m] : d[l-mm][l+m];
00460         double f1 = d1+d2, f2 = d1-d2;
00461         almtmp[m].re += t1.re*f1; almtmp[m].im += t1.im*f2;
00462         flip2 = !flip2;
00463         }
00464       flip = !flip;
00465       }
00466 }
00467 
00468     for (int m=0; m<=l; ++m)
00469       alm(l,m) = almtmp[m]*expphi[m];
00470     }
00471   end_announce_progress();
00472   }
00473 
00474 template void rotate_alm (Alm<xcomplex<float> > &alm,
00475   double psi, double theta, double phi);
00476 template void rotate_alm (Alm<xcomplex<double> > &alm,
00477   double psi, double theta, double phi);
00478 
00479 template<typename T> void rotate_alm (Alm<xcomplex<T> > &almT,
00480   Alm<xcomplex<T> > &almG, Alm<xcomplex<T> > &almC,
00481   double psi, double theta, double phi)
00482   {
00483   planck_assert (almT.Lmax()==almT.Mmax(),
00484     "rotate_alm: lmax must be equal to mmax");
00485   planck_assert (almG.conformable(almT) && almC.conformable(almT),
00486     "rotate_alm: a_lm are not conformable");
00487   int lmax=almT.Lmax();
00488   arr<xcomplex<double> > exppsi(lmax+1), expphi(lmax+1);
00489   for (int m=0; m<=lmax; ++m)
00490     {
00491     exppsi[m].Set (cos(psi*m),-sin(psi*m));
00492     expphi[m].Set (cos(phi*m),-sin(phi*m));
00493     }
00494 
00495   wigner_d rec(lmax,theta);
00496 
00497   arr<xcomplex<double> > almtmpT(lmax+1), almtmpG(lmax+1), almtmpC(lmax+1);
00498 
00499   for (int l=0; l<=lmax; ++l)
00500     {
00501     announce_progress (pow(double(l),3),pow(l-1.,3),pow(double(lmax),3));
00502     const arr2<double> &d(rec.recurse());
00503 
00504     for (int m=0; m<=l; ++m)
00505       {
00506       almtmpT[m] = almT(l,0)*d[l][m+l];
00507       almtmpG[m] = almG(l,0)*d[l][m+l];
00508       almtmpC[m] = almC(l,0)*d[l][m+l];
00509       }
00510 
00511 #pragma omp parallel
00512 {
00513     int lo,hi;
00514     openmp_calc_share(0,l+1,lo,hi);
00515 
00516     bool flip = true;
00517     for (int mm=1; mm<=l; ++mm)
00518       {
00519       xcomplex<double> t1T = almT(l,mm)*exppsi[mm];
00520       xcomplex<double> t1G = almG(l,mm)*exppsi[mm];
00521       xcomplex<double> t1C = almC(l,mm)*exppsi[mm];
00522       bool flip2 = ((mm+lo)&1) ? true : false;
00523       for (int m=lo; m<hi; ++m)
00524         {
00525         double d1 = flip2 ? -d[l-mm][l-m] : d[l-mm][l-m];
00526         double d2 = flip  ? -d[l-mm][l+m] : d[l-mm][l+m];
00527         double f1 = d1+d2, f2 = d1-d2;
00528         almtmpT[m].re += t1T.re*f1; almtmpT[m].im += t1T.im*f2;
00529         almtmpG[m].re += t1G.re*f1; almtmpG[m].im += t1G.im*f2;
00530         almtmpC[m].re += t1C.re*f1; almtmpC[m].im += t1C.im*f2;
00531         flip2 = !flip2;
00532         }
00533       flip = !flip;
00534       }
00535 }
00536 
00537     for (int m=0; m<=l; ++m)
00538       {
00539       almT(l,m) = almtmpT[m]*expphi[m];
00540       almG(l,m) = almtmpG[m]*expphi[m];
00541       almC(l,m) = almtmpC[m]*expphi[m];
00542       }
00543     }
00544   end_announce_progress();
00545   }
00546 
00547 template void rotate_alm (Alm<xcomplex<float> > &almT,
00548   Alm<xcomplex<float> > &almG, Alm<xcomplex<float> > &almC,
00549   double psi, double theta, double phi);
00550 template void rotate_alm (Alm<xcomplex<double> > &almT,
00551   Alm<xcomplex<double> > &almG, Alm<xcomplex<double> > &almC,
00552   double psi, double theta, double phi);
00553 
00554 
00555 template<typename T> void rotate_alm (Alm<xcomplex<T> > &alm,
00556   const rotmatrix &mat)
00557   {
00558   double a1, a2, a3;
00559   mat.Extract_CPAC_Euler_Angles (a1, a2, a3);
00560   rotate_alm (alm, a3, a2, a1);
00561   }
00562 
00563 template void rotate_alm (Alm<xcomplex<float> > &alm, const rotmatrix &mat);
00564 template void rotate_alm (Alm<xcomplex<double> > &alm, const rotmatrix &mat);
00565 
00566 template<typename T> void rotate_alm (Alm<xcomplex<T> > &almT,
00567   Alm<xcomplex<T> > &almG, Alm<xcomplex<T> > &almC,
00568   const rotmatrix &mat)
00569   {
00570   double a1, a2, a3;
00571   mat.Extract_CPAC_Euler_Angles (a1, a2, a3);
00572   rotate_alm (almT, almG, almC, a3, a2, a1);
00573   }
00574 
00575 template void rotate_alm (Alm<xcomplex<float> > &almT,
00576   Alm<xcomplex<float> > &almG, Alm<xcomplex<float> > &almC,
00577   const rotmatrix &mat);
00578 template void rotate_alm (Alm<xcomplex<double> > &almT,
00579   Alm<xcomplex<double> > &almG, Alm<xcomplex<double> > &almC,
00580   const rotmatrix &mat);

Generated on Fri Jun 18 16:12:30 2010 for Healpix C++
Privacy / Copyright
FIRST GOV Contact: NASA Home Page Site Manager:
Webmaster:

CL 03-2650