11/*
2-
3- Simple example of the 1D type-1 transform. To compile, run
4-
5- nvcc -o getting_started getting_started.cpp -lcufinufft
6-
7- followed by
8-
9- ./getting_started
10-
11- with the necessary paths set if the library is not installed in the standard
12- directories. If the library has been compiled in the standard way, this means
13-
14- export CPATH="${CPATH:+${CPATH}:}../../include"
15- export LIBRARY_PATH="${LIBRARY_PATH:+${LIBRARY_PATH}:}../../build"
16- export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}../../build"
17-
18- */
19-
20- #include < complex.h>
2+ Simple example of the 1D type-1 transform using std::complex.
3+ To compile:
4+ nvcc -o getting_started getting_started.cpp -lcufinufft
5+ */
6+
7+ #include < cmath>
8+ #include < complex>
9+ #include < cstdio>
10+ #include < cstdlib>
2111#include < cuComplex.h>
2212#include < cuda_runtime.h>
2313#include < cufinufft.h>
24- #include < math.h>
25- #include < stdio.h>
26- #include < stdlib.h>
14+ #include < vector>
2715
28- static const double PI = 3.141592653589793238462643383279502884 ;
16+ static constexpr double PI = 3.141592653589793238462643383279502884 ;
2917
3018int main () {
3119 // Problem size: number of nonuniform points (M) and grid size (N).
@@ -35,9 +23,9 @@ int main() {
3523 int64_t modes[1 ] = {N};
3624
3725 // Host pointers: frequencies (x), coefficients (c), and output (f).
38- float *x ;
39- float _Complex *c ;
40- float _Complex *f ;
26+ std::vector< float > x (M) ;
27+ std::vector<std:: complex < float >> c (M) ;
28+ std::vector<std:: complex < float >> f (N) ;
4129
4230 // Device pointers.
4331 float *d_x;
@@ -48,71 +36,61 @@ int main() {
4836
4937 // Manual calculation at a single point idx.
5038 int idx;
51- float _Complex f0;
52-
53- // Allocate the host arrays.
54- x = (float *)malloc (M * sizeof (float ));
55- c = (float _Complex *)malloc (M * sizeof (float _Complex ));
56- f = (float _Complex *)malloc (N * sizeof (float _Complex ));
57-
58- // Fill with random numbers. Frequencies must be in the interval [-pi, pi)
59- // while strengths can be any value.
60- srand (0 );
39+ std::complex <float > f0;
6140
41+ // Fill with random numbers.
42+ std::srand (42 );
6243 for (int j = 0 ; j < M; ++j) {
63- x[j] = 2 * PI * (((float )rand ()) / RAND_MAX - 1 );
64- c[j] =
65- (2 * ((float )rand ()) / RAND_MAX - 1 ) + I * (2 * ((float )rand ()) / RAND_MAX - 1 );
44+ x[j] = 2 * PI * ((float )std::rand () / RAND_MAX - 1 );
45+ float re = 2 * ((float )std::rand ()) / RAND_MAX - 1 ;
46+ float im = 2 * ((float )std::rand ()) / RAND_MAX - 1 ;
47+ c[j] = std::complex <float >(re, im);
6648 }
6749
68- // Allocate the device arrays and copy the x and c arrays .
50+ // Allocate the device arrays and copy x and c.
6951 cudaMalloc (&d_x, M * sizeof (float ));
70- cudaMalloc (&d_c, M * sizeof (float _Complex ));
71- cudaMalloc (&d_f, N * sizeof (float _Complex ));
52+ cudaMalloc (&d_c, M * sizeof (cuFloatComplex));
53+ cudaMalloc (&d_f, N * sizeof (cuFloatComplex));
54+
55+ std::vector<cuFloatComplex> c_dev (M);
56+ for (int j = 0 ; j < M; ++j) c_dev[j] = make_cuFloatComplex (c[j].real (), c[j].imag ());
7257
73- cudaMemcpy (d_x, x, M * sizeof (float ), cudaMemcpyHostToDevice);
74- cudaMemcpy (d_c, c , M * sizeof (float _Complex ), cudaMemcpyHostToDevice);
58+ cudaMemcpy (d_x, x. data () , M * sizeof (float ), cudaMemcpyHostToDevice);
59+ cudaMemcpy (d_c, c_dev. data () , M * sizeof (cuFloatComplex ), cudaMemcpyHostToDevice);
7560
76- // Make the cufinufft plan for a 1D type-1 transform with six digits of
77- // tolerance.
78- cufinufftf_makeplan (1 , 1 , modes, 1 , 1 , 1e-6 , &plan, NULL );
61+ // Make the cufinufft plan for 1D type-1 transform.
62+ cufinufftf_makeplan (1 , 1 , modes, 1 , 1 , 1e-6 , &plan, nullptr );
7963
8064 // Set the frequencies of the nonuniform points.
81- cufinufftf_setpts (plan, M, d_x, NULL , NULL , 0 , NULL , NULL , NULL );
65+ cufinufftf_setpts (plan, M, d_x, nullptr , nullptr , 0 , nullptr , nullptr , nullptr );
8266
8367 // Actually execute the plan on the given coefficients and store the result
8468 // in the d_f array.
8569 cufinufftf_execute (plan, d_c, d_f);
8670
8771 // Copy the result back onto the host.
88- cudaMemcpy (f, d_f, N * sizeof (float _Complex ), cudaMemcpyDeviceToHost);
72+ cudaMemcpy (f. data () , d_f, N * sizeof (cuFloatComplex ), cudaMemcpyDeviceToHost);
8973
9074 // Destroy the plan and free the device arrays after we're done.
9175 cufinufftf_destroy (plan);
92-
9376 cudaFree (d_x);
9477 cudaFree (d_c);
9578 cudaFree (d_f);
9679
9780 // Pick an index to check the result of the calculation.
9881 idx = 4 * N / 7 ;
99-
100- printf (" f[%d] = %lf + %lfi\n " , idx, crealf (f[idx]), cimagf (f[idx]));
82+ printf (" f[%d] = %lf + %lfi\n " , idx, std::real (f[idx]), std::imag (f[idx]));
10183
10284 // Calculate the result manually using the formula for the type-1
10385 // transform.
10486 f0 = 0 ;
10587
88+ std::complex <float > I (-0.0 , 1.0 );
10689 for (int j = 0 ; j < M; ++j) {
107- f0 += c[j] * cexp (I * x[j] * (idx - N / 2 ));
90+ f0 += c[j] * std::exp (I * x[j] * float (idx - N / 2 ));
10891 }
10992
110- printf (" f0[%d] = %lf + %lfi\n " , idx, crealf (f0), cimagf (f0));
111-
112- // Finally free the host arrays.
113- free (x);
114- free (c);
115- free (f);
93+ printf (" f0[%d] = %lf + %lfi\n " , idx, std::real (f0), std::imag (f0));
11694
11795 return 0 ;
11896}
0 commit comments