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