Skip to content

Instantly share code, notes, and snippets.

@nshaffer
Created January 13, 2020 05:35
Show Gist options
  • Save nshaffer/9b132a556cb6f6dea6abdce0b073f3e0 to your computer and use it in GitHub Desktop.
Save nshaffer/9b132a556cb6f6dea6abdce0b073f3e0 to your computer and use it in GitHub Desktop.
Demonstrate the use of `fypp` to generate a kind- and type-generic function
module fypp_sum
#! Define variables for kind parameters. Presumably, we would have
#! these defined in a general-purpose definitions file that peeks at
#! the values of `real_kinds` and `integer_kinds` in the
#! `iso_fortran_env` module.
#:set REALKINDS = ["qp", "dp", "sp"]
#:set INTKINDS = ["int64", "int32", "int16", "int8"]
#:set KINDS = REALKINDS + INTKINDS
#:set TYPES = ["real({})".format(k) for k in REALKINDS] &
& + ["integer({})".format(k) for k in INTKINDS]
! In a real applicaion, we'd `use stdlib_experimental_kinds` or whatever.
use, intrinsic :: iso_fortran_env, only: &
qp => real128, dp => real64, sp => real32, int64, int32, int16, int8
implicit none
private
public :: sum
interface sum
#:for k1 in KINDS
#:for k2 in KINDS
module procedure sum_${k1}$_${k2}$
#:endfor
#:endfor
end interface sum
contains
#! Loop from most precise to least precise real, then widest to
#! narrowest integer.
#:set ikt = list(zip(range(len(KINDS)), KINDS, TYPES))
#:for i, k1, t1 in ikt
#:for j, k2, t2 in ikt
#:set t3 = t1 if i < j else t2
function sum_${k1}$_${k2}$(a, b) result(c)
${t1}$, intent(in) :: a
${t2}$, intent(in) :: b
${t3}$ :: c
c = a + b
end function sum_${k1}$_${k2}$
#:endfor
#:endfor
end module fypp_sum
@nshaffer
Copy link
Author

Assuming you have fypp installed, you could process this template like

$ fypp fypp_sum.f90 > fypp_sum.out.f90

Template and output files can (and probably should) be named differently in practice. This is no difficulty for fypp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment