bluestein.c

00001 /*
00002  *  This file is part of libfftpack.
00003  *
00004  *  libfftpack 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  *  libfftpack 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 libfftpack; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  */
00018 
00019 /*
00020  *  libfftpack is being developed at the Max-Planck-Institut fuer Astrophysik
00021  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00022  *  (DLR).
00023  */
00024 
00025 /*
00026  *  Copyright (C) 2005-2008 Max-Planck-Society
00027  *  \author Martin Reinecke
00028  */
00029 
00030 #include <math.h>
00031 #include <stdlib.h>
00032 #include "fftpack.h"
00033 #include "bluestein.h"
00034 
00035 /* returns the sum of all prime factors of n */
00036 size_t prime_factor_sum (size_t n)
00037   {
00038   size_t result=0,x,limit,tmp;
00039   while (((tmp=(n>>1))<<1)==n)
00040     { result+=2; n=tmp; }
00041 
00042   limit=(size_t)sqrt(n+0.01);
00043   for (x=3; x<=limit; x+=2)
00044   while ((tmp=(n/x))*x==n)
00045     {
00046     result+=x;
00047     n=tmp;
00048     limit=(size_t)sqrt(n+0.01);
00049     }
00050   if (n>1) result+=n;
00051 
00052   return result;
00053   }
00054 
00055 /* returns the smallest composite of 2, 3 and 5 which is >= n */
00056 static size_t good_size(size_t n)
00057   {
00058   size_t f2, f23, f235, bestfac=2*n;
00059   if (n<=6) return n;
00060 
00061   for (f2=1; f2<bestfac; f2*=2)
00062     for (f23=f2; f23<bestfac; f23*=3)
00063       for (f235=f23; f235<bestfac; f235*=5)
00064         if (f235>=n) bestfac=f235;
00065   return bestfac;
00066   }
00067 
00068 void bluestein_i (size_t n, double **tstorage, size_t *worksize)
00069   {
00070   static const double pi=3.14159265358979323846;
00071   size_t n2=good_size(n*2-1);
00072   size_t m, coeff;
00073   double angle, xn2;
00074   double *bk, *bkf, *work;
00075   double pibyn=pi/n;
00076   *worksize=2+2*n+8*n2+16;
00077   *tstorage = RALLOC(double,2+2*n+8*n2+16);
00078   ((size_t *)(*tstorage))[0]=n2;
00079   bk  = *tstorage+2;
00080   bkf = *tstorage+2+2*n;
00081   work= *tstorage+2+2*(n+n2);
00082 
00083 /* initialize b_k */
00084   bk[0] = 1;
00085   bk[1] = 0;
00086 
00087   coeff=0;
00088   for (m=1; m<n; ++m)
00089     {
00090     coeff+=2*m-1;
00091     if (coeff>=2*n) coeff-=2*n;
00092     angle = pibyn*coeff;
00093     bk[2*m] = cos(angle);
00094     bk[2*m+1] = sin(angle);
00095     }
00096 
00097 /* initialize the zero-padded, Fourier transformed b_k. Add normalisation. */
00098   xn2 = 1./n2;
00099   bkf[0] = bk[0]*xn2;
00100   bkf[1] = bk[1]*xn2;
00101   for (m=2; m<2*n; m+=2)
00102     {
00103     bkf[m]   = bkf[2*n2-m]   = bk[m]   *xn2;
00104     bkf[m+1] = bkf[2*n2-m+1] = bk[m+1] *xn2;
00105     }
00106   for (m=2*n;m<=(2*n2-2*n+1);++m)
00107     bkf[m]=0.;
00108   cffti (n2,work);
00109   cfftf (n2,bkf,work);
00110   }
00111 
00112 void bluestein (size_t n, double *data, double *tstorage, int isign)
00113   {
00114   size_t n2=*((size_t *)tstorage);
00115   size_t m;
00116   double *bk, *bkf, *akf, *work;
00117   bk  = tstorage+2;
00118   bkf = tstorage+2+2*n;
00119   work= tstorage+2+2*(n+n2);
00120   akf = tstorage+2+2*n+6*n2+16;
00121 
00122 /* initialize a_k and FFT it */
00123   if (isign>0)
00124     for (m=0; m<2*n; m+=2)
00125       {
00126       akf[m]   = data[m]*bk[m]   - data[m+1]*bk[m+1];
00127       akf[m+1] = data[m]*bk[m+1] + data[m+1]*bk[m];
00128       }
00129   else
00130     for (m=0; m<2*n; m+=2)
00131       {
00132       akf[m]   = data[m]*bk[m]   + data[m+1]*bk[m+1];
00133       akf[m+1] =-data[m]*bk[m+1] + data[m+1]*bk[m];
00134       }
00135   for (m=2*n; m<2*n2; ++m)
00136     akf[m]=0;
00137 
00138   cfftf (n2,akf,work);
00139 
00140 /* do the convolution */
00141   if (isign>0)
00142     for (m=0; m<2*n2; m+=2)
00143       {
00144       double im = -akf[m]*bkf[m+1] + akf[m+1]*bkf[m];
00145       akf[m  ]  =  akf[m]*bkf[m]   + akf[m+1]*bkf[m+1];
00146       akf[m+1]  = im;
00147       }
00148   else
00149     for (m=0; m<2*n2; m+=2)
00150       {
00151       double im = akf[m]*bkf[m+1] + akf[m+1]*bkf[m];
00152       akf[m  ]  = akf[m]*bkf[m]   - akf[m+1]*bkf[m+1];
00153       akf[m+1]  = im;
00154       }
00155 
00156 
00157 /* inverse FFT */
00158   cfftb (n2,akf,work);
00159 
00160 /* multiply by b_k* */
00161   if (isign>0)
00162     for (m=0; m<2*n; m+=2)
00163       {
00164       data[m]   = bk[m]  *akf[m] - bk[m+1]*akf[m+1];
00165       data[m+1] = bk[m+1]*akf[m] + bk[m]  *akf[m+1];
00166       }
00167   else
00168     for (m=0; m<2*n; m+=2)
00169       {
00170       data[m]   = bk[m]  *akf[m] + bk[m+1]*akf[m+1];
00171       data[m+1] =-bk[m+1]*akf[m] + bk[m]  *akf[m+1];
00172       }
00173   }

Generated on Thu Oct 8 14:48:49 2015 for LevelS FFT library