Inicialización de arreglos de 2 variables INTEGER , DIMENSIÓN (4, 3) : : ini DO i=1, 4 DO j= 1,3 ini(i, j) = j END DO END DO i=1 1 2 3 i=2 1 2 3 i=3 1 2 3 i=4 1 2 3 j=1 j=2 j=3 Ini es de 4x3 Pero si inicializamos con: (/1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3/) 1 1 1 1 2 2 2 2 3 3 3 3 Ini es de 1x12 Aunque los 2 arreglos tienen el mismo numero de elementos, no tienen la misma forma y no pueden ser usados en la misma operación. Para transformalo está la función intrínseca RESHAPE Ej ini= RESHAPE ((/1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3/), (/4, 3/) Convierte al vector 1X12 en una matriz de 4X3 la cual es asignada a ini: INTEGER, DIMENSION (4,3) : : ini (4,3)=& RESHAPE ((/1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3/), (/4, 3/) Buena costumbre: Cuando se trabaja con matrices conservar su forma. Leerlas y escribirlas con DO o DO implícitos y al realizar operaciones→ programas mas entendibles. Matrices y subconjuntos de matrices Se puede realizar operaraciones aritméticas con dos matrices cuando son conformes o una es un escalar Ej a= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Para realizar un subconjunto de la matriz a 1 a(1, : ) = [ 1 2 3 4 5 ] 6 a( : , 1)= 11 16 21 a(1: 3, 1: 5: 2) = 1 3 5 6 8 10 11 13 15 Arreglos de mas de 2 dimensiones Ej 2x2x2 A(1,1,1) A(2,1,1) A(1,2,1) A(2,2,1) A(1,1,2) A(2,1,2) A(1,2,2) A(2,2,2) Generalizando para N dimensiones: El primer subíndice es el que se mueve mas rápidamente, un poco mas lento el segundo… el último es el más lento de todos. Esto se debe tener en cuenta para inicializar, leer o escribir….. Enmascarar : la construcción WHERE Ej: Queremos calcular el logaritmo a una matriz DO i=1, ifin DO j=1, jfin logval(i,j)= log(valor(i,j)) END DO END DO Otra forma: logva= log (valor) Pero no tubimos en cuenta si exiistia algun valor negativo o un 0 para la cual la función LOG no es válida. Para evitar ese error se deberia programar: DO i=1,ifin DO j=1,jfin IF(valor(i,j) >0.) then logval(i, j) = LOG(valor(i,j)) ELSE logval(i, j) = -99999. END IF END DO END DO A esta asignación se le dice enmascarar En FORTRAN 90 existe una función que realiza esta asignación: WHERE [nombre] WHERE ( mask_exp) Sentencias de asignación del arreglo !Bloque 1 ELSEWHERE [nombre] Sentencias de asignación del arreglo !Bloque 2 END WHERE [nombre] Si la expresión mask_exp es verdad se ejecuta el Bloque 1, en caso contrario se ejecuta el Bloque 2. Ej WHERE (valor>0) logval=LOG(valor) ELSEWHERE logval=-99999. ENDWHERE El FORTRAN 95 agrega una clausula mas al WHERE [nombre] WHERE ( mask_exp1) Sentencias de asignación del arreglo !Bloque 1 ELSEWHERE ( mask_exp2) [nombre] Sentencias de asignación del arreglo !Bloque 2 ELSEWHERE [nombre] Sentencias de asignación del arreglo !Bloque 3 END WHERE [nombre] En los FORTRAN 90/95 también es válido WHERE(mask_exp) sentencia de asignación del arreglo Analizar un conjunto de datos de entrada cuyo rango se debe encontrar entre -1000 y 1000. Si un valor no esta dentro de este intervalo asignarle el valor del límite inferior o superior según sea su signo. Usando DO e IF Usando WHERE Forall permite aplicar operaciones a elemento por elemento de una matriz o a un subconjunto , ya sea a través de los índices o/y una expresión lógica. (FORTRAN 95) En general: [nombre] FORALL (in1= icom, ifin, incr, [in2= ico, m2, ifin2, incr…..exp_log] sentencia 1 …….. sentencia n END FORALL [nombre] Ej SI se quiere conocer la inversa de una matriz de números reales FORALL(i=1:n, j=1: m , r(i,j)/=0) r(i, j) =1./ r (i, j) END FORALL FORALL puede representar un DO anidado combinado con un IF DO i= 1,n DO j=1,m IF (r (i, j)/= 0.) THEN r (i, j)=1./ r (i, j) END IF END DO END DO Cuando utilizamos las sentencias Do e IF las setencias dentro de ella se realizan en forma secuencial, en la forma seleccionada por el procesador. FORALL (i=2:n-1, j=2,m-2) a( i, j) = SQRT(a( i, j)) b( i, j) = 1./ a( i, j) END FORALL Realiza todos a( i, j) y cuando termina hace los b( i, j) FORALL (in1= icom, ifin, incr, [in2= ico, m2, ifin2, incr…..exp_log] sentencia de asignación ALLOCATABLE ARRAYS Hasta ahora el tamaño de los arreglos que hemos utilizado fue declarado junto con el nombre de la variable. Ej: INTEGER , DIMENSIÓN (4, 3) : : ini Esto se denomina STATIC MEMORY ALLOCATION. El espacio en memoria para almacenar el contenido del arreglo es siempre el mismo a lo largo de todo el programa. En algunos casos, esto puede resultar inconveniente si hay algún arreglo que interviene en nuestro programa del que no conocemos a priori el tamaño que va a tener. Para salvar este problema generalmente se definen arreglos muy grandes que eventualmente permitan ajustarse a muchas situaciones, pero esto puede ser ineficiente si no utilizamos el tamaño completo de las variables ya que estamos usando mucha memoria. Para resolver este problema, se introdujo la DYNAMIC MEMORY ALLOCATION que permite definir el tamaño de un arreglo durante la ejecución del programa. Esto hace que podamos adaptar los tamaños de los arreglos al problema específico que estamos resolviendo en cada caso. Para permitir que el tamaño de un arreglo sea asignado durante la ejecución del Programa → el atributo ALLOCATABLE en la declaración de las variables. REAL, ALLOCATABLE, DIMENSION(:) :: X ! La variable X tiene una sola dimensión Este atributo le dice al programa que el tamaño de X no será determinado en el momento de la declaración sino más adelante. Si bien no hay que especificar el tamaño, si las dimensiones, esto lo hacemos colocando un “: “. REAL, ALLOCATABLE, DIMENSION(:,:) :: X !En este otro caso X tiene 2 dimensiones. Para lograr asignarle un espacio en la memoria y poder utilizar a la variable X disponemos de la sentencia ALLOCATE. ALLOCATE ( X(10,20)) Esta sentencia le indica al programa que reserve un espacio de 10 filas por 2 columnas en la memoria para la variable X. A partir de este momento podemos utilizar la variable X como lo hacíamos antes. ALLOCATE(X(N,M)) ! Esto también es válido si N y M son 2 INTEGER. Para liberar el espacio que está ocupado por la variable X en la memoria ⇨ DEALLOCATE DEALLOCATE ( X ) IMPORTANTE ⇨ después de haber hecho esto no podremos acceder más a la variable X, su contenido se ha perdido. EJ: Tipiar y compilar el siguiente programa, ejecutarlo mirando como varía la memoria utilizada por el sistema con el monitor del sistema de windows. PROGRAM pepe REAL, ALLOCATABLE, DIMENSION(:,:) :: X WRITE(*,*)"Antes de asignar a X espacio en memoria, presione enter" READ(*,*) ALLOCATE(X(50000,1000)) WRITE(*,*)"X ya está en la memoria de la máquina, presione enter" READ(*,*) DEALLOCATE(X) WRITE(*,*)"X fue eliminado de la memoria de la máquina" STOP END PROGRAM pepe