Отличия стандарта 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 будут реализованы достаточно быстро.
ссылка на оригинал статьи https://habr.com/ru/articles/786716/
Добавить комментарий