Here is rather odd-looking way to do this in Fortran 2018 using reduce (and probably not very efficient based on what I saw in Compiler Explorer). A newer version of the Intel Fortran compiler is needed.
module fold
implicit none
public
contains
function flatidx(extent,index) result(idx)
integer, intent(in) :: extent(:), index(:)
integer :: idx
type :: pair
integer :: e, i
end type
type(pair) :: tmp(size(extent))
type(pair) :: res
tmp%e = extent
tmp%i = index
res = reduce(tmp,op)
idx = res%i
contains
pure function op(a,b) result(c)
type(pair), intent(in) :: a, b
type(pair) :: c
c = pair(a%e*b%e, a%i + a%e*(b%i - 1))
end function
end function
end module
program test_fold
use fold, only: flatidx
implicit none
integer :: i, j
! 1-d
do i = 1, 8
print *, i, flatidx([8],[i])
end do
! 2-d
do j = 1, 8
do i = 1, 4
print *, i, j, flatidx([4,8],[i,j])
end do
end do
end program
The solution is inspired by the blog posts: