Question

I have a matrix say REAL*8 MATRIX(100,100), I want to create a pointer out of just the main diagonal or the upper triangle. How to do that?

The purpose is to easily access those elements in a clean "named" way.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top