# 逐元操作

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

- `elemental` 过程；
- *显式形状* 数组；
- 实现向量的操作，并对不同的维度编写简单的包装器（内部使用`reshape`实现）。

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

``` fortran
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
```

所有参数（`in`和`out`）必须是标量。例如，您可以对任何（兼容的）形状的数组使用此函数，

``` fortran
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)
```

输出如下，

``` fortran
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` 关键字来取消这一限制，

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