Upload
lamnguyet
View
227
Download
5
Embed Size (px)
Citation preview
ELEMENTI DI PROGRAMMAZIONE
Gli ARRAY
in
FORTRAN 90
Andrea Prevete, UNINA2 INGEGNERIA MECCANICA/AEROSPAZIALE, a.a. 2012/13
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Un ARRAY è un AGGREGATO di più DATI dello stesso TIPO (interi, reali, etc), ognuno univocamente individuato dal valore di uno oppure due .. e fino a sette indici.
Ogni indice caratterizza una DIMENSIONE dell’array ed il numero di indici definisce il RANGO dell’ array.
Un array monodimensionale, che chiameremo VETTORE, è assimilabile concettualmente ad un elenco ordinato di valori di un certo tipo – per esempio:
(1, -5, 7, 0, 8)
Come ogni altra variabile o costante con nome, un array può avere un NOME che lo individua globalmente come aggregato. Poi ci si potrà riferire ad un suo elemento utilizzando i succitati
INDICI.Supponiamo, per esempio, di aver assegnato al vettore di cui sopra il nome Cinquina, allora Cinquina(2) sarà il suo secondo elemento – cioè l’intero -5. In realtà FORTRAN 90 consente
un’estrema flessibilità nell’organizzazione del DOMINIO o RANGE di un indice. VETTORE: ( 1, -5, 7, 0, 8)
⇑ ⇑ ⇑ ⇑ ⇑RANGE: [-2, -1, 0, 1, 2]
Definito così il RANGE, per riferirci all’elemento -5 del vettore dovremo scrivere Cinquina(-1). Dall’esempio è sufficientemente evidente che un RANGE è dato definendone gli estremi, nel
nostro caso -2 e 2, così che l’ESTENSIONE o AMPIEZZA del vettore risulta come LIMSUP-LIMINF+1.
Due array sono detti CONFORMI se hanno lo stesso rango e stessa ampiezza per ogni dimensione.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Gli array bidimensionali, che chiameremo MATRICI, sono concettualmente
assimilabili a tabelle ordinate secondo indici di riga e colonna.
Supponendo - ad esempio - data una matrice di nome Tabella, con
elementi INTERI disposti su quattro righe e tre colonne, avremo lo
schema concettuale che segue:
L’elemento Tabella(3, 2) individuerà quindi l’intero 1024 – posto
all’intersezione fra la terza riga e la seconda colonna.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
In effetti, lo schema precedente illustra anche un’ulteriore importante
peculiarità degli Array multidimensionali così come implementati da
FORTRAN 90: la cosiddetta organizzazione per colonne. Le frecce in
figura evidenziano appunto un criterio di linearizzazione della struttura
bidimensionale, un ordine interno, su cui al momento non ci soffermeremo
ripromettendoci di riconsiderarlo al momento opportuno.
Resta valido quanto detto sulla flessibilità del range per gli indici.
Supponiamo di aver definito per l’indice di riga:
INIZIO=10, FINE=13
E per l’indice di colonna:
INIZIO=-1, FINE=1
Allora l’elemento di matrice evidenziato in figura dovrebbe essere riferito
come Tabella(12, 0).
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
La sintassi generale di una istruzione di dichiarazione Fortran 90 per un array è la
seguente:
TIPO, DIMENSION(range1 [,range2 [..range7]] ) [, ATTRIBUTO1, ...] :: lista_di_array
in cui TIPO è il il tipo di appartenenza di tutti i componenti della lista_di_array, la
parola chiave DIMENSION è un attributo che serve a specificare la dimensione
dell’array che si sta dichiarando, mentre range1, .. range7 forniscono i range in
cui spaziano gli indici dell’array in ogni dimensione.
Esempi:
INTEGER, DIMENSION(10) :: Numeri
CHARACTER, DIMENSION(-2:5, 3) :: CharTab
REAL, DIMENSION(-9:0, 2:5) :: RealTab
! Numeri è un vettore di interi ad 1 dimensione di estensione 10
! CharTab è una matrice di caratteri con estensione 8 nella 1ª dimensione (righe)
! ed estensione 3 nella 2ª dimensione (colonne)
! RealTab è una matrice di reali con 10 righe e 8 colonne
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Un array deve essere, prima di ogni utilizzazione, esplicitamente inizializzato. L’inizializzazione può essere effettuata a tempo di esecuzione, utilizzando una variabile indice, come negli esempi che seguono:
! Esempio 1
INTEGER, DIMENSION(10) :: Numeri
INTEGER i
DO i=1,10
Numeri(i)=2**i
END DO
! Esempio 2
INTEGER, DIMENSION(-10:10) :: Numeri
INTEGER i
DO i=-10,10
READ(*,*) Numeri(i)
END DO
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
L’inizializzazione può essere anche realizzata a tempo di compilazione, utilizzando i cosiddetti COSTRUTTORI:
! Qui l’array è inizializzato contestualmente alla sua
! dichiarazione
INTEGER, DIMENSION(5) :: Numeri=(/ 1, 5, -7, 3, 4 /)
Comunque, il costruttore può anche essere utilizzato per inizializzare l’array a tempo di esecuzione:
INTEGER, DIMENSION(-2:2) :: Numeri
Numeri =(/ 1, 5, -7, 3, 4 /)
INDICIAndrea Prevete, UNINA2 - 2013
Qualsiasi espressione che fornisce come risultato un intero è un indice valido per un array.Consideriamo, come esempio, il segmento di codice:
REAL, DIMENSION(5) :: lista=(/ 3, 4, -5, 6, 3/)
INTEGER :: i=1, j=5
WRITE(*,*) lista(i)
!corretto, fornisce come output lista(1), quindi 3
WRITE(*,*) lista(i+j/2)
!corretto, fornisce come output lista(3), quindi -5
WRITE(*,*) lista(i+0.5*j)
!il compilatore denuncia un errore di tipo, infatti il valore dell’espressione-indice è di
!tipo reale
WRITE(*,*) lista(i+j)
!errore di out-range in compilazione
DO IMPLICITOAndrea Prevete, UNINA2 - 2013
Quando si lavora con gli array risulta particolarmente utile utilizzare un costrutto logico che consente di realizzare iterazioni per così dire implicite.
Per esempio il segmente di codice che segue ..
DO i=1,10
lista(i)=1000*i
END DO
può essere sostituito dalla singola linea di codice ..
lista = (/ (1000*i, i=1, 10) /)
dove il costrutto (1000*i, i=1, 10) realizza il suddetto DO IMPLICITO.
SEZIONI DI ARRAYAndrea Prevete, UNINA2 - 2013
Nel codice che segue, un’altra importantissima feature degli array Fortran – la possibilità di definire ed usare in maniera estremamente flessibile porzioni di array, dette sezioni.
INTEGER, DIMENSION(1:10):: lista
INTEGER, DIMENSION(1:5) :: listaP
INTEGER, DIMENSION(-5:-1) :: listaD
lista = (/ (1000*i, i=1, 10) /)
listaP = lista(1:10:2)
listaD = lista(2:10:2)
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Un array dinamico è dichiarato utilizzando l’ attributo ALLOCATABLE.
Poichè le dimensioni di un array dinamico non sono, per definizione, note all’atto della dichiarazione, il limite di ciascuno dei suoi indici va sostituito con il simbolo dei due punti:
TIPO, ALLOCATABLE, DIMENSION(: [, :, ...]) :: nome_array
Esempi:
integer, ALLOCATABLE, DIMENSION(:) :: elenco_interi
character(10), ALLOCATABLE, DIMENSION(:,:) :: tabella_parole
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Le estensioni di un array dichiarato ma non ancora allocato possono essere specificate utilizzando l’istruzione ALLOCATE che ha appunto la funzione di riservare spazio in memoria per i suoi elementi. La sintassi della suddetta istruzione è quella che segue:
ALLOCATE(lista_di_array_dimensionati)
Esempio:
INTEGER, ALLOCATABLE, DIMENSION(:) :: elenco_interi
CHARACTER(10), ALLOCATABLE, DIMENSION(:,:) :: tabella_parole
…
ALLOCATE(elenco_interi(100), tabella_parole(0:9, 10))
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
L’istruzione ALLOCATE rende disponibile al progettista un’opzione per monitorare il successo dell’operazione di allocazione. Il formato di questa versione estesa
dell’istruzione prevede l’indicazione di una variabile intera che conterrà in esito
all’esecuzione dell’operazione di allocazione un codice numerico di errore oppure il valore 0
se tutto è andato bene.
ALLOCATE(lista_di_array_dimensionati, STAT=variabile_di_controllo)
Esempio:INTEGER :: errore
INTEGER, ALLOCATABLE, DIMENSION(:) :: elenco_interi
…
ALLOCATE(elenco_interi(100), STAT=errore)
IF (errore/=0) THEN
PRINT*, "Allocazione dell’array fallita, codice errore: “, errore
STOP
END IF
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Lo spazio di memoria occupato da un array correntemente allocato può essere liberato
mediante l’istruzione DEALLOCATE che ha la seguente sintassi:
DEALLOCATE(lista_di_array [, STAT=variabile_di_controllo])
dove il significato e l’uso della clausola STAT=variabile_di_stato sono identici a quelli visti
per l’istruzione di allocazione.
E’ importante ricordare che una volta che un array sia stato deallocato i dati in esso
immagazzinati sono definitivamente non più disponibili.
L’uso combinato delle istruzioni ALLOCATE e DEALLOCATE consente di lavorare con un
array allocabile di dimensioni continuamente variabili. Attenzione:
ALLOCATE(vettore(10))
…
ALLOCATE(vettore(20)) ! ERRORE
Non è possibile riallocare lo stesso array prima di averlo deallocato!
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
program reverse_array_dinamico_errori
implicit none
integer, allocatable, dimension(:) :: elenco
integer :: i, n, errore
print*, "quanti elementi vuoi inserire?"
read(*,*) n
allocate(elenco(n), STAT=errore)
IF (stato/=0) THEN
PRINT*, "Allocazione degli array fallita, codice & errore:“, errore
STOP
END IF
read(*,*) elenco
elenco((/(i, i=n,1,-1)/))=elenco ! esegue il reverse
write(*,*) elenco
deallocate(elenco)
end program
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
!
! viene creato un vettore per immagazzinare le coordinate
! di n punti di uno spazio a 3 dimensioni
!
TYPE :: coord3
REAL :: x
REAL :: y
REAL :: z
END TYPE coord3
TYPE(coord3), ALLOCATABLE, DIMENSION(:) :: elenco_punti
INTEGER :: n
…
WRITE(*,*) “Numero di punti da leggere: “
READ(*,*) n
ALLOCATE(elenco_punti(n))
…
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
..
TYPE :: coord3
REAL :: x
REAL :: y
REAL :: z
END TYPE coord3
TYPE :: spezzata
TYPE(coord3), ALLOCATABLE, DIMENSION(:) :: elenco_punti
END TYPE spezzata
INTEGER :: n, i
TYPE(spezzata) :: mia_spezzata
WRITE(*,*) "Numero di punti della spezzata: "
READ(*,*) n
ALLOCATE(mia_spezzata%elenco_punti(n))
DO i=1, n
mia_spezzata%elenco_punti(i)=coord3(REAL(i),REAL(i),REAL(i))
END DO
! mostra i punti
DO i=1, n
write(*,*) mia_spezzata%elenco_punti(i)
END DO
END PROGRAM
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
PROGRAM confronta
IMPLICIT NONE
INTEGER, PARAMETER :: n=10
INTEGER, DIMENSION(n) :: a, b
INTEGER :: i
WRITE(*,*) “Immetti il primo elenco di ”, n, “ interi:”
READ(*,*) (a(i), i=1, n)
WRITE(*,*) “Immetti il secondo elenco di “, n, “ interi:”
READ(*,*) (b(i), i=1, n)
IF (a==b) THEN
WRITE(*,*) “i due elenchi sono uguali!”
ELSE
WRITE(*,*) “i due elenchi non sono uguali!”
END IF
END PROGRAM confronta
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Modifichiamo il programma come segue:
PROGRAM confrontaINTEGER, PARAMETER :: n=10INTEGER, DIMENSION(n) :: a, bINTEGER :: iWRITE(*,*) “Immetti il primo elenco di ”, n, “ interi:”READ(*,*) (a(i), i=1, n)WRITE(*,*) “Immetti il secondo elenco di “, n, “ interi:”READ(*,*) (b(i), i=1, n)WRITE(*,*) “Esito del confronto:”WRITE(*,*) (a==b)END PROGRAM confronta
La compilazione non darà errori ed in esecuzione potremmo avere il seguente risultato:
Immetti il primo elenco di 10 interi:"1 3 5 6 7 2 3 4 5 8
Immetti il secondo elenco di 10 interi:2 3 5 6 3 4 4 3 5 8
Esito del confronto:F T T T F F F F T T
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Il confronto fra due array (conformi!) è quindi possibile e
genera un array logico avente per contenuti i risultati del confronto, elemento per elemento!
a==b
b
a
TTFFFFTTTF
====================
8534436532
8543276531
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
IF (a==b) THEN
⇓⇓⇓⇓
IF (ALL(a==b)) THEN
ALL è una cosiddetta funzione intrinseca di array, appartiene cioè
ad una classe di funzioni specificamente pensate per evere come
argomento/i degli array. In particolare ALL restituirà lo scalare
logico .TRUE. se il suo argomento (un array logico) contiene come
elementi tutti .TRUE., lo scalare .FALSE. altrimenti.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
ALL((a==b)) ! Restituisce .FALSE.
ALL((a(1:4)==b(1:4))) ! Restituisce .TRUE.
ANY((a==b)) ! Restituisce .TRUE.
ANY((a(5:8)==b(5:8))) ! Restituisce .FALSE.
Riuscite ad individuare cosa fa la funzione ANY?
b
a
8534436531
8543276531
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Le funzioni intrinseche di array sono usualmente ricondotte, a seconda dell’uso e degli scopi, a 7 categorie:
1. Funzioni di riduzione
2. Funzioni di interrogazione
3. Funzioni di costruzione
4. Funzioni di trasformazione
5. Funzioni topologiche
6. Funzioni di manipolazione
7. Funzioni algebriche
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni di interrogazione (esempi)
ALLOCATED (ARRAY)Indica se l’ ARRAY è o non è allocato. Il risultato è .TRUE. se ARRAY è correntemente allocato, .FALSE. altrimenti.
Esempio:
REAL, ALLOCATABLE, DIMENSION (:,:,:) :: myarr
...PRINT*, ALLOCATED(myarr) ! stampa il valore .FALSE.
ALLOCATE(myarr(10,0:9))PRINT*, ALLOCATED(myarr) ! stampa il valore .TRUE.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni di costruzione (esempi)
MERGE(TSOURCE,FSOURCE,MASK)
Seleziona tra due valori, o tra gli elementi corrispondenti di due array, in accordo con la condizione specificata da una maschera.TSOURCE può essere uno scalare o un array di tipo qualsiasi.FSOURCE è uno scalare o un array avente stesso tipo di TSOURCE.MASK è un array logico.Il risultato (che ha lo stesso tipo di TSOURCE) viene determinato prendendo, elemento×elemento, il valore corrispondente di TSOURCE (se MASK è .TRUE.) o di FSOURCE (se MASK è .FALSE.).Ad esempio, se la variabile intera r ha valore -3, allora il risultato diMERGE(1.0,0.0,r<0)ha valore 1.0, mentre per r pari a 7 ha the valore 0.0.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni di costruzione (esempi)
Un esempio appena più complesso è il seguente. Se TSOURCE è l’array:
1 3 5
2 4 6
FSOURCE è l’array:
8 9 0
1 2 3
e MASK è l’array:
.FALSE. .TRUE. .TRUE.
.TRUE. .TRUE. .FALSE.
allora l’istruzione:
MERGE(TSOURCE,FSOURCE,MASK)
produce il risultato:
8 3 5
2 4 3
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni di trasformazione (esempi)
RESHAPE(SOURCE,SHAPE[,PAD][,ORDER])
Costruisce un array di forma differente a partire da un array in input.
L’argomento SOURCE è un vettore di tipo qualsiasi. Esso fornisce gli elementi per l’array risultante. La sua estensione deve essere maggiore o uguale a PRODUCT(SHAPE) se PAD è omesso oppure se ha estensione nulla.
L’argomento SHAPE è un vettore numerico di sette elementi al massimo. Esso definisce la forma dell’array risultante. Non può avere estensione nulla ed i suoi elementi non possono essere negativi.
L’argomento opzionale PAD è un array avente stesso tipo di SOURCE.
Il suo compito è quello di fornire valori ”di riserva” nel caso in cui l’array risultante avesse ampiezza maggiore di SOURCE.
Infine, L’argomento opzionale ORDER è un array della stessa forma di SHAPE i cui elementi rappresentano una permutazione della n_pla (/1,2,...,n /), essendo n l’estensione di SHAPE. Il suo scopo è quello di modificare l’ordine di riempimento di default dell’ array risultante.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni di trasformazione (esempi)
Un semplice esempio di utilizzo della funzione RESHAPE è fornito dalla seguente istruzione:RESHAPE((/3,4,5,6,7,8/),(/2,3/))la quale fornisce come risultato la matrice:
3 5 74 6 8
mentre l’istruzione:RESHAPE((/3,4,5,6,7,8/),(/2,4/),(/1,1/))fornisce il seguente risultato:
3 5 7 14 6 8 1
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Esaminiamo un’applicazione dell’ opzione ORDER:
...
INTEGER, DIMENSION(2,5) :: myarr
REAL, DIMENSION(5,3,8) :: a
REAL, DIMENSION(8,3,5) :: b
...
myarr = &
RESHAPE((/1,2,3,4,5,6/),(/2,5/),(/0,0/),(/2,1/))
! In esito all’istruzione precedente si avrà:
! [1 2 3 4 5]
! [6 0 0 0 0]
END PROGRAM
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni topologiche (esempi)
MAXLOC(ARRAY [,DIM][,MASK])
MINLOC (ARRAY [,MASK])
Restituiscono la posizione dell’elemento di valore
massimo/minimo di un array, di una sezione di array
o lungo una specificata dimensione dell’array.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni topologiche (esempi)
L’argomento ARRAY è un array di tipo intero o reale.
Se DIM è presente, il risultato è un array di rango n-1 dove nè il rango dell’array. I valori risultanti individuano le locazioni contenenti i max/min lungo la dimensione definita da DIM.Se assente, il risultato è un array di rango 1 ed ampiezza pari al rango dell’array sorgente. I suoi elementi sono gli indici dell’elemento max/min dell’array sorgente. L’argomento opzionale MASK è un array logico conforme ad ARRAY.
Se MASK è presente, nelle operazioni di cui prima non saranno considerati gli elementi per cui risulta nell’array logico il valore FALSE.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni topologiche (esempi)
Esempi:
Il valore di MAXLOC((/3,7,4,7/)) è 2, essendo questo l’indice della posizione della
prima occorrenza del valore massimo (7) nell’array monodimensionale specificato
come argomento.
Sia mat l’array:
4 0 -3 23 1 -2 6-1 -4 5 -5
MAXLOC(mat,MASK=mat<5) fornisce il valore (/1,1/) poiché questi sono gli indici
che puntano all’elemento di valore massimo (4) fra tutti quelli minori di 5.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni di manipolazione (esempi)Esempi:
TRANSPOSE(matrice)Traspone un array di rango due.
L’argomento matrice può essere un array bidimensionale di tipo qualsiasi.
Il risultato della funzione è un array avente stesso tipo di matrice e forma (/n,m/) essendo (/m,n/) la forma dell’argomento.
L’elemento (i,j)_mo dell’array risultante coincide con il valore di matrice(j,i).
A titolo di esempio, definita la seguente matrice mat:
1 2 34 5 67 8 9
TRANSPOSE(mat) avrà valore:
1 4 72 5 83 6 9
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni algebriche (esempi)Esempi:
DOT_PRODUCT(VECTOR_A,VECTOR_B)Esegue il prodotto scalare di due vettori numerici (interi, reali o complessi) aventi stessa
dimensione.
Il risultato è uno scalare il cui tipo dipende dai vettori operandi VECTOR_A e VECTOR_B. In
particolare:
• Se l’argomento VECTOR_A è di tipo INTEGER o REAL allora il risultato avrà valore pari a
SUM(VECTOR_A*VECTOR_B).
• Se l’argomento VECTOR_A è di tipo COMPLEX, allora il risultato avrà valore pari a
SUM(CONJG(VECTOR_A)*VECTOR_B).
Se gli array operandi hanno dimensione nulla, il risultato vale zero se essi sono di tipo
numerico oppure .FALSE. se gli operandi sono di tipo logico.
Gli ARRAY in FORTRAN 90Andrea Prevete, UNINA2 - 2013
Funzioni algebriche (esempi)
Ad esempio, l’istruzione:
DOT_PRODUCT((/1,2,3/),(/3,4,5/))
restituisce il valore 26
(infatti: (1×3)+(2×4)+(3×5)=26)
Invece, l’istruzione:
DOT_PRODUCT((/(1.0,2.0),(2.0,3.0)/),(/(1.0,1.0),(1.0,4.0)/))
fornisce l’array (/17.0,4.0/).
(infatti: (1-2j)(1+j)+(2-3j)(1+4j)=(1+2-j)+(2+12+5j)=17+4j)