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

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

问题描述

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

  b 

整数,参数:: p = 3,q = 4,r = 5
整数a(p,q,r),i,j, k
integer,allocatable :: b(:,:)

a = reshape([(((100 * i + 10 * j + k,i = 1,p) 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)自动(重新)分配
!分配(b,source = a(:,1,:))!! (B)来源分配
!分配(b,霉= a(:,1,:))!! (C)假定形状分配

print * $ b b print *,shape(b)=,shape(b)
print *,b(:, :) =,b
结束

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

  gfortran4.8.2 
[A]
形状(b)= 3 5
b(:, :) :) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B],[C]
f951:内部编译器错误:分段错误
(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
错误:ALLOCATE语句在(1 )

gfortran6.0.0(实验)
[A]
形状(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(:, :) :) 0 -1094645928 57 141 241 341 142 242 342 143 243 343 144 244 344
[C]
shape(b)= 3 5
b( :,:) =(垃圾数据,合理)

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]
形状(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]
形状(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(:, :) =(垃圾数据,合理)

解决方案

在Fortran 2中引入了源分配003以及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天全站免登陆