Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can Fortran 95 reuse interfaces?

Status
Not open for further replies.

AlanRominger

Technical User
Jan 12, 2012
2
US
I found a sweet syntax that was really helpful to simplify a lot of code. Problem is, I discovered this is a Fortran 2003 feature. It works like this:

interface
subroutine name_in_interface(a)
real, dimension:)), intent(in) :: a
end subroutine name_in_interface
end interface

procedure (name_in_interface) :: actual_procedure_name

With this, you can use the same interface type for multiple functions. Again, the problem is, this doesn't seem to be a 95 feature. I want to ask if there is any way to have the following code made cleaner using only Fortran 95 features. This does not compile, for instance, in g95. Do Fortran coders who don't use a modern compiler have no choice but to copy the interface over and over again no matter how large their project is (because you must use interfaces if there are assumed size arrays)? Thanks.

And someone, please please let me know how to properly quote code in these forums. I looked for a while and couldn't find anything (although I see where other people did it).

module routine_interfaces
implicit none
interface

subroutine one_array(array)
real, dimension:)), intent(in) :: array
end subroutine one_array

end interface
end module routine_interfaces

program main
use routine_interfaces
implicit none
real, dimension(3) :: a

procedure(one_array) :: sum_array, div_array, sd_array

a = 2.

call sum_array(a)
call div_array(a)
call sd_array(a)

end program main


subroutine sum_array(a)
implicit none
real, dimension:)), intent(in) :: a
write(*,*) ' sum= ',sum(a)
end subroutine sum_array

subroutine div_array(a)
implicit none
real, dimension:)), intent(in) :: a
write(*,*) ' sum= ',sum(1./a)
end subroutine div_array

subroutine sd_array(a)
implicit none
real, dimension:)), intent(in) :: a
write(*,*) ' sum= ',sum(a+1./a)
end subroutine sd_array

 
The normal way, in any Fortran version greater than 77, consists in avoiding interfaces, just in putting your subroutines within a module :

Code:
module routines
contains
subroutine sum_array(a)
  implicit none
  real, dimension(:), intent(in) :: a
  write(*,*) ' sum= ',sum(a)
end subroutine sum_array

subroutine div_array(a)
  implicit none
  real, dimension(:), intent(in) :: a
  write(*,*) ' sum= ',sum(1./a)
end subroutine div_array

subroutine sd_array(a)
  implicit none
  real, dimension(:), intent(in) :: a
  write(*,*) ' sum= ',sum(a+1./a)
end subroutine sd_array

end module

program main
  use routines
  implicit none
  real, dimension(3) :: a
  
  a = 2.
  
  call sum_array(a)
  call div_array(a)
  call sd_array(a)
  
end program main

Result with g95 :

Code:
[lcoul@localhost test]$ g95 t63.f90
[lcoul@localhost test]$ ./a.out
  sum=  6.
  sum=  1.5
  sum=  7.5

Notice that this solution is shorter than yours, works with any F90 compiler, and is much less error prone.

For instance, if one of your routines does not respect the interface, then your code will fail when running. One the contrary, with the classical solution, the compiler will detect immediately any discrepancy between the calling sequence and the subroutine signature.

A general good advice : avoid external procedure (i.e. procedures defined outside modules)


François Jacq
 
And someone, please please let me know how to properly quote code in these forums. I looked for a while and couldn't find anything (although I see where other people did it).

You can get a short user manual just in pressing the button "preview post"

François Jacq
 
True, the solution offered by FJacq seems to be robust. I recently encountered something that confused me even more. I discovered that the following does in fact work with g95.

Code:
module routine_interfaces
  implicit none
  interface
    subroutine array_function(array)
      real, dimension(:), intent(in) :: array
    end subroutine array_function
  end interface
  
  contains
  
  subroutine call_the_proc(a_proc,a_array)
    procedure(array_function) :: a_proc
    real, dimension(:), intent(in) :: a_array
    
    call a_proc(a_array)
    
  end subroutine call_the_proc
  
  
end module routine_interfaces

module model

  contains
  
  subroutine sum_array(a)
    implicit none
    real, dimension(:), intent(in) :: a
    
    write(*,*) ' size= ',size(a)
    write(*,*) ' sum= ',sum(a)
    
  end subroutine sum_array

end module model

program main
  use routine_interfaces
  use model
  implicit none
  real, dimension(3) :: a
  
  a = 2.
  
  call call_the_proc(sum_array,a)
  
end program main

Now it's driving me a little crazy wondering if this is really Fortran 95 acceptable, or if this is just because g95 felt like allowing it. The procedure statement is used, but only within the module. That would actually be kind of useful, but I don't know what version of Fortran this is supposedly using.
 
PROCEDURE declaration (see OP) is Fortran 2003 feature.
The g95 compiler implements Fortran 95 Standard. Now it also has partial support of some Fortran 2003 features.
 
You are using Fortran2003 which has introduced the syntax "procedure(...)".

This is often strongly connected to abstract interfaces (again a F2003 notion) and I would like also to mention the useful addition of procedure pointers which were missing in F95.

François Jacq
 
Apropos, the simplest way to get a short user manual on post formatting is:
Click "Process TGML" link on the post input form (turn on scripting in your browser).
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top