Pull to refresh

Принят новый стандарт Fortran 2023

Level of difficultyMedium
Reading time5 min
Views9.5K
В конце 2023 года был принят очередной стандарт языка Фортран, ISO/IEC 1539-1:2023. Programming languages. Fortran (в просторечии – 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 будут реализованы достаточно быстро.
Tags:
Hubs:
Total votes 23: ↑22 and ↓1+21
Comments21

Articles