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;