Tablice wielowymiarowe#

Tablice wielowymiarowe są przechowywane w kolejności kolumnowej. Oznacza to, że najbardziej lewy (najbardziej wewnętrzny) indeks adresuje elementy w sposób ciągły. Z praktycznego punktu widzenia oznacza to, że wycinek tablicy V(:, 1) jest ciągły, podczas gdy odstęp między elementami w wycinku V(1, :) jest wymiarem kolumn. Jest to ważne podczas przekazywania wycinków tablicy do procedur, które mają działać na danych ciągłych.

Lokalność pamięci jest ważnym czynnikiem, który należy wziąć pod uwagę w zależności od aplikacji. Zazwyczaj podczas wykonywania operacji na pamięci wielowymiarowej dostęp sekwencyjny powinien zawsze następować jednostajnie.

W poniższym przykładzie oceniana jest odwrotna odległość między dwoma zbiorami punktów. Zauważ, że punkty są przechowywane w sposób ciągły w tablicach xyz1/xyz2, podczas gdy najbardziej wewnętrzna pętla przesuwa najbardziej lewy indeks macierzy a.

subroutine coulomb_matrix(xyz1, xyz2, a)
  real(dp), intent(in) :: xyz1(:, :)
  real(dp), intent(in) :: xyz2(:, :)
  real(dp), intent(out) :: a(:, :)
  integer :: i, j
  do i = 1, size(a, 2)
    do j = 1, size(a, 1)
      a(j, i) = 1.0_dp/norm2(xyz1(:, j) - xyz2(:, i))
    end do
  end do
end subroutine coulomb_matrix

Innym przykładem może być redukcja trzeciego wymiaru tablicy rzędu trzeciego:

do i = 1, size(amat, 3)
  do j = 1, size(amat, 2)
    do k = 1, size(amat, 1)
      cmat(k, j) = cmat(k, j) + amat(k, j, i) * bvec(i)
    end do
  end do
end do

Ciągłe wycinki tablic mogą być użyte do ponownego mapowania tablicy, co pozwala na używanie tablic o wyższej randze jako tablic o niższej randze, bez konieczności przekształcania i potencjalnego tworzenia tymczasowej kopii tablicy.

Na przykład można użyć tej funkcji do zmniejszenia trzeciego wymiaru tablicy rzędu trzeciego za pomocą operacji macierzowo-wektorowej:

subroutine matmul312(amat, bvec, cmat)
  real(dp), contiguous, intent(in), target :: amat(:, :, :)
  real(dp), intent(in) :: bvec(:)
  real(dp), contiguous, intent(out), target :: cmat(:, :)
  real(dp), pointer :: aptr(:, :)
  real(dp), pointer :: cptr(:)

  aptr(1:size(amat, 1)*size(amat, 2), 1:size(amat, 3)) => amat
  cptr(1:size(cmat)) => cmat

  cptr = matmul(aptr, bvec)
end subroutine matmul312