Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
725 views
in Technique[技术] by (71.8m points)

fortran - Sourced allocation of a non-contiguous array section

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)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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".


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...