![]() |
NFFT
3.3.2
|
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 /* \} */