It’s nice that in Fortran 2018, a function can have an assumed-rank array argument that can be a scalar or an array of any rank, so that the program
module m_mod
implicit none
contains
function mean(x) result(y)
real, intent(in) :: x(..) ! assumed-rank array
real :: y
select rank(x)
rank(0) ; y = x
rank(1) ; y = sum(x)/size(x)
rank(2) ; y = sum(x)/size(x)
rank default ; y = -huge(x) ! signal that rank not handled
end select
end function mean
end module m_mod
program main
use m_mod, only: mean
implicit none
real :: x,xvec(3),xmat(3,3),xtens(3,3,3)
x = 5.0
xvec = 5.0
xmat = 5.0
xtens = 5.0
print*,mean(x),mean(xvec),mean(xmat),mean(xtens)
end program main
gives output
5.00000000 5.00000000 5.00000000 -3.40282347E+38
To handle the case above where the same code is used for different ranks, the alternatives to manual copying would be to use INCLUDE or have a preprocessor generate the code? Analogous with SELECT CASE, it would be ideal if one could write
rank(1:7); y = sum(x)/size(x)
but using the assumed-rank feature is still more concise than having to define separate mean_scalar, mean_vector, mean_matrix functions as MODULE PROCEDUREs for the INTERFACE mean, as one would do in Fortran 95. Is there a way to have the program fail at compile time when an array of rank 3 or higher is passed to mean?