I was trying to figure out a way to have a library that exports procedures with multiple real kinds (single, double, quad) that:
- doesn’t duplicate code
- is standard fortran (preprocessing also OK)
- doesn’t break IDEs, linters, syntax highlighters
So, fypp
is out for the last two reasons.
I used a preprocessing scheme in my new Quadpack library. It creates sort of a parameritized module like so. First, I make a generic version of the module (quadpack_generic.F90 ):
#ifndef MOD_INCLUDE
module quadpack_generic
use iso_fortran_env, only: wp => real64
#endif
! put all routines here, Using wp real kind
#ifndef MOD_INCLUDE
end module quadpack_generic
#endif
So, notice that if MOD_INCLUDE
is not defined, this is just a normal module that uses double precision reals. So, it works fine in an IDE and doesn’t break anything. But if MOD_INCLUDE
is defined, then it can be used as an include file to change the value of wp
.
To instantiate a single precision version of this module, we create a new file (quadpack_single.F90):
module quadpack_single
use iso_fortran_env, only: wp => real32
#define MOD_INCLUDE=1
#include "quadpack_generic.F90"
end module quadpack_single
Can do same for quad precision. So, you can use these modules as is, and we can also make a single module that exports all of them (quadpack.F90):
module quadpack
use quadpack_single, only: qag => dqag, ...
use quadpack_double
use quadpack_quad, only: qqag => dqag, ...
end module quadpack
Notice that I’m renaming them to match the old interface (so, for example the module exports qag
(single), dqag
(double() and qqag
(quad). We could also make an interface block.
What do you think of this approach? It seems OK, if a little clunky.