Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Precision and Enumerators

lopes8070
Beginner
1,754 Views
program test

  integer :: i

  enum, bind (c)
    enumerator :: enum
  end enum

  print*, KIND(i), KIND(enum)

end program test

 

When compiled with ifort (IFORT) 15.0.3 20150407 and -i8 option, the kind of the enumerator does not match the kind of the default integer (4 vs. 8).  Shouldn't the enumerator also be of kind 8?  I have not tried compiling with the latest ifort.  Also, I tried the following but it threw compiler errors.

program test

  integer :: i

  enum (kind=8), bind (c)
    enumerator :: enum
  end enum

  print*, KIND(i), KIND(enum)

end program test

 

0 Kudos
9 Replies
Steven_L_Intel1
Employee
1,754 Views

Nope. Enumerators are always kind C_INT. There is no syntax to change it. The standard says:

For an enumeration, the kind is selected such that an integer type with that kind is interoperable (15.3.2) with the corresponding C enumeration type. The corresponding C enumeration type is the type that would be declared by a C enumeration specifier (6.7.2.2 of ISO/IEC 9899:1999) that specified C enumeration constants with the same values as those specified by the enum-def , in the same order as specified by the enum-def .

I don't have a C standard handy, but one reference I found says:

In ANSI C, the expressions that define the value of an enumerator constant always have int type; thus, the storage associated with an enumeration variable is the storage required for a single int value. An enumeration constant or a value of enumerated type can be used anywhere the C language permits an integer expression.

0 Kudos
Steven_L_Intel1
Employee
1,754 Views

By the way, if you no longer want to be (name withheld), go to the Dashboard (click on your name in the upper right and then Dashboard), and then edit your profile (I think it's a gear icon) to set a "Display Name".

0 Kudos
lopes8070
Beginner
1,754 Views

Steve,

Thanks again for a quick response (not the first time you have saved my rear).  In regard to the display name, I see nothing wrong with my profile.  I followed your instructions and my display name is set to what I want it to be.  Maybe I am missing something else.

 

For the enumerator, it seems strange that the following code will compile with -i4 but not -i8.  I guess I should specify the precision of the dummy enumerator in the function?

module modul

  interface foobar
    module procedure foo1
    module procedure foo2
  end interface foobar

contains

  subroutine foo1 (dmy_enum)
    integer :: dmy_enum
    print*, KIND (dmy_enum)
  end subroutine foo1

  subroutine foo2 (dmy_flt)
    real :: dmy_flt
  end subroutine foo2

end module modul

program test

  use modul

  integer :: i

  enum, bind (c)
    enumerator :: enum
  end enum

  print*, KIND(i), KIND(enum)
  call foobar (enum)

end program test

 

I guess I have to explicitly state that the argument to foo1 is always single precision 

integer (kind=4) :: dmy_enum

this would override anything specified on the command line, correct?

0 Kudos
lopes8070
Beginner
1,754 Views

Quick response, seems the display name is good to go, even though I didn't set anything... strange.

0 Kudos
Steven_L_Intel1
Employee
1,754 Views

The IDZ admins just changed things a bit so that it is ok if your display name is your login ID, as long as it isn't an email address. (And also as long as you're not an Intel employee.)

As I said above, an enum is always kind C_INT, which is 4 in our implementation. If you pass it to a routine that accepts it as "default integer" and change that default to kind 8, you have a kind mismatch and an error that is caught through the use of explicit interfaces here.

I recommend against using numbers as kinds, as it is not portable. If you're using ENUMs, it's probably best to use C_INT from ISO_C_BINDING. Elsewhere you can use SELECTED_INT_KIND or one of the values from ISO_FORTRAN_ENV as appropriate. A common practice is to have a "Kinds" module that declares PARAMETER constants for the various kinds to be used in the program, and then using the named constants throughout.

And lastly, you're not really specifying precision here, but kind - for integer types that affects the range in the model - precision for integers isn't meaningful.

0 Kudos
lopes8070
Beginner
1,754 Views

Steve,

Yes, I agree.  And I am doing exactly as you say with the KIND module.  I set the default integer kind to INT32 or INT64 depending on a switch at compile time.  I use to have all my integers set to {{{integer (INT32)}}} or {{{integer (INT64)}}} but now I have to distinguish between integers and enumerators.  I am now setting all enumerators to INT32 regardless of that switch I mentioned.  Are you saying that I should set all enumerators to C_INT?  Is there a difference between INT32 and C_INT?  I wish you could set the enumerator as the dummy argument like below.

Thanks

 

module modul

  interface foobar
    module procedure foo1
    module procedure foo2
  end interface foobar

contains

  subroutine foo1 (dmy_enum)
    enumerator :: dmy_enum    !<---------- declare dummy argument as enumerator, not integer.
    print*, KIND (dmy_enum)
  end subroutine foo1

  subroutine foo2 (dmy_flt)
    real :: dmy_flt
  end subroutine foo2

end module modul

program test

  use modul

  integer :: i

  enum, bind (c)
    enumerator :: enum
  end enum

  print*, KIND(i), KIND(enum)
  call foobar (enum)

end program test

 

0 Kudos
lopes8070
Beginner
1,754 Views

Also, I looked but could not find, is there a compiler flag that will throw a warning with mixed kind operations, like multiplication/addition/sin/log?

0 Kudos
Steven_L_Intel1
Employee
1,754 Views

In our implementation, INT32 and C_INT are the same. But that may not be the case everywhere. You could do this, though:

module modul

  interface foobar
    module procedure foo1
    module procedure foo2
  end interface foobar

  enum, bind(C)
    enumerator :: enum_proto
  end enum
  integer, parameter :: enum_kind = kind(enum_proto)

contains

  subroutine foo1 (dmy_enum)
   integer(enum_kind), intent(IN) :: dmy_enum.
    print*, KIND (dmy_enum)
  end subroutine foo1

We tend not to offer warnings for standard usage that could be problematic, though I have lobbied the developers to add such,  Asking for standards checking will warn you about cases that we allow as extensions.

0 Kudos
lopes8070
Beginner
1,754 Views

Ok, thanks for the help!  I will do something similar to what you say.  I do not think i will use the prototype that you suggest mainly because we are pretty much sticking with intel (and I'll use C_INT).  We use 2003/2008 extensively and even though we have put significant effort into using other compilers, non are close to as much support as intel.  

0 Kudos
Reply