!------------------------------------------------------------------------------
!
!  Program name:
!
!    array_pointers
!
!  Purpose:
!
!    This program shows the use of array pointers (the target
!    of a pointer can also be an array and such a pointer can 
!    be referred to as an array pointer).
!
!------------------------------------------------------------------------------

PROGRAM array_pointers

  IMPLICIT NONE 
  REAL, DIMENSION (:), POINTER :: pv1
  REAL, DIMENSION (:, :), POINTER :: pv2
  REAL, DIMENSION (-3:5), TARGET :: tv1
  REAL, DIMENSION (5, 10), TARGET :: tv2
  INTEGER :: i

  ! Construction of tv1 array 
  tv1 = (/ (i, i = 1, 9) /)
  WRITE(*, "(' tv1(-3:5) =', 9F5.1/)") tv1

  ! construction of tv2 array
  tv2 = RESHAPE((/ (i, i = 1, 50) /), SHAPE = (/ 5, 10 /))
  WRITE(*, *) "tv2(1:5, 1:10) ="
  DO I = 1, 5
    WRITE(*, "(10F5.1)") tv2(i, :)
  END DO
  !  WRITE(*, "(10F5.1)") (tv2(i, :), i = 1, 5)
  WRITE(*, *)

  pv1 => tv1		! pv1 aliased to tv1
  WRITE(*, *) "With pv1 => tv1, pv1 has SIZE = ", SIZE(pv1), &
	      ", LBOUND = ", LBOUND(pv1), ", SHAPE = ", SHAPE(pv1)
  WRITE(*, "(' pv1(-3:5) =', 9F5.1/)") pv1

  pv1 => tv1(:)         ! pv1 points to tv1 with array section subscript,
                        ! which means pv1 points to an array section, so
                        ! the lower bound is renumbered as 1
  WRITE(*, *) "With pv1 => tv1(:), pv1 has SIZE = ", SIZE(pv1), &
	      ", LBOUND = ", LBOUND(pv1), ", SHAPE = ", SHAPE(pv1)
  WRITE(*, "(' pv1(1:9) =', 9F5.1/)") pv1

  pv1 => tv2(4, :)      ! pv1 points to the 4th row of tv2

  WRITE(*, *) "With pv1 => tv2(4, :), pv1 has SIZE = ", SIZE(pv1), &
	      ", LBOUND = ", LBOUND(pv1), ", SHAPE = ", SHAPE(pv1)
  WRITE(*, "(' pv1(1:10) =', 10F5.1)/") pv1

  pv2 => tv2(2:4, 4:8)  ! pv2 points to a section of tv2

  WRITE(*, *) "With pv2 => tv2(2:4, 4:8), pv2 has SIZE = ", SIZE(pv2), &
	      ", LBOUND = ", LBOUND(pv2), ", SHAPE = ", SHAPE(pv2)
  WRITE(*, *) "pv2(1:3, 1:5) ="
  WRITE(*, "(5F5.1)") (pv2(i, :), i = 1, 3)
  WRITE(*, *)

  pv1 => tv1(1:5:2)     ! pv1 points to a section of tv1 using triple subscript

  WRITE(*, *) "With pv1 => tv1(1:5:2), pv1 has SIZE = ", SIZE(pv1), &
	      ", LBOUND = ", LBOUND(pv1), ", SHAPE = ", SHAPE(pv1)
  WRITE(*, "(' pv1(1:3) =', 3F5.1)") pv1

END PROGRAM array_pointers
