NFFT  3.3.2
ndft_fast.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 
00025 #include "config.h"
00026 
00027 #include <stdio.h>
00028 #include <math.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #ifdef HAVE_COMPLEX_H
00032 #include <complex.h>
00033 #endif
00034 
00035 #include "nfft3.h"
00036 #include "infft.h"
00037 
00038 static void ndft_horner_trafo(NFFT(plan) *ths)
00039 {
00040   INT j, k;
00041   C *f_hat_k, *f_j;
00042   C exp_omega_0;
00043 
00044   for (j = 0, f_j = ths->f; j < ths->M_total; j++, f_j++)
00045     (*f_j) = K(0.0);
00046 
00047   for (j = 0, f_j = ths->f; j < ths->M_total; j++, f_j++)
00048   {
00049     exp_omega_0 = CEXP(+K2PI * II * ths->x[j]);
00050     for (k = 0, f_hat_k = ths->f_hat; k < ths->N[0]; k++, f_hat_k++)
00051     {
00052       (*f_j) += (*f_hat_k);
00053       (*f_j) *= exp_omega_0;
00054     }
00055     (*f_j) *= CEXP(-KPI * II * (R)(ths->N[0]) * ths->x[j]);
00056   }
00057 } /* ndft_horner_trafo */
00058 
00059 static void ndft_pre_full_trafo(NFFT(plan) *ths, C *A)
00060 {
00061   INT j, k;
00062   C *f_hat_k, *f_j;
00063   C *A_local;
00064 
00065   for (j = 0, f_j = ths->f; j < ths->M_total; j++, f_j++)
00066     (*f_j) = K(0.0);
00067 
00068   for (j = 0, f_j = ths->f, A_local = A; j < ths->M_total; j++, f_j++)
00069     for (k = 0, f_hat_k = ths->f_hat; k < ths->N[0]; k++, f_hat_k++, A_local++)
00070       (*f_j) += (*f_hat_k) * (*A_local);
00071 } /* ndft_pre_full_trafo */
00072 
00073 static void ndft_pre_full_init(NFFT(plan) *ths, C *A)
00074 {
00075   INT j, k;
00076   C *f_hat_k, *f_j, *A_local;
00077 
00078   for (j = 0, f_j = ths->f, A_local = A; j < ths->M_total; j++, f_j++)
00079     for (k = 0, f_hat_k = ths->f_hat; k < ths->N[0]; k++, f_hat_k++, A_local++)
00080       (*A_local) = CEXP(
00081           -K2PI * II * ((R) (k) - (R) (ths->N[0]) / K(2.0)) * ths->x[j]);
00082 
00083 } /* ndft_pre_full_init */
00084 
00085 static void ndft_time(int N, int M, unsigned test_ndft, unsigned test_pre_full)
00086 {
00087   int r;
00088   R t, t_ndft, t_horner, t_pre_full, t_nfft;
00089   C *A = NULL;
00090   ticks t0, t1;
00091 
00092   NFFT(plan) np;
00093 
00094   printf("%d\t%d\t", N, M);
00095 
00096   NFFT(init_1d)(&np, N, M);
00097 
00098   /* Initialize pseudo random nodes. */
00099   NFFT(vrand_shifted_unit_double)(np.x, np.M_total);
00100 
00101   if (test_pre_full)
00102   {
00103     A = (C*) NFFT(malloc)((size_t)(N * M) * sizeof(R));
00104     ndft_pre_full_init(&np, A);
00105   }
00106 
00107   /* Initialize pseudo random Fourier coefficients. */
00108   NFFT(vrand_unit_complex)(np.f_hat, np.N_total);
00109 
00110   /* NDFT */
00111   if (test_ndft)
00112   {
00113     t_ndft = K(0.0);
00114     r = 0;
00115     while (t_ndft < K(0.1))
00116     {
00117       r++;
00118       t0 = getticks();
00119       NFFT(trafo_direct)(&np);
00120       t1 = getticks();
00121       t = NFFT(elapsed_seconds)(t1, t0);
00122       t_ndft += t;
00123     }
00124     t_ndft /= (R) (r);
00125 
00126     printf("%.2" __FES__ "\t", t_ndft);
00127   }
00128   else
00129     printf("N/A\t\t");
00130 
00131   /* Horner NDFT */
00132   t_horner = K(0.0);
00133   r = 0;
00134   while (t_horner < K(0.1))
00135   {
00136     r++;
00137     t0 = getticks();
00138     ndft_horner_trafo(&np);
00139     t1 = getticks();
00140     t = NFFT(elapsed_seconds)(t1, t0);
00141     t_horner += t;
00142   }
00143   t_horner /= (R)(r);
00144 
00145   printf("%.2" __FES__ "\t", t_horner);
00146 
00147   /* Fully precomputed NDFT */
00148   if (test_pre_full)
00149   {
00150     t_pre_full = K(0.0);
00151     r = 0;
00152     while (t_pre_full < K(0.1))
00153     {
00154       r++;
00155       t0 = getticks();
00156       ndft_pre_full_trafo(&np, A);
00157       t1 = getticks();
00158       t = NFFT(elapsed_seconds)(t1, t0);
00159       t_pre_full += t;
00160     }
00161     t_pre_full /= (R)(r);
00162 
00163     printf("%.2" __FES__ "\t", t_pre_full);
00164   }
00165   else
00166     printf("N/A\t\t");
00167 
00168   t_nfft = K(0.0);
00169   r = 0;
00170   while (t_nfft < K(0.1))
00171   {
00172     r++;
00173     t0 = getticks();
00174     NFFT(trafo)(&np);
00175     t1 = getticks();
00176     t = NFFT(elapsed_seconds)(t1, t0);
00177     t_nfft += t;
00178   }
00179   t_nfft /= (R)(r);
00180 
00181   printf("%.2" __FES__ "\n", t_nfft);
00182 
00183   fflush(stdout);
00184 
00185   if (test_pre_full)
00186     NFFT(free)(A);
00187 
00188   NFFT(finalize)(&np);
00189 }
00190 
00191 int main(int argc, char **argv)
00192 {
00193   int l, trial;
00194 
00195   if (argc < 4)
00196   {
00197     fprintf(stderr, "ndft_fast type first last trials\n");
00198     return EXIT_FAILURE;
00199   }
00200   else
00201   {
00202     int arg2 = (atoi(argv[2]));
00203     int arg3 = (atoi(argv[3]));
00204     int arg4 = (atoi(argv[4]));
00205     fprintf(stderr, "Testing ndft, Horner-like ndft, fully precomputed ndft.\n");
00206     fprintf(stderr, "Columns: N, M, t_ndft, t_horner, t_pre_full, t_nfft\n\n");
00207 
00208     /* time vs. N=M */
00209     if (atoi(argv[1]) == 0)
00210     {
00211       for (l = arg2; l <= arg3; l++)
00212       {
00213         for (trial = 0; trial < arg4; trial++)
00214         {
00215           int N = (int)(1U << l);
00216           int M = (int)(1U << l);
00217           ndft_time(N, M, l <= 15 ? 1 : 0, l <= 13 ? 1 : 0);
00218         }
00219       }
00220     }
00221   }
00222 
00223   return EXIT_SUCCESS;
00224 }