views:

172

answers:

2

hello,

GOOGLE has yet to find an answer for me, so here goes:

In FORTRAN, is there a way to determine the TYPE of a variable? E.G., pass the variable type as an argument in a function, to then be able to call type-specific code with that fuction; eliminating the need to have seperate similar functions for each data type. thanks.

+1  A: 

Well you might be able to do what you want if you mess about with the KIND intrinsic and POINTERs, but if you are only concerned with the signature of functions and subroutines, leave it to Fortran. If you define

function calc8(arg1)
    real(8), intent(in) :: arg1
    ...

and

function calc4(arg1)
    real(4), intent(in) :: arg1
    ...

in a module, and declare an interface like this

interface calc
    module procedure calc8
    module procedure calc4
end interface

(Warning, I haven't checked the syntax in detail, that's your responsibility.)

then Fortran will match the call to the right version of the function. Sure, you have to write both versions of the function, but that's really the Fortran 95 way of doing it. This can be quite tedious, I tend to write a generic version and run a sed script to specialise it. It's a bit of a kludge but it works.

If the code of the function is identical apart from the kind of the arguments I sometimes write the function for real(8) (or whatever) and write a version for real(4) which calls the real(8) version wrapped in type conversions.

In Fortran 2003 there are improved ways of defining polymorphic and generic functions, but I haven't really got my head around them yet.

High Performance Mark
A: 

Yes, there are two ways.

The first way does requires you to write separate functions or subroutines for each variable type, but you don't have to call different functions. This may or may not be close enough to what you want. You write the separate routines, then to write an interface to create a generic function or subroutine wrapping these specific subroutines. You don't have to pass the variable type, or do anything special in your call -- it is all done via the declaration and automatically by the compiler from the variable itself, as long as the variables are different enough that the compiler can distinguish them (there are rules about what is required). This is similar to how intrinsic functions work -- you can call sin with a real argument, a double precision real argument or a complex argument and the compiler calls the correct actual function and returns the matching result. High Performance Mark sketched a solution along these lines. For another question, I posted a working example, where the distinguishing feature of the variables was array rank: http://stackoverflow.com/questions/2257248/fortran-2003-how-to-write-wrapper-for-allocate. An advantage of this method is that it is widely support by Fortran compilers.

In Fortran 2003/2008 there are extensive object oriented features. Quoting "Fortran 95/2003 explained" by Metcalf, Reid and Cohen, "To execute alternative code depending on the dynamic type of a polymorphic entity and to gain access to the dynamic parts, the select type construct is provided." The select type statement is a bit similar to a select case statement. This is support by fewer compilers. Again, you don't have to pass the type, since the compiler can figure it you from the variable itself. But it has to be a polymorphic type... Both Intel ifort and gfortran list select type and polymorphic datatypes as supported -- the later with some experimental aspects in gfortran (http://gcc.gnu.org/wiki/Fortran2003). These are recent additions to these compilers.

M. S. B.
There is a code example of "select type" with a polymorphic type at http://software.intel.com/en-us/forums/showthread.php?t=73454
M. S. B.