Как 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-м случае, поэтому он делает временную копию "под капотом", чтобы избежать проблемы перезаписи, но это всего лишь предположение с моей стороны. Кто-нибудь может дать более подробное объяснение, почему сдвиг работает в одну сторону, а не в другую?

0 ответов

Другие вопросы по тегам