The NFSFT routines depend on initially precomputed global data that limits the
maximum degree N
that can be used for computing transformations. This
precomputation has to be performed only once at program runtime regardless of
how many individual transform plans are used throughout the rest. This is done
by
nfsft_precompute(N,1000,0U,0U);
N
is the maximum degree that can be used in all subsequent transformations,
1000
is the threshold for the FPTs used internally, and
0U
and 0U
are optional flags for the NFSFT and FPT. If you
are unsure which values to use, leave the threshold at 1000
and
the flags at 0U
.
Initialisation of a plan is done by calling one of the
nfsft_init
-functions. We need no dimension parameter here, as in
the NFFT case. The simplest version is a call to nfsft_init
specifying only the bandwidth
and the number of nonequispaced nodes
.
For an application-owned variable nfsft_plan my_plan
the function call
is
nfsft_init(&my_plan,N,M);
After initialising a plan, one defines the nodes
in spherical coordinates in the member variable
my_plan.x
.
For consistency with the other modules and the conventions used there, we
use swapped and scaled spherical coordinates
my_plan.x[2*j] = /* your choice in [-0.5,0.5] */;
my_plan.x[2*j+1] = /* your choice in [0,0.5] */;
|
nfsft_precompute_x(&my_plan);
nfft_precompute_one_psi(&my_plan)
as explained above. You might modify
the precomputation strategy by passing the appropriate NFFT flags to one of the
more advanced nfsft_init
routines.
Setting the spherical Fourier coefficients
in my_plan.f_hat
should be done using the helper macro NFSFT_INDEX
. This reads
for (k = 0; k <= N; k++)
for (n = -k; n <= k; n++)
my_plan.f_hat[NFSFT_INDEX(k,n,&plan)] = /* your choice */;
|
NFSFT_INDEX
for setting
the spherical Fourier coefficients. If, in place of a NFSFT transformation, you
would like to perform an adjoint NFSFT transformation, you set
the values
in my_plan.f
as follows:
for (j = 0; j < M; j++)
my_plan.f[j] = /* your choice */;
|
The actual transforms are computed by calling either nfsft_trafo(&my_plan)
for the NFSFT (see Algorithm 3) or
nfsft_adjoint(&my_plan)
for the adjoint NFSFT (see Algorithm
4).
Remember, that you must make sure that my_plan.x
and my_plan.f_hat
or my_plan.f
have been initialised appropriately prior to calling the
corresponding transformation routine.
On execution, nfsft_trafo
overwrites my_plan.f
while
nfsft_adjoint
overwrites my_plan.f_hat
.
One only needs one plan for several transforms of the same kind,
i.e. transforms with equal initialisation parameters.
For comparison, the direct calculation of (3.1) and (3.5)
are done by ndsft_trafo
and ndsft_adjoint
, respectively.
All memory allocated by the init routine is deallocated by
nfsft_finalize(&my_plan);
nfsft_precompute
gets
freed by calling
nfsft_forget();
The library defines the structure nfsft_plan
, the most important
members are listed in Table 4.3.
The structure contains, public read-only (r) and public read-write (w)
members.
The user functions for the NFSFT are collected in Table
4.4.
|
|
Some more things should be kept in mind when using the NFSFT module:
nfsft_precompute
is always chosen as the
next power of two with respect to the specified maximum bandwidth
.
ndsft_trafo
and nfsft_trafo
, are allowed to destroy the
input f_hat
while the input x
is preserved. On the contrary,
the adjoint NDSFT and NFSFT transformations, ndsft_adjoint
and
nfsft_adjoint
, do not destroy the input f
and x
by
default. The desired behaviour can be assured by using the
NFSFT_PRESERVE_F_HAT
, NFSFT_PRESERVE_X
, NFSFT_PRESERVE_F
and
NFSFT_DESTROY_F_HAT
, NFSFT_DESTROY_X
, NFSFT_DESTROY_F
flags.