首页 >

Fortran 202X 新特性

作者:St_Maxwell  日期:04-02
来源:St Maxwell, 清风徐来, e^(πi)+1=0
Fortran语言的下一个版本Fortran 202X,并且按计划将会在2023年发布(202X并不是正式版本称呼,如无意外应该是Fortran 2023)。这个版本依然是一个小版本更新。泛型等特性按计划可能于再下一个版本的Fortran 202Y中推出。下文将列举出202X版本计划添加的新内容。
语言特性
1. 自由格式中,单行最大长度拓展到一万个字符,语句的最大长度(包含所有续行)拓展到一百万个字符。
2. 递延长度字符变量在内置过程和语句中,也可被自动分配内存。
例如IO语句中的iomsg和errmsg参数,作为内部文件写入,以及在内置过程的intent(out)/(inout)参数中使用。
character(len=:), allocatable :: str write(str,"(g0)") 100 ! str = "100"
3. typeof和classof标识。用于定义变量的类型,方式为typeof(data-ref)或classof(data-ref),相当于定义了与data-ref相同类型的一个变量。
很难想象有什么实际用处。
integer(kind=4) :: i typeof(i) :: k ! k is an integer with kind equal to 4 补充:调查发现C语言的下一个版本C2x也将添加typeof标识,与Fortran 202X中的用法相当接近。
typeof很早就是gcc等编译器的拓展,这次是将其标准化添加到C语言的标准中。但是Fortran不像C语言一样有宏,
typeof不一定能像C语言中的那么有用。(Not-so-magic - typeof for C)
4. 条件表达式和条件参数。与其他语言的条件运算符比较相似。
value = (condition ? true_value : false_value)
上面这个例子等价于当前的Fortran代码
if (condition) then
value = true_value
else
value = false_value
end if
更一般的形式为 (condition ? [: condition ? ]... : expresion)
其实就是在条件表达式的 中再嵌套条件表达式。注意,整个语句中的表达式都应当具有相同的类型、kind以及维度。
这种写法也可以作为过程的实参,但是存在一点区别。由于过程的参数可能是可选的,因此条件参数中,除了表达式和变量,还可以有字面值常量.nil.。
subroutine sub (arg)
integer, intent(in), optional :: arg
end subroutine
call sub( (x > 0 ? 5 : .nil.) )
在上面的代码中,若x > 0,那么虚参arg将为5;若x < 0,虚参arg相当于未被使用,即present(arg)将返回.false. 。
5. 二进制、八进制、十六进制常量表达式。在Fortran 2018中,这些boz常量只允许出现在data语句和一部分内置过程的实参中。
Fortran 202X中,boz常量将可以出现在integer或real类型变量、常量的初始化中,integer或real类型变量赋值语句的右手边
作为integer或real类型数组构造器中的值(需要有类型标识)
enum构造器中的值
也就是说在大部分情况下,可以像一般的integer字面值常量一样使用。
integer :: a = b'1001' ! a = 9 a = z'4D2' ! a = 1234
内置过程和模块
1. 从字符串中提取token。例如有字符串"one two three;",我们希望根据分隔符" "和";"将其分为"one"、"two"、"three"和""四个token。
一种方式是得到分隔符的位置,另一种方式是直接返回每个token的起始与结束位置。
Fortran 202X中为此提供了split和tokenize子程序,其中tokenize有两种重载接口。
2. 度数的三角函数。Fortran中原本的三角函数都是以弧度为单位,Fortran 202X将作为编译器扩展的度数三角函数被纳入了新标准。
acosd, asind, atand, atan2d, cosd, sind, tand 半圈的三角函数。
为弧度制增加了半圈三角函数,以 π 作为单位。 acospi, asinpi, atanpi, atan2pi, cospi, sinpi, tanpi
3. select_logical_kind函数。用于选择logical变量的kind。
4. system_clock的更新。
5. 与新IEEE标准保持一致。ieee_arithmetic内置模块有所更新,从而与新的IEEE标准ISO/IEC 60559:2020保持一致。增加了四种逐元函数
ieee_max(x, y) ieee_max_mag(x, y) ieee_min(x, y) ieee_min_mag(x, y) 用于比较real类型变量。
6. 新添加的用于指定kind的命名常量。在iso_fortran_env模块中新添加了以下常量 logical8 logical16 logical32 logical64 real16 看来Fortran 202X有16位浮点数。
与C语言的交互
1. 拓展了c_f_pointer子程序,添加了可选参数lower,可用于指定返回时fptr数组指针的下界。
2. 添加了在Fortran和C之间传递字符串的过程。 IO
1. AT格式描述符。与A格式描述符的区别是,打印字符串对象时会自动去掉字符串尾部的空字符。可以理解为自动调用了trim函数。
2. 可调整打印real值时是否有前导的"0"字符。
3, Namelist中可包含private的变量。 Coarrays 更新了几个小特性。 过程 1. Simple过程。
Fortran中的pure过程在执行时不产生副作用,除了具有intent(out)/intent(inout)的参数(对于子程序而言,pure函数所有参数都必须是intent(in)),其在执行过程中不改变任何外部变量(例如其所在的module中定义的变量)的值。
而simple过程在pure过程的基础上再添加了一个限制,simple过程内部不允许访问其定义域外部的变量,只能通过其虚参交互。定义这种过程可能有利于编译器的优化。
Fortran中所有的内置函数都是simple的,内置module中的函数也全都是simple的。也有一部分内置的子程序是simple的。
定义simple过程需要在函数定义语句前加上simple关键词 real simple function increment (x) real :: x ... 定义一个simple过程的限制除了与定义pure过程相同的部分,还包括不能通过use其依据其所在的宿主(说白了就是不能使用过程所在的更上层代码块中定义的变量,比如module中定义的函数不能使用所在module中定义的变量)访问变量不能通过common块访问变量。所有作为参数的过程必须都是simple的
所有内部定义的过程必须是simple的
所有调用的过程必须是simple的
当某些上下文中需要simple过程,被使用的过程必须具有显式接口,且注明了其为simple不能有entry语句
数组特性
1. 使用integer数组表示下标。Fortran 202X中允许使用integer数组,也可称为多重下标来指代一系列下标,例如 A(@[3,5]) ! 等价于A(3,5) A(6, @[3,5], 1) ! 等价于 A(6,3,5,1) A(@V1, :, @V2) ! 一维数组,A的总维数等于size(V1) + 1 + size(V2)
此外还有多重下标三元组(multiple sub triplet)的形式
@ [int-expr] : [int-expr] [ : int-expr]
每个int-expr或者为一维数组,或者为单个整数。三个int-expr分别描述每个维度上切片的起始、结束以及步长。
例如 A(@[3,5] : [9,10] : [2,3]) ! 等价于A(3:9:2, 5:10:3) A(@[3,5] : [9,10] : 2) ! 等价于 A(3:9:2, 5:10:2) ?A(@[3,5] : [9,10]) ! 等价于A(3:9, 5:10)
使用integer数组表示数组维数及边界。假定有一大小固定的integer数组,我们可以用它来描述数组下标的上界或下界,数组的维数与该integer数组的大小相同。
real, dimension(:,:,:), allocatable :: x, y, z
integer :: lower(3), upper(3) ... ! 确定lower和upper的值
allocate( x(:upper) ) ! 等价于 allocate(x(upper(1),upper(2),upper(3))
allocate( y(lower:upper) ) ! 等价于 allocate(y(lower(1):upper(1),lower(2):upper(2),lower(3):upper(3))
allocate( z(0:upper) ) ! 等价于allocate(z(0:upper(1),0:upper(2),0:upper(3))
2. 使用integer常量表示数组维数。 real, rank(2) :: a ! 等价于 real :: a(:,:)
3. do concurrent的规约标识。与OpenMP中的reduction子句的用处一样。
real :: a, b, x(n)
do concurrent (i = 1:n)
reduce(+:a)
reduce(max:b)
a = a + x(i)**2
b = max(b, x(i))
end do 上面这个例子中,如果代码在编译后是并行执行的,在每个线程内都会创建私有的a和b变量,各线程计算完成后,再根据规约运算符合并得到最终结果。
允许的规约运算符包括+、*、.and.、.or.、.eqv.、.neqv.,以及max、min、iand、ieor、ior内置函数。
reduce子句中也可以放入一组规约变量,例如
do concurrent (i = 1:n)
reduce(+:a, b, c)
reduce(max:d, e, f)
枚举
1. Enumeration类型。Fortran 202X中新添加的特性。
enumeration type :: color
enumerator :: red, orange, green
end type
type(color) :: light
if (light == red) ... enumeration类型并不是派生类型,但是用法很像没有成员的派生类型。
定义一个enumeration类型时也会定义一系列枚举值enumerator。enumeration类型可以和integer类型相互转换:int(enumerator_value)返回enumerator在其类型定义中的位置;
enumeration_type(int)返回第int个枚举值。 i = int(green) ! 1 = 3 ?light = color(1) ! light = red 此外enumeration类型也可用于select case块中。
2. Enum类型。
Fortran 2018中引入的枚举类型,所以Fortran将同时存在两种“枚举”类型。
Fortran 2018中所谓的Enum类型本质上只是等价于定义了一些命名的integer常量,和integer类型没有任何区别。
在这次的Fortran 202X中,定义Enum类型就是定义一个新类型。目前发现Enum与Enumeration的区别只有前者可以为enumerator自定义枚举值。
例如
enum, bind(C) :: season enumerator :: spring = 4, summer = 7, autumn, winter
end enum
参考
1. J. Reid, https://wg5-fortran.org/N2151-N2200/N2194.pdf
2. j3-fortran, https://j3-fortran.org/doc/year/22/22-007.pdf
3. J. Williams, https://degenerateconic.com/the-new-features-of-fortran-202x.html
4. Doctor Fortran, https://stevelionel.com/drfortran/2022/03/28/doctor-fortran-in-its-getting-drafty-in-here/
常规|工具|专业|读物|
代码|教学|算法|
首页 >
FortranCoder手机版-导航