ls_fft.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 Max-Planck-Society
00027  *  \author Martin Reinecke
00028  */
00029 
00030 #include <stdlib.h>
00031 #include <math.h>
00032 #include <string.h>
00033 #include "bluestein.h"
00034 #include "fftpack.h"
00035 #include "ls_fft.h"
00036 
00037 complex_plan make_complex_plan (size_t length)
00038   {
00039   complex_plan plan = RALLOC(complex_plan_i,1);
00040   size_t pfsum = prime_factor_sum(length);
00041   double comp1 = (double)(length*pfsum);
00042   double comp2 = 2*3*length*log(3.*length);
00043   comp2*=3.; /* fudge factor that appears to give good overall performance */
00044   plan->length=length;
00045   plan->bluestein = (comp2<comp1);
00046   if (plan->bluestein)
00047     bluestein_i (length,&(plan->work),&(plan->worksize));
00048   else
00049     {
00050     plan->worksize=4*length+15;
00051     plan->work=RALLOC(double,4*length+15);
00052     cffti(length, plan->work);
00053     }
00054   return plan;
00055   }
00056 
00057 complex_plan copy_complex_plan (complex_plan plan)
00058   {
00059   if (!plan) return NULL;
00060   {
00061   complex_plan newplan = RALLOC(complex_plan_i,1);
00062   *newplan = *plan;
00063   newplan->work=RALLOC(double,newplan->worksize);
00064   memcpy(newplan->work,plan->work,sizeof(double)*newplan->worksize);
00065   return newplan;
00066   }
00067   }
00068 
00069 void kill_complex_plan (complex_plan plan)
00070   {
00071   DEALLOC(plan->work);
00072   DEALLOC(plan);
00073   }
00074 
00075 void complex_plan_forward (complex_plan plan, double *data)
00076   {
00077   if (plan->bluestein)
00078     bluestein (plan->length, data, plan->work, -1);
00079   else
00080     cfftf (plan->length, data, plan->work);
00081   }
00082 
00083 void complex_plan_backward (complex_plan plan, double *data)
00084   {
00085   if (plan->bluestein)
00086     bluestein (plan->length, data, plan->work, 1);
00087   else
00088     cfftb (plan->length, data, plan->work);
00089   }
00090 
00091 
00092 real_plan make_real_plan (size_t length)
00093   {
00094   real_plan plan = RALLOC(real_plan_i,1);
00095   size_t pfsum = prime_factor_sum(length);
00096   double comp1 = .5*length*pfsum;
00097   double comp2 = 2*3*length*log(3.*length);
00098   comp2*=3; /* fudge factor that appears to give good overall performance */
00099   plan->length=length;
00100   plan->bluestein = (comp2<comp1);
00101   if (plan->bluestein)
00102     bluestein_i (length,&(plan->work),&(plan->worksize));
00103   else
00104     {
00105     plan->worksize=2*length+15;
00106     plan->work=RALLOC(double,2*length+15);
00107     rffti(length, plan->work);
00108     }
00109   return plan;
00110   }
00111 
00112 real_plan copy_real_plan (real_plan plan)
00113   {
00114   if (!plan) return NULL;
00115   {
00116   real_plan newplan = RALLOC(real_plan_i,1);
00117   *newplan = *plan;
00118   newplan->work=RALLOC(double,newplan->worksize);
00119   memcpy(newplan->work,plan->work,sizeof(double)*newplan->worksize);
00120   return newplan;
00121   }
00122   }
00123 
00124 void kill_real_plan (real_plan plan)
00125   {
00126   DEALLOC(plan->work);
00127   DEALLOC(plan);
00128   }
00129 
00130 void real_plan_forward_fftpack (real_plan plan, double *data)
00131   {
00132   if (plan->bluestein)
00133     {
00134     size_t m;
00135     size_t n=plan->length;
00136     double *tmp = RALLOC(double,2*n);
00137     for (m=0; m<n; ++m)
00138       {
00139       tmp[2*m] = data[m];
00140       tmp[2*m+1] = 0.;
00141       }
00142     bluestein(n,tmp,plan->work,-1);
00143     data[0] = tmp[0];
00144     memcpy (data+1, tmp+2, (n-1)*sizeof(double));
00145     DEALLOC(tmp);
00146     }
00147   else
00148     rfftf (plan->length, data, plan->work);
00149   }
00150 
00151 static void fftpack2halfcomplex (double *data, size_t n)
00152   {
00153   size_t m;
00154   double *tmp = RALLOC(double,n);
00155   tmp[0]=data[0];
00156   for (m=1; m<(n+1)/2; ++m)
00157     {
00158     tmp[m]=data[2*m-1];
00159     tmp[n-m]=data[2*m];
00160     }
00161   if (!(n&1))
00162     tmp[n/2]=data[n-1];
00163   memcpy (data,tmp,n*sizeof(double));
00164   DEALLOC(tmp);
00165   }
00166 
00167 static void halfcomplex2fftpack (double *data, size_t n)
00168   {
00169   size_t m;
00170   double *tmp = RALLOC(double,n);
00171   tmp[0]=data[0];
00172   for (m=1; m<(n+1)/2; ++m)
00173     {
00174     tmp[2*m-1]=data[m];
00175     tmp[2*m]=data[n-m];
00176     }
00177   if (!(n&1))
00178     tmp[n-1]=data[n/2];
00179   memcpy (data,tmp,n*sizeof(double));
00180   DEALLOC(tmp);
00181   }
00182 
00183 void real_plan_forward_fftw (real_plan plan, double *data)
00184   {
00185   real_plan_forward_fftpack (plan, data);
00186   fftpack2halfcomplex (data,plan->length);
00187   }
00188 
00189 void real_plan_backward_fftpack (real_plan plan, double *data)
00190   {
00191   if (plan->bluestein)
00192     {
00193     size_t m;
00194     size_t n=plan->length;
00195     double *tmp = RALLOC(double,2*n);
00196     tmp[0]=data[0];
00197     tmp[1]=0.;
00198     memcpy (tmp+2,data+1, (n-1)*sizeof(double));
00199     if ((n&1)==0) tmp[n+1]=0.;
00200     for (m=2; m<n; m+=2)
00201       {
00202       tmp[2*n-m]=tmp[m];
00203       tmp[2*n-m+1]=-tmp[m+1];
00204       }
00205     bluestein (n, tmp, plan->work, 1);
00206     for (m=0; m<n; ++m)
00207       data[m] = tmp[2*m];
00208     DEALLOC(tmp);
00209     }
00210   else
00211     rfftb (plan->length, data, plan->work);
00212   }
00213 
00214 void real_plan_backward_fftw (real_plan plan, double *data)
00215   {
00216   halfcomplex2fftpack (data,plan->length);
00217   real_plan_backward_fftpack (plan, data);
00218   }
00219 
00220 void real_plan_forward_c (real_plan plan, double *data)
00221   {
00222   size_t m;
00223   size_t n=plan->length;
00224 
00225   if (plan->bluestein)
00226     {
00227     for (m=1; m<2*n; m+=2)
00228       data[m]=0;
00229     bluestein (plan->length, data, plan->work, -1);
00230     data[1]=0;
00231     for (m=2; m<n; m+=2)
00232       {
00233       double avg;
00234       avg = 0.5*(data[2*n-m]+data[m]);
00235       data[2*n-m] = data[m] = avg;
00236       avg = 0.5*(data[2*n-m+1]-data[m+1]);
00237       data[2*n-m+1] = avg;
00238       data[m+1] = -avg;
00239       }
00240     if ((n&1)==0) data[n+1] = 0.;
00241     }
00242   else
00243     {
00244 /* using "m+m" instead of "2*m" to avoid a nasty bug in Intel's compiler */
00245     for (m=0; m<n; ++m) data[m+1] = data[m+m];
00246     rfftf (n, data+1, plan->work);
00247     data[0] = data[1];
00248     data[1] = 0;
00249     for (m=2; m<n; m+=2)
00250       {
00251       data[2*n-m]   =  data[m];
00252       data[2*n-m+1] = -data[m+1];
00253       }
00254     if ((n&1)==0) data[n+1] = 0.;
00255     }
00256   }
00257 
00258 void real_plan_backward_c (real_plan plan, double *data)
00259   {
00260   size_t n=plan->length;
00261 
00262   if (plan->bluestein)
00263     {
00264     size_t m;
00265     data[1]=0;
00266     for (m=2; m<n; m+=2)
00267       {
00268       double avg;
00269       avg = 0.5*(data[2*n-m]+data[m]);
00270       data[2*n-m] = data[m] = avg;
00271       avg = 0.5*(data[2*n-m+1]-data[m+1]);
00272       data[2*n-m+1] = avg;
00273       data[m+1] = -avg;
00274       }
00275     if ((n&1)==0) data[n+1] = 0.;
00276     bluestein (plan->length, data, plan->work, 1);
00277     for (m=1; m<2*n; m+=2)
00278       data[m]=0;
00279     }
00280   else
00281     {
00282     ptrdiff_t m;
00283     data[1] = data[0];
00284     rfftb (n, data+1, plan->work);
00285     for (m=n-1; m>=0; --m)
00286       {
00287       data[2*m]   = data[m+1];
00288       data[2*m+1] = 0.;
00289       }
00290     }
00291   }

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