Il Fortran 90/95 per esempi

Claudio Chiaruttini

Università di Trieste
Dipartimento di Matematica e Informatica

Premessa

La presente cartella contiene esempi di programmi Fortran nello standard 90/95. I programmi sono commentati, in modo da costituire una guida introduttiva al linguaggio, di cui illustrano le principali strutture, senza pretesa di completezza. Gli esempi sono rivolti a chi già conosca altri linguaggi di programmazione imperativa, quali Pascal, C, Basic, ecc.
Si rimanda a pubblicazioni specifiche per una trattazione esauriente, ad esempio:

Programming in FORTRAN 90, di J. S. Morgan e J. L. Schonfelder (1993)
Ottimo testo, conciso e completo, purtroppo difficilmente reperibile in commercio.
Fortran 90/95 Explained, di M. Metcalf e J. Reid (Oxford, 1996)
Manuale completo, ma poco didattico.
Fortran 90/95, guida alla programmazione, di S. J. Chapman (McGraw-Hill, 2000)
Prolisso e incompleto, può tuttavia essere utile a chi non conosca altri linguaggi.

Alcuni testi in linea sul Fortran 90:
http://www.ciaburro.it/man-f90/
Buona introduzione
http://www.liv.ac.uk/HPC/F90page.html
Corsi di Fortran 90 dell'Università di Liverpool. Dal sito si può prelevare un ottimo manuale: CourseNotes.ps.zip oppure CourseNotes.ps.gz
http://wwwasdoc.web.cern.ch/wwwasdoc/f90.html
Buono come manuale

Il linguaggio

trapezio.f90

Elementi fondamentali del linguaggio: alfabeto, nomi, commenti, variabili, costanti, stringhe di caratteri.
Inizio e fine del codice un programma: PROGRAM, END PROGRAM.
Terminazione dell'esecuzione: STOP.
Variabili reali e loro dichiarazione, IMPLICIT NONE.
Espressioni aritmetiche ed assegnazioni, operazioni fra numeri reali ed interi.
Lettura e scrittura guidata da lista da e per unità standard.

valore_assoluto_1.f90

Costrutto IF-THEN.
Espressioni logiche, operatori relazionali (predicati).

valore_assoluto_2.f90

Istruzione IF.

valore_assoluto_3.f90

Funzioni intrinseche, funzione ABS (valore assoluto).

quadratica1.f90

Costrutti IF-THEN-ELSE e loro annidamento.
Operatore di elevamento a potenza.
Ordine di esecuzione delle operazioni nelle espressioni aritmetiche.
Funzione intrinseca radice quadrata (SQRT).

quadratica1bis.f90

Selezione a più vie: costrutto IF-THEN-ELSE con clausola ELSE IF.

quadratica2.f90

Precisione finita delle operazioni fra valori reali e loro confronti.
Costanti con nome, attributo PARAMETER.
Costanti reali in notazione esponenziale.

mese.f90

Selezioni a più vie: costrutto SELECT CASE.

somma.f90

Cicli a conteggio: costrutto DO.

matrice.f90

Variabili di tipo array: definizioni di rango (rank), estensione (extent), forma (shape), ampiezza (size); attributo DIMENSION; sezioni di array.
Ordine di memorizzazione degli elementi di una matrice.
Lettura e scrittura di una matrice per righe.

listino2.f90

Definizione di tipi derivati e dichiarazione di strutture: istruzioni TYPE e TYPE(tipo); selezione di componente.
Variabili di tipo carattere (stringhe).
Cicli a condizione: costrutti DO con istruzione EXIT.
Variabili e costanti logiche, operatori logici e loro regole di precedenza.
Clausola DO implicito nella lettura e scrittura di array.

listino3.f90

Programma principale con SUBROUTINE interna. Dichiarazioni globali e locali. Istruzione CONTAINS.
Chiamata di SUBROUTINE (istruzione CALL) e sua terminazione (istruzione RETURN).
Interfaccia esplicita di una procedura, argomenti di ingresso e di uscita (attributo INTENT).
Argomenti vettoriali di forma esplicita.
Argomenti carattere di lunghezza presunta.
Unità di programma di tipo "programma principale".

hanoi.f90

Procedure ricorsive.
Inizializzazione di variabili nella dichiarazione.
Istruzioni lunghe: loro distribuzione su più righe.
Ingresso/uscita con formato: descrittori X, A, I, fattori di ripetizione, stringhe.

fattoriale.f90

