Возможности языка Fortran 95

Стандарт языка программирования Фортран, издание 1995 г.

Это обзор возможностей языка Fortran 95. Включены дополнительные возможности TR-15581:Enhanced Data Type Facilities, которые были реализованы повсеместно. Старые возможности, которые были заменены новыми, не описаны — немногие из этих исторических возможностей используются в современных программах, хотя большинство из них были сохранены в языке для поддержания обратной совместимости . Дополнительные возможности последующих стандартов, вплоть до Fortran 2023, описаны в стандартном документе Fortran 2023, ISO/IEC 1539-1:2023. Многие из его новых возможностей все еще реализуются в компиляторах. [1]

Элементы языка

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

Основы

Основным компонентом языка Фортран является его набор символов . Его членами являются

  • буквы A ... Z и a ... z (которые эквивалентны вне контекста символа)
  • цифры 0 ... 9
  • подчеркивание _
  • специальные символы=  : + blank - * / ( ) [ ] , . $ ' ! "  % &  ; < >  ?

Токены , имеющие синтаксическое значение для компилятора, строятся из этих компонентов. Существует шесть классов токенов:

Этикетка123
Постоянный123.456789_long
Ключевое словоALLOCATABLE
Оператор.add.
Имяsolve_equation(до 31 символа, включая _)
Разделитель / ( ) (/ /) [ ] , = =>  :  ::  ;  %

Из токенов строятся утверждения . Их можно кодировать с помощью новой свободной исходной формы , которая не требует позиционирования в жесткой структуре столбцов:

FUNCTION string_concat ( s1 , s2 ) ! Это комментарий TYPE ( string ), INTENT ( IN ) :: s1 , s2 TYPE ( string ) string_concat string_concat % string_data = s1 % string_data ( 1 : s1 % length ) // & s2 % string_data ( 1 : s2 % length ) ! Это продолжение string_concat % length = s1 % length + s2 % length END FUNCTION string_concat                       

Обратите внимание на завершающие комментарии и завершающий знак продолжения. Может быть 39 строк продолжения и 132 символа в каждой строке. Пробелы имеют значение. Если токен или константа символа разделены на две строки:

 ... начало_имени ... 'очень длинная  & & строка '    

&Также требуется наличие лидирующей части на продолжении линии.

Внутренние типы данных

Fortran имеет пять внутренних типов данных : INTEGER, REAL, COMPLEX, LOGICALи CHARACTER. Каждый из этих типов может быть дополнительно охарактеризован видом . Вид, по сути, определяет внутреннее представление типа: для трех числовых типов он определяет точность и диапазон, а для двух других — специфику представления хранения. Таким образом, это абстрактное понятие, которое моделирует пределы представления типов данных; оно выражается как элемент набора целых чисел (например, это может быть {1, 2, 4, 8} для целых чисел, обозначающих байты хранения), но эти значения не определены Стандартом и не переносимы. Для каждого типа существует вид по умолчанию , который используется, если вид явно не указан. Для каждого внутреннего типа существует соответствующая форма литеральной константы . Числовые типы INTEGERи REALмогут быть только знаковыми (понятия знака для типа нет COMPLEX).

Литеральные константы и виды

ЦЕЛОЕ ЧИСЛО

Целочисленные литеральные константы типа по умолчанию имеют вид

1 0 - 999 32767 + 10    

Kind может быть определен как именованная константа. Если желаемый диапазон составляет ±10 kind , переносимый синтаксис для определения соответствующего kind two_bytes

ЦЕЛОЕ ЧИСЛО , ПАРАМЕТР :: two_bytes = SELECTED_INT_KIND ( 4 )     

что позволяет впоследствии определять константы вида

- 1234_два_байта + 1_два_байта 

Здесь two_bytes— параметр типа kind; это также может быть явная целочисленная литеральная константа по умолчанию, например

- 1234_2

но такое использование непереносимо.

Функция KIND возвращает значение параметра типа kind:

ВИД ( 1 ) ВИД ( 1_два_байта ) 

и RANGEфункция предоставляет фактический десятичный диапазон (поэтому пользователь должен выполнить фактическое сопоставление с байтами):

ДИАПАЗОН ( 1_два_байта )

Кроме того, в операторах DATA (инициализация) могут использоваться двоичные (B), восьмеричные (O) и шестнадцатеричные (Z) константы (часто неформально называемые «константами BOZ»):

B '01010101' O '01234567' Z '10fa'  
НАСТОЯЩИЙ

Существует как минимум два действительных типа — по умолчанию и один с большей точностью (он заменяет DOUBLE PRECISION). SELECTED_REAL_KINDФункции возвращают номер типа для требуемого диапазона и точности; для как минимум 9 десятичных знаков точности и диапазона от 10 −99 до 10 99 его можно указать как:

ЦЕЛОЕ ЧИСЛО , ПАРАМЕТР :: long = SELECTED_REAL_KIND ( 9 , 99 )      

и литералы впоследствии указаны как

1.7_длинный

Также существуют внутренние функции

ТИП ( 1.7_long ) ТОЧНОСТЬ ( 1.7_long ) ДИАПАЗОН ( 1.7_long )  

которые в свою очередь дают значение типа типа, фактическую точность (здесь не менее 9) и фактический диапазон (здесь не менее 99).

СЛОЖНЫЙ

COMPLEXТип данных состоит из двух целочисленных или действительных компонентов:

( 1 , 3.7_длинный ) 
ЛОГИЧНЫЙ

Существует только два основных значения логических констант: .TRUE.и .FALSE.. Здесь также могут быть разные виды. Логические не имеют собственных функций запроса видов, но используют виды, указанные для INTEGERs; вид по умолчанию LOGICALтакой же, как у INTEGER.

. ЛОЖЬ . . правда . _ один_байт 

и KINDфункция работает так, как и ожидалось:

ВИД (. ИСТИНА .)
ХАРАКТЕР

Формы литеральных констант для CHARACTERтипа данных:

