2012-08-03 13 views
7

Ho bisogno di una copia profonda di un array (reale) in Fortran (90), ma non sono sicuro di come ottenerne uno, poiché non capisco completamente come funzionano i riferimenti. Intuitivamente, mi sarei aspettato questo per ottenere me quello che voglio:Copia deep array in Fortran

do i=1,n 
    b(i) = a(i) 
end do 

Tuttavia, è stato recentemente mi ha fatto notare che b(1:n) = a(1:n) è equivalente al codice di cui sopra. Intuitivamente, mi aspetto che lo b(1:n) = a(1:n) faccia semplicemente in modo che il riferimento di b(1:n) indichi la posizione di a(1:n) nella memoria.

È b(1:n) = a(1:n) una copia profonda? Perché? Cosa sta succedendo con i riferimenti sottostanti in contrasto con b = a?

risposta

13

I tre modi di cui parli per le matrici la copia, il ciclo do, b(1:n) = a(1:n) e b = a, sono tutti equivalenti; copiano il contenuto dell'array a nell'array b. a e b sono semplicemente matrici, non puntatori di fantasia o altro e quindi l'assegnazione a = b è fondamentalmente la stessa dell'espressione matematica. Non c'è magia con i riferimenti in corso (che l'utente deve sapere), motivo per cui Fortran è un linguaggio piuttosto semplice da imparare. Puoi avere array di puntatori in Fortran, ma questo è un altro problema.

M Metcalf e J Reid's Fortran 90/95 ha spiegato è sempre un buon riferimento per la consultazione sulle funzionalità del linguaggio Fortran. Da pagina 48:

3,11 assegnazione Array

Con assegnazione intrinseca, un'espressione matrice può essere assegnato ad una variabile array della stessa forma, che viene interpretata come se sono stati assegnati ciascun elemento dell'espressione all'elemento corrispondente della variabile. Ad esempio, con le dichiarazioni

real, dimension(10, 20) :: a 

L'assegnazione

a = a + 1.0 

sostituisce a(i,j) da a(i,j) + 1.0 per i=1,2..,10 e j=1,2,..,20.

noti inoltre che un'espressione scalare può essere assegnato ad una matrice, nel qual caso il valore saclar viene trasmesso a tutti gli elementi dell'array.

In termini di come tutto questo è effettivamente implementato, che è quello che penso tu stia guidando con la tua domanda, questo è completamente non specificato dallo standard Fortran. Questo genere di cose non viene specificato per consentire agli autori di compilatori di fare qualsiasi ottimizzazione si sentano. Ad esempio, nell'assegnazione a = b, l'ordine in cui gli elementi di b vengono copiati in a non è specificato dallo standard, pertanto compilatori diversi potrebbero farlo in modi diversi. Tutto quello che devi sapere è che questa domanda è che, fornito a e non sono puntatori, quindi a e sono array distinti e che la modifica di un elemento di uno non modifica l'elemento corrispondente dell'altro. Quindi, in un certo senso, a=b è una "copia profonda" e puoi pensare a ciò copiando tutti gli elementi in b nella posizione di memoria di a.

+0

@IanH Questo non è qualcosa di cui so molto, quindi mi sono concentrato sugli array nella mia risposta. Sarebbe interessante vedere un esempio di ciò che non è il caso dei tipi derivati ​​se si desidera pubblicare una risposta. – Chris

+0

Ci scusiamo per questo balbettio, è stata una bolla di pensiero incompiuta che ho deciso non pertinente alla domanda (dato che il manifesto menziona specificamente variabili REALI). Non ero nemmeno consapevole del fatto che fosse stato pubblicato. – IanH

+1

'b (1: n) = a (1: n)' e 'b = a' non sono equivalenti. Il primo non controllerà la necessaria riallocazione, per esempio. –

6

a = b copia l'intero array b in a. Se si desidera solo una parte dell'array dimensionata più grande di n, è possibile utilizzare la notazione del pedice a (1: n) = b (1: n). Questo è Fortran 90 - è un linguaggio di livello superiore rispetto a FORTRAN 77. Possiamo dire che "a = b" è una copia e non associa il puntatore a con l'obiettivo b poiché tale istruzione utilizza l'operatore "=". L'associazione del puntatore utilizza =>.

Modifica: per copia, esegue un duplicato, probabilmente con lo stesso codice macchina del ciclo do. L'associazione puntatore crea un riferimento senza eseguire il ciclo do per duplicare tutti gli elementi dell'array.

Vedi http://en.wikipedia.org/wiki/Fortran_95_language_features

+1

Come lo copia? Rinunciando il riferimento di 'a' alla posizione di' b' nella memoria, o spostando una copia di tutti gli elementi in 'b' nella posizione di' a' in memoria? – astay13

+2

@ astay13, Fortran non è Java o C#. Non ha riferimenti. Ha dei puntatori, ma quelli usano una sintassi speciale da associare come ha sottolineato M. S. B. ('=>' invece di '='). 'gfortran' ad esempio implementa la copia dell'array usando sia' memcpy' (copia di memoria bit per bit, molto veloce) o 'DO' nascosti, a seconda del contesto. –

+0

@HristoIliev, sì, la domanda viene perché Java è la mia prima lingua, quindi sono abituato a pensare in termini di === essere utilizzato per l'assegnazione di riferimento. – astay13