next up previous contents
След.: Модули Выше: Процедуры Пред.: Оператор PROCEDURE и указатели   Содержание


Комассивы в процедурах

Текст этого параграфа есть сокращенный перевод соответствующего параграфа [11].

Формальный аргумент процедуры может быть комассивом. Его конфигурация может быть задана явно, может перениматься, а может перениматься размер. Кроме того, комассив может быть размещаемым. Пример (формальные аргументы-комассивы):

SUBROUTINE SUBR(n,w,x,y,z)

INTEGER :: n

REAL :: w(n)[n,*] ! Явная конфигурация

REAL :: x(n,*)[*] ! Перенимаемый размер

REAL :: y(:,:)[*] ! Перенимаемая конфигурация

REAL, ALLOCATABLE :: z(:)[:,:] ! Размещаемый

Интерфейс к процедуре с формальными аргументами-комассивами:

INTERFACE

SUBROUTINE sub(x,y)

REAL :: x(:)[*], y(:)[*]

END SUBROUTINE sub

END INTERFACE

...

REAL, ALLOCATABLE :: a(:)[:], b(:,:)[:]

...

CALL sub(a(:),b(1,:))

При вызове процедуры соответствующие фактические аргументы также должны быть комассивами. Аргумент связывается с самим комассивом, а не его копией. Копирование потребовало бы синхронизации при входе и выходе, чтобы убедиться, что удаленный доступ в процедуре не относится к еще или уже не существующей копии. Некоторые ограничения гарантируют, что копирование в или из никогда не требуется. Поэтому также требуется явный интерфейс процедур, чтобы компилятор мог проверить выполнение ограничений. Пример -- выше.

Если формальный аргумент -- размещаемый комассив, то соответствующий фактический аргумент должен быть размещаемым комассивом того же ранга и коранга. Он должен быть связан, возможно через много уровней вызова процедур, с одним и тем же неформальным аргументом-комассивом на каждом образе. Это позволяет размещать и удалять массив в подпрограмме.

Если формальный аргумент -- размещаемый комассив, он не должен содержать атрибут INTENT(OUT). Это позволяет избежать неявной синхронизации, вызванной удалением размещаемого массива. Автоматические комассивы не допускаются. Например, такой фрагмент недопустим:

SUBROUTINE solve3(n)

INTEGER :: n REAL :: work(n)[*] !недопустимо

Если бы автоматические комассивы допускались, требовалась бы синхронизация образов как перед выделением памяти при входе, так и перед освобождением памяти при выходе. Также потребовались бы правила, гарантирующие, что размеры массивов на всех образах одинаковы. Это привело бы к тому, что процедуру пришлось бы вызывать на всех образах одновременно (см. предпоследний абзац этого параграфа). Вместо автоматических комассивов следует использовать размещаемые комассивы. Результат функции не может быть комассивом по тем же причинам, по которым запрещены автоматические массивы.

Стерильная или поэлементная процедура не может определять коиндексированный объект или содержать операторы контроля образа (то есть, синхронизации), так как это вызвало бы побочный эффект (определение коиндексированного объекта сопоставимо с определением переменной в вызывающей программной единице или модуле). Однако доступ к значению коиндексированного объекта допустим.

Поэлементная процедура не может иметь формальный аргумент-комассив. Если объект не размещаемый и не формальный аргумент, но комассив, он должен иметь атрибут SAVE. Заметьте, что в Fortran-2008 переменные, объявляемые в описательной части модуля, а также в основной программе, автоматически снабжаются атрибутом SAVE. Если бы комассив был объявлен в процедуре с заданным размером, но без атрибута SAVE, то потребовалась бы неявная синхронизация при входе в процедуру и выходе из нее. Без этого возможно было бы обращение из образа к несуществующим данным другого образа. Размещаемый комассив не требует атрибута SAVE, так как рекурсивная процедура может размещать массивы на разных уровнях рекурсии. Процедура с неразмещаемым формальным аргументом-комассивом будет, как правило, вызвана одновременно на всех образах с одним и тем же фактическим аргументом- комассивом, но это не является требованием. Например, образы могут быть сгруппированы в два класса; одни вызывают процедуру с одним комассивом в качестве параметра, а другие -- с другим или вообще выполняют другой код.

Каждый образ независимо связывает свои неразмещаемые формальные аргументы-комассивы с фактическими аргументами-комассивами, возможно, через много вызовов процедур, и определяет коранг и кограницы заново. Эта информация используется для интерпретации обращений к коиндексированному объекту, не принимая во внимание возможное выполнение той же процедуры с соответствующим комассивом другим образом в это же время.

Фактический аргумент с коиндексом и атрибутом ASYNCHRONOUS или VOLATILE не должен соответствовать формальному аргументу с хотя бы одним из этих атрибутов.

Для создания собственных процедур нужно только знать синтаксис объявления, следует вникнуть в технологию автоматических и перенимающих массивов. Полезен атрибут INTENT. Простые процедуры можно сделать внутренними, отделив от кода программы словом CONTAINS. В ряде случаев полезен также OPTIONAL, позволяющий задавать необязательные параметры. Помните о возможности ключевого задания параметров при вызове, давайте осмысленные имена формальным аргументам (особенно если есть необязательные). В ряде случаев (например, при реализации квадратурных формул) требуются указатели на процедуры, и тогда с ними стоит разобраться. Полезно ознакомиться с возможностью создавать стерильные и (особенно важно) поэлементные процедуры -- если Ваш алгоритм подпадает под определение, поставьте атрибут. Если действительно есть нужда в рекурсии, помните, что Фортрану следует дать знать об этом, указав атрибут RECURSIVE.



Ilya A. Chernov 2012-12-19
X