В современном Фортране есть общий шаблон для проблемы, с которой вы сталкиваетесь ( приложение с частичной функцией ). В отличие от других языков, Fortran не имеет замыканий функций, поэтому создание лексической области видимости для функции немного «запутано» и ограничено.
Вы действительно должны рассмотреть вопрос о повторном посещении всех ссылок @VladmirF на комментарий, большинство из которых применимы непосредственно к вашему делу. Я приведу вам пример решения.
Это решение без использования типа оболочки. Я буду использовать функцию, включенную в стандарт Fortran 2008: передачу внутренней процедуры в качестве аргумента. Он совместим с последними версиями gfortran, Intel и многими другими.
Если вы не можете получить доступ к компилятору с этой функцией или предпочитаете решение с производным типом, вы можете обратиться к этому ответу.
module without_custom_type
use, intrinsic :: iso_fortran_env, only: r8 => real64
use :: solver
contains
subroutine solve_quad(a, b, c, x0, x, iters, debug)
integer, intent(in) :: a, b, c
real(r8), intent(in) :: x0
real(r8), intent(out) :: x
integer, intent(out) :: iters
logical, intent(in) :: debug
call solve(f, fp, x0, x, iters, debug)
contains
real(r8) function f(x)
real(r8),intent(in) :: x
f = a * x * x + b * x + c
end
real(r8) function fp(x)
real(r8),intent(in) :: x
fp = 2 * a * x + b
end
end
end
Обоснование этого кода: поскольку f
и fp
лежат внутри процедуры solve_quad
, они имеют доступ к аргументам a
, b
и c
по ассоциации хоста, не касаясь подписи этих функций. Результирующий эффект похож на изменение арности функции.
Тестируя его с помощью gfortran 8.0 и реализации solver
по ссылке, которой вы поделились, я получил следующее:
program test
use, intrinsic :: iso_fortran_env, only: r8 => real64
use :: without_custom_type
implicit none
real(r8) :: x, x0
integer :: iters
integer :: a = 1, b = -5, c = 4
x0 = 0
call solve_quad(a, b, c, x0, x, iters, .false.)
print *, x, iters
! output: 1.0000000000000000, 5
x0 = 7
call solve_quad(a, b, c, x0, x, iters, .false.)
print *, x, iters
! output: 4.0000000000000000, 6
end