@node Calling FFTW from Legacy Fortran, Upgrading from FFTW version 2, Calling FFTW from Modern Fortran, Top @chapter Calling FFTW from Legacy Fortran @cindex Fortran interface This chapter describes the interface to FFTW callable by Fortran code in older compilers not supporting the Fortran 2003 C interoperability features (@pxref{Calling FFTW from Modern Fortran}). This interface has the major disadvantage that it is not type-checked, so if you mistake the argument types or ordering then your program will not have any compiler errors, and will likely crash at runtime. So, greater care is needed. Also, technically interfacing older Fortran versions to C is nonstandard, but in practice we have found that the techniques used in this chapter have worked with all known Fortran compilers for many years. The legacy Fortran interface differs from the C interface only in the prefix (@samp{dfftw_} instead of @samp{fftw_} in double precision) and a few other minor details. This Fortran interface is included in the FFTW libraries by default, unless a Fortran compiler isn't found on your system or @code{--disable-fortran} is included in the @code{configure} flags. We assume here that the reader is already familiar with the usage of FFTW in C, as described elsewhere in this manual. The MPI parallel interface to FFTW is @emph{not} currently available to legacy Fortran. @menu * Fortran-interface routines:: * FFTW Constants in Fortran:: * FFTW Execution in Fortran:: * Fortran Examples:: * Wisdom of Fortran?:: @end menu @c ------------------------------------------------------- @node Fortran-interface routines, FFTW Constants in Fortran, Calling FFTW from Legacy Fortran, Calling FFTW from Legacy Fortran @section Fortran-interface routines Nearly all of the FFTW functions have Fortran-callable equivalents. The name of the legacy Fortran routine is the same as that of the corresponding C routine, but with the @samp{fftw_} prefix replaced by @samp{dfftw_}.@footnote{Technically, Fortran 77 identifiers are not allowed to have more than 6 characters, nor may they contain underscores. Any compiler that enforces this limitation doesn't deserve to link to FFTW.} The single and long-double precision versions use @samp{sfftw_} and @samp{lfftw_}, respectively, instead of @samp{fftwf_} and @samp{fftwl_}; quadruple precision (@code{real*16}) is available on some systems as @samp{fftwq_} (@pxref{Precision}). (Note that @code{long double} on x86 hardware is usually at most 80-bit extended precision, @emph{not} quadruple precision.) For the most part, all of the arguments to the functions are the same, with the following exceptions: @itemize @bullet @item @code{plan} variables (what would be of type @code{fftw_plan} in C), must be declared as a type that is at least as big as a pointer (address) on your machine. We recommend using @code{integer*8} everywhere, since this should always be big enough. @cindex portability @item Any function that returns a value (e.g. @code{fftw_plan_dft}) is converted into a @emph{subroutine}. The return value is converted into an additional @emph{first} parameter of this subroutine.@footnote{The reason for this is that some Fortran implementations seem to have trouble with C function return values, and vice versa.} @item @cindex column-major The Fortran routines expect multi-dimensional arrays to be in @emph{column-major} order, which is the ordinary format of Fortran arrays (@pxref{Multi-dimensional Array Format}). They do this transparently and costlessly simply by reversing the order of the dimensions passed to FFTW, but this has one important consequence for multi-dimensional real-complex transforms, discussed below. @item Wisdom import and export is somewhat more tricky because one cannot easily pass files or strings between C and Fortran; see @ref{Wisdom of Fortran?}. @item Legacy Fortran cannot use the @code{fftw_malloc} dynamic-allocation routine. If you want to exploit the SIMD FFTW (@pxref{SIMD alignment and fftw_malloc}), you'll need to figure out some other way to ensure that your arrays are at least 16-byte aligned. @item @tindex fftw_iodim @cindex guru interface Since Fortran 77 does not have data structures, the @code{fftw_iodim} structure from the guru interface (@pxref{Guru vector and transform sizes}) must be split into separate arguments. In particular, any @code{fftw_iodim} array arguments in the C guru interface become three integer array arguments (@code{n}, @code{is}, and @code{os}) in the Fortran guru interface, all of whose lengths should be equal to the corresponding @code{rank} argument. @item The guru planner interface in Fortran does @emph{not} do any automatic translation between column-major and row-major; you are responsible for setting the strides etcetera to correspond to your Fortran arrays. However, as a slight bug that we are preserving for backwards compatibility, the @samp{plan_guru_r2r} in Fortran @emph{does} reverse the order of its @code{kind} array parameter, so the @code{kind} array of that routine should be in the reverse of the order of the iodim arrays (see above). @end itemize In general, you should take care to use Fortran data types that correspond to (i.e. are the same size as) the C types used by FFTW. In practice, this correspondence is usually straightforward (i.e. @code{integer} corresponds to @code{int}, @code{real} corresponds to @code{float}, etcetera). The native Fortran double/single-precision complex type should be compatible with @code{fftw_complex}/@code{fftwf_complex}. Such simple correspondences are assumed in the examples below. @cindex portability @c ------------------------------------------------------- @node FFTW Constants in Fortran, FFTW Execution in Fortran, Fortran-interface routines, Calling FFTW from Legacy Fortran @section FFTW Constants in Fortran When creating plans in FFTW, a number of constants are used to specify options, such as @code{FFTW_MEASURE} or @code{FFTW_ESTIMATE}. The same constants must be used with the wrapper routines, but of course the C header files where the constants are defined can't be incorporated directly into Fortran code. Instead, we have placed Fortran equivalents of the FFTW constant definitions in the file @code{fftw3.f}, which can be found in the same directory as @code{fftw3.h}. If your Fortran compiler supports a preprocessor of some sort, you should be able to @code{include} or @code{#include} this file; otherwise, you can paste it directly into your code. @cindex flags In C, you combine different flags (like @code{FFTW_PRESERVE_INPUT} and @code{FFTW_MEASURE}) using the @samp{@code{|}} operator; in Fortran you should just use @samp{@code{+}}. (Take care not to add in the same flag more than once, though. Alternatively, you can use the @code{ior} intrinsic function standardized in Fortran 95.) @c ------------------------------------------------------- @node FFTW Execution in Fortran, Fortran Examples, FFTW Constants in Fortran, Calling FFTW from Legacy Fortran @section FFTW Execution in Fortran In C, in order to use a plan, one normally calls @code{fftw_execute}, which executes the plan to perform the transform on the input/output arrays passed when the plan was created (@pxref{Using Plans}). The corresponding subroutine call in legacy Fortran is: @example call dfftw_execute(plan) @end example @findex dfftw_execute However, we have had reports that this causes problems with some recent optimizing Fortran compilers. The problem is, because the input/output arrays are not passed as explicit arguments to @code{dfftw_execute}, the semantics of Fortran (unlike C) allow the compiler to assume that the input/output arrays are not changed by @code{dfftw_execute}. As a consequence, certain compilers end up optimizing out or repositioning the call to @code{dfftw_execute}, assuming incorrectly that it does nothing. There are various workarounds to this, but the safest and simplest thing is to not use @code{dfftw_execute} in Fortran. Instead, use the functions described in @ref{New-array Execute Functions}, which take the input/output arrays as explicit arguments. For example, if the plan is for a complex-data DFT and was created for the arrays @code{in} and @code{out}, you would do: @example call dfftw_execute_dft(plan, in, out) @end example @findex dfftw_execute_dft There are a few things to be careful of, however: @itemize @bullet @item You must use the correct type of execute function, matching the way the plan was created. Complex DFT plans should use @code{dfftw_execute_dft}, Real-input (r2c) DFT plans should use use @code{dfftw_execute_dft_r2c}, and real-output (c2r) DFT plans should use @code{dfftw_execute_dft_c2r}. The various r2r plans should use @code{dfftw_execute_r2r}. @item You should normally pass the same input/output arrays that were used when creating the plan. This is always safe. @item @emph{If} you pass @emph{different} input/output arrays compared to those used when creating the plan, you must abide by all the restrictions of the new-array execute functions (@pxref{New-array Execute Functions}). The most difficult of these, in Fortran, is the requirement that the new arrays have the same alignment as the original arrays, because there seems to be no way in legacy Fortran to obtain guaranteed-aligned arrays (analogous to @code{fftw_malloc} in C). You can, of course, use the @code{FFTW_UNALIGNED} flag when creating the plan, in which case the plan does not depend on the alignment, but this may sacrifice substantial performance on architectures (like x86) with SIMD instructions (@pxref{SIMD alignment and fftw_malloc}). @ctindex FFTW_UNALIGNED @end itemize @c ------------------------------------------------------- @node Fortran Examples, Wisdom of Fortran?, FFTW Execution in Fortran, Calling FFTW from Legacy Fortran @section Fortran Examples In C, you might have something like the following to transform a one-dimensional complex array: @example fftw_complex in[N], out[N]; fftw_plan plan; plan = fftw_plan_dft_1d(N,in,out,FFTW_FORWARD,FFTW_ESTIMATE); fftw_execute(plan); fftw_destroy_plan(plan); @end example In Fortran, you would use the following to accomplish the same thing: @example double complex in, out dimension in(N), out(N) integer*8 plan call dfftw_plan_dft_1d(plan,N,in,out,FFTW_FORWARD,FFTW_ESTIMATE) call dfftw_execute_dft(plan, in, out) call dfftw_destroy_plan(plan) @end example @findex dfftw_plan_dft_1d @findex dfftw_execute_dft @findex dfftw_destroy_plan Notice how all routines are called as Fortran subroutines, and the plan is returned via the first argument to @code{dfftw_plan_dft_1d}. Notice also that we changed @code{fftw_execute} to @code{dfftw_execute_dft} (@pxref{FFTW Execution in Fortran}). To do the same thing, but using 8 threads in parallel (@pxref{Multi-threaded FFTW}), you would simply prefix these calls with: @example integer iret call dfftw_init_threads(iret) call dfftw_plan_with_nthreads(8) @end example @findex dfftw_init_threads @findex dfftw_plan_with_nthreads (You might want to check the value of @code{iret}: if it is zero, it indicates an unlikely error during thread initialization.) To check the number of threads currently being used by the planner, you can do the following: @example integer iret call dfftw_planner_nthreads(iret) @end example @findex dfftw_planner_nthreads To transform a three-dimensional array in-place with C, you might do: @example fftw_complex arr[L][M][N]; fftw_plan plan; plan = fftw_plan_dft_3d(L,M,N, arr,arr, FFTW_FORWARD, FFTW_ESTIMATE); fftw_execute(plan); fftw_destroy_plan(plan); @end example In Fortran, you would use this instead: @example double complex arr dimension arr(L,M,N) integer*8 plan call dfftw_plan_dft_3d(plan, L,M,N, arr,arr, & FFTW_FORWARD, FFTW_ESTIMATE) call dfftw_execute_dft(plan, arr, arr) call dfftw_destroy_plan(plan) @end example @findex dfftw_plan_dft_3d Note that we pass the array dimensions in the ``natural'' order in both C and Fortran. To transform a one-dimensional real array in Fortran, you might do: @example double precision in dimension in(N) double complex out dimension out(N/2 + 1) integer*8 plan call dfftw_plan_dft_r2c_1d(plan,N,in,out,FFTW_ESTIMATE) call dfftw_execute_dft_r2c(plan, in, out) call dfftw_destroy_plan(plan) @end example @findex dfftw_plan_dft_r2c_1d @findex dfftw_execute_dft_r2c To transform a two-dimensional real array, out of place, you might use the following: @example double precision in dimension in(M,N) double complex out dimension out(M/2 + 1, N) integer*8 plan call dfftw_plan_dft_r2c_2d(plan,M,N,in,out,FFTW_ESTIMATE) call dfftw_execute_dft_r2c(plan, in, out) call dfftw_destroy_plan(plan) @end example @findex dfftw_plan_dft_r2c_2d @strong{Important:} Notice that it is the @emph{first} dimension of the complex output array that is cut in half in Fortran, rather than the last dimension as in C. This is a consequence of the interface routines reversing the order of the array dimensions passed to FFTW so that the Fortran program can use its ordinary column-major order. @cindex column-major @cindex r2c/c2r multi-dimensional array format @c ------------------------------------------------------- @node Wisdom of Fortran?, , Fortran Examples, Calling FFTW from Legacy Fortran @section Wisdom of Fortran? In this section, we discuss how one can import/export FFTW wisdom (saved plans) to/from a Fortran program; we assume that the reader is already familiar with wisdom, as described in @ref{Words of Wisdom-Saving Plans}. @cindex portability The basic problem is that is difficult to (portably) pass files and strings between Fortran and C, so we cannot provide a direct Fortran equivalent to the @code{fftw_export_wisdom_to_file}, etcetera, functions. Fortran interfaces @emph{are} provided for the functions that do not take file/string arguments, however: @code{dfftw_import_system_wisdom}, @code{dfftw_import_wisdom}, @code{dfftw_export_wisdom}, and @code{dfftw_forget_wisdom}. @findex dfftw_import_system_wisdom @findex dfftw_import_wisdom @findex dfftw_export_wisdom @findex dfftw_forget_wisdom So, for example, to import the system-wide wisdom, you would do: @example integer isuccess call dfftw_import_system_wisdom(isuccess) @end example As usual, the C return value is turned into a first parameter; @code{isuccess} is non-zero on success and zero on failure (e.g. if there is no system wisdom installed). If you want to import/export wisdom from/to an arbitrary file or elsewhere, you can employ the generic @code{dfftw_import_wisdom} and @code{dfftw_export_wisdom} functions, for which you must supply a subroutine to read/write one character at a time. The FFTW package contains an example file @code{doc/f77_wisdom.f} demonstrating how to implement @code{import_wisdom_from_file} and @code{export_wisdom_to_file} subroutines in this way. (These routines cannot be compiled into the FFTW library itself, lest all FFTW-using programs be required to link with the Fortran I/O library.)