逐元操作

当使用子例程和函数时,有三种方法可以在数组上执行逐元操作:

  • elemental 过程;
  • 显式形状 数组;
  • 实现向量的操作,并对不同的维度编写简单的包装器(内部使用reshape实现)。

在第一种方法中,使用elemental关键字创建这样的函数:

real(dp) elemental function nroot(n, x) result(y)
  integer, intent(in) :: n
  real(dp), intent(in) :: x
  y = x**(1._dp / n)
end function nroot

所有参数(inout)必须是标量。例如,您可以对任何(兼容的)形状的数组使用此函数,

print *, nroot(2, 9._dp)
print *, nroot(2, [1._dp, 4._dp, 9._dp, 10._dp])
print *, nroot(2, reshape([1._dp, 4._dp, 9._dp, 10._dp], [2, 2]))
print *, nroot([2, 3, 4, 5], [1._dp, 4._dp, 9._dp, 10._dp])
print *, nroot([2, 3, 4, 5], 4._dp)

输出如下,

3.0000000000000000
1.0000000000000000        2.0000000000000000        3.0000000000000000        3.1622776601683795
1.0000000000000000        2.0000000000000000        3.0000000000000000        3.1622776601683795
1.0000000000000000        1.5874010519681994        1.7320508075688772        1.5848931924611136
2.0000000000000000        1.5874010519681994        1.4142135623730951        1.3195079107728942

如上,通常情况下,n是一个参数,而x是一个任意形状的数组。 但是如您所见,只要最终的操作是有意义的(即如果一个参数是数组, 那么其他的参数必须是相同的形状的数组或标量),Fortran并不在乎其形式。 如果不满足,那么将得到一个编译错误。

elemental关键字通常意味着pure关键字,因此过程必须是纯的,没有副作用。 您可以添加 impure 关键字来取消这一限制,

impure elemental subroutine write_all(a)
  inetger, intent(in) :: a
  write(*,"(g0)") a
end subroutine write_all