\chapter{Fortran} \label{chap:Fortran} \index{Fortran} \begin{quote} Fortran (\textsc{FORmula TRANslator}) est, avec le Cobol\index{Cobol}, un des premiers langages évolués. Il a été conçu après la seconde guerre mondiale, en 1954, par John Warner Backus, ingénieur en radiophonie chez IBM\index{IBM}, \end{quote} Pourquoi j'ai redécouvert un langage de ma jeunesse, et pourquoi vous devriez vous aussi y jeter un regard attentif. Il y a plein de bonnes choses, la septième va vous tenir compagnie. % ======================================== % % un petit historique ? % \section{On the big irons} TODO\index{XXX} \section{FORTRAN77} Dernière version à exiger le format '80 colonnes' des cartes perforées, cette version est aussi (aux yeux de vieux dinos) la plus pure, à cause d'instructions comme le \textsl{computed goto} ou le mythique \textsl{comefrom}\footnote{Keyword: Datamatic}. Nom officiel : \texttt{ANSI X3.9-1978}. L'incarnation \texttt{g77}\index{g77} n'existe plus, meis peut être à-priori émulable en jouant avec les options de \texttt{gfortran} et un brin de shell. % ============****************=============== % https://linuxfr.org/users/vmagnin/journaux/taptempo-fortran % https://en.wikipedia.org/wiki/Fortran_95_language_features \section{Gfortan} \index{gfortran} Puis ce langage du passé a subi une évolution lente vers quelque chose de bien plus moderne : le Fortran 90. Les dinos vont devoir s'adapter. Et songer à utiliser un \texttt{gfortran} moderne, un élément de la Gnu Compiler Collection\index{gcc}. Comme pour tous les langages de programmation, il est obligatoire d'avoir l'exemple canonique, donc le voilà. Il faut l'enregister dans un fichier nommé \texttt{hello.f90} pour que le compilateur puisse admettre que c'est écrit en \textsl{free form format}. \begin{lstlisting} $ cat hello.f90 program hello implicit none print *, "hello world" end $ gfortran -Wall hello.f90 -o hello && ./hello hello world $ \end{lstlisting} % -------------------------------------------------------- % % https://fortranwiki.org/fortran/show/Command-line+arguments % \section{Args \& Env} Un fort beau programme que ce \textsc{helloworld}, mais il est un peu fermé au monde extérieur. Quand on lance un programme, il peut recevoir des instructions par (mais pas que) deux canaux : les arguments de la ligne de commande et les variables d'environnement. \begin{lstlisting} program rum_me implicit none integer :: nbarg, foo character(len=32) :: arg nbarg = IARGC() if (nbarg .GT. 0) then do foo=1, nbarg call GETARG(foo, arg) print *, foo," ", arg enddo endif end \end{lstlisting} Si un des arguments doir être vu comme une valeur numérique, il faut convertir la chaine de caractères avant usage. Exemple pour un nombre flottant~: \begin{lstlisting} character(len=89) :: arg real :: cx call getarg(2, string) read (string, *) cx \end{lstlisting} % -------------------------------------------------------- \section{Tableaux} Rank, Size, \textsc{allocatable}, toussa\dots Amies du C, soyez d'entrée prévenues, en Fortran, l'indice par défaut du premier élément d'un tableau est \textbf{1}, mais cette valeur peut être modifiée à la déclaration du tableau. Ce qui permet des \textsl{of-by-anynumber} du plus bel effet. % -------------------------------------------------------- % new 29 decembre 2022 \section{Nombres complexes} Partie imaginaire : \texttt{ipart = aimag(cmplx)}. % -------------------------------------------------------- % nouveau 4 mars 2023 \section {Les structures}\index{type} Une « structure », c'est comme une petite boite dans laquelle on peut mettre des variables de différentes natures. Les accès à chacune de ces variables sont idépendants les uns des autres. \begin{lstlisting} type t_pixrgb integer :: r, g, b integer :: alpha = 0 end type t_pixrgb :: pixel pixel%r = 0x55 \end{lstlisting} Nous verrons plus loin l'importance de cette notion. % ======================================== \section{Fichiers} Pour qui vient du C et de la philosophie Unix, la gestion des fichiers en Fortran est assez déroutante% \footnote{Par contre, pour un dino des \textsl{big irons}\dots}. Il semble qu'il y ait deux concepts orthogonaux : \begin{itemize} \item Direct access \textit{vs.} Sequential access \item Formtated \textit{vs.} Unformated \end{itemize} \textit{Open, Read, Write, Inquire, toussa\dots} % -------------------------------------------------------- \subsection{Ouvrir un fichier} C'est la première étape : attacher un fichier à un numéro d'unité. Il y a une foultitude d'options, nous allons commencer par les plus courantes. % -------------------------------------------------------- \subsection{Sequentiel texte} XXX\index{XXX} Pour faire simple, on accède à chaque unité de donnée l'une après l'autre, comme quand on déroule une bande 6250bpi. Ces unités peuvent être (restons simple pour commencer) des lignes entières de texte. Dans l'ancien temps\footnote{F66 rulz the world} des cartes à trous, le format de ces lignes devait être précisement structurées, avec des largeurs de champs dans la ligne fixés. % -------------------------------------------------------- \subsection{Indexé} \index{index} XXX\index{XXX} C'est pas pareil : d'abord les enregistrements sont tous de la même taille. Ensuite, on y accède par son rang, son numéro d'ordre dans le fichier. Dès que j'ai fini de planter les deux arbres en attente, je vous propose un exemple simple et aussi artificiel que les autres exemples de ce ouvrage. % -------------------------------------------------------- \section{Read et Write} Ces deux opérations (la lecture et l'écriture) sont contrôlables par plusieurs choses~: les paramètres à l'ouverture, du fichier, à XXX\index{XXX}, et surtout les chaines de format. Bienvenue dans le monde du légendaire champ "Hollerith". \subsection{Les chaines de format} % % attention, il y a un hack pour l'affichage du mot "format" ! % Attention, dans "{\small{\textsc{format}}}", les accolades % exterieures sont indispensables. Affaire à suivre... % La chaine de {\small{\textsc{format}}} contrôle la façon dont les données (nombres, textes ou booleans) seront présentées à l'affiche ou à l'impression. Une bonne connaissance, et une longue pratique des chaines de {\small{\textsc{format}}} est indispendable pour arriver à l'harmonie ultime bien que rigoureuse, de vos interminables listings de chiffres abscons. Nous verrons ensuite comment les utiliser pour faire de la saisie presque (mais pas complètement) utilisable en milieu \textsl{enduser}\index{enduser}. Il y a deux manières de les utiliser~: en ligne de l'instruction d'écriture/lecture, ou séparément en tant que chaine de caractères. Pour la clarté de lecture, c'est la seconde que je vais utiliser. % % % % INSERT BIG "TODO" HERE. % % \lstinputlisting{code/fortran/printty.f90} % -------------------------------------------------------- \section{Modules} Une notion essentielle, à mon avis, pour écrire des programmes au-delà de 104 lignes. Oui, j'avoue, j'ai bien changé depuis l'époque où je confectionnait des procédures \textsl{monobloc} de 1337 lignes, avec une bonne centaine de \texttt{GOTO} dedans. Il serait bon de voir un exemple du monde réel. Ou juste un exemple basique. Mais avec des explications. Parce que ce n'est pas vraiment évident. Mais c'est un concept balaize. Nous allons donc créer un module qui ne fait quasiment rien, ce qui limitera le nombre de pannes possibles dans la suite des opérations. \begin{lstlisting} module dummy implicit none contains subroutine print_dummy print *, 'this is the dummy subroutine' end subroutine end module \end{lstlisting} Rien de bien compliqué~: Un module peut être vu comme une boite qui contient (\texttt{contains}) des procédures (\texttt{function} ou \texttt{subroutine}), et qui sera utilisé avec ce genre de petit programme~: \begin{lstlisting} program t use dummy implicit none print *, '=== programme de test ===' call print_dummy end program \end{lstlisting} La première ligne, \texttt{use dummy}, permet d'accéder aux fonctions disponibles dans le module dummy. Elle doit être suivie d'un \texttt{implicit none}, pour une raison à éclaircir. Et ensuite nous pouvons appeler notre procédure. Mais les modules permettent de faire bien d'autre choses. % -------------------------------------------------------- \section{Random et Aléa} Tentative de sranding faite à la rache. La dernière ligne va vous étonner. \begin{lstlisting} integer, dimension(3) :: tarray integer :: t3 real :: dummy call itime(tarray) t3 = 3600*tarray(1) + 60*tarray(2) + tarray(3) write(0, '(A,3I3,A,I6)') "sranding: ", tarray, " --> ", t3 call srand(t3) ! after initializing the random generator engine, ! you MUST use it for initializing the initializer dummy = rand() \end{lstlisting} Mais il y a d'autres manières plus rigoureuses d'utiliser les nombres pseudo-aléàtoires avec le fortan moderne. % -------------------------------------------------------- % new Thu 24 Nov 2022 02:27:05 AM CET \section{Options de gfortran} \index{gfortran} Comme d'habitude avec gcc\footnote{Giant Complicated Compilords}, les options sont innombrables. J'ai essayé d'en dégager les plus importantes, mais ce ne sont probablement pas les seules. Pour commencer, la plus obligatoire de toutes ces options est sans contexte le protecteur de base \texttt{-Wall} qui vous protégera de nombreux maléfices. % -------------------------------------------------------- \section{Images} La bibliothèque \textbf{Plplot} semble être un bon choix pour commencer, mais il existe bien d'autres options. Par exemple \textbf{g2} (vue en page \pageref{g2}) semble être utilisable avec les vieux F77, et possiblement avec un Fortran moderne, il faut juste un peu de \textsc{rtfm}. Nous allons donc commencer par PlPlot, pour envisager ensuite les alternatives. % -------------------------------------------------------- % % $ dillo /usr/share/doc/plplot-doc/html/index.html & % \subsection{Plplot} \index{plplot} \label{ploplt} Commençons directement par un EMC\footnote{Exemple Minimal Compilable} qui ne va pas faire grand chose, à part initialiser la machinerie interne de Plplot qui est assez avancée. Il y a beaucoup de paramètres réglables, mais aussi des fonctions qui gèrent pour vous les valeurs « par défaut ». Voyez cette exemple comme un \textsl{boilerplate} simple ou un \textsc{HelloWorld}~: \lstinputlisting{code/fortran/plplotting.f90} Il ne se passe pas grand chose, sauf qu'on a une proposition de choisir le type de sortie. Dans la version que j'ai (XXX\index{XXX}), on a le choix entre X-Window, PostScript mono ou couleur, Xfig, PNG, SVG, et bien d'autres dont certains, pour moi, assez ésotériques. D'autre part, avec cette méthode, il semble impossible de préciser la taille de l'image. Mais la démonstration est faite. Il faut quand même regarder de plus près la subroutine \texttt{plenv()} (\textsl{Set up standard window and draw box}) qui initialise simplement un contexte graphique 2D somme toute assez classique. Elle prend six paramètres. Les quatre premiers sont les coordonnées flottantes de deux coins du papier, le cinquième controle l'échelle des axes, et le dernier controle le tracé des boites autour du graphique. Nous avons les bases, commençons donc à dessiner. Premièrement, nous allons chosir de démarrer automatiquement dans une fenètre X11, en gardant le reste de la configuration avec ses valeurs par défaut. Pour cela, il suffit de rajouter \texttt{call plsdev('xwin')} juste avant l'appel à \texttt{plinit}, Ensuite, pour mettre en évidence notre art, nous allons choisir une couleur pour l'encre (qui est d'un rouge du meilleur effet par défaut en mode "xwin"), puis écrire quelques légendes canoniques, donc inutiles, . \begin{verbatim} call plcol0 (15) ! pure white call pllab ("Fuzzfactor", "Yoyodines", "Some nice plots") \end{verbatim} Il est maintenant temps de poser un premier trait de crayon numérique sur notre feuille blanche numérique\footnote{Actuellement noire, mais nous trouverons bien comment changer ça}. La forme de ce tracé sera donnée par une suite de coordonnées flottantes \textsl{x/y} stockées dans deux tableaux parallèles que nous allons immédiatement garnir de données pertinentes~: \begin{verbatim} integer, parameter :: lg = 500 real :: x(lg), y(lg) real :: k integer :: i k = 0.1 do i = 1, lg x(i) = k * sin(real(i)/3.0) y(i) = k * cos(real(i)/5.0) k = k * 1.006021 enddo \end{verbatim} Une fois en possession de ces données conceptuelles, que l'on peut aisément voir comme un cheminement, nous allons demander au crayon de se promener sur notre feuille virtuelle en suivant ce chemin, et enfin de s'arreter de dessiner~: \begin{verbatim} call plcol0 (12) call plline (x, y) call plend () \end{verbatim} Au passage, vous pouvez remarquer la magie du Fortran moderne~: il n'est plus nécessaire de signifier la dimension des tableaux lors de l'appel de la procédure. Dans ce mode de fonctionnement interactif, il vous faudra utiliser la touche \textsl{} pour sortir\footnote{Une de mes prochaines tâche sera de regarder comment quitter avec le '\textbf{q}' canonique}. Nous verrons pas la suite comment écrire des fichiers 'image' vectoriels ou bitmap en mode \textsl{batch}. Enfin une ouverture vers les Gifs animées\index{gif89a}. % -------------------------------------------------------- \section{Questions en attente} \index{XXX} \begin{itemize} \item Comment déclarer une variable statique dans une procédure ? \item Pourquoi ne pas parler de DISLIN ? \item Est-il possible de causer à \texttt{libsndfile} ? \item Comment caler une chaine à gauche avec un \textsc{format} ? \item Is there a \texttt{-fortran} option for making comments with \texttt{boxes} + \texttt{figlet}\index{figlet} ? \end{itemize} % -------------------------------------------------------- \section{Réponses} \textsl{} Voilà, c'est tout pour le moment\dots % ========================================