Funzioni ricorsive: loro dichiarazione ed uso.
Istruzione STOP con messaggio di errore.

primitive_lista.f90

Puntatori e loro uso: dichiarazione (attributo POINTER), allocazione e disallocazione, riferimento, assegnazione di puntatore, variabile associata (target),  funzione intrinseca ASSOCIATED per controllare l'associazione di un puntatore.
Unità di programma di tipo MODULE per definire tipi derivati ed operazioni su di essi. Procedure di modulo.
Funzioni non ricorsive. Puntatori come argomenti di procedure.

test_lista.f90

Richiamo dei moduli: istruzione USE.
Stati di un puntatore. Istruzione NULLIFY per dissociare i puntatori.

primitive_coda.f90, test_coda.f90

Moduli: restrizione della visibilità delle definizioni, clausola USE-ONLY;
cambiamento di nome ad un'oggetto.

lista_ordinata.f90

Esempio completo di uso dei puntatori e relative procedure intrinseche.
Istruzione ASSOCIATED con due argomenti: controllo dell'associazione di un puntatore ad uno specifico target.
Connessione di un file di testo (formattato) al programma. Istruzione OPEN, clausole UNIT, FILE, STATUS.
Lettura di un file formattato, clausola IOSTAT.
Scrittura con la clausola ADVANCE='NO'.

file_binario_sequenziale.f90

Creazione e scrittura di un file binario (non formattato) sequenziale, clausola FORM.

file_binario_diretto.f90

Creazione e scrittura di un file binario ad accesso diretto, clausole ACCESS e RECL.
Istruzione INQUIRE per determinare la lunghezza di un record.
Funzione intrinseca HUGE per ottenere il massimo intero rappresentabile.
Ciclo DO con contatore ed istruzione EXIT.

Esempi di programmazione vettoriale

Somma di diagonali ed antidiagonali di una matrice

diagonali1.f90

Questo programma si basa su di un algoritmo sequenziale, come risulta dalla presenza dei cicli a conteggio.
Allocazione dinamica di array: attributo ALLOCATABLE, istruzione ALLOCATE.
Funzione intrinseca vettoriale SUM per sommare tutti gli elementi di un array.
Funzione intrinseca vettoriale SIZE per ottennere l'estensione di un indice.
Funzioni a valore vettoriale: definizione ed uso.
Costrutto ed istruzione FORALL: assegnazione multipla di elementi di array.
Sezioni di array di ampiezza nulla. E' legittimo che il limite inferiore di un indice sia maggiore di quello superiore (es. A(1:0)); in tal caso, SIZE(A(1:0)) vale 0. Sezioni di questo tipo sono usabili quali argomenti delle funzioni  intrinseche.

diagonali2.f90

Programma parallelo. Si noti l'uso di funzioni vettoriali al posto dei cicli DO.
Assegnazioni vettoriali.
Costruttore di vettori: (/ ... /).
Funzione intrinseca vettoriale EOSHIFT per lo scorrimento di un array.
Uso della funzione intrinseca SUM per sommare righe e colonne di una matrice.

Estrazione dei numeri primi mediante in crivello di Eratostene

Algoritmo
Fissato un limite superiore N, metti nel crivello tutti gli interi da 2 ad N.
Togli dal crivello tutti i multipli dei numeri in esso presenti.
I numeri rimasti nel crivello sono primi.

eratostene_s.f90

Programma sequenziale basato su ciclo DO.
Istruzione CYCLE per interrompere l'iterazione corrente di un ciclo.
Array. Scalari nelle espressioni vettoriali: conformità di uno scalare a qualunque array; sezioni di array con passo (stride).
Funzione intrinseca vettoriale PACK per estrarre elementi di un array sotto il controllo di una maschera.

eratostene_p.f90

Programma parallelo basato su costrutto FORALL.

Note
1) La semantica del FORALL è parallela in quanto, per definizione, le operazioni elementari, possono essere eseguite in un ordine qualunque. Al contrario la semantica del DO, in qualunque forma, è sequenziale in quanto, per definizione, le operazioni elementari devono essere eseguite nell'ordine definito dalla sequenza degli indici.
2) I costrutti paralleli possono non essere efficienti con un singolo processore. Infatti, nella versione sequenziale, ogni numero non primo viene eliminato una volta sola, mentre nella versione parallela, viene eliminato un numero di volte pari al numero dei suoi sottomultipli.
(aggiornato il 18/11/2004)