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
347 views
in Technique[技术] by (71.8m points)

fortran - Can the shape of an array in an interface match multiple fixed array size?

I have multiple subroutines with a parameter p which is an array of explicit size like

subroutine foo(p)
integer,dimension(2),intent(in) ::p
end subroutine foo

subroutine bar(p)
integer,dimension(3),intent(in) ::p
end subroutine bar

I'd like to call these two functions through an indirect call, but could not find a way to declare an interface that matches both foo and bar signature...

Using an assumed array size in the interface for example does not work:

subroutine indirect(f,p)
integer,dimension(*),intent(in):p
interface
  subroutine f(p)
  integer,dimension(*),intent(in) :: p
  end subroutine f
end interface
call f(p)
end subroutine indirect

When I invoke foo or bar thru indirect, the compiler (gfortran 4.9.2) complains about shape mismatch for first argument p of f...

integer,dimension(2) :: pfoo
integer,dimension(3) :: pbar

pfoo = (/ 0,1 /)

pbar = (/ 1,2,3 /)

call foo(pfoo) ! direct call is OK
call bar(pbar)

call indirect(foo,pfoo) ! compiler complains about foo signature
call indirect(bar,pbar) ! same for bar...

Compiler error is something like:

Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of argument 'p'

Of course, I could modify foo and bar signature to use assumed array size (*) instead of fixed array size, but

  1. it's like I'm loosing some information just for making the compiler happy without adding any kind of security

  2. foo and bar are not my code and I'd rather not change them...

I've found a workaround, but it consist of writing an assumed size wrapper for each subroutine foo and bar

call indirect(foo_wrapper,pfoo) ! compiler complains about foo signature
call indirect(bar_wrapper,pbar) ! same for bar...

subroutine foo_wrapper(p)
integer,dimension(*),intent(in) ::p
call foo(p)
end subroutine foo_wrapper

subroutine bar_wrapper(p)
integer,dimension(*),intent(in) ::p
call bar(p)
end subroutine bar_wrapper

or eventually, replacing all assumed size by deferred size in indirect and wrapper, so as to give a chance to runtime checks, also works, but that's not the point...

The point is, since I have many such foo/bar isn't there a way to declare the interface properly (I mean without wrappers or other artefacts).

I couldn't decipher the standard (I used http://www.j3-fortran.org/doc/year/10/10-007.pdf - I presume it's around 12.5.2.9 Actual arguments associated with dummy procedure entities §2), so I don't know if it's a limitation of gfortran. Right now i haven't any other compiler available, but I'd like to know if some other compiler would compile (intel? - I'm on windows 7 64 bits).

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

I'll look at whether gfortran is correct to complain and, regardless, what options there are to work around the complaint. References are to Fortran 2008.

12.5.2.9 is indeed important.

  1. If the interface of a dummy procedure is explicit, its characteristics as a procedure (12.3.1) shall be the same as those of its effective argument, except that [inapplicable things]

f in indirect is a dummy procedure with an explicit interface (through the interface block; 12.4.2.1). Looking at the reference 12.3.1 we see

The characteristics of a procedure are .. , the characteristics of its dummy arguments, ..

foo, bar and f are all procedures with a single dummy argument (all called p, by coincidence). So, if foo wants to be the effective argument associated with f then foo's p must match the characteristics of f's p. Each p is a dummy data object, so 12.3.2.2 becomes relevant:

The characteristics of a dummy data object are its type, its type parameters (if any), its shape, ... If a shape, size, or type parameter is assumed or deferred, it is a characteristic.

We have that the type and type parameters match. However, p in f has its size assumed. p in foo does not have this matching characteristic. It is, then, not allowed to associate foo with f in the call to indirect. The same holds for bar.

This requirement for matching characteristics of the dummy data objects to have the same shape also leads naturally to another conclusion: foo and bar don't have matching characteristics as procedures. For a third procedure to match both the shape characteristic must be ignored.

Using a wrapper subroutine is possible, but I'd also think about whether I could change the various subroutines to take assumed-shape arguments. This is much better than assumed-size. But, as you say, I'd also be reluctant to change that code.

For the subroutines foo and bar as you have them, there is another available option. Nothing about those subroutines requires a caller to have an explicit interface for them available (12.4.2.2). So, in indirect you could just scrap the interface block: the rules about matching are much more relaxed (other parts of 12.5.2.9). For other procedures this may not be possible, though.

All that said, ifort appears to happily compile and run the code as you have it...


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

...