Reputation: 201
My scenario: I would like to have my Fortran (>=95) program choose one of two subroutines in a calculation, based on a parameter. As an example, let's have two subroutines, foo
, which subtracts; and bar
, which adds its two integer arguments. I furthermore have a subroutine callingsub
which gets either foo
or bar
as an argument. Full program could look like
program choice
implicit none
integer :: a,b
a=3
b=4
call callingsub(a,b,foo)
contains
subroutine foo(a,b,c)
integer, intent(in) :: a,b
integer, intent(out) :: c
c=a-b
end subroutine foo
subroutine bar(a,b,c)
integer, intent(in) :: a,b
integer, intent(out) :: c
c=a+b
end subroutine bar
subroutine callingsub(a,b,sub)
integer, intent(in) :: a,b
interface
subroutine sub(a,b,c)
integer, intent(in) :: a,b
integer, intent(out) :: c
end subroutine sub
end interface
integer :: c
call sub(a,b,c)
write(*,*) 'Your answer is ',c
end subroutine callingsub
end program choice
Now to switch between foo
and bar
I have to recompile, but I would rather have a choice at run time. I imagine having an integer flag
, which, if 0
chooses foo
and if 1
chooses bar. I could of course write a subroutine
subroutine baz(a,b,c,flag)
integer, intent(in) :: a,b
integer, intent(out) :: c
integer, intent(in) :: flag
if (flag==0) then
c=a-b
else if (flag==1) then
c=a+b
else
write(0,*) 'illegal flag ', flag
stop 1
end if
end subroutine baz
which uses the flag
to decide, however, the call to callingsub
will be in a huge loop, and my feeling tells me, that it would be better to have the decision on foo
or bar
before the loop.
Is there any possibility to have a conditional to decide in the main program? I imagine something like
if (flag==0) then
chosensub=foo
elseif (flag==1) then
chosensub=bar
else
!error and exit
end if
and then call callingsub(a,b,chosensub)
, which unfortunately does not work. I cannot put interface
s into a conditional either.
I appreciate any help on this, and hope I made myself clear enough!
PS I have access to Intel ifort 18.0.5 20180823, so I am not limited to F95.
Upvotes: 2
Views: 380
Reputation: 201
OK, for future reference here is what I did, after following @M.S.B s answer here, so thanks @HighPerformanceMark and @IanBush for pointing (haha) in that direction:
program choice
implicit none
integer :: a,b,flag
interface
subroutine chosensub(a,b,c)
integer, intent(in) :: a,b
integer, intent(out) :: c
end subroutine chosensub
end interface
procedure(chosensub), pointer :: subptr=>null()
read(*,*) flag
if (flag==0) then
subptr=>foo
else if (flag==1) then
subptr=>bar
else
write(0,*) 'error message'
stop 1
end if
a=3
b=4
call callingsub(a,b,subptr)
contains
! as in OP
end program choice
Upvotes: 5