Main Page | Modules | File List | Globals

bluestein.c

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) 2005 Max-Planck-Society
00029  *  \author Martin Reinecke
00030  */
00031 
00032 #include <math.h>
00033 #include <stdlib.h>
00034 #include "fftpack.h"
00035 #include "bluestein.h"
00036 
00037 /* returns the largest prime factor of n */
00038 int largest_prime_factor (int n)
00039   {
00040   int maxdiv=0,x,limit,tmp;
00041   while (((tmp=(n>>1))<<1)==n)
00042     { maxdiv=2; n=tmp; }
00043 
00044   limit=sqrt(n+0.01);
00045   for (x=3; x<=limit; x+=2)
00046   while ((tmp=(n/x))*x==n)
00047     {
00048     maxdiv=x;
00049     n=tmp;
00050     limit=sqrt(n+0.01);
00051     }
00052   if (n>maxdiv) maxdiv=n;
00053 
00054   return maxdiv;
00055   }
00056 
00057 /* returns the sum of all prime factors of n */
00058 int prime_factor_sum (int n)
00059   {
00060   int result=0,x,limit,tmp;
00061   while (((tmp=(n>>1))<<1)==n)
00062     { result+=2; n=tmp; }
00063 
00064   limit=sqrt(n+0.01);
00065   for (x=3; x<=limit; x+=2)
00066   while ((tmp=(n/x))*x==n)
00067     {
00068     result+=x;
00069     n=tmp;
00070     limit=sqrt(n+0.01);
00071     }
00072   if (n>1) result+=n;
00073 
00074   return result;
00075   }
00076 
00077 /* returns the smallest power of 2 which is >= n */
00078 int nextpow2 (int n)
00079   {
00080   int cnt=1;
00081   while ((n>>cnt)>0)
00082     ++cnt;
00083   return 1<<cnt;
00084   }
00085 
00086 /* returns the smallest composite of 2, 3 and 5 which is >= n */
00087 int good_size(int n)
00088   {
00089   int maxfactors=1, i, j, k, f2=1, f3, f5, bestfac, guessfac;
00090   while ((n>>maxfactors)>0)
00091     ++maxfactors;
00092   bestfac=1<<maxfactors;
00093 
00094   for (i=0; i<maxfactors; ++i)
00095     {
00096     f3=1;
00097     for (j=0; j<maxfactors-i; ++j)
00098       {
00099       if (f2*f3>bestfac) break;
00100       f5=1;
00101       for (k=0; k<maxfactors-i-j; ++k)
00102         {
00103         guessfac = f2*f3*f5;
00104         if (guessfac>=bestfac) break;
00105         if ((guessfac>=n) && (guessfac<bestfac))
00106           bestfac=guessfac;
00107         f5*=5;
00108         }
00109       f3*=3;
00110       }
00111     f2*=2;
00112     }
00113   return bestfac;
00114   }
00115 
00116 void bluestein_i (int n, double **tstorage)
00117   {
00118   static const double pi=3.14159265358979323846;
00119   int n2=good_size(n*2-1);
00120   int m, coeff;
00121   double angle, xn2;
00122   double *bk, *bkf, *work;
00123   double pibyn=pi/n;
00124   *tstorage = (double *)malloc (sizeof(double)*(1+2*n+8*n2+15));
00125   ((int *)(*tstorage))[0]=n2;
00126   bk  = *tstorage+1;
00127   bkf = *tstorage+1+2*n;
00128   work= *tstorage+1+2*(n+n2);
00129 
00130 /* initialize b_k */
00131   bk[0] = 1;
00132   bk[1] = 0;
00133 
00134   coeff=0;
00135   for (m=1; m<n; ++m)
00136     {
00137     coeff+=2*m-1;
00138     if (coeff>=2*n) coeff-=2*n;
00139     angle = pibyn*coeff;
00140     bk[2*m] = cos(angle);
00141     bk[2*m+1] = sin(angle);
00142     }
00143 
00144 /* initialize the zero-padded, Fourier transformed b_k. Add normalisation.  */
00145   xn2 = 1./n2;
00146   bkf[0] = bk[0]*xn2;
00147   bkf[1] = bk[1]*xn2;
00148   for (m=2; m<2*n; m+=2)
00149     {
00150     bkf[m]   = bkf[2*n2-m]   = bk[m]   *xn2;
00151     bkf[m+1] = bkf[2*n2-m+1] = bk[m+1] *xn2;
00152     }
00153   for (m=2*n;m<=(2*n2-2*n+1);++m)
00154     bkf[m]=0.;
00155   cffti (n2,work);
00156   cfftf (n2,bkf,work);
00157   }
00158 
00159 void bluestein (int n, double *data, double *tstorage, int isign)
00160   {
00161   int n2=*((int *)tstorage);
00162   int m;
00163   double *bk, *bkf, *akf, *work;
00164   bk  = tstorage+1;
00165   bkf = tstorage+1+2*n;
00166   work= tstorage+1+2*(n+n2);
00167   akf = tstorage+1+2*n+6*n2+15;  
00168 
00169 /* initialize a_k and FFT it */
00170   if (isign>0)
00171     for (m=0; m<2*n; m+=2)
00172       {
00173       akf[m]   = data[m]*bk[m]   - data[m+1]*bk[m+1];
00174       akf[m+1] = data[m]*bk[m+1] + data[m+1]*bk[m];
00175       }
00176   else
00177     for (m=0; m<2*n; m+=2)
00178       {
00179       akf[m]   = data[m]*bk[m]   + data[m+1]*bk[m+1];
00180       akf[m+1] =-data[m]*bk[m+1] + data[m+1]*bk[m];
00181       }
00182   for (m=2*n; m<2*n2; ++m)
00183     akf[m]=0;
00184 
00185   cfftf (n2,akf,work);
00186 
00187 /* do the convolution */
00188   if (isign>0)
00189     for (m=0; m<2*n2; m+=2)
00190       {
00191       double im = -akf[m]*bkf[m+1] + akf[m+1]*bkf[m];
00192       akf[m  ]  =  akf[m]*bkf[m]   + akf[m+1]*bkf[m+1];
00193       akf[m+1]  = im;
00194       }
00195   else
00196     for (m=0; m<2*n2; m+=2)
00197       {
00198       double im = akf[m]*bkf[m+1] + akf[m+1]*bkf[m];
00199       akf[m  ]  = akf[m]*bkf[m]   - akf[m+1]*bkf[m+1];
00200       akf[m+1]  = im;
00201       }
00202 
00203 
00204 /* inverse FFT */
00205   cfftb (n2,akf,work);
00206 
00207 /* multiply by b_k* */
00208   if (isign>0)
00209     for (m=0; m<2*n; m+=2)
00210       {
00211       data[m]   = bk[m]  *akf[m] - bk[m+1]*akf[m+1];
00212       data[m+1] = bk[m+1]*akf[m] + bk[m]  *akf[m+1];
00213       }
00214   else
00215     for (m=0; m<2*n; m+=2)
00216       {
00217       data[m]   = bk[m]  *akf[m] + bk[m+1]*akf[m+1];
00218       data[m+1] =-bk[m+1]*akf[m] + bk[m]  *akf[m+1];
00219       }
00220   }

Generated on Fri Jul 8 09:37:13 2005 for LevelS FFT library