Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Tagging in Fortran (like enum)

emreka82
Beginner
1,869 Views

Hi,

I would like to tag some pointers to some values, such a definition reminds me the enumeration type of C, such as:

 [cpp] enum ctype { out, cut, in, sp}; [/cpp]

and we have a pointer (named as type_) that will be allocated for the values above:

 [cpp] ctype *type_;  [/cpp]

in a subroutine I try to tag a pointer such as:

 [cpp]

if(*nnn->type_==out)

{

}

if(*nnn->type_==cut)

{

}

if(*nnn->type_==in)

{

}

if(*nnn->type_==sp)

{

}

 [/cpp]

How can I rewrite the above tagging in Fortran, should I use  [fortran] integer(selected_int_kind)  [/fortran] or [fortran] enum, bind(c) ctype [/fortran] ? I try both of them but cannot figure out what is wrong... I will appreciate any contribution, suggestion about the problem. Thanks.

0 Kudos
5 Replies
IanH
Honored Contributor III
1,869 Views
Are you interacting with C code, or are you rewriting something in Fortran exclusively? If you want an enumeration that lines up exactly with the values and storage that you get in C, then the syntax is: [fortran] ENUM, BIND(C) ENUMERATOR :: out, cut, in, sp END ENUM [/fortran] Note that you don't name the enumeration, just the enumerators. If you want the kind used for the enumerators, then you can just use KIND(out), or similar. If you are just working in the Fortran world, then you could just declare the integer constants that are the enumerators directly. Perhaps something like: [fortran] INTEGER, PARAMETER :: ctype_kind = KIND(1) INTEGER(ctype_kind), PARAMETER :: out = 1 INTEGER(ctype_kind), PARAMETER :: cut = 2 INTEGER(ctype_kind), PARAMETER :: in = 3 INTEGER(ctype_kind), PARAMETER :: sp = 4 [/fortran] In the above, the kind for the enumeration is just default kind you could change that depending on your requirements. Practically the two forms are often equivalent - the kind of a enumeration that interoperates with C may well be default kind.
0 Kudos
emreka82
Beginner
1,869 Views
IanH wrote:

If you are just working in the Fortran world, then you could just declare the integer constants that are the enumerators directly. Perhaps something like:


  INTEGER, PARAMETER :: ctype_kind = KIND(1)

  INTEGER(ctype_kind), PARAMETER :: out = 1

  INTEGER(ctype_kind), PARAMETER :: cut = 2

  INTEGER(ctype_kind), PARAMETER :: in = 3

  INTEGER(ctype_kind), PARAMETER :: sp = 4

In the above, the kind for the enumeration is just default kind you could change that depending on your requirements.

Practically the two forms are often equivalent - the kind of a enumeration that interoperates with C may well be default kind.

I think, second one is my choice, my code will be in Fortran. The most important part of my problem is the "CALL" part. I want to call the ctype_kind and tag it, such as: [fortran] if(nnn%type_==out) then !...statements end if if(nnn%type_==cut) then !...statements end if if(nnn%type_==in) then !...statements end if if(nnn%type_==sp) then !...statements end if [/fortran] , where nnn is a pointer which points to a next pointer type_ and type_ has the enumerated values in, out, cut and sp.
0 Kudos
emreka82
Beginner
1,869 Views
emreka82 wrote:

Quote:

IanH wrote:

If you are just working in the Fortran world, then you could just declare the integer constants that are the enumerators directly. Perhaps something like:

INTEGER, PARAMETER :: ctype_kind = KIND(1) INTEGER(ctype_kind), PARAMETER :: out = 1 INTEGER(ctype_kind), PARAMETER :: cut = 2 INTEGER(ctype_kind), PARAMETER :: in = 3 INTEGER(ctype_kind), PARAMETER :: sp = 4

In the above, the kind for the enumeration is just default kind you could change that depending on your requirements.

Practically the two forms are often equivalent - the kind of a enumeration that interoperates with C may well be default kind.

