VALUE Attribute Vs INTENT(IN)

VALUE Attribute Vs INTENT(IN)

This is just a general question for peoples opinions on the VALUE attribute used in subroutines. I know it The VALUE attributie is sometimes necessary for interoperability with C, but my interest is what would be the benefit beyond that compared to INTENT(IN). I am assuming  that it makes no sense to have both at the same time.

 

Below is a simple example of what I am talking about

SUBROUTINE DOUBLER(X,Y) 
  REAL,      VALUE::X
  REAL,INTENT(OUT)::Y
  Y=2.*X
END SUBROUTINE

or

SUBROUTINE DOUBLER(X,Y) 
  REAL, INTENT(IN)::X
  REAL,INTENT(OUT)::Y
  Y=2.*X
END SUBROUTINE

 

Or another example would be:

FUNCTION DOUBLER(X) RESULT(Y) 
  REAL, VALUE::X
  REAL::Y
  Y=2.*X
END FUNCTION

or

FUNCTION DOUBLER(X)   RESULT(Y) 
  REAL::X                             !FUNCTION IMPLICITLY USES IN
  REAL::Y
  Y=2.*X
END FUNCTION

13 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Use INTENT(IN) if your intent is that dummy argument should not be changed in the procedure e.g., not make it to the left-hand side of an assignment.

Use VALUE if your intent is to use the dummy argument the way "pass by value" arguments are used in languages such as C e.g., the dummy argument may change during the course of the procedure execution, but not referenced back to the caller.

jimdempseyatthecove's picture

I haven't tried this, but you may also be able to use VALUE, INTENT(IN) for variables that you wish to be passed by value .AND. inhibit use on left hand side (or passed to routine that can modify it).

Jim Dempsey

www.quickthreadprogramming.com
Steve Lionel (Intel)'s picture

VALUE has different meanings depending on whether you use BIND(C) or not. (And also /standard-semantics).

With BIND(C), it means pass by value. Without BIND(C), it means pass a writable copy by reference. You can write to either one, but the effect will be discarded on return.

The current ifort. though, misimplements the second case, causing VALUE to mean pass-by-value always. In 14.0 we added /assume:std-value to get the standard-specified behavior, and this is implied by /standard-semantics. In the future we might make this the default (probably not this year.)

Steve

I guess my main question is, outside of making the subroutine work better with C, is there any advantage over using just an internal temp variable. I often have subroutines using the following form.

SUBROUTINE DOUBLER(X,Y) 
  REAL, INTENT(IN)::X
  REAL,INTENT(OUT)::Y
  REAL::XX
  XX=X
  XX=2*X
  Y=XX
END SUBROUTINE

This is a ridiculously simple example, but my main question is, other then shorter code, is there any benifit to changing the code too

SUBROUTINE DOUBLER(X,Y) 
  REAL, VALUE::X
  REAL,INTENT(OUT)::Y
  X=2*X
  Y=X
END SUBROUTINE

 

mecej4's picture

You could make the subroutine even shorter, with the only executable statement being "Y = 2*X".

We need a better example in order to bring out the issues involved.

I know you could collapse that down. I just was using that to illustrate what I was trying to say. Typically I make copies for more complicated code or when a string is being passed in that is converted to upper case.

Steve Lionel (Intel)'s picture

It depends on what sort of argument you'd tend to pass in. I like using local variables when an argument is optional, so I can set a default. I'm not particularly in favor of the idea of assigning to a VALUE argument as I think that is less clear to the reader regarding what is going on.

Steve
jimdempseyatthecove's picture

>> Without BIND(C), it means pass a writable copy by reference

Just how does this relate with fastcall (pass value in register)?
a) stack location reserved but not written, value in register, token for variable marked as modified (0 writes, 0 reads)
b) stack location obtained, value written, call made, value read, ... (1 write, 1 read)

Jim Dempsey

www.quickthreadprogramming.com
Steve Lionel (Intel)'s picture

Quote:

jimdempseyatthecove wrote:

>> Without BIND(C), it means pass a writable copy by reference

Just how does this relate with fastcall (pass value in register)?

It doesn't. Such a routine is not interoperable.

Steve

 

Thanks Steve and Jim for your help as always was confused Jim by "pass a writable copy by reference". does that mean that it makes a copy of the referenced location or still operates on the actual original variables location.

For Steve, how would you initialize an optional variable with VALUE? Below is an example function that I was interested in applying this too. This function takes in a string (Ln) and processes it to a certain output (RES). One of the things I do in the subroutine is make a copy of LN, convert that copy to upper case, and use the copy for processing. The optional logicals (CHECKCASE,CHECKKEY) are also used for additional checks by the function for sections of the code where speed is not as important as debug information. Since the logicals are optional variables would they benefit from VALUE and how would I initialize them if they are not present. Right now I just have a local copy of a variable that set to a default value and when the optional are present overwritten with their values.

 

     FUNCTION LINEINTERPRETER(Ln,NAMES,NAMEVALUES,CHECKCASE,CHECKKEY) RESULT(RES)
      CHARACTER(*),                 INTENT(IN)::Ln
      CHARACTER(*),    DIMENSION(:),INTENT(IN)::NAMES
      DOUBLE PRECISION,DIMENSION(:),INTENT(IN)::NAMEVALUES
      LOGICAL,         OPTIONAL,    INTENT(IN)::CHECKCASE
      LOGICAL,         OPTIONAL,    INTENT(IN)::CHECKKEY
      DOUBLE PRECISION                        ::RES

 

Thanks again for all your help.

jimdempseyatthecove's picture

RE: Steve's: Without BIND(C), it means pass a writable copy by reference

Meaning when an optional argument with VALUE and without BIND(C)

is present, a copy is made and the reference to the copy is passed
is not present, a NULL reference is passed, thus permitting testing for presence

I think this was the principal reason for doing it this way.

Jim Dempsey

www.quickthreadprogramming.com
Steve Lionel (Intel)'s picture

I would not use VALUE for this purpose. Here's how I handled such things in the WinPrint sample:

logical(4), intent(in), optional :: Default_Printer
...
logical(4), parameter :: DDefault_Printer = .TRUE.  ! Use default printer?
logical(4) :: WDefault_Printer
...
! Establish defaults for optional arguments
!
WDefault_Printer = DDefault_Printer
...
if (present(Default_Printer)) then
  WDefault_Printer = Default_Printer
  end if

I then used WDefaultPrinter in the rest of the code.

While the standard allows VALUE for non-BIND(C) routines, I don't find that of much "value" since, as I mentioned above, it obscures behavior.

Steve

Login to leave a comment.