NFFT  3.3.2
linogram_fft_test.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2002, 2016 Jens Keiner, Stefan Kunis, Daniel Potts
00003  *
00004  * This program is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU General Public License as published by the Free Software
00006  * Foundation; either version 2 of the License, or (at your option) any later
00007  * version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00012  * details.
00013  *
00014  * You should have received a copy of the GNU General Public License along with
00015  * this program; if not, write to the Free Software Foundation, Inc., 51
00016  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00028 #include <math.h>
00029 #include <stdlib.h>
00030 #include <complex.h>
00031 
00032 #define NFFT_PRECISION_DOUBLE
00033 
00034 #include "nfft3mp.h"
00035 
00042 NFFT_R GLOBAL_elapsed_time;
00043 
00047 static int linogram_grid(int T, int rr, NFFT_R *x, NFFT_R *w)
00048 {
00049   int t, r;
00050   NFFT_R W = (NFFT_R) T * (((NFFT_R) rr / NFFT_K(2.0)) * ((NFFT_R) rr / NFFT_K(2.0)) + NFFT_K(1.0) / NFFT_K(4.0));
00051 
00052   for (t = -T / 2; t < T / 2; t++)
00053   {
00054     for (r = -rr / 2; r < rr / 2; r++)
00055     {
00056       if (t < 0)
00057       {
00058         x[2 * ((t + T / 2) * rr + (r + rr / 2)) + 0] = (NFFT_R) (r) / (NFFT_R)(rr);
00059         x[2 * ((t + T / 2) * rr + (r + rr / 2)) + 1] = NFFT_K(4.0) * ((NFFT_R)(t) + (NFFT_R)(T) / NFFT_K(4.0)) / (NFFT_R)(T)
00060             * (NFFT_R)(r) / (NFFT_R)(rr);
00061       }
00062       else
00063       {
00064         x[2 * ((t + T / 2) * rr + (r + rr / 2)) + 0] = -NFFT_K(4.0) * ((NFFT_R)(t) - (NFFT_R)(T) / NFFT_K(4.0)) / (NFFT_R)(T)
00065             * (NFFT_R)(r) / (NFFT_R)(rr);
00066         x[2 * ((t + T / 2) * rr + (r + rr / 2)) + 1] = (NFFT_R) r / (NFFT_R)(rr);
00067       }
00068       if (r == 0)
00069         w[(t + T / 2) * rr + (r + rr / 2)] = NFFT_K(1.0) / NFFT_K(4.0) / W;
00070       else
00071         w[(t + T / 2) * rr + (r + rr / 2)] = NFFT_M(fabs)((NFFT_R) r) / W;
00072     }
00073   }
00074 
00075   return T * rr; 
00076 }
00077 
00079 static int linogram_dft(NFFT_C *f_hat, int NN, NFFT_C *f, int T, int rr, int m)
00080 {
00081   double t0, t1;
00082   int j, k; 
00083   NFFT(plan) my_nfft_plan; 
00085   NFFT_R *x, *w; 
00087   int N[2], n[2];
00088   int M = T * rr; 
00090   N[0] = NN;
00091   n[0] = 2 * N[0]; 
00092   N[1] = NN;
00093   n[1] = 2 * N[1]; 
00095   x = (NFFT_R *) NFFT(malloc)((size_t)(2 * T * rr) * (sizeof(NFFT_R)));
00096   if (x == NULL)
00097     return EXIT_FAILURE;
00098 
00099   w = (NFFT_R *) NFFT(malloc)((size_t)(T * rr) * (sizeof(NFFT_R)));
00100   if (w == NULL)
00101     return EXIT_FAILURE;
00102 
00104   NFFT(init_guru)(&my_nfft_plan, 2, N, M, n, m,
00105       PRE_PHI_HUT | PRE_PSI | MALLOC_X | MALLOC_F_HAT | MALLOC_F | FFTW_INIT
00106           | FFT_OUT_OF_PLACE,
00107       FFTW_MEASURE | FFTW_DESTROY_INPUT);
00108 
00110   linogram_grid(T, rr, x, w);
00111   for (j = 0; j < my_nfft_plan.M_total; j++)
00112   {
00113     my_nfft_plan.x[2 * j + 0] = x[2 * j + 0];
00114     my_nfft_plan.x[2 * j + 1] = x[2 * j + 1];
00115   }
00116 
00118   for (k = 0; k < my_nfft_plan.N_total; k++)
00119     my_nfft_plan.f_hat[k] = f_hat[k];
00120 
00122   t0 = NFFT(clock_gettime_seconds)();
00123   NFFT(trafo_direct)(&my_nfft_plan);
00124   t1 = NFFT(clock_gettime_seconds)();
00125   GLOBAL_elapsed_time = (t1 - t0);
00126 
00128   for (j = 0; j < my_nfft_plan.M_total; j++)
00129     f[j] = my_nfft_plan.f[j];
00130 
00132   NFFT(finalize)(&my_nfft_plan);
00133   NFFT(free)(x);
00134   NFFT(free)(w);
00135 
00136   return EXIT_SUCCESS;
00137 }
00138 
00140 static int linogram_fft(NFFT_C *f_hat, int NN, NFFT_C *f, int T, int rr, int m)
00141 {
00142   double t0, t1;
00143   int j, k; 
00144   NFFT(plan) my_nfft_plan; 
00146   NFFT_R *x, *w; 
00148   int N[2], n[2];
00149   int M = T * rr; 
00151   N[0] = NN;
00152   n[0] = 2 * N[0]; 
00153   N[1] = NN;
00154   n[1] = 2 * N[1]; 
00156   x = (NFFT_R *) NFFT(malloc)((size_t)(2 * T * rr) * (sizeof(NFFT_R)));
00157   if (x == NULL)
00158     return EXIT_FAILURE;
00159 
00160   w = (NFFT_R *) NFFT(malloc)((size_t)(T * rr) * (sizeof(NFFT_R)));
00161   if (w == NULL)
00162     return EXIT_FAILURE;
00163 
00165   NFFT(init_guru)(&my_nfft_plan, 2, N, M, n, m,
00166       PRE_PHI_HUT | PRE_PSI | MALLOC_X | MALLOC_F_HAT | MALLOC_F | FFTW_INIT
00167           | FFT_OUT_OF_PLACE,
00168       FFTW_MEASURE | FFTW_DESTROY_INPUT);
00169 
00171   linogram_grid(T, rr, x, w);
00172   for (j = 0; j < my_nfft_plan.M_total; j++)
00173   {
00174     my_nfft_plan.x[2 * j + 0] = x[2 * j + 0];
00175     my_nfft_plan.x[2 * j + 1] = x[2 * j + 1];
00176   }
00177 
00179   if (my_nfft_plan.flags & PRE_LIN_PSI)
00180     NFFT(precompute_lin_psi)(&my_nfft_plan);
00181 
00182   if (my_nfft_plan.flags & PRE_PSI)
00183     NFFT(precompute_psi)(&my_nfft_plan);
00184 
00185   if (my_nfft_plan.flags & PRE_FULL_PSI)
00186     NFFT(precompute_full_psi)(&my_nfft_plan);
00187 
00189   for (k = 0; k < my_nfft_plan.N_total; k++)
00190     my_nfft_plan.f_hat[k] = f_hat[k];
00191 
00193   t0 = NFFT(clock_gettime_seconds)();
00194   NFFT(trafo)(&my_nfft_plan);
00195   t1 = NFFT(clock_gettime_seconds)();
00196   GLOBAL_elapsed_time = (t1 - t0);
00197 
00199   for (j = 0; j < my_nfft_plan.M_total; j++)
00200     f[j] = my_nfft_plan.f[j];
00201 
00203   NFFT(finalize)(&my_nfft_plan);
00204   NFFT(free)(x);
00205   NFFT(free)(w);
00206 
00207   return EXIT_SUCCESS;
00208 }
00209 
00211 static int inverse_linogram_fft(NFFT_C *f, int T, int rr, NFFT_C *f_hat, int NN,
00212     int max_i, int m)
00213 {
00214   double t0, t1;
00215   int j, k; 
00216   NFFT(plan) my_nfft_plan; 
00217   SOLVER(plan_complex) my_infft_plan; 
00219   NFFT_R *x, *w; 
00220   int l; 
00222   int N[2], n[2];
00223   int M = T * rr; 
00225   N[0] = NN;
00226   n[0] = 2 * N[0]; 
00227   N[1] = NN;
00228   n[1] = 2 * N[1]; 
00230   x = (NFFT_R *) NFFT(malloc)((size_t)(2 * T * rr) * (sizeof(NFFT_R)));
00231   if (x == NULL)
00232     return EXIT_FAILURE;
00233 
00234   w = (NFFT_R *) NFFT(malloc)((size_t)(T * rr) * (sizeof(NFFT_R)));
00235   if (w == NULL)
00236     return EXIT_FAILURE;
00237 
00239   NFFT(init_guru)(&my_nfft_plan, 2, N, M, n, m,
00240       PRE_PHI_HUT | PRE_PSI | MALLOC_X | MALLOC_F_HAT | MALLOC_F | FFTW_INIT
00241           | FFT_OUT_OF_PLACE,
00242       FFTW_MEASURE | FFTW_DESTROY_INPUT);
00243 
00245   SOLVER(init_advanced_complex)(&my_infft_plan,
00246       (NFFT(mv_plan_complex)*) (&my_nfft_plan), CGNR | PRECOMPUTE_WEIGHT);
00247 
00249   linogram_grid(T, rr, x, w);
00250   for (j = 0; j < my_nfft_plan.M_total; j++)
00251   {
00252     my_nfft_plan.x[2 * j + 0] = x[2 * j + 0];
00253     my_nfft_plan.x[2 * j + 1] = x[2 * j + 1];
00254     my_infft_plan.y[j] = f[j];
00255     my_infft_plan.w[j] = w[j];
00256   }
00257 
00259   if (my_nfft_plan.flags & PRE_LIN_PSI)
00260     NFFT(precompute_lin_psi)(&my_nfft_plan);
00261 
00262   if (my_nfft_plan.flags & PRE_PSI)
00263     NFFT(precompute_psi)(&my_nfft_plan);
00264 
00265   if (my_nfft_plan.flags & PRE_FULL_PSI)
00266     NFFT(precompute_full_psi)(&my_nfft_plan);
00267 
00269   if (my_infft_plan.flags & PRECOMPUTE_DAMP)
00270     for (j = 0; j < my_nfft_plan.N[0]; j++)
00271       for (k = 0; k < my_nfft_plan.N[1]; k++)
00272       {
00273         my_infft_plan.w_hat[j * my_nfft_plan.N[1] + k] = (
00274             NFFT_M(sqrt)(
00275                 NFFT_M(pow)((NFFT_R)(j - my_nfft_plan.N[0] / 2), NFFT_K(2.0))
00276                     + NFFT_M(pow)((NFFT_R)(k - my_nfft_plan.N[1] / 2), NFFT_K(2.0)))
00277                 > (NFFT_R)(my_nfft_plan.N[0] / 2) ? 0 : 1);
00278       }
00279 
00281   for (k = 0; k < my_nfft_plan.N_total; k++)
00282     my_infft_plan.f_hat_iter[k] = NFFT_K(0.0) + _Complex_I * NFFT_K(0.0);
00283 
00284   t0 = NFFT(clock_gettime_seconds)();
00286   SOLVER(before_loop_complex)(&my_infft_plan);
00287 
00288   if (max_i < 1)
00289   {
00290     l = 1;
00291     for (k = 0; k < my_nfft_plan.N_total; k++)
00292       my_infft_plan.f_hat_iter[k] = my_infft_plan.p_hat_iter[k];
00293   }
00294   else
00295   {
00296     for (l = 1; l <= max_i; l++)
00297     {
00298       SOLVER(loop_one_step_complex)(&my_infft_plan);
00299     }
00300   }
00301 
00302   t1 = NFFT(clock_gettime_seconds)();
00303   GLOBAL_elapsed_time = (t1 - t0);
00304 
00306   for (k = 0; k < my_nfft_plan.N_total; k++)
00307     f_hat[k] = my_infft_plan.f_hat_iter[k];
00308 
00310   SOLVER(finalize_complex)(&my_infft_plan);
00311   NFFT(finalize)(&my_nfft_plan);
00312   NFFT(free)(x);
00313   NFFT(free)(w);
00314 
00315   return EXIT_SUCCESS;
00316 }
00317 
00319 static int comparison_fft(FILE *fp, int N, int T, int rr)
00320 {
00321   double t0, t1;
00322   FFTW(plan) my_fftw_plan;
00323   NFFT_C *f_hat, *f;
00324   int m, k;
00325   NFFT_R t_fft, t_dft_linogram;
00326 
00327   f_hat = (NFFT_C *) NFFT(malloc)(sizeof(NFFT_C) * (size_t)(N * N));
00328   f = (NFFT_C *) NFFT(malloc)(sizeof(NFFT_C) * (size_t)((T * rr / 4) * 5));
00329 
00330   my_fftw_plan = FFTW(plan_dft_2d)(N, N, f_hat, f, FFTW_BACKWARD, FFTW_MEASURE);
00331 
00332   for (k = 0; k < N * N; k++)
00333     f_hat[k] = NFFT(drand48)() + _Complex_I * NFFT(drand48)();
00334 
00335   t0 = NFFT(clock_gettime_seconds)();
00336   for (m = 0; m < 65536 / N; m++)
00337   {
00338     FFTW(execute)(my_fftw_plan);
00339     /* touch */
00340     f_hat[2] = NFFT_K(2.0) * f_hat[0];
00341   }
00342   t1 = NFFT(clock_gettime_seconds)();
00343   GLOBAL_elapsed_time = (t1 - t0);
00344   t_fft = (NFFT_R)(N) * GLOBAL_elapsed_time / NFFT_K(65536.0);
00345 
00346   if (N < 256)
00347   {
00348     linogram_dft(f_hat, N, f, T, rr, m);
00349     t_dft_linogram = GLOBAL_elapsed_time;
00350   }
00351 
00352   for (m = 3; m <= 9; m += 3)
00353   {
00354     if ((m == 3) && (N < 256))
00355       fprintf(fp, "%d\t&\t&\t%1.1" NFFT__FES__ "&\t%1.1" NFFT__FES__ "&\t%d\t", N, t_fft, t_dft_linogram,
00356           m);
00357     else if (m == 3)
00358       fprintf(fp, "%d\t&\t&\t%1.1" NFFT__FES__ "&\t       &\t%d\t", N, t_fft, m);
00359     else
00360       fprintf(fp, "  \t&\t&\t       &\t       &\t%d\t", m);
00361 
00362     printf("N=%d\tt_fft=%1.1" NFFT__FES__ "\tt_dft_linogram=%1.1" NFFT__FES__ "\tm=%d\t", N, t_fft,
00363         t_dft_linogram, m);
00364 
00365     linogram_fft(f_hat, N, f, T, rr, m);
00366     fprintf(fp, "%1.1" NFFT__FES__ "&\t", GLOBAL_elapsed_time);
00367     printf("t_linogram=%1.1" NFFT__FES__ "\t", GLOBAL_elapsed_time);
00368     inverse_linogram_fft(f, T, rr, f_hat, N, m + 3, m);
00369     if (m == 9)
00370       fprintf(fp, "%1.1" NFFT__FES__ "\\\\\\hline\n", GLOBAL_elapsed_time);
00371     else
00372       fprintf(fp, "%1.1" NFFT__FES__ "\\\\\n", GLOBAL_elapsed_time);
00373     printf("t_ilinogram=%1.1" NFFT__FES__ "\n", GLOBAL_elapsed_time);
00374   }
00375 
00376   fflush(fp);
00377 
00378   NFFT(free)(f);
00379   NFFT(free)(f_hat);
00380 
00381   return EXIT_SUCCESS;
00382 }
00383 
00385 int main(int argc, char **argv)
00386 {
00387   int N; 
00388   int T, rr; 
00389   int M; 
00390   NFFT_R *x, *w; 
00391   NFFT_C *f_hat, *f, *f_direct, *f_tilde;
00392   int k;
00393   int max_i; 
00394   int m;
00395   NFFT_R temp1, temp2, E_max = NFFT_K(0.0);
00396   FILE *fp1, *fp2;
00397   char filename[30];
00398   int logN;
00399 
00400   if (argc != 4)
00401   {
00402     printf("linogram_fft_test N T R \n");
00403     printf("\n");
00404     printf("N          linogram FFT of size NxN    \n");
00405     printf("T          number of slopes          \n");
00406     printf("R          number of offsets         \n");
00407 
00409     printf("\nHence, comparison FFTW, linogram FFT and inverse linogram FFT\n");
00410     fp1 = fopen("linogram_comparison_fft.dat", "w");
00411     if (fp1 == NULL)
00412       return (-1);
00413     for (logN = 4; logN <= 8; logN++)
00414       comparison_fft(fp1, (int)(1U << logN), 3 * (int)(1U << logN),
00415           3 * (int)(1U << (logN - 1)));
00416     fclose(fp1);
00417 
00418     return EXIT_FAILURE;
00419   }
00420 
00421   N = atoi(argv[1]);
00422   T = atoi(argv[2]);
00423   rr = atoi(argv[3]);
00424   printf("N=%d, linogram grid with T=%d, R=%d => ", N, T, rr);
00425 
00426   x = (NFFT_R *) NFFT(malloc)((size_t)(5 * T * rr / 2) * (sizeof(NFFT_R)));
00427   w = (NFFT_R *) NFFT(malloc)((size_t)(5 * T * rr / 4) * (sizeof(NFFT_R)));
00428 
00429   f_hat = (NFFT_C *) NFFT(malloc)(sizeof(NFFT_C) * (size_t)(N * N));
00430   f = (NFFT_C *) NFFT(malloc)(sizeof(NFFT_C) * (size_t)(5 * T * rr / 4)); /* 4/pi*log(1+sqrt(2)) = 1.122... < 1.25 */
00431   f_direct = (NFFT_C *) NFFT(malloc)(sizeof(NFFT_C) * (size_t)(5 * T * rr / 4));
00432   f_tilde = (NFFT_C *) NFFT(malloc)(sizeof(NFFT_C) * (size_t)(N * N));
00433 
00435   M = linogram_grid(T, rr, x, w);
00436   printf("M=%d.\n", M);
00437 
00439   fp1 = fopen("input_data_r.dat", "r");
00440   fp2 = fopen("input_data_i.dat", "r");
00441   if ((fp1 == NULL) || (fp2 == NULL))
00442     return EXIT_FAILURE;
00443   for (k = 0; k < N * N; k++)
00444   {
00445     fscanf(fp1, NFFT__FR__ " ", &temp1);
00446     fscanf(fp2, NFFT__FR__ " ", &temp2);
00447     f_hat[k] = temp1 + _Complex_I * temp2;
00448   }
00449   fclose(fp1);
00450   fclose(fp2);
00451 
00453   linogram_dft(f_hat, N, f_direct, T, rr, 1);
00454   //  linogram_fft(f_hat,N,f_direct,T,R,12);
00455 
00457   printf("\nTest of the linogram FFT: \n");
00458   fp1 = fopen("linogram_fft_error.dat", "w+");
00459   for (m = 1; m <= 12; m++)
00460   {
00462     linogram_fft(f_hat, N, f, T, rr, m);
00463 
00465     E_max = NFFT(error_l_infty_complex)(f_direct, f, M);
00466     //E_max=NFFT(error_l_2_complex)(f_direct,f,M);
00467 
00468     printf("m=%2d: E_max = %" NFFT__FES__ "\n", m, E_max);
00469     fprintf(fp1, "%" NFFT__FES__ "\n", E_max);
00470   }
00471   fclose(fp1);
00472 
00474   for (m = 3; m <= 9; m += 3)
00475   {
00476     printf("\nTest of the inverse linogram FFT for m=%d: \n", m);
00477     sprintf(filename, "linogram_ifft_error%d.dat", m);
00478     fp1 = fopen(filename, "w+");
00479     for (max_i = 0; max_i <= 20; max_i += 2)
00480     {
00482       inverse_linogram_fft(f_direct, T, rr, f_tilde, N, max_i, m);
00483 
00485       E_max = NFFT(error_l_infty_complex)(f_hat, f_tilde, N * N);
00486       printf("%3d iterations: E_max = %" NFFT__FES__ "\n", max_i, E_max);
00487       fprintf(fp1, "%" NFFT__FES__ "\n", E_max);
00488     }
00489     fclose(fp1);
00490   }
00491 
00493   NFFT(free)(x);
00494   NFFT(free)(w);
00495   NFFT(free)(f_hat);
00496   NFFT(free)(f);
00497   NFFT(free)(f_direct);
00498   NFFT(free)(f_tilde);
00499 
00500   return EXIT_SUCCESS;
00501 }
00502 /* \} */