michstam

AOCC: issue with contained functions?

Discussion created by michstam on May 5, 2020
Latest reply on Aug 4, 2020 by praveen

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

Outcomes