subrutinas subprogramas resueltos programas programación problemas matematicas intrinsecas funciones ejemplos function fortran subroutine intel-fortran

function - subprogramas - return en fortran



Fortran-Devuelve una función anónima de la subrutina (1)

Estoy intentando generalizar una llamada de función desde una subrutina. Entonces mi idea es algo como esto

if (case1) then call MainSubroutine1(myFun) elseif (case2) call MainSubroutine2(myFun) end if do i = 1,4 data = myFun(i) end do

Me doy cuenta de que esto es un poco vago, pero no estoy seguro si esto es posible.

Gracias,

John

editar 1/31/14 7:57 AM

Lo siento por la forma vaga en que expresé esto. Estaba pensando algo similar a lo que @haraldki hizo, pero esperaba poder definir una función anónima dentro de MainSubroutine1 y MainSubroutine2 y transferir esa definición al código principal.

Esto se debe a que myFun depende de diferentes distribuciones estiradas (Gaussian y Fermi-Dirac) y no quiero tener una función que solo llame a una función con una constante lanzada.

es posible?

Gracias de nuevo.

John


La respuesta a su pregunta simplemente es: no, no puede devolver una función anónima. Esto se debe a que, como dice @VladimirF en los comentarios, no hay funciones anónimas en Fortran. Como dicen los comentarios, sin embargo, los indicadores de procedimiento son bastante pasables.

Continua la especulación masiva que es útil como una forma de evitar el requisito de la función anónima.

Deduzco que le gustaría hacer algo como

subroutine MainSubroutine1(fptr) procedure(func), pointer, intent(out) :: fptr ! Calculate parameterization for your "anonymous" function fptr => anon_parameterized contains real function anon_parameterized(i) integer, intent(in) :: i ! Use the parameterization anon_parameterized = ... end function end subroutine

y no quieres hacer

subroutine MainSubroutine1(fptr) procedure(func), pointer, intent(out) :: fptr fptr => Gaussian end subroutine real function Gaussian(i) integer, intent(in) :: i ! Calculate parameterization Gaussian = Gaussian_parameterized(i, ...) contains function Gaussian_parameterized(i, ...) integer, intent(in) :: i !... other intent(in) parameters end function end subroutine

Tenga en cuenta que estos no son internos, ya que pasar punteros a cosas internas en otros lugares aún no está bien implementado (como una función de F2008), y es complicado. Pasar un puntero a un procedimiento interno para obtener la asociación de host me asusta.

Si mi inferencia es correcta, existe la posibilidad de usar variables de módulo para almacenar la parametrización, permitiendo de nuevo que la llamada final "parametrizada" no sea interna a MainSubroutine1 .

Sin embargo, es posible que desee evitar las variables del módulo, en cuyo caso puede considerar pasar la parametrización junto con la llamada a la función:

procedure(func), pointer :: myFun => null() if (case1) then call MainSubroutine1(myFun) else if (case2) call MainSubroutine2(myFun) end if if (.not.associated(myFun)) STOP ":(" data = myFun(1, par1, par2)

Ah, pero no sabes con certeza qué parámetros requiere la función no parametrizada myFun , por lo que tu interfaz está rota. ¿No es así?

Que luego conduce al polimorfismo.

module dists type, abstract :: par_type end type par_type type, extends(par_type) :: par_gaussian real :: mu=5.2, sigma=1.2 end type par_gaussian type, extends(par_type) :: par_fermi_dirac real :: eps=11.1, mu=4.5 end type par_fermi_dirac abstract interface real function func(i, pars) import par_type integer, intent(in) :: i class(par_type), intent(in) :: pars end function func end interface contains real function gaussian(i, pars) integer, intent(in) :: i class(par_type), intent(in) :: pars select type (pars) class is (par_gaussian) print*, "Gaussian", pars%mu, pars%sigma gaussian = pars%mu+pars%sigma end select end function gaussian real function fermi_dirac(i, pars) integer, intent(in) :: i class(par_type), intent(in) :: pars select type (pars) class is (par_fermi_dirac) print*, "Fermi-Dirac", pars%eps, pars%mu fermi_dirac = pars%eps+pars%mu end select end function fermi_dirac subroutine sub1(fptr, pars) procedure(func), pointer, intent(out) :: fptr class(par_type), intent(out), allocatable :: pars fptr => gaussian allocate(par_gaussian :: pars) end subroutine sub1 subroutine sub2(fptr, pars) procedure(func), pointer, intent(out) :: fptr class(par_type), intent(out), allocatable :: pars fptr => fermi_dirac allocate(par_fermi_dirac :: pars) end subroutine sub2 end module dists program prog use dists implicit none class(par_type), allocatable :: pars procedure(func), pointer :: myfun call sub1(myfun, pars) print*, myfun(i, pars) call sub2(myfun, pars) print*, myfun(i, pars) end program prog

Sin embargo, eso es toda especulación.