Aggiunto qualche esempio sulle subroutine

Leonardo Robol [2009-11-06 15:55]
Aggiunto qualche esempio sulle subroutine
Filename
AppFortran.tex
diff --git a/AppFortran.tex b/AppFortran.tex
index d10872b..6a94abe 100644
--- a/AppFortran.tex
+++ b/AppFortran.tex
@@ -156,4 +156,88 @@ a quel determinato file sostituendo quell'intero a \lstinline-*-. Questo codice
 Abbiamo qui introdotto anche la chiamata \lstinline-CLOSE()- che serve appunto per
 chiudere un file. \`E normalmente buona norma chiudere tutti i file che si aprono e quindi,
 in programma corposi, conviene sempre scrivere la chiamata ad \lstinline-OPEN()- insieme
-alla chiamata \lstinline-CLOSE()- per evitare di dimenticarla.
\ No newline at end of file
+alla chiamata \lstinline-CLOSE()- per evitare di dimenticarla.
+
+\section{Subroutine}
+Mano a mano che il programma cresce diventerà necessario razionalizzare la disposizione di
+funzioni e strutturare meglio il listato. In particolare siamo interessati a scrivere delle
+funzioni che si occupino di svolgere un determinato compito in modo che poi possiamo chiamarle
+senza preoccuparci (troppo) di come sono implementate.
+Quelle che in C si chiamavano funzioni in Fortran si chiamano \emph{subroutine}. La sintassi
+per una subroutine assomiglia molto a quella di un programma:
+\begin{lstlisting}[frame=tb,caption=Una subroutine]
+ SUBROUTINE nome(...)
+  ! [ Dichiarazioni ]
+  ! [ Corpo della subroutine ]
+ END SUBROUTINE
+\end{lstlisting}
+Una particolarità per così dire ``curiosa'' è che le variabili passate alla subroutine dovranno
+essere ridichiarate all'interno della stessa perché essa ci possa accedere. Le variabili inoltre
+vengono sempre passate per riferimento (quello che succede in C passando per riferimento o quello
+che succede in C++ passando una reference) e, per conludere, non c'è un'istruzione di ritorno\footnote{%
+O perlomeno, non ne ho mai incontrate. Notare però che programmo in fortran da pochi giorni e quindi.. potrei
+scoprirle prossimamente :) }.
+Ci saranno quindi variabili di Input e variabili di Output\footnote{So che sono schizzinoso, ma trovo che sia
+una cosa \underline{orribile}}, ma tutte insieme nella chiamata della funzione.
+Per chiarire le idee, e spiegare i passaggi che mancano, proponiamo un esempio di una funzione che prenda un
+numero e lo moltiplichi per due\footnote{che esempio inutile, direte voi\ldots e avete anche ragione ma
+in questo momento non mi viene in mente niente di più costruttivo}
+\begin{lstlisting}[frame=tb,caption=Un semplice programma che fa uso di subroutine]
+ ! Questo programma prende in input un numero e lo moltiplica per due;
+ ! Di per se' e' piuttosto inutile ma mostra come si utilizza una subroutine
+ ! nell'ambito di un programma
+
+ PROGRAM sub_doppio
+
+  REAL :: x;
+  ! Leggo dallo standard input x
+  READ(*,*) x;
+
+  ! Lo moltiplico per due facendo uso della subroutine
+  CALL doppio(x);
+
+  ! Lo stampo. Atttenzione! La subroutine ha modificato il vero
+  ! valore di x perche' le ho di fatto passato un puntatore
+  WRITE(*,*) x;
+
+! Terminiamo l'esecuzione del programma principale.
+END PROGRAM sub_doppio
+
+SUBROUTINE doppio(x)
+ REAL :: x;
+ x = x * 2;
+END SUBROUTINE doppio
+\end{lstlisting}
+Naturalmente si possono fare esempi molto più complessi, e soprattutto più utili. Ad esempio, supponiamo
+di implementare la subroutine \lstinline-dotprod- che avevamo pensato parlando del pagerank per fare il prodotto
+matrice vettore con una matrice sparsa. Non la riportiamo qui perché è già stata scritta (si veda il Listato~\ref{lst:matrixvec})
+ma commentiamo alcuni fatti:
+\begin{itemize}
+ \item Le keyword \lstinline-INTENT(IN)- e \lstinline-INTENT(OUT)- servono per l'appunto a specificare se una variabile
+ è da considerarsi di input o di output. Questo di fatto non cambia nulla, a parte che il compilatore ci avviserà
+ se tentiamo di modificare variabili di input;
+ \item La \lstinline-SUBROUTINE- può venir scritta in un file separato e poi linkata insieme al file eseguibile che
+ la richiama. Spiegheremo meglio questo concetto con un esempio;
+\end{itemize}
+
+Supponiamo di avere scritto la subroutine in un file di nome \verb-dotprod.f90-, e di aver successivamente
+scritto un listato \verb-matrici.f90- in cui compaia l'istruzione \lstinline-CALL dotprod(...)-. Sarebbe tedioso
+dover copiare il contenuto del file \verb-dotprod.f90- all'interno di \verb-matrici.f90- per poi compilarlo.
+In effetti esiste un metodo più pratico per agire.
+\begin{enumerate}
+ \item Compilare i file sorgenti separatamente, senza creare l'eseguibile ma solamente i \emph{file oggetto}
+ che contengono la versione compilata del listato, senza che le referenze siano stare risolto. Questo significa
+ che all'interno del file oggetto associato a \verb-matrici.f90- ci sarà una chiamata ad una \lstinline-dotprod()-
+ senza che abbia la minima idea di dove andare a prenderla; questa operazione si realizza su Linux con \verb-f95- in questo
+ modo: \\
+ \verb+# f95 -c dotprod.f90 matrici.f90+
+
+ \item Il secondo passo consiste nel creare un eseguibile unico con le dipendenze risolte, ovvero in cui ci sia
+ la chiamata a \lstinline-dotprod()- ma questa volta sia chiaro dove poterla trovare\footnote{sono conscio che questa
+ spiegazione non è molto chiara. Cercherò di migliorarla}; questo compito viene eseguito dal \emph{linker} che, su Linux,
+ fa ancora parte di \verb-f95-\footnote{forse si portebbe discutere sulla correttezza di questa affermazione, in ogni caso noi
+ daremo il comando f95 per eseguire l'operazione. Quello che poi lui faccia davvero, compreso chiamare altri programmi,
+ per il momento non è affar nostro}; il comando è il seguente: \\
+ \verb+# f95 -o matrici matrici.o dotprod.o+
+\end{enumerate}
+
ViewGit