2012-08-03 6 views
7

Necesito una copia profunda de una matriz (real) en Fortran (90), pero no estoy seguro de cómo obtenerla, ya que no entiendo completamente cómo funcionan las referencias. Intuitivamente, yo esperaría que esto me consiga lo que quiero:Copia de gran profundidad en Fortran

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

Sin embargo, recientemente se me señaló que b(1:n) = a(1:n) es equivalente al código de seguridad. Intuitivamente, esperaría que b(1:n) = a(1:n) simplemente haga que la referencia de b(1:n) apunte a la ubicación de a(1:n) en la memoria.

¿Es b(1:n) = a(1:n) una copia profunda? ¿Por qué? ¿Qué está pasando con las referencias subyacentes en comparación con b = a?

Respuesta

13

Las tres maneras que usted menciona para las matrices de copia, el bucle do, b(1:n) = a(1:n) y b = a, son todos equivalentes; copian el contenido de la matriz a en la matriz b. a y b son simplemente matrices, no punteros de fantasía ni nada, por lo que la asignación a = b es básicamente la misma que la expresión matemática. No hay magia con las referencias en curso (que el usuario necesita saber), por lo que Fortran es un lenguaje bastante directo para aprender. Puede tener matrices de punteros en Fortran, pero este es otro problema.

M Metcalf y J Reid's Fortran 90/95 explicado es siempre una buena referencia para consultar sobre las características del lenguaje Fortran. Desde la página 48:

3,11 asignación de matriz

Por asignación intrínseca, una expresión de matriz puede ser asignado a una variable de matriz de la misma forma, que se interpreta como si se asigna a cada elemento de la expresión al elemento correspondiente de la variable. Por ejemplo, con las declaraciones

real, dimension(10, 20) :: a 

La asignación

a = a + 1.0 

reemplaza a(i,j) por a(i,j) + 1.0 para i=1,2..,10 y j=1,2,..,20.

en cuenta también que una expresión escalar puede ser asignado a una matriz, en cuyo caso el valor saclar se difunde a todos los elementos de la matriz.

En términos de cómo esto es todo realmente implementado, que es lo que creo que está manejando con su pregunta, esto no está completamente especificado por el estándar Fortran. Este tipo de cosas no se especifican para permitir que los compiladores hagan las optimizaciones que deseen. Por ejemplo, en la asignación a = b, el orden en que se copian los elementos de b en a no está especificado en el estándar, por lo que diferentes compiladores podrían hacerlo de diferentes maneras. Todo lo que necesita saber es que para esta pregunta es que, siempre que a y b no sean punteros, entonces a y b son matrices distintas y que cambiar un elemento de uno no cambia el elemento correspondiente del otro. Así que es un sentido, a=b es una "copia profunda" y puede pensar en esto como copiar todos los elementos en b en la ubicación de memoria de a.

+0

@IanH Esto no es algo de lo que yo sepa tanto, así que me centré en las matrices en mi respuesta. Sería interesante ver un ejemplo de lo anterior que no es el caso para los tipos derivados si desea publicar una respuesta. – Chris

+0

Disculpas por ese balbuceo, era una burbuja de pensamiento inconclusa que decidí que era irrelevante para la pregunta (dado que el cartel menciona específicamente variables REALES). Ni siquiera era consciente de que había sido publicado. – IanH

+1

'b (1: n) = a (1: n)' y 'b = a' no son equivalentes. El primero no verificará la reasignación necesaria, por ejemplo. –

6

a = b copia toda la matriz b en a. Si solo quiere una parte de la matriz que tiene un tamaño mayor que n, puede usar la notación de subíndice a (1: n) = b (1: n). Eso es Fortran 90 - es un lenguaje de nivel superior a FORTRAN 77. Podemos decir que "a = b" es una copia y no asociar el puntero a con el objetivo b porque esa declaración usó el operador "=". La asociación del puntero usa =>.

Editar: por copia, hace un duplicado, probablemente con el mismo código de máquina que su bucle do. La asociación del puntero hace una referencia sin hacer el ciclo do para duplicar todos los elementos de la matriz.

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

+1

¿Cómo lo copia? ¿Reponiendo la referencia de 'a' a la ubicación de' b' en la memoria, o moviendo una copia de todos los elementos en 'b' a la ubicación de' a' en la memoria? – astay13

+2

@ astay13, Fortran no es Java o C#. No tiene referencias. Tiene punteros pero aquellos usan una sintaxis especial para asociarse como M. S. B. ha señalado ('=>' en vez de '='). 'gfortran' por ejemplo implementa una copia de matriz usando' memcpy' (copia de memoria bit a bit, muy rápido) o bucles 'DO 'ocultos, dependiendo del contexto. –

+0

@HristoIliev, sí, la pregunta viene porque Java es mi primer idioma, así que estoy acostumbrado a pensar en términos de '=' que se usa para la asignación de referencia. – astay13

Cuestiones relacionadas