39 #define NFST_DEFAULT_FLAGS   PRE_PHI_HUT|\ 
   47 #define FFTW_DEFAULT_FLAGS   FFTW_ESTIMATE|\ 
   50 #define NFST_SUMMANDS ( 2 * ths->m + 2) 
   51 #define NODE(p,r) ( ths->x[(p) * ths->d + (r)]) 
   53 #define MACRO_ndst_init_result_trafo      \ 
   54   memset( f, 0, ths->M_total * sizeof( double)); 
   55 #define MACRO_ndst_init_result_adjoint \ 
   56   memset( f_hat, 0, ths->N_total * sizeof( double)); 
   59 #define MACRO_nfst_D_init_result_A        \ 
   60   memset(g_hat, 0, nfst_prod_minus_a_int( ths->n, 0, ths->d) * sizeof( double)); 
   61 #define MACRO_nfst_D_init_result_T        \ 
   62   memset(f_hat, 0, ths->N_total * sizeof( double)); 
   64 #define MACRO_nfst_B_init_result_A        \ 
   65   memset(f, 0,     ths->M_total * sizeof( double)); 
   66 #define MACRO_nfst_B_init_result_T        \ 
   67   memset(g, 0, nfst_prod_minus_a_int( ths->n, 0, ths->d) * sizeof( double)); 
   70 #define NFST_PRE_WINFUN( d)  ths->N[d] = 2 * ths->N[d];         \ 
   71                              ths->n[d] = nfst_fftw_2N( ths->n[d]); 
   73 #define NFST_POST_WINFUN( d) ths->N[d] = (LRINT(0.5 * ths->N[d]));   \ 
   74                              ths->n[d] = nfst_fftw_2N_rev( ths->n[d]); 
   77 #define NFST_WINDOW_HELP_INIT  WINDOW_HELP_INIT 
   80 double nfst_phi_hut( 
nfst_plan *ths, 
int k, 
int d)
 
   83   double phi_hut_tmp = PHI_HUT( k, d);
 
   89 double nfst_phi( 
nfst_plan *ths, 
double x, 
int d)
 
   92   double phi_tmp = PHI( x, d);
 
   98 int nfst_fftw_2N( 
int n)
 
  103 int nfst_fftw_2N_rev( 
int n)
 
  108   return n_div.quot - 1;
 
  111 #define MACRO_with_sin_vec     sin_vec[t][ka[t]] 
  112 #define MACRO_without_sin_vec  sin( 2.0 * PI * (ka[t]+1) * NODE(j,t)) 
  115 #define MACRO_with_PRE_PHI_HUT     ths->c_phi_inv[t][kg[t]]; 
  116 #define MACRO_compute_PHI_HUT_INV  (1.0 / (nfst_phi_hut( ths, kg[t]+1, t))) 
  118 #define MACRO_with_PRE_PSI     ths->psi[(j * ths->d + t) * NFST_SUMMANDS + lc[t]]; 
  119 #define MACRO_compute_PSI      \ 
  120   nfst_phi( ths, NODE(j,t) - (( double)(lc[t] + lb[t])) / nfst_fftw_2N( ths->n[t]), t) 
  139 #define MACRO_ndst_malloc__sin_vec                                              \ 
  142   sin_vec = (double**)nfft_malloc( ths->d * sizeof( double*));                       \ 
  143   for( t = 0; t < ths->d; t++)                                                  \ 
  144     sin_vec[t] = (double*)nfft_malloc( ( ths->N[t] - 1) * sizeof( double));          \ 
  149 #define MACRO_ndst_free__sin_vec                                                \ 
  152   for( t = 0; t < ths->d; t++)                                                  \ 
  153   nfft_free( sin_vec[t]);                                                          \ 
  154   nfft_free( sin_vec);                                                               \ 
  159 #define MACRO_ndst_init__sin_vec                                                \ 
  161   for( t = 0; t < ths->d; t++)                                                  \ 
  163     cos_x[t] = cos( 2.0 * PI * NODE(j,t));                                      \ 
  164     sin_vec[t][0] = sin( 2.0 * PI * NODE(j,t));                                 \ 
  165     sin_vec[t][1] = sin( 4.0 * PI * NODE(j,t));                                 \ 
  166     for( k = 2; k < ths->N[t] - 1; k++)                                         \ 
  167       sin_vec[t][k] = 2.0 * cos_x[t] * sin_vec[t][k-1]                          \ 
  173 #define MACRO_ndst_init__k__sin_k( which_one)                                   \ 
  176   for( t = 0; t < ths->d; t++)                                                  \ 
  179   for( t = 0; t < ths->d; t++)                                                  \ 
  181     sin_k[t+1] = sin_k[t] * MACRO_ ##which_one;                                 \ 
  186 #define MACRO_ndst_count__k__sin_k( which_one)                                  \ 
  190   while( ( ka[i] == ths->N[i] - 1) && ( i > 0))                                 \ 
  197   for( t = i; t < ths->d; t++)                                                  \ 
  198     sin_k[t+1] = sin_k[t] * MACRO_ ##which_one;                                 \ 
  202 #define MACRO_ndst_compute__trafo                                               \ 
  204   f[j] += f_hat[k] * sin_k[ths->d];                                             \ 
  207 #define MACRO_ndst_compute__adjoint                                             \ 
  209   f_hat[k] += f[j] * sin_k[ths->d];                                             \ 
  214 #define MACRO_ndst( which_one)                                                  \ 
  215   void nfst_ ## which_one ## _direct ( nfst_plan *ths)                                     \ 
  219     double sin_k[ths->d+1];                                                     \ 
  220     double cos_x[ths->d];                                                       \ 
  222     double *f     = ths->f;                                                     \ 
  223     double *f_hat = ths->f_hat;                                                 \ 
  225     MACRO_ndst_init_result_ ## which_one;                                       \ 
  228       for( j = 0; j < ths->M_total; j++)                                        \ 
  229         for( k = 0; k < ths->N_total; k++)                                      \ 
  231           sin_k[ths->d] = sin( 2.0 * PI * (k+1) * NODE(j,0));                   \ 
  232           MACRO_ndst_compute__ ## which_one;                                    \ 
  237         for( j = 0; j < ths->M_total; j++)                                      \ 
  239           MACRO_ndst_init__k__sin_k(without_sin_vec);                           \ 
  241           for( k = 0; k < ths->N_total; k++)                                    \ 
  243             MACRO_ndst_compute__ ## which_one;                                  \ 
  245             MACRO_ndst_count__k__sin_k(without_sin_vec);                        \ 
  251         MACRO_ndst_malloc__sin_vec;                                             \ 
  253         for( j = 0; j < ths->M_total; j++)                                      \ 
  255           MACRO_ndst_init__sin_vec;                                             \ 
  257           MACRO_ndst_init__k__sin_k(with_sin_vec);                              \ 
  259           for( k = 0; k < ths->N_total; k++)                                    \ 
  261             MACRO_ndst_compute__ ## which_one;                                  \ 
  263             MACRO_ndst_count__k__sin_k(with_sin_vec);                           \ 
  266         MACRO_ndst_free__sin_vec;                                               \ 
  291 #define MACRO_nfst__lower_boundary( j,act_dim)                                  \ 
  294     (LRINT(NODE((j),(act_dim)) * nfst_fftw_2N( ths->n[(act_dim)]))) - ths->m;   \ 
  297 #define MACRO_nfst_D_compute_A                                                  \ 
  299   g_hat[kg_plain[ths->d]] = f_hat[k_L] * c_phi_inv_k[ths->d];                   \ 
  302 #define MACRO_nfst_D_compute_T                                                  \ 
  304   f_hat[k_L] = g_hat[kg_plain[ths->d]] * c_phi_inv_k[ths->d];                   \ 
  308 #define MACRO_init__kg                                                          \ 
  310   for( t = 0; t < ths->d; t++)                                                  \ 
  317 #define MACRO_count__kg                                                         \ 
  321   while( ( kg[i] == ths->N[i] - 1) && ( i > 0))                                 \ 
  331 #define MACRO_update__c_phi_inv_k__lg_plain( which_one, which_phi)              \ 
  333   for( t = i; t < ths->d; t++) {                                                \ 
  334     MACRO__c_phi_inv_k( which_phi);                                             \ 
  335     kg_plain[t+1] = kg_plain[t] * ths->n[t] + kg[t];                            \ 
  340 #define MACRO__c_phi_inv_k( which_phi)                                          \ 
  342   c_phi_inv_k[t+1] = 0.5 * c_phi_inv_k[t] * MACRO_ ## which_phi;                \ 
  346 #define MACRO_nfst_D(which_one)                                                 \ 
  347 static inline void nfst_D_ ## which_one (nfst_plan *ths)                               \ 
  353   double c_phi_inv_k[ths->d+1];               \ 
  354   int kg_plain[ths->d+1];                     \ 
  356   double *g_hat, *f_hat;                      \ 
  358   g_hat = ths->g_hat;                                                           \ 
  359   f_hat = ths->f_hat;                                                           \ 
  361   MACRO_nfst_D_init_result_ ## which_one                                        \ 
  363   c_phi_inv_k[0] = 1;                                                           \ 
  368   if( ths->nfst_flags & PRE_PHI_HUT)                                            \ 
  370     for( k_L = 0; k_L < ths->N_total; k_L++)                                    \ 
  372       MACRO_update__c_phi_inv_k__lg_plain( which_one, with_PRE_PHI_HUT);        \ 
  374       MACRO_nfst_D_compute_ ## which_one;                                       \ 
  382     for( k_L = 0; k_L < ths->N_total; k_L++)                                    \ 
  384       MACRO_update__c_phi_inv_k__lg_plain( which_one, compute_PHI_HUT_INV);     \ 
  386       MACRO_nfst_D_compute_ ## which_one;                                       \ 
  405 #define MACRO_nfst_B_PRE_FULL_PSI_compute_A                                     \ 
  407   (*fj) += ths->psi[ix] * g[ths->psi_index_g[ix]];                              \ 
  410 #define MACRO_nfst_B_PRE_FULL_PSI_compute_T                                     \ 
  412   g[ths->psi_index_g[ix]] += ths->psi[ix] * (*fj);                              \ 
  417 #define MACRO_nfst_B_compute_A                                                  \ 
  419   (*fj) += phi_tilde[ths->d] * g[lg_plain[ths->d]];                             \ 
  422 #define MACRO_nfst_B_compute_T                                                  \ 
  424   g[lg_plain[ths->d]] += phi_tilde[ths->d] * (*fj);                             \ 
  429 #define MACRO_compute_lg_offset__count_lg( i0)                                  \ 
  435       (lb[(i0)] % nfst_fftw_2N( ths->n[(i0)])) + nfst_fftw_2N( ths->n[(i0)]);   \ 
  439     lg_offset[(i0)] = lb[(i0)] % nfst_fftw_2N( ths->n[(i0)]);                   \ 
  442   if( lg_offset[(i0)] > ths->n[(i0)]+1)                                         \ 
  443       lg_offset[(i0)] = -( nfst_fftw_2N( ths->n[(i0)]) - lg_offset[(i0)]);      \ 
  448 #define MACRO_set__lg__to__lg_offset                                            \ 
  450   if( lg_offset[i] <= 0)                                                        \ 
  452     lg[i] = -lg_offset[i];                                                      \ 
  457     lg[i] = +lg_offset[i];                                                      \ 
  464 #define MACRO_count__lg(dim)                                                    \ 
  467   if( ((lg[(dim)] == 0) || (lg[(dim)] == (ths->n[(dim)] + 1))) )                \ 
  468     count_lg[(dim)] *= -1;                                                      \ 
  470   lg[(dim)] += count_lg[(dim)];                                                 \ 
  475 #define MACRO_init_lb_lg_lc_phi_tilde_lg_plain( which_psi)                      \ 
  477   for( i = 0; i < ths->d; i++)                                                  \ 
  479     MACRO_nfst__lower_boundary( j, i);                                          \ 
  481     MACRO_compute_lg_offset__count_lg( i);                                      \ 
  482     MACRO_set__lg__to__lg_offset;                                               \ 
  488   for( t = 0; t < ths->d; t++)                                                  \ 
  492       lg_plain[t+1]  = lg_plain[t] * ths->n[t];                                 \ 
  493       phi_tilde[t+1] = 0.0;                                                     \ 
  496       if( lg[t] == ths->n[t]+1)                                                 \ 
  498         lg_plain[t+1]  = lg_plain[t] * ths->n[t] + ths->n[t]-1;                 \ 
  499         phi_tilde[t+1] = 0.0;                                                   \ 
  503         MACRO__phi_tilde( which_psi);                                           \ 
  504         lg_plain[t+1]  = lg_plain[t] * ths->n[t] + lg[t]-1;                     \ 
  513 #define MACRO_count__lg_lc                                                      \ 
  515   MACRO_count__lg( ths->d-1);                                                   \ 
  520   while( (lc[i] == NFST_SUMMANDS) && (i > 0))                                   \ 
  526     MACRO_count__lg( i - 1);                                                    \ 
  528     MACRO_set__lg__to__lg_offset;                                               \ 
  535 #define MACRO_update__phi_tilde__lg_plain( which_psi)                           \ 
  537   for( t = i; t < ths->d; t++)                                                  \ 
  539     if( (lg[t] != 0) && (lg[t] != ths->n[t]+1))                                 \ 
  541       MACRO__phi_tilde( which_psi);                                             \ 
  542       lg_plain[t+1] = lg_plain[t] * ths->n[t] + lg[t]-1;                        \ 
  545       phi_tilde[t+1] = 0.0;                                                     \ 
  551 #define MACRO__phi_tilde( which_psi)                                            \ 
  553   phi_tilde[t+1] = (double)count_lg[t] * phi_tilde[t] * MACRO_ ## which_psi;    \ 
  559 #define MACRO_nfst_B( which_one)                                                \ 
  560   static inline void nfst_B_ ## which_one ( nfst_plan *ths)                            \ 
  564     int lprod, l_L, ix;                   \ 
  567     int lg_offset[ths->d];                \ 
  568     int count_lg[ths->d];                 \ 
  569     int lg_plain[ths->d+1];               \ 
  571     double phi_tilde[ths->d+1];           \ 
  574     f = ths->f; g = ths->g;                                                     \ 
  576     MACRO_nfst_B_init_result_ ## which_one                                      \ 
  579     if( (ths->nfst_flags & PRE_PSI) && (ths->nfst_flags & PRE_FULL_PSI))        \ 
  581       for( ix = 0, j = 0, fj = &f[0]; j < ths->M_total; j++, fj += 1)           \ 
  582         for( l_L = 0; l_L < ths->psi_index_f[j]; l_L++, ix++)                   \ 
  584           MACRO_nfst_B_PRE_FULL_PSI_compute_ ## which_one;                      \ 
  592       for( t = 0, lprod = 1; t < ths->d; t++)                                   \ 
  593         lprod *= NFST_SUMMANDS;                                                 \ 
  596       if( ths->nfst_flags & PRE_PSI)                                            \ 
  598         for( j = 0, fj = &f[0]; j < ths->M_total; j++, fj += 1)                 \ 
  600           MACRO_init_lb_lg_lc_phi_tilde_lg_plain( with_PRE_PSI);                \ 
  602           for( l_L = 0; l_L < lprod; l_L++)                                     \ 
  604             MACRO_update__phi_tilde__lg_plain( with_PRE_PSI);                   \ 
  606             MACRO_nfst_B_compute_ ## which_one;                                 \ 
  608             MACRO_count__lg_lc;                                                 \ 
  617         for( j = 0, fj = &f[0]; j < ths->M_total; j++, fj += 1)                 \ 
  619           MACRO_init_lb_lg_lc_phi_tilde_lg_plain( compute_PSI);                 \ 
  621           for( l_L = 0; l_L < lprod; l_L++)                                     \ 
  623             MACRO_update__phi_tilde__lg_plain( compute_PSI);                    \ 
  625             MACRO_nfst_B_compute_ ## which_one;                                 \ 
  627             MACRO_count__lg_lc;                                                 \ 
  653   ths->g_hat = ths->g1;
 
  674   fftw_execute( ths->my_fftw_r2r_plan);
 
  698   ths->g_hat = ths->
g2;
 
  719   fftw_execute( ths->my_fftw_r2r_plan);
 
  740 void nfst_precompute_phi_hut( 
nfst_plan *ths)
 
  745   ths->c_phi_inv = (
double**)
nfft_malloc( ths->d * 
sizeof( 
double*));
 
  747   for( t = 0; t < ths->d; t++)
 
  749     ths->c_phi_inv[t] = (
double*)
nfft_malloc( ( ths->N[t] - 1) * 
sizeof( double));
 
  751     for( kg[t] = 0; kg[t] < ths->N[t] - 1; kg[t]++)
 
  753       ths->c_phi_inv[t][kg[t]] = MACRO_compute_PHI_HUT_INV;
 
  760 void nfst_precompute_psi( 
nfst_plan *ths)
 
  767   for (t = 0; t < ths->
d; t++)
 
  769     for(j = 0; j < ths->
M_total; j++)
 
  771       MACRO_nfst__lower_boundary( j, t);
 
  773       for( lc[t] = 0; lc[t] < NFST_SUMMANDS; lc[t]++)
 
  774         ths->
psi[(j * ths->
d + t) * NFST_SUMMANDS + lc[t]] = MACRO_compute_PSI;
 
  794   int lg_plain[ths->
d+1];               
 
  795   int count_lg[ths->
d];
 
  796   int lg_offset[ths->
d];
 
  801   double phi_tilde[ths->
d+1];
 
  803   int *index_g, *index_f;
 
  805   int ix, ix_old, size_psi;
 
  814     index_g  =    (
int*)
nfft_malloc( size_psi * 
sizeof( 
int));
 
  815     new_psi  = (
double*)
nfft_malloc( size_psi * 
sizeof( 
double));
 
  817     for( t = 0,lprod = 1; t < ths->
d; t++)
 
  819       lprod *= NFST_SUMMANDS;
 
  823     for( ix = 0, ix_old = 0, j = 0; j < ths->
M_total; j++)
 
  825       MACRO_init_lb_lg_lc_phi_tilde_lg_plain( with_PRE_PSI);
 
  827       for( l_L = 0; l_L < lprod; l_L++)
 
  829         MACRO_update__phi_tilde__lg_plain( with_PRE_PSI);
 
  831         if( fabs(phi_tilde[ths->
d]) > eps)
 
  833           index_g[ix] =  lg_plain[ths->
d];
 
  834           new_psi[ix] = phi_tilde[ths->
d];
 
  840             index_g   =    (
int*)realloc( index_g, size_psi * 
sizeof( 
int));
 
  841             new_psi   = (
double*)realloc( new_psi, size_psi * 
sizeof( 
double));
 
  848       index_f[j] = ix - ix_old;
 
  857     index_g       = (
int*)realloc( index_g, size_psi * 
sizeof( 
int));
 
  858     new_psi       = (
double*)realloc( new_psi, size_psi * 
sizeof( 
double));
 
  878   for( t = 0; t < ths->
d; t++)
 
  880     ths->
sigma[t] = ((
double)ths->
n[t] + 1) / ths->
N[t];
 
  883   ths->r2r_kind = (fftw_r2r_kind*) 
nfft_malloc ( ths->
d * 
sizeof( fftw_r2r_kind));
 
  884   for (t = 0; t < ths->
d; t++)
 
  885     ths->r2r_kind[t] = FFTW_RODFT00;
 
  900     nfst_precompute_phi_hut( ths);
 
  911     ths->nfst_full_psi_eps = pow(10, -10);
 
  925       ths->my_fftw_r2r_plan =
 
  926         fftw_plan_r2r( ths->
d, ths->
n, ths->
g1, ths->
g2, ths->r2r_kind, ths->
fftw_flags);
 
  930   ths->
mv_adjoint = (void (*) (
void* ))nfst_adjoint;
 
  933 void nfst_init( 
nfst_plan *ths, 
int d, 
int *N, 
int M_total)
 
  941   for(t = 0;t < d; t++)
 
  946   for( t = 0; t < d; t++)
 
  947     ths->
n[t] = 2 * X(next_power_of_2)( ths->
N[t]) - 1;
 
  959   nfst_init_help( ths);
 
  963 void nfst_init_m( 
nfst_plan *ths, 
int d, 
int *N, 
int M_total, 
int m)
 
  967   for( t = 0; t < d; t++)
 
  968     n[t] = nfst_fftw_2N( X(next_power_of_2)( N[t]));
 
  970   nfst_init_guru( ths, d, N, M_total, n, m, NFST_DEFAULT_FLAGS, FFTW_DEFAULT_FLAGS);
 
  974 void nfst_init_guru( 
nfst_plan *ths, 
int d, 
int *N,
 
  975      int M_total, 
int *n, 
int m,
 
  976      unsigned nfst_flags, 
unsigned fftw_flags)
 
  985   for( t = 0; t < d; t++)
 
  990   for( t = 0; t < d; t++)
 
  998   nfst_init_help( ths);
 
 1002 void nfst_init_1d( 
nfst_plan *ths, 
int N0, 
int M_total)
 
 1007   nfst_init( ths, 1, N, M_total);
 
 1010 void nfst_init_2d( 
nfst_plan *ths, 
int N0, 
int N1, 
int M_total)
 
 1016   nfst_init( ths, 2, N, M_total);
 
 1019 void nfst_init_3d( 
nfst_plan *ths, 
int N0, 
int N1, 
int N2, 
int M_total)
 
 1026   nfst_init( ths, 3, N, M_total);
 
 1035     fftw_destroy_plan( ths->my_fftw_r2r_plan);
 
 1056     for( t = 0; t < ths->
d; t++)
 
 1070   WINDOW_HELP_FINALIZE;