EXTERNAL vs INTERNAL procedures and passing of them, F90/95 standard

EXTERNAL vs INTERNAL procedures and passing of them, F90/95 standard

With the Fortran 90/95 standard, the name of an internal procedure must not be passed as an argument to another procedure. This means that if you have a single procedure P1, that depends on arbitrary other procedures which share a common interface P2, you either have to:

A) Make many versions of P1 for each version of P2 you are likely to encounter. P2 can be then be internal, external, or module procedures in P1.

B) Declare all P2 as external, and lose all benefits of the use of modules and host association.

I am in a position whereby A) is too tedious since there are lots of P2's, and replication of P1 could lead to errors. Also, my code is structured in such a way that it would become really annoying if I lost the benefits of host association by making the P2's external. Finally, I realise that Compaq Visual Fortran allows one to pass internal procedures as an extension, but I wish to keep my code to the standard, so that it is easily portable.

Has anyone got a work around for this problem which sticks to the fortran 90/95 standard please?

Thanks alot,

Paul.

9 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

No replies... Presumably because there is no work around.
Its just an annoying restriction in f90/95.

For those that are interested, there is probably one way of getting around the problem. Upgrade to f2000. I found this document:
Proposals for new features in f2000
which contains this text:
--------------------------------------------

Number: 42 |

Title: Allow internal procedures as actual arguments

Submitted By: UK

Status: For Consideration for F2000

References:

Basic Functionality: Allow internal procedures as actual arguments.

Rationale: The data for a numerical problem is often expressed in the
form of a procedure as well as a set of numbers. Examples are to
integrate a function over an interval, to optimize a function over a
region, and to solve an equation. Procedure dummy arguments are
intended to provide this functionality, but are restricted in
Fortran 90, in that the corresponding actual argument is not
permitted to be an internal procedure. This prohibits a very
convenient mechanism to allow calls of the dummy procedure to access
other local data. Here is an example

            CALL SOLVE (F, A, B, X) ! Solve F(X)=0 in the interval (A,B)
              ............
     CONTAINS
            FUNCTION F(X)  ! By host association, F has access to
            REAL F, X      ! any data that it needs from the environment
                           ! at the point of call of SOLVE.

The lack of this facility has meant that library codes often use
"reverse communication", where a return is made in place of each call
of the dummy procedure. The above example becomes

            CONTROL = 1 ! Integer variable that controls the calls
            DO          ! Solve F(X)=0 in the interval (A,B)
               :        ! Code to calculate F(X)
              CALL SOLVE (CONTROL, A, B, X, F)
              IF (CONTROL==0) EXIT !  The solution has been found
            END DO

This is unnatural at the point of call and leads to poorly structured
code in the library procedure. It also means that the library code has
either to use the SAVE attribute for its local data (which inhibits
parallelism), to make copies of this data on each return, or rely on
arrays provided by the user (which may be accidentally corrupted by the
user).

Estimated Impact: The reason for this restriction is that the host
might be a recursive procedure, in which case an indicator of the
instance would need to be passed from the dummy procedure argument to
the actual argument. However, ... (Malcolm: please add words to explain
why this is not a problem). The additions needed to the standard will
not be great since all that is needed is to remove a restriction. Note
that the interface has to be explicit anyway.

Detailed Specification: Allow internal procedures as actual arguments.

Sorry. The link seems to have gone wrong. The URL for the F2000 proposals is:

http://www.mailbase.ac.uk/lists/comp-fortran-90/files/n1144.txt

Paul

You didn't allow much time for people to respond before you gave up! I don't have an answer, though. It's not clear what "upgrade to F2000" does for you here - there is no such standard at present, just a draft. Once it becomes a standard, it would be rather pointless to instantly declare your solution standard if in practice it means that few compilers support the feature.

As you note, Compaq Fortran already supports this, so if you stick to our compilers, you're all set! :-)

Steve

Retired 12/31/2016

Good fair comments. Cheers. Actually I will probably do exactly what you said, and use the Compaq extension to the standard.

At the moment the code is run and tested on a Windows based single-processor PC, but our department has purchased a Compaq multi-processor supercomputer to be arriving shortly. Presumably the supercomputer will come with compaq high performance fortran.

Do you know if this will also allow the extension to the f90/95 standard?

Cheers,

Paul

All Compaq Fortran 95 compilers support this extension.

Steve

Retired 12/31/2016

That's great. Cheers Steve and forall.

For those that are interested...

I have been in contact with a representative from NAG who also happens to be on the committee that decides on fortran standards, and have managed to obtain the following useful info:

The latest versions of the drafts of the new standard (f2000) and many other committee documents can be found at
http://www.j3-fortran.org/

Another useful link which contains details on the public consultation period for the new standard, plus links to a summary of the new features can be found at
http://www.bcs.org/siggroup/fortran/f200xf.htm

With regards to the passing of internal procedure names as actual arguments, since the UK was the only country which requested such an extension to the f90/95 standard, it did not actually gain sufficient support to gain approval. So we shouldn't expect to see it in f2000.

However, I found a work around which was simple to implement, and sticks to the f95 standard, the net personal consequence of which was that I had to use host association within a module to share some information, and alter one procedure so that it was no longer PURE. What I didn't realise is that internal, external, and module procedures are all classed as being independent, and that module procedures ARE allowed to be passed as actual arguments to other procedures, even though internal ones aren't. Therefore, I simply moved my internal procedures outside such that they were module procedures, (and I had to use host association within the module to transfer some data between the two).

In summary (or if what I just said didn't seem to make much sense), if you have a module which does contains a routine which integrates a function,

MODULE int_mod

CONTAINS

   REAL FUNCTION integrate(fun)
      INTERFACE
      REAL FUNCTION fun(x)
      REAL, INTENT(IN) x
      END FUNCTION fun
      END INTERFACE
      ...
   END FUNCTION integrate

END MODULE int_mod

then the following isn't allowed...

MODULE mod_A

CONTAINS

   SUBROUTINE sub_1
      USE int_mod
      ...
      result=integrate(fun)
      ...
   CONTAINS

      ! function fun declared as an internal procedure
      REAL FUNCTION fun(x)
         ...
      END FUNCTION fun

   END SUBROUTINE sub_1

END MODULE mod_A

but the following IS allowed

MODULE mod_A

CONTAINS

   SUBROUTINE sub_1
      USE int_mod
      ...
      result=integrate(fun)
      ...
   END SUBROUTINE sub_1

   ! function fun declared as a module procedure
   REAL FUNCTION fun(x)
      ...
   END FUNCTION fun

END MODULE mod_A

under the f95 standard. I hope that's clear.

Paul

Just a side remark: the (slight) disadvantage of that method vs. "pure" implementation in the language is inability to inherit automatic variables from the "host" procedure (since module variables are typically implemented as static). For example, variables in RECURSIVE procedures are automatic unless explicitly SAVEd.

That may sound exotic, but I've encountered ugly bugs in GUI codes related with my failures to declare routines RECURSIVE or variables (non-standardly) AUTOMATIC. You have no idea what an innocently-looking call to MessageBox function can do to execution path of your code :-).

Jugoslav

Jugoslav
www.xeffort.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today