I am trying to use the Fortran Compiler within the AMD Optimizing C/C++ Compiler suite (AOCC) and I have run into an issue that is exemplified by the program shown below. Just a few words on motivation first: when trying to solve an equation like f(x,p) = 0, we usually have to invoke a solver that only knows how to search for roots of a function g(x). The solver doesn't know or care about the parameters p of our equation, and to make things worse, p may be a complicated data-structure that has to be populated or handled by programming units beyond those encoding the solver. A trick to pass on the parameter object p "under the table" is to define a contained function (or subroutine) that accesses p via its membership to the programing unit that handles p. However, this does not work in AOCC, for which the program below crashes after compiling fine (while it compiles and runs without issues on other compilers). I was wondering: is the trick I am trying non-standard Fortran, or is there an issue with the AOCC compiler? Is there maybe a better way of doing what I would like to do? Thanks!
module function_interface
interface
subroutine eval_integer_function(iarg,ireslt)
integer, intent(in) :: iarg
integer, intent(out) :: ireslt
end subroutine eval_integer_function
end interface
end module function_interface
module solver
use function_interface
contains
subroutine brute_force_solution_search(evalfunc,imin,imax,isolution,iflag)
implicit none
procedure (eval_integer_function), pointer, intent(in) :: evalfunc
integer, intent(in) :: imin, imax
integer, intent(out) :: isolution, iflag
integer :: i, reslt
iflag = 1 ! flag values: 0 = no error, 1 = no solution found
do i = imin,imax
call evalfunc(i,reslt)
if (reslt == 0) then
isolution = i
iflag = 0
return
end if
end do
return
end subroutine brute_force_solution_search
end module solver
program main_test
use solver
use function_interface
implicit none
integer :: isolution, iflag, kparam
procedure (eval_integer_function), pointer :: evallhs
! Trying to solve f(i,kparam) == 0 but the solver only understands: g(i) == 0
! To bypass the limitation we define a locally contained function, which "knows"
! the value of kparam by its membership to "main_test"
kparam = 5
evallhs => eval_left_hand_side
call brute_force_solution_search(evallhs,0,10,isolution,iflag)
if (iflag == 0) then
write(*,*) 'solution found:',isolution
else
write(*,*) 'no solution found'
end if
contains
subroutine eval_left_hand_side(i,lhs)
implicit none
integer, intent(in) :: i
integer, intent(out) :: lhs
lhs = (i+1)*(i-kparam) ! this compiles but leads to seg-fault in AOCC;
! yet, it compiles and runs fine in GNU and Intel Fortran
! lhs = (i+1)*(i-5) ! this is fine with all 3 compilers but has kparam "hardcoded"
return
end subroutine eval_left_hand_side
end program main_test