Главная страница
Навигация по странице:

  • Замечание.

  • 8.29. Порядок операторов и директив Операторы и директивы в программных единицах должны появляться в приведенном в табл. 8.5 порядке. 288

  • современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран


    Скачать 2.24 Mb.
    НазваниеО. В. Бартеньев Современный Фортран
    Анкорсовременный фортран , Бортеньев.pdf
    Дата28.05.2018
    Размер2.24 Mb.
    Формат файлаpdf
    Имя файласовременный фортран , Бортеньев.pdf
    ТипДокументы
    #19729
    страница31 из 49
    1   ...   27   28   29   30   31   32   33   34   ...   49
    279

    О. В. Бартеньев. Современный ФОРТРАН
    subroutine shosa( ) real da, a, dum common /bz/ da, a, dum(10) real(8), save :: x, y save /bz/
    8.23. Атрибут STATIC
    Имеющие атрибут STATIC переменные (в процедуре или модуле) сохраняются в (статической) памяти в течение всего времени выполнения программы. Атрибут является расширением над стандартом Фортрана и эквивалентен ранее приведенному атрибуту SAVE и атрибуту STATIC языка
    СИ. Значения статических переменных сохраняются после выполнения оператора RETURN или END. Напомним, что в CVF и FPS по умолчанию переменные (кроме динамических) размещены в статической памяти. Для изменения правил умолчания используются атрибуты ALLOCATABLE,
    AUTOMATIC и POINTER. Атрибут STATIC может быть задан в двух формах:
    STATIC [[::] список объектов]
    type-spec, STATIC [, атрибуты] :: список объектов
    Список объектов может включать имена переменных и common-блоков.
    Имена последних при включении их в список объектов оператора STATIC обрамляются слешами.
    Пример: integer :: ng = -1 do while(ng /= 0)
    ! Цикл завершается при ng = 0 call sub1(ng, ng + ng) print *, 'Enter integer non zero value to continue or zero to quit' read *, ng end do contains subroutine sub1(iold, inew) integer, intent(inout) :: iold integer, static :: n2
    ! При каждом вызове n2 = -1 integer, automatic :: n3 integer, intent(in) :: inew if(iold == -1) then n2 = iold n3 = iold
    ! Значение n3 определено только при ng = -1 end if print *, 'new: ', inew, ' n2: ', n2, ' n3: ', n3 end subroutine end
    280

    8. Программные единицы
    8.24. Атрибут VOLATILE
    Атрибут может быть задан только в CVF и является расширением над стандартом Фортрана. Атрибут указывает компилятору, что значение объекта непредсказуемо. Объект, обладающий атрибутом VOLATILE, не будет оптимизироваться в процесс компиляции. Как и другие, атрибут может быть задан в двух формах:
    VOLATILE список объектов
    type-spec, VOLATILE [, атрибуты] :: список объектов
    Список объектов может включать имена переменных и common-блоков.
    Имена последних при включении их в список объектов оператора VOLA-
    TILE обрамляются слешами.
    Переменная или common-блок должны объявляться VOLATILE, если способ их определения неочевиден для компилятора. Например, если операционная система размещает переменную в разделяемой памяти, с тем чтобы ее могла использовать другая программа, которая может в том числе и изменить значение переменной, или в случае ассоциирования памяти посредством оператора EQUIVALENCE.
    Если составной объект (массив, производный тип) объявляется VOLA-
    TILE, то каждый его элемент получает этот атрибут. Аналогично если com-
    mon-блок объявляется VOLATILE, то этим атрибутом обладает каждый его элемент.
    Атрибут VOLATILE не может быть задан процедуре, результату функции и namelist-группе.
    Пример: logical(kind = 1) ipi(4) integer(kind = 4) a, b, c, d, e, ilook integer(kind = 4) p1, p2, p3, p4 common /blk1/ a, b, c volatile /blk1/, d, e equivalence(ilook, ipi) equivalence(a, p1) equivalence(p1, p4)
    Именованный common-блок blk1, переменные d и e объявляются VOLA-
    TILE явно. Поведение переменных p1 и p4 в результате их ассоциирования по памяти (прямого и непрямого) с volatile-переменной a зависит от a.
    8.25. Чистые процедуры
    Чистыми называются процедуры, не имеющие побочных эффектов.
    Пример побочного эффекта демонстрирует следующая программа: program side_effect real(4) :: dist, d, p = 3.0, q = 4.0, r = 5.0
    281

    О. В. Бартеньев. Современный ФОРТРАН
    d = max(dist(p, q), dist(q, r)) print *, d
    ! 7.071068 end program side_effect function dist(p, q) real(4) :: dist, p, q dist = sqrt(p * p + q * q) q = dist
    ! Изменение q - побочный эффект end function dist
    Суть его в том, что функция dist переопределяет значение параметра q.
    А это означает, что второй вызов функции dist при вычислении d, выполняется при q, равном 5.0, вместо ожидаемого первоначального значения q = 4.0. Такие эффекты запрещены стандартом и должны отслеживаться и устраняться программистом.
    Сообщение о том, что процедура является чистой, обеспечивается ключевым словом PURE, применяемым в заголовке процедуры:
    [type-spec] PURE SUBROUTINE | FUNCTION name &
    [RESULT
    (resultname)] или
    PURE [type-spec] SUBROUTINE | FUNCTION name &
    [RESULT
    (resultname)]
    type-spec - тип результирующей переменной функции.
    name - имя процедуры.
    resultname - имя результирующей переменной функции.
    Чистая процедура характеризуется тем, что:

    функция возвращает значение и не меняет ни одного из своих параметров;

    подпрограмма изменяет только те параметры, которые имеют вид связи
    INTENT(OUT) и INTENT(INOUT).
    По умолчанию чистыми являются:

    все встроенные функции и встроенная подпрограмма MVBITS;

    процедуры библиотеки высокоскоростного Фортрана, применяемого для параллельных вычислений под Юниксом.
    В чистых процедурах все формальные параметры, кроме формальных процедур и ссылок, должны иметь вид связи:

    для функций - только INTENT(IN);

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

    обладать атрибутом SAVE;

    быть инициализированными в операторах объявления или DATA.
    В чистых процедурах имеются ограничения на использование:
    282

    8. Программные единицы

    глобальных переменных;

    формальных параметров с видом связи INTENT(IN) или с необъявленным видом связи;

    объектов, ассоциируемых по памяти с какими-либо глобальными переменными.
    Ограничения таковы: перечисленные объекты не должны использоваться:
    1)
    в случаях, когда возможно изменение их значения. Это может произойти, если переменная является:

    левой частью оператора присваивания или прикрепления ссылки (если объект является ссылкой);

    фактическим параметром, ассоциированным с формальным параметром с видом связи INTENT(OUT или INOUT) или обладающим атрибутом
    POINTER;

    индексной переменной операторов DO, FORALL или встроенного DO- цикла;

    переменной оператора ASSIGN;

    элементом списка ввода оператора READ;

    именем внутреннего файла оператора WRITE;

    объектом операторов ALLOCATE, DEALLOCATE или NULLIFY;

    спецификатором IOSTAT или SIZE операторов В/В или STAT операторов ALLOCATE и DEALLOCATE;
    2)
    в создании ссылки, например в качестве адресата или в качестве элемента правой части оператора присваивания переменной производного типа, если он имеет ссылочный компонент на любом из его уровней.
    Чистые процедуры не должны содержать:

    операторы В/В во внешние файлы или устройства;

    операторы PAUSE и STOP.
    Чистые процедуры предназначены для вызова в тех случаях, когда вызов иных, не владеющих ключевым словом PURE процедур недопустим:

    в операторе FORALL или его выражении-маске;

    из другой чистой процедуры.
    Также только чистую процедуру можно использовать в качестве параметра другой чистой процедуры.
    Если чистая процедура используется в приведенных ситуациях, то ее интерфейс должен быть задан явно и она должна быть объявлена в нем с ключевым словом PURE. Напомним, что все встроенные процедуры являются чистыми и по умолчанию обладают явным интерфейсом.
    Пример:
    pure function decr(k, m) real(4) :: decr
    283

    О. В. Бартеньев. Современный ФОРТРАН
    integer(4), intent(in) :: k, m
    ! Формальные параметры чистой функции decr = real(m) / real(k)
    ! должны иметь вид связи INTENT(IN) end function decr program pudem real(4), dimension(5, 5) :: array = 5.0 interface pure function decr(k, m)
    ! Поскольку функция используется в FORALL, real(4) :: decr
    ! то необходимо задать ее интерфейс integer(4), intent(in) :: k, m end function decr end interface forall(i = 1:5, j = 1:5) array(i, j) = decr(i, j) print '(10f5.1)', array(1, :)
    ! 1.0 2.0 3.0 4.0 5.0 end program pudem
    Замечание. Чистые процедуры введены стандартом 1995 г.
    8.26. Элементные процедуры
    Элементные пользовательские процедуры подобно встроенным элементным процедурам могут иметь в качестве фактических параметров либо скаляры, либо массивы. В последнем случае массивы должны быть согласованы, т. е. иметь одинаковую форму; результатом процедуры является поэлементная обработка массивов - фактических параметров.
    Приведем пример выполнения встроенной элементной функции MOD, возвращающей остаток от деления первого параметра на второй: integer(4), dimension(5) :: a = (/ 1, 2, 3, 4, 5 /), b = (/ 1, 2, -2, 4, 3 /), c integer(4) :: d c = mod(a, b)
    ! Параметры функции - массивы print *, c
    ! 0 0 1 0 2 d = mod(b(4), a(3))
    ! Параметры функции - скаляры print *, d
    ! 1
    Программная единица, вызывающая элементную функцию, должна содержать ее интерфейс, в котором явно указано слово ELEMENTAL.
    Цель введения элементных функций - упростить распараллеливание вычислений на многопроцессорных машинах: компилятор, имеющий сведения о том, что функция элементная, выполняет распараллеливание по заложенным в него правилам.
    Элементные функции - это чистые функции, имеющие только скалярные формальные параметры, не являющиеся ссылками или процедурами. Вид связи параметров - INTENT(IN). Результирующая переменная элементной функции также является скаляром и не может быть ссылкой. Элементная функция снабжается ключевым словом ELEMENTAL, которое автоматически подразумевает ключевое слово PURE. Элементные функции не могут быть оснащены ключевым словом RECURSIVE.
    284

    8. Программные единицы
    Если фактическими параметрами элементной функции являются массивы, то они должны быть согласованы; результатом такой функции является массив, согласованный с массивами-параметрами.
    Пример: elemental integer(4) function find_c(a, b) integer(4), intent(in) :: a, b
    ! Не забываем задать вид связи INTENT(IN) if(a > b) then find_c = a else if(b < 0) then find_c = abs(b) else find_c = 0 end if end function find_c program etest interface
    ! Интерфейс обязателен elemental integer(4) function find_c(a, b) integer(4), intent(in) :: a, b
    ! Обязательное задание вида связи INTENT(IN) end function find_c end interface integer(4), dimension(5) :: a = (/ -1, 2, -3, 4, 5 /), b = (/ 1, 2, -2, 4, 3 /), c integer(4) :: d = 5 c = find_c(a, b)
    ! Параметры функции - массивы print *, c
    ! 0 0 2 0 5 d = find_c(-1, 1)
    ! Параметры функции - скаляры print *, d
    ! 0 end program etest
    Замечание. Поскольку элементные функции являются чистыми, они могут быть использованы в операторе и конструкции FORALL.
    Элементные подпрограммы задаются подобно элементным функциям.
    В теле процедуры могут изменяться параметры с видом связи OUT и INOUT.
    Пример:
    elementalsubroutine find_c(a, b, c) integer(4), intent(in) :: a, b integer(4), intent(out) :: c if(a > b) then c = a else if(b < 0) then c = abs(b) else c = 0
    285

    О. В. Бартеньев. Современный ФОРТРАН
    end if end subroutine find_c program etest2 interface elemental subroutine find_c(a, b, c) integer(4), intent(in) :: a, b integer(4), intent(out) :: c end subroutine end interface integer(4), dimension(5) :: a = (/ -1, 2, -3, 4, 5 /), b = (/ 1, 2, -2, 4, 3 /), c integer(4) :: d = 5
    286

    8. Программные единицы call find_c(a, b, c)
    ! Параметры и результат - массивы print *, c
    ! 0 0 2 0 5 call find_c(-1, 1, d)
    ! Параметры и результат - скаляры print *, d
    ! 0 end program etest2
    Замечание. Элементные процедуры введены стандартом 1995 г.
    8.27. Операторные функции
    Если некоторое выражение встречается в программной единице неоднократно, то его можно оформить в виде операторной функции и заменить все вхождения выражения на эту функцию. Операторные функции задаются так:
    имя функции ([список формальных параметров]) = выражение
    Если список формальных параметров содержит более одного имени, то имена разделяются запятыми.
    Как и встроенная или внешняя функция, операторная функция вызывается в выражении. Областью видимости операторной функции является программная единица, в которой эта функция определена. В то же время операторная функция может быть доступна в других программных единицах за счет ассоциирования через носитель или use-ассоциирования, но не может быть ассоциирована через параметры процедуры. Тип операторной функции следует объявлять явно, размещая ее имя в операторе объявления типа или в операторе IMPLICIT.
    Пример. Выполнить табуляцию функции z = siny
    *
    e
    -x
    real(8) :: x = -1.0_8, y, z
    ! Используем двойную точность real(8) :: dx = 0.4_8, dy = 0.3_8 z(x, y) = exp(-x) * sin(y)
    ! Задание операторной функции z(x, y) write(*, '(6h x/y , 20f8.2)') (y, y = -0.6, 0.6, 0.3) do while(x <= 1.0_8) write(*, '(f6.2 \)') x
    ! Вывод x без перехода на новую строку y = -0.60_8 do while(y <= 0.6_8) write(*, '(f8.2 \)') z(x, y)
    ! Вывод z без перехода на новую строку y = y + dy end do x = x + dx write(*, *)
    ! Переход на новую строку end do end
    Замечание. Для вывода без продвижения на новую строку используется преобразование обратного слеша (\).
    287

    О. В. Бартеньев. Современный ФОРТРАН
    8.28. Строка INCLUDE
    В больших программах исходный код целесообразно хранить в разных файлах. Это упрощает работу над фрагментами программы и над программой в целом. Включение исходного кода одного файла в код другого можно выполнить при помощи директивы $INCLUDE или строки
    INCLUDE, имеющей вид:
    INCLUDE 'имя файла'
    имя файла - заключенное в апострофы или двойные кавычки имя текстового файла с исходным кодом фрагмента Фортран-программы. При необходимости имя файла должно содержать и путь к файлу.
    Строка INCLUDE не является оператором Фортрана. Она вставляет содержимое текстового файла в то место программной единицы, где он расположен. При этом строка INCLUDE замещается вставляемым текстом.
    Компилятор рассматривает содержимое вставленного файла как часть исходной программы и выполняет компиляцию этой части сразу после ее вставки. После завершения компиляции вставленного файла компилятор продолжает компиляцию исходной программной единицы начиная с оператора, следующего сразу после строки INCLUDE.
    Включаемый файл может содержать другие строки INCLUDE, но не должен прямо или косвенно ссылаться сам на себя. Такие включаемые файлы называются вложенными. Компилятор позволяет создавать вложенные включаемые файлы, содержащие до 10 уровней вложения с любым набором строк INCLUDE.
    Первая строка включаемого файла не должна быть строкой продолжения, а его последняя строка не должна содержать перенос. Перед оператором не может быть поставлена метка.
    В Фортране include-файлы рассматриваются как избыточное средство языка и могут быть практически полностью и с большим эффектом заменены модулями. Модули не только обеспечивают доступ к расположенным в модуле операторам объявления и описания и размещенным после оператора CONTAINS модульным процедурам, но и позволяют выполнять (за счет use-ассоциирования) обмен данными между использующими модули программными единицами.
    8.29. Порядок операторов и директив
    Операторы и директивы в программных единицах должны появляться в приведенном в табл. 8.5 порядке.
    288

    8. Программные единицы
    Таблица 8.5. Последовательность операторов и директив
    $INTEGER, $REAL, $[NO]SRICT, $OPTIMIZE
    $ATTRIBUTES
    BLOCK DATA, FUNCTION, MODULE, PROGRAM, SUBROUTINE
    $[NO]DEBUG
    USE-операторы $[NO]DECLARE
    IMPLICIT NONE
    PARAMETER
    $DEFINE, $UNDEFINE
    IMPLICIT
    $IF, $IF DEFINED
    Определения производных типов
    $ELSE, $ELSEIF, $END IF
    Интерфейсные блоки
    $FIXFORMLINESIZE
    Операторы объявления типа PARAMETER
    ENTRY
    $[NO]FREEFORM
    Операторы объявления DATA
    FORMAT
    $INCLUDE,
    $LINE
    Операторные функции
    $LINESIZE,
    $[NO]LIST
    Исполняемые операторы DATA $MESSAGE
    CONTAINS $OBJCOMMENT,
    $PACK
    Внутренние и модульные процедуры $PAGE,
    $PAGESIZE
    END $SUBTITLE,
    $TITLE
    В табл. 8.6 для разных программных компонентов указаны операторы, которые могут в них появляться. Строка "Объявления" подразумевает операторы PARAMETER, IMPLICIT, объявления типов данных и их атрибутов.
    Таблица 8.6. Операторы программных компонентов
    Операторы
    Главная
    программа
    Модуль
    BLOCK
    DATA
    Внешняя
    процедура
    Модульная
    процедура
    Внутренняя
    процедура
    Тело
    интерфейса
    USE
    Да
    Да
    Да
    Да
    Да
    Да
    Да
    ENTRY
    Нет
    Нет
    Нет
    Да
    Да
    Нет
    Нет
    FORMAT
    Да
    Нет
    Нет
    Да
    Да
    Да
    Нет
    Объявления
    Да
    Да
    Да
    Да
    Да
    Да
    Да
    DATA
    Да
    Да
    Да
    Да
    Да
    Да
    Нет
    Определения производных типов
    Да
    Да
    Да
    Да
    Да
    Да
    Да
    Интерфейсные блоки
    Да
    Да
    Нет
    Да
    Да
    Да
    Да
    Операторные функции
    Да
    Нет
    Нет
    Да
    Да
    Да
    Нет
    Исполняемые операторы
    Да
    Нет
    Нет
    Да
    Да
    Да
    Нет
    CONTAINS
    Да
    Да
    Нет
    Да
    Да
    Нет
    Нет
    289

    9. Форматный ввод/вывод
    Данные в памяти ЭВМ хранятся в двоичной форме, представляя собой последовательность нулей и единиц. С особенностями представления различных типов данных в ЭВМ можно познакомиться, например, в [5].
    Употребляемые в Фортране модели данных целого и вещественного типа рассмотрены в разд. 6.11.1.
    Входные и выходные данные часто необходимо представить в ином, отличном от внутреннего представления виде. Тогда и возникает задача преобразования данных из входной формы в машинное (внутреннее) представление и, наоборот, из машинного представления во внешнее, например текстовое или графическое.
    Стандартные средства Фортрана поддерживают 4 вида В/В данных:

    форматный;

    под управлением списка В/В;

    неформатный;

    двоичный.
    Первые два вида предназначены для преобразования текстовой информации во внутреннее представление при вводе и, наоборот, из внутреннего представления в текстовое при выводе. Выполняемые преобразования при форматном В/В задаются списком дескрипторов преобразований. Управляемый списком В/В по существу является разновидностью форматного В/В: преобразования выполняются по встроенным в Фортран правилам в соответствии с типами и значениями элементов списка В/В. Управляющий передачей данных список может быть именованным или неименованным.
    В настоящей главе мы рассмотрим только два первых вида передачи данных: форматный и под управлением списка. Неформатный и двоичный
    В/В рассмотрены в гл. 10.
    1   ...   27   28   29   30   31   32   33   34   ...   49


    написать администратору сайта