fftw3: FFTW Fortran type reference
7.3 FFTW Fortran type reference
===============================
The following are the most important type correspondences between the C
interface and Fortran:
* Plans ('fftw_plan' and variants) are 'type(C_PTR)' (i.e. an opaque
pointer).
* The C floating-point types 'double', 'float', and 'long double'
correspond to 'real(C_DOUBLE)', 'real(C_FLOAT)', and
'real(C_LONG_DOUBLE)', respectively. The C complex types
'fftw_complex', 'fftwf_complex', and 'fftwl_complex' correspond in
Fortran to 'complex(C_DOUBLE_COMPLEX)', 'complex(C_FLOAT_COMPLEX)',
and 'complex(C_LONG_DOUBLE_COMPLEX)', respectively. Just as in C
(Precision), the FFTW subroutines and types are prefixed
with 'fftw_', 'fftwf_', and 'fftwl_' for the different precisions,
and link to different libraries ('-lfftw3', '-lfftw3f', and
'-lfftw3l' on Unix), but use the _same_ include file 'fftw3.f03'
and the _same_ constants (all of which begin with 'FFTW_'). The
exception is 'long double' precision, for which you should _also_
include 'fftw3l.f03' (Extended and quadruple precision in
Fortran).
* The C integer types 'int' and 'unsigned' (used for planner flags)
become 'integer(C_INT)'. The C integer type 'ptrdiff_t' (e.g. in
the 64-bit Guru Interface) becomes 'integer(C_INTPTR_T)',
and 'size_t' (in 'fftw_malloc' etc.) becomes 'integer(C_SIZE_T)'.
* The 'fftw_r2r_kind' type (Real-to-Real Transform Kinds)
becomes 'integer(C_FFTW_R2R_KIND)'. The various constant values of
the C enumerated type ('FFTW_R2HC' etc.) become simply integer
constants of the same names in Fortran.
* Numeric array pointer arguments (e.g. 'double *') become
'dimension(*), intent(out)' arrays of the same type, or
'dimension(*), intent(in)' if they are pointers to constant data
(e.g. 'const int *'). There are a few exceptions where numeric
pointers refer to scalar outputs (e.g. for 'fftw_flops'), in which
case they are 'intent(out)' scalar arguments in Fortran too. For
the new-array execute functions (New-array Execute
Functions), the input arrays are declared 'dimension(*),
intent(inout)', since they can be modified in the case of in-place
or 'FFTW_DESTROY_INPUT' transforms.
* Pointer _return_ values (e.g 'double *') become 'type(C_PTR)'. (If
they are pointers to arrays, as for 'fftw_alloc_real', you can
convert them back to Fortran array pointers with the standard
intrinsic function 'c_f_pointer'.)
* The 'fftw_iodim' type in the guru interface (Guru vector and
transform sizes) becomes 'type(fftw_iodim)' in Fortran, a derived
data type (the Fortran analogue of C's 'struct') with three
'integer(C_INT)' components: 'n', 'is', and 'os', with the same
meanings as in C. The 'fftw_iodim64' type in the 64-bit guru
interface (64-bit Guru Interface) is the same, except that
its components are of type 'integer(C_INTPTR_T)'.
* Using the wisdom import/export functions from Fortran is a bit
tricky, and is discussed in Accessing the wisdom API from
Fortran. In brief, the 'FILE *' arguments map to 'type(C_PTR)',
'const char *' to 'character(C_CHAR), dimension(*), intent(in)'
(null-terminated!), and the generic read-char/write-char functions
map to 'type(C_FUNPTR)'.
You may be wondering if you need to search-and-replace
'real(kind(0.0d0))' (or whatever your favorite Fortran spelling of
"double precision" is) with 'real(C_DOUBLE)' everywhere in your program,
and similarly for 'complex' and 'integer' types. The answer is no; you
can still use your existing types. As long as these types match their C
counterparts, things should work without a hitch. The worst that can
happen, e.g. in the (unlikely) event of a system where
'real(kind(0.0d0))' is different from 'real(C_DOUBLE)', is that the
compiler will give you a type-mismatch error. That is, if you don't use
the 'iso_c_binding' kinds you need to accept at least the theoretical
possibility of having to change your code in response to compiler errors
on some future machine, but you don't need to worry about silently
compiling incorrect code that yields runtime errors.