Как Fortran обрабатывает расширенное присвоение массивов?
В последнее время я работал над некоторым кодом, который требует от меня смещения элементов в массиве влево, вправо, вверх и вниз (в зависимости от индекса i
). Моей первой мыслью было попробовать что-то вроде этого:
subroutine shift(f)
real, intent(inout) :: f(0:8, rDim, cDim)
real :: periodicHor(rDim)
periodicHor(:) = f(1,:,cDim)
f(1,:,2:cDim) = f(1,:,1:cDim - 1)
f(1,:,1) = periodicHor(:)
!and so on for directions 2:8
end subroutine
Однако, когда я выкладываю это таким образом, столбец 1 копируется в столбец 2, который копируется в столбец 3, который копируется в... Это не смещение данных, а первый столбец, перезаписывающий все влево.
Если я переверну индексы,
subroutine betterShift(f)
real, intent(inout) :: f(rDim, cDim, 0:8)
real :: periodicHor(rDim)
periodicHor(:) = f(:,cDim,1)
f(:,2:cDim,1) = f(:,1:cDim - 1,1)
f(:,1,1) = periodicHor(:)
end subroutine
все работает нормально, смещаясь влево или вправо. Я подозреваю, что компилятор обнаруживает обновление непрерывной памяти на месте во 2-м случае, поэтому он делает временную копию "под капотом", чтобы избежать проблемы перезаписи, но это всего лишь предположение с моей стороны. Кто-нибудь может дать более подробное объяснение, почему сдвиг работает в одну сторону, а не в другую?