osprey
osprey

Reputation: 768

Can a Fortran function return multiple variables?

In the example function below how can one tell whether a, b or c are input or output values, other than from the context?

Also, if example() is called is a value assigned to c outside the scope of example()?

function example(a, b, c)
   real*8 a, b, c
   c = a + b
   example = c
end function example

Upvotes: 3

Views: 1014

Answers (2)

francescalus
francescalus

Reputation: 32366

You have an answer which talks about intents for arguments. These provide valuable hints to the programmer (as a form of documentation) and compiler as to how the arguments are used. These intents give an idea of the restrictions on an argument and apply to procedures (subroutines as well as functions) more widely.

However, some dummy arguments may even not be allowed to be given an intent. Further, an intent specification doesn't mean that the argument is used in that way (intent(in) arguments needn't be referenced; intent(inout) variables needn't be modified; intent(out) arguments needn't be defined).

Ultimately you will have to look at the function's behaviour.

Given the function of the question

function example(a, b, c)
   real*8 a, b, c
   c = a + b
   example = c
end function example

we can consider a and b to be "inputs" and they must be defined when the function is entered and their values are used in evaluating the function result. The function result is called example but there is a side-effect of modifying c, an "output". Its value on entering the function isn't needed, and it needn't even be defined.

Now, this being Fortran, there is a subtlety to note. You ask

is a value assigned to c outside the scope of example?

and the answer is, possibly.

If example were a subroutine then yes, the actual argument matching c would have a value defined after the subroutine call. With example a function, then maybe not.

Consider:

implicit none
real*8 a, b, c, d
real*8 example  ! Really you should be using an explicit interface

a = 1.
b = 2.
c = 0.
d = 0.

print*, example(a,b,c)
print*, c

if (.false..and.example(a,b,d)>0) print*

end program

then although the value of c is modified by this function reference, the variable d actually becomes undefined!1


1 By "undefined" I mean that it doesn't have a value that you can reliably query or use. Because Fortran allows a compiler to short-circuit the evaluation of the function but doesn't it require it, it says that the value becomes undefined. You can't rely on side effects from a function if you can't be sure that the function is used.

Upvotes: 3

albert
albert

Reputation: 9057

Fortran has the possibility to specify intent attribute:

The INTENT attribute specifies the intended use of a dummy argument. An INTENT (IN) dummy argument is suitable for receiving data from the invoking scoping unit, an INTENT (OUT) dummy argument is suitable for returning data to the invoking scoping unit, and an INTENT (INOUT) dummy argument is suitable for use both to receive data from and to return data to the invoking scoping unit.

Furthermore one can specify a result attribute or give the function a type, So one could write:

double precision function example(a, b, c)
   implicit none
   double precision, intent(in) :: a, b
   double precision, intent(out) :: c
   c = a + b
   example = c
end function example

or

function example(a, b, c) result(res)
   implicit none
   double precision, intent(in) :: a, b
   double precision, intent(out) :: c
   double precision :: res
   c = a + b
   res = c
end function example

Note: I also added the "implicit none" and replaced the real*8 by double precision.

Upvotes: 3

Related Questions