В конце 2023 года был принят очередной стандарт языка Фортран, ISO/IEC 1539-1:2023. Programming languages. Fortran (в просторечии – Fortran 2023).
Отличия стандарта 2023 года от действовавшего до него стандарта Fortran 2018 полностью описаны в свободно доступном документе The new features of Fortran 2023, не имеющем официального статуса.
Приведём короткий обзор нововведений.
Максимальная длина строки программы увеличена до 10 тысяч символов, максимальная длина одного оператора – до миллиона символов. Компиляторам предписывается в точности соблюдать эти лимиты, не более и не менее. Как утверждается, целью является облегчение написания программ искусственными интеллектами.
Разрешено автоматическое размещение в памяти строк переменной длины в результате получения выходных параметров системных процедур и операторов (т.е. пользователю не надо руками отводить буфер).
Новые атрибуты typeof и classof для создания переменных такого же типа, как другие:
Долго ожидавшиеся условные выражения:
Скобки обязательны, но одно выражение может содержать вложенные условия:
Также результатом условного выражения может быть один или несколько фактических параметров процедуры, в том числе передаваемых по ссылке или опускаемых необязательных:
Лексема .nil. здесь передаёт отсутствие фактического параметра.
Более расширенное использование двоичных, восьмеричных и шестнадцатеричных (boz) литеральных констант. В языке Фортран такие литералы не имеют типа, представляя собой просто запись содержимого ячеек памяти, поэтому их использование отличается от использования десятичных чисел. В целом, теперь, когда можно вывести тип значения по левой части присваивания, то в правой могут использоваться boz.
Добавлены полезные подпрограммы токенизации строк split и tokenize для эффективной работы со словами в строке.
Через 59 лет после реализации аналогичного решения в языке PL/I, добавлены тригонометрические функции для работы с аргументами в градусах (acosd вдобавок к acos и так далее до tand).
Добавлены тригонометрические функции для работы с аргументами в интервале от 0 до Пи в соответствии со стандартом IEEE (от acospi до tanpi).
Функция selected_logical_kind позволяет получить атрибут байтовой длины логического значения, в которое уместится заданная разрядность.
Ограничены типы параметров стандартной подпрограммы system_clock. В частности, разрядность должна быть не меньше умолчательного размера integer.
Добавлены новые функции педантичных максимумов и минимумов для соответствия новому стандарту IEEE, ISO/IEC 60559:2020 – ieee_max, ieee_max_mag, ieee_min, ieee_min_mag. Отличаются от обычных точной спецификацией, что возвращается в случае различных NaN'ов, положительных и отрицательных нулей и т.п.
Добавлены целые константы logical8, logical16, logical32,
logical64, real16 для указания размеров соответствующих типов. Заметим, что во всех вменяемых компиляторах они равны 8, 16, 32, 64 и 16 соответственно. Шиза косит наши ряды.
Расширено взаимодействие с функциями на языке Си всякими экзотическими случаями вроде многобайтовой кодировки символов по умолчанию.
Добавлены следующие два крайне полезных нововведения в форматном выводе, которых (во всяком случае, второго) ждали чуть ли не 70 лет.
Новый формат вывода AT действует как A с применением функции trim, то есть отбрасывает лишние хвостовые пробелы:
Наконец!!! можно управлять печатью нуля перед десятичной точкой в вещественных числах между 0 и 1 (ранее могло быть как .5, так и 0.5 в зависимости от реализации). Для этого предназначены управляющие форматы LZP, LZS, LZ (print/suppress/default), либо ключевой параметр leading_zero=… в операторе open со значениями print, suppress, processor_defined (по некоторым сведениям – и в операторе write):
Расширен синтаксис оператора namelist.
Разрешены динамически размещаемые в памяти объекты, содержащие в себе комассивы, и всё это очень сложно работает.
Добавлен механизм put with notify, обеспечивающий изменение данных в чужом адресном пространстве с отправкой уведомления. Для этого расширен синтаксис оператора комассивного присваивания опцией notify и добавлен оператор notify wait:
Чем это лучше последовательных операторов присваивания и нотификации? Тем, что для двух разных операторов последовательность сообщений об изменении данных и о нотификации может перепутаться в пути от одного узла к другому, и фокус не удастся.
Улучшена обработка ошибочных состояний в тех случаях, когда они возникают только в части параллельных потоков.
Добавлены простые (simple) процедуры. Они отличаются от чистых (pure) процедур тем, что не только не модифицируют внешнее окружение иначе, чем через формальные параметры, но и не читают внешнее окружение иначе, чем через формальные параметры. Очевидно, полезно для выгрузки кода в GPU и в прочих неоднородных архитектурах.
Массивы разрешено индексировать массивами, задавать размерность (количество измерений) массива динамически, и вообще много разврата в стиле языка APL:
Долгожданное введение спецификации редукции в асинхронный оператор цикла, которое раньше было возможно только в макросах OpenMP:
Наконец, много малополезных возможностей, связанных с enum.
В целом, стандарт Fortran 2023 года производит положительное впечатление, а отдельных нововведений прямо-таки заждались. Но при этом вызывает беспокойство, что комитет ISO сильновато ушёл в отрыв от разработчиков компиляторов: предыдущий стандарт Fortran 2018 поддержан компиляторами только в небольшой части, а стандартом де-факто на сегодняшний день остаётся Fortran 2008. Остаётся надеяться, что хотя бы самые востребованные возможности Fortran 2023 будут реализованы достаточно быстро.
Отличия стандарта 2023 года от действовавшего до него стандарта Fortran 2018 полностью описаны в свободно доступном документе The new features of Fortran 2023, не имеющем официального статуса.
Приведём короткий обзор нововведений.
Максимальная длина строки программы увеличена до 10 тысяч символов, максимальная длина одного оператора – до миллиона символов. Компиляторам предписывается в точности соблюдать эти лимиты, не более и не менее. Как утверждается, целью является облегчение написания программ искусственными интеллектами.
Разрешено автоматическое размещение в памяти строк переменной длины в результате получения выходных параметров системных процедур и операторов (т.е. пользователю не надо руками отводить буфер).
Новые атрибуты typeof и classof для создания переменных такого же типа, как другие:
integer :: i
typeof (i) :: j
Долго ожидавшиеся условные выражения:
value = ( a>0.0 ? a : 0.0)
Скобки обязательны, но одно выражение может содержать вложенные условия:
value = ( a>0.0 ? a : b > 0.0 ? b : 0.0)
Также результатом условного выражения может быть один или несколько фактических параметров процедуры, в том числе передаваемых по ссылке или опускаемых необязательных:
call sub ( ( x>0? x : y>0? y : z ), ( edge>0? edge : mode==3? 1.0 : .nil.) )
Лексема .nil. здесь передаёт отсутствие фактического параметра.
Более расширенное использование двоичных, восьмеричных и шестнадцатеричных (boz) литеральных констант. В языке Фортран такие литералы не имеют типа, представляя собой просто запись содержимого ячеек памяти, поэтому их использование отличается от использования десятичных чисел. В целом, теперь, когда можно вывести тип значения по левой части присваивания, то в правой могут использоваться boz.
Добавлены полезные подпрограммы токенизации строк split и tokenize для эффективной работы со словами в строке.
Через 59 лет после реализации аналогичного решения в языке PL/I, добавлены тригонометрические функции для работы с аргументами в градусах (acosd вдобавок к acos и так далее до tand).
Добавлены тригонометрические функции для работы с аргументами в интервале от 0 до Пи в соответствии со стандартом IEEE (от acospi до tanpi).
Функция selected_logical_kind позволяет получить атрибут байтовой длины логического значения, в которое уместится заданная разрядность.
Ограничены типы параметров стандартной подпрограммы system_clock. В частности, разрядность должна быть не меньше умолчательного размера integer.
Добавлены новые функции педантичных максимумов и минимумов для соответствия новому стандарту IEEE, ISO/IEC 60559:2020 – ieee_max, ieee_max_mag, ieee_min, ieee_min_mag. Отличаются от обычных точной спецификацией, что возвращается в случае различных NaN'ов, положительных и отрицательных нулей и т.п.
Добавлены целые константы logical8, logical16, logical32,
logical64, real16 для указания размеров соответствующих типов. Заметим, что во всех вменяемых компиляторах они равны 8, 16, 32, 64 и 16 соответственно. Шиза косит наши ряды.
Расширено взаимодействие с функциями на языке Си всякими экзотическими случаями вроде многобайтовой кодировки символов по умолчанию.
Добавлены следующие два крайне полезных нововведения в форматном выводе, которых (во всяком случае, второго) ждали чуть ли не 70 лет.
Новый формат вывода AT действует как A с применением функции trim, то есть отбрасывает лишние хвостовые пробелы:
print "(AT,AT)", "Imperial ", "bastion"
Imperialbastion
Наконец!!! можно управлять печатью нуля перед десятичной точкой в вещественных числах между 0 и 1 (ранее могло быть как .5, так и 0.5 в зависимости от реализации). Для этого предназначены управляющие форматы LZP, LZS, LZ (print/suppress/default), либо ключевой параметр leading_zero=… в операторе open со значениями print, suppress, processor_defined (по некоторым сведениям – и в операторе write):
print "(LZP, F0.2, 1X, LZS, F0.2)", .5, .5
0.50 .50
Расширен синтаксис оператора namelist.
Разрешены динамически размещаемые в памяти объекты, содержащие в себе комассивы, и всё это очень сложно работает.
Добавлен механизм put with notify, обеспечивающий изменение данных в чужом адресном пространстве с отправкой уведомления. Для этого расширен синтаксис оператора комассивного присваивания опцией notify и добавлен оператор notify wait:
use iso_fortran_env
type(notify_type) nx[*]
me = this_image()
if (me <= 4) then
x(me)[10, notify=nx] = y
else if (me == 10) then
notify wait (nx, until_count=4)
z(1:4) = x(1:4)
end if
Чем это лучше последовательных операторов присваивания и нотификации? Тем, что для двух разных операторов последовательность сообщений об изменении данных и о нотификации может перепутаться в пути от одного узла к другому, и фокус не удастся.
Улучшена обработка ошибочных состояний в тех случаях, когда они возникают только в части параллельных потоков.
Добавлены простые (simple) процедуры. Они отличаются от чистых (pure) процедур тем, что не только не модифицируют внешнее окружение иначе, чем через формальные параметры, но и не читают внешнее окружение иначе, чем через формальные параметры. Очевидно, полезно для выгрузки кода в GPU и в прочих неоднородных архитектурах.
Массивы разрешено индексировать массивами, задавать размерность (количество измерений) массива динамически, и вообще много разврата в стиле языка APL:
A(@[3,5])
! Array element, equivalent to A(3, 5)
A(6, @[3,5], 1)
! Array element, equivalent to A(6, 3, 5, 1)
A(@V1, :, @V2)
! Rank-one array section, the rank of A being
! SIZE (V1) + 1 + SIZE (V2).
integer, dimension(3) :: lb_array = 0
real :: zz(lb_array+2:)
real, dimension(lb_array:) :: x, y
real, allocatable, dimension(:,:,:) :: x, y, z
integer :: lower(3), upper(3)
allocate(x(:upper), y(lower:upper), z(0:upper))
subroutine ex(a)
real, rank(2) :: a
! Equivalent to real :: a(:,:)
integer :: x0(10,10,10)
logical, rank(rank(x0)), allocatable :: x1
! rank 3, deferred shape
complex, rank(2), pointer :: x2
! rank 2, deferred-shape
logical, rank(rank(x0)) :: x3
! rank 3, assumed-shape
real, rank(0) :: x4
! scalar
Долгожданное введение спецификации редукции в асинхронный оператор цикла, которое раньше было возможно только в макросах OpenMP:
real :: a, b, x(n)
a = 0.
b = -huge(b)
do concurrent (i = 1:n) reduce(+:a) reduce(max:b)
a = a + x(i)**2
b = max(b,x(i))
end do
Наконец, много малополезных возможностей, связанных с enum.
В целом, стандарт Fortran 2023 года производит положительное впечатление, а отдельных нововведений прямо-таки заждались. Но при этом вызывает беспокойство, что комитет ISO сильновато ушёл в отрыв от разработчиков компиляторов: предыдущий стандарт Fortran 2018 поддержан компиляторами только в небольшой части, а стандартом де-факто на сегодняшний день остаётся Fortran 2008. Остаётся надеяться, что хотя бы самые востребованные возможности Fortran 2023 будут реализованы достаточно быстро.