Library exporting interface for multiple real kinds

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 ):

module quadpack_generic
    use iso_fortran_env, only: wp => real64

! put all routines here, Using wp real kind

end module quadpack_generic

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.

1 Like

In either of the two approaches just demonstrated, how do you introduce kind-dependent specifics?

An example of this could be a polynomial approximation that uses different coefficients or a different number of terms for the single and double versions.

1 Like

In the PLplot project we provide Fortran bindings for both single- and double-precision in the same library. Many of the other languages we support there, only use double precision, so there is less interest for such a dual interface. The technique is quite useable for any Fortran package ;).