NFFT Logo 3.2.3
nfct.c
1 /*
2  * Copyright (c) 2002, 2012 Jens Keiner, Stefan Kunis, Daniel Potts
3  *
4  * This program is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free Software
6  * Foundation; either version 2 of the License, or (at your option) any later
7  * version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 51
16  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 /* $Id: nfct.c 3896 2012-10-10 12:19:26Z tovo $ */
20 
21 /* Nonequispaced fast cosine transform
22  * Author: Steffen Klatt 2004-2006, Jens Keiner 2010 */
23 
24 #include <stdio.h>
25 #include <math.h>
26 #include <string.h>
27 #include <stdlib.h>
28 
29 #include "nfft3util.h"
30 #include "nfft3.h"
31 #include "infft.h"
32 
33 #undef X
34 #if defined(NFFT_SINGLE)
35 #define X(name) CONCAT(nfctf_, name)
36 #elif defined(NFFT_LDOUBLE)
37 #define X(name) CONCAT(nfctl_, name)
38 #else
39 #define X(name) CONCAT(nfct_, name)
40 #endif
41 
42 static inline int fftw_2N(int n)
43 {
44  return 2 * (n - 1);
45 }
46 
47 static inline int fftw_2N_rev(int n)
48 {
49  return (LRINT(K(0.5) * n) + 1);
50 }
51 
52 static inline int prod_int(int *vec, int d)
53 {
54  int t, prod = 1;
55 
56  for (t = 0; t < d; t++)
57  prod *= vec[t];
58 
59  return prod;
60 }
61 
62 /* handy shortcuts */
63 #define NFCT_DEFAULT_FLAGS PRE_PHI_HUT | PRE_PSI | MALLOC_X | MALLOC_F_HAT | \
64  MALLOC_F | FFTW_INIT | FFT_OUT_OF_PLACE
65 
66 #define FFTW_DEFAULT_FLAGS FFTW_ESTIMATE | FFTW_DESTROY_INPUT
67 
68 #define NFCT_SUMMANDS (2 * ths->m + 2)
69 #define NODE(p,r) (ths->x[(p) * ths->d + (r)])
70 
71 #define MACRO_ndct_init_result_trafo \
72  memset(f, 0, ths->M_total * sizeof(R));
73 #define MACRO_ndct_init_result_adjoint \
74  memset(f_hat, 0, ths->N_total * sizeof(R));
75 
76 #define MACRO_nfct_D_init_result_A \
77  memset(g_hat, 0, prod_int(ths->n, ths->d) * sizeof(R));
78 #define MACRO_nfct_D_init_result_T \
79  memset(f_hat, 0, ths->N_total * sizeof(R));
80 
81 #define MACRO_nfct_B_init_result_A \
82  memset(f, 0, ths->M_total * sizeof(R));
83 #define MACRO_nfct_B_init_result_T \
84  memset(g, 0, prod_int(ths->n, ths->d) * sizeof(R));
85 
86 #define NFCT_PRE_WINFUN(d) ths->N[d] = 2 * ths->N[d]; \
87  ths->n[d] = fftw_2N(ths->n[d]);
88 
89 #define NFCT_POST_WINFUN(d) ths->N[d] = LRINT(K(0.5) * ths->N[d]); \
90  ths->n[d] = fftw_2N_rev(ths->n[d]);
91 
92 #define NFCT_WINDOW_HELP_INIT WINDOW_HELP_INIT
93 
94 R X(phi_hut)(X(plan) *ths, int k, int d)
95 {
96  NFCT_PRE_WINFUN(d);
97  R phi_hut_tmp = PHI_HUT(k, d);
98  NFCT_POST_WINFUN(d);
99 
100  return phi_hut_tmp;
101 }
102 
103 R X(phi)(X(plan) *ths, R x, int d)
104 {
105  NFCT_PRE_WINFUN(d);
106  R phi_tmp = PHI(x, d);
107  NFCT_POST_WINFUN(d);
108 
109  return phi_tmp;
110 }
111 
112 #define MACRO_with_cos_vec cos_vec[t][ka[t]]
113 #define MACRO_without_cos_vec COS(K(2.0) * KPI * ka[t] * NODE(j,t))
114 
115 #define MACRO_with_PRE_PHI_HUT ths->c_phi_inv[t][kg[t]];
116 #define MACRO_compute_PHI_HUT_INV (K(1.0) / (X(phi_hut)(ths, kg[t], t)))
117 
118 #define MACRO_with_PRE_PSI ths->psi[(j * ths->d + t) * NFCT_SUMMANDS + lc[t]]
119 #define MACRO_compute_PSI X(phi)(ths, NODE(j,t) - ((R)(lc[t] + lb[t])) / (K(2.0)*((R)(ths->n[t])-K(1.0))/*(R)(fftw_2N(ths->n[t]))*/), t)
120 
136 #define MACRO_ndct_malloc__cos_vec \
137  R **cos_vec; \
138  cos_vec = (R**)Y(malloc)(ths->d * sizeof(R*)); \
139  for (t = 0; t < ths->d; t++) \
140  cos_vec[t] = (R*)Y(malloc)(ths->N[t] * sizeof(R));
141 
142 #define MACRO_ndct_free__cos_vec \
143 { \
144  /* free allocated memory */ \
145  for (t = 0; t < ths->d; t++) \
146  Y(free)(cos_vec[t]); \
147  Y(free)(cos_vec); \
148 }
149 
150 #define MACRO_ndct_init__cos_vec \
151 { \
152  for(t = 0; t < ths->d; t++) \
153  { \
154  cos_vec[t][0] = K(1.0); \
155  cos_vec[t][1] = COS(K(2.0) * KPI * NODE(j,t)); \
156  for (k = 2; k < ths->N[t]; k++) \
157  cos_vec[t][k] = K(2.0) * cos_vec[t][1] * cos_vec[t][k-1] - \
158  cos_vec[t][k-2]; \
159  } \
160 }
161 
162 #define MACRO_ndct_init__k__cos_k(which_one) \
163 { \
164  cos_k[0] = K(1.0); \
165  for (t = 0; t < ths->d; t++) \
166  ka[t] = 0; \
167 \
168  for (t = 0; t < ths->d; t++) \
169  { \
170  cos_k[t+1] = cos_k[t] * MACRO_ ##which_one; \
171  } \
172 }
173 
174 #define MACRO_ndct_count__k__cos_k(which_one) \
175 { \
176  ka[ths->d-1]++; \
177  i = ths->d - 1; \
178  while ((ka[i] == ths->N[i]) && (i > 0)) \
179  { \
180  ka[i - 1]++; \
181  ka[i] = 0; \
182  i--; \
183  } \
184  for (t = i; t < ths->d; t++) \
185  cos_k[t+1] = cos_k[t] * MACRO_ ##which_one; \
186 }
187 
188 #define MACRO_ndct_compute__trafo \
189 { \
190  f[j] += f_hat[k] * cos_k[ths->d]; \
191 }
192 
193 #define MACRO_ndct_compute__adjoint \
194 { \
195  f_hat[k] += f[j] * cos_k[ths->d]; \
196 }
197 
198 /* slow (trafo) transform */
199 #define MACRO_ndct(which_one) \
200  void X(which_one ## _direct) (X(plan) *ths) \
201  { \
202  int j, k, t, i; \
203  int ka[ths->d]; \
204  R cos_k[ths->d+1]; \
205  R *f = ths->f; \
206  R *f_hat = ths->f_hat; \
207 \
208  MACRO_ndct_init_result_ ## which_one; \
209  if (ths->d == 1) \
210  for (j = 0; j < ths->M_total; j++) \
211  { \
212  for (k = 0; k < ths->N[0]; k++) \
213  { \
214  cos_k[ths->d] = COS(K(2.0) * KPI * k * NODE(j,0)); \
215  MACRO_ndct_compute__ ## which_one; \
216  } \
217  } \
218  else \
219  { \
220  /* fast nfct_trafo_direct */ \
221  MACRO_ndct_malloc__cos_vec; \
222 \
223  for (j = 0; j < ths->M_total; j++) \
224  { \
225  MACRO_ndct_init__cos_vec; \
226  MACRO_ndct_init__k__cos_k(with_cos_vec); \
227 \
228  for (k = 0; k < ths->N_total; k++) \
229  { \
230  MACRO_ndct_compute__ ## which_one; \
231  MACRO_ndct_count__k__cos_k(with_cos_vec); \
232  } \
233  } \
234  MACRO_ndct_free__cos_vec; \
235  } \
236 } /* ndct_{trafo, adjoint} */
237 
238 MACRO_ndct(trafo)
239 MACRO_ndct(adjoint)
240 
255 #define MACRO_nfct__lower_boundary(j,act_dim) \
256 { \
257  lb[(act_dim)] = \
258  LRINT(NODE((j),(act_dim)) * fftw_2N(ths->n[(act_dim)])) - ths->m; \
259 }
260 
261 #define MACRO_nfct_D_compute_A \
262 { \
263  g_hat[kg_plain[ths->d]] = f_hat[k_L] * c_phi_inv_k[ths->d]; \
264 }
265 
266 #define MACRO_nfct_D_compute_T \
267 { \
268  f_hat[k_L] = g_hat[kg_plain[ths->d]] * c_phi_inv_k[ths->d]; \
269 }
270 
271 #define MACRO_init__kg \
272 { \
273  for (t = 0; t < ths->d; t++) \
274  kg[t] = 0; \
275  i = 0; \
276 }
277 
278 #define MACRO_count__kg \
279 { \
280 \
281  kg[ths->d - 1]++; \
282  i = ths->d - 1; \
283  while ((kg[i] == ths->N[i]) && (i > 0)) \
284  { \
285  kg[i - 1]++; \
286  kg[i] = 0; \
287  i--; \
288  } \
289 }
290 
291 #define MACRO_update__phi_inv_k__kg_plain(what_kind, which_phi) \
292 { \
293  for (t = i; t < ths->d; t++) \
294  { \
295  MACRO__c_phi_inv_k__ ## what_kind(which_phi); \
296  kg_plain[t+1] = kg_plain[t] * ths->n[t] + kg[t]; \
297  } \
298 }
299 
300 #define MACRO__c_phi_inv_k__A(which_phi) \
301 { \
302  if (kg[t] == 0) \
303  { \
304  c_phi_inv_k[t+1] = c_phi_inv_k[t] * MACRO_ ## which_phi; \
305  } \
306  else \
307  { \
308  c_phi_inv_k[t+1] = K(0.5) * c_phi_inv_k[t] * MACRO_ ## which_phi; \
309  } \
310 }
311 
312 #define MACRO__c_phi_inv_k__T(which_phi) \
313 { \
314  c_phi_inv_k[t+1] = c_phi_inv_k[t] * MACRO_ ## which_phi; \
315 }
316 
317 #define MACRO_nfct_D(which_one) \
318 static inline void D_ ## which_one (X(plan) *ths) \
319 { \
320  int k_L; /* plain index */ \
321  int i, t; \
322  int kg[ths->d]; /* multi index in g_hat,c_phi */ \
323  R c_phi_inv_k[ths->d+1]; /* postfix product of PHI_HUT_INV */ \
324  int kg_plain[ths->d+1]; /* postfix plain index */ \
325  R *g_hat, *f_hat; /* local copy */ \
326 \
327  g_hat = ths->g_hat; \
328  f_hat = ths->f_hat; \
329 \
330  MACRO_nfct_D_init_result_ ## which_one \
331 \
332  c_phi_inv_k[0] = K(1.0); \
333  kg_plain[0] = 0; \
334 \
335  MACRO_init__kg; \
336 \
337  if (ths->nfct_flags & PRE_PHI_HUT) \
338  for (k_L = 0; k_L < ths->N_total; k_L++) \
339  { \
340  MACRO_update__phi_inv_k__kg_plain(which_one, with_PRE_PHI_HUT); \
341  MACRO_nfct_D_compute_ ## which_one; \
342  MACRO_count__kg; \
343  } /* for (k_L) */ \
344  else \
345  for (k_L = 0; k_L < ths->N_total; k_L++) \
346  { \
347  MACRO_update__phi_inv_k__kg_plain(which_one,compute_PHI_HUT_INV); \
348  MACRO_nfct_D_compute_ ## which_one; \
349  MACRO_count__kg; \
350  } /* for(k_L) */ \
351 } /* nfct_D */
352 
353 MACRO_nfct_D(A)
354 MACRO_nfct_D(T)
355 
359 #define MACRO_nfct_B_PRE_FULL_PSI_compute_A \
360 { \
361  (*fj) += ths->psi[ix] * g[ths->psi_index_g[ix]]; \
362 }
363 
364 #define MACRO_nfct_B_PRE_FULL_PSI_compute_T \
365 { \
366  g[ths->psi_index_g[ix]] += ths->psi[ix] * (*fj); \
367 }
368 
369 #define MACRO_nfct_B_compute_A \
370 { \
371  (*fj) += phi_tilde[ths->d] * g[lg_plain[ths->d]]; \
372 }
373 
374 #define MACRO_nfct_B_compute_T \
375 { \
376  g[lg_plain[ths->d]] += phi_tilde[ths->d] * (*fj); \
377 }
378 
379 #define MACRO_compute_lg_offset__count_lg(i0) \
380 { \
381  /* determine index in g-array corresponding to lb[(i0)] */ \
382  if (lb[(i0)] < 0) \
383  lg_offset[(i0)] = \
384  (lb[(i0)] % fftw_2N(ths->n[(i0)])) + fftw_2N(ths->n[(i0)]); \
385  else \
386  lg_offset[(i0)] = lb[(i0)] % (fftw_2N(ths->n[(i0)])); \
387  if (lg_offset[(i0)] >= ths->n[(i0)]) \
388  lg_offset[(i0)] = -(fftw_2N(ths->n[(i0)]) - lg_offset[(i0)]); \
389 }
390 
391 #define MACRO_set__lg__to__lg_offset \
392 { \
393  if (lg_offset[i] <= 0) \
394  { \
395  lg[i] = -lg_offset[i]; \
396  count_lg[i] = -1; \
397  } \
398  else \
399  { \
400  lg[i] = +lg_offset[i]; \
401  count_lg[i] = +1; \
402  } \
403 }
404 
405 #define MACRO_count__lg(dim) \
406 { \
407  /* turn around if we hit one of the boundaries */ \
408  if ((lg[(dim)] == 0) || (lg[(dim)] == ths->n[(dim)]-1)) \
409  count_lg[(dim)] *= -1; \
410  /* move array index */ \
411  lg[(dim)] += count_lg[(dim)]; \
412 }
413 
414 #define MACRO_init_lb_lg_lc \
415 { \
416  for (i = 0; i < ths->d; i++) \
417  { \
418  MACRO_nfct__lower_boundary(j, i); \
419  MACRO_compute_lg_offset__count_lg(i); \
420  MACRO_set__lg__to__lg_offset; \
421  /* counter for lg */ \
422  lc[i] = 0; \
423  } \
424  i = 0; \
425 }
426 
427 #define MACRO_count__lg_lc \
428 { \
429  MACRO_count__lg(ths->d-1); \
430  lc[ths->d - 1]++; \
431  i = ths->d - 1; \
432  while ((lc[i] == NFCT_SUMMANDS) && (i > 0)) \
433  { \
434  lc[i - 1]++; \
435  lc[i] = 0; \
436  /* ansonsten lg[i-1] verschieben */ \
437  MACRO_count__lg(i - 1); \
438  /* lg[i] = anfangswert */ \
439  MACRO_set__lg__to__lg_offset; \
440  i--; \
441  } \
442 }
443 
444 #define MACRO_update_phi_tilde_lg_plain(which_one, which_psi) \
445 { \
446  for (t = i; t < ths->d; t++) \
447  { \
448  MACRO__phi_tilde__ ## which_one(which_psi); \
449  lg_plain[t+1] = lg_plain[t] * ths->n[t] + lg[t]; \
450  } \
451 }
452 
453 #define MACRO__phi_tilde__A(which_psi) \
454 { \
455  phi_tilde[t+1] = phi_tilde[t] * MACRO_ ## which_psi; \
456 }
457 
458 #define MACRO__phi_tilde__T(which_psi) \
459 { \
460  if(lg[t] == 0 || lg[t] == ths->n[t] - 1) \
461  { \
462  phi_tilde[t+1] = phi_tilde[t] * MACRO_ ## which_psi; \
463  } \
464  else \
465  { \
466  phi_tilde[t+1] = K(0.5) * phi_tilde[t] * MACRO_ ## which_psi; \
467  } \
468 }
469 
470 #define MACRO_nfct_B(which_one) \
471 static inline void B_ ## which_one (nfct_plan *ths) \
472 { /* MACRO_nfct_B */ \
473  int lb[ths->d]; /* multi band with respect to x_j */ \
474  int j, t, i; /* index nodes, help vars */ \
475  int lprod, l_L, ix; /* index one row of B */ \
476  int lc[ths->d]; /* multi index 0<=lc<2m+2 */ \
477  int lg[ths->d]; /* real index of g in array */ \
478  int lg_offset[ths->d]; /* offset in g according to u */ \
479  int count_lg[ths->d]; /* count summands (2m+2) */ \
480  int lg_plain[ths->d+1]; /* index of g in multi_array */ \
481  R *f, *g; /* local copy */ \
482  R phi_tilde[ths->d+1]; /* holds values for psi */ \
483  R *fj; /* pointer to final result */ \
484 \
485  f = ths->f; g = ths->g; \
486 \
487  MACRO_nfct_B_init_result_ ## which_one \
488 \
489  /* both flags are set */ \
490  if ((ths->nfct_flags & PRE_PSI)&&(ths->nfct_flags & PRE_FULL_PSI)) \
491  { \
492  for (ix = 0, j = 0, fj = &f[0]; j < ths->M_total; j++, fj += 1) \
493  for (l_L = 0; l_L < ths->psi_index_f[j]; l_L++, ix++) \
494  { \
495  MACRO_nfct_B_PRE_FULL_PSI_compute_ ## which_one; \
496  } \
497  } \
498  else \
499  { \
500  phi_tilde[0] = K(1.0); \
501  lg_plain[0] = 0; \
502 \
503  for (t = 0, lprod = 1; t < ths->d; t++) \
504  lprod *= NFCT_SUMMANDS; \
505 \
506  /* PRE_PSI flag is set */ \
507  if (ths->nfct_flags & PRE_PSI) \
508  for (j = 0, fj = &f[0]; j < ths->M_total; j++, fj += 1) \
509  { \
510  MACRO_init_lb_lg_lc; \
511  for (l_L = 0; l_L < lprod; l_L++) \
512  { \
513  MACRO_update_phi_tilde_lg_plain(which_one, with_PRE_PSI); \
514  MACRO_nfct_B_compute_ ## which_one; \
515  MACRO_count__lg_lc; \
516  } /* for(l_L) */ \
517  } /* for(j) */ \
518 \
519  /* no PSI flag is set */ \
520  else \
521  for (j = 0, fj = &f[0]; j < ths->M_total; j++, fj += 1) \
522  { \
523  MACRO_init_lb_lg_lc; \
524  for (l_L = 0; l_L < lprod; l_L++) \
525  { \
526  MACRO_update_phi_tilde_lg_plain(which_one,compute_PSI); \
527  MACRO_nfct_B_compute_ ## which_one; \
528  MACRO_count__lg_lc; \
529  } /* for (l_L) */ \
530  } /* for (j) */ \
531  } /* else (PRE_PSI && FULL_PRE_PSI) */ \
532 } /* nfct_B */
533 
534 MACRO_nfct_B(A)
535 MACRO_nfct_B(T)
536 
537 /* more memory, but faster */
538 #define MACRO_nfct_full_psi(which_one) \
539 static inline void full_psi__ ## which_one(nfct_plan *ths) \
540 { \
541  int t, i; /* index over all dimensions */ \
542  int j; /* node index */ \
543  int l_L; /* plain index 0 <= l_L < lprod */ \
544  int lc[ths->d]; /* multi index 0<=lj<u+o+1 */ \
545  int lg_plain[ths->d+1]; /* postfix plain index */ \
546  int count_lg[ths->d]; \
547  int lg_offset[ths->d]; \
548  int lg[ths->d]; \
549  int lprod; /* 'bandwidth' of matrix B */ \
550  int lb[ths->d]; /* depends on x_j */ \
551 \
552  R phi_tilde[ths->d+1]; \
553  R eps = ths->nfct_full_psi_eps; \
554 \
555  int *index_g, *index_f; \
556  R *new_psi; \
557  int ix, ix_old, size_psi; \
558 \
559  phi_tilde[0] = K(1.0); \
560  lg_plain[0] = 0; \
561  \
562  if (ths->nfct_flags & PRE_PSI) \
563  { \
564  size_psi = ths->M_total; \
565  index_f = (int*)Y(malloc)(ths->M_total * sizeof(int)); \
566  index_g = (int*)Y(malloc)(size_psi * sizeof(int)); \
567  new_psi = (R*)Y(malloc)(size_psi * sizeof(R)); \
568 \
569  for (t = 0,lprod = 1; t < ths->d; t++) \
570  { \
571  lprod *= NFCT_SUMMANDS; \
572  eps *= nfct_phi(ths, K(0.0), t); \
573  } \
574 \
575  for (ix = 0, ix_old = 0, j = 0; j < ths->M_total; j++) \
576  { \
577  MACRO_init_lb_lg_lc; \
578 \
579  for (l_L = 0; l_L < lprod; l_L++) \
580  { \
581  MACRO_update_phi_tilde_lg_plain(which_one, with_PRE_PSI); \
582 \
583  if (phi_tilde[ths->d] > eps) \
584  { \
585  index_g[ix] = lg_plain[ths->d]; \
586  new_psi[ix] = phi_tilde[ths->d]; \
587 \
588  ix++; \
589  if (ix == size_psi) \
590  { \
591  size_psi += ths->M_total; \
592  index_g = (int*)realloc(index_g, size_psi * sizeof(int)); \
593  new_psi = (R*)realloc(new_psi, size_psi * sizeof(R)); \
594  } \
595  } \
596 \
597  MACRO_count__lg_lc; \
598 \
599  } /* for (l_L) */ \
600 \
601  index_f[j] = ix - ix_old; \
602  ix_old = ix; \
603 \
604  } /* for(j) */ \
605 \
606  Y(free)(ths->psi); \
607  size_psi = ix; \
608  ths->size_psi = size_psi; \
609 \
610  index_g = (int*)realloc(index_g, size_psi * sizeof(int)); \
611  new_psi = (R*)realloc(new_psi, size_psi * sizeof(R)); \
612 \
613  ths->psi = new_psi; \
614  ths->psi_index_g = index_g; \
615  ths->psi_index_f = index_f; \
616 \
617  } /* if(PRE_PSI) */ \
618 }
619 
620 MACRO_nfct_full_psi(A)
621 MACRO_nfct_full_psi(T)
622 
623 /* user routines */
624 
625 void X(trafo)(X(plan) *ths)
626 {
627  /* use ths->my_fftw_r2r_plan */
628  ths->g_hat = ths->g1;
629  ths->g = ths->g2;
630 
631  /* form \f$ \hat g_k = \frac{\hat f_k}{c_k\left(\phi\right)} \text{ for }
632  * k \in I_N \f$ */
633  TIC(0)
634  D_A(ths);
635  TOC(0)
636 
637  /* Compute by d-variate discrete Fourier transform
638  * \f$ g_l = \sum_{k \in I_N} \hat g_k {\rm e}^{-2\pi {\rm i} \frac{kl}{n}}
639  * \text{ for } l \in I_n \f$ */
640  TIC(1)
641  Z(execute)(ths->my_fftw_r2r_plan);
642  TOC(1)
643 
644  if (ths->nfct_flags & PRE_FULL_PSI)
645  full_psi__A(ths);
646 
647  /* Set \f$ f_j = \sum_{l \in I_n,m(x_j)} g_l \psi\left(x_j-\frac{l}{n}\right)
648  * \text{ for } j=0,\hdots,M-1 \f$ */
649  TIC(2)
650  B_A(ths);
651  TOC(2)
652 
653  if (ths->nfct_flags & PRE_FULL_PSI)
654  {
655  Y(free)(ths->psi_index_g);
656  Y(free)(ths->psi_index_f);
657  }
658 } /* nfct_trafo */
659 
660 void X(adjoint)(X(plan) *ths)
661 {
662  /* use ths->my_fftw_plan */
663  ths->g_hat = ths->g2;
664  ths->g = ths->g1;
665 
666  if (ths->nfct_flags & PRE_FULL_PSI)
667  full_psi__T(ths);
668 
669  /* Set \f$ g_l = \sum_{j=0}^{M-1} f_j \psi\left(x_j-\frac{l}{n}\right)
670  * \text{ for } l \in I_n,m(x_j) \f$ */
671  TIC(2)
672  B_T(ths);
673  TOC(2)
674 
675  if (ths->nfct_flags & PRE_FULL_PSI)
676  {
677  Y(free)(ths->psi_index_g);
678  Y(free)(ths->psi_index_f);
679  }
680 
681  /* Compute by d-variate discrete cosine transform
682  * \f$ \hat g_k = \sum_{l \in I_n} g_l {\rm e}^{-2\pi {\rm i} \frac{kl}{n}}
683  * \text{ for } k \in I_N\f$ */
684  TIC(1)
685  Z(execute)(ths->my_fftw_r2r_plan);
686  TOC(1)
687 
688  /* Form \f$ \hat f_k = \frac{\hat g_k}{c_k\left(\phi\right)} \text{ for }
689  * k \in I_N \f$ */
690  TIC(0)
691  D_T(ths);
692  TOC(0)
693 
694 } /* nfct_adjoint */
695 
696 static inline void precompute_phi_hut(X(plan) *ths)
697 {
698  int kg[ths->d]; /* index over all frequencies */
699  int t; /* index over all dimensions */
700 
701  ths->c_phi_inv = (R**)Y(malloc)(ths->d * sizeof(R*));
702 
703  for (t = 0; t < ths->d; t++)
704  {
705  ths->c_phi_inv[t] = (R*)Y(malloc)(ths->N[t] * sizeof(R));
706 
707  for (kg[t] = 0; kg[t] < ths->N[t]; kg[t]++)
708  {
709  ths->c_phi_inv[t][kg[t]] = MACRO_compute_PHI_HUT_INV;
710  }
711  }
712 } /* nfct_phi_hut */
713 
714 void X(precompute_psi)(X(plan) *ths)
715 {
716  int t; /* index over all dimensions */
717  int j; /* index over all nodes */
718  int lc[ths->d]; /* index 0<=lj<u+o+1 */
719  int lb[ths->d]; /* depends on x_j */
720 
721  for (t = 0; t < ths->d; t++)
722  {
723  for (j = 0; j < ths->M_total; j++)
724  {
725  MACRO_nfct__lower_boundary(j, t);
726  for(lc[t] = 0; lc[t] < NFCT_SUMMANDS; lc[t]++)
727  ths->psi[(j * ths->d + t) * NFCT_SUMMANDS + lc[t]] = MACRO_compute_PSI;
728  } /* for (j) */
729  } /* for (t) */
730 } /* nfct_precompute_psi */
731 
732 static inline void init_help(X(plan) *ths)
733 {
734  int t; /* index over all dimensions */
735 
736  ths->N_total = prod_int(ths->N, ths->d);
737  ths->sigma = (R*)Y(malloc)(ths->d * sizeof(R));
738 
739  for (t = 0; t < ths->d; t++)
740  ths->sigma[t] = ((R)(ths->n[t] - 1)) / ths->N[t];
741 
742  /* Assign r2r transform kinds for each dimension */
743  ths->r2r_kind = (Z(r2r_kind)*)Y(malloc)(ths->d * sizeof (Z(r2r_kind)));
744  for (t = 0; t < ths->d; t++)
745  ths->r2r_kind[t] = FFTW_REDFT00;
746 
747  NFCT_WINDOW_HELP_INIT;
748 
749  if (ths->nfct_flags & MALLOC_X)
750  ths->x = (R*)Y(malloc)(ths->d * ths->M_total * sizeof(R));
751 
752  if (ths->nfct_flags & MALLOC_F_HAT)
753  ths->f_hat = (R*)Y(malloc)(ths->N_total * sizeof(R));
754 
755  if (ths->nfct_flags & MALLOC_F)
756  ths->f = (R*)Y(malloc)(ths->M_total * sizeof(R));
757 
758  if (ths->nfct_flags & PRE_PHI_HUT)
759  precompute_phi_hut(ths);
760 
761  /* NO FFTW_MALLOC HERE */
762  if (ths->nfct_flags & PRE_PSI)
763  {
764  ths->psi =
765  (R*)Y(malloc)(ths->M_total * ths->d * NFCT_SUMMANDS * sizeof(R));
766 
767  /* Set default for full_psi_eps */
768  ths->nfct_full_psi_eps = POW(K(10.0), K(-10.0));
769  }
770 
771  if (ths->nfct_flags & FFTW_INIT)
772  {
773  ths->g1 =
774  (R*)Y(malloc)(prod_int(ths->n, ths->d) * sizeof(R));
775 
776  if (ths->nfct_flags & FFT_OUT_OF_PLACE)
777  ths->g2 =
778  (R*) Y(malloc)(prod_int(ths->n, ths->d) * sizeof(R));
779  else
780  ths->g2 = ths->g1;
781 
782  ths->my_fftw_r2r_plan =
783  Z(plan_r2r)(ths->d, ths->n, ths->g1, ths->g2, ths->r2r_kind,
784  ths->fftw_flags);
785  }
786 
787  ths->mv_trafo = (void (*) (void* ))X(trafo);
788  ths->mv_adjoint = (void (*) (void* ))X(adjoint);
789 }
790 
791 void X(init)(X(plan) *ths, int d, int *N, int M_total)
792 {
793  int t;
794 
795  ths->d = d;
796  ths->M_total = M_total;
797  ths->N = (int*) Y(malloc)(ths->d * sizeof(int));
798 
799  for (t = 0;t < d; t++)
800  ths->N[t] = N[t];
801 
802  ths->n = (int*) Y(malloc)(ths->d * sizeof(int));
803 
804  for (t = 0; t < d; t++)
805  ths->n[t] = fftw_2N(Y(next_power_of_2)(ths->N[t]));
806 
807 /* Was soll dieser Ausdruck machen? Es handelt sich um eine Ganzzahl!
808 
809  WINDOW_HELP_ESTIMATE_m;
810 */
811  ths->nfct_flags = NFCT_DEFAULT_FLAGS;
812  ths->fftw_flags = FFTW_DEFAULT_FLAGS;
813 
814  init_help(ths);
815 }
816 
817 /* Was macht diese Funktion. Wird sie gebraucht? Bei NFST ist sie auch in
818  * nfft3.h deklariert.
819 void nfct_init_m(nfct_plan *ths, int d, int *N, int M_total, int m)
820 {
821  int t, n[d];
822 
823  for(t = 0; t < d; t++)
824  n[t] = fftw_2N(X(next_power_of_2)(N[t]));
825 
826  nfct_init_guru(ths, d, N, M_total, n, m, NFCT_DEFAULT_FLAGS, FFTW_DEFAULT_FLAGS);
827 }
828 */
829 
830 void X(init_guru)(X(plan) *ths, int d, int *N, int M_total, int *n, int m,
831  unsigned nfct_flags, unsigned fftw_flags)
832 {
833  int t; /* index over all dimensions */
834 
835  ths->d = d;
836  ths->M_total = M_total;
837 
838  ths->N = (int*)Y(malloc)(ths->d * sizeof(int));
839 
840  for (t = 0; t < d; t++)
841  ths->N[t] = N[t];
842 
843  ths->n = (int*)Y(malloc)(ths->d * sizeof(int));
844 
845  for (t = 0; t < d; t++)
846  ths->n[t] = n[t];
847 
848  ths->m = m;
849 
850  ths->nfct_flags = nfct_flags;
851  ths->fftw_flags = fftw_flags;
852 
853  init_help(ths);
854 }
855 
856 void X(init_1d)(X(plan) *ths, int N0, int M_total)
857 {
858  int N[1];
859 
860  N[0] = N0;
861  X(init)(ths, 1, N, M_total);
862 }
863 
864 void X(init_2d)(X(plan) *ths, int N0, int N1, int M_total)
865 {
866  int N[2];
867 
868  N[0] = N0;
869  N[1] = N1;
870  X(init)(ths, 2, N, M_total);
871 }
872 
873 void X(init_3d)(X(plan) *ths, int N0, int N1, int N2, int M_total)
874 {
875  int N[3];
876 
877  N[0] = N0;
878  N[1] = N1;
879  N[2] = N2;
880  X(init)(ths, 3, N, M_total);
881 }
882 
883 void X(finalize)(X(plan) *ths)
884 {
885  int t; /* dimension index*/
886 
887  if (ths->nfct_flags & FFTW_INIT)
888  {
889  Z(destroy_plan)(ths->my_fftw_r2r_plan);
890 
891  if (ths->nfct_flags & FFT_OUT_OF_PLACE)
892  Y(free)(ths->g2);
893 
894  Y(free)(ths->g1);
895  }
896 
897  /* NO FFTW_FREE HERE */
898  if (ths->nfct_flags & PRE_PSI)
899  {
900  Y(free)(ths->psi);
901  }
902 
903  if (ths->nfct_flags & PRE_PHI_HUT)
904  {
905  for (t = 0; t < ths->d; t++)
906  Y(free)(ths->c_phi_inv[t]);
907  Y(free)(ths->c_phi_inv);
908  }
909 
910  if (ths->nfct_flags & MALLOC_F)
911  Y(free)(ths->f);
912 
913  if(ths->nfct_flags & MALLOC_F_HAT)
914  Y(free)(ths->f_hat);
915 
916  if (ths->nfct_flags & MALLOC_X)
917  Y(free)(ths->x);
918 
919  WINDOW_HELP_FINALIZE;
920 
921  Y(free)(ths->N);
922  Y(free)(ths->n);
923  Y(free)(ths->sigma);
924 
925  Y(free)(ths->r2r_kind);
926 } /* nfct_finalize */

Generated on Tue Apr 30 2013 by Doxygen 1.8.1