viewgit/index.php:465 Only variables should be passed by reference [2048]

viewgit/index.php:466 Non-static method GeSHi::get_language_name_from_extension() should not be called statically [2048]

  1. \chapter{Il fortran 95}
  2. Il linguaggio di programmazione usato per implementare gli algoritmi è stato il FORTRAN, una
  3. ``minor revision''\footnote{non ho mai capito come si traduca veramente in italiano la parola
  4. revision -- ogni suggerimento è bene accetto} del FORTRAN 90. \\
  5. Rispetto all versioni precedenti ci sono delle interessanti novità, per cui se state pensando
  6. ``Oddio, il FORTRAN nel 2009, non ci posso credere'' prima leggete il seguito\footnote{Ebbene sì,
  7. è quello che ho pensato io, ma poi mi sono resoconto che il linguaggio aveva fatto dei progressi
  8. dagli anni sessanta a questa parte}; è l'elenco delle cose che non mi aspettavo
  9. \begin{enumerate}[(a)]
  10. \item Allocazione dinamica della memoria;
  11. \item Creazione di tipi astratti e overloading degli operatori;
  12. \item Programmazione ad oggetti e polimorfismo (solo Fortran 2003/2008);
  13. \end{enumerate}
  14.  
  15. In ogni caso, in queste note includerò alcune righe su come si scrivono le prime righe di codice
  16. in fortran. In codice Fortran saranno infatti riportati tutti gli esempi nella parte di esercitazione.
  17.  
  18. \section{La sintassi}
  19. \subsection{Hello World!}
  20. Per una convenzione che di cui non so l'origine non è posibbile cominciare da qualcosa di diverso del
  21. programma Hello World! Noi non saremo da meno. Cominceremo a guardare il codice e a commentarlo
  22. passo passo..
  23.  
  24. \begin{lstlisting}[frame=tb,caption=Hello World,label=lst:helloworld]
  25. PROGRAM helloworld
  26. IMPLICIT NONE
  27. WRITE(*,*) 'Hello World'
  28. END PROGRAM
  29. \end{lstlisting}
  30.  
  31. Tutte le righe precedute da \lstinline-!- sono dei commenti e quindi vengono scartate
  32. dal compilatore. Ad esempio '\lstinline-a = 1 ! Inizializzazione-' è equivalente a
  33. '\lstinline-a = 1-'.
  34.  
  35. L'istruzione \lstinline-PROGRAM helloworld- spiega al compilatore che questo è l'inizio del
  36. nostro programma e che si chiamerà helloworld. Si aspetta di trovare alla fine un
  37. \lstinline-END PROGRAM- che noi abbiamo prontamente inserito.
  38.  
  39. L'istruzione \lstinline-IMPLICIT NONE- serve invece a disattivare delle convenzione che si
  40. usavano nelle prime versione del fortran (e che esistono ancora per retrocompatibilità)
  41. che stabiliscono che le variabili \lstinline-i,j,k- sono di tipo intero, mentre ad esempio
  42. \lstinline-x,y,z- sono reali. Questo non è desiderabile in un linguaggio di programmazione
  43. moderno in cui ci si aspetta di scrivere del codice comprensibile.
  44.  
  45. Infine l'istruzione \lstinline-WRITE(*,*)- scrive sull stdout\footnote{che, nelle maggior parte
  46. dei casi, coincide con il monitor} tutti gli argomenti che gli si passano dopo. \`E possibile
  47. controllare la formattazione di quello che viene stampato ma, come è simboleggiato dagli asterischi,
  48. per ora non ce ne stiamo preoccupando.
  49.  
  50. \subsection{La struttura}
  51. Un programma in FORTRAN ha una struttura prefissata:
  52. \begin{lstlisting}[label=lst:fotranstruct,frame=tb]
  53. PROGRAM nomeprogramma
  54. IMPLICIT NONE
  55. ! Specificazioni: in questa parte si trova la dichiarazione
  56. ! delle variabili e dei nuovi tipi
  57.  
  58. ! Parte di esecuzione: qui troviamo il codice vero e proprio che
  59. ! viene eseguito
  60.  
  61. ! Subroutine: qui troviamo la definizione dei sottoprogrammi che
  62. ! possono venire chiamati dalla parte di esecuzione
  63. END PROGRAM
  64. \end{lstlisting}
  65. \subsection{I tipi}
  66. Come il C e tutti i linguaggi che vantano una certa storia il FORTRAN è un linguaggio tipato,
  67. ovvero ogni variabile ha un tipo (ad esempio intero) e non gli si possono assegnare valori
  68. di tipi differenti. \\
  69. Si possono aggiungere delle parole chiave alle dichiarazioni di tipi, più precisamente
  70. \begin{itemize}
  71. \item \lstinline-PARAMETER-: questa indica che la variabile non verrà modificata, è semplicemente
  72. un parametro per il programma.
  73. \item \lstinline-ALLOCATABLE-: Questo parola chiave indica che la memoria per la variabile verrà
  74. allocata esplicitamente in un secondo momento, è particolarmente utile con l'altra parola chiave
  75. \item \lstinline-DIMENSION-: questa permette di speicificare che la variabile dichiarate è un array
  76. e la sua relativa dimensione (Esempio: \lstinline- INTEGER, DIMENSION(5) :: vec-); è possibile specificare
  77. \lstinline-:- come dimensione, nel qual caso il compilatore assumerà che la dimensione verrà determinata
  78. in un secondo momento. Un caso tipico è la creazione di un vettore la cui dimensione verrà determinata
  79. a run-time\footnote{ovvero durante l'esecuzione.}; questo si può realizzare con un codice di questo tipo
  80. \begin{lstlisting}[frame=tb]
  81. PROGRAM allocatore
  82. INTEGER , ALLOCATABLE :: i
  83. INTEGER :: size
  84. ! Leggo da tastiera la dimensione dell'array e lo alloco
  85. READ(*,*) size
  86. ALLOCATE(i(size))
  87. END PROGRAM
  88. \end{lstlisting}
  89.  
  90. \end{itemize}
  91. I tipi principali presenti in Fortran sono
  92. \begin{itemize}
  93. \item \textbf{Interi}: Sono denotati dalla parola chiave \lstinline-INTEGER- e sono appunto numeri
  94. interi. Generalemente occupano $4$ byte.
  95. \item \textbf{Reali}: Numeri reali, che vengono memorizzati come floating point. La parola chiave
  96. è \lstinline-REAL- e occupano generalmente $4$ byte. Per i nostri scopi questi sono pochi, e quindi
  97. useremo in generale il seguente trucchetto:
  98. \begin{lstlisting}[frame=tb]
  99. INTEGER, PARAMETER :: db = KIND(0.D0)
  100. REAL(dp) :: real_var
  101. \end{lstlisting}
  102. che si occuperà di assegnare al tipo \lstinline-REAL- dichiarato la stessa dimensione delle costante di tipo
  103. \texttt{double} \lstinline-0.D0-.
  104. \end{itemize}
  105.  
  106. \subsection{Input e Output}
  107. Per iniziare ci basterà conoscere le istruzioni di stampa su schermo e lettura da tastiera, che sono rispettivamente
  108. \begin{itemize}
  109. \item \lstinline-WRITE(*,*) dato_1, dato_2 , ...- che si occuperà di scrivere sullo schermo (identificato dal primo
  110. \lstinline-*-) e con una formattazione standard (identificata dal secondo \lstinline-*-) i dati che gli inseriamo dopo;
  111. \item \lstinline-READ(*,*) var_1, var_2, ...- che si occuperà di leggere da tastiera (il primo \lstinline-*-) i dati
  112. in un formato standard (il secondo \lstinline-*-);
  113. \end{itemize}
  114. In realtà queste istruzioni ci permettono di controllare anche formattazioni e sorgenti e destinazioni di Input e Output.
  115. Per scrivere (o leggere) su un file è prima necessario \textbf{aprirlo}. Per fare questo bisogna eseguire una
  116. chiamata alla funzione \lstinline-OPEN()-. Questa si occuperà di aprire un file da noi indicata ed assegnarlo ad
  117. un numero intero, anche quello indicato da noi. Bisogna fare attenzione in quest'ultimo passaggio a ricordare
  118. che \lstinline-5- e \lstinline-6- sono già riservati alla tastiera ed allo schermo.
  119. Potremmo poi fare riferimento (sia in lettura che in scrittura)
  120. a quel determinato file sostituendo quell'intero a \lstinline-*-. Questo codice probabilmente chiarirà meglio la questione.
  121. \begin{lstlisting}[frame=tb]
  122. PROGRAM CopiaIncolla
  123. IMPLICIT NONE
  124.  
  125. ! Dichiaro delle variabili intere di tipo PARAMETER
  126. ! per contenere gli interi con cui poi mi riferiro' ai file.
  127. ! Sarebbe infatti complicato dover ricordare tanti numeri
  128. ! a memoria e renderebbe il codice meno leggibile
  129. INTEGER, PARAMETER :: infile = 11, outfile = 12
  130. INTEGER :: j
  131. INTEGER :: buf
  132.  
  133. ! Cerco di aprire il file in.txt
  134. OPEN(FILE='in.txt', UNIT=infile)
  135.  
  136. ! E anche il file out.txt
  137. OPEN(FILE='out.txt', UNIT=outfile)
  138.  
  139. ! Leggo le prime 10 righe da questo file
  140. ! e le scrivo su out.txt, raddoppiate (assumendo
  141. ! che siano interi)
  142. DO j=1,10
  143. READ(infile,*) buf
  144. WRITE(outfile,*) buf * 2
  145. END DO
  146.  
  147. ! Alla chiusura del programma anche tutti i file vengono chiusi,
  148. ! e quindi questo rende le prossime righe superflue. Pero' e' buona
  149. ! norma ricordarsi di chiudere i file che si sono aperti, e quindi
  150. ! lo facciamo
  151. CLOSE(infile)
  152. CLOSE(outfile)
  153.  
  154. END PROGRAM
  155. \end{lstlisting}
  156. Abbiamo qui introdotto anche la chiamata \lstinline-CLOSE()- che serve appunto per
  157. chiudere un file. \`E normalmente buona norma chiudere tutti i file che si aprono e quindi,
  158. in programma corposi, conviene sempre scrivere la chiamata ad \lstinline-OPEN()- insieme
  159. alla chiamata \lstinline-CLOSE()- per evitare di dimenticarla.
  160.  
  161. \section{Subroutine}
  162. Mano a mano che il programma cresce diventerà necessario razionalizzare la disposizione di
  163. funzioni e strutturare meglio il listato. In particolare siamo interessati a scrivere delle
  164. funzioni che si occupino di svolgere un determinato compito in modo che poi possiamo chiamarle
  165. senza preoccuparci (troppo) di come sono implementate.
  166. Quelle che in C si chiamavano funzioni in Fortran si chiamano \emph{subroutine}. La sintassi
  167. per una subroutine assomiglia molto a quella di un programma:
  168. \begin{lstlisting}[frame=tb,caption=Una subroutine]
  169. SUBROUTINE nome(...)
  170. ! [ Dichiarazioni ]
  171. ! [ Corpo della subroutine ]
  172. END SUBROUTINE
  173. \end{lstlisting}
  174. Una particolarità per così dire ``curiosa'' è che le variabili passate alla subroutine dovranno
  175. essere ridichiarate all'interno della stessa perché essa ci possa accedere. Le variabili inoltre
  176. vengono sempre passate per riferimento (quello che succede in C passando per riferimento o quello
  177. che succede in C++ passando una reference) e, per conludere, non c'è un'istruzione di ritorno\footnote{%
  178. O perlomeno, non ne ho mai incontrate. Notare però che programmo in fortran da pochi giorni e quindi.. potrei
  179. scoprirle prossimamente :) }.
  180. Ci saranno quindi variabili di Input e variabili di Output\footnote{in realtà in FORTRAN esistono
  181. anche delle funzioni, che come in C ritornano dei valori; noi non le scriveremo (e quindi in particolare
  182. non ne ho mai scritta una) e quindi non sono qui esposte. Nonostante questo verranno utilizzate
  183. nel corso funzioni interne del fortran come \lstinline-RESHAPE()- o \lstinline-MATMUL()-. }, ma tutte insieme nella chiamata della funzione.
  184. Per chiarire le idee, e spiegare i passaggi che mancano, proponiamo un esempio di una funzione che prenda un
  185. numero e lo moltiplichi per due\footnote{che esempio inutile, direte voi\ldots e avete anche ragione ma
  186. in questo momento non mi viene in mente niente di più costruttivo}
  187. \begin{lstlisting}[frame=tb,caption=Un semplice programma che fa uso di subroutine]
  188. ! Questo programma prende in input un numero e lo moltiplica per due;
  189. ! Di per se' e' piuttosto inutile ma mostra come si utilizza una subroutine
  190. ! nell'ambito di un programma
  191.  
  192. PROGRAM sub_doppio
  193.  
  194. REAL :: x;
  195. ! Leggo dallo standard input x
  196. READ(*,*) x;
  197.  
  198. ! Lo moltiplico per due facendo uso della subroutine
  199. CALL doppio(x);
  200.  
  201. ! Lo stampo. Atttenzione! La subroutine ha modificato il vero
  202. ! valore di x perche' le ho di fatto passato un puntatore
  203. WRITE(*,*) x;
  204.  
  205. ! Terminiamo l'esecuzione del programma principale.
  206. END PROGRAM sub_doppio
  207.  
  208. SUBROUTINE doppio(x)
  209. REAL :: x;
  210. x = x * 2;
  211. END SUBROUTINE doppio
  212. \end{lstlisting}
  213. Naturalmente si possono fare esempi molto più complessi, e soprattutto più utili. Ad esempio, supponiamo
  214. di implementare la subroutine \lstinline-dotprod- che avevamo pensato parlando del pagerank per fare il prodotto
  215. matrice vettore con una matrice sparsa. Non la riportiamo qui perché è già stata scritta (si veda il Listato~\ref{lst:matrixvec})
  216. ma commentiamo alcuni fatti:
  217. \begin{itemize}
  218. \item Le keyword \lstinline-INTENT(IN)- e \lstinline-INTENT(OUT)- servono per l'appunto a specificare se una variabile
  219. è da considerarsi di input o di output. Questo di fatto non cambia nulla, a parte che il compilatore ci avviserà
  220. se tentiamo di modificare variabili di input;
  221. \item La \lstinline-SUBROUTINE- può venir scritta in un file separato e poi linkata insieme al file eseguibile che
  222. la richiama. Spiegheremo meglio questo concetto con un esempio;
  223. \end{itemize}
  224.  
  225. Supponiamo di avere scritto la subroutine in un file di nome \verb-dotprod.f90-, e di aver successivamente
  226. scritto un listato \verb-matrici.f90- in cui compaia l'istruzione \lstinline-CALL dotprod(...)-. Sarebbe tedioso
  227. dover copiare il contenuto del file \verb-dotprod.f90- all'interno di \verb-matrici.f90- per poi compilarlo.
  228. In effetti esiste un metodo più pratico per agire.
  229. \begin{enumerate}
  230. \item Compilare i file sorgenti separatamente, senza creare l'eseguibile ma solamente i \emph{file oggetto}
  231. che contengono la versione compilata del listato, senza che le referenze siano stare risolto. Questo significa
  232. che all'interno del file oggetto associato a \verb-matrici.f90- ci sarà una chiamata ad una \lstinline-dotprod()-
  233. senza che abbia la minima idea di dove andare a prenderla; questa operazione si realizza su Linux con \verb-f95- in questo
  234. modo: \\
  235. \verb+# f95 -c dotprod.f90 matrici.f90+
  236.  
  237. \item Il secondo passo consiste nel creare un eseguibile unico con le dipendenze risolte, ovvero in cui ci sia
  238. la chiamata a \lstinline-dotprod()- ma questa volta sia chiaro dove poterla trovare\footnote{sono conscio che questa
  239. spiegazione non è molto chiara. Cercherò di migliorarla}; questo compito viene eseguito dal \emph{linker} che, su Linux,
  240. fa ancora parte di \verb-f95-\footnote{forse si portebbe discutere sulla correttezza di questa affermazione, in ogni caso noi
  241. daremo il comando f95 per eseguire l'operazione. Quello che poi lui faccia davvero, compreso chiamare altri programmi,
  242. per il momento non è affar nostro}; il comando è il seguente: \\
  243. \verb+# f95 -o matrici matrici.o dotprod.o+
  244. \end{enumerate}
  245.