为 Fortran 数组操作指定冒号



Fortran允许非常容易地使用数组操作。例如

double precision :: a(3,3), b(3,3), c(3,3)

鉴于初始化ab,我知道一个简单的c=a+b会导致矩阵添加。使用c(:,:) = a(:,:)+b(:,:)也可以实现相同的目的。我知道第二种方法允许使用适当的索引对数组进行切片。除此之外,这两种方法之间有什么区别吗?是否应该优先使用特定方法?

在表达式中

c = a + b

abc的引用是整个数组。 在

c(:,:) = a(:,:) + b(:,:)

a(:,:)b(:,:)c(:,:)的引用都是对数组部分的引用。 这些是不同的东西。

通常,数组部分没有整个数组的属性:如果c是指针或可分配数组,即使c(:,:)不是。 当分配时可能发生重新分配时,这种方面最为明显。

c=a+bc可以未分配,并将在响应中分配,但在c(:)=...c必须在分配之前分配。 如果在分配c=...时分配了c,则在以下情况下将取消分配:

  • 右侧的形状与c的形状不同;或
  • 右侧的任何长度类型参数都与c不同;或
  • c是多态的,具有与c不同的右侧表达式的动态类型或相应的种类类型参数。

如果存在此类释放,则重新分配c以匹配右侧表达式。

对于数组部分,不存在这样的自由:c(:)必须适当地匹配右侧表达式,或者必须有适当的转换可用(包括定义的赋值)。

从整个数组和数组部分的区别来看,还有其他方面。

在数组是显式形状的问题的特定上下文中

,则无需担心。在风格方面,人们可能会认为使用数组部分可以增加代码的人类读者的清晰度,因为"这是一个数组赋值",或者使用整个数组来帮助编译器优化数组操作。 这些之间的平衡是特定于情况的,King指出了一个考虑性能方面的相关问题。

此外,由于上面提到的释放/重新分配,编译器有义务对可分配的整个数组的内部赋值执行(可能昂贵的)形状/类型/类型参数检查(以确定是否必须进行释放)。 使用数组部分意味着不需要这些测试。例如,与

c(:,:) = array_expr

程序员保证数组表达式array_exprc具有相同的形状(如果不是这种情况,则片段不能是有效的Fortran),并且编译器不需要运行释放检查。同样,使用它是针对个人情况的选择。 (另请注意,编译器可能会提供运行时检查,查看此类表达式是否匹配:如果使用此"技巧",则应禁用这些检查。

最新更新