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

How to *create* an optional argument inside a subroutine

OP1
New Contributor III
731 Views

Hi!

The title of this threadmay seem a bit obscure. I want to do the following:

SUBROUTINE S2(D)
REAL,INTENT(IN),OPTIONAL :: D
... do some stuff here...
END SUBROUTINE S2

And:

SUBROUTINE S1(A,B)
REAL,INTENT(IN) :: A
REAL,INTENT(IN),OPTIONAL :: B
REAL C
IF (PRESENT(B)) THEN
C=B+1
ENDIF
IF (PRESENT(B)) THEN
CALL S2(C)
ELSE
CALL S2
ENDIF
END SUBROUTINE S1

If there are many calls to S2, I need to repeat many times the IF construct that checks for the presence of B. Is there a way to make the declaration of C *disappear* if the argument B is not provided? In which case I would only need to call S2(C), whether C exists or not.
In other words: passing C to S2 is contingent upon the presence of the optional argument B, and I don't want to have to write the IF construct (if there is another way to do this, of course) every time I call S2.

Thanks for your help regarding this unusual question,

Olivier

0 Kudos
5 Replies
jimdempseyatthecove
Honored Contributor III
731 Views

Olivier,

When S2 is making the many calls to S1, then simply pass the optional arg

IF (PRESENT(B)) THEN
C=B+1
ENDIF
CALL S2(C)

This requires S2 to have C be pass by reference. Fortran permits passing a missing optional arg in a call.

You may also want to look in the documentation under Generic Interface to see how the same named "subroutine" can call one of several other named subroutines.

Jim Dempsey
0 Kudos
OP1
New Contributor III
731 Views

Olivier,

When S2 is making the many calls to S1, then simply pass the optional arg

IF (PRESENT(B)) THEN
C=B+1
ENDIF
CALL S2(C)

This requires S2 to have C be pass by reference. Fortran permits passing a missing optional arg in a call.

You may also want to look in the documentation under Generic Interface to see how the same named "subroutine" can call one of several other named subroutines.

Jim Dempsey

I am afraid I didn't explain very well what I wanted. In the example above, S2 will stillhave the argument C passed to it when B is not present. In which case the value in C has no meaning and S2 should certainly not use it.
In other words:
If B is present, call S2 with the updated value of C.
If B is absent, call S2 without C.
I can't see a way to do this without a IF construct... maybe somebody has a better idea.

Olivier
0 Kudos
Steven_L_Intel1
Employee
731 Views
I don't know of a way to do that. The only thing I can offer is that if you call S2 with B, the "omitted-ness" of B gets passed along to S2. Make sure that explicit interfaces are visible to the callers of any routine with an OPTIONAL argument.
0 Kudos
OP1
New Contributor III
731 Views
I don't know of a way to do that. The only thing I can offer is that if you call S2 with B, the "omitted-ness" of B gets passed along to S2. Make sure that explicit interfaces are visible to the callers of any routine with an OPTIONAL argument.

Thanks Steve. That's what I suspected - but couldn't be sure of. I'll stick to the IF constructs, no matter how inelegant (and tedious) this is. This is still doable with one or two optional arguments - but become quickly an untractable combinatorial issue for more.
It would be nice if there was a way in Fortran to make a variable definition *disappear* from within a subroutine, so that it becomes invisible to subroutines that accept optional arguments (if necessary):

SUBROUTINE S1(A,B)
INTEGER,INTENT(IN) :: A
INTEGER,INTENT(IN),OPTIONAL :: B
INTEGER,OPTIONALIZABLE :: C
INTERFACE
SUBROUTINE S2(X)
INTEGER,INTENT(INOUT),OPTIONAL :: X
...do some work here...
END SUBROUTINE S2
END INTERFACE
...do some work here...
IF (PRESENT(B)) THEN
C = C+1
ELSE
HIDE(C)
ENDIF
CALL S2(C)
SHOW(C)
WRITE(*,*) C
END SUBROUTINE S1

Maybe this will happen in Fortran 2013 :) ...

Olivier
0 Kudos
Steven_L_Intel1
Employee
731 Views
No chance of that - Fortran 2013 may not have any new features at all if some members of the committee get their way (and I would agree.) However, consider this:

[plain]subroutine s1 (b,c)
real, optional :: b,c
if (present(b) .and. present(c)) then
  c = c + 1
  end if
call s2(c)
end subroutine s1[/plain]
You'd just have to know that if you call s1 with b you also have to pass c, and if b is not passed, don't pass c. (You could add protective code in s1 to check for that.)
0 Kudos
Reply