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

Parameter statement with conditional declaration

sant
Novice
1,990 Views

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 Kudos
1 Solution
sant
Novice
1,927 Views
0 Kudos
12 Replies
JohnNichols
Valued Contributor III
1,983 Views
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 Kudos
jimdempseyatthecove
Honored Contributor III
1,961 Views

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 Kudos
sant
Novice
1,954 Views

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 Kudos
Steve_Lionel
Honored Contributor III
1,950 Views

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 Kudos
sant
Novice
1,944 Views

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 Kudos
JohnNichols
Valued Contributor III
1,933 Views

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

0 Kudos
sant
Novice
1,928 Views

Sure will.

Thanks Jim, Steve and John.

0 Kudos
Arjen_Markus
Honored Contributor I
1,912 Views

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 Kudos
jimdempseyatthecove
Honored Contributor III
1,896 Views

>> 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 Kudos
sant
Novice
1,886 Views

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 Kudos
jimdempseyatthecove
Honored Contributor III
1,882 Views

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 Kudos
sant
Novice
1,875 Views

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 Kudos
Reply