Czy istnieje sposób na niejawne zdefiniowanie funkcji midprogram w Fortran '[duplikat]
Próbuję rozwiązać kilka problemów z wartością własną. Używam gfortran. Napisałem moduł zawierający bisection_methodpodprogram. W moim programie zdefiniowałem secular(m,x)funkcję, która przyjmuje tablicę 2D mi zmiennoprzecinkową xi generuje charakterystyczny wielomian mat x; tj. det (m - x Id). Jednym z argumentów bisection_methodpodprogramu jest funkcja f, która miała być funkcją jednego rzeczywistego wejścia i rzeczywistego wyjścia. Chciałbym jednak wprowadzić funkcję „częściowo zastosowaną” secular(m,_)do tego podprogramu. Czy można to zrobić bez jawnego definiowania tej funkcji w module?
Nie mogę jednoznacznie zdefiniować tej funkcji, ponieważ mam wykonać tę procedurę dla kilku macierzy m. Nie mogę też modyfikować treści bisection_methodargumentu, ponieważ używam go również do funkcji jednego prawdziwego argumentu. Czy jest sposób na obejście tego w Fortranie?
Odpowiedzi
Jak zauważył @francescalus, chcesz mieć zamknięcie swojego problemu.
Zamknięcia są częściowo obsługiwane w Fortranie przy użyciu procedur wewnętrznych, ponieważ procedura wewnętrzna ma dostęp do wszystkich zmiennych w otaczającym zakresie¹.
Zakładając, że chcesz znaleźć wartości własne w Mswoim kodzie, może on mieć taką strukturę.²
module bisection_and_linalg
use iso_fortran_env, only: real64
integer, parameter :: wp = real64
implicit none(type, external)
abstract interface
real(wp) pure function real_function(x)
real(wp), intent(in) :: x
end function
end interface
contains
!> Find the root of f in the interval I
real(wp) pure function bisect(f, I)
procedure(real_function) :: f
real(wp) :: I(2)
...
end function
!> Evaluate the characteristic polynomial of m at x
real(wp) pure function secular(M, x)
real(wp), intent(in) :: M(:, :), x
...
end function
!> Get eigenvalues
real(wp) pure function eigenvalues(M)
real(wp), intent(in) :: M(:, :)
...
! n.b. here you can use the bisection method to
! find your eigenvalues.
bisect(f, ...)
contains
real(wp) pure function f(x)
! n.b. here you have your closure.
! M is captured from surrounding scope.
f = secular(M, x)
end function
end function
end module
¹ Jedynym zastrzeżeniem jest to, że wewnętrzne procedury istnieją tylko tak długo, jak długo istnieje otaczający zakres. Dlatego niestety nie jest możliwe napisanie funkcji ogólnej, która pobiera funkcję i zwraca wskaźnik funkcji do jej częściowo zastosowanej wersji przy użyciu procedur wewnętrznych. Ale to nie dotyczy twojego problemu.
² Być może lepiej byłoby zwrócić rzeczywisty charakterystyczny wielomian. Wtedy mógłbyś go wyprowadzić, używając np. Newtona-Raphsona zamiast bisekcji.