非连续数组部分的源分配 [英] Sourced allocation of a non-contiguous array section

查看:30
本文介绍了非连续数组部分的源分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于最近的帖子关于如何简明地声明数组形状,我尝试了以下三种模式,即(A)自动重新分配,(B)源分配,以及(C)具有假定形状的分配.然后,在源分配的情况下,gfortran 似乎为 b(:,:) 提供了不正确的结果.在这里,我做错了什么,还是仅仅是因为 gfortran 尚未完全支持它?虽然后者似乎很可能,但我不太确定我的 gcc5 和 6 的安装或使用是否正确(我使用的是 Linux x86_64).

程序主隐式无整数,参数 :: p=3, q=4, r=5整数 a( p, q, r ), i, j, k整数,可分配 :: b( :, : )a = reshape( [ ((( 100*i + 10*j + k, i=1,p), j=1,q), k=1,r) ], [p,q,r] )打印 *print *, "shape( a ) = ", shape( a )打印 *, "a(:,:,:) = ", a打印 *, "a(:,1,:) = ", a(:,1,:)b = a( :, 1, : ) !!(A) 自动(重新)分配!分配(b,源 = a(:,1,:))!(B) 来源分配!分配(b,模具=a(:,1,:))!(C) 具有假定形状的分配打印 *打印*, "形状( b ) = ", 形状( b )打印 *, "b(:,:) = ", b结尾

结果:(在所有情况下,自动重新分配都会给出正确的结果.)

gfortran4.8.2[一种]形状( b ) = 3 5b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315[乙], [丙]f951:内部编译器错误:分段错误gfortran5.2.1[一种]形状( b ) = 3 5b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315[乙], [丙]分配( b, 源 = a( :, 1, : ) )1错误:在 (1) 处的 ALLOCATE 语句中需要数组规范gfortran6.0.0(实验性)[一种]形状( b ) = 3 5b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315[B] <--- 似乎不正确形状( b ) = 3 5b(:,:) = 0 -1094645928 57 141 241 341 142 242 342 143 243 343 144 244 344[C]形状( b ) = 3 5b(:,:) =(垃圾数据,合理)英特尔 Fortran 14.0.1(-假设 realloc_lhs)[一种]形状( b ) = 3 5b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315[乙]形状( b ) = 3 5b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315[C]形状( b ) = 3 5b(:,:) = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0甲骨文 Fortran 12.4[一种]形状( b ) = 3 5b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315[乙]形状( b ) = 3 5b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315[C]形状( b ) = 3 5b(:,:) =(垃圾数据,合理)

解决方案

在 Fortran 2003 中引入了源分配,并且在 Fortran 2008 中更改了规则/约束.gfortran 5.2.1 拒绝程序似乎是一个结果遵循 F2003.

在 F2003 下,源分配需要明确指定要分配的数组的数组边界.在 F2008 下,这不是必需的,另外可以指定多个要分配的对象.因此,您的代码无效 F2003.

然而,该程序(好吧,那个分配部分)是有效的 F2008:要分配的数组的边界可能来自源表达式,就像值一样.数组部分的连续性或其他方面不重要,因为表达式的值(和边界)才是关键.自然地,表达式数组边界的计算为出错提供了机会.

总之,分配表在 F2008 下有效,但在 F2003 下无效.使用 F2003 规则的编译器必须能够检测到违规行为,而不是随意胡说八道.但是 F2008 很容易出错.

而且,由于您的测试,为 gfortran 编写此代码的安全方法是

allocate(b(p,r), source=a(:,1,:))

确实,gfortran 文档将边界的给出列为未实现".>

In relation to a recent post regarding how to declare the array shape concisely, I tried the following three patterns, i.e., (A) automatic re-allocation, (B) sourced allocation, and (C) allocation with assumed shape. Then gfortran seems to give incorrect results for b(:,:) in the case of sourced allocation. Here, am I doing something wrong, or is this simply because it is not yet fully supported by gfortran? Although the latter seems likely, I am not very sure if my installation or usage of gcc5 and 6 is correct (I am using Linux x86_64).

program main
    implicit none
    integer, parameter :: p=3, q=4, r=5
    integer a( p, q, r ), i, j, k
    integer, allocatable :: b( :, : )

    a = reshape( [ ((( 100*i + 10*j + k, i=1,p), j=1,q), k=1,r) ], [p,q,r] )

    print *
    print *, "shape( a ) = ", shape( a )
    print *, "a(:,:,:) = ", a
    print *, "a(:,1,:) = ", a(:,1,:)

    b = a( :, 1, : )                           !! (A) automatic (re)allocation
    ! allocate( b, source = a( :, 1, : ) )     !! (B) sourced allocation
    ! allocate( b, mold = a( :, 1, : ) )       !! (C) allocation with assumed shape

    print *
    print *, "shape( b ) = ", shape( b )
    print *, "b(:,:) = ", b
end

Results: (In all cases, automatic reallocation gives the correct result.)

gfortran4.8.2
[A]
shape( b ) =   3   5
b(:,:) =  111  211  311  112  212  312  113  213  313  114  214  314  115  215  315
[B], [C]
f951: internal compiler error: Segmentation fault

gfortran5.2.1
[A]
shape( b ) =   3   5
b(:,:) =  111  211  311  112  212  312  113  213  313  114  214  314  115  215  315 
[B], [C]
allocate( b, source = a( :, 1, : ) )
         1
Error: Array specification required in ALLOCATE statement at (1)

gfortran6.0.0 (experimental)
[A]
shape( b ) =   3   5
b(:,:) =  111  211  311  112  212  312  113  213  313  114  214  314  115  215  315
[B]  <--- seems incorrect
shape( b ) =   3   5
b(:,:) =  0  -1094645928  57  141  241  341  142  242  342  143  243  343  144  244 344
[C]
shape( b ) =   3   5
b(:,:) = (garbage data, reasonable)

Intel Fortran 14.0.1 (-assume realloc_lhs)
[A]
shape( b ) =   3   5
b(:,:) =  111  211  311  112  212  312  113  213  313  114  214  314  115  215  315
[B]
shape( b ) =   3   5
b(:,:) =  111  211  311  112  212  312  113  213  313  114  214  314  115  215  315
[C]
shape( b ) =   3   5
b(:,:) =  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

Oracle Fortran 12.4
[A]
shape( b ) =  3 5
b(:,:) =  111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B]
shape( b ) =  3 5
b(:,:) =  111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[C]
shape( b ) =  3 5
b(:,:) = (garbage data, reasonable)

解决方案

Sourced allocation was introduced in Fortran 2003 and the rules/constraints were changed in Fortran 2008. Rejection of the program by gfortran 5.2.1 would appear to be a consequence of following F2003.

Under F2003 sourced allocation required the explicit specification of array bounds for the array to be allocated. Under F2008 this is not required, and additionally multiple objects to be allocated could be specified. So, your code isn't valid F2003.

The program (well, that allocation part) is, though, valid F2008: the bounds of the array to be allocated may come from the source expression just as the value does. The contiguity or otherwise of the array section shouldn't be important as it's the value (and bounds) of the expression being key. Naturally, the calculation of bounds of the expression array offers opportunity for things to go wrong.

In conclusion, the allocation statement is valid under F2008 but not under F2003. A compiler which is using the F2003 rules must be able to detect the violation rather than being free to give nonsense. But F2008 is easy enough to do buggily.

And, thanks to your testing, the safe way to write this code for gfortran would be

allocate(b(p,r), source=a(:,1,:))

Indeed, documentation for gfortran lists the giving of bounds as being "unimplemented".

这篇关于非连续数组部分的源分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