I think, second one is my choice, my code will be in Fortran. The most important part of my problem is the "CALL" part. I want to call the ctype_kind and tag it, such as:


if(nnn%type_==out) then

!...statements

end if
if(nnn%type_==cut) then

!...statements

end if
if(nnn%type_==in) then

!...statements

end if
if(nnn%type_==sp) then

!...statements

end if

, where nnn is a pointer which points to a next pointer type_ and type_ has the enumerated values in, out, cut and sp.

I have written a module, a main program and two subroutines to clearly understand the problem, then I think I figure it out, can you check it ? Module: [fortran] module param_mod type c_type integer :: val end type c_type type(c_type), parameter :: out=c_type(0), cut=c_type(1), sp=c_type(2), in=c_type(3) type c type(c_type), pointer :: type_ end type c interface operator(==) module procedure operate end interface contains logical function operate(a,b) type(c_type), intent(in) :: a,b operate = a%val.eq.b%val end function operate end module param_mod [/fortran] Main program: [fortran] program param use param_mod call example call system('pause') end program param [/fortran] Invoking subroutine: [fortran] subroutine invoke(nnn2) use param_mod type(c), pointer :: nnn2 allocate(nnn2) allocate(nnn2%type_) nnn2%type_=cut end subroutine invoke [/fortran] Example subroutine: [fortran] subroutine example use param_mod integer, target :: new type(c), pointer :: nnn allocate(nnn) allocate(nnn%type_) call invoke(nnn) ! here I tag the "nnn%type_" as "cut". print*, nnn%type_ ! shows the value of the pointer if(nnn%type_==out) then ! if nnn%type_= out, values are both 0 print*, "out" !...statements else if(nnn%type_==cut) then ! if nnn%type_= cut, values are both 1 print*, "cut" !...statements else if(nnn%type_==sp) then ! if nnn%type_= sp, values are both 2 print*, "sp" !...statements else ! if nnn%type_= in, values are both 3 print*, "in" !...statements end if deallocate(nnn%type_) deallocate(nnn) end subroutine example [/fortran] As you can see above, I overload the operator ==, could the overloading result in any problem ? And do you have any suggestions for more clever and direct solution for the problem other than that above ? Thanks.
0 Kudos
IanH
Honored Contributor III
1,869 Views
I don't understand what it is that you are trying to achieve. Wrapping an integer component in a derived type with appropriate set and test (operator(==)) procedures is certainly one way to implement a strongly typed enumeration in Fortran. There are some disadvantages - for example you can't use such an enumeration directly in a SELECT CASE construct. (Your invoke procedure in your example code has a dummy argument (nnn2) that is a pointer - an explicit interface is required.)
0 Kudos
emreka82
Beginner
1,869 Views
Firstly, thanks for the contribution Ian, you have been very helpful. I have some questions in my mind about your comments:
IanH wrote:

I don't understand what it is that you are trying to achieve.

Wrapping an integer component in a derived type with appropriate set and test (operator(==)) procedures is certainly one way to implement a strongly typed enumeration in Fortran. There are some disadvantages - for example you can't use such an enumeration directly in a SELECT CASE construct.

(Your invoke procedure in your example code has a dummy argument (nnn2) that is a pointer - an explicit interface is required.)

I am trying to tag a pointer(type_) as out, cut, sp or in. This pointer (type_) is a component of another pointer (nnn or nnn2).
IanH wrote:

Wrapping an integer component in a derived type with appropriate set and test (operator(==)) procedures is certainly one way to implement a strongly typed enumeration in Fortran. There are some disadvantages - for example you can't use such an enumeration directly in a SELECT CASE construct.

Then, my solution is correct, right ? Where would I need "SELECT CASE construct" ?
IanH wrote:

(Your invoke procedure in your example code has a dummy argument (nnn2) that is a pointer - an explicit interface is required.)

"explicit interface is required", then should I write an interface in the param_mod module, right ? Such as: [fortran] module param_mod !...................... interface subroutine invoke(nnn2) type(c), pointer :: nnn2 end subroutine invoke end interface [/fortran]
0 Kudos
Reply