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