今天介绍的是Fortran中一些零零散散的语句,有些之前提到过,不过没有细讲。

forall

forall是一种并行的循环,也就是说,在forall程序块中的语句是一句一句执行的,并且每一句对应的所有指数的元素是同时进行计算的,这里说起来有点绕,举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
1    integer :: num(5), i
2 num = 0 ! [0,0,0,0,0]
3 forall(i=2:5)
4 num(i) = i ! [0,2,3,4,5]
5 num(i) = num(i-1) + 1 ! [0,1,3,4,5]
6 end forall
7 write(*,*) num
8 num = 0 ! [0,0,0,0,0]
9 do i=2,5
10 num(i) = i ! [0,2,3,4,5]
11 num(i) = num(i-1) + 1 ! [0,1,2,3,4]
12 end do
13 write(*,*) num

这里通过do和forall语句的对比能看出来,forall中元素是一起执行的(第5行),有点像Python中对元组的操作(通过x,y=y,x就可以达到交换元素的目的 )。而do是每个指标依次执行。这里能看出来,其实只要同一行代码指标是相同的,do和forall的结果就会是一样的(第5行代码中指标出现了i和i-1两个)。forall也可以多层循环,甚至可以加一个简单的判断,形式如下:

1
2
3
forall(指标1,指标2...指标n,判断条件)
循环体
end forall

这里另外一个要注意的地方时,这里指标循环上下限中间是冒号:隔开的。

where

where语句是通过判断条件是否满足再执行相应的语句,这里的循环过程和forall是一致的,是同时执行的。例如:

1
2
3
4
5
6
1    integer :: arr1(5)=[1,2,3,4,5]
2 integer :: arr2(5)=[5,4,3,2,1], arr3=0
3 where(arr1>arr2)
4 arr3=arr1
5 end where
6 write(*,*) arr3 ! [0,0,0,4,5]

还有elsewhere语句可以进行where中的else判断。

associate

associate有点类似于C/C++中的宏定义(#define),但是又不同,举个例子:

1
2
3
4
5
1    real, parameter :: pi=3.1415926
2 associate(p => pi)
3 write(*,*) p*2.0
4 write(*,*) p**2.0
5 end associate

这里的例子举的不太好,但是能看出这个关键字的功能,有时候变量名会很长(尤其是调用类type中的变量,甚至多层),会简化很多代码。associate可以定义多个简化变量,用逗号,隔开。