00001 #include <stdio.h>
00002 #include <math.h>
00003 #include <string.h>
00004 #include <stdlib.h>
00005
00006 #include "util.h"
00007 #include "options.h"
00008 #include "window_defines.h"
00009
00010 #include "nfft3.h"
00011
00012
00013 #define MACRO_nndft_init_result_trafo memset(f,0,ths->M_total*sizeof(complex double));
00014 #define MACRO_nndft_init_result_conjugated MACRO_nndft_init_result_trafo
00015 #define MACRO_nndft_init_result_adjoint memset(f_hat,0,ths->N_total* \
00016 sizeof(complex double));
00017 #define MACRO_nndft_init_result_transposed MACRO_nndft_init_result_adjoint
00018
00019 #define MACRO_nndft_sign_trafo (+2.0*PI)
00020 #define MACRO_nndft_sign_conjugated (-2.0*PI)
00021 #define MACRO_nndft_sign_adjoint (-2.0*PI)
00022 #define MACRO_nndft_sign_transposed (+2.0*PI)
00023
00024 #define MACRO_nndft_compute_trafo (*fj) += (*f_hat_k)*cexp(-I*omega);
00025
00026 #define MACRO_nndft_compute_conjugated MACRO_nndft_compute_trafo
00027
00028 #define MACRO_nndft_compute_adjoint (*f_hat_k) += (*fj)*cexp(+I*omega);
00029
00030 #define MACRO_nndft_compute_transposed MACRO_nndft_compute_adjoint
00031
00032 #define MACRO_nndft(which_one) \
00033 void nndft_ ## which_one (nnfft_plan *ths) \
00034 { \
00035 int j; \
00036 int t; \
00037 int l; \
00038 complex double *f_hat, *f; \
00039 complex double *f_hat_k; \
00040 complex double *fj; \
00041 double omega; \
00042 \
00043 f_hat=ths->f_hat; f=ths->f; \
00044 \
00045 MACRO_nndft_init_result_ ## which_one \
00046 \
00047 for(j=0, fj=f; j<ths->M_total; j++, fj++) \
00048 { \
00049 for(l=0, f_hat_k=f_hat; l<ths->N_total; l++, f_hat_k++) \
00050 { \
00051 omega=0.0; \
00052 for(t = 0; t<ths->d; t++) \
00053 omega+=ths->v[l*ths->d+t] * ths->x[j*ths->d+t] * ths->N[t]; \
00054 \
00055 omega*= MACRO_nndft_sign_ ## which_one; \
00056 \
00057 MACRO_nndft_compute_ ## which_one \
00058 \
00059 } \
00060 } \
00061 } \
00062
00063 MACRO_nndft(trafo)
00064 MACRO_nndft(adjoint)
00065
00068 void nnfft_uo(nnfft_plan *ths,int j,int *up,int *op,int act_dim)
00069 {
00070 double c;
00071 int u,o;
00072
00073 c = ths->v[j*ths->d+act_dim] * ths->n[act_dim];
00074
00075 u = c; o = c;
00076 if(c < 0)
00077 u = u-1;
00078 else
00079 o = o+1;
00080
00081 u = u - (ths->m); o = o + (ths->m);
00082
00083 up[0]=u; op[0]=o;
00084 }
00085
00089 #define MACRO_nnfft_B_init_result_A memset(f,0,ths->M_total*sizeof(complex double));
00090 #define MACRO_nnfft_B_init_result_T memset(g,0,ths->aN1_total*sizeof(complex double));
00091
00092 #define MACRO_nnfft_B_PRE_FULL_PSI_compute_A { \
00093 (*fj) += ths->psi[ix] * g[ths->psi_index_g[ix]]; \
00094 }
00095
00096 #define MACRO_nnfft_B_PRE_FULL_PSI_compute_T { \
00097 g[ths->psi_index_g[ix]] += ths->psi[ix] * (*fj); \
00098 }
00099
00100 #define MACRO_nnfft_B_compute_A { \
00101 (*fj) += phi_prod[ths->d] * g[ll_plain[ths->d]]; \
00102 }
00103
00104 #define MACRO_nnfft_B_compute_T { \
00105 g[ll_plain[ths->d]] += phi_prod[ths->d] * (*fj); \
00106 }
00107
00108
00109 #define MACRO_with_PRE_LIN_PSI (ths->psi[(ths->K+1)*t2+y_u[t2]]* \
00110 (y_u[t2]+1-y[t2]) + \
00111 ths->psi[(ths->K+1)*t2+y_u[t2]+1]* \
00112 (y[t2]-y_u[t2]))
00113 #define MACRO_with_PRE_PSI ths->psi[(j*ths->d+t2)*(2*ths->m+2)+lj[t2]]
00114 #define MACRO_without_PRE_PSI PHI(-ths->v[j*ths->d+t2]+ \
00115 ((double)l[t2])/ths->N1[t2], t2)
00116
00117 #define MACRO_init_uo_l_lj_t { \
00118 for(t = ths->d-1; t>=0; t--) \
00119 { \
00120 nnfft_uo(ths,j,&u[t],&o[t],t); \
00121 l[t] = u[t]; \
00122 lj[t] = 0; \
00123 } \
00124 t++; \
00125 }
00126
00127 #define MACRO_update_with_PRE_PSI_LIN { \
00128 for(t2=t; t2<ths->d; t2++) \
00129 { \
00130 y[t2] = fabs(((-ths->N1[t2]*ths->v[j*ths->d+t2]+(double)l[t2]) \
00131 * ((double)ths->K))/(ths->m+1)); \
00132 y_u[t2] = (int)y[t2]; \
00133 } \
00134 }
00135
00136 #define MACRO_update_phi_prod_ll_plain(which_one) { \
00137 for(t2=t; t2<ths->d; t2++) \
00138 { \
00139 phi_prod[t2+1]=phi_prod[t2]* MACRO_ ## which_one; \
00140 ll_plain[t2+1]=ll_plain[t2]*ths->aN1[t2] +(l[t2]+ths->aN1[t2]*3/2)%ths->aN1[t2]; \
00141 } \
00142 }
00143
00144 #define MACRO_count_uo_l_lj_t { \
00145 for(t = ths->d-1; (t>0)&&(l[t]==o[t]); t--) \
00146 { \
00147 l[t] = u[t]; \
00148 lj[t] = 0; \
00149 } \
00150 \
00151 l[t]++; \
00152 lj[t]++; \
00153 }
00154
00155 #define MACRO_nnfft_B(which_one) \
00156 inline void nnfft_B_ ## which_one (nnfft_plan *ths) \
00157 { \
00158 int lprod; \
00159 int u[ths->d], o[ths->d]; \
00160 int t, t2; \
00161 int j; \
00162 int l_L, ix; \
00163 int l[ths->d]; \
00164 int lj[ths->d]; \
00165 int ll_plain[ths->d+1]; \
00166 double phi_prod[ths->d+1]; \
00167 complex double *f, *g; \
00168 complex double *fj; \
00169 double y[ths->d]; \
00170 int y_u[ths->d]; \
00171 \
00172 f=ths->f_hat; g=ths->F; \
00173 \
00174 MACRO_nnfft_B_init_result_ ## which_one \
00175 \
00176 if(ths->nnfft_flags & PRE_FULL_PSI) \
00177 { \
00178 for(ix=0, j=0, fj=f; j<ths->N_total; j++,fj++)\
00179 for(l_L=0; l_L<ths->psi_index_f[j]; l_L++, ix++) \
00180 MACRO_nnfft_B_PRE_FULL_PSI_compute_ ## which_one; \
00181 return; \
00182 } \
00183 \
00184 phi_prod[0]=1; \
00185 ll_plain[0]=0; \
00186 \
00187 for(t=0,lprod = 1; t<ths->d; t++) \
00188 lprod *= (2*ths->m+2); \
00189 \
00190 if(ths->nnfft_flags & PRE_PSI) \
00191 { \
00192 for(j=0, fj=f; j<ths->N_total; j++, fj++) \
00193 { \
00194 MACRO_init_uo_l_lj_t; \
00195 \
00196 for(l_L=0; l_L<lprod; l_L++) \
00197 { \
00198 MACRO_update_phi_prod_ll_plain(with_PRE_PSI); \
00199 \
00200 MACRO_nnfft_B_compute_ ## which_one; \
00201 \
00202 MACRO_count_uo_l_lj_t; \
00203 } \
00204 } \
00205 return; \
00206 } \
00207 \
00208 if(ths->nnfft_flags & PRE_LIN_PSI) \
00209 { \
00210 for(j=0, fj=f; j<ths->N_total; j++, fj++) \
00211 { \
00212 MACRO_init_uo_l_lj_t; \
00213 \
00214 for(l_L=0; l_L<lprod; l_L++) \
00215 { \
00216 MACRO_update_with_PRE_PSI_LIN; \
00217 \
00218 MACRO_update_phi_prod_ll_plain(with_PRE_LIN_PSI); \
00219 \
00220 MACRO_nnfft_B_compute_ ## which_one; \
00221 \
00222 MACRO_count_uo_l_lj_t; \
00223 } \
00224 } \
00225 return; \
00226 } \
00227 \
00228 \
00229 for(j=0, fj=f; j<ths->N_total; j++, fj++) \
00230 { \
00231 \
00232 MACRO_init_uo_l_lj_t; \
00233 \
00234 for(l_L=0; l_L<lprod; l_L++) \
00235 { \
00236 MACRO_update_phi_prod_ll_plain(without_PRE_PSI); \
00237 \
00238 MACRO_nnfft_B_compute_ ## which_one; \
00239 \
00240 MACRO_count_uo_l_lj_t; \
00241 } \
00242 } \
00243 }
00244
00245 MACRO_nnfft_B(A)
00246 MACRO_nnfft_B(T)
00247
00248 inline void nnfft_D (nnfft_plan *ths){
00249 int j,t;
00250 double tmp;
00251
00252 if(ths->nnfft_flags & PRE_PHI_HUT) {
00253 for(j=0; j<ths->M_total; j++)
00254 ths->f[j] *= ths->c_phi_inv[j];
00255 } else {
00256 for(j=0; j<ths->M_total; j++)
00257 {
00258 tmp = 1.0;
00259
00260 for(t=0; t<ths->d; t++)
00261 tmp*= 1.0 /((PHI_HUT(ths->x[ths->d*j + t]*((double)ths->N[t]),t)) );
00262 ths->f[j] *= tmp;
00263 }
00264 }
00265 }
00266
00269 void nnfft_trafo(nnfft_plan *ths)
00270 {
00271 int j,t;
00272
00273 nnfft_B_T(ths);
00274
00275 for(j=0;j<ths->M_total;j++) {
00276 for(t=0;t<ths->d;t++) {
00277 ths->x[j*ths->d+t]= ths->x[j*ths->d+t] / ((double)ths->sigma[t]);
00278 }
00279 }
00280
00281 ths->direct_plan->f = ths->f;
00282 nfft_trafo(ths->direct_plan);
00283
00284 for(j=0;j<ths->M_total;j++) {
00285 for(t=0;t<ths->d;t++) {
00286 ths->x[j*ths->d+t]= ths->x[j*ths->d+t] * ((double)ths->sigma[t]);
00287 }
00288 }
00289
00290 nnfft_D(ths);
00291 }
00292
00293 void nnfft_adjoint(nnfft_plan *ths)
00294 {
00295 int j,t;
00296
00297 nnfft_D(ths);
00298
00299 for(j=0;j<ths->M_total;j++) {
00300 for(t=0;t<ths->d;t++) {
00301 ths->x[j*ths->d+t]= ths->x[j*ths->d+t] / ((double)ths->sigma[t]);
00302 }
00303 }
00304
00305 ths->direct_plan->f = ths->f;
00306 nfft_adjoint(ths->direct_plan);
00307
00308 for(j=0;j<ths->M_total;j++) {
00309 for(t=0;t<ths->d;t++) {
00310 ths->x[j*ths->d+t]= ths->x[j*ths->d+t] * ((double)ths->sigma[t]);
00311 }
00312 }
00313
00314 nnfft_B_A(ths);
00315 }
00316
00319 void nnfft_precompute_phi_hut(nnfft_plan *ths)
00320 {
00321 int j;
00322 int t;
00323 double tmp;
00324
00325 ths->c_phi_inv= (double*)fftw_malloc(ths->M_total*sizeof(double));
00326
00327 for(j=0; j<ths->M_total; j++)
00328 {
00329 tmp = 1.0;
00330 for(t=0; t<ths->d; t++)
00331 tmp*= 1.0 /(PHI_HUT(ths->x[ths->d*j + t]*((double)ths->N[t]),t));
00332 ths->c_phi_inv[j]=tmp;
00333 }
00334 }
00335
00336
00341 void nnfft_precompute_lin_psi(nnfft_plan *ths)
00342 {
00343 int t;
00344 int j;
00345 double step;
00347 nfft_precompute_lin_psi(ths->direct_plan);
00348
00349 for (t=0; t<ths->d; t++)
00350 {
00351 step=((double)(ths->m+1))/(ths->K*ths->N1[t]);
00352 for(j=0;j<=ths->K;j++)
00353 {
00354 ths->psi[(ths->K+1)*t + j] = PHI(j*step,t);
00355 }
00356 }
00357 }
00358
00359 void nnfft_precompute_psi(nnfft_plan *ths)
00360 {
00361 int t;
00362 int j;
00363 int l;
00364 int lj;
00365 int u, o;
00367 for (t=0; t<ths->d; t++)
00368 for(j=0;j<ths->N_total;j++)
00369 {
00370 nnfft_uo(ths,j,&u,&o,t);
00371
00372 for(l=u, lj=0; l <= o; l++, lj++)
00373 ths->psi[(j*ths->d+t)*(2*ths->m+2)+lj]=
00374 (PHI((-ths->v[j*ths->d+t]+((double)l)/((double)ths->N1[t])),t));
00375 }
00376
00377 for(j=0;j<ths->M_total;j++) {
00378 for(t=0;t<ths->d;t++) {
00379 ths->x[j*ths->d+t]= ths->x[j*ths->d+t] / ((double)ths->sigma[t]);
00380 }
00381 }
00382
00383 nfft_precompute_psi(ths->direct_plan);
00384
00385 for(j=0;j<ths->M_total;j++) {
00386 for(t=0;t<ths->d;t++) {
00387 ths->x[j*ths->d+t]= ths->x[j*ths->d+t] * ((double)ths->sigma[t]);
00388 }
00389 }
00390
00391 }
00392
00393
00394
00398 void nnfft_precompute_full_psi(nnfft_plan *ths)
00399 {
00400 int t,t2;
00401 int j;
00402 int l_L;
00403 int l[ths->d];
00404 int lj[ths->d];
00405 int ll_plain[ths->d+1];
00406 int lprod;
00407 int u[ths->d], o[ths->d];
00409 double phi_prod[ths->d+1];
00410
00411 int ix,ix_old;
00412
00413 for(j=0;j<ths->M_total;j++) {
00414 for(t=0;t<ths->d;t++) {
00415 ths->x[j*ths->d+t]= ths->x[j*ths->d+t] / ((double)ths->sigma[t]);
00416 }
00417 }
00418
00419 nnfft_precompute_psi(ths);
00420
00421 nfft_precompute_full_psi(ths->direct_plan);
00422
00423 for(j=0;j<ths->M_total;j++) {
00424 for(t=0;t<ths->d;t++) {
00425 ths->x[j*ths->d+t]= ths->x[j*ths->d+t] * ((double)ths->sigma[t]);
00426 }
00427 }
00428
00429 phi_prod[0]=1;
00430 ll_plain[0]=0;
00431
00432 for(t=0,lprod = 1; t<ths->d; t++)
00433 lprod *= 2*ths->m+2;
00434
00435 for(j=0,ix=0,ix_old=0; j<ths->N_total; j++)
00436 {
00437 MACRO_init_uo_l_lj_t;
00438
00439 for(l_L=0; l_L<lprod; l_L++, ix++)
00440 {
00441 MACRO_update_phi_prod_ll_plain(without_PRE_PSI);
00442
00443 ths->psi_index_g[ix]=ll_plain[ths->d];
00444 ths->psi[ix]=phi_prod[ths->d];
00445
00446 MACRO_count_uo_l_lj_t;
00447 }
00448
00449
00450 ths->psi_index_f[j]=ix-ix_old;
00451 ix_old=ix;
00452 }
00453 }
00454
00455 void nnfft_init_help(nnfft_plan *ths, int m2, unsigned nfft_flags, unsigned fftw_flags)
00456 {
00457 int t;
00458 int lprod;
00459 int N2[ths->d];
00460
00461 ths->aN1 = (int*) fftw_malloc(ths->d*sizeof(int));
00462
00463 ths->a = (double*) fftw_malloc(ths->d*sizeof(double));
00464
00465 ths->sigma = (double*) fftw_malloc(ths->d*sizeof(double));
00466
00467 ths->n = ths->N1;
00468
00469 ths->aN1_total=1;
00470
00471 for(t = 0; t<ths->d; t++) {
00472 ths->a[t] = 1.0 + (2.0*((double)ths->m))/((double)ths->N1[t]);
00473 ths->aN1[t] = ths->a[t] * ((double)ths->N1[t]);
00474
00475 if(ths->aN1[t]%2 != 0)
00476 ths->aN1[t] = ths->aN1[t] +1;
00477
00478 ths->aN1_total*=ths->aN1[t];
00479 ths->sigma[t] = ((double) ths->N1[t] )/((double) ths->N[t]);;
00480
00481
00482 N2[t] = ceil(ths->sigma[t]*(ths->aN1[t]));
00483
00484
00485 if(N2[t]%2 != 0)
00486 N2[t] = N2[t] +1;
00487 }
00488
00489 WINDOW_HELP_INIT
00490
00491 if(ths->nnfft_flags & MALLOC_X)
00492 ths->x = (double*)fftw_malloc(ths->d*ths->M_total*
00493 sizeof(double));
00494
00495 if(ths->nnfft_flags & MALLOC_V)
00496 ths->v = (double*)fftw_malloc(ths->d*ths->N_total*
00497 sizeof(double));
00498
00499 if(ths->nnfft_flags & MALLOC_F_HAT)
00500 ths->f_hat = (complex double*)fftw_malloc(ths->N_total*
00501 sizeof(complex double));
00502 if(ths->nnfft_flags & MALLOC_F)
00503 ths->f=(complex double*)fftw_malloc(ths->M_total*sizeof(complex double));
00504
00505 if(ths->nnfft_flags & PRE_LIN_PSI)
00506 {
00507 ths->K=100000;
00508 ths->psi = (double*) fftw_malloc((ths->K+1)*ths->d*sizeof(double));
00509 }
00510
00511
00512 if(ths->nnfft_flags & PRE_PSI)
00513 ths->psi = (double*) malloc(ths->N_total*ths->d*
00514 (2*ths->m+2)*sizeof(double));
00515
00516 if(ths->nnfft_flags & PRE_FULL_PSI)
00517 {
00518 for(t=0,lprod = 1; t<ths->d; t++)
00519 lprod *= 2*ths->m+2;
00520
00521 ths->psi = (double*) fftw_malloc(ths->M_total*lprod*sizeof(double));
00522
00523 ths->psi_index_f = (int*) fftw_malloc(ths->M_total*sizeof(int));
00524 ths->psi_index_g = (int*) fftw_malloc(ths->M_total*lprod*sizeof(int));
00525 }
00526
00527 ths->direct_plan = (nfft_plan*) malloc(sizeof(nfft_plan));
00528
00529 nfft_init_guru(ths->direct_plan, ths->d, ths->aN1, ths->M_total, N2, m2,
00530 nfft_flags, fftw_flags);
00531
00532 ths->direct_plan->x = ths->x;
00533 ths->direct_plan->f = ths->f;
00534 ths->F = ths->direct_plan->f_hat;
00535 }
00536
00537 void nnfft_init_guru(nnfft_plan *ths, int d, int N_total, int M_total, int *N, int *N1,
00538 int m, unsigned nnfft_flags)
00539 {
00540 int t;
00542 unsigned nfft_flags;
00543 unsigned fftw_flags;
00544
00545 ths->d= d;
00546 ths->M_total= M_total;
00547 ths->N_total= N_total;
00548 ths->m= m;
00549 ths->nnfft_flags= nnfft_flags;
00550 fftw_flags= FFTW_ESTIMATE| FFTW_DESTROY_INPUT;
00551 nfft_flags= PRE_PHI_HUT| MALLOC_F_HAT| FFTW_INIT| FFT_OUT_OF_PLACE;
00552
00553 if(ths->nnfft_flags & PRE_PSI)
00554 nfft_flags = nfft_flags | PRE_PSI;
00555
00556 if(ths->nnfft_flags & PRE_FULL_PSI)
00557 nfft_flags = nfft_flags | PRE_FULL_PSI;
00558
00559 if(ths->nnfft_flags & PRE_LIN_PSI)
00560 nfft_flags = nfft_flags | PRE_LIN_PSI;
00561
00562 ths->N = (int*) fftw_malloc(ths->d*sizeof(int));
00563 ths->N1 = (int*) fftw_malloc(ths->d*sizeof(int));
00564
00565 for(t=0; t<d; t++) {
00566 ths->N[t] = N[t];
00567 ths->N1[t] = N1[t];
00568 }
00569 nnfft_init_help(ths,m,nfft_flags,fftw_flags);
00570 }
00571
00572 void nnfft_init(nnfft_plan *ths, int d, int N_total, int M_total, int *N)
00573 {
00574 int t;
00576 unsigned nfft_flags;
00577 unsigned fftw_flags;
00578
00579 ths->d = d;
00580 ths->M_total = M_total;
00581 ths->N_total = N_total;
00582
00583
00584 WINDOW_HELP_ESTIMATE_m;
00585
00586 ths->N = (int*) fftw_malloc(ths->d*sizeof(int));
00587 ths->N1 = (int*) fftw_malloc(ths->d*sizeof(int));
00588
00589 for(t=0; t<d; t++) {
00590 ths->N[t] = N[t];
00591
00592
00593 ths->N1[t] = ceil(1.5*ths->N[t]);
00594
00595
00596 if(ths->N1[t]%2 != 0)
00597 ths->N1[t] = ths->N1[t] +1;
00598 }
00599 ths->nnfft_flags=PRE_PSI| PRE_PHI_HUT| MALLOC_X| MALLOC_V| MALLOC_F_HAT| MALLOC_F;
00600 nfft_flags= PRE_PSI| PRE_PHI_HUT| MALLOC_F_HAT| FFTW_INIT| FFT_OUT_OF_PLACE;
00601
00602 fftw_flags= FFTW_ESTIMATE| FFTW_DESTROY_INPUT;
00603
00604 nnfft_init_help(ths,ths->m,nfft_flags,fftw_flags);
00605 }
00606
00607 void nnfft_finalize(nnfft_plan *ths)
00608 {
00609 nfft_finalize(ths->direct_plan);
00610
00611 free(ths->direct_plan);
00612
00613 free(ths->aN1);
00614 free(ths->N);
00615 free(ths->N1);
00616
00617 if(ths->nnfft_flags & PRE_FULL_PSI)
00618 {
00619 fftw_free(ths->psi_index_g);
00620 fftw_free(ths->psi_index_f);
00621 fftw_free(ths->psi);
00622 }
00623
00624 if(ths->nnfft_flags & PRE_PSI)
00625 fftw_free(ths->psi);
00626
00627 if(ths->nnfft_flags & PRE_LIN_PSI)
00628 fftw_free(ths->psi);
00629
00630
00631 if(ths->nnfft_flags & PRE_PHI_HUT)
00632 fftw_free(ths->c_phi_inv);
00633
00634 if(ths->nnfft_flags & MALLOC_F)
00635 fftw_free(ths->f);
00636
00637 if(ths->nnfft_flags & MALLOC_F_HAT)
00638 fftw_free(ths->f_hat);
00639
00640 if(ths->nnfft_flags & MALLOC_X)
00641 fftw_free(ths->x);
00642
00643 if(ths->nnfft_flags & MALLOC_V)
00644 fftw_free(ths->v);
00645 }