2010-03-22 2 views
4

Я прохожу через код Fortran, и один бит немного озадачил меня.Массивы и подпрограммы Fortran (вспомогательные массивы)

Существует подпрограмма, скажет

SUBROUTINE SSUB(X,...) 
REAL*8 X(0:N1,1:N2,0:N3-1),... 
... 
RETURN 
END 

Что называется в другой подпрограмме по:

CALL SSUB(W(0,1,0,1),...) 

, где W представляет собой "рабочий массив. Похоже, что определенное значение из W передается X, однако X измеряется как массив. Что происходит?

ответ

7

Это нестандартная идиома для того, чтобы подпрограмма работала над подмножеством (прямоугольным в N-измерениях) исходного массива.

Все параметры в Fortran (по крайней мере, до Fortran 90) передаются по ссылке, поэтому фактический аргумент массива разрешен как местоположение в памяти. Выберите местоположение внутри пространство, выделенное для всего массива, и подпрограмма управляет только частью массива.

Самая большая проблема: у вас должно быть be aware of how the array is laid out in memory и как работает система индексации массивов Fortran. Fortran использует упорядочивание основных массивов столбцов, что является противоположным соглашением от c. Рассмотрим массив размером 5x5 (и проиндексируйте оба направления от 0, чтобы упростить сравнение с c). На обоих языках 0,0 - это первый элемент в памяти. В c следующий элемент в памяти - [0][1], но в Фортране это (1,0). Это влияет на то, какие индексы вы бросаете при выборе подпространства: если исходный массив равен A (i, j, k, l), а подпрограмма работает на трехмерном подпространстве (как в вашем примере), в c работает Aprime[i=constant][j][k][l], но в Фортране в работах на Aprime(i,j,k,l=constant).

Другой риск - обертывание. Размеры массива (sub) в подпрограмме должны совпадать с размерами в вызывающей процедуре, или странные, странные вещи (подумайте об этом). Поэтому, если A объявлен размером (0: 4,0: 5,0: 6,0: 7), и мы вызываем его с помощью элемента A(0,1,0,1), процедура приема может запускать индекс каждого измерения, где ему когда-либо нравится, но должен иметь размеры (4,5,6) или еще; но это означает, что последний элемент в направлении j действительно обертывается! Дело в том, что это не использовать последний элемент. Удостовериться, что это происходит, это работа программистов и боль в прикладе. Береги себя. Много заботы.

+0

Спасибо, пример и ссылка особенно полезны.Это имеет смысл для передачи сказать 0,0 или 0,5, но в этом случае, когда это 0,1,0,1, как эта вторая 1 вступает в игру? Будут ли следующие элементы 1,1,0,1, а затем после первого измерения 0,2,0,1? – ccook

+0

Ваш комментарий с моим правлением. Последний индекс, указанный в вызывающей подпрограмме, фактически является константой в вызываемой процедуре. – dmckee

+0

А, простите об этом. Редакции, безусловно, помогают, снова. Полагаю, сейчас у меня проблемы с этим вторым. Привести это к 2d, то есть начать с индекса (0,1) первого столбца, второй строки и последовательно «отобразить» в массив? – ccook

2

в переменных fortran передаются по адресу. Таким образом, W(0,1,0,1) - это значение и адрес. поэтому в основном вы проходите Subarray, начиная с W(0,1,0,1).

+0

Благодарим вас за отзыв. Я подозревал это, но, не могли бы вы объяснить, как формируется подобие? Вот где он начинается и как он сопоставляется с новым размером. Считывается ли/последовательно отображается в новый размер? – ccook

2

Это называется «ассоциация последовательностей». В этом случае то, что кажется масштабируемым, элемент массива (фактический аргумент в вызывающем объекте) ассоциируется с массивом (неявно первым элементом), фиктивным аргументом в подпрограмме. После этого элементы массивов связаны порядком хранения, известным как «последовательность». Это было сделано в Fortran 77 и ранее по разным причинам, здесь, по-видимому, для массива рабочей области - возможно, программист занимался собственным управлением памятью. Это сохраняется в Fortran> = 90 для обратной совместимости, но IMO не входит в новый код.

+0

Что такое современный подход? – ccook

Смежные вопросы