NFFT Logo 3.2.3
util.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: util.c 3896 2012-10-10 12:19:26Z tovo $ */
20 
25 #include "config.h"
26 
27 #include "infft.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <float.h>
32 #include <sys/time.h>
33 #include "cstripack.h"
34 #ifdef HAVE_COMPLEX_H
35 #include <complex.h>
36 #endif
37 
38 #ifdef _OPENMP
39 #include <omp.h>
40 #endif
41 
42 #include "nfft3.h"
43 #include "nfft3util.h"
44 #include "infft.h"
45 
46 double nfft_elapsed_seconds(ticks t1, ticks t0)
47 {
48  UNUSED(t1);
49  UNUSED(t0);
50  return elapsed(t1,t0) / TICKS_PER_SECOND;
51 }
52 
55 int nfft_prod_int(int *vec, int d)
56 {
57  int t, prod;
58 
59  prod=1;
60  for(t=0; t<d; t++)
61  prod *= vec[t];
62 
63  return prod;
64 }
65 
68 int nfst_prod_minus_a_int(int *vec, int a, int d)
69 {
70  int t, prod;
71 
72  prod=1;
73  for(t=0; t<d; t++)
74  prod *= vec[t]-a;
75 
76  return prod;
77 }
78 
81 int nfft_plain_loop(int *idx,int *N,int d)
82 {
83  int t,sum;
84 
85  sum = idx[0];
86  for (t = 1; t < d; t++)
87  sum = sum * N[t] + idx[t];
88 
89  return sum;
90 }
91 
94 double nfft_prod_real(double *vec,int d)
95 {
96  int t;
97  double prod;
98 
99  prod=1.0;
100  for(t=0; t<d; t++)
101  prod*=vec[t];
102 
103  return prod;
104 }
105 
106 static void bspline_help(int k, double x, double *scratch, int j, int ug,
107  int og, int r)
108 {
109  int i; /* row index of the de Boor scheme */
110  int idx; /* index in scratch */
111  double a; /* alpha of the de Boor scheme */
112 
113  /* computation of one column */
114  for (i = og + r - k + 1, idx = og; idx >= ug; i--, idx--)
115  {
116  a = ((R)(x - i)) / ((R)(k - j));
117  scratch[idx] = (1 - a) * scratch[idx-1] + a * scratch[idx];
118  }
119 } /* bspline_help */
120 
124 double nfft_bspline(int k, double x, double *scratch)
125 {
126  double result_value;
127  int r;
128  int g1,g2;
129  int j,idx,ug,og;
130  double a;
132  result_value=0.0;
133  if(0<x && x<k)
134  {
135  /* using symmetry around k/2 */
136  if((k-x)<x) x=k-x;
137 
138  r=(int)(ceil(x)-1.0);
139 
140  for(idx=0; idx<k; idx++)
141  scratch[idx]=0.0;
142 
143  scratch[k-r-1]=1.0;
144 
145  /* bounds of the algorithm */
146  g1 = r;
147  g2 = k - 1 - r;
148  ug = g2;
149 
150  /* g1<=g2 holds */
151 
152  for(j=1, og=g2+1; j<=g1; j++, og++)
153  {
154  a = (x - r + k - 1 - og)/(k - j);
155  scratch[og] = (1 - a) * scratch[og-1];
156  bspline_help(k,x,scratch,j,ug+1,og-1,r);
157  a = (x - r + k - 1 - ug)/(k - j);
158  scratch[ug] = a * scratch[ug];
159  }
160  for(og-- ; j<=g2; j++)
161  {
162  bspline_help(k,x,scratch,j,ug+1,og,r);
163  a = (x - r + k - 1 - ug)/(k - j);
164  scratch[ug] = a * scratch[ug];
165  }
166  for( ; j<k; j++)
167  {
168  ug++;
169  bspline_help(k,x,scratch,j,ug,og,r);
170  }
171  result_value = scratch[k-1];
172  }
173  return(result_value);
174 } /* bspline */
175 
178 double nfft_dot_complex(double _Complex *x, int n)
179 {
180  int k;
181  double dot;
182 
183  for(k=0,dot=0; k<n; k++)
184  dot+=conj(x[k])*x[k];
185 
186  return dot;
187 }
188 
191 double nfft_dot_double(double *x, int n)
192 {
193  int k;
194  double dot;
195 
196  for(k=0,dot=0; k<n; k++)
197  dot+=x[k]*x[k];
198 
199  return dot;
200 }
201 
202 
205 double nfft_dot_w_complex(double _Complex *x, double *w, int n)
206 {
207  int k;
208  double dot;
209 
210  for(k=0,dot=0.0; k<n; k++)
211  dot+=w[k]*conj(x[k])*x[k];
212 
213  return dot;
214 }
215 
218 double nfft_dot_w_double(double *x, double *w, int n)
219 {
220  int k;
221  double dot;
222 
223  for(k=0,dot=0.0; k<n; k++)
224  dot+=w[k]*x[k]*x[k];
225 
226  return dot;
227 }
228 
229 
233 double nfft_dot_w_w2_complex(double _Complex *x, double *w, double *w2, int n)
234 {
235  int k;
236  double dot;
237 
238  for(k=0,dot=0.0; k<n; k++)
239  dot+=w[k]*w2[k]*w2[k]*conj(x[k])*x[k];
240 
241  return dot;
242 }
243 
247 double nfft_dot_w2_complex(double _Complex *x, double *w2, int n)
248 {
249  int k;
250  double dot;
251 
252  for(k=0,dot=0.0; k<n; k++)
253  dot+=w2[k]*w2[k]*conj(x[k])*x[k];
254 
255  return dot;
256 }
257 
260 void nfft_cp_complex(double _Complex *x, double _Complex *y, int n)
261 {
262  int k;
263 
264  for(k=0;k<n;k++)
265  x[k]=y[k];
266 }
267 
270 void nfft_cp_double(double *x, double *y, int n)
271 {
272  int k;
273 
274  for(k=0;k<n;k++)
275  x[k]=y[k];
276 }
277 
280 void nfft_cp_a_complex(double _Complex *x, double a, double _Complex *y, int n)
281 {
282  int k;
283 
284  for(k=0;k<n;k++)
285  x[k]=a*y[k];
286 }
287 
290 void nfft_cp_a_double(double *x, double a, double *y, int n)
291 {
292  int k;
293 
294  for(k=0;k<n;k++)
295  x[k]=a*y[k];
296 }
297 
298 
301 void nfft_cp_w_complex(double _Complex *x, double *w, double _Complex *y, int n)
302 {
303  int k;
304 
305  for(k=0;k<n;k++)
306  x[k]=w[k]*y[k];
307 }
308 
311 void nfft_cp_w_double(double *x, double *w, double *y, int n)
312 {
313  int k;
314 
315  for(k=0;k<n;k++)
316  x[k]=w[k]*y[k];
317 }
318 
319 
320 
323 void nfft_upd_axpy_complex(double _Complex *x, double a, double _Complex *y, int n)
324 {
325  int k;
326 
327  for(k=0;k<n;k++)
328  x[k]=a*x[k]+y[k];
329 }
330 
333 void nfft_upd_axpy_double(double *x, double a, double *y, int n)
334 {
335  int k;
336 
337  for(k=0;k<n;k++)
338  x[k]=a*x[k]+y[k];
339 }
340 
341 
344 void nfft_upd_xpay_complex(double _Complex *x, double a, double _Complex *y, int n)
345 {
346  int k;
347 
348  for(k=0;k<n;k++)
349  x[k]+=a*y[k];
350 }
351 
354 void nfft_upd_xpay_double(double *x, double a, double *y, int n)
355 {
356  int k;
357 
358  for(k=0;k<n;k++)
359  x[k]+=a*y[k];
360 }
361 
362 
363 
366 void nfft_upd_axpby_complex(double _Complex *x, double a, double _Complex *y, double b, int n)
367 {
368  int k;
369 
370  for(k=0;k<n;k++)
371  x[k]=a*x[k]+b*y[k];
372 }
373 
376 void nfft_upd_axpby_double(double *x, double a, double *y, double b, int n)
377 {
378  int k;
379 
380  for(k=0;k<n;k++)
381  x[k]=a*x[k]+b*y[k];
382 }
383 
384 
387 void nfft_upd_xpawy_complex(double _Complex *x, double a, double *w, double _Complex *y, int n)
388 {
389  int k;
390 
391  for(k=0;k<n;k++)
392  x[k]+=a*w[k]*y[k];
393 }
394 
397 void nfft_upd_xpawy_double(double *x, double a, double *w, double *y, int n)
398 {
399  int k;
400 
401  for(k=0;k<n;k++)
402  x[k]+=a*w[k]*y[k];
403 }
404 
405 
406 
409 void nfft_upd_axpwy_complex(double _Complex *x, double a, double *w, double _Complex *y, int n)
410 {
411  int k;
412 
413  for(k=0;k<n;k++)
414  x[k]=a*x[k]+w[k]*y[k];
415 }
416 
419 void nfft_upd_axpwy_double(double *x, double a, double *w, double *y, int n)
420 {
421  int k;
422 
423  for(k=0;k<n;k++)
424  x[k]=a*x[k]+w[k]*y[k];
425 }
426 
427 
428 void nfft_fftshift_complex(double _Complex *x, int d, int* N)
429 {
430  int d_pre, d_act, d_post;
431  int N_pre, N_act, N_post;
432  int k_pre, k_act, k_post;
433  int k,k_swap;
434 
435  double _Complex x_swap;
436 
437  for(d_act=0;d_act<d;d_act++)
438  {
439  for(d_pre=0, N_pre=1;d_pre<d_act;d_pre++)
440  N_pre*=N[d_pre];
441 
442  N_act=N[d_act];
443 
444  for(d_post=d_act+1, N_post=1;d_post<d;d_post++)
445  N_post*=N[d_post];
446 
447  for(k_pre=0;k_pre<N_pre;k_pre++)
448  for(k_act=0;k_act<N_act/2;k_act++)
449  for(k_post=0;k_post<N_post;k_post++)
450  {
451  k=(k_pre*N_act+k_act)*N_post+k_post;
452  k_swap=(k_pre*N_act+k_act+N_act/2)*N_post+k_post;
453 
454  x_swap=x[k];
455  x[k]=x[k_swap];
456  x[k_swap]=x_swap;
457  }
458  }
459 }
460 
463 void nfft_vpr_int(int *x, int n, char *text)
464 {
465  int k;
466 
467  if(text!=NULL)
468  {
469  printf ("\n %s, adr=%p\n", text, (void*)x);
470  for (k=0; k<n; k++)
471  {
472  if (k%8==0)
473  printf("%6d.\t", k);
474  printf("%d,", x[k]);
475  if (k%8==7)
476  printf("\n");
477  }
478  if (n%8!=0)
479  printf("\n");
480  }
481  else
482  for (k=0; k<n; k++)
483  printf("%d,\n", x[k]);
484  fflush(stdout);
485 }
486 
488 void X(vpr_double)(R *x, const int n, const char *text)
489 {
490  int k;
491 
492  if (x == NULL)
493  {
494  printf("null pointer\n");
495  fflush(stdout);
496  exit(-1);
497  }
498 
499  if (text != NULL)
500  {
501  printf ("\n %s, adr=%p\n", text, (void*)x);
502 
503  for (k = 0; k < n; k++)
504  {
505  if (k%8 == 0)
506  printf("%6d.\t", k);
507 
508  printf("%+.1" FE ",", x[k]);
509 
510  if (k%8 == 7)
511  printf("\n");
512  }
513 
514  if (n%8 != 0)
515  printf("\n");
516  }
517  else
518  for (k = 0; k < n; k++)
519  printf("%+" FE ",\n", x[k]);
520 
521  fflush(stdout);
522 }
523 
525 void X(vpr_complex)(C *x, const int n, const char *text)
526 {
527  int k;
528 
529  if(text != NULL)
530  {
531  printf("\n %s, adr=%p\n", text, (void*)x);
532  for (k = 0; k < n; k++)
533  {
534  if (k%4 == 0)
535  printf("%6d.\t", k);
536 
537  printf("%+.1" FE "%+.1" FE "i,", CREAL(x[k]), CIMAG(x[k]));
538 
539  if (k%4==3)
540  printf("\n");
541  }
542  if (n%4!=0)
543  printf("\n");
544  }
545  else
546  for (k = 0; k < n; k++)
547  printf("%+" FE "%+" FE "i,\n", CREAL(x[k]), CIMAG(x[k]));
548 
549  fflush(stdout);
550 }
551 
552 void X(vrand_unit_complex)(C *x, const int n)
553 {
554  int k;
555 
556  for (k = 0; k < n; k++)
557  x[k] = nfft_drand48() + II*nfft_drand48();
558 }
559 
560 void X(vrand_shifted_unit_double)(R *x, const int n)
561 {
562  int k;
563 
564  for (k = 0; k < n; k++)
565  x[k] = nfft_drand48() - K(0.5);
566 }
567 
569 void X(voronoi_weights_1d)(R *w, R *x, const int M)
570 {
571  int j;
572 
573  w[0] = (x[1]-x[0])/K(2.0);
574 
575  for(j = 1; j < M-1; j++)
576  w[j] = (x[j+1]-x[j-1])/K(2.0);
577 
578  w[M-1] = (x[M-1]-x[M-2])/K(2.0);
579 }
580 
581 void nfft_voronoi_weights_S2(double *w, double *xi, int M)
582 {
583  double *x;
584  double *y;
585  double *z;
586  int j;
587  int k;
588  int el;
589  int Mlocal = M;
590  int lnew;
591  int ier;
592  int *list;
593  int *lptr;
594  int *lend;
595  int *near;
596  int *next;
597  double *dist;
598  int *ltri;
599  int *listc;
600  int nb;
601  double *xc;
602  double *yc;
603  double *zc;
604  double *rc;
605  double *vr;
606  int lp;
607  int lpl;
608  int kv;
609  double a;
610 
611  /* Allocate memory for auxilliary arrays. */
612  x = (double*)nfft_malloc(M * sizeof(double));
613  y = (double*)nfft_malloc(M * sizeof(double));
614  z = (double*)nfft_malloc(M * sizeof(double));
615 
616  list = (int*)nfft_malloc((6*M-12+1)*sizeof(int));
617  lptr = (int*)nfft_malloc((6*M-12+1)*sizeof(int));
618  lend = (int*)nfft_malloc((M+1)*sizeof(int));
619  near = (int*)nfft_malloc((M+1)*sizeof(int));
620  next = (int*)nfft_malloc((M+1)*sizeof(int));
621  dist = (double*)nfft_malloc((M+1)*sizeof(double));
622  ltri = (int*)nfft_malloc((6*M+1)*sizeof(int));
623  listc = (int*)nfft_malloc((6*M-12+1)*sizeof(int));
624  xc = (double*)nfft_malloc((2*M-4+1)*sizeof(double));
625  yc = (double*)nfft_malloc((2*M-4+1)*sizeof(double));
626  zc = (double*)nfft_malloc((2*M-4+1)*sizeof(double));
627  rc = (double*)nfft_malloc((2*M-4+1)*sizeof(double));
628  vr = (double*)nfft_malloc(3*(2*M-4+1)*sizeof(double));
629 
630  /* Convert from spherical Coordinates in [0,1/2]x[-1/2,1/2) to Cartesian
631  * coordinates. */
632  for (k = 0; k < M; k++)
633  {
634  x[k] = sin(2.0*PI*xi[2*k+1])*cos(2.0*PI*xi[2*k]);
635  y[k] = sin(2.0*PI*xi[2*k+1])*sin(2.0*PI*xi[2*k]);
636  z[k] = cos(2.0*PI*xi[2*k+1]);
637  }
638 
639  /* Generate Delaunay triangulation. */
640  trmesh_(&Mlocal, x, y, z, list, lptr, lend, &lnew, near, next, dist, &ier);
641 
642  /* Check error flag. */
643  if (ier == 0)
644  {
645  /* Get Voronoi vertices. */
646  crlist_(&Mlocal, &Mlocal, x, y, z, list, lend, lptr, &lnew, ltri, listc, &nb, xc,
647  yc, zc, rc, &ier);
648 
649  if (ier == 0)
650  {
651  /* Calcuate sizes of Voronoi regions. */
652  for (k = 0; k < M; k++)
653  {
654  /* Get last neighbour index. */
655  lpl = lend[k];
656  lp = lpl;
657 
658  j = 0;
659  vr[3*j] = x[k];
660  vr[3*j+1] = y[k];
661  vr[3*j+2] = z[k];
662 
663  do
664  {
665  j++;
666  /* Get next neighbour. */
667  lp = lptr[lp-1];
668  kv = listc[lp-1];
669  vr[3*j] = xc[kv-1];
670  vr[3*j+1] = yc[kv-1];
671  vr[3*j+2] = zc[kv-1];
672  /* fprintf(stderr, "lp = %ld\t", lp); */
673  } while (lp != lpl);
674 
675  a = 0;
676  for (el = 0; el < j; el++)
677  {
678  a += areas_(vr, &vr[3*(el+1)],&vr[3*(((el+1)%j)+1)]);
679  }
680 
681  w[k] = a;
682  }
683  }
684  }
685 
686  /* Deallocate memory. */
687  nfft_free(x);
688  nfft_free(y);
689  nfft_free(z);
690 
691  nfft_free(list);
692  nfft_free(lptr);
693  nfft_free(lend);
694  nfft_free(near);
695  nfft_free(next);
696  nfft_free(dist);
697  nfft_free(ltri);
698  nfft_free(listc);
699  nfft_free(xc);
700  nfft_free(yc);
701  nfft_free(zc);
702  nfft_free(rc);
703  nfft_free(vr);
704 }
705 
710 R X(modified_fejer)(const int N, const int kk)
711 {
712  return (K(2.0)/((R)(N*N))*(K(1.0)-FABS(K(2.0)*kk+K(1.0))/((R)N)));
713 }
714 
716 R X(modified_jackson2)(const int N, const int kk)
717 {
718  int kj;
719  const R n=(N/K(2.0)+K(1.0))/K(2.0);
720  R result, k;
721 
722  for (result = K(0.0), kj = kk; kj <= kk+1; kj++)
723  {
724  k = ABS(kj);
725 
726  if(k/n < K(1.0))
727  result += K(1.0) - (K(3.0)*k + K(6.0)*n*POW(k,K(2.0))
728  - K(3.0)*POW(k,K(3.0)))/(K(2.0)*n*(K(2.0)*POW(n,K(2.0))+K(1.0)));
729  else
730  result+= (K(2.0)*n-k)*(POW(2*n-k,K(2.0))-K(1.0))/(K(2.0)
731  *n*(K(2.0)*POW(n,K(2.0))+K(1.0)));
732  }
733 
734  return result;
735 }
736 
738 R X(modified_jackson4)(const int N, const int kk)
739 {
740  int kj;
741  const R n = (N/K(2.0)+K(3.0))/K(4.0), normalisation = (K(2416.0)*POW(n,K(7.0))
742  + K(1120.0)*POW(n,K(5.0)) + K(784.0)*POW(n,K(3.0)) + K(720.0)*n);
743  R result, k;
744 
745  for (result = K(0.0), kj = kk; kj <= kk + 1; kj++)
746  {
747  k = ABS(kj);
748 
749  if (k/n < K(1.0))
750  result += K(1.0) - (K(1260.0)*k + (K(1680.0)*POW(n, K(5.0))
751  + K(2240.0)*POW(n, K(3.0)) + K(2940.0)*n)*POW(k, K(2.0))
752  - K(1715.0)*POW(k, K(3.0)) - (K(560.0)*POW(n, K(3.0))
753  + K(1400.0)*n)*POW(k, K(4.0)) + K(490.0)*POW(k, K(5.0))
754  + K(140.0)*n*POW(k, K(6.0)) - K(35.0)*POW(k,K(7.0)))/normalisation;
755 
756  if ((K(1.0) <= k/n) && (k/n < K(2.0)))
757  result += ((K(2472.0)*POW(n, K(7.0)) + K(336.0)*POW(n, K(5.0))
758  + K(3528.0)*POW(n, K(3.0)) - K(1296.0)*n) - (K(392.0)*POW(n, K(6.0))
759  - K(3920.0)*POW(n, K(4.0)) + K(8232.0)*POW(n, K(2.0)) - K(756.0))*k
760  - (K(504.0)*POW(n, K(5.0)) + K(10080.0)*POW(n, K(3.0))
761  - K(5292.0)*n)*POW(k, K(2.0)) - (K(1960.0)*POW(n, K(4.0))
762  - K(7840.0)*POW(n, K(2.0)) + K(1029.0))*POW(k, K(3.0))
763  + (K(2520.0)*POW(n, K(3.0)) - K(2520.0)*n) * POW(k, K(4.0))
764  - (K(1176.0)*POW(n, K(2.0)) - K(294.0)) * POW(k, K(5.0))
765  + K(252.0)*n*POW(k, K(6.0)) - K(21.0)*POW(k, K(7.0)))/normalisation;
766 
767  if ((K(2.0) <= k/n) && (k/n < K(3.0)))
768  result += (-(K(1112.0)*POW(n, K(7.0)) - K(12880.0)*POW(n, K(5.0))
769  + K(7448.0)*POW(n, K(3.0)) - K(720.0)*n) + (K(12152.0)*POW(n, K(6.0))
770  - K(27440.0)*POW(n, K(4.0)) + K(8232.0)*POW(n, K(2.0)) - K(252.0))*k
771  - (K(19320.0)*POW(n, K(5.0)) - K(21280.0)*POW(n, K(3.0))
772  + K(2940.0)*n)*POW(k, K(2.0)) + (K(13720.0)*POW(n, K(4.0))
773  - K(7840.0)*POW(n, K(2.0)) + K(343.0))*POW(k, K(3.0))
774  - (K(5320.0)*POW(n, K(3.0)) - K(1400.0)*n)*POW(k, K(4.0))
775  + (K(1176.0)*POW(n, K(2.0)) - K(98.0))*POW(k, K(5.0))
776  - K(140.0)*n*POW(k, K(6.0)) + K(7.0) * POW(k, K(7.0)))/normalisation;
777 
778  if ((K(3.0) <= k/n) && (k/n < K(4.0)))
779  result += ((4*n-k)*(POW(4*n-k, K(2.0)) - K(1.0))*(POW(4*n-k, K(2.0))
780  - K(4.0))*(POW(4*n-k, K(2.0)) - K(9.0)))/normalisation;
781  }
782 
783  return result;
784 }
785 
787 R X(modified_sobolev)(const R mu, const int kk)
788 {
789  R result;
790  int kj, k;
791 
792  for (result = K(0.0), kj = kk; kj <= kk+1; kj++)
793  {
794  k = ABS(kj);
795  if (k == 0)
796  result += K(1.0);
797  else
798  result += POW((double)k,-K(2.0)*mu);
799  }
800 
801  return result;
802 }
803 
805 R X(modified_multiquadric)(const R mu, const R c, const int kk)
806 {
807  R result;
808  int kj, k;
809 
810  for (result = K(0.0), kj = kk; kj <= kk+1; kj++)
811  {
812  k = ABS(kj);
813  result += POW((double)(k*k + c*c), -mu);
814  }
815 
816  return result;
817 }
818 
819 static inline int scaled_modified_bessel_i_series(const R x, const R alpha,
820  const int nb, const int ize, R *b)
821 {
822  const R enmten = K(4.0)*nfft_float_property(NFFT_R_MIN);
823  R tempa = K(1.0), empal = K(1.0) + alpha, halfx = K(0.0), tempb = K(0.0);
824  int n, ncalc = nb;
825 
826  if (enmten < x)
827  halfx = x/K(2.0);
828 
829  if (alpha != K(0.0))
830  tempa = POW(halfx, alpha)/TGAMMA(empal);
831 
832  if (ize == 2)
833  tempa *= EXP(-x);
834 
835  if (K(1.0) < x + K(1.0))
836  tempb = halfx*halfx;
837 
838  b[0] = tempa + tempa*tempb/empal;
839 
840  if (x != K(0.0) && b[0] == K(0.0))
841  ncalc = 0;
842 
843  if (nb == 1)
844  return ncalc;
845 
846  if (K(0.0) < x)
847  {
848  R tempc = halfx, tover = (enmten + enmten)/x;
849 
850  if (tempb != K(0.0))
851  tover = enmten/tempb;
852 
853  for (n = 1; n < nb; n++)
854  {
855  tempa /= empal;
856  empal += K(1.0);
857  tempa *= tempc;
858 
859  if (tempa <= tover*empal)
860  tempa = K(0.0);
861 
862  b[n] = tempa + tempa*tempb/empal;
863 
864  if (b[n] == K(0.0) && n < ncalc)
865  ncalc = n;
866  }
867  }
868  else
869  for (n = 1; n < nb; n++)
870  b[n] = K(0.0);
871 
872  return ncalc;
873 }
874 
875 static inline void scaled_modified_bessel_i_normalize(const R x,
876  const R alpha, const int nb, const int ize, R *b, const R sum_)
877 {
878  const R enmten = K(4.0)*nfft_float_property(NFFT_R_MIN);
879  R sum = sum_, tempa;
880  int n;
881 
882  /* Normalize, i.e., divide all b[n] by sum */
883  if (alpha != K(0.0))
884  sum = sum * TGAMMA(K(1.0) + alpha) * POW(x/K(2.0), -alpha);
885 
886  if (ize == 1)
887  sum *= EXP(-x);
888 
889  tempa = enmten;
890 
891  if (K(1.0) < sum)
892  tempa *= sum;
893 
894  for (n = 1; n <= nb; n++)
895  {
896  if (b[n-1] < tempa)
897  b[n-1] = K(0.0);
898 
899  b[n-1] /= sum;
900  }
901 }
902 
950 int nfft_smbi(const R x, const R alpha, const int nb, const int ize, R *b)
951 {
952  /* machine dependent parameters */
953  /* NSIG - DECIMAL SIGNIFICANCE DESIRED. SHOULD BE SET TO */
954  /* IFIX(ALOG10(2)*NBIT+1), WHERE NBIT IS THE NUMBER OF */
955  /* BITS IN THE MANTISSA OF A WORKING PRECISION VARIABLE. */
956  /* SETTING NSIG LOWER WILL RESULT IN DECREASED ACCURACY */
957  /* WHILE SETTING NSIG HIGHER WILL INCREASE CPU TIME */
958  /* WITHOUT INCREASING ACCURACY. THE TRUNCATION ERROR */
959  /* IS LIMITED TO A RELATIVE ERROR OF T=.5*10**(-NSIG). */
960  /* ENTEN - 10.0 ** K, WHERE K IS THE LARGEST int SUCH THAT */
961  /* ENTEN IS MACHINE-REPRESENTABLE IN WORKING PRECISION. */
962  /* ENSIG - 10.0 ** NSIG. */
963  /* RTNSIG - 10.0 ** (-K) FOR THE SMALLEST int K SUCH THAT */
964  /* K .GE. NSIG/4. */
965  /* ENMTEN - THE SMALLEST ABS(X) SUCH THAT X/4 DOES NOT UNDERFLOW. */
966  /* XLARGE - UPPER LIMIT ON THE MAGNITUDE OF X WHEN IZE=2. BEAR */
967  /* IN MIND THAT IF ABS(X)=N, THEN AT LEAST N ITERATIONS */
968  /* OF THE BACKWARD RECURSION WILL BE EXECUTED. */
969  /* EXPARG - LARGEST WORKING PRECISION ARGUMENT THAT THE LIBRARY */
970  /* EXP ROUTINE CAN HANDLE AND UPPER LIMIT ON THE */
971  /* MAGNITUDE OF X WHEN IZE=1. */
972  const int nsig = MANT_DIG + 2;
973  const R enten = nfft_float_property(NFFT_R_MAX);
974  const R ensig = POW(K(10.0),(R)nsig);
975  const R rtnsig = POW(K(10.0),-CEIL((R)nsig/K(4.0)));
976  const R xlarge = K(1E4);
977  const R exparg = FLOOR(LOG(POW(K(R_RADIX),K(DBL_MAX_EXP-1))));
978 
979  /* System generated locals */
980  int l, n, nend, magx, nbmx, ncalc, nstart;
981  R p, em, en, sum, pold, test, empal, tempa, tempb, tempc, psave, plast, tover,
982  emp2al, psavel;
983 
984  magx = LRINT(FLOOR(x));
985 
986  /* return if x, nb, or ize out of range */
987  if ( nb <= 0 || x < K(0.0) || alpha < K(0.0) || K(1.0) <= alpha
988  || ((ize != 1 || exparg < x) && (ize != 2 || xlarge < x)))
989  return (MIN(nb,0) - 1);
990 
991  /* 2-term ascending series for small x */
992  if (x < rtnsig)
993  return scaled_modified_bessel_i_series(x,alpha,nb,ize,b);
994 
995  ncalc = nb;
996  /* forward sweep, Olver's p-sequence */
997 
998  nbmx = nb - magx;
999  n = magx + 1;
1000 
1001  en = (R) (n+n) + (alpha+alpha);
1002  plast = K(1.0);
1003  p = en/x;
1004 
1005  /* significance test */
1006  test = ensig + ensig;
1007 
1008  if ((5*nsig) < (magx << 1))
1009  test = SQRT(test*p);
1010  else
1011  test /= POW(K(1.585),(R)magx);
1012 
1013  if (3 <= nbmx)
1014  {
1015  /* calculate p-sequence until n = nb-1 */
1016  tover = enten/ensig;
1017  nstart = magx+2;
1018  nend = nb - 1;
1019 
1020  for (n = nstart; n <= nend; n++)
1021  {
1022  en += K(2.0);
1023  pold = plast;
1024  plast = p;
1025  p = en*plast/x + pold;
1026  if (p > tover)
1027  {
1028  /* divide p-sequence by tover to avoid overflow. Calculate p-sequence
1029  * until 1 <= |p| */
1030  tover = enten;
1031  p /= tover;
1032  plast /= tover;
1033  psave = p;
1034  psavel = plast;
1035  nstart = n + 1;
1036 
1037  do
1038  {
1039  n++;
1040  en += K(2.0);
1041  pold = plast;
1042  plast = p;
1043  p = en*plast/x + pold;
1044  } while (p <= K(1.0));
1045 
1046  tempb = en/x;
1047 
1048  /* Backward test. Find ncalc as the largest n such that test is passed. */
1049  test = pold*plast*(K(0.5) - K(0.5)/(tempb * tempb))/ensig;
1050  p = plast*tover;
1051  n--;
1052  en -= K(2.0);
1053  nend = MIN(nb,n);
1054 
1055  for (ncalc = nstart; ncalc <= nend; ncalc++)
1056  {
1057  pold = psavel;
1058  psavel = psave;
1059  psave = en*psavel/x + pold;
1060  if (test < psave * psavel)
1061  break;
1062  }
1063 
1064  ncalc--;
1065  goto L80;
1066  }
1067  }
1068 
1069  n = nend;
1070  en = (R) (n+n) + (alpha+alpha);
1071 
1072  /* special significance test for 2 <= nbmx */
1073  test = FMAX(test,SQRT(plast*ensig)*SQRT(p+p));
1074  }
1075 
1076  /* calculate p-sequence until significance test is passed */
1077  do
1078  {
1079  n++;
1080  en += K(2.0);
1081  pold = plast;
1082  plast = p;
1083  p = en*plast/x + pold;
1084  } while (p < test);
1085 
1086  /* Initialize backward recursion and normalization sum. */
1087 L80:
1088  n++;
1089  en += K(2.0);
1090  tempb = K(0.0);
1091  tempa = K(1.0)/p;
1092  em = (R)(n-1);
1093  empal = em + alpha;
1094  emp2al = em - K(1.0) + (alpha+alpha);
1095  sum = tempa*empal*emp2al/em;
1096  nend = n-nb;
1097 
1098  if (nend < 0)
1099  {
1100  /* We have n <= nb. So store b[n] and set higher orders to zero */
1101  b[n-1] = tempa;
1102  nend = -nend;
1103  for (l = 1; l <= nend; ++l)
1104  b[n-1 + l] = K(0.0);
1105  }
1106  else
1107  {
1108  if (nend != 0)
1109  {
1110  /* recur backward via difference equation, calculating b[n] until n = nb */
1111  for (l = 1; l <= nend; ++l)
1112  {
1113  n--;
1114  en -= K(2.0);
1115  tempc = tempb;
1116  tempb = tempa;
1117  tempa = en*tempb/x + tempc;
1118  em -= K(1.0);
1119  emp2al -= K(1.0);
1120 
1121  if (n == 1)
1122  break;
1123 
1124  if (n == 2)
1125  emp2al = K(1.0);
1126 
1127  empal -= K(1.0);
1128  sum = (sum + tempa*empal)*emp2al/em;
1129  }
1130  }
1131 
1132  /* store b[nb] */
1133  b[n-1] = tempa;
1134 
1135  if (nb <= 1)
1136  {
1137  sum = sum + sum + tempa;
1138  scaled_modified_bessel_i_normalize(x,alpha,nb,ize,b,sum);
1139  return ncalc;
1140  }
1141 
1142  /* calculate and store b[nb-1] */
1143  n--;
1144  en -= 2.0;
1145  b[n-1] = en*tempa/x + tempb;
1146 
1147  if (n == 1)
1148  {
1149  sum = sum + sum + b[0];
1150  scaled_modified_bessel_i_normalize(x,alpha,nb,ize,b,sum);
1151  return ncalc;
1152  }
1153 
1154  em -= K(1.0);
1155  emp2al -= K(1.0);
1156 
1157  if (n == 2)
1158  emp2al = K(1.0);
1159 
1160  empal -= K(1.0);
1161  sum = (sum + b[n-1]*empal)*emp2al/em;
1162  }
1163 
1164  nend = n - 2;
1165 
1166  if (nend != 0)
1167  {
1168  /* Calculate and store b[n] until n = 2. */
1169  for (l = 1; l <= nend; ++l)
1170  {
1171  n--;
1172  en -= K(2.0);
1173  b[n-1] = en*b[n]/x + b[n+1];
1174  em -= K(1.0);
1175  emp2al -= K(1.0);
1176 
1177  if (n == 2)
1178  emp2al = K(1.0);
1179 
1180  empal -= K(1.0);
1181  sum = (sum + b[n-1]*empal)*emp2al/em;
1182  }
1183  }
1184 
1185  /* calculate b[1] */
1186  b[0] = K(2.0)*empal*b[1]/x + b[2];
1187  sum = sum + sum + b[0];
1188 
1189  scaled_modified_bessel_i_normalize(x,alpha,nb,ize,b,sum);
1190  return ncalc;
1191 }
1192 
1197 void nfft_assertion_failed(const char *s, int line, const char *file)
1198 {
1199  fflush(stdout);
1200  fprintf(stderr, "nfft: %s:%d: assertion failed: %s\n", file, line, s);
1201 #ifdef HAVE_ABORT
1202  /* Use abort function. */
1203  abort();
1204 #else
1205  /* Use exit function. */
1206  exit(EXIT_FAILURE);
1207 #endif
1208 }
1209 
1210 /* We declare drand48() and srand48() ourselves, if they are is not declared in
1211  * math.h (e.g. on SuSE 9.3), grrr. */
1212 #include "config.h"
1213 #if HAVE_DECL_DRAND48 == 0
1214  extern double drand48(void);
1215 #endif
1216 #if HAVE_DECL_SRAND48 == 0
1217  extern void srand48(long int);
1218 #endif
1219 
1220 double nfft_drand48(void)
1221 {
1222 #ifdef HAVE_DRAND48
1223  return drand48();
1224 #else
1225  return ((R)rand())/((R)RAND_MAX);
1226 #endif
1227 }
1228 
1229 void nfft_srand48(long int seed)
1230 {
1231 #ifdef HAVE_SRAND48
1232  srand48(seed);
1233 #else
1234  srand((unsigned int)seed);
1235 #endif
1236 }
1237 
1238 
1239 #define z_swap(_a_, _b_, _t_) do { (_t_) = (_a_); (_a_) = (_b_); (_b_) = (_t_); } while (0)
1240 
1246 static void nfft_sort_node_indices_sort_bubble(int n, int *keys)
1247 {
1248  int i, j, ti;
1249 
1250  for (i = 0; i < n; ++i)
1251  {
1252  j = i;
1253  while (j > 0 && keys[2 * j + 0] < keys[2 * (j - 1) + 0])
1254  {
1255  z_swap(keys[2 * j + 0], keys[2 * (j - 1) + 0], ti);
1256  z_swap(keys[2 * j + 1], keys[2 * (j - 1) + 1], ti);
1257  --j;
1258  }
1259  }
1260 }
1261 
1267 static void nfft_sort_node_indices_radix_count(int n, int *keys, int shift, int mask, int *counts)
1268 {
1269  int i, k;
1270 
1271  for (i = 0; i < n; ++i)
1272  {
1273  k = (keys[2 * i + 0] >> shift) & mask;
1274  ++counts[k];
1275  }
1276 }
1277 
1283 static void nfft_sort_node_indices_radix_rearrange(int n, int *keys_in, int *keys_out, int shift, int mask, int *displs)
1284 {
1285  int i, k;
1286 
1287  for (i = 0; i < n; ++i)
1288  {
1289  k = (keys_in[2 * i + 0] >> shift) & mask;
1290  keys_out[2 * displs[k] + 0] = keys_in[2 * i + 0];
1291  keys_out[2 * displs[k] + 1] = keys_in[2 * i + 1];
1292  ++displs[k];
1293  }
1294 }
1295 
1301 void nfft_sort_node_indices_radix_lsdf(int n, int *keys0, int *keys1, int rhigh)
1302 {
1303  const int rwidth = 9;
1304  const int radix_n = 1 << rwidth;
1305  const int radix_mask = radix_n - 1;
1306  const int rhigh_in = rhigh;
1307 
1308  const int tmax =
1309 #ifdef _OPENMP
1310  omp_get_max_threads();
1311 #else
1312  1;
1313 #endif
1314 
1315  int *from, *to, *tmp;
1316 
1317  int i, k, l, h;
1318  int lcounts[tmax * radix_n];
1319 
1320  int tid = 0, tnum = 1;
1321 
1322 
1323  from = keys0;
1324  to = keys1;
1325 
1326  while (rhigh >= 0)
1327  {
1328 #ifdef _OPENMP
1329  #pragma omp parallel private(tid, tnum, i, l, h)
1330  {
1331  tid = omp_get_thread_num();
1332  tnum = omp_get_num_threads();
1333 #endif
1334 
1335  for (i = 0; i < radix_n; ++i) lcounts[tid * radix_n + i] = 0;
1336 
1337  l = (tid * n) / tnum;
1338  h = ((tid + 1) * n) / tnum;
1339 
1340  nfft_sort_node_indices_radix_count(h - l, from + (2 * l), rhigh_in - rhigh, radix_mask, &lcounts[tid * radix_n]);
1341 #ifdef _OPENMP
1342  }
1343 #endif
1344 
1345  k = 0;
1346  for (i = 0; i < radix_n; ++i)
1347  {
1348  for (l = 0; l < tmax; ++l) lcounts[l * radix_n + i] = (k += lcounts[l * radix_n + i]) - lcounts[l * radix_n + i];
1349  }
1350 
1351 #ifdef _OPENMP
1352  #pragma omp parallel private(tid, tnum, i, l, h)
1353  {
1354  tid = omp_get_thread_num();
1355  tnum = omp_get_num_threads();
1356 #endif
1357 
1358  l = (tid * n) / tnum;
1359  h = ((tid + 1) * n) / tnum;
1360 
1361  nfft_sort_node_indices_radix_rearrange(h - l, from + (2 * l), to, rhigh_in - rhigh, radix_mask, &lcounts[tid * radix_n]);
1362 #ifdef _OPENMP
1363  }
1364 #endif
1365 
1366 /* print_keys(n, to);*/
1367 
1368  tmp = from;
1369  from = to;
1370  to = tmp;
1371 
1372  rhigh -= rwidth;
1373  }
1374 
1375  if (to == keys0) memcpy(to, from, n * 2 * sizeof(int));
1376 }
1377 
1383 void nfft_sort_node_indices_radix_msdf(int n, int *keys0, int *keys1, int rhigh)
1384 {
1385  const int rwidth = 9;
1386  const int radix_n = 1 << rwidth;
1387  const int radix_mask = radix_n - 1;
1388 
1389  const int tmax =
1390 #ifdef _OPENMP
1391  omp_get_max_threads();
1392 #else
1393  1;
1394 #endif
1395 
1396  int i, k, l, h;
1397  int lcounts[tmax * radix_n];
1398 
1399  int counts[radix_n], displs[radix_n];
1400 
1401  int tid = 0, tnum = 1;
1402 
1403 
1404  rhigh -= rwidth;
1405 
1406 #ifdef _OPENMP
1407  #pragma omp parallel private(tid, tnum, i, l, h)
1408  {
1409  tid = omp_get_thread_num();
1410  tnum = omp_get_num_threads();
1411 #endif
1412 
1413  for (i = 0; i < radix_n; ++i) lcounts[tid * radix_n + i] = 0;
1414 
1415  l = (tid * n) / tnum;
1416  h = ((tid + 1) * n) / tnum;
1417 
1418  nfft_sort_node_indices_radix_count(h - l, keys0 + (2 * l), rhigh + 1, radix_mask, &lcounts[tid * radix_n]);
1419 #ifdef _OPENMP
1420  }
1421 #endif
1422 
1423  k = 0;
1424  for (i = 0; i < radix_n; ++i)
1425  {
1426  for (l = 0; l < tmax; ++l) lcounts[l * radix_n + i] = (k += lcounts[l * radix_n + i]) - lcounts[l * radix_n + i];
1427 
1428  displs[i] = lcounts[0 * radix_n + i];
1429  if (i > 0) counts[i - 1] = displs[i] - displs[i - 1];
1430  }
1431  counts[radix_n - 1] = n - displs[radix_n - 1];
1432 
1433 #ifdef _OPENMP
1434  #pragma omp parallel private(tid, tnum, i, l, h)
1435  {
1436  tid = omp_get_thread_num();
1437  tnum = omp_get_num_threads();
1438 #endif
1439 
1440  l = (tid * n) / tnum;
1441  h = ((tid + 1) * n) / tnum;
1442 
1443  nfft_sort_node_indices_radix_rearrange(h - l, keys0 + (2 * l), keys1, rhigh + 1, radix_mask, &lcounts[tid * radix_n]);
1444 #ifdef _OPENMP
1445  }
1446 #endif
1447 
1448  memcpy(keys0, keys1, n * 2 * sizeof(int));
1449 
1450  if (rhigh >= 0)
1451  {
1452  for (i = 0; i < radix_n; ++i)
1453  {
1454  if (counts[i] > 1)
1455  {
1456  if (counts[i] > 256)
1457  nfft_sort_node_indices_radix_msdf(counts[i], keys0 + 2 * displs[i], keys1 + 2 * displs[i], rhigh);
1458  else
1459  nfft_sort_node_indices_sort_bubble(counts[i], keys0 + 2 * displs[i]);
1460  }
1461  }
1462  }
1463 }
1464 
1465 int nfft_get_num_threads(void)
1466 {
1467 #ifdef _OPENMP
1468  return nfft_get_omp_num_threads();
1469 #else
1470  return 1;
1471 #endif
1472 }
1473 
1474 #ifdef _OPENMP
1475 int nfft_get_omp_num_threads(void)
1476 {
1477  int nthreads;
1478  #pragma omp parallel default(shared)
1479  {
1480  int n = omp_get_num_threads();
1481  #pragma omp master
1482  {
1483  nthreads = n;
1484  }
1485  }
1486  return nthreads;
1487 }
1488 #endif

Generated on Tue Apr 30 2013 by Doxygen 1.8.1