For the main diagonal, with care, you can do something like:
PROGRAM diagonal
IMPLICIT NONE
REAL, TARGET :: array(4,4)
REAL, POINTER :: ptr(:)
INTEGER :: i
array = RESHAPE([(i,i=1,SIZE(array))], SHAPE(array))
CALL get_diagonal_pointer(array, SIZE(array, 1), ptr)
PRINT "(*(G0,:,','))", ptr
CONTAINS
SUBROUTINE get_diagonal_pointer(arr, n, ptr)
REAL, INTENT(IN), TARGET :: arr(*)
INTEGER, INTENT(IN) :: n
REAL, INTENT(OUT), POINTER :: ptr(:)
!****
ptr => arr(1:n*n:n+1)
END SUBROUTINE get_diagonal_pointer
END PROGRAM diagonal
But note that array
in the main program is simply contiguous and has the TARGET attribute. If array
was not simply contiguous, then things get ... complicated.
You can accomplish the same using an intermediate rank one pointer and pointer bounds remapping. The same requirements as for the assumed size approach apply.
REAL, POINTER :: tmp(:)
tmp(1:SIZE(array)) => array
ptr => tmp(::SIZE(array,1)+1)
The upper triangle of a matrix is not "regular" (the spacing between elements that you want to point at varies) and hence it can't be pointed at.