## Fortran polymorphism with CMake

Fortran polymorphism and generic programming (sets, lists, generators) are consistently the highest ranked survey feature requests for Fortran 202X. Fortran programmers introduce polymorphic procedures and variables into modern Fortran by:

- C++ preprocessor
`#ifdef`

etc. (simplest, not officially part of language (or truly polymorphism), but very widely supported and used) - Fortran 2003 static procedure polymorphism is simple to use and is standard Fortran language feature.
- using Fortran user-defined types, with duplicated procedures for each and every desired type/kind. This is more verbose to use, but it is the most powerful / flexible true Fortran polymorphism.

The preprocessor method might be thought of as compile-time polymorphism. It’s not a perfect solution, and not true polymorphism since each procedure still requires exactly one type/kind per argument. However, this technique combined with static polymorphism is simple to develop and handles many real-life use cases quickly and easily.

## Compile-time Fortran polymorphic `REAL`

in all your Fortran code, for each

`REAL`

variable and function, make`kind=wp`

. For example`polyreal.F90`

(notice the capital`F90`

):`use, intrinsic:: iso_fortran_env implicit none #if REALBITS==32 integer,parameter :: wp=real32 #elif REALBITS==64 integer,parameter :: wp=real64 #elif REALBITS==128 integer,parameter :: wp=real128 #endif real(wp) :: pi,b integer :: i pi = 4._wp * atan(1._wp) b = timestwo(pi) print *,'pi',pi,'2pi',b contains elemental real(wp) function timestwo(a) result(b) real(wp), intent(in) :: a b = 2*a end function timestwo end program`

make a command-line options

`-Drealbits=64`

or`-Drealbits=32`

etc. in`CMakeLists.txt`

:`cmake_minimum_required(VERSION 3.1) project(realpoly Fortran) if(NOT realbits) set(realbits 64) endif() # your modules and programs add_executable(poly polyreal.f90) target_compile_definitions(poly PRIVATE REALBITS=${realbits})`

We typically have a

`comm.f90`

that contains various constants including`wp`

used throughout a program.Generate then build as usual:

`cmake -Drealbits=64 .. make ./poly`

pi 3.1415926535897931 2pi 6.2831853071795862

That uses double-precision real64 variables and functions. The concept is trivially extensible to large programs consisting of many files and modules.

To then select a different kind and rerun, perhaps to evaluate accuracy vs. runtime tradeoffs (real32 is generally faster than real64, but less accurate):

`cmake -Drealbits=32 .. make ./poly`

pi 3.14159274 2pi 6.28318548

or for quad-precision Fortran real128:

`cmake -Drealbits=128 .. make ./poly`

pi 3.14159265358979323846264338327950280 2pi 6.28318530717958647692528676655900559

## Real and Complex compile-time polymorphism

This is shown by example in signal_subspace. Let me know if you’d like more detailed explanation. It includes different procedures for real vs. complex.

## Notes

- Fortran 2018 examples