'Строка' "Другой" ' ''''' '   

(последнее — пустая строка). Разрешены различные типы (например, для различения строк ASCII и UNICODE ), но не поддерживаются широко компиляторами. Опять же, значение типа задается функцией KIND:

ТИП ( 'ASCII' )

Числовая модель и внутренние функции

Числовые типы основаны на числовых моделях с соответствующими функциями запроса (чьи значения не зависят от значений их аргументов; аргументы используются только для предоставления вида). Эти функции важны для переносимого числового программного обеспечения:

DIGITS(X)Количество значащих цифр
EPSILON(X)Почти ничтожно мала по сравнению с единицей (реальной)
HUGE(X)Наибольшее число
MAXEXPONENT(X)Максимальный показатель модели (действительный)
MINEXPONENT(X)Минимальный показатель модели (действительный)
PRECISION(X)Точность десятичной дроби (действительная, комплексная)
RADIX(X)Основа модели
RANGE(X)Диапазон десятичных показателей
TINY(X)Наименьшее положительное число (действительное)

Скалярные переменные

Скалярные переменные, соответствующие пяти внутренним типам, определяются следующим образом:

INTEGER ( KIND = 2 ) :: i REAL ( KIND = long ) :: a COMPLEX :: current LOGICAL :: Pravda CHARACTER ( LEN = 20 ) :: word CHARACTER ( LEN = 2 , KIND = Kanji ) :: kanji_word             

где необязательный KINDпараметр указывает нестандартный вид, а ::нотация отделяет тип и атрибуты от имени(й) переменной(ых) и их необязательных начальных значений, что позволяет вводить полную спецификацию и инициализацию переменных в одном операторе (в предыдущих стандартах атрибуты и инициализаторы приходилось объявлять в нескольких операторах). Хотя в приведенных выше примерах это не требуется (поскольку нет дополнительных атрибутов и инициализации), большинство программистов на Fortran-90 привыкают использовать его везде.

LEN=спецификатор применим только к CHARACTERs и указывает длину строки (заменяя старую *lenформу). Явные KIND=и LEN=спецификаторы необязательны:

ХАРАКТЕР ( 2 , Кандзи ) :: kanji_word   

работает так же хорошо.

Есть еще несколько интересных особенностей характера. Так же как подстрока, как в

СИМВОЛ ( 80 ) :: строка ... = строка ( i : i ) ! подстрока      

раньше было возможно, теперь подстрока

'0123456789' ( я : я )

Также допускаются строки нулевой длины:

строка ( i : i - 1 ) ! строка нулевой длины 

Наконец, существует набор внутренних функций характера, примерами которых являются

ACHARIACHAR(для набора ASCII)
ADJUSTLADJUSTR
LEN_TRIMINDEX(s1, s2, BACK=.TRUE.)
REPEATSCAN(за один комплект)
TRIMVERIFY(для всего набора)

Производные типы данных

Для производных типов данных сначала необходимо определить форму типа:

ТИП персона ПЕРСОНАЖ ( 10 ) имя РЕАЛЬНЫЙ возраст КОНЕЦ ТИП персона   

и затем можно определить переменные этого типа:

ТИП ( человек ) ты , я  

Для выбора компонентов производного типа %используется квалификатор:

ваш % возраст

Литеральные константы производных типов имеют вид TypeName(1stComponentLiteral, 2ndComponentLiteral, ...):

вы = человек ( 'Смит' , 2 3,5 )   

который известен как конструктор структур . Определения могут ссылаться на ранее определенный тип:

ТИП точка REAL x , y КОНЕЦ ТИП точка ТИП треугольник ТИП ( точка ) a , b , c КОНЕЦ ТИП треугольник      

и для переменной типа треугольник, как в

ТИП ( треугольник ) т 

каждый компонент типа pointдоступен как

т % а т % б т % в  

которые, в свою очередь, имеют конечные компоненты типа real:

т % а % х т % а % у т % б % х и т.д.   

(Обратите внимание, что %был выбран квалификатор вместо точки ( .) из-за потенциальной неоднозначности с записью оператора, например .OR.).

Неявная и явная типизация

Если не указано иное, все переменные, начинающиеся с букв I, J, K, L, M и N, являются переменными по умолчанию INTEGERs, а все остальные — переменными по умолчанию REAL; другие типы данных должны быть явно объявлены. Это известно как неявная типизация и является наследием ранних дней FORTRAN. Эти значения по умолчанию могут быть переопределены с помощью IMPLICIT TypeName (CharacterRange)операторов, например:

НЕЯВНЫЙ КОМПЛЕКС ( Z ) НЕЯВНЫЙ ХАРАКТЕР ( A - B ) НЕЯВНЫЙ ВЕЩЕСТВЕННЫЙ ( C - H , N - Y )

Однако хорошей практикой является явное указание всех переменных, и этого можно добиться, вставив оператор IMPLICIT NONEв начало каждого программного модуля.

Массивы

Массивы считаются переменными сами по себе. Каждый массив характеризуется своим типом , рангом и формой (которая определяет пределы каждого измерения). Границы каждого измерения по умолчанию равны 1 и размеру , но произвольные границы могут быть явно указаны. DIMENSIONключевое слово является необязательным и считается атрибутом; если оно опущено, форма массива должна быть указана после имени переменной-массива. Например,

REAL :: a ( 10 ) INTEGER , РАЗМЕРНОСТЬ ( 0 : 100 , - 50 : 50 ) :: карта     

объявляет два массива, rank-1 и rank-2, элементы которых располагаются в порядке столбцов . Элементы, например,

а ( 1 ) а ( я * дж ) 

и являются скалярами. Индексы могут быть любым скалярным целочисленным выражением.

Разделы являются частями переменных массива и сами по себе являются массивами:

a ( i : j ) ! ранг один map ( i : j , k : l : m ) ! ранг два a ( map ( i , k : l )) ! индекс вектора a ( 3 : 2 ) ! нулевая длина      

Целые массивы и секции массивов являются объектами, имеющими значения массива. Константы, имеющие значения массива (конструкторы), доступны, заключенные в (/ ... /):

( / 1 , 2 , 3 , 4 / ) ( / ( ( / 1 , 2 , 3 / ), я = 1 , 4 ) / ) ( / ( я , я = 1 , 9 , 2 ) / ) ( / ( 0 , я = 1 , 100 ) / ) ( / ( 0,1 * я , я = 1 , 10 ) / )                                   

используя подразумеваемую нотацию цикла DO. Fortran 2003 позволяет использовать скобки: [1, 2, 3, 4]и [([1,2,3], i=1,4)]вместо первых двух примеров выше, и многие компиляторы теперь поддерживают это. Производный тип данных может, конечно, содержать компоненты массива:

ТИП триплет REAL , РАЗМЕРНОСТЬ ( 3 ) :: вершина КОНЕЦ ТИП триплет ТИП ( триплет ), РАЗМЕРНОСТЬ ( 4 ) :: t       

так что

  • t(2) является скаляром (структурой)
  • t(2)%vertex является компонентом массива скаляра

Инициализация данных

Переменным могут быть присвоены начальные значения, указанные в спецификации:

РЕАЛЬНЫЙ , РАЗМЕРНОСТЬ ( 3 ) :: a = ( / 0,1 , 0,2 , 0,3 / )         

и компоненту производного типа данных может быть присвоено начальное значение по умолчанию:

ТИП триплет REAL , РАЗМЕРНОСТЬ ( 3 ) :: вершина = 0.0 КОНЕЦ ТИП триплет      

Когда локальные переменные инициализируются внутри процедуры, они неявно приобретают атрибут SAVE:

РЕАЛЬНЫЙ , РАЗМЕРНОСТЬ ( 3 ) :: точка = ( / 0,0 , 1,0 , - 1,0 / )         

Это заявление эквивалентно

РЕАЛЬНЫЙ , РАЗМЕР ( 3 ), СОХРАНИТЬ :: точка = ( / 0.0 , 1.0 , - 1.0 / )          

для локальных переменных внутри подпрограммы или функции. Атрибут SAVE заставляет локальные переменные сохранять свое значение после вызова процедуры, а затем инициализировать переменную сохраненным значением при возврате в процедуру.

Атрибут ПАРАМЕТР

Именованную константу можно указать напрямую, добавив PARAMETERатрибут и значения константы к оператору типа:

REAL , РАЗМЕРНОСТЬ ( 3 ) , ПАРАМЕТР :: поле = ( /0.,1.,2./ ) ТИП ( триплет ) , ПАРАМЕТР :: t = триплет ( ( /0.,0.,0./ ) )                     

Заявление ДАННЫЕ

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

ТИП ( триплет ) :: t1 , t2 ДАННЫЕ t1 / триплет ( ( / 0. , 1. , 2. / ) ) / , t2 % вершина ( 1 ) / 12 3. / ДАННЫЕ массив ( 1 : 64 ) / 64 * 0 / ДАННЫЕ i , j , k / B '01010101' , O '77' , Z 'ff' /                 

Инициализационные выражения

Значения, используемые в операторах DATAи PARAMETERили с этими атрибутами, являются константными выражениями, которые могут включать ссылки на: конструкторы массивов и структур, элементарные встроенные функции с целочисленными или символьными аргументами и результатами, а также шесть трансформационных функций REPEAT, SELECTED_INT_KIND, TRIM, SELECTED_REAL_KIND, RESHAPEи TRANSFER(см. Встроенные процедуры):

ЦЕЛОЕ ЧИСЛО , ПАРАМЕТР :: long = SELECTED_REAL_KIND ( 12 ), & массив ( 3 ) = ( / 1 , 2 , 3 / )             

Спецификационные выражения

Можно указать сведения о переменных, используя любое неконстантное, скалярное, целочисленное выражение, которое также может включать ссылки на функции запроса:

ПОДПРОГРАММА s ( b , m , c ) ИСПОЛЬЗОВАТЬ mod ! содержит a REAL , DIMENSION (:, :) :: b REAL , DIMENSION ( UBOUND ( b , 1 ) + 5 ) :: x INTEGER :: m CHARACTER ( LEN =* ) :: c CHARACTER ( LEN = m + LEN ( c )) :: cc REAL ( SELECTED_REAL_KIND ( 2 * PRECISION ( a ))) :: z                                

Выражения и назначения

Скалярный числовой

Доступны обычные арифметические операторы +, -, *, /, **(приведены здесь в порядке возрастания приоритета).

Скобки используются для указания порядка оценки, где это необходимо:

а * б + в ! * первый а * ( б + в ) ! + первый      

Правила для скалярных числовых выражений и присваиваний учитывают нестандартные типы. Таким образом, смешанные числовые выражения и правила присваивания включают различные параметры типа типа ожидаемым образом:

real2 = integer0 + real1    

преобразуется integer0в действительное значение того же рода, что и real1; результат имеет тот же род и преобразуется в вид real2для присваивания.

Эти функции доступны для контролируемого округления действительных чисел до целых:

  • NINT: округлить до ближайшего целого числа, вернуть целочисленный результат
  • ANINT: округлить до ближайшего целого числа, вернуть действительный результат
  • INT: усечение (округление в сторону нуля), возврат целого результата
  • AINT: усечение (округление в сторону нуля), возврат действительного результата
  • CEILING: наименьшее целое значение, не меньшее аргумента (округление вверх) (Fortran-90)
  • FLOOR: наибольшее целое значение, не большее аргумента (округлено в меньшую сторону) (Fortran-90)

Скалярные реляционные операции

Для скалярных реляционных операций числовых типов существует набор встроенных операторов:

< <= == /= > >=.LT. .LE. .EQ. .NE. .GT. .GE.

(формы выше являются новыми для Fortran-90, а более старые эквивалентные формы приведены ниже). Примеры выражений:

a < b . AND . i /= j ! для числовых переменных flag = a == b ! для логических переменных flags            

Скалярные символы

В случае скалярных символов и заданныхCHARACTER(8) result

это законно писать

результат ( 3 : 5 ) = результат ( 1 : 3 ) ! перекрытие разрешено результат ( 3 : 3 ) = результат ( 3 : 2 ) ! нет назначения нулевой строки      

Конкатенация выполняется оператором '//'.

результат = 'abcde' // '123' имя файла = результат // '.dat'    

Производные типы данных

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

ТИП string80 INTEGER длина CHARACTER ( 80 ) значение КОНЕЦ ТИП string80 CHARACTER :: char1 , char2 , char3 ТИП ( string80 ) :: str1 , str2 , str3         

мы можем написать

str3 = str1 // str2 ! необходимо определить операцию str3 = str1 . concat . str2 ! необходимо определить операцию char3 = char2 // char3 ! только внутренний оператор str3 = char1 ! необходимо определить присваивание            

Обратите внимание на « перегруженное » использование внутреннего символа //и именованного оператора .concat.. Разница между двумя случаями заключается в том, что для токена внутреннего оператора применяются обычные правила приоритета, тогда как для именованных операторов приоритет является наивысшим как у унарного оператора или низшим как у бинарного. В

вектор3 = матрица * вектор1 + вектор2 вектор3 = ( матрица . умножить на . вектор1 ) + вектор2           

эти два выражения эквивалентны только в том случае, если добавлены соответствующие скобки, как показано. В каждом случае в модуле должны быть определены процедуры, определяющие оператор и присваивание, а также соответствующая ассоциация оператор-процедура, как показано ниже:

ОПЕРАТОР ИНТЕРФЕЙСА ( // ) !Перегружает оператор // как вызывающий процедуру string_concat МОДУЛЬ ПРОЦЕДУРА string_concat КОНЕЦ ИНТЕРФЕЙСА  

Функция конкатенации строк — это более сложная версия той, что уже была показана в Basics. Обратите внимание, что для обработки состояния ошибки, которое возникает, когда две строки вместе превышают предустановленный предел в 80 символов, было бы безопаснее использовать подпрограмму для выполнения конкатенации (в этом случае перегрузка операторов не будет применима).

МОДУЛЬ string_type НЕЯВНЫЙ НЕТ  ТИП string80 ЦЕЛОЕ число длина СИМВОЛ ( LEN = 80 ) :: string_data КОНЕЦ ТИП string80 НАЗНАЧЕНИЕ ИНТЕРФЕЙСА ( = ) МОДУЛЬ ПРОЦЕДУРА c_to_s_assign , s_to_c_assign КОНЕЦ ИНТЕРФЕЙС ОПЕРАТОР  ИНТЕРФЕЙСА ( // ) МОДУЛЬ ПРОЦЕДУРА string_concat КОНЕЦ ИНТЕРФЕЙС  СОДЕРЖИТ ПОДПРОГРАММУ c_to_s_assign ( s , c ) ТИП ( string80 ), НАМЕРЕНИЕ ( OUT ) :: s СИМВОЛ ( LEN =* ), НАМЕРЕНИЕ ( IN ) :: c s % string_data = c s % длина = LEN ( c ) КОНЕЦ ПОДПРОГРАММА c_to_s_assign ПОДПРОГРАММА s_to_c_assign ( c , s ) ТИП ( string80 ), INTENT ( IN ) :: s CHARACTER ( LEN =* ), INTENT ( OUT ) :: c c = s % string_data ( 1 : s % length ) КОНЕЦ ПОДПРОГРАММЫ s_to_c_assign ТИП ( string80 ) ФУНКЦИЯ string_concat ( s1 , s2 ) ТИП ( string80 ), INTENT ( IN ) :: s1 , s2 ТИП ( string80 ) :: s ЦЕЛОЕ ЧИСЛО :: n1 , n2 СИМВОЛ ( 160 ) :: ctot n1 = LEN_TRIM ( s1 % string_data ) n2 = LEN_TRIM ( s2 %                                                                    string_data ) IF ( n1 + n2 <= 80 ) then s % string_data = s1 % string_data ( 1 : n1 ) // s2 % string_data ( 1 : n2 ) ELSE ! Это ошибочное состояние, которое следует обработать - сейчас просто усекаем ctot = s1 % string_data ( 1 : n1 ) // s2 % string_data ( 1 : n2 ) s % string_data = ctot ( 1 : 80 ) END IF s % length = LEN_TRIM ( s % string_data ) string_concat = s END FUNCTION string_concat END MODULE string_type                        ПРОГРАММА main USE string_type TYPE ( string80 ) :: s1 , s2 , s3 CALL c_to_s_assign ( s1 , 'Меня зовут' ) CALL c_to_s_assign ( s2 , 'Линус Торвальдс' ) s3 = s1 // s2 WRITE ( * , * ) 'Результат: ' , s3 % string_data WRITE ( * , * ) 'Длина: ' , s3 % length КОНЕЦ ПРОГРАММЫ               

Определенные операторы, подобные этим, требуются для выражений, которые также разрешены в конструкторах структур (см. Производные типы данных):

str1 = string ( 2 , char1 // char2 ) ! конструктор структуры    

Массивы

В случае массивов, если они имеют одинаковую форму (согласующиеся), операции и присваивания расширяются очевидным образом, поэлементно. Например, данные объявления

REAL , РАЗМЕРНОСТЬ ( 10 , 20 ) :: a , b , c REAL , РАЗМЕРНОСТЬ ( 5 ) :: v , w ЛОГИЧЕСКИЙ флаг ( 10 , 20 )           

можно записать:

a = b ! присваивание всего массива c = a / b ! деление всего массива и присваивание c = 0. ! присваивание всего массива скалярному значению w = v + 1. ! сложение всего массива со скалярным значением w = 5 / v + a ( 1 : 5 , 5 ) ! деление массива и сложение с разделом flag = a == b ! проверка отношения всего массива и присваивание c ( 1 : 8 , 5 : 10 ) = a ( 2 : 9 , 5 : 10 ) + b ( 1 : 8 , 15 : 20 ) ! сложение и присваивание раздела массива v ( 2 : 5 ) = v ( 1 : 4 ) ! присваивание перекрывающегося раздела                                  

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

Некоторые реальные внутренние функции, которые полезны для числовых вычислений:

  • CEILING
  • FLOOR
  • MODULO(также целое число)
  • EXPONENT
  • FRACTION
  • NEAREST
  • RRSPACING
  • SPACING
  • SCALE
  • SET_EXPONENT

Это массив значений для аргументов массива (элементарные), как и все функции FORTRAN 77 (кроме LEN):

  • INT
  • REAL
  • CMPLX
  • AINT
  • ANINT
  • NINT
  • ABS
  • MOD
  • SIGN
  • DIM
  • MAX
  • MIN

Степени, логарифмы и тригонометрические функции

  • SQRT
  • EXP
  • LOG
  • LOG10
  • SIN
  • COS
  • TAN
  • ASIN
  • ACOS
  • ATAN
  • ATAN2
  • SINH
  • COSH
  • TANH

Комплексные числа:

  • AIMAG
  • CONJG

Ниже приведены данные для персонажей:

  • LGE
  • LGT
  • LLE
  • LLT
  • ICHAR
  • CHAR
  • INDEX

Контрольные заявления

Ветвление и условия

Простая GO TO метка существует, но ее обычно избегают — в большинстве случаев более конкретная конструкция ветвления позволит реализовать ту же логику с большей ясностью.

Простейшим условным тестом является IFутверждение:IF (a > b) x = y

Полноценная IFконструкция проиллюстрирована

ЕСЛИ ( i < 0 ) ТО  ЕСЛИ ( j < 0 ) ТО x = 0. ИНАЧЕ z = 0. КОНЕЦ ЕСЛИ ИНАЧЕ ЕСЛИ ( k < 0 ) ТО z = 1. ИНАЧЕ x = 1. КОНЕЦ ЕСЛИ                          

Конструкция CASE

Эта CASEконструкция является заменой вычисляемой GOTO, но лучше структурирована и не требует использования меток операторов:

SELECT CASE ( number ) ! number of type integer CASE (: - 1 ) ! all values ​​less 0 n_sign = - 1 CASE ( 0 ) ! only 0 n_sign = 0 CASE ( 1 :) ! all values ​​more 0 n_sign = 1 END SELECT                 

Каждый CASEсписок селекторов может содержать список и/или диапазон целых чисел, символьных или логических констант, значения которых не могут перекрываться внутри или между селекторами:

ДЕЛО ( 1 , 2 , 7 , 10 : 17 , 23 )     

Доступно значение по умолчанию:

СЛУЧАЙ ПО УМОЛЧАНИЮ

Существует только одна оценка и только одно совпадение.

СДЕЛАЙТЕ конструкцию

Упрощенная, но достаточная форма конструкции DOпроиллюстрирована следующим образом:

внешний : DO внутренний : DO i = j , k , l ! от j до k с шагом l (l необязательно) : IF (...) CYCLE : IF (...) EXIT внешний : END DO внутренний END DO внешний                  

где мы отмечаем, что циклы могут быть необязательно названы, так что любой оператор EXIT или CYCLE может указывать, какой цикл имеется в виду.

Многие, но не все, простые циклы можно заменить выражениями массива и присваиваниями или новыми встроенными функциями. Например

tot = 0. DO i = m , n tot = tot + a ( i ) КОНЕЦ DO          

становится простоtot = SUM( a(m:n) )

Программные единицы и процедуры

Определения

Для обсуждения этой темы нам нужны некоторые определения. В логических терминах исполняемая программа состоит из одной основной программы и нуля или более подпрограмм (или процедур ) — они что-то делают. Подпрограммы — это либо функции , либо подпрограммы , которые являются внешними, внутренними или модульными подпрограммами. (Внешние подпрограммы — это то, что мы знали из FORTRAN 77.)

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

Пример основной (и полной) программы:

ПРОГРАММА тест ПЕЧАТЬ * , 'Привет, мир!' КОНЕЦ ПРОГРАММЫ тест   

Примером основной программы и внешней подпрограммы, образующих исполняемую программу, является

ПРОГРАММА test CALL print_message КОНЕЦ ПРОГРАММЫ test SUBROUTINE print_message ПЕЧАТЬ * , 'Привет, мир!' КОНЕЦ ПОДПРОГРАММЫ print_message    

Форма функции:

ФУНКЦИЯ имя ( arg1 , arg2 ) ! ноль или более аргументов : имя = ... : END ФУНКЦИЯ имя        

Форма ссылки функции:x = name(a, b)

Внутренние процедуры

Внутренняя подпрограмма содержится одна в другой (максимум на одном уровне вложенности) и обеспечивает замену функции оператора:

ПОДПРОГРАММА внешняя REAL x , y : СОДЕРЖИТ  ПОДПРОГРАММУ внутренняя REAL y y = x + 1. : КОНЕЦ ПОДПРОГРАММЫ внутренняя ! ПОДПРОГРАММА обязательна КОНЕЦ ПОДПРОГРАММЫ внешняя            

Мы говорим, что является outerхостом иinner что innerполучает доступ к сущностям в outerпосредством ассоциации с хостом (например, с x), тогда как yявляется локальной переменной для inner.

Областью действия именованной сущности является единица области действия , в данном случае outerменьше innerи inner.

Имена программных модулей и внешних процедур являются глобальными , а имена подразумеваемых переменных DO имеют область действия оператора, который их содержит.

Модули

Модули используются для упаковки

  • глобальные данные (заменяют COMMON и BLOCK DATA из Fortran 77);
  • определения типов (которые сами по себе являются единицей области действия);
  • подпрограммы (которые, помимо прочего, заменяют использование ENTRY из Fortran 77);
  • интерфейсные блоки (еще одна единица обзора, см. Интерфейсные блоки);
  • перечислите группы поимённо (см. любой учебник).

Примером модуля, содержащего определение типа, блок интерфейса и функциональную подпрограмму, является

MODULE interval_arithmetic ТИП интервал REAL нижний , верхний КОНЕЦ ТИП интервал ИНТЕРФЕЙС ОПЕРАТОР ( + ) МОДУЛЬ ПРОЦЕДУРА add_intervals КОНЕЦ ИНТЕРФЕЙС : СОДЕРЖИТ  ФУНКЦИЮ add_intervals ( a , b ) ТИП ( интервал ), НАМЕРЕНИЕ ( В ) :: a , b ТИП ( интервал ) add_intervals add_intervals % нижний = a % нижний + b % нижний add_intervals % верхний = a % верхний + b % верхний КОНЕЦ ФУНКЦИЯ add_intervals ! ФУНКЦИЯ обязательная : КОНЕЦ МОДУЛЬ interval_arithmetic                            

и простое утверждение

 ИСПОЛЬЗОВАТЬ интервальную арифметику

обеспечивает использование ассоциации для всех сущностей модуля. Подпрограммы модуля могут, в свою очередь, содержать внутренние подпрограммы.

Контроль доступности

Атрибуты PUBLICи PRIVATEиспользуются в спецификациях в модулях для ограничения области действия сущностей. Форма атрибута:

REAL , PUBLIC :: x , y , z ! default INTEGER , PRIVATE :: u , v , w           

и форма заявления

ОБЩЕСТВЕННЫЙ :: x , y , z , ОПЕРАТОР (. add .) ЧАСТНЫЙ :: u , v , w , ПРИСВОЕНИЕ ( = ), ОПЕРАТОР ( * )           

Форму заявления необходимо использовать для ограничения доступа операторов, а также ее можно использовать для изменения общего значения по умолчанию:

PRIVATE ! устанавливает значение по умолчанию для модуля PUBLIC :: only_this   

Для производных типов существует три возможности: тип и его компоненты являются PUBLIC, тип является PUBLIC, а его компоненты — PRIVATE (видим только тип, и можно легко изменить его данные), или все они являются PRIVATE (только для внутреннего использования в модуле):

МОДУЛЬ мой ЧАСТНЫЙ  ТИП , ОБЩИЙ :: список РЕАЛЬНЫЙ x , y ТИП ( список ), УКАЗАТЕЛЬ :: следующий КОНЕЦ ТИП список ТИП ( список ) :: дерево : КОНЕЦ МОДУЛЬ мой               

Целью оператора USEявляется получение доступа к сущностям в модуле. Он имеет опции для разрешения конфликтов имен, если импортированное имя совпадает с локальным:

ИСПОЛЬЗУЙТЕ мой , local_list => список   

или ограничить используемые сущности указанным набором:

ИСПОЛЬЗУЙТЕ мой , ТОЛЬКО : список   

Их можно комбинировать:

ИСПОЛЬЗУЙТЕ мой , ТОЛЬКО : local_list => list     

Аргументы

Мы можем указать цель фиктивных аргументов:

ПОДПРОГРАММА перетасовки ( ncards , карты ) ЦЕЛОЕ ЧИСЛО , НАМЕРЕНИЕ ( ВХОД ) :: ncards ЦЕЛОЕ ЧИСЛО , НАМЕРЕНИЕ ( ВЫХОД ), РАЗМЕР ( ncards ) :: карты           

Также возможен INOUT: здесь фактический аргумент должен быть переменной (в отличие от случая по умолчанию, где он может быть константой).

Аргументы могут быть необязательными:

ПОДПРОГРАММА mincon ( n , f , x , upper , lower , equalities , inequalityities , convex , xstart ) REAL , OPTIONAL , DIMENSION :: upper , lower : IF ( PRESENT ( lower )) THEN ! проверка на наличие фактического аргумента :                    

позволяет нам звонить minconпо

CALL mincon ( n , f , x , верхний )    

Аргументы могут быть ключевыми словами, а не позиционными (которые идут первыми):

CALL mincon ( n , f , x , равенства = 0 , xstart = x0 )    

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

Интерфейсные блоки

Любая ссылка на внутреннюю или модульную подпрограмму осуществляется через интерфейс, который является «явным» (то есть компилятор может видеть все детали). Ссылка на внешнюю (или фиктивную) процедуру обычно является «неявной» (компилятор предполагает детали). Однако в этом случае мы также можем предоставить явный интерфейс. Это копия заголовка, спецификаций и оператора END соответствующей процедуры, либо помещенная в модуль, либо вставленная напрямую:

REAL FUNCTION minimum ( a , b , func ) ! возвращает минимальное значение функции func(x) ! в интервале (a,b) REAL , INTENT ( in ) :: a , b INTERFACE REAL FUNCTION func ( x ) REAL , INTENT ( IN ) :: x END FUNCTION func END INTERFACE REAL f , x : f = func ( x ) ! вызов пользовательской функции. : END FUNCTION minimum                        

Явный интерфейс обязателен для

  • необязательные и ключевые аргументы;
  • Аргументы POINTER и TARGET (см. Указатели);
  • Результат функции POINTER;
  • новый стиль аргументов массива и функций массива (обработка массивов).

Он позволяет проводить полную проверку во время компиляции между фактическими и фиктивными аргументами.

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

Перегрузка и универсальные интерфейсы

Интерфейсные блоки предоставляют механизм, с помощью которого мы можем определять общие имена для конкретных процедур:

INTERFACE gamma ! общее имя FUNCTION sgamma ( X ) ! конкретное имя REAL ( SELECTED_REAL_KIND ( 6 )) sgamma , x END  FUNCTION dgamma ( X ) ! конкретное имя REAL ( SELECTED_REAL_KIND ( 12 )) dgamma , x END END INTERFACE               

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

ИНТЕРФЕЙС гамма МОДУЛЬ ПРОЦЕДУРА sgamma , dgamma КОНЕЦ ИНТЕРФЕЙС  

Мы можем использовать существующие имена, например, SIN, и компилятор подберет правильную ассоциацию.

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

Рекурсия

Косвенная рекурсия полезна для многомерной интеграции.

объем = интегрировать ( fy , ybounds )   

Мы могли бы иметь

РЕКУРСИВНАЯ ФУНКЦИЯ интегрировать ( f , bounds ) ! Интегрировать f(x) от bounds(1) до bounds(2) REAL интегрировать INTERFACE  FUNCTION f ( x ) REAL f , x END FUNCTION f END INTERFACE REAL , DIMENSION ( 2 ), INTENT ( IN ) :: bounds : END FUNCTION интегрировать              

и проинтегрировать f(x, y) по прямоугольнику:

ФУНКЦИЯ fy ( y ) ИСПОЛЬЗОВАТЬ func ! модуль func содержит функцию f REAL fy , y yval = y fy = integrated ( f , xbounds ) END           

Прямая рекурсия — это когда процедура вызывает сама себя, как в

РЕКУРСИВНАЯ ФУНКЦИЯ факториал ( n ) РЕЗУЛЬТАТ ( res ) ЦЕЛОЕ ЧИСЛО res , n ЕСЛИ ( n . EQ . 0 ) ТО res = 1 ИНАЧЕ res = n * факториал ( n - 1 ) КОНЕЦ ЕСЛИ КОНЕЦ             

Здесь мы отмечаем RESULTусловие и тест на прекращение.

Чистые процедуры

Это функция параллельных вычислений.

В операторе и конструкции FORALL любые побочные эффекты в функции могут помешать оптимизации на параллельном процессоре – порядок выполнения назначений может повлиять на результаты. Чтобы контролировать эту ситуацию, мы добавляем ключевое PUREслово к оператору SUBROUTINEor FUNCTION– утверждение, что процедура (выраженная просто):

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

Компилятор может проверить, что это так, например:

ЧИСТАЯ ФУНКЦИЯ вычислить ( x ) 

Все внутренние функции являются чистыми.

Обработка массивов

Обработка массивов включена в Fortran по двум основным причинам:

  • удобство записи, которое он обеспечивает, приближая код к базовой математической форме;
  • за дополнительные возможности оптимизации, которые он предоставляет компиляторам (хотя есть также много возможностей для ухудшения оптимизации!).

В то же время были добавлены серьезные расширения функционала в этой области. Целые массивы мы уже встречали выше #Arrays 1 и здесь #Arrays 2 - теперь развиваем тему.

Массивы нулевого размера

Массив нулевого размера обрабатывается Фортраном как законный объект, без специального кодирования программистом. Таким образом, в

ДЕЛАТЬ i = 1 , n x ( i ) = b ( i ) / a ( i , i ) b ( i + 1 : n ) = b ( i + 1 : n ) - a ( i + 1 : n , i ) * x ( i ) КОНЕЦ ДЕЛАТЬ                

Для последней итерации, где , не требуется специального кода i = n. Отметим, что массив нулевого размера считается определенным; однако массив формы (0,2) не согласуется с массивом формы (0,3), тогда как является допустимым оператором «ничего не делать».x(1:0) = 3

Массивы предполагаемой формы

Это расширение и замена для массивов предполагаемого размера. При наличии фактического аргумента, например:

РЕАЛЬНЫЙ , РАЗМЕРНОСТЬ ( 0:10 , 0:20 ) :: a : ВЫЗОВ подпрограммы ( a )     

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

ПОДПРОГРАММА sub ( da ) REAL , РАЗМЕР (:, :) :: da     

и это как если бы daбыли размерными (11,21). Однако мы можем указать любую нижнюю границу, и массив отобразится соответствующим образом.

РЕАЛЬНЫЙ , РАЗМЕРНОСТЬ ( 0 :, 0 :) :: da    

Передается форма, а не границы, где нижняя граница по умолчанию равна 1, а верхняя граница по умолчанию — соответствующему размеру.

Автоматические массивы

Частичная замена использованного EQUIVALENCE предоставляется этой возможностью, полезной для локальных временных массивов, как в

ПОДПРОГРАММА swap ( a , b ) REAL , DIMENSION (:) :: a , b REAL , DIMENSION ( SIZE ( a )) :: work work = a a = b b = work КОНЕЦ ПОДПРОГРАММЫ swap                   

Фактическое хранилище обычно размещается в стеке.

ВЫДЕЛЯЕМЫЙ и ВЫДЕЛЯЕМЫЙ

Fortran обеспечивает динамическое распределение памяти; он опирается на механизм хранения кучи (и заменяет другое использование EQUIVALENCE). Примером создания рабочего массива для всей программы является

MODULE work_array INTEGER n REAL , DIMENSION (:,:,:), ALLOCATABLE :: work КОНЕЦ МОДУЛЬНОЙ ПРОГРАММЫ main USE work_array READ ( input , * ) n ALLOCATE ( work ( n , 2 * n , 3 * n ), STAT = status ) : DEALLOCATE ( work )                  

Рабочий массив может быть распространен по всей программе с помощью USE оператора в каждом программном модуле. Мы можем указать явную нижнюю границу и выделить несколько сущностей в одном операторе. Чтобы освободить мертвое хранилище, мы пишем, например,

ОСВОБОДИТЬ ( a , b ) 

Освобождение массивов происходит автоматически, когда они выходят из области видимости.

Элементарные операции, задания и процедуры

Мы уже встречались с присваиваниями и операциями целых массивов:

REAL , DIMENSION ( 10 ) :: a , b a = 0. ! скалярная трансляция; элементное присваивание b = SQRT ( a ) ! результат встроенной функции как объект массива          

Во втором назначении встроенная функция возвращает массив-значный результат для массив-значного аргумента. Мы можем сами написать функции массив-значные (они требуют явного интерфейса):

PROGRAM test REAL , DIMENSION ( 3 ) :: a = ( / 1. , 2. , 3. / ), & b = ( / 2. , 2. , 2. / ), r r = f ( a , b ) PRINT * , r СОДЕРЖИТ  ФУНКЦИЮ f ( c , d ) REAL , DIMENSION (:) :: c , d REAL , DIMENSION ( SIZE ( c )) :: f f = c * d ! (или какая-то более полезная функция c и d) КОНЕЦ ФУНКЦИИ f КОНЕЦ ПРОГРАММЫ test                                        

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

Большинство встроенных функций являются элементарными, и Fortran 95 расширяет эту возможность на невстроенные процедуры, тем самым обеспечивая эффект написания на Fortran 90 22 различных версий для рангов 0-0, 0-1, 1-0, 1-1, 0-2, 2-0, 2-2, ... 7-7, и является дополнительным средством оптимизации на параллельных процессорах. Элементарная процедура должна быть чистой.

ЭЛЕМЕНТАРНАЯ ПОДПРОГРАММА swap ( a , b ) REAL , INTENT ( INOUT ) :: a , b REAL :: work work = a a = b b = work КОНЕЦ ПОДПРОГРАММЫ swap                  

Фиктивные аргументы не могут использоваться в выражениях спецификации (см. выше), за исключением аргументов определенных внутренних функций ( BIT_SIZE, KIND, LEN, и числовых функций запроса (см. ниже).

ГДЕ

Часто нам нужно замаскировать назначение. Это можно сделать с помощью WHERE, либо как оператор:

ГДЕ ( a /= 0.0 ) a = 1.0 / a ! избегайте деления на 0       

(примечание: проверка выполняется поэлементно, а не по всему массиву) или как конструкция:

WHERE ( a /= 0.0 ) a = 1.0 / a b = a ! все массивы одинаковой формы END WHERE          

или

ГДЕ ( a /= 0.0 ) a = 1.0 / a В ДРУГОМ МЕСТЕ a = ОГРОМНЫЙ ( a ) КОНЕЦ ГДЕ         

Дальше:

  • разрешается маскировать не только WHEREутверждение конструкции WHERE, но и любое ELSEWHEREутверждение, которое она содержит;
  • конструкция WHEREможет содержать любое количество замаскированных ELSEWHEREоператоров, но не более одного ELSEWHEREоператора без маски, и он должен быть последним;
  • WHERE конструкции могут быть вложены друг в друга, просто FORALLконструкции;
  • оператор WHEREприсваивания может быть определенным присваиванием при условии, что он является элементарным;
  • конструкция WHEREможет быть названа так же, как и другие конструкции.

Оператор и конструкция FORALL

При DOвыполнении конструкции каждая последующая итерация выполняется по порядку и одна за другой, что затрудняет оптимизацию на параллельном процессоре.

ДЛЯ ВСЕХ ( i = 1 : n ) a ( i , i ) = x ( i )      

где отдельные присваивания могут выполняться в любом порядке и даже одновременно. Их FORALLможно рассматривать как присваивание массива, выраженное с помощью индексов.

ДЛЯ ВСЕХ ( i = 1 : n , j = 1 : n , y ( i , j ) /= 0. ) x ( j , i ) = 1.0 / y ( i , j )     

с маскирующим состоянием.

Конструкция FORALLпозволяет выполнить несколько операторов присваивания по порядку.

а ( 2 : n - 1 , 2 : n - 1 ) = а ( 2 : n - 1 , 1 : n - 2 ) + а ( 2 : n - 1 , 3 : n ) + а ( 1 : n - 2 , 2 : n - 1 ) + а ( 3 : n , 2 : n - 1 ) б ( 2 : n - 1 , 2 : n - 1 ) = а ( 2 : n - 1 , 2 : n - 1 )          

эквивалентно присваиванию массива

ДЛЯ ВСЕХ ( i = 2 : n - 1 , j = 2 : n - 1 ) a ( i , j ) = a ( i , j - 1 ) + a ( i , j + 1 ) + a ( i - 1 , j ) + a ( i + 1 , j ) b ( i , j ) = a ( i , j ) КОНЕЦ ДЛЯ ВСЕХ                 

Версия FORALLболее читабельна.

Присваивание в a FORALLпохоже на присваивание массива: как если бы все выражения были оценены в любом порядке, удерживались во временном хранилище, затем все присваивания выполнялись в любом порядке. Первое выражение должно полностью завершиться, прежде чем второе может начаться.

A FORALLможет быть вложенным и может включать в себя WHERE. Процедуры, на которые ссылаются внутри , FORALLдолжны быть чистыми.

Элементы массива

Для простого случая, учитывая

РЕАЛЬНЫЙ , РАЗМЕРНОСТЬ ( 100 , 100 ) :: а    

мы можем ссылаться на один элемент, например, a(1, 1). Для производного типа данных, например

ТИП fun_del REAL u REAL , РАЗМЕР ( 3 ) :: du КОНЕЦ ТИП fun_del     

мы можем объявить массив такого типа:

ТИП ( fun_del ), РАЗМЕР ( 10 , 20 ) :: tar    

и ссылка типа — это элемент (скаляр!) типа fun_del, но это массив типа real, и является его элементом. Основное правило, которое следует запомнить, заключается в том, что элемент массива всегда имеет индекс или индексы, квалифицирующие как минимум фамилию.tar(n, 2)tar(n, 2)%dutar(n, 2)%du(2)

Массив подобъектов (разделов)

Общая форма индекса для раздела массива:

 [ нижний ] : [ верхний ] [ : шаг ]

(где [ ] указывает на необязательный элемент), как в

REAL a ( 10 , 10 ) a ( i , 1 : n ) ! часть одной строки a ( 1 : m , j ) ! часть одного столбца a ( i , : ) ! вся строка a ( i , 1 : n : 3 ) ! каждый третий элемент строки a ( i , 10 : 1 : - 1 ) ! строка в обратном порядке a ( ( / 1 , 7 , 3 , 2 / ), 1 ) ! векторный индекс a ( 1 , 2 : 11 : 2 ) ! 11 допустимо, так как не ссылается a ( :, 1 : 7 ) ! раздел ранга два                        

Обратите внимание, что векторный индекс с повторяющимися значениями не может появляться в левой части присваивания, так как это будет неоднозначно. Таким образом,

б ( ( / 1 , 7 , 3 , 7 / ) ) = ( / 1 , 2 , 3 , 4 / )              

недопустимо. Также раздел с индексом вектора не должен быть предоставлен как фактический аргумент для аргумента- пустышки OUTили INOUTфиктивного аргумента. Массивы массивов не допускаются:

tar % du ! незаконный 

Отметим, что на заданное значение в массиве можно ссылаться и как на элемент, и как на раздел:

a ( 1 , 1 ) ! скаляр (ранг ноль) a ( 1 : 1 , 1 ) ! раздел массива (ранг один)    

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

tar % u ! раздел массива (компонент структуры) tar ( 1 , 1 )% u ! компонент элемента массива   

Встроенные функции массивов

Умножение векторов и матриц

DOT_PRODUCTСкалярное произведение двух массивов ранга 1
MATMULУмножение матриц

Сокращение массива

ALLИстина, если все значения истинны
ANYTrue, если любое значение является true. Пример:IF (ANY( a > b)) THEN
COUNTКоличество истинных элементов в массиве
MAXVALМаксимальное значение в массиве
MINVALМинимальное значение в массиве
PRODUCTПроизведение элементов массива
SUMСумма элементов массива

Запрос массива

ALLOCATEDСтатус распределения массива
LBOUNDНижние границы размерности массива
SHAPEФорма массива (или скаляра)
SIZEОбщее количество элементов в массиве
UBOUNDВерхние границы размерности массива

Построение массива

MERGEОбъединить под маской
PACKУпаковать массив в массив ранга один под маской
SPREADСкопировать массив, добавив измерение
UNPACKРаспаковываем массив ранга один в массив под маской

Изменение формы массива

RESHAPEИзменить форму массива

Манипуляции с массивами

CSHIFTКруговой сдвиг
EOSHIFTКонец смены
TRANSPOSEТранспонирование массива ранга два

Расположение массива

MAXLOCРасположение первого максимального значения в массиве
MINLOCРасположение первого минимального значения в массиве

Указатели

Основы

Указатели — это переменные с POINTERатрибутом ; они не являются отдельным типом данных (и поэтому никакая «арифметика указателей» невозможна).

РЕАЛЬНЫЙ , УКАЗАТЕЛЬ :: var   

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

ВЫДЕЛИТЬ ( var ) 

и они автоматически разыменовываются, поэтому не требуется никаких специальных символов. В

вар = вар + 2,3    

используется и изменяется значение цели var. Указатели не могут передаваться через ввод-вывод. Оператор

ЗАПИСЬ * , вар  

записывает значение цели var, а не сам дескриптор указателя.

Указатель может указывать на другой указатель и, следовательно, на свою цель или на статический объект, имеющий TARGETатрибут:

REAL , POINTER :: object REAL , TARGET :: target_obj var => object ! назначение указателя var => target_obj           

но они строго типизированы:

ЦЕЛОЕ ЧИСЛО , УКАЗАТЕЛЬ :: int_var var => int_var ! незаконно - типы должны совпадать      

и, аналогично, для массивов должны совпадать как ранги, так и тип.

Указатель может быть компонентом производного типа:

ТИП запись ! тип для разреженной матрицы REAL :: значение INTEGER :: индекс ТИП ( запись ), POINTER :: следующий ! примечание рекурсия КОНЕЦ ТИП запись            

и мы можем определить начало связанной цепочки таких записей:

ТИП ( запись ), УКАЗАТЕЛЬ :: цепь   

После соответствующих распределений и определений первые две записи можно рассматривать как

цепочка % цепочка создания стоимости % следующая % цепочка создания стоимости % индекс цепочка % следующая % индекс цепочка % следующая цепочка % следующая % следующая 

но мы обычно определяем дополнительные указатели, указывающие, например, на первую и текущую записи в списке.

Ассоциация

Статус ассоциации указателя — один из

  • неопределено (исходное состояние);
  • ассоциированный (после выделения или назначения указателя);
  • диссоциированный:
    DEALLOCATE ( p , q ) ! для возврата хранилища NULLIFY ( p , q ) ! для установки в 'null'      

Необходимо соблюдать осторожность, чтобы не оставить указатель «висящим» при использовании DEALLOCATEего цели, не аннулировав при этом любой другой указатель, ссылающийся на него.

Встроенная функция ASSOCIATEDможет проверить статус ассоциации определенного указателя:

ЕСЛИ ( АССОЦИИРОВАННЫЙ ( ptr )) ТОГДА  

или между определенным указателем и определенной целью (которая сама может быть указателем):

ЕСЛИ ( АССОЦИИРОВАННЫЙ ( ptr , target )) ТОГДА   

Альтернативным способом инициализации указателя, также в операторе спецификации, является использование NULLфункции:

REAL , POINTER , DIMENSION (:) :: vector => NULL () ! время компиляции vector => NULL () ! время выполнения          

Указатели в выражениях и присваиваниях

Для внутренних типов мы можем 'прочесывать' указатели по разным наборам целевых данных, используя тот же код без какого-либо перемещения данных. Учитывая манипуляцию матрицей y = BC z , мы можем написать следующий код (хотя в этом случае тот же результат можно было бы получить проще другими способами):

REAL , TARGET :: b ( 10 , 10 ), c ​​( 10 , 10 ), r ( 10 ), s ( 10 ), z ( 10 ) REAL , POINTER :: a (:,:), x (:), y (:) INTEGER mult : DO mult = 1 , 2 IF ( mult == 1 ) THEN y => r ! нет перемещения данных a => c x => z ELSE y => s ! нет перемещения данных a => b x => r END IF y = MATMUL ( a , x ) ! общее вычисление END DO                                               

Для объектов производного типа мы должны различать указатель и обычное присваивание.

ТИП ( запись ), УКАЗАТЕЛЬ :: первый , текущий : первый => текущий      

назначение заставляет сначала указывать на ток, тогда как

первый = текущий  

заставляет текущий перезаписывать первым и эквивалентно

первый % значение = текущий % значение первый % индекс = текущий % индекс первый % следующий => текущий % следующий      

Аргументы указателя

Если фактический аргумент является указателем, то, если фиктивный аргумент также является указателем,

  • он должен иметь тот же ранг,
  • он получает свой ассоциативный статус от фактического аргумента,
  • он возвращает свой окончательный статус ассоциации фактическому аргументу (примечание: цель может быть неопределена!),
  • он может не иметь INTENTатрибута (это было бы неоднозначно),
  • для этого требуется блок интерфейса.

Если фиктивный аргумент не является указателем, он становится связанным с целью фактического аргумента:

 REAL , УКАЗАТЕЛЬ :: a (:,:) : ВЫДЕЛИТЬ ( a ( 80 , 80 )) : ВЫЗОВ sub ( a ) : ПОДПРОГРАММА sub ( c ) REAL c (:, :)             

Функции указателя

Результаты функции также могут иметь POINTERатрибут; это полезно, если размер результата зависит от вычислений, выполняемых в функции, как в

ИСПОЛЬЗОВАНИЕ data_handler REAL x ( 100 ) REAL , УКАЗАТЕЛЬ :: y (:) : y => compact ( x )     

где модуль data_handler содержит

FUNCTION compact ( x ) REAL , POINTER :: compact (:) REAL x (:) ! Процедура удаления дубликатов из массива x INTEGER n : ! Найти количество различных значений, n ALLOCATE ( compact ( n )) : ! Скопировать различные значения в compact END FUNCTION compact            

Результат можно использовать в выражении (но он должен быть связан с определенной целью).

Массивы указателей

Они не существуют как таковые: учитывая

ТИП ( запись ) :: строки ( n )  

затем

строки % следующие ! нелегально 

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

ТИП строка REAL , УКАЗАТЕЛЬ :: r (:) КОНЕЦ ТИП    

и затем определение массивов этого типа данных

ТИП ( строка ) :: s ( n ), t ( n )   

где хранилище для строк может быть выделено, например,

DO i = 1 , n ALLOCATE ( t ( i )% r ( 1 : i )) ! Выделить строку i длины i END DO      

Присвоение массива тогда эквивалентно присвоению указателей для всех компонентов.s = ts(i)%r => t(i)%r

Указатели как динамические псевдонимы

Дан массив

РЕАЛЬНЫЙ , ЦЕЛЕВОЙ :: таблица ( 100 , 100 )   

на который часто ссылаются с фиксированными индексами

таблица ( м : н , п : д ) 

эти ссылки могут быть заменены на

REAL , РАЗМЕРНОСТЬ (:, :), УКАЗАТЕЛЬ :: окно : окно => таблица ( m : n , p : q )         

Индексы окна — это . Аналогично, для (как уже определено в ), мы можем использовать, скажем, для указания на все компоненты u tar и индексировать его как1:n-m+1, 1:q-p+1tar%utaru => tar%utaru(1, 2)

Подстрочные индексы такие же, как у самого tar. (Это заменяет еще больше EQUIVALENCE.)

В ассоциации указателей

указатель => выражение_массива  

нижние границы для pointerопределяются так, как если бы lboundбыло применено к array_expression. Таким образом, когда указатель назначается всей переменной массива, он наследует нижние границы переменной, в противном случае нижние границы по умолчанию равны 1.

Fortran 2003 позволяет указывать произвольные нижние границы для ассоциации указателей, например

окно ( r :, s :) => таблица ( m : n , p : q )  

так что границы windowстановятся r:r+n-m,s:s+q-p. В Fortran 95 эта функция отсутствует; однако ее можно смоделировать с помощью следующего трюка (основанного на правилах ассоциации указателей для предполагаемых фиктивных аргументов массива форм):

ФУНКЦИЯ remap_bounds2 ( lb1 , lb2 , массив ) РЕЗУЛЬТАТ ( ptr ) ЦЕЛОЕ ЧИСЛО , НАМЕРЕНИЕ ( IN ) :: lb1 , lb2 ДЕЙСТВИТЕЛЬНОЕ , РАЗМЕР ( lb1 :, lb2 :), НАМЕРЕНИЕ ( IN ), ЦЕЛЬ :: массив ДЕЙСТВИТЕЛЬНОЕ , РАЗМЕР (:,:), УКАЗАТЕЛЬ :: ptr ptr => массив КОНЕЦ ФУНКЦИИ : окно => remap_bounds2 ( r , s , таблица ( m : n , p : q ))                      

Исходный код расширенного примера использования указателей для поддержки структуры данных находится в pointer.f90.

Внутренние процедуры

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

ВЫЗОВ ДАТА_И_ВРЕМЯ ( ВРЕМЯ = t ) 

и многие из них имеют необязательные аргументы.

Внутренние процедуры сгруппированы в четыре категории:

  1. элементарный - работа со скалярами или массивами, например ABS(a);
  2. запрос - независимый от значения аргумента (который может быть неопределенным), например PRECISION(a);
  3. трансформационный - аргумент массива с результатом массива другой формы, например RESHAPE(a, b);
  4. подпрограммы, например SYSTEM_CLOCK.

Процедуры, которые еще не введены, следующие:

Запрос бита

BIT_SIZEКоличество бит в модели

Манипуляция битами

BTESTТестирование бит
IANDЛогическое И
IBCLRОчистить бит
IBITSИзвлечение бита
IBSETУстановить бит
IEORИсключительное ИЛИ
IORИнклюзивное ИЛИ
ISHFTЛогический сдвиг
ISHFTCКруговой сдвиг
NOTЛогическое дополнение

Передаточная функция, как в

ЦЕЛОЕ ЧИСЛО :: i = ПЕРЕДАЧА ( 'abcd' , 0 )     

(заменяет часть ЭКВИВАЛЕНТНОСТИ)

Подпрограммы

DATE_AND_TIMEПолучить дату и/или время
MVBITSКопирует биты
RANDOM_NUMBERВозвращает псевдослучайные числа
RANDOM_SEEDДоступ к семенам
SYSTEM_CLOCKДоступ к системным часам
CPU_TIMEВозвращает процессорное время в секундах

Передача данных

Форматированный ввод/вывод

Эти примеры иллюстрируют различные формы списков ввода-вывода с некоторыми простыми форматами (см. ниже):

ЦЕЛОЕ ЧИСЛО :: i ДЕЙСТВИТЕЛЬНОЕ , РАЗМЕРНОСТЬ ( 10 ) :: a СИМВОЛ ( длина = 20 ) :: слово ПЕЧАТЬ "(i10)" , i ПЕЧАТЬ "(10f10.3)" , a ПЕЧАТЬ "(3f10.3)" , a ( 1 ), a ( 2 ), a ( 3 ) ПЕЧАТЬ "(a10)" , слово ( 5 : 14 ) ПЕЧАТЬ "(3f10.3)" , a ( 1 ) * a ( 2 ) + i , КОРЕНЬ ( a ( 3 : 4 ))                  

Переменные, но не выражения, одинаково допустимы во входных операторах, использующих READоператор:

ЧИТАЙТЕ "(i10)" , я  

Если массив отображается как элемент, он обрабатывается так, как если бы элементы были указаны в порядке элементов массива.

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

Элемент производного типа рассматривается так, как если бы компоненты были указаны в том же порядке, что и в объявлении типа, поэтому

читать "(8f10.5)" , p , t ! типы точка и треугольник    

имеет тот же эффект, что и утверждение

ЧИТАЙТЕ "(8f10.5)" , p % x , p % y , t % a % x , t % a % y , t % b % x , & t % b % y , t % c % x , t % c % y          

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

Обратите внимание, что массив нулевого размера может встречаться как элемент в списке ввода-вывода. Такой элемент не соответствует фактической передаче данных.

Спецификация формата может быть также задана в виде символьного выражения:

СИМВОЛ ( len =* ), параметр :: form = "(f10.3)" : PRINT form , q      

или как звездочка – это тип ввода-вывода, известный как ввод-вывод , управляемый списком (см. ниже), в котором формат определяется компьютерной системой:

PRINT * , "Квадратный корень из q = " , SQRT ( q )   

Операции ввода/вывода используются для передачи данных между хранилищем исполняемой программы и внешним носителем, указанным номером устройства . Однако два оператора ввода/вывода PRINTи вариант READне ссылаются ни на один номер устройства: это называется терминальным вводом/выводом. В противном случае форма будет следующей:

ЧИТАТЬ ( ЕДИНИЦА = 4 , FMT = "(f10.3)" ) q ЧИТАТЬ ( ЕДИНИЦА = nunit , FMT = "(f10.3)" ) q ЧИТАТЬ ( ЕДИНИЦА = 4 * i + j , FMT = "(f10.3)" ) a         

где UNIT=необязательно. Значение может быть любым неотрицательным целым числом, разрешенным системой для этой цели (но 0, 5 и 6 часто обозначают ошибку, клавиатуру и терминал соответственно).

Звездочка — это вариант — опять же с клавиатуры:

ЧИТАТЬ ( ЕДИНИЦА =* , FMT = "(f10.3)" ) q   

Чтение с указателем единицы измерения позволяет обрабатывать исключения :

READ ( UNIT = NUNIT , FMT = "(3f10.3)" , IOSTAT = ios ) a , b , c IF ( ios == 0 ) THEN ! Успешное чтение - продолжить выполнение. : ELSE ! Состояние ошибки - предпринять соответствующие действия. CALL error ( ios ) END IF           

Существует второй тип форматированного выходного оператора WRITE:

ЗАПИСЬ ( ЕДИНИЦА = nout , FMT = "(10f10.3)" , IOSTAT = ios ) а    

Внутренние файлы

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

ЦЕЛОЕ ЧИСЛО , РАЗМЕР ( 30 ) :: ival ЦЕЛОЕ ЧИСЛО :: key СИМВОЛ ( ДЛИНА = 30 ) :: буфер СИМВОЛ ( ДЛИНА = 6 ), РАЗМЕР ( 3 ), ПАРАМЕТР :: form = ( / "(30i1)" , "(15i2)" , "(10i3)" / ) READ ( ЕДИНИЦА =* , FMT = "(a30,i1)" ) буфер , key READ ( ЕДИНИЦА = буфер , FMT = form ( ключ )) ival ( 1 : 30 / ключ )                       

Если внутренний файл является скаляром, он имеет одну запись, длина которой равна длине скаляра.

Если это массив, его элементы, в порядке следования элементов массива, рассматриваются как последовательные записи файла, и каждая имеет длину, равную длине элемента массива.

Пример использования WRITEутверждения:

INTEGER :: день REAL :: наличные CHARACTER ( LEN = 50 ) :: строка : ! записать в строку WRITE ( UNIT = строка , FMT = "(a, i2, a, f8.2, a)" ) "Выручка за день " , день , " составляет " , наличные , " долларов"             

которые могли бы написать

Выручка за 3-й день составила 4329,15 долларов.

Ввод-вывод, управляемый списком

Пример чтения без указанного формата для ввода:

ЦЕЛОЕ ЧИСЛО :: i ДЕЙСТВИТЕЛЬНОЕ :: a КОМПЛЕКСНОЕ , РАЗМЕРНОСТЬ ( 2 ) :: поле ЛОГИЧЕСКОЕ :: флаг СИМВОЛ ( ДЛИНА = 12 ) :: заголовок СИМВОЛ ( ДЛИНА = 4 ) :: слово : ЧИТАТЬ * , i , a , поле , флаг , заголовок , слово                    

Если это считывает входную запись

10 6,4 ( 1,0 , 0,0 ) ( 2,0 , 0,0 ) t тест /     

(в котором в качестве разделителей используются пробелы), то i, a, field, flag, и titleприобретут значения 10, 6,4, (1,0,0,0) и (2,0,0,0) .true.и testсоответственно, а wordостанется неизменным.

Кавычки или апострофы необходимы в качестве разделителей для строки, содержащей пробел.

Непрогрессирующий ввод-вывод

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

CHARACTER ( LEN = 3 ) :: key INTEGER :: u , s , ios : READ ( UNIT = u , FMT = "(a3)" , ADVANCE = "no" , SIZE = s , IOSTAT = ios ) key IF ( ios == 0 ) THEN : ELSE ! key не находится ни в одной записи key ( s + 1 :) = "" : END IF                    

При непродвижении можно прочитать первые несколько символов записи, а при обычном чтении — оставшуюся часть.

Чтобы вывести приглашение на экран терминала и прочитать его со следующей позиции символа на экране без промежуточного перевода строки, мы можем написать:

WRITE ( UNIT =* , FMT = "(a)" , ADVANCE = "no" ) "введите следующее простое число:" READ ( UNIT =* , FMT = "(i10)" ) простое_число       

Непрогрессирующий ввод-вывод предназначен для внешних файлов и недоступен для ввода-вывода, управляемого списком.

Редактировать дескрипторы

Можно указать, что дескриптор редактирования должен повторяться указанное количество раз, используя счетчик повторов :10f12.3

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

ПЕЧАТЬ "(2(2i5,2f8.2))" , я ( 1 ), я ( 2 ), а ( 1 ) , а ( 2 ) , я ( 3 ) , я ( 4 ) , а ( 3 ), а ( 4 )   

Все спецификации формата могут быть повторены:

ПЕЧАТЬ "(10i8)" , ( / ( i ( j ), j = 1 , 200 ) / )     

записывает 10 целых чисел, каждое из которых занимает 8 позиций символов, на каждой из 20 строк (повторение спецификации формата приводит к переходу на следующую строку).

Дескрипторы редактирования данных

  • Целое число: iW iW.M
  • Настоящий: fW.D esW.D esW.DeE
  • Сложные: пары fили esдескрипторы редактирования
  • Логично: lW
  • Характер: a aW
  • Производные типы: редактируются с помощью соответствующей последовательности дескрипторов редактирования, соответствующих внутренним типам конечных компонентов производного типа.
    ТИП , PUBLIC :: строка ЦЕЛОЕ ЧИСЛО :: длина СИМВОЛ ( ДЛИНА = 20 ) :: слово КОНЕЦ ТИП строка ТИП ( строка ) :: текст ЧИТАТЬ ( ЕДИНИЦА =* , FMT = "(i2, a)" ) текст             

Управление дескрипторами редактирования

Условия настройки дескрипторов редактирования управления :

  • Дескриптор ssредактирования (sign suppress) подавляет начальные знаки плюс. Для включения печати знака плюс spиспользуется дескриптор (sign print). sДескриптор редактирования восстанавливает опцию для процессора.
  • Этот дескриптор остается в силе для оставшейся части спецификации формата, если не выполняется другое из них.

Управление дескрипторами редактирования для немедленной обработки :

  • Табуляция:tN trN tlN
    ЧИТАТЬ ( ЕДИНИЦА =* , FMT = "(t3,i4, tl4,i1, i2)" ) i , j , k   
  • Новые рекорды: / N/
    ЧИТАЙТЕ "(i5,i3,/,i5,i3,i2 ) " , я , к , л , м      

    Обратите внимание, что

    ПЕЧАТЬ "(i5,4/,i5)" , i , j   
    разделяет два значения тремя пустыми записями.
  • Редактирование двоеточием:  :завершает управление форматом, если в списке ввода-вывода больше нет элементов.
    ПЕЧАТЬ "( i5, :, /, i5, :, /, i5)" , ( / ( l ( i ), i = 1 , n ) / )   
    останавливает новые записи, если nравно 1 или 2.

Неформатированный ввод/вывод

Этот тип ввода-вывода следует использовать только в тех случаях, когда записи генерируются программой на одном компьютере и считываются на том же компьютере или другом компьютере с использованием тех же внутренних числовых представлений:

ОТКРЫТЬ ( ЕДИНИЦА = 4 , ФАЙЛ = 'test' , ФОРМА = 'неформатированный' ) ЧТЕНИЕ ( ЕДИНИЦА = 4 ) q ЗАПИСЬ ( ЕДИНИЦА = nout , IOSTAT = ios ) a !no fmt=      

Файлы прямого доступа

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

INTEGER , PARAMETER :: nunit = 2 , length = 100 REAL , DIMENSION ( length ) :: a REAL , DIMENSION ( length + 1 : 2 * length ) :: b INTEGER :: i , rec_length : INQUIRE ( IOLENGTH = rec_length ) a OPEN ( UNIT = nunit , ACCESS = "direct" , RECL = rec_length , STATUS = "scratch" , ACTION = "readwrite" ) : ! Записать массив b в файл прямого доступа в запись 14 WRITE ( UNIT = nunit , REC = 14 ) b : ! ! Считать массив обратно в массив a READ ( UNIT = nunit , REC = 14 ) a : DO i = 1 , length / 2 a ( i ) = i END DO ! ! Заменить измененную запись WRITE ( UNIT = nunit , REC = 14 ) a                                   

Файл должен быть внешним, а форматирование по списку и непоследовательный ввод-вывод недоступны.

Операции с внешними файлами

Еще раз напоминаем, что это всего лишь обзор.

Заявления о позиционировании файлов

  • Заявление BACKSPACE:
    BACKSPACE ( UNIT = u [, IOSTAT = ios ]) ! где [ ] означает необязательно    
  • Заявление REWIND:
    ПЕРЕМАТКА НАЗАД ( ЕДИНИЦА = u [, IOSTAT = ios ])   
  • Заявление endfile:
    КОНЕЦФАЙЛА ( единица измерения = u [, iostat = ios ])   

ЗаявлениеOPEN

Оператор используется для подключения внешнего файла к устройству, создания файла, который предварительно подключен, или создания файла и подключения его к устройству. Синтаксис:

ОТКРЫТЫЙ ( ЕДИНИЦА = u , СТАТУС = st , ДЕЙСТВИЕ = act [, olist ])    

где olist— список необязательных спецификаторов. Спецификаторы могут появляться в любом порядке.

ОТКРЫТО ( ЕДИНИЦА = 2 , IOSTAT = ios , ФАЙЛ = "cities" , СТАТУС = "новый" , ДОСТУП = "прямой" , & ДЕЙСТВИЕ = "чтение/запись" , ЗАПИСЬ = 100 )        

Другими спецификаторами являются FORMи POSITION.

ЗаявлениеCLOSE

Используется для отключения файла от устройства.

ЗАКРЫТЬ ( ЕДИНИЦА = u [, IOSTAT = ios ] [, СТАТУС = st ])     

как в

ЗАКРЫТЬ ( ЕДИНИЦА = 2 , IOSTAT = ios , СТАТУС = "удалить" )   

Заявлениеinquire

В любой момент выполнения программы можно запросить информацию о состоянии и атрибутах файла, используя этот оператор.

Используя вариант этого утверждения, можно аналогичным образом определить статус устройства, например, существует ли номер устройства для этой системы.

Другой вариант позволяет запрашивать длину выходного списка при использовании для записи неформатированной записи.

Для запроса по единице

ЗАПРОС ( ЕДИНИЦА = u , ilist )  

или для запроса по файлу

ЗАПРОС ( ФАЙЛ = fln , ilist )  

или для запроса по списку ввода/вывода

INQUIRE ( IOLENGTH = длина ) olist  

В качестве примера

ЛОГИЧЕСКИЙ :: ex , op СИМВОЛ ( LEN = 11 ) :: nam , acc , seq , frm ЦЕЛОЕ ЧИСЛО :: irc , nr ЗАПРОС ( ЕДИНИЦА = 2 , EXIST = ex , OPENED = op , NAME = nam , ACCESS = acc , SEQUENTIAL = seq , & FORM = frm , RECL = irc , NEXTREC = nr )                      

урожайность

ex . true . op . true . nam cities acc ПРЯМАЯ seq NO frm НЕФОРМАТИРОВАННЫЙ irec 100 nr 1        

(при условии отсутствия промежуточных операций чтения или записи).

Другие спецификаторы: IOSTAT, OPENED, NUMBER, NAMED, FORMATTED, POSITION, ACTION, READ, WRITE, READWRITE.

Ссылки

  1. ^ "Fortranplus | Информация о Фортране".
Взято с "https://en.wikipedia.org/w/index.php?title=Fortran_95_language_features&oldid=1251301194"