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

Parameter statement with conditional declaration

sant
Novice
4 250 Visites

Hello,

the following program throws the following compiler error with IVF Composer XE 2013:

error #6263: This intrinsic function is invalid in constant expressions. [MERGE]

>>
program test
implicit none

integer :: id

id=4

call testsub(id)

end

subroutine testsub(id)
implicit none

integer, parameter :: id1=1
integer :: id
integer, parameter :: idim=merge(1,3,id==id1)

real(8) :: a
real(8) :: stor(100)

equivalence(stor(idim+1),a)

return
end
<<

What I am trying to do is to set the value of a parameter (IDIM) based on the value of another variable (ID) that will be available at runtime. I know from the error that intrinsic functions such as MERGE cannot be used in PARAMETER statements. Does anyone know how I can achieve what I'm trying to do. Thanks.

0 Compliments
1 Solution
sant
Novice
4 187 Visites
0 Compliments
12 Réponses
JohnNichols
Précieux contributeur III
4 243 Visites
program test
implicit none

integer :: id

id=4

call testsub(id)

end

subroutine testsub(id)
implicit none

integer, parameter :: id1=1
integer :: id
integer, parameter :: idim=merge(1,3,id==id1)

real(8) :: a
real(8) :: stor(100)

equivalence(stor(idim+1),a)

return
end
0 Compliments
jimdempseyatthecove
Contributeur émérite III
4 221 Visites

Parameters must be declared with constant expressions. The variable id in testsub is not constant (parameter).

Try (untested code):

 

module params
  integer, parameter :: id = 4
end module params

program test
  use params
  implicit none
  call testsub()
end program test

subroutine testsub()
  use params
  implicit none
  integer, parameter :: id1=1
  integer, parameter :: idim=merge(1,3,id==id1)
  real(8) :: a
  real(8) :: stor(100)
  equivalence(stor(idim+1),a)
  return
end subroutine testsub

 

Jim Dempsey

 

0 Compliments
sant
Novice
4 214 Visites

Thanks for the reply. The above code has the same problem as the original code above - the error is caused by the presence of MERGE function in the PARAMETER statement.

 

Basically, what I am trying to do is go assign different parameter values to a variable depending on the value of another variable that is read in. This is shown in the following pseudocode):

>>

  integer :: id

  read() id

  If  (id.eq.1) then

    integer, parameter :: idim=1

  else

    integer, parameter :: idim=3

  end if

<<

 

Can this be done in Intel FORTRAN?

0 Compliments
Steve_Lionel
Contributeur émérite III
4 210 Visites

You can't do that - you're attempting to define a named constant based on some run-time value. Unfortunately, the error message is somewhat misleading - it isn't MERGE itself that is the problem. Jim's code compiles OK.

0 Compliments
sant
Novice
4 204 Visites

It's good to know that it cant be done.

 

However, I still get the following error upon compiling Jim's code using IVF Composer XE 2013:

error #6263: This intrinsic function is invalid in constant expressions. [MERGE]

 

Is there a compiler switch that has to be turned on or off to prevent the error?

 

Thanks

0 Compliments
JohnNichols
Précieux contributeur III
4 193 Visites

Update to the latest one api Fortran for free from Intel.  2013 is a lot of iterations ago. 

0 Compliments
sant
Novice
4 188 Visites

Sure will.

Thanks Jim, Steve and John.

0 Compliments
Arjen_Markus
Contributeur émérite II
4 172 Visites

Rather than using EQUIVALENCE, why not use a pointer? real(8), pointer, save :: a. Then you can let a point to the right element in the stor array. You cannot do that in a declaration, but it is certainly a possibility.

0 Compliments
jimdempseyatthecove
Contributeur émérite III
4 156 Visites

>> why not use a pointer?

 

Or, use ASSOCIATE

 

subroutine testsub()
  use params
  implicit none
  integer, parameter :: id1=1
  integer, parameter :: idim=merge(1,3,id==id1)
  real(8) :: stor(100)
  ... ! code
  associate (a => stor(idim+1))
    ... ! code
  end associate
  ... ! code
  return
end subroutine testsub

 

Jim Dempsey 

0 Compliments
sant
Novice
4 146 Visites

Jim, Thanks for the suggestion.  I will try pointers or associate.

 

Currently, I have data stored in a large array that are copied to local variables, manipulated, and copied back to the original array for storage until the next solution iteration. I am hoping that replacing the 'two copying's' by the use of pointers/associate statements will speed up the code.

 

Any experience along these lines?

0 Compliments
jimdempseyatthecove
Contributeur émérite III
4 142 Visites

The EQUIVALENCE presents no runtime overhead.

POINTER and ASSOCIATE have very little runtime overhead.

However, should the variable get registerized through optimization, then the cost to register each method would be in effect the same.

 

POINTER will require you to declare the pointee (your array stor) as having the TARGET attribute.

ASSOCIATE will not require this.

 

Also, POINTER, being a variable declaration, will have procedure scope. Whereas ASSOCIATE (generally) has a smaller scope that up to the END ASSOCIATE.

POINTER may require the memory location of the pointer variable to be written even when at times it gets regestered, whereas ASSOCIATE in small scopes may keep the reference pointer solely within a register.

 

Jim Dempsey

 

0 Compliments
sant
Novice
4 135 Visites

Jim, thanks for the details. Tried out an example of my issue and looks like using ASSOCIATE will result in some savings in runtime as compared to copying variables.

0 Compliments
Répondre