NFFT Logo 3.2.3
nfsoft.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: nfsoft.c 3919 2012-11-20 13:31:45Z grman $ */
20 
21 #include "config.h"
22 
23 #include <stdio.h>
24 #include <math.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #ifdef HAVE_COMPLEX_H
28 #include <complex.h>
29 #endif
30 #include "nfft3.h"
31 #include "nfft3util.h"
32 #include "infft.h"
33 #include "wigner.h"
34 
35 #define DEFAULT_NFFT_CUTOFF 6
36 #define FPT_THRESHOLD 1000
37 
38 static fpt_set SO3_fpt_init(int l, unsigned int flags, int kappa);
39 
40 void nfsoft_init(nfsoft_plan *plan, int N, int M)
41 {
42  nfsoft_init_advanced(plan, N, M, NFSOFT_MALLOC_X | NFSOFT_MALLOC_F
43  | NFSOFT_MALLOC_F_HAT);
44 }
45 
46 void nfsoft_init_advanced(nfsoft_plan *plan, int N, int M,
47  unsigned int nfsoft_flags)
48 {
49  nfsoft_init_guru(plan, N, M, nfsoft_flags, PRE_PHI_HUT | PRE_PSI | MALLOC_X
50  | MALLOC_F_HAT | MALLOC_F | FFTW_INIT | FFT_OUT_OF_PLACE,
51  DEFAULT_NFFT_CUTOFF, FPT_THRESHOLD);
52 }
53 
54 void nfsoft_init_guru(nfsoft_plan *plan, int B, int M,
55  unsigned int nfsoft_flags, unsigned int nfft_flags, int nfft_cutoff,
56  int fpt_kappa)
57 {
58  int N[3];
59  int n[3];
60 
61  N[0] = 2* B + 2;
62  N[1] = 2* B + 2;
63  N[2] = 2* B + 2;
64 
65  n[0] = 8* B ;
66  n[1] = 8* B ;
67  n[2] = 8* B ;
68 
69  nfft_init_guru(&plan->p_nfft, 3, N, M, n, nfft_cutoff, nfft_flags,
70  FFTW_ESTIMATE | FFTW_DESTROY_INPUT);
71 
72  if ((plan->p_nfft).nfft_flags & PRE_LIN_PSI)
73  {
75  }
76 
77  plan->N_total = B;
78  plan->M_total = M;
79  plan->fpt_kappa = fpt_kappa;
80  plan->flags = nfsoft_flags;
81 
82  if (plan->flags & NFSOFT_MALLOC_F_HAT)
83  {
84  plan->f_hat = (C*) nfft_malloc((B + 1) * (4* (B +1)*(B+1)-1)/3*sizeof(C));
85  if (plan->f_hat == NULL ) printf("Allocation failed!\n");
86  }
87 
88  if (plan->flags & NFSOFT_MALLOC_X)
89  {
90  plan->x = (R*) nfft_malloc(plan->M_total*3*sizeof(R));
91  if (plan->x == NULL ) printf("Allocation failed!\n");
92  }
93  if (plan->flags & NFSOFT_MALLOC_F)
94  {
95  plan->f = (C*) nfft_malloc(plan->M_total*sizeof(C));
96  if (plan->f == NULL ) printf("Allocation failed!\n");
97  }
98 
99  plan->wig_coeffs = (C*) nfft_malloc((X(next_power_of_2)(B)+1)*sizeof(C));
100  plan->cheby = (C*) nfft_malloc((2*B+2)*sizeof(C));
101  plan->aux = (C*) nfft_malloc((2*B+4)*sizeof(C));
102 
103  if (plan->wig_coeffs == NULL ) printf("Allocation failed!\n");
104  if (plan->cheby == NULL ) printf("Allocation failed!\n");
105  if (plan->aux == NULL ) printf("Allocation failed!\n");
106 
107  plan->mv_trafo = (void (*) (void* ))nfsoft_trafo;
108  plan->mv_adjoint = (void (*) (void* ))nfsoft_adjoint;
109 
110  plan->internal_fpt_set = SO3_fpt_init(plan->N_total, plan->flags, plan->fpt_kappa);
111 
112 }
113 
114 static void c2e(nfsoft_plan *my_plan, int even)
115 {
116  int j, N;
117 
119  N = 2* (my_plan ->N_total+1);
120 
122  my_plan->cheby[my_plan->N_total+1] = my_plan->wig_coeffs[0];
123  my_plan->cheby[0]=0.0;
124 
125  for (j=1;j<my_plan->N_total+1;j++)
126  {
127  my_plan->cheby[my_plan->N_total+1+j]=0.5* my_plan->wig_coeffs[j];
128  my_plan->cheby[my_plan->N_total+1-j]=0.5* my_plan->wig_coeffs[j];
129  }
130 
131  C *aux= (C*) nfft_malloc((N+2)*sizeof(C));
132 
133  for(j=1;j<N;j++)
134  aux[j]=my_plan->cheby[j];
135 
136  aux[0]=0.;
137  aux[N]=0.;
138 
139  if (even>0)
140  {
141  my_plan->cheby[0]=(C) (-1.)/(2.*_Complex_I) * aux[1];
142  for (j=1;j<N;j++)
143  {
144  my_plan->cheby[j]=(1./(2.*_Complex_I)*(aux[j+1]-aux[j-1]));
145  }
146 
147  }
148  free(aux);
149  aux = NULL;
150 }
151 
152 
153 static fpt_set SO3_fpt_init(int l, unsigned int flags, int kappa)
154 {
155  fpt_set set = 0;
156  int N, t, k_start, k_end, k, m;
157  int glo = 0;
158  R *alpha, *beta, *gamma;
159 
161  if (flags & NFSOFT_USE_DPT)
162  {
163  if (l < 2)
164  N = 2;
165  else
166  N = l;
167 
168  t = (int) log2(X(next_power_of_2)(N));
169 
170  }
171  else
172  {
174  if (l < 2)
175  N = 2;
176  else
177  N = X(next_power_of_2)(l);
178 
179  t = (int) log2(N);
180  }
181 
183  alpha = (R*) nfft_malloc((N + 2) * sizeof(R));
184  beta = (R*) nfft_malloc((N + 2) * sizeof(R));
185  gamma = (R*) nfft_malloc((N + 2) * sizeof(R));
186 
188  if (flags & NFSOFT_NO_STABILIZATION)
189  {
190  set = fpt_init((2* N + 1) * (2* N + 1), t, 0U | FPT_NO_STABILIZATION);
191  }
192  else
193  {
194  set = fpt_init((2* N + 1) * (2* N + 1), t, 0U);
195  }
196 
197  for (k = -N; k <= N; k++)
198  for (m = -N; m <= N; m++)
199  {
201  k_start = (ABS(k) >= ABS(m)) ? ABS(k) : ABS(m);
202  k_end = N;
203 
204  SO3_alpha_row(alpha, N, k, m);
205  SO3_beta_row(beta, N, k, m);
206  SO3_gamma_row(gamma, N, k, m);
207 
208  fpt_precompute(set, glo, alpha, beta, gamma, k_start, kappa);
209  glo++;
210  }
211 
212  free(alpha);
213  free(beta);
214  free(gamma);
215  alpha = NULL;
216  beta = NULL;
217  gamma = NULL;
218 
219  return set;
220 }
221 
222 static fpt_set SO3_single_fpt_init(int l, int k, int m, unsigned int flags, int kappa)
223 {
224  int N, t, k_start, k_end;
225  R *alpha, *beta, *gamma;
226  fpt_set set = 0;
227 
229  if (flags & NFSOFT_USE_DPT)
230  {
231  if (l < 2)
232  N = 2;
233  else
234  N = l;
235 
236  t = (int) log2(X(next_power_of_2)(N));
237 
238  }
239  else
240  {
242  if (l < 2)
243  N = 2;
244  else
245  N = X(next_power_of_2)(l);
246 
247  t = (int) log2(N);
248  }
249 
251  alpha = (R*) nfft_malloc((N + 2) * sizeof(R));
252  beta = (R*) nfft_malloc((N + 2) * sizeof(R));
253  gamma = (R*) nfft_malloc((N + 2) * sizeof(R));
254 
256  {
257  unsigned int fptflags = 0U
258  | IF(flags & NFSOFT_USE_DPT,FPT_NO_FAST_ALGORITHM,IF(t > 1,FPT_NO_DIRECT_ALGORITHM,0U))
259  | IF(flags & NFSOFT_NO_STABILIZATION,FPT_NO_STABILIZATION,0U);
260  set = fpt_init(1, t, fptflags);
261  }
262 
264  k_start = (ABS(k) >= ABS(m)) ? ABS(k) : ABS(m);
265  k_end = N;
266 
267  SO3_alpha_row(alpha, N, k, m);
268  SO3_beta_row(beta, N, k, m);
269  SO3_gamma_row(gamma, N, k, m);
270 
271  /*{
272  int rr;
273  for (rr = 0; rr < N + 2; rr++)
274  fprintf(stderr, "a[%4d] = %10e b[%4d] = %10e c[%4d] = %10e\n",rr,alpha[rr],rr,beta[rr],rr,gamma[rr]);
275  }*/
276 
277  fpt_precompute(set, 0, alpha, beta, gamma, k_start, kappa);
278 
279  free(alpha);
280  free(beta);
281  free(gamma);
282  alpha = NULL;
283  beta = NULL;
284  gamma = NULL;
285 
286  return set;
287 }
288 
289 void SO3_fpt(C *coeffs, fpt_set set, int l, int k, int m, unsigned int flags)
290 {
291  int N;
293  C* x;
295  C* y;
296 
297  int trafo_nr;
298  int k_start, k_end, j;
299  int function_values = 0;
300 
302  if (flags & NFSOFT_USE_DPT)
303  {
304  N = l;
305  if (l < 2)
306  N = 2;
307  }
308  else
309  {
310  if (l < 2)
311  N = 2;
312  else
313  N = X(next_power_of_2)(l);
314  }
315 
317  k_start = (ABS(k) >= ABS(m)) ? ABS(k) : ABS(m);
318  k_end = N;
319  trafo_nr = (N + k) * (2* N + 1) + (m + N);
320 
322  x = (C*) nfft_malloc((k_end + 1) * sizeof(C));
323 
324  for (j = 0; j <= k_end; j++)
325  x[j] = K(0.0);
326 
327 
328  for (j = 0; j <= l - k_start; j++)
329  {
330  x[j + k_start] = coeffs[j];
331  }
332  for (j = l - k_start + 1; j <= k_end - k_start; j++)
333  {
334  x[j + k_start] = K(0.0);
335  }
336 
338  y = (C*) nfft_malloc((k_end + 1) * sizeof(C));
339 
340  if (flags & NFSOFT_USE_DPT)
341  {
342  fpt_trafo_direct(set, trafo_nr, &x[k_start], y, k_end, 0U
343  | (function_values ? FPT_FUNCTION_VALUES : 0U));
344  }
345  else
346  {
347  fpt_trafo(set, trafo_nr, &x[k_start], y, k_end, 0U
348  | (function_values ? FPT_FUNCTION_VALUES : 0U));
349  }
350 
352  for (j = 0; j <= l; j++)
353  {
354  coeffs[j] = y[j];
355  }
356 
359  free(x);
360  free(y);
361  x = NULL;
362  y = NULL;
363 }
364 
365 void SO3_fpt_transposed(C *coeffs, fpt_set set, int l, int k, int m,
366  unsigned int flags)
367 {
368  int N, k_start, k_end, j;
369  int trafo_nr;
370  int function_values = 0;
372  C* x;
374  C* y;
375 
378  if (flags & NFSOFT_USE_DPT)
379  {
380  N = l;
381  if (l < 2)
382  N = 2;
383  }
384  else
385  {
386  if (l < 2)
387  N = 2;
388  else
389  N = X(next_power_of_2)(l);
390  }
391 
393  k_start = (ABS(k) >= ABS(m)) ? ABS(k) : ABS(m);
394  k_end = N;
395  trafo_nr = (N + k) * (2* N + 1) + (m + N);
396 
398  y = (C*) nfft_malloc((k_end + 1) * sizeof(C));
400  x = (C*) nfft_malloc((k_end + 1) * sizeof(C));
401 
402  for (j = 0; j <= l; j++)
403  {
404  y[j] = coeffs[j];
405  }
406  for (j = l + 1; j <= k_end; j++)
407  {
408  y[j] = K(0.0);
409  }
410 
411  if (flags & NFSOFT_USE_DPT)
412  {
413  fpt_transposed_direct(set, trafo_nr, &x[k_start], y, k_end, 0U
414  | (function_values ? FPT_FUNCTION_VALUES : 0U));
415  }
416  else
417  {
418  fpt_transposed(set, trafo_nr, &x[k_start], y, k_end, 0U
419  | (function_values ? FPT_FUNCTION_VALUES : 0U));
420  }
421 
422  for (j = 0; j <= l; j++)
423  {
424  coeffs[j] = x[j];
425  }
426 
428  free(x);
429  free(y);
430  x = NULL;
431  y = NULL;
432 }
433 
434 void nfsoft_precompute(nfsoft_plan *plan3D)
435 {
436  int j;
437  int N = plan3D->N_total;
438  int M = plan3D->M_total;
439 
442  for (j = 0; j < M; j++)
443  {
444  plan3D->p_nfft.x[3* j ] = plan3D->x[3* j + 2];
445  plan3D->p_nfft.x[3* j + 1] = plan3D->x[3* j ];
446  plan3D->p_nfft.x[3* j + 2] = plan3D->x[3* j + 1];
447  }
448 
449  for (j = 0; j < 3* plan3D ->p_nfft.M_total; j++)
450  {
451  plan3D->p_nfft.x[j] = plan3D->p_nfft.x[j] * (1 / (2* PI ));
452  }
453 
454  if ((plan3D->p_nfft).nfft_flags & FG_PSI)
455  {
456  nfft_precompute_one_psi(&(plan3D->p_nfft));
457  }
458  if ((plan3D->p_nfft).nfft_flags & PRE_PSI)
459  {
460  nfft_precompute_one_psi(&(plan3D->p_nfft));
461  }
462 
463 }
464 
465 void nfsoft_trafo(nfsoft_plan *plan3D)
466 {
467  int i, j, m, k, max, glo1, glo2;
468 
469  i = 0;
470  glo1 = 0;
471  glo2 = 0;
472 
473  int N = plan3D->N_total;
474  int M = plan3D->M_total;
475 
477  if (N == 0)
478  {
479  for (j = 0; j < M; j++)
480  plan3D->f[j] = plan3D->f_hat[0];
481  return;
482  }
483 
484  for (j = 0; j < plan3D->p_nfft.N_total; j++)
485  plan3D->p_nfft.f_hat[j] = 0.0;
486 
487  for (k = -N; k <= N; k++)
488  {
489  for (m = -N; m <= N; m++)
490  {
491 
492  max = (ABS(m) > ABS(k) ? ABS(m) : ABS(k));
493 
494  for (j = 0; j <= N - max; j++)
495  {
496  plan3D->wig_coeffs[j] = plan3D->f_hat[glo1];
497 
498  if ((plan3D->flags & NFSOFT_NORMALIZED))
499  {
500  plan3D->wig_coeffs[j] = plan3D->wig_coeffs[j] * (1. / (2. * PI))
501  * SQRT(0.5 * (2. * (max + j) + 1.));
502  }
503 
504  if ((plan3D->flags & NFSOFT_REPRESENT))
505  {
506  if ((k < 0) && (k % 2))
507  {
508  plan3D->wig_coeffs[j] = plan3D->wig_coeffs[j] * (-1);
509  }
510  if ((m < 0) && (m % 2))
511  plan3D->wig_coeffs[j] = plan3D->wig_coeffs[j] * (-1);
512 
513  if ((m + k) % 2)
514  plan3D->wig_coeffs[j] = plan3D->wig_coeffs[j] * (-1);
515 
516  }
517 
518  glo1++;
519  }
520 
521  for (j = N - max + 1; j < X(next_power_of_2)(N) + 1; j++)
522  plan3D->wig_coeffs[j] = 0.0;
523  //fprintf(stdout,"\n k= %d, m= %d \n",k,m);
524  SO3_fpt(plan3D->wig_coeffs, plan3D->internal_fpt_set, N, k, m, plan3D->flags);
525 
526  c2e(plan3D, ABS((k + m) % 2));
527 
528  for (i = 1; i <= 2* plan3D ->N_total + 2; i++)
529  {
530  plan3D->p_nfft.f_hat[NFSOFT_INDEX(k, m, i - N - 1, N) - 1]
531  = plan3D->cheby[i - 1];
532  //fprintf(stdout,"%f \t", plan3D->nfft_plan.f_hat[NFSOFT_INDEX(k,m,i-N-1,N)-1]);
533  //fprintf(stdout,"another index: %d for k=%d,m=%d,l=%d,N=%d \n", NFSOFT_INDEX(k,m,i-N-1,N)-1,k,m,i-N-1,N);
534  }
535 
536  }
537  }
538 
539  if (plan3D->flags & NFSOFT_USE_NDFT)
540  {
541  nfft_trafo_direct(&(plan3D->p_nfft));
542  }
543  else
544  {
545  nfft_trafo(&(plan3D->p_nfft));
546  }
547 
548  for (j = 0; j < plan3D->M_total; j++)
549  plan3D->f[j] = plan3D->p_nfft.f[j];
550 
551 }
552 
553 static void e2c(nfsoft_plan *my_plan, int even)
554 {
555  int N;
556  int j;
557 
559  N = 2* (my_plan ->N_total+1);
560  //nfft_vpr_complex(my_plan->cheby,N+1,"chebychev");
561 
562 
563  if (even>0)
564  {
565  //my_plan->aux[N-1]= -1/(2*I)* my_plan->cheby[N-2];
566  my_plan->aux[0]= 1/(2*_Complex_I)*my_plan->cheby[1];
567 
568  for(j=1;j<N-1;j++)
569  {
570  my_plan->aux[j]=1/(2*_Complex_I)*(my_plan->cheby[j+1]-my_plan->cheby[j-1]);
571 }
572 my_plan->aux[N-1]=1/(2*_Complex_I)*(-my_plan->cheby[j-1]);
573 
574 
575 for(j=0;j<N;j++)
576 {
577 my_plan->cheby[j]= my_plan->aux[j];
578 }
579 }
580 
581 my_plan->wig_coeffs[0]=my_plan->cheby[my_plan->N_total+1];
582 
583 for(j=1;j<=my_plan->N_total;j++)
584 {
585 my_plan->wig_coeffs[j]=0.5*(my_plan->cheby[my_plan->N_total+j+1]+my_plan->cheby[my_plan->N_total+1-j]);
586 }
587 
588 
589 
590 //nfft_vpr_complex(my_plan->wig_coeffs,my_plan->N_total,"chebychev ");
591 
592 }
593 
594 void nfsoft_adjoint(nfsoft_plan *plan3D)
595 {
596  int i, j, m, k, max, glo1, glo2;
597 
598  i = 0;
599  glo1 = 0;
600  glo2 = 0;
601 
602  int N = plan3D->N_total;
603  int M = plan3D->M_total;
604 
605  //nothing much to be done for polynomial degree 0
606  if (N == 0)
607  {
608  plan3D->f_hat[0]=0;
609  for (j = 0; j < M; j++)
610  plan3D->f_hat[0] += plan3D->f[j];
611  return;
612  }
613 
614  for (j = 0; j < M; j++)
615  {
616  plan3D->p_nfft.f[j] = plan3D->f[j];
617  }
618 
619  if (plan3D->flags & NFSOFT_USE_NDFT)
620  {
621  nfft_adjoint_direct(&(plan3D->p_nfft));
622  }
623  else
624  {
625  nfft_adjoint(&(plan3D->p_nfft));
626  }
627 
628  //nfft_vpr_complex(plan3D->nfft_plan.f_hat,plan3D->nfft_plan.N_total,"all results");
629 
630  glo1 = 0;
631 
632  for (k = -N; k <= N; k++)
633  {
634  for (m = -N; m <= N; m++)
635  {
636 
637  max = (ABS(m) > ABS(k) ? ABS(m) : ABS(k));
638 
639  for (i = 1; i < 2* plan3D ->N_total + 3; i++)
640  {
641  plan3D->cheby[i - 1] = plan3D->p_nfft.f_hat[NFSOFT_INDEX(k, m, i - N
642  - 1, N) - 1];
643  }
644 
645  //fprintf(stdout,"k=%d,m=%d \n",k,m);
646  //nfft_vpr_complex(plan3D->cheby,2*plan3D->N_total+2,"euler");
647  e2c(plan3D, ABS((k + m) % 2));
648 
649  //nfft_vpr_complex(plan3D->wig_coeffs,plan3D->N_total+1,"chebys");
650  SO3_fpt_transposed(plan3D->wig_coeffs, plan3D->internal_fpt_set, N, k, m,
651  plan3D->flags);
652  //nfft_vpr_complex(plan3D->wig_coeffs,plan3D->N_total+1,"wigners");
653  // SO3_fpt_transposed(plan3D->wig_coeffs,N,k,m,plan3D->flags,plan3D->fpt_kappa);
654 
655 
656  for (j = max; j <= N; j++)
657  {
658  if ((plan3D->flags & NFSOFT_REPRESENT))
659  {
660  if ((k < 0) && (k % 2))
661  {
662  plan3D->wig_coeffs[j] = -plan3D->wig_coeffs[j];
663  }
664  if ((m < 0) && (m % 2))
665  plan3D->wig_coeffs[j] = -plan3D->wig_coeffs[j];
666 
667  if ((m + k) % 2)
668  plan3D->wig_coeffs[j] = plan3D->wig_coeffs[j] * (-1);
669 
670  }
671 
672  plan3D->f_hat[glo1] = plan3D->wig_coeffs[j];
673 
674  if ((plan3D->flags & NFSOFT_NORMALIZED))
675  {
676  plan3D->f_hat[glo1] = plan3D->f_hat[glo1] * (1 / (2. * PI)) * SQRT(
677  0.5 * (2. * (j) + 1.));
678  }
679 
680  glo1++;
681  }
682 
683  }
684  }
685 }
686 
687 void nfsoft_finalize(nfsoft_plan *plan)
688 {
689  /* Finalise the nfft plan. */
690  nfft_finalize(&plan->p_nfft);
691  free(plan->wig_coeffs);
692  free(plan->cheby);
693  free(plan->aux);
694 
695  fpt_finalize(plan->internal_fpt_set);
696  plan->internal_fpt_set = NULL;
697 
698  if (plan->flags & NFSOFT_MALLOC_F_HAT)
699  {
700  //fprintf(stderr,"deallocating f_hat\n");
701  free(plan->f_hat);
702  }
703 
704  /* De-allocate memory for samples, if neccesary. */
705  if (plan->flags & NFSOFT_MALLOC_F)
706  {
707  //fprintf(stderr,"deallocating f\n");
708  free(plan->f);
709  }
710 
711  /* De-allocate memory for nodes, if neccesary. */
712  if (plan->flags & NFSOFT_MALLOC_X)
713  {
714  //fprintf(stderr,"deallocating x\n");
715  free(plan->x);
716  }
717 }
718 
719 int posN(int n, int m, int B)
720 {
721  int pos;
722 
723  if (n > -B)
724  pos = posN(n - 1, m, B) + B + 1 - MAX(ABS(m), ABS(n - 1));
725  else
726  pos = 0;
727  //(n > -B? pos=posN(n-1,m,B)+B+1-MAX(ABS(m),ABS(n-1)): pos= 0)
728  return pos;
729 }
730 

Generated on Tue Apr 30 2013 by Doxygen 1.8.1