6
votes

Transmettre une procédure interne comme argument

Je veux résoudre une équation différentielle beaucoup de fois pour différents paramètres. Il est plus compliqué que cela, mais pour des raisons de clarté, disons que l'ode est y '(x) = (y + a) * x code> avec y (0) = 0 code> et je veux y (1) code>. J'ai choisi l'algorithme Dverk de NetLib pour résoudre l'ode et il s'attend à ce que la fonction sur le côté droit soit d'une certaine forme. Maintenant, ce que j'ai fait avec le compilateur Intel Fortran est ce qui suit (simplifié):

subroutine f(x,a,ans)
implicite none
double precision f,a,ans,y,tol,c(24),w(9)
...
call dverk(1,faux,x,y,1.d0,tol,ind,c,1,w)
...
contains
    subroutine faux(n,xx,yy,yprime)
           implicite none
           integer n
           double precision xx,yy(n),yprime(n)
           yprime(1) = (yy(1)+a)*xx
    end subroutine faux
end subroutine f


1 commentaires

Je pense que le passage d'une procédure contenue dans une autre comme argument est une fonctionnalité Fortran 2008. Ce qui explique probablement pourquoi cela fonctionne dans un compilateur et non un autre.


3 Réponses :


5
votes

Vous pouvez mettre tout cela dans un module et faire a une variable de module global. FAIRE FAUX Procédure de module. De cette façon, il a accès à A . xxx


0 commentaires

3
votes

Le passage d'une procédure interne est autorisé par Fortran 2008. Cela signifie que votre code est correct FORTRAN et qu'un compilateur plus récent est nécessaire.

À l'époque où cette question a été affichée, le support pour cela dans les compilateurs existants était inégalé. Certains l'ont soutenu, certains ne l'ont pas fait. Cela a été considérablement changé et au moment de la rédaction de cette révision de la réponse, on peut normalement l'utiliser sans avoir à penser à la pension du compilateur.

Vous ne vous limiterez pas de partager les données dans un module. Il vous suffit de vous assurer que la procédure contenant est toujours en cours d'exécution. Il n'est pas possible d'enregistrer le pointeur et de faire une soi-disant " fermeture 'connue de Lisp et de nombreuses langues modernes. Dans des langues telles que Fortran ou C, l'environnement enfermé pour les appels futurs n'est pas enregistré et que les pointeurs vers des fonctions internes deviennent invalides.

L'avantage de la procédure interne sur la procédure du module est que vous pouvez partager les données sans le partager dans l'ensemble du module.

Ça fonctionne bien, les versions raisonnablement anciennes de GCC (GFORTRAN), FORTRAN INTEL FORTRAN et CRAY FRAY (testé personnellement) et éventuellement d'autres. Je me souviens de ne pas être capable de compiler par PGI et Oracle Fortran. Comme indiqué par Daniel, il peut être vérifié à http://fortranwiki.org/fortran/ Afficher / Fortran + 2008 + Statut (recherche procédure interne comme argument réel ). La version la plus récente de ce tableau est publiée périodiquement dans le forum FORTRAN ACM SIGPLAN.

Il y a des informations intéressantes dans cet article https://stevelionel.com/drfortran/2009/09/02/doctor-fortran-in-think-Thank-thunk/

Sachez que la mise en œuvre de cette fonctionnalité nécessite normalement une pile exécutable en raison de l'utilisation de trampolines. On ne pense normalement pas à cela, mais si le système d'exploitation interdit une pile exécutable, l'exécutable peut échouer (il y avait des problèmes dans les versions initiales du sous-système Windows pour Linux, par exemple).


2 commentaires

Il vous suffit de vous assurer que la procédure contenant est toujours en cours d'exécution. Comment cela ferait-il cela dans la pratique? Comment la procédure contenant ne peut-elle pas fonctionner?


@knia Cela pourrait arriver si vous stockez l'adresse de la procédure passée quelque part et l'invoquez plus tard.