annotate src/fftw-3.3.3/doc/legacy-fortran.texi @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 37bf6b4a2645
children
rev   line source
Chris@10 1 @node Calling FFTW from Legacy Fortran, Upgrading from FFTW version 2, Calling FFTW from Modern Fortran, Top
Chris@10 2 @chapter Calling FFTW from Legacy Fortran
Chris@10 3 @cindex Fortran interface
Chris@10 4
Chris@10 5 This chapter describes the interface to FFTW callable by Fortran code
Chris@10 6 in older compilers not supporting the Fortran 2003 C interoperability
Chris@10 7 features (@pxref{Calling FFTW from Modern Fortran}). This interface
Chris@10 8 has the major disadvantage that it is not type-checked, so if you
Chris@10 9 mistake the argument types or ordering then your program will not have
Chris@10 10 any compiler errors, and will likely crash at runtime. So, greater
Chris@10 11 care is needed. Also, technically interfacing older Fortran versions
Chris@10 12 to C is nonstandard, but in practice we have found that the techniques
Chris@10 13 used in this chapter have worked with all known Fortran compilers for
Chris@10 14 many years.
Chris@10 15
Chris@10 16 The legacy Fortran interface differs from the C interface only in the
Chris@10 17 prefix (@samp{dfftw_} instead of @samp{fftw_} in double precision) and
Chris@10 18 a few other minor details. This Fortran interface is included in the
Chris@10 19 FFTW libraries by default, unless a Fortran compiler isn't found on
Chris@10 20 your system or @code{--disable-fortran} is included in the
Chris@10 21 @code{configure} flags. We assume here that the reader is already
Chris@10 22 familiar with the usage of FFTW in C, as described elsewhere in this
Chris@10 23 manual.
Chris@10 24
Chris@10 25 The MPI parallel interface to FFTW is @emph{not} currently available
Chris@10 26 to legacy Fortran.
Chris@10 27
Chris@10 28 @menu
Chris@10 29 * Fortran-interface routines::
Chris@10 30 * FFTW Constants in Fortran::
Chris@10 31 * FFTW Execution in Fortran::
Chris@10 32 * Fortran Examples::
Chris@10 33 * Wisdom of Fortran?::
Chris@10 34 @end menu
Chris@10 35
Chris@10 36 @c -------------------------------------------------------
Chris@10 37 @node Fortran-interface routines, FFTW Constants in Fortran, Calling FFTW from Legacy Fortran, Calling FFTW from Legacy Fortran
Chris@10 38 @section Fortran-interface routines
Chris@10 39
Chris@10 40 Nearly all of the FFTW functions have Fortran-callable equivalents.
Chris@10 41 The name of the legacy Fortran routine is the same as that of the
Chris@10 42 corresponding C routine, but with the @samp{fftw_} prefix replaced by
Chris@10 43 @samp{dfftw_}.@footnote{Technically, Fortran 77 identifiers are not
Chris@10 44 allowed to have more than 6 characters, nor may they contain
Chris@10 45 underscores. Any compiler that enforces this limitation doesn't
Chris@10 46 deserve to link to FFTW.} The single and long-double precision
Chris@10 47 versions use @samp{sfftw_} and @samp{lfftw_}, respectively, instead of
Chris@10 48 @samp{fftwf_} and @samp{fftwl_}; quadruple precision (@code{real*16})
Chris@10 49 is available on some systems as @samp{fftwq_} (@pxref{Precision}).
Chris@10 50 (Note that @code{long double} on x86 hardware is usually at most
Chris@10 51 80-bit extended precision, @emph{not} quadruple precision.)
Chris@10 52
Chris@10 53 For the most part, all of the arguments to the functions are the same,
Chris@10 54 with the following exceptions:
Chris@10 55
Chris@10 56 @itemize @bullet
Chris@10 57
Chris@10 58 @item
Chris@10 59 @code{plan} variables (what would be of type @code{fftw_plan} in C),
Chris@10 60 must be declared as a type that is at least as big as a pointer
Chris@10 61 (address) on your machine. We recommend using @code{integer*8} everywhere,
Chris@10 62 since this should always be big enough.
Chris@10 63 @cindex portability
Chris@10 64
Chris@10 65 @item
Chris@10 66 Any function that returns a value (e.g. @code{fftw_plan_dft}) is
Chris@10 67 converted into a @emph{subroutine}. The return value is converted into
Chris@10 68 an additional @emph{first} parameter of this subroutine.@footnote{The
Chris@10 69 reason for this is that some Fortran implementations seem to have
Chris@10 70 trouble with C function return values, and vice versa.}
Chris@10 71
Chris@10 72 @item
Chris@10 73 @cindex column-major
Chris@10 74 The Fortran routines expect multi-dimensional arrays to be in
Chris@10 75 @emph{column-major} order, which is the ordinary format of Fortran
Chris@10 76 arrays (@pxref{Multi-dimensional Array Format}). They do this
Chris@10 77 transparently and costlessly simply by reversing the order of the
Chris@10 78 dimensions passed to FFTW, but this has one important consequence for
Chris@10 79 multi-dimensional real-complex transforms, discussed below.
Chris@10 80
Chris@10 81 @item
Chris@10 82 Wisdom import and export is somewhat more tricky because one cannot
Chris@10 83 easily pass files or strings between C and Fortran; see @ref{Wisdom of
Chris@10 84 Fortran?}.
Chris@10 85
Chris@10 86 @item
Chris@10 87 Legacy Fortran cannot use the @code{fftw_malloc} dynamic-allocation routine.
Chris@10 88 If you want to exploit the SIMD FFTW (@pxref{SIMD alignment and fftw_malloc}), you'll
Chris@10 89 need to figure out some other way to ensure that your arrays are at
Chris@10 90 least 16-byte aligned.
Chris@10 91
Chris@10 92 @item
Chris@10 93 @tindex fftw_iodim
Chris@10 94 @cindex guru interface
Chris@10 95 Since Fortran 77 does not have data structures, the @code{fftw_iodim}
Chris@10 96 structure from the guru interface (@pxref{Guru vector and transform
Chris@10 97 sizes}) must be split into separate arguments. In particular, any
Chris@10 98 @code{fftw_iodim} array arguments in the C guru interface become three
Chris@10 99 integer array arguments (@code{n}, @code{is}, and @code{os}) in the
Chris@10 100 Fortran guru interface, all of whose lengths should be equal to the
Chris@10 101 corresponding @code{rank} argument.
Chris@10 102
Chris@10 103 @item
Chris@10 104 The guru planner interface in Fortran does @emph{not} do any automatic
Chris@10 105 translation between column-major and row-major; you are responsible
Chris@10 106 for setting the strides etcetera to correspond to your Fortran arrays.
Chris@10 107 However, as a slight bug that we are preserving for backwards
Chris@10 108 compatibility, the @samp{plan_guru_r2r} in Fortran @emph{does} reverse the
Chris@10 109 order of its @code{kind} array parameter, so the @code{kind} array
Chris@10 110 of that routine should be in the reverse of the order of the iodim
Chris@10 111 arrays (see above).
Chris@10 112
Chris@10 113 @end itemize
Chris@10 114
Chris@10 115 In general, you should take care to use Fortran data types that
Chris@10 116 correspond to (i.e. are the same size as) the C types used by FFTW.
Chris@10 117 In practice, this correspondence is usually straightforward
Chris@10 118 (i.e. @code{integer} corresponds to @code{int}, @code{real}
Chris@10 119 corresponds to @code{float}, etcetera). The native Fortran
Chris@10 120 double/single-precision complex type should be compatible with
Chris@10 121 @code{fftw_complex}/@code{fftwf_complex}. Such simple correspondences
Chris@10 122 are assumed in the examples below.
Chris@10 123 @cindex portability
Chris@10 124
Chris@10 125 @c -------------------------------------------------------
Chris@10 126 @node FFTW Constants in Fortran, FFTW Execution in Fortran, Fortran-interface routines, Calling FFTW from Legacy Fortran
Chris@10 127 @section FFTW Constants in Fortran
Chris@10 128
Chris@10 129 When creating plans in FFTW, a number of constants are used to specify
Chris@10 130 options, such as @code{FFTW_MEASURE} or @code{FFTW_ESTIMATE}. The
Chris@10 131 same constants must be used with the wrapper routines, but of course the
Chris@10 132 C header files where the constants are defined can't be incorporated
Chris@10 133 directly into Fortran code.
Chris@10 134
Chris@10 135 Instead, we have placed Fortran equivalents of the FFTW constant
Chris@10 136 definitions in the file @code{fftw3.f}, which can be found in the same
Chris@10 137 directory as @code{fftw3.h}. If your Fortran compiler supports a
Chris@10 138 preprocessor of some sort, you should be able to @code{include} or
Chris@10 139 @code{#include} this file; otherwise, you can paste it directly into
Chris@10 140 your code.
Chris@10 141
Chris@10 142 @cindex flags
Chris@10 143 In C, you combine different flags (like @code{FFTW_PRESERVE_INPUT} and
Chris@10 144 @code{FFTW_MEASURE}) using the @samp{@code{|}} operator; in Fortran
Chris@10 145 you should just use @samp{@code{+}}. (Take care not to add in the
Chris@10 146 same flag more than once, though. Alternatively, you can use the
Chris@10 147 @code{ior} intrinsic function standardized in Fortran 95.)
Chris@10 148
Chris@10 149 @c -------------------------------------------------------
Chris@10 150 @node FFTW Execution in Fortran, Fortran Examples, FFTW Constants in Fortran, Calling FFTW from Legacy Fortran
Chris@10 151 @section FFTW Execution in Fortran
Chris@10 152
Chris@10 153 In C, in order to use a plan, one normally calls @code{fftw_execute},
Chris@10 154 which executes the plan to perform the transform on the input/output
Chris@10 155 arrays passed when the plan was created (@pxref{Using Plans}). The
Chris@10 156 corresponding subroutine call in legacy Fortran is:
Chris@10 157 @example
Chris@10 158 call dfftw_execute(plan)
Chris@10 159 @end example
Chris@10 160 @findex dfftw_execute
Chris@10 161
Chris@10 162 However, we have had reports that this causes problems with some
Chris@10 163 recent optimizing Fortran compilers. The problem is, because the
Chris@10 164 input/output arrays are not passed as explicit arguments to
Chris@10 165 @code{dfftw_execute}, the semantics of Fortran (unlike C) allow the
Chris@10 166 compiler to assume that the input/output arrays are not changed by
Chris@10 167 @code{dfftw_execute}. As a consequence, certain compilers end up
Chris@10 168 optimizing out or repositioning the call to @code{dfftw_execute},
Chris@10 169 assuming incorrectly that it does nothing.
Chris@10 170
Chris@10 171 There are various workarounds to this, but the safest and simplest
Chris@10 172 thing is to not use @code{dfftw_execute} in Fortran. Instead, use the
Chris@10 173 functions described in @ref{New-array Execute Functions}, which take
Chris@10 174 the input/output arrays as explicit arguments. For example, if the
Chris@10 175 plan is for a complex-data DFT and was created for the arrays
Chris@10 176 @code{in} and @code{out}, you would do:
Chris@10 177 @example
Chris@10 178 call dfftw_execute_dft(plan, in, out)
Chris@10 179 @end example
Chris@10 180 @findex dfftw_execute_dft
Chris@10 181
Chris@10 182 There are a few things to be careful of, however:
Chris@10 183
Chris@10 184 @itemize @bullet
Chris@10 185
Chris@10 186 @item
Chris@10 187 You must use the correct type of execute function, matching the way
Chris@10 188 the plan was created. Complex DFT plans should use
Chris@10 189 @code{dfftw_execute_dft}, Real-input (r2c) DFT plans should use use
Chris@10 190 @code{dfftw_execute_dft_r2c}, and real-output (c2r) DFT plans should
Chris@10 191 use @code{dfftw_execute_dft_c2r}. The various r2r plans should use
Chris@10 192 @code{dfftw_execute_r2r}.
Chris@10 193
Chris@10 194 @item
Chris@10 195 You should normally pass the same input/output arrays that were used when
Chris@10 196 creating the plan. This is always safe.
Chris@10 197
Chris@10 198 @item
Chris@10 199 @emph{If} you pass @emph{different} input/output arrays compared to
Chris@10 200 those used when creating the plan, you must abide by all the
Chris@10 201 restrictions of the new-array execute functions (@pxref{New-array
Chris@10 202 Execute Functions}). The most difficult of these, in Fortran, is the
Chris@10 203 requirement that the new arrays have the same alignment as the
Chris@10 204 original arrays, because there seems to be no way in legacy Fortran to obtain
Chris@10 205 guaranteed-aligned arrays (analogous to @code{fftw_malloc} in C). You
Chris@10 206 can, of course, use the @code{FFTW_UNALIGNED} flag when creating the
Chris@10 207 plan, in which case the plan does not depend on the alignment, but
Chris@10 208 this may sacrifice substantial performance on architectures (like x86)
Chris@10 209 with SIMD instructions (@pxref{SIMD alignment and fftw_malloc}).
Chris@10 210 @ctindex FFTW_UNALIGNED
Chris@10 211
Chris@10 212 @end itemize
Chris@10 213
Chris@10 214 @c -------------------------------------------------------
Chris@10 215 @node Fortran Examples, Wisdom of Fortran?, FFTW Execution in Fortran, Calling FFTW from Legacy Fortran
Chris@10 216 @section Fortran Examples
Chris@10 217
Chris@10 218 In C, you might have something like the following to transform a
Chris@10 219 one-dimensional complex array:
Chris@10 220
Chris@10 221 @example
Chris@10 222 fftw_complex in[N], out[N];
Chris@10 223 fftw_plan plan;
Chris@10 224
Chris@10 225 plan = fftw_plan_dft_1d(N,in,out,FFTW_FORWARD,FFTW_ESTIMATE);
Chris@10 226 fftw_execute(plan);
Chris@10 227 fftw_destroy_plan(plan);
Chris@10 228 @end example
Chris@10 229
Chris@10 230 In Fortran, you would use the following to accomplish the same thing:
Chris@10 231
Chris@10 232 @example
Chris@10 233 double complex in, out
Chris@10 234 dimension in(N), out(N)
Chris@10 235 integer*8 plan
Chris@10 236
Chris@10 237 call dfftw_plan_dft_1d(plan,N,in,out,FFTW_FORWARD,FFTW_ESTIMATE)
Chris@10 238 call dfftw_execute_dft(plan, in, out)
Chris@10 239 call dfftw_destroy_plan(plan)
Chris@10 240 @end example
Chris@10 241 @findex dfftw_plan_dft_1d
Chris@10 242 @findex dfftw_execute_dft
Chris@10 243 @findex dfftw_destroy_plan
Chris@10 244
Chris@10 245 Notice how all routines are called as Fortran subroutines, and the
Chris@10 246 plan is returned via the first argument to @code{dfftw_plan_dft_1d}.
Chris@10 247 Notice also that we changed @code{fftw_execute} to
Chris@10 248 @code{dfftw_execute_dft} (@pxref{FFTW Execution in Fortran}). To do
Chris@10 249 the same thing, but using 8 threads in parallel (@pxref{Multi-threaded
Chris@10 250 FFTW}), you would simply prefix these calls with:
Chris@10 251
Chris@10 252 @example
Chris@10 253 integer iret
Chris@10 254 call dfftw_init_threads(iret)
Chris@10 255 call dfftw_plan_with_nthreads(8)
Chris@10 256 @end example
Chris@10 257 @findex dfftw_init_threads
Chris@10 258 @findex dfftw_plan_with_nthreads
Chris@10 259
Chris@10 260 (You might want to check the value of @code{iret}: if it is zero, it
Chris@10 261 indicates an unlikely error during thread initialization.)
Chris@10 262
Chris@10 263 To transform a three-dimensional array in-place with C, you might do:
Chris@10 264
Chris@10 265 @example
Chris@10 266 fftw_complex arr[L][M][N];
Chris@10 267 fftw_plan plan;
Chris@10 268
Chris@10 269 plan = fftw_plan_dft_3d(L,M,N, arr,arr,
Chris@10 270 FFTW_FORWARD, FFTW_ESTIMATE);
Chris@10 271 fftw_execute(plan);
Chris@10 272 fftw_destroy_plan(plan);
Chris@10 273 @end example
Chris@10 274
Chris@10 275 In Fortran, you would use this instead:
Chris@10 276
Chris@10 277 @example
Chris@10 278 double complex arr
Chris@10 279 dimension arr(L,M,N)
Chris@10 280 integer*8 plan
Chris@10 281
Chris@10 282 call dfftw_plan_dft_3d(plan, L,M,N, arr,arr,
Chris@10 283 & FFTW_FORWARD, FFTW_ESTIMATE)
Chris@10 284 call dfftw_execute_dft(plan, arr, arr)
Chris@10 285 call dfftw_destroy_plan(plan)
Chris@10 286 @end example
Chris@10 287 @findex dfftw_plan_dft_3d
Chris@10 288
Chris@10 289 Note that we pass the array dimensions in the ``natural'' order in both C
Chris@10 290 and Fortran.
Chris@10 291
Chris@10 292 To transform a one-dimensional real array in Fortran, you might do:
Chris@10 293
Chris@10 294 @example
Chris@10 295 double precision in
Chris@10 296 dimension in(N)
Chris@10 297 double complex out
Chris@10 298 dimension out(N/2 + 1)
Chris@10 299 integer*8 plan
Chris@10 300
Chris@10 301 call dfftw_plan_dft_r2c_1d(plan,N,in,out,FFTW_ESTIMATE)
Chris@10 302 call dfftw_execute_dft_r2c(plan, in, out)
Chris@10 303 call dfftw_destroy_plan(plan)
Chris@10 304 @end example
Chris@10 305 @findex dfftw_plan_dft_r2c_1d
Chris@10 306 @findex dfftw_execute_dft_r2c
Chris@10 307
Chris@10 308 To transform a two-dimensional real array, out of place, you might use
Chris@10 309 the following:
Chris@10 310
Chris@10 311 @example
Chris@10 312 double precision in
Chris@10 313 dimension in(M,N)
Chris@10 314 double complex out
Chris@10 315 dimension out(M/2 + 1, N)
Chris@10 316 integer*8 plan
Chris@10 317
Chris@10 318 call dfftw_plan_dft_r2c_2d(plan,M,N,in,out,FFTW_ESTIMATE)
Chris@10 319 call dfftw_execute_dft_r2c(plan, in, out)
Chris@10 320 call dfftw_destroy_plan(plan)
Chris@10 321 @end example
Chris@10 322 @findex dfftw_plan_dft_r2c_2d
Chris@10 323
Chris@10 324 @strong{Important:} Notice that it is the @emph{first} dimension of the
Chris@10 325 complex output array that is cut in half in Fortran, rather than the
Chris@10 326 last dimension as in C. This is a consequence of the interface routines
Chris@10 327 reversing the order of the array dimensions passed to FFTW so that the
Chris@10 328 Fortran program can use its ordinary column-major order.
Chris@10 329 @cindex column-major
Chris@10 330 @cindex r2c/c2r multi-dimensional array format
Chris@10 331
Chris@10 332 @c -------------------------------------------------------
Chris@10 333 @node Wisdom of Fortran?, , Fortran Examples, Calling FFTW from Legacy Fortran
Chris@10 334 @section Wisdom of Fortran?
Chris@10 335
Chris@10 336 In this section, we discuss how one can import/export FFTW wisdom
Chris@10 337 (saved plans) to/from a Fortran program; we assume that the reader is
Chris@10 338 already familiar with wisdom, as described in @ref{Words of
Chris@10 339 Wisdom-Saving Plans}.
Chris@10 340
Chris@10 341 @cindex portability
Chris@10 342 The basic problem is that is difficult to (portably) pass files and
Chris@10 343 strings between Fortran and C, so we cannot provide a direct Fortran
Chris@10 344 equivalent to the @code{fftw_export_wisdom_to_file}, etcetera,
Chris@10 345 functions. Fortran interfaces @emph{are} provided for the functions
Chris@10 346 that do not take file/string arguments, however:
Chris@10 347 @code{dfftw_import_system_wisdom}, @code{dfftw_import_wisdom},
Chris@10 348 @code{dfftw_export_wisdom}, and @code{dfftw_forget_wisdom}.
Chris@10 349 @findex dfftw_import_system_wisdom
Chris@10 350 @findex dfftw_import_wisdom
Chris@10 351 @findex dfftw_export_wisdom
Chris@10 352 @findex dfftw_forget_wisdom
Chris@10 353
Chris@10 354
Chris@10 355 So, for example, to import the system-wide wisdom, you would do:
Chris@10 356
Chris@10 357 @example
Chris@10 358 integer isuccess
Chris@10 359 call dfftw_import_system_wisdom(isuccess)
Chris@10 360 @end example
Chris@10 361
Chris@10 362 As usual, the C return value is turned into a first parameter;
Chris@10 363 @code{isuccess} is non-zero on success and zero on failure (e.g. if
Chris@10 364 there is no system wisdom installed).
Chris@10 365
Chris@10 366 If you want to import/export wisdom from/to an arbitrary file or
Chris@10 367 elsewhere, you can employ the generic @code{dfftw_import_wisdom} and
Chris@10 368 @code{dfftw_export_wisdom} functions, for which you must supply a
Chris@10 369 subroutine to read/write one character at a time. The FFTW package
Chris@10 370 contains an example file @code{doc/f77_wisdom.f} demonstrating how to
Chris@10 371 implement @code{import_wisdom_from_file} and
Chris@10 372 @code{export_wisdom_to_file} subroutines in this way. (These routines
Chris@10 373 cannot be compiled into the FFTW library itself, lest all FFTW-using
Chris@10 374 programs be required to link with the Fortran I/O library.)