00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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.;
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;
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
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 }