Loading AI tools
структурный язык программирования Из Википедии, свободной энциклопедии
Фортра́н (англ. Fortran) — первый язык программирования высокого уровня, получивший практическое применение, имеющий транслятор и испытавший дальнейшее развитие[2]. Создан в период с 1954 по 1957 год группой программистов под руководством Джона Бэкуса в корпорации IBM[3]. Название Fortran является сокращением от FORmula TRANslator (формульный транслятор)[4]. Фортран широко используется в первую очередь для научных и инженерных вычислений. Одно из преимуществ современного Фортрана — большое количество написанных на нём программ и библиотек подпрограмм[5].
Фортран | |
---|---|
Семантика | императивный, параллельный |
Класс языка | процедурный, модульный, c элементами объектно-ориентированного программирования |
Тип исполнения | компилируемый |
Появился в | 1957 |
Автор | Джон Бэкус, IBM |
Разработчик | IBM[1] и Джон Бэкус[1] |
Расширение файлов |
.for .f .f90 .f95 .ftn |
Выпуск | Fortran 2023 (ISO/IEC 1539-1:2023) (17 ноября 2023) |
Система типов | строгая, статическая |
Основные реализации | GFortran, Open Watcom, Sun Studio, XL Fortran, Intel Fortran |
Диалекты | High Performance Fortran |
Испытал влияние | Speedcoding[вд] |
Повлиял на | ALGOL 68, Бейсик, PL/I |
Лицензия | лицензия MIT |
Сайт | fortran-lang.org (англ.) |
Медиафайлы на Викискладе |
Имеется большое количество написанных на Фортране (в большей части на старых версиях языка) различных математических библиотек для матричной алгебры и решения систем линейных уравнений, библиотеки для решения дифференциальных уравнений, интегральных уравнений и их систем, аппроксимации функций, специальных функций, быстрых преобразований Фурье, математической статистики и других математических дисциплин. Эти библиотеки поставляются, как правило, с компилятором. Ряд таких пакетов создавался на протяжении десятилетий и популярен в научной среде по сей день, например — Международная математическая библиотека подпрограмм (IMSL)[6][7].
Большинство таких библиотек является фактически достоянием человечества: они доступны в исходных кодах, хорошо документированы, отлажены и весьма эффективны.
Современный Фортран (Fortran 95 и Fortran 2003) приобрёл черты, необходимые для эффективного программирования, для новых вычислительных архитектур; позволяет применять современные технологии программирования, в частности, обобщённое и модульное программирование, ООП, сохраняя при этом преемственность с более ранними версиями. Одна из главных концепций развития современного Фортрана — средства поддержки параллельности и векторные операции[8].
Фортран — жёстко стандартизированный язык, поэтому он легко переносится на различные платформы. Новые стандарты языка в значительной мере сохраняют преемственность с более старыми, что позволяет использовать коды ранее написанных программ и модифицировать их[8]. При этом по мере развития языка заранее объявляются устаревшие конструкции, которые в будущем, возможно, будут удалены[9].
OPEN
, CLOSE
) и вывода на стандартное устройство — PRINT
.IF
и конструкция IF THEN
— ELSE IF THEN
— END IF
, а также оператор включения фрагмента программы INCLUDE
.READ
и WRITE
[12].IMPLICIT NONE
, TYPE
, ALLOCATABLE
, POINTER
, TARGET
, NAMELIST
.DO
… END DO
(вместо завершения цикла меткой), DO WHILE
, оператор передачи управления на начало цикла CYCLE
, конструкция выбора SELECT CASE
(для замены громоздких конструкций IF
и операторов GOTO
), а также заключительный оператор программной единицы, модульной или внутренней процедуры END
[8].ALLOCATE
, DEALLOCATE
, NULLIFY
).MODULE
, PRIVATE
, PUBLIC
, CONTAINS
, INTERFACE
, USE
, INTENT
.WHERE
для частичной замены циклов (правая часть оператора присваивания не изменяется). Маскирование присваивания распространяется практически на все операторы, конструкции и функции, оперирующие с массивами.ALL
(логическое произведение) и MASK
(логическое сложение), COUNT
(число истинных элементов), PRODUCT
(произведение элементов массива), SUM
(сложение элементов массива), DOT_PRODUCT
(скалярное произведение), MATMUL
(умножение матриц). Добавились справочные функции, а также функции переформирования и свёртки массивов.TRIM
(удаление завершающих пробелов) и REPEAT
(кратное копирование строки) и функции выравнивания по левой и правой границам.FORALL
, позволяющие более гибко, чем оператор и конструкция WHERE
, присваивать массивы и заменять громоздкие циклы. FORALL
позволяет заменить любое присваивание сечений или оператор и конструкцию WHERE
, в частности, обеспечивает доступ к диагонали матрицы. Данный оператор считается перспективным в параллельных вычислениях, способствуя более эффективному, чем циклы, осуществлению распараллеливания[16][12][17].Фортран имеет большой набор встроенных математических функций, поддерживает работу с целыми, вещественными и комплексными числами двойной и повышенной точности (при бинарных операциях используется real(10)
), имеет богатый инструментарий работы с массивами и внешними файлами. Современный Фортран (2003 и выше) имеет полноценный инструментарий для работы с символьными данными.
Изначально выразительные средства языка были не очень велики, поскольку Фортран был первым реализованным языком высокого уровня. В дальнейшем в Фортран были добавлены многие лексические конструкции, характерные для структурного, модульного, обобщённого и объектно-ориентированного программирования.
Структура программ изначально была ориентирована на ввод с перфокарт и имела ряд удобных именно для этого случая свойств. Так, с 1-й по 5-ю колонку располагалась область меток, 6-я служила для маркировки текста как продолжения предыдущей строки (любым символом, кроме пробела и «0»), а с 7-й по 72-ю располагался собственно текст оператора или комментария. Колонки с 73-й по 80-ю могли служить для нумерации карт (чтобы восстановить случайно рассыпавшуюся колоду) или для краткого комментария, транслятором они игнорировались. Если текст оператора не вписывался в отведённое пространство (с 7-й по 72-ю колонку), в 6-й колонке следующей строки ставился признак продолжения, и затем оператор продолжался на ней. Расположить два или более оператора в одной строке (карте) было нельзя. Когда перфокарты ушли в историю, эти достоинства превратились в серьёзные неудобства.
Именно поэтому к стандарту Фортрана, начиная с Fortran 90, с сохранением фиксированного формата исходного текста, был добавлен свободный формат, который не регламентирует позиции строки и позволяет записывать более одного оператора на строку. Введение свободного формата и современных способов структурного программирования[8] позволило создавать код, читаемость и ясность которого не уступает коду, созданному при помощи других современных языков программирования, таких как Паскаль, C или Java. Современные среды разработки позволяют комбинировать форматы: например, расширять длину строки до свободного формата (обычно 132 символа), позволяют записывать несколько операторов в строке, но при этом позволяют также сохранять отступ слева (делать левое поле), характерный для старого фиксированного формата, оставляя тем самым выделенную колонку для меток ошибок и форматов, а также колонку продолжения строки.
Своего рода «визитной карточкой» старого Фортрана является огромное количество меток, которые использовались в операторах безусловного перехода GOTO
, операторах циклов, в условных операторах и в операторах описания форматного ввода-вывода FORMAT
. Большое количество меток и операторов GOTO
часто делало программы на Фортране трудными для понимания.
Именно этот негативный опыт стал причиной, по которой в ряде современных языков программирования (например, в языке Java) метки и связанные с ними операторы безусловного перехода сильно видоизменены.
Однако современный Фортран (в основном начиная с версии Fortran’90) избавлен от избытка меток за счёт введения таких операторов, как DO
… END DO
, DO WHILE
, SELECT CASE
, конструкции IF THEN
-ELSEIF THEN
-ELSE
-END IF
и др. Более того, в современных стандартах языка оставлен лишь классический оператор GOTO
, применяемый во многих языках и поныне. Вычисляемый оператор GOTO
, а также конструкция ENTRY
— множественного входа в процедуры, — были исключены из стандарта, хотя, как правило, продолжают поддерживаться компиляторами.
Фиксированный формат (символами «␣» выделены пробелы в позициях строки с 1 по 6):
␣␣␣␣␣␣PRINT*, 'Hello, World!'
␣␣␣␣␣␣END
Свободный формат:
print *, "Hello, World!"
end
Замечания.
PROGRAM
не является обязательным. Строго говоря, единственный обязательный оператор Фортран-программы — оператор END
.Фортран поддерживает 5 основных элементарных встроенных типов данных: действительный (REAL
), комплексный (COMPLEX
), целый (INTEGER
) со знаком или без, логический (LOGICAL
) и символьный (CHARACTER
). Кроме того, возможно создавать производные типы данных с помощью ключевого слова TYPE
. С самого начала создания языка существовали 4 типа данных: действительный, комплексный, целый и логический.
Существует понятие разновидности типа данных или параметры типа. Это позволяет параметризовать вещественные и комплексные данные (то есть указывать точность и диапазон десятичного порядка) и другие данные, повышая мобильность приложений.
Для всех числовых данных определены обычные арифметические операции и присваивания, существуют встроенные функции. Встроенная функция Log(x)
в качестве аргумента x
может иметь только действительное или комплексное число (не целое).
Как правило, для действительных чисел «одинарной» точности отводится 4 байта (REAL(4)
, или параметр разновидности типа KIND=4
), «двойной» — 8 байт. Для комплексных чисел число байт удваивается.
Целые числа могут занимать от 1 до 4 байт. Современные компиляторы позволяют программисту оперировать числами и «учетверённой» точности.
В арифметических операциях изменение типа производится по умолчанию от целого в действительное и далее комплексное число, либо применением специальной встроенной числовой функции. Так, эквивалентны следующие выражения (i — целое): Log(i*1.)
и Log(real(i))
.
Строковые (символьные) данные задаются с указанием длины в скобках либо после атрибута типа, либо после имени строки. Для задания строки в теле программы используются одинарные или двойные кавычки. Так, эквивалентны записи: A='It is hot' или A="It is hot". Это удобно в тех случаях, когда в самой строке присутствуют кавычки: B="It isn’t hot".
Для строк существует встроенная операция конкатенации (сложения) строк: //
. Существует 17 специализированных встроенных функций для символьных данных (помимо универсальных, обрабатывающих все типы данных).
Метки — это целые числа с числом цифр не более 5; символы не допускаются. Метки используются в операторах GO TO
, операторах чтения, записи и форматирования, а также при обработке ошибок и исключений. Помимо меток, в Фортране имеется возможность именовать управляющие конструкции (циклы, логические условия, конструкции FORALL
… END FORALL
, WHERE
… END WHERE
, SELECT CASE
… END SELECT
, TYPE
… END TYPE
и др.), причём имя конструкции может содержать любые допустимые в именах переменных символы.
Для преобразования число-символ: CHAR(i)
и ACHAR(i)
. Преобразуют целое в соответствующий ему символ операционной системы или символ таблицы ASCII.
Для преобразования символ-число: ICHAR(i)
и IACHAR(i)
. Осуществляют обратные преобразования.
Функции сравнения строк: LGE(A,B)
, LGT(A,B)
, LLE(A,B)
и LLT(A,B)
. Результат функций — «истина», если длины строк (L(A) и L(B)), выраженные в символах ASCII, удовлетворяют следующим неравенствам соответственно: L(A)L(B), L(A)L(B), L(A)L(B) и L(A)L(B).
Функции длины: LEN(A)
и LEN_TRIM(A)
. Первая возвращает длину строки А (количество символов), вторая — возвращает длину строки без завершающих пробелов, если они имеются.
Функции преобразования: TRIM(A)
, ADJUSTL(A)
и ADJUSTR(A)
, REPEAT(A,N)
. Функция TRIM(A)
возвращает строку A без завершающих пробелов. Функции ADJUSTL(A)
и ADJUSTR(A)
выравнивают строку (удаляют пробелы) слева и справа соответственно. Функция REPEAT(A,N)
возвращает N копий строки А.
Функции поиска в строке: SCAN(A,B,[back])
, INDEX(A,B,[back])
, VERIFY(A,B,[back])
. Факультативный параметр back определяет направление поиска: по умолчанию слева (для back=.false.
) направо (для back=.true.
).
Функция SCAN
определяет номер позиции в строке A (слева или справа) первого найденного символа из списка-строки В. Если результат отрицательный, то функция возвратит целочисленный 0. Функция INDEX
определяет номер позиции, с которой впервые начинается полное вхождение строки В в строку А. Причём поиск может вестись как слева, так и справа, но номер позиции исчисляется всегда слева, от начала строки. При неудачном поиске функция возвратит 0. Функция VERIFY
обратна функции INDEX
. Так, VERIFY
возвращает номер позиции такого символа строки A, которого нет в строке-маске В. Если же все (различные) символы строки А присутствуют в строке-маске В, то функция вернёт 0.
Все эти функции являются элементными и их аргументом может быть массив символов или целых чисел. Результатом будет согласованный численный, символьный или логический массив.
Стандарты Фортрана, начиная с версии 2003, предусматривают возможность работы с символами Юникода.
Помимо указанных возможностей, Фортран позволяет обрабатывать символьные данные средствами своего встроенного матричного (векторного) анализа, что существенно повышает гибкость обработки символьных данных.
В Фортране для совместимости с программами, написанными на языке Си, существует понятие Си-строки, которая задаётся добавлением символа с после кавычки: А='Это Си-строка’с. Нулевая строка будет задана так: А='\0’c.
Подпрограммы в Фортране существовали с самого первого стандарта и поныне являются одним из главных инструментов программирования[8].
В Фортране вызов подпрограмм, функций и передача их параметров происходят исключительно по ссылке (а не по значению). Поэтому подпрограмма может изменить переданный ей аргумент в главной программе, если специальным образом это не предотвратить. Такой механизм позволяет сделать естественной нотацию при записи математических формул и сохранить при этом высокое быстродействие при работе с большими массивами данных[24].
Подпрограммы Фортрана могут содержать в списке параметров (называемых формальными параметрами) и необязательные (опциональные) параметры, а могут вообще не содержать параметров.
Стандарт языка позволяет осуществлять перегрузку процедур и операций посредством родового интерфейса, объединяя различные процедуры (оперирующая каждая, например, целыми, действительными, комплексными числами и символьными переменными) под одним (родовым) именем. В этом случае в главной программе достаточно обратиться к родовой процедуре, а характер выполняемых операций будет зависеть от типа данных, предложенных процедуре для обработки. По такому принципу сделаны все встроенные функции и подпрограммы, например, COS(x)
. Перегрузка процедур, функций и операторов (причём символы перегруженных операторов программист может предложить свои, помимо встроенных) распространяется не только на встроенные типы данных, но и на типы, определённые программистом[12].
Процедуры разделяются на подпрограммы и функции. Подпрограммы удобнее, если необходимо возвратить большое число разнородных результатов; функции — при возвращении результата одного типа (в том числе массива).
Подпрограмма определяется оператором описания Subroutine
имя_подпрограммы (список формальных аргументов), функция — оператором Function
имя_функции (список формальных аргументов).
Вызов подпрограммы осуществляется оператором Call
имя_подпрограммы (список фактических аргументов). Вызов функции осуществляется по имени с указанием списка фактических аргументов и без использования какого-либо специального оператора.
Начиная со стандарта F’90 поддерживаются рекурсивные процедуры (отсутствовавшие в ранних версиях из-за ограниченной машинной памяти), для объявления которых необходим явный спецификатор recursive
. При этом результат функции должен отличаться от имени самой функции.
Чистые процедуры и функции (pure subroutine [function]
) — введённые стандартом F’95 процедуры и функции, не имеющие побочных эффектов. Чистая функция должна возвращать значение и не должна изменять ни одного из своих входных параметров и/или глобальных данных; чистая процедура должна изменять только те параметры, которые явно указаны как результирующие (выходные) посредством атрибута intent(out
или inout)
). Возможность побочных эффектов в Фортране (то есть, в конечном итоге, возможность изменения переменных в главной программе через подпрограмму) — побочное следствие быстрого метода передачи по адресу.
Чистые программные единицы не могут содержать операторов В/В (WRITE
и READ
) во внешние файлы и устройства, включая клавиатуру и экран, а также операторов паузы и останова программы.
Все встроенные функции и подпрограммы Фортрана, в том числе математические (кроме обращающихся к операционной системе, функций даты и времени, а также датчиков случайных чисел) являются чистыми, то есть не создают побочных эффектов. Чистые функции введены с целью повышения культуры программирования и повышения эффективности распараллеливания алгоритмов[25][9].
В качестве аргументов подпрограмм могут быть любые встроенные типы данных, включая массивы и их секции, указатели, а также типы, определяемые программистом. Аргументами подпрограмм также могут быть функции и другие подпрограммы, кроме внутренних подпрограмм, операторной функции, родовых (обобщённых) процедур (допускаются только специфические имена) и некоторых др. встроенных типов.
Аргументы подразделяются на формальные и фактические. Аргументы заключаются в скобки после имени подпрограммы и разделяются запятыми. Имена фактических и формальных аргументов могут совпадать.
Формальные аргументы — это аргументы подпрограммы (функции), указанные при её описании. При отсутствии аргументов у подпрограммы, скобки могут быть опущены. У функции скобки расставляются и при отсутствии формальных аргументов. Формальный параметр-процедура называется формальной процедурой.
Фактические аргументы — это аргументы, передаваемые подпрограмме или функции для выполнения при её вызове. Функция без аргументов вызывается с пустым списком в скобках, подпрограмма — без скобок.
Формальные и фактические аргументы должны быть согласованы. Типы аргументов и разновидности их вида должны быть одинаковыми, массиву должен соответствовать массив (или сечение массива) той же конфигурации.
Существуют массивы, перенимающие конфигурацию и перенимающие размер как формальные аргументы процедур. Массив, перенимающий конфигурацию — это формальный аргумент-массив, который наследует конфигурацию соответствующего ему фактического массива. У такого массива при его объявлении задаётся размерность (совпадающая с размерностью фактического аргумента-массива) и опускаются верхние границы. По умолчанию нижние границы равны 1, но могут быть заданы произвольными. Число и значение элементов массива, перенимающего конфигурацию, точно наследуются от фактического аргумента-массива. Массив, перенимающий размер — это оставленный для совместимости более ранний, свойственный языку Fortran’77, способ описания наследующих массивов. У таких массивов наследуется только последнее измерение, верхняя граница которого описывается звёздочкой (*
). При этом формальный и фактический массивы-аргументы могут иметь разную размерность. Массивы, перенимающие конфигурацию и размер, не могут быть динамическими или быть указателями. Процедуры, имеющие наследующие массивы, должны иметь явный интерфейс.
Строки-формальные аргументы также могут наследовать (перенимать) длину у соответствующего фактического аргумента-строки. Строки, перенимающие длину, описываются посредством символа *
: Character (Len = *)
имя_строки. При явном задании длины строки, длина строки-формального аргумента не может быть больше соответствующего фактического аргумента-строки.
Аргументы бывают позиционными и ключевыми. Позиционные формальные и фактические аргументы связываются друг с другом по порядку их расположения в списке аргументов, который должен совпадать. Ключевые — по имени ключа, который совпадает с именем формального аргумента. Ключевые позволяют нарушить порядок следования аргументов или пропустить часть из них. Так, для подпрограммы с заголовком Subroutine
ONE (A, B, C, D) вызов может быть таким: Call
ONE (D=Z, C=Y, B=X, A=W), где W, X, Y, Z — фактические аргументы.
Ключевые аргументы позволяют иметь необязательные аргументы, которые могут быть опущены. В этом случае необязательные аргументы должны иметь атрибут Optional
. Например, если задано Optional
C, D, то в этом случае возможен вызов Call
ONE (B=X, A=W).
Процедуры с необязательными параметрами должны иметь явный интерфейс.
Массивы — центральный пункт философии Фортрана. Все конструкции языка, данные, программные единицы, операторы, встроенные функции, циклы созданы и создаются для эффективной обработки прежде всего массивов. Фортран по мере своего развития следует принципу максимального, насколько это возможно, ухода от детального (поэлементного) описания и обработки массивов. Особенно это эффективно при обработке многомерных массивов (предельная размерность массивов стандарта F2008 — 15). Такой взгляд на массивы не был свойственен ранним версиям языка; первые элементы обобщённого подхода к массивам появились в FORTRAN77; развиваются они и поныне.
Массивы бывают статическими и динамическими. Динамические разделяются на размещаемые и автоматические (образуемые при вызове подпрограммы). Элементы двумерного массива в Фортране размещаются по столбцам, а не по строкам, как, например, в Си. Таким образом, быстрее всего изменяется первый индекс массива. Поэтому для эффективной работы с массивами во вложенных циклах следует индексировать внутренние циклы левыми индексами, а внешние — правыми. По умолчанию присваивание, ввод, вывод и инициализация массивов осуществляются по столбцам.
do k=1,10
do j=1,20
do i=1,100
arr(i,j,k)=25 ! правильно
brr(k,j,i)=0 ! работоспособно, но медленнее в несколько раз
end do; end do; end do
Массивы могут быть нулевого размера (в том числе, если нижняя граница превосходит верхнюю). Индексами границ массивов могут быть любые целые числа. По умолчанию нижняя граница равна 1.
Real, allocatable:: ArR(:,:,:) ! объявление размещаемого динамического действительного массива
Integer, allocatable:: ArI(:), ArSI(2,5) ! целых динамического и статического массивов
Character(32), allocatable:: ArC(:), ArC2(20) ! динамического массива строк длиной 32 символа и статического массива строк
Allocate(ArR(-74:0,8,1:3), ArI(0), ArC(1:-1)) ! размещение динамических массивов
print *, size(ArR), size(ArI), size(ArC), size(ArSI) ! 1800 0 0 10
ArC2(17)(5:27)='Это присваивание строки' ! В строку номер 17 будет записано ␣ ␣ ␣ ␣ Это␣ присваивание␣ строки␣ ␣ ␣ ␣ ␣
...
FORALL
и WHERE
Фортран позволяет эффективно присваивать массивы без циклов посредством маскирования присваивания с помощью операторов WHERE
и FORALL
, а также сечений массивов и векторных индексов. Во всех случаях первоначально вычисляется правая часть выражения целиком (для всех индексов массива) и лишь затем выполняется присваивание для индексов, удовлетворяющих массиву-маске. Вычисления с помощью этих инструментов позволяют повышать быстродействие и облегчают компилятору работу по выделению участков программы, которые могут быть выполнены независимо, то есть распараллелены.
Real:: arr(I1:I2,J1:J2,K1:K2), arr1(I1:I2,J1:J2,K1:K2), arr2(I1:I2,J1:J2,K1:K2)
Real:: frr(100), frr1(10)/1,2,3,3*4,4*5/
! или
Real:: frr1(10)=(/1,2,3,4,4,4,5,5,5,5/)
...
arr=1. ! присваивание массива (встроенная перегрузка для оператора присваивания)
arr1=Sin(arr)+arr ! элементная функция sin применяется к каждому элементу массива
arr2(I1:I2:1,J1:J2:2,K2:K1:-4)=arr1(I1:I2:1,J1:J2:2,K2:K1:-4) ! присваивание элементов с шагом 1, 2 и -4 (назад), заданное индексным триплетом
frr=(/(J, J=1,100)/) ! присваивание одномерного массива посредством циклического списка
Forall(i=I1:I2, j=J1:J2, k=K1:K2, arr(i,j,k)>0.) brr(i,j,k)=Log(arr(i,j,k)) ! замена циклов и условных операторов и конструкций. Маскирование присваивания (маска — arr(i,j,k)>0.)
Forall(i=1:N, j=1:N, k=1:N) crr(i,j,k)=Sin(0.5*(i+j)-k) ! расширение возможностей сечений
Forall(i=1:100) ! конструкция Forall для нескольких операторов присваивания
drr(i,i)=0. ! доступ к диагонали матрицы
err(i,i,i)=1. ! и диагонали трёхмерного массива
End Forall
Возможны менее очевидные операции:
Integer V(-2:2,1:5)
V=reshape(source=(/(i, i=1,25)/), shape=(/5,5/)) ! инициализация массива порядковыми номерами с помощью конструктора массива и функции переформирования
print *, V ! Вывод в DOS-окно будет произведён по строкам
! 1 2 3 4 5 — 1-й столбец
! 6 7 8 9 10 — 2-й
! 11 12 13 14 15 — 3-й
! 16 17 18 19 20 — 4-й
! 21 22 23 24 25 — 5-й
V(2,3:4)=V(-1:0,1) ! Повернуть кусочек массива
print *, V ! Вывод в DOS-окно будет произведён по строкам
! 1 2 3 4 5
! 6 7 8 9 10
! 11 12 13 14 2 замена в 3-м столбце 15 на 2
! 16 17 18 19 3 замена в 4-м столбце 20 на 3
! 21 22 23 24 25
Возможности оператора и конструкции FORALL
, введённого стандартом F’95, шире возможностей оператора и конструкции WHERE
, однако последний в некоторых случаях логического ветвления позволяет упростить код ввиду наличия альтернативы ELSEWHERE
, избегая вложенных условных операторов и сложносоставленных массивов-масок.
Оператор и конструкция FORALL
допускает использование только чистых процедур и функций. При маскировании присваивания в операторах WHERE
, FORALL
, а также в специальных встроенных функциях для массивов (например, SUM
) логический массив-маска вычисляется до присваивания и позволяет заменять циклы с логическими условиями внутри них, что позволяет избежать дополнительной работы для предсказателя переходов микропроцессора.
Векторный индекс — целочисленный одномерный массив, значения которого — индексы некоторого другого массива. Векторные индексы используются для создания произвольных сечений многомерных массивов и являются их обобщениями. При использовании векторных индексов следует следить за повторяющимися значениями индексов в левой части оператора присваивания, так как в этом случае будет осуществлена попытка записи в одну ячейку памяти, возможно, разных значений. Порядок индексов — произвольный (хотя этим не следует злоупотреблять во избежание снижения быстродействия).
Integer vi(5)/7,7,7,3,8/, vj(4)/1,2,3,10/ ! инициализация массивов - векторных индексов
Real arr(20,20), brr(10,10)
brr=0.; arr=1.
! векторные индексы можно задавать и внутри использующего их массива
brr((/8,6,2,1,4/),vj)=arr(vi,vj) ! размерность векторных индексов должна совпадать слева и справа, а их значения - не выходить за пределы границ использующих их массивов
! размер векторных индексов может быть меньше размера рабочих массивов
В современном Фортране имеется большое количество специализированных встроенных функций для работы с численными и символьными массивами (помимо разобранных выше общих способов). Аргументами функций выступают численный и/или символьный массив array, логический массив mask (являющийся, например, условием array>0) и измерение dim массива array, формирующее (если задан аргумент dim) сечение массива вдоль одного из измерений с номером dim. Массив array может быть, если не указано иное, целочисленным, содержать действительные или комплексные числа. Если массив-маска не задан, то его значение считается тождественно истинным. Логический массив mask, если задан, должен иметь ту же форму, что и массив array, либо скалярное значение .TRUE.
.
Основная масса функций введена стандартом F’90.
ALL(mask[, dim])
— логическая функция; возвращает «истина», если все элементы логического массива mask истинны (вдоль факультативного измерения dim) и наоборот в противном случае.
ANY(mask[, dim])
— логическая функция; имеет значение «истина», если хотя бы один элемент логического массива mask истинен (вдоль факультативного измерения dim).
COUNT(mask[, dim])
— целочисленная функция; результат равен числу истинных элементов массива mask (вдоль факультативного измерения dim).
MAXLOC(array[, mask][, dim])
, MINLOC(array[, mask][, dim])
,
— целочисленные функции, возвращающие соответственно индекс максимального и минимального элемента (или индексы максимальных и минимальных элементов) вдоль факультативного измерения dim для элементов, удовлетворяющих массиву-маске. Функции возвращают индекс первого по порядку следования элемента массива array. Если аргумент функций dim не задан, или если array — одномерный массив, то результат записывается в одномерный массив.
Для многомерных массивов array результат записывается в массив с рангом, на единицу меньшим ранга массива array (исключается измерение с номером dim).
Значения индексов отсчитываются по порядку от нижних границ массива. То есть в случае, если номер нижней границы массива array отличается от единицы, то для доступа к максимальному или минимальному элементу массива следует прибавить к результату функций MAXLOC
и MINLOC
разницу между индексом нижней границы и единицей.
MAXVAL(array[, mask][, dim])
, MINVAL(array[, mask][, dim])
— функции поиска максимального и минимального элемента соответственно в массиве array для элементов, удовлетворяющих логическому массиву-маске mask вдоль факультативного измерения dim.
Результат функции — такого же типа и разновидности, что и массив array. Массив array может быть только вещественным или целочисленным.
Для одномерного массива array или при отсутствии аргумента dim результатом является скаляр, иначе — массив с рангом, на единицу меньшим ранга массива array.
FINDLOC(array, value[, dim][, mask])
— целочисленная функция, возвращающая индекс равного value элемента массива array. Введена стандартом F2008. Искомые элементы массива удовлетворяют логическому массиву-маске mask вдоль факультативного измерения dim. Тип аргумента value должен совпадать с типом массива array и может быть любого встроенного типа (включая комплексный, логический или символьный). Остальные свойства функции аналогичны свойствам функций MAXLOC
и MINLOC
.
Начиная со стандарта F2003, функции MAXLOC
и MINLOC
, как и функция FINDLOC
, оперируют также и символьными данными.
SUM(array[, mask][, dim])
и PRODUCT(array[, mask][, dim])
осуществляют соответственно суммирование и умножение элементов массива. Смысл аргументов функций SUM
и PRODUCT
тот же, что и у выше рассмотренных функций.
Функция PRODUCT
оперирует комплексными данными, начиная со стандарта F2003.
DOT_PRODUCT(vector_1, vector_2)
осуществляет скалярное произведение по правилам линейной алгебры векторов vector_1 и vector_2 (одномерных массивов) одинакового размера. Одномерные массивы vector_1 и vector_2 могут содержать данные любого численного и логического типа. Вектора vector_1 и vector_2 могут быть либо оба численными, либо оба — логическими.
MATMUL(matrix_a, matrix_b)
— встроенная функция матричного перемножения. Перемножает две матрицы, матрицу на вектор, вектор на матрицу по правилам линейной алгебры. Аргументы функции matrix_a и matrix_b — двумерные или одномерные численные (любых встроенных численных типов) или логические массивы. Аргументами функции не могут быть одновременно два вектора: один из аргументов обязан быть матрицей (двумерным массивом). Число элементов первого (либо единственного) измерения массива matrix_b должно быть равно числу элементов последнего измерения массива matrix_a. Введена стандартом F’90.
В некоторых случаях при расчёте произведения вектор-столбца на вектор-строку, требующего при использовании функции MATMUL
дополнительного преобразовывания векторов в матрицы формы (/m,1/)
и (/1,n/)
, эффективность MATMUL
по данным Бартеньева[12] заметно уступает обычному вложенному циклу.
По тестам NASA[26] для произведения матриц (двумерных массивов) быстродействие MATMUL
компилятора фирмы Intel при использовании полной оптимизации -O3 существенно (в некоторых случаях — на порядок) превышает быстродействие вложенных циклов, хотя для матриц размером ~1000×1000 и больше несколько уступает быстродействию подпрограммы DGEMM библиотеки LAPAK. В то же время для матриц ~100×100 и меньше MATMUL
превосходит по скорости DGEMM. Компилятор Фортрана фирмы IBM, начиная с версии F’90, использует для MATMUL
алгоритм Винограда — Штрассена со сложностью [27]. Отметим, что стандартом алгоритмические реализации математических функций обычно не оговариваются и остаются на усмотрение разработчика компилятора.
MERGE(t_source, f_source, mask)
— функция, создающая новый массив под управлением маски-массива mask из элементов массивов t_source и f_source той же формы и того же размера, что и исходные массивы. Массивы-аргументы и массив-результат могут быть любого встроенного типа и совпадать по типу данных, размеру и форме.
Если элемент mask есть истина (.ТRUE.
), то соответствующий ему элемент массива-результата равен соответствующему элементу массива t_source; если ложь (.FALSE.
) — то элементу массива f_source.
Аргументами функции могут быть скаляры; в этом случае, например, MERGE(a,0,c>=0)
=a·Θ(с), где Θ(с) — целочисленная функция Хэвисайда.
MOVE_ALLOC(from, to)
— встроенная подпрограмма, позволяющая динамически переразмещать ранее размещённый динамический массив to с новыми границами и размером, как у динамического массива from. При этом данные из массива from копируются в массив to. Тип данных и ранг массивов from и to должны совпадать. После переразмещения массива to массив from освобождает память и становится неразмещённым. Может быть полезна в численных методах с изменяющейся дискретизацией задачи (многосеточных и адаптивных методах).
Введена стандартом F2003.
TRANSPOSE(matrix)
— функция, транспонирующая (меняющая местами строки и столбцы) двумерную матрицу.
В современном Фортране предусмотрены встроенные функции упаковки и распаковки многомерного массива в одномерный массив (и из одномерного массива, соответственно) под управлением логического условия для повышения быстродействия и экономии памяти.
PACK(array, mask [, vector])
— функция; упаковывает многомерный массив любого типа array в одномерный массив-вектор под управлением логического массива mask. Необязательный одномерный массив vector должен иметь тот же тип данных, что и array, причём количество элементов в vector, если он задан, должно быть не меньше числа истинных элементов в mask. Если mask — скаляр со значением .TRUE.
, то число элементов в массиве vector, если он задан, должно быть не меньше, чем общее число элементов в array.
Результатом функции будет одномерный массив того же типа, что и array. Длина результата будет равна длине вектора vector, если он задан; если нет — то числу истинных элементов в массиве-маске mask. Если vector не задан, а mask — скаляр со значением истина, то длина результирующего одномерного вектора равна числу элементов массива array.
Результирующий массив последовательно заполняется элементами массива array (в порядке их размещения в компьютерной памяти), удовлетворяющими истинным значениям массива mask. При этом, если задан vector, из него выбираются недостающие (возможно) элементы в массиве-результате, причём начиная с индекса, следующего за последним по порядку истинным элементом массива array.
Так, для массива
результатом функции PACK(A, mask=A.NE.0)
будет одномерный массив . Если дополнительно задан вектор , то результатом PACK(A, mask=A.NE.0, V)
будет
.
Фортран обладает богатым встроенным инструментарием для операций ввода-вывода, в том числе для больших массивов данных. Файлы в Фортране бывают внутренние и внешние.
Внутренний файл — это любой массив, символьная строка или подстрока. Внутренние файлы всегда открыты по умолчанию. Внешний файл — это любой файл, внешний по отношению к выполняемой программе.
С обоими типами файлов используются одни и те же операторы записи WRITE
и чтения READ
. Внутренние файлы используются для преобразований число-строка-число и для создания смешанных числовых и символьных записей.
Character(15) string
Real:: xyz=-123.456
Integer intg
Write(string,*) xyz ! Запись в строку числа -123.456
Print *, 'string=', string ! string=␣ -123.4560␣ ␣
Read (string,'(I6)') intg ! Чтение из строки целого числа
Print *, 'intg=', intg ! intg=␣ -123
!...
Внешние файлы подразделяются на форматные (текстовые, CR- и LF-потоки), бинарные (двоичные), непосредственно отображающие оперативную память, и неформатные (не двоичные). Кроме того, они могут быть файлами прямого и последовательного доступов с записями фиксированной и переменной длины (переменной — только для последовательных файлов), а также сегментированными записями (для очень больших неформатных последовательных файлов). Таким образом, Фортран позволяет создавать и обрабатывать довольно большое количество видов файлов — 15 способов организации. Максимальный размер одной записи — два гигабайта.
Файлы прямого доступа позволяют осуществлять операции ввода-вывода с записями с заданным номером (без затирания вышерасположенных или нижерасположенных записей в файле).
При открытии последовательного файла его можно позиционировать в начало, в конец (перед записью «конец файла»), что позволяет добавлять данные по мере их накопления без затирания ранее введённых, а также либо в начало, либо в конец в зависимости от ранее определённого статуса файла (был он открыт ранее или нет).
В современных стандартах языка (начиная с Fortran’90 или Fortran’95) возможна работа с тремя видами динамических массивов (автоматическими, размещаемыми и массивами-ссылками), указателями, ссылками; имеются встроенные процедуры для работы с памятью напрямую и процедуры для побитовых операций.
Стандарты языка предполагают автоматическое освобождение оперативной памяти, занятой любым типом динамического массива, после завершения работы программы или подпрограммы (процедуры, функции), даже если программистом освобождение не было выполнено явно. Это позволяет избегать возникновения утечек памяти при работе с динамическими массивами средствами Фортрана (при использовании указателей и в других случаях утечки возможны) при небрежности программирования[12].
Автоматические массивы (размещаемые компилятором) создаются при вызове подпрограммы и являются её локальными объектами. Их границы определяются всякий раз при обращении к процедуре; при этом при выходе из неё они уничтожаются, а память — очищается. Автоматические массивы во время выполнения программы находятся в стеке, размещаемые (с помощью оператора ALLOCATE
) — в куче[25].
Указатели Фортрана аналогичны указателям Си[12], однако при решении вычислительных задач и разработке математических алгоритмов они в большинстве случаев с успехом заменяются иными инструментами Фортрана.
Начиная со стандарта F’90 конструкция условного перехода IF THEN
— ELSEIF THEN
— END IF
не отличается от подобных конструкций в других современных языках и заменила т. н. «арифметический» IF
с метками, признанный устаревшим[9]. Существует и более простая форма условного оператора: IF
(логическое условие)
оператор
, где исполняемый оператор должен быть единственным после оператора IF
, например, Goto
метка
.
Конструкция выбора SELECT CASE
— CASE
— CASE DEFAULT
— END SELECT
, наоборот, отличается от конструкции SWITCH
— CASE
в Си-подобных языках, таких как: C++[28], Java[29], JavaScript[30] и других, несколько напоминая по возможностям оператор CASE
в Паскале[31].
Integer N(74) ! выражение выбора — это целое, логическое, символьное выражение или
... ! целочисленый массив, или массив символов с любым ненулевым числом элементов
nameSC: Select Case(N(i)) ! nameSC — имя конструкции, N(i) — элемент массива
Case(:-5) ! выполняется для всех N(i), меньших либо равных -5 с шагом +1
! Блок 1
Case(-3,-1,0,2) ! для переменной N(i), равной -3, -1, 0, 2
! Блок 2
Case(50:100) ! для N(i) в диапазоне от 50 до 100 включительно (шаг +1)
! Блок 3
Case(400) ! для N(i)=400
! Блок 4
Case(1,20:30,35) ! для N(i)=1, N(i) в диапазоне от 20 до 30 включительно и N(i)=35
! Блок 5
Case Default ! для всех прочих ситуаций. Case Default — опциональный, необязательный оператор
! Блок по умолчанию
End Select nameSC
Если значение переменной N, называемой выражением выбора, совпадёт со списком селекторов (списком значений или диапазоном) в к-либо операторе CASE
, например, в третьем для N=70, то, после выполнения соответствующего блока операторов Блок-3, происходит выход из конструкции SELECT CASE
[12][25], и операторов прерывания (типа BREAK
) не требуется. Оператор CASE DEFAULT
, равно как и имя конструкции, не является необходимым. Диапазоны в списках селекторов различных операторов CASE
не должны пересекаться или иметь хотя бы одного общего элемента.
В качестве выражения выбора (N) может быть элемент целочисленного массива.
Диапазоны в списках селекторов применяются только для целых или для символов, по возрастанию от нижней границы к верхней; для символов — по возрастанию их кодов.
В современном Фортране существуют две формы циклов со счётчиком итераций: традиционная конструкция DO
—ENDDO
и цикл с меткой. Последняя признана устаревшей конструкцией начиная со стандарта F’90, однако до сих пор входит в стандарты. Для вложенных циклов с большим уровнем вложенности последняя форма может быть более лаконичной:
! Синтаксис устаревшей конструкции цикла
do 1 k=1,10 ! 1- это метка конца цикла
do 1 j=1,20 ! метка может быть одинаковой для вложенных циклов
do 1 i=1,100
arr(i,j,k)=25
1 Continue ! метка может стоять только перед к-либо оператором
L1: do k=1,10 ! однако современная запись допускает именовать циклы,
L2: do j=1,20 ! что больше соответствует концепции структурного программирования
L3: do i=1,100 ! и позволяет легче избежать ошибок
arr(i,j,k)=25
end do L3
end do L2
end do L1
Заголовок цикла со счётчиком имеет следующий полный вид:
name: DO I=N1, N2, dN ! имя конструкции необязательно
... ! N1 — начальное значение счётчика, N2 — конечное, dN — шаг (параметры цикла)
END DO name ! Параметры цикла — целые числа произвольного знака. dN не равно нулю.
Число выполнения тела цикла без прерывания равно Nс=max
(int
((N2-N1+dN)/dN), 0) и может быть равным нулю.
Например, цикл выполнится нуль раз, если N2<N1 и шаг положителен: dN>0. Если шаг отрицательный, dN<0, то цикл пройдёт в обратном порядке, при этом для выполнения цикла необходимо, чтобы N2<N1. Если шаг dN опущен, то по умолчанию он считается равным единице: dN=1.
Значение переменной цикла I после выхода из него всегда равно Nс+1, то есть на единицу больше числа итераций цикла и не менее единицы: I≥1.
Возможен также цикл с условием DO WHILE
(логическое условие)
— END DO
, и бесконечный цикл DO
— END DO
, имеющие стандартную форму.
Оператор CYCLE
имя цикла
прерывает текущую итерацию цикла и переходит к следующей итерации этого же цикла. Если имя цикла не указано, то выполняется прерывание итерации текущего цикла (в котором расположен оператор CYCLE
).
Оператор EXIT
имя цикла
прерывает выполнение цикла с указанным именем и передаёт управление далее, а при отсутствии имени — прерывает текущий цикл (в который вложен оператор EXIT
).
Операторы CYCLE
и EXIT
логически тождественны оператору GOTO
(в соответствующих обстоятельствах), но существенно облегчают понимание и обслуживание кода программистом.
С момента первоначальной разработки языка компиляторы Фортрана производит фирма IBM. В настоящее время фирмой IBM поставляется оптимизирующий компилятор VS Fortran[32] для мэйнфреймов IBM System z, история развития различных версий которого восходит ещё к 1964 году, а также компилятор XL Fortran[33] для платформ на базе архитектуры PowerPC — AIX, Linux и суперкомпьютера Blue Gene (выпускалась также версия для Mac OS X, когда компьютеры Macintosh использовали процессоры PowerPC). Оба этих компилятора содержат очень сложные оптимизаторы, являющиеся результатом непрерывной научной работы специалистов IBM на протяжении полувека. На базе компилятора IBM Fortran XL фирмой Absoft, бизнес-партнёром IBM, создан и поставляется компилятор Absoft Pro Fortran для систем на базе процессоров PowerPC (Linux, Mac OS X) и Intel (Linux, Mac OS X, Windows)[34].
Существовала реализация Фортрана для виртуальной машины UCSD p-System, которая позволяла создавать исполняемый код независимый от аппаратной платформы.
До 1997 крупным производителем компилятора Фортран для операционной системы Windows была корпорация Microsoft. Впоследствии она отказалась от их разработки в связи с низкой прибыльностью. После этого компилятор поставляла фирма DEC, вошедшая в 1998 году в состав Compaq и вместе с последней в 2002 году слившаяся с HP. Дальнейшей разработкой этой версии компилятора стала заниматься фирма Intel, а компилятор называется Intel Fortran Compiler, который позволяет оптимизировать код под платформы Intel IA-32, x86_64 и IA-64.
Компания DEC поставляет компилятор, интегрированный в среду разработки Digital Visual Fortran, основанную на Microsoft Visual Studio. Наиболее известными продуктами этой линейки являются FPS 4.0 (Microsoft Fortran Power Station), DVF 5.0 и 6.0. Каждый компилятор может поддерживать несколько стандартов Фортрана. Слияния компаний явились причиной того, что последующие продукты появлялись на рынке под торговыми марками Compaq и HP. В настоящее время HP продаёт среду разработки версии 6.6 для Intel/win32. Поддержка Фортрана реализована также для всех высокопроизводительных платформ HP.
Другим крупным поставщиком систем разработки на Фортране является фирма Lahey, предлагающая интегрированные решения для Windows и Linux.
Долгое время лучшим компилятором Фортрана для PC считался компилятор фирмы Watcom, который был выделен в отдельный проект Open Watcom, развивающий компилятор на открытой основе.
Среди бесплатных компиляторов Фортран следует выделить компилятор от бывшей Sun Microsystems (сейчас Oracle), входящий в состав Sun Studio, который генерирует эффективный код под SPARC, x86 и x86-64[35] и доступен для ОС Solaris, OpenSolaris и GNU/Linux.
Фонд свободного программного обеспечения GNU выпускал открытый компилятор Фортрана-77 g77, доступный практически для любой платформы и полностью совместимый с GCC. Сейчас ему на смену пришёл компилятор GFortran, в котором реализованы практически все конструкции стандарта Фортран-95 и многие конструкции стандартов Фортран-2003, Фортран-2008 и Фортран-2018. Он также полностью обратно совместим с Фортран-77. Также существует независимый проект g95 по созданию на основе GCC компилятора Фортран-95.
Многие системы программирования позволяют компоновать полученные в результате трансляции фортрановской программы объектные файлы с объектными файлами, полученными от компиляторов с других языков, что позволяет создавать более гибкие и многофункциональные приложения. Для языка Фортран также доступно большое количество библиотек, содержащих как подпрограммы решения классических вычислительных задач (LAPACK, IMSL, BLAS), задач организации распределённых вычислений (MPI, PVM), так и задач построения графических интерфейсов (Quickwin, FORTRAN/TK) или доступа к СУБД (Oracle).
Фортран в СССР появился позже, чем на Западе, поскольку поначалу в СССР более перспективным языком считался Алгол. Во внедрении Фортрана большую роль сыграло общение советских физиков со своими коллегами из CERN, где в 1960-х годах почти все расчёты велись с использованием программ на Фортране[36].
Первый советский компилятор с Фортрана был создан в 1967 году для машины Минск-2, однако он не получил большой известности. Широкое внедрение Фортрана началось после создания в 1968 году компилятора ФОРТРАН-ДУБНА для машины БЭСМ-6. Фортран — основной язык для АСВТ и СМ ЭВМ, часто использовался вместе с препроцессором РАТФОР. Машины ЕС ЭВМ, появившиеся в 1972 году, уже изначально имели транслятор Фортрана («позаимствованный» с IBM/360 вместе с другим программным обеспечением).
В 1970-x годах в ИПМ была разработана графическая библиотека ГРАФОР («Графическое РАсширение ФОРтрана»)[37].
В конце 1980-х — начале 1990-х физик Андрей Зарецкий создал серию детских книжек, одним из главных героев которых был профессор Фортран, доступным языком объяснявший детям основы компьютерной грамотности и программирования[38][39].
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.