Fortran90 - Grupo de Paralelismo
Transcripción
Fortran90 - Grupo de Paralelismo
Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación Fortran90 24−25 de junio de 2002 Francisco de Sande [email protected] Dpto. de Estadística, I.O. y Computación Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Presentación Nombre Campo de trabajo Experiencia en informática Módulos del curso que ha realizado Motivación que le ha llevado a matricularse Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 1 Introducción Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Introducción Índice 1.1 Historia 1.2 Objetivos 1.3 Principales características 1.4 Otras características 1.5 Disponibilidad de compiladores 1.6 Referencias 1.7 Lista de recursos 1.8 Convenios de codificación Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Historia FORmula TRANslation 1954 Fortran I 1958 Fortran II 1958 Fortran IV 1966 Fortran 66 standard 1978 Fortran 77 standard 1991 Fortran 90 standard La próxima revisión se espera que ocurra dentro de unos 10 años Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Objetivos de Fortran 90 Evolucionar el lenguaje Características obsoletas Estandarizar las extensiones de las diferentes compañías Portabilidad Modernizar el lenguaje Facilitando su utilización a través de nuevas características como los tipos derivados o el formato libre Introducción de gestión de memoria dinámica Modularización a través de la definición de los módulos Portabilidad numérica a través de la selección de precisión Sentencias case, exit, cycle Sobrecarga de operadores Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Objetivos del lenguaje Proporcionar capacidad de paralelismo de datos Operaciones paralelas sobre vectores para una mejor utilización de procesadores vectoriales y máquinas paralelas Compatibilidad con Fortran77 Fortran77 es un subconjunto de Fortran90 Mejorar la seguridad Reduciendo el riesgo de errores en códigos estándar Concordancia con el estándar Los compiladores han de notificar códigos no estándar y características anticuadas Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Principales Características Proceso de vectores Memoria dinámica Módulos Procedimientos: Parámetros opcionales y parámetros con nombre Procedimientos internos Procedimientos recursivos Punteros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Otras Características Formato del código fuente Especificaciones / implicit none Tipos de datos parametrizados (kind) Tipos derivados y sobrecarga de operadores Estructuras de control Nuevas funciones intrínsecas Nuevas características de entrada/salida Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Características obsoletas Fortran90 sigue manteniendo algunas características que califica de obsoletas. Pueden ser eliminadas en la siguiente revisión del lenguaje: http://www.ccti.ull.es/cpu/f90/f90_reference_manual_a.txt if aritmético Variables real y double en bucles do y expresiones de control Terminación del do con sentencias distintas de continue o end do Sentencias assign y goto asignadas Especificadores asignados en sentencias format Saltos a un end if desde dentro de un bloque if return alternado Sentencia pause Descriptor H edit Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Disponibilidad Compiladores de Fortran90 Where can I get a f95 compiler? http://www.physics.ohio−state.edu/~wilkins/computing/f95.html http://www.fortran.com/fortran/metcalf.htm Cray CF90 − YMP vectorización. Mensajes limitados y algunas funciones intrínsecas no están bien ajustadas DEC Fortran90 − DEC OSF/1. Incluye extensiones HPF http://www.ccti.ull.es/cpu/f90/f90.htm EPC Fortran90 − SPARC Solaris, IBM RS/6000, Intel 3/486, Motorola 88000 IBM XLF V3 − RISC System 6000 Lahey − Fujitsu LF90 − Para DOS y Windows http://www.lahey.com/ Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Disponibilidad Microway − DOS, OS/2, Unix NA Software F90+ − 386/486, Sparc, T800, T9000 Portland Group http://www.pgroup.com/ NAG f90 − Diversas plataformas Unix y VAX/VMS. Utiliza C como lenguaje intermedio http://www.nag.com/nagware.asp Pacific Sierra VAST−90 − Utiliza Fortran77 como lenguaje intermedio Parasoft − F77 como lenguaje intermedio Absoft http://www.cs−software.com/software/fortran/absoft/absoft.html Salford FTN90 − Implementación para PC s del NAG f90. Genera código directamente Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Referencias Bibliografía y Referencias Adams, J. C. et. al. (1992) Fortran 90 Handbook. McGraw−Hill. ISBN 0−07−000406−4 Brainerd, W. S. et. al., (1994) Programmer’s Guide to Fortran 90. 2nd edition , Unicomp. ISBN 0−07−000248−7 Counihan, M. (1991) Fortran 90. Pitman. ISBN 0−273−03073−6 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Referencias Bibliografía y Referencias Hahn, B. D. (1994) Fortran 90 for Scientists and Engineers. Edward Arnold. ISBN: 0−340− 60034−9 Kerrigan, J. (1993) Migrating to Fortran 90. O’Reilly and Associates. ISBN 1−56592−049− X Metcalf, M. & Reid, J. (1992) Fortran 90 Explained. Oxford University Press. ISBN: 0− 19−850558−2 Morgan, J. S. & Schonfelder, J. L. (1993) Programming in Fortran 90. Alfred Waller Ltd. ISBN 1−872474−06−3 Smith, I M. Programming in Fortran 90. Wiley. 0471−94185−9 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Referencias Bibliografía y Referencias Este Curso http://webpages.ull.es/~fsande/doctorado/curso_doc.html Recursos sobre Fortran: http://webpages.ull.es/~fsande/doctorado/curso_doc.html http://www.csi.ull.es/~sande/compi2/recursos.html Pueden encontrar: FAQ Cursos y tutoriales Grupos de discusión Repositorios de software Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Convenios de codificación Reservar las mayúsculas solo para constantes. Utilizaremos minúsculas para las palabras reservadas. Indentar 2 columnas en el cuerpo de las unidades de programa, bloques interface, bucles do, bloques if, bloques case, etc. Incluir siempre el nombre del programa, subrutina o función en su sentencia end En las sentencias use utilizar la cláusula only para documentar explícitamente todos los elementos que son accedidos desde ese módulo En sentencias call y referencias a funciones utilizar parámetros con nombre para los parámetros opcionales Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Conexión al sistema telnet teide.ccti.ull.es login: ic2aluXX passwd: ihiu2001 /usr/local/bin/tcsh home> mkdir f90 home> cd f90 home/f90> cp /tmp/inicio.tar . home/f90> tar xvf inicio.tar home/f90> cd inicio home/f90> f90 hola.f90 home/f90> ls −l home/f90> ./a.out home/f90> man f90 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 2 Código Fuente, Tipos y Estructuras de Control Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Código Fuente, Tipos y Estructuras de Control Índice 2.1 Formato del código fuente 2.2 Especificaciones 2.3 implicit none 2.4 Valores de clase (Kind) 2.5 Tipos derivados 2.6 Sentencias de control 2.7 Ejercicios Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Código Fuente Las líneas pueden tener hasta 132 caracteres Se permiten letras minúsculas Identificadores hasta 31 caracteres (incluyendo el subrayado, underscore) (El primer carácter ha de ser una letra). Usar identificadores significativos!! Se usa punto y coma (;) para separar diferentes sentencias en la misma línea Los comentarios pueden comenzar con exclamación (!) El Ampersand (&) se usa como signo de continuación El juego de caracteres incluye +<>;!?%−“ & Nuevos operadores relacionales: < <= == /= >= > Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Código Fuente Ejemplo: program programa_en_formato_libre !nombres largos con subrayado ! No hay columnas especiales implicit none !Mayúsculas y minúsculas real :: tx, ty, tz !Comentario final !Varias sentencias por línea tx = 1.0; ty = 2.0; tz = tx * ty; !Las líneas se pueden partir print *, & tx, ty, tz end program programa_en_formato_libre Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Especificaciones Una especificación es una forma (extendida) de declaración donde se colocan juntas todas las características de una entidad tipo [ [, atributo ] ... :: ] lista El tipo puede ser integer, real, complex, logical o character con un valor de clase opcional: integer [([kind=]kind−value)] character [(actual−parameter−list)] type (type−name) El atributo puede ser parameter private target dimension(extent−list) optional external public pointer allocatable intent(inout) save intrinsic Se pueden inicializar variables en las especificaciones Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Especificaciones Ejemplos real :: a = 2.61828, b = 3.14159 ! Dos variables reales declaradas e ! inicializadas integer, parameter :: N = 100, M = 1000 ! Declaración e inicialización de dos ! constantes enteras character (len = 8) :: ch ! Declaración de una cadena de caracteres ! de longitud 8 integer, dimension(−3:5, 7) :: ia ! Declaración de un vector de enteros con ! límite inferior negativo integer, dimension(−3:5,7) :: ia, ib, ic(5,5) ! Vectores de 9x7 componentes ! Los índices de ic varían en [1,5] [1, 5] Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 implicit none En Fortran77 los tipos implícitos permiten la utilización de variables no declaradas. Esto ha sido la causa de muchos errores de programación implicit none obliga a declarar todas las variables que se utilizan en un programa implicit none puede ir precedida en una unidad de programa solamente por sentencias use y format Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Valores de clase Hay 5 tipos intrínsecos: real, integer, complex, character y logical Cada tipo puede tener asociado un valor entero no negativo llamado el parámetro de clase de tipo (Kind). El parámetro de clase es un entero no negativo. Se trata de una característica útil para escribir código portable que requiera una precisión numérica determinada Los valores de clase dependen de la máquina en cuestión, pero todo procesador ha de soportar al menos 2 clases para real y complex y 1 para integer, logical y character Hay diversas funciones intrínsecas para obtener y establecer los parámetros de clase Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Valores de clase real real (kind=wp)::ra real(wp)::ra ! o bien: Declara una variable, ra, cuya precisión está determinada por el parámetro de clase wp Los valores de clase son dependientes del sistema Una variable real de 8 bytes (64 bits) habitualmente tiene un valor de clase 8 ó 2 Una variable real de 4 bytes (32 bits) habitualmente tiene un valor de clase de 4 ó 1 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Valores de clase La función intrínseca kind, que tiene un parámetro de cualquier tipo intrínseco devuelve la clase de tipo de su parámetro. Por ejemplo: real(kind = 2) :: x ! x declarada de clase de tipo 2 real :: y ! y declarada de clase de tipo ! por defecto integer :: i,j i = kind(x) ! i=2 j = kind(y) ! j tiene el valor por ! defecto de los reales ! El valor de j depende ! del sistema Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Valores de clase real La función intrínseca selected_real_kind tiene dos parámetros enteros opcionales, p y r El valor p especifica el número de dígitos decimales y r especifica el mínimo rango de exponente que se desea La función selected_real_kind (p, r) devuelve el valor de clase que se ajusta o que excede los requisitos dados por p y r. Si más de un valor de clase satisface los requisitos el valor que se devuelve es el que tenga la mínima precisión decimal. Si la precisión no está disponible se retorna −1. Si el rango no está disponible, −2 http://www.ccti.ull.es/cpu/f90/f90_reference_manual_9.txt Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Valores de clase real El uso de kind con esta función da una gran portabilidad: integer, parameter ::idp=kind(1.0D) real(kind=idp) ::ra La variable ra se declara de doble precisión. Nótese que el valor de clase depende del sistema integer, parameter :: IDP = kind(1.0D) complex (kind=IDP) :: raiz1, raiz2 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Valores de clase integer Los enteros habitualmente tienen 16, 32 ó 64 bits Para declarar un entero de forma que dependa del sistema, indique el valor de clase asociado con el rango de enteros que se desea: integer, parameter :: & I8=selected_INT_kind(8) integer(kind=I8) :: ia, ib, ic Las variables ia, ib, ic tomarán valores en el rango de al menos [−108, 108] si lo permite el procesador Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Valores de clase program mayores implicit none integer, parameter :: & I8 = selected_INT_kind(8) integer(kind=I8) :: ia print *, huge(ia), kind(ia) end program mayores Este código imprime el mayor entero disponible para este tipo de enteros, y su valor de clase integer, parameter :: & I10 = selected_real_kind(10, 200) real(kind=I10) :: a print *, range(a), precision(a), kind(a) Imprime el rango del exponente, los dígitos de precisión y el valor de clase de la variable a Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Tipos derivados Son definidos por el usuario Pueden contener diferentes tipos intrínsecos (básicos) y otros tipos derivados Las componentes se acceden usando el símbolo (%) El único operador predefinido para tipos derivados es el de asignación (=) Se pueden (re)definir operadores (los estudiaremos con la sobrecarga de operadores) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Tipos derivados Ejemplos: Definición de la forma del tipo derivado: type matricula character (len=2) :: letra integer :: numero character (len=2) :: prov end type matricula Declaración de variables de ese tipo: type(matricula) :: coche1, coche2 matricula :: coche1 !Incorrecto! Asignar un valor constante a coche1: coche1 = matricula( AG’, 2227, TF’) Uso de % para asignar una componente de coche2: coche2%letra = BZ’ Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Tipos derivados Ejemplos: Definir un vector de un tipo derivado: type (matricula), dimension(n) :: coches Definir un tipo derivado conteniendo otro: type household character (len=1) :: name character (len=50) :: address type(matricula) :: car end type household Declarar una estructura de tipo household: type(household) :: myhouse Utilizar % para referenciar una componente letra: myhouse%car%letra = BZ Una constante de un tipo derivado: type puntos::origin=puntos(0.0, 0.0, 0.0) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control Fortran 90 posee tres constructores de bloque: if do case Todos ellos pueden ser anidados y puede dárseles nombres para incrementar la legibilidad y fiabilidad Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control if La Forma general de un if es: [name:] if (logical expression) then block else if (logical expression) then [name] block]... [else [name] block] end if [name] Ejemplo: seleccion: if (i < 0) then call negativo else if (i==0) then seleccion call cero else select call positivo end if seleccion Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control Bucles do Forma general: [name:] do [control clause] block end do [name] La cláusula de control puede ser: Una cláusula de control de iteración count = inicial, final [, incr] una cláusula de control while while (expr. logica) ninguna Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control Bucles do Clausula de control de iteración: fils: do i = 1, n cols: do j = 1, m a(1, j) = i + j end do cols end do fils Cláusula de control while: cierto: do while (i <= 100) ... Body of loop ... end do true Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control Bucles do Uso de exit y cycle: Se sale de un bucle con exit cycle transfiere control al end do exit y cycle, por defecto se refieren al bucle más interno pero pueden referirse a un bucle con nombre Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control Bucles do Uso de exit y cycle: exter: do i = 1,n interm: do j = 1,m intern: do k = 1,l ... if (a(i,j,k)<0) exit exter if (j==5) cycle interm ! Salta fuera ! Omite j==5 y ! hace j=6 if (i==5) cycle ! Salta el resto ! Del bucle interno ! Y pasa a su ! Siguiente iteración ... end do intern end do interm end do exter Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control Bucles do Sin cláusula de control: do read(*, *) x if (x < 0) exit y = sqrt(x) ... end do Nótese que esta forma puede tener el mismo efecto que un bucle do−while Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control case Es una forma estructurada de seleccionar diferentes opciones, dependiendo del valor de una única expresión Sirve para reemplazar a: Un goto calculado (Fortran77) Repetidos if ... then ... else Forma General: [name:] select case (expression) [case (selector)[name] block] . . . end select [name] Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control case La expresión ha de ser de tipo character, logical o integer El selector ha de ser default o bien uno ó más valores del mismo tipo que la expresión: Un único valor Un rango de valores separados por : (solamente integer o character) Una lista de valores o rangos. El valor mayor o menor del rango puede omitirse Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructuras de Control case Ejemplo: colour: select case (ch) case ( C , D , G : M ) colour = red case ( X :) colour = green case default colour = blue end select colour Por compatibilidad con Fortran77, la sentencia goto sigue estando disponible, pero es preferible usar if, do, case, exit y cycle en su lugar Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 3 Procedimientos y Módulos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos y Módulos Índice 3.1 Unidades de programa 3.2 Procedimientos 3.3 bloques interface 3.4 Procedimientos internos 3.5 Argumentos procedurales 3.6 Cláusula result para funciones 3.7 Funciones que devuelven vectores 3.8 Procedimientos recursivos 3.9 Procedimientos genéricos 3.10 Módulos 3.11 Sobrecarga de operadores 3.12 Definición de operadores 3.13 Sobrecarga del operador de asignación 3.14 Ámbito 3.15 Estructura de los programas 3.16 Ejercicios Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Unidades de Programa Programa Principal Módulo Procedimiento Externo Procedimientos de módulo Procedimientos Internos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Unidades de programa Un programa sólo puede tener un único programa principal y todas las unidades de programa que se desee (módulos o procedimientos externos) Un módulo se utiliza para que diferentes programas compartan código (datos y subrutinas) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Programa Principal Forma: program nombre_de_programa [sentencias_de_especificación] [sentencias_ejecutables] ... end [program [nombre_de_programa]] Ejemplo: program prueba ... ... ! end ! end program end program prueba Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Llamamos procedimientos de forma genérica a Funciones y Subrutinas Una función devuelve un único resultado y no suele modificar los valores de sus parámetros. Las subrutinas realizan tareas generalmente más complejas y retornan valores a través de sus parámetros Estructuralmente los procedimientos pueden ser: Externos (autocontenidos, no necesariamente Fortran) Internos (dentro de una unidad de programa) de Módulo (miembros de un módulo) Fortran 77 sólo tiene procedimientos externos Un bloque interface se utiliza para definir los detalles de los parámetros de un procedimiento. Es obligatorio para los procedimientos externos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Externos Forma: subroutine nombre(parámetros_formales) [sentencias_de_especificación] [sentencias_ejecutables] ... end [subroutine [nombre]] O bien: function nombre(dummy−argument−list) [sentecias_de_especificación] [sentecias_ejecutables] ... end [function [nombre]] Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Internos Cualquier unidad de programa (un programa principal, un módulo o un procedimiento externo) puede contener procedimientos internos Los procedimientos internos se colocan todos juntos al final de una unidad de programa y precedidos por la sentencia contains Tienen la misma forma que los procedimientos externos excepto en que la palabra subroutine/function ha de aparecer en la sentencia end Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Internos Las variables definidas en la unidad de programa permanecen accesibles (definidas) en los procedimientos internos, a menos que se redefinan allí Es una buena práctica declarar todas las variables que se utilicen en un subprograma (parámetros y variables locales) No se permite anidar procedimientos internos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Internos Ejemplo: program principal implicit none real :: a, b, c real :: suma_ppal ... suma_ppal = suma() ... contains Tiene efecto sobre todos los proc. internos que contenga function suma() real :: suma ! a, b y c ya definidas suma = a + b + c end function suma ... end program principal Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos internos implicit none en una unidad de programa también tiene efecto sobre todos los procedimientos internos que contenga. No obstante, se recomienda volver a usarlo, tanto por claridad como para evitar errores: subroutine aritmetica(n,x,y,z) implicit none integer :: n real, dimension(100) :: x, y, z ... contains function suma(a, b, c) result(sum) implicit none real, intent(in) :: a, b, c real :: sum sum = a + b + c end function suma end subroutine aritmetica Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Bloques interface Si se suministra explícitamente una interface para un procedimiento, el compilador puede comprobar inconsistencias en los parámetros En el caso de los subprogramas intrínsecos, los subprogramas internos y los módulos, el compilador conoce siempre esta información y se dice que es explícita Cuando se invoca un subprograma externo, esta información no está disponible y se dice que es implícita Fortran90 utiliza los bloques interface para especificar una interface explícita para los procedimientos externos Hay que utilizar siempre bloques interface en las unidades de programa que invoquen procedimientos externos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Bloques interface Forma general: interface cuerpo_de_la_interface ... end interface !Ojo: no se pone nombre Donde cuerpo_de_la_interface es una copia exacta de la especificación del subprograma, su especificación de argumentos y su sentencia end Ejemplo: interface real function func(x) real, intent(in) :: x end function func end interface !Lo veremos El bloque interface se coloca en la unidad de programa que realiza la llamada Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Argumentos − Intent Sirve para especificar si un parámetro de un procedimiento es para: Entrada (in) (No puede ser modificado) Salida (out) o ambos (inout) Ejemplos integer, intent(in) :: x real, intent(out) :: y real, intent(inout) :: Z subroutine interc_real(a, b) implicit none real, intent(inout) :: a, b real :: temp temp = a a = b b = temp end subroutine interc_real ! llamada: call interc_real(x, y) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Parámetros con nombre Se utiliza para evitar confusión cuando un procedimiento tiene varios parámetros. Evita el tener que recordar el orden de los parámetros. Ejemplo: Si se tiene la función real function area(inicio, fin, error) implicit none real, intent(in) :: inicio, fin, error ... end function area La llamada podría hacerse: a = area(0.0, 100.0, 0.01) b = area(inicio=0.0, error=0.01, fin=100.0) c = area(0.0, error=0.01, fin=100.0) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Parámetros con nombre Una vez que se usa un nombre para uno de los parámetros, el resto de parámetros han de usarlo también. Así no es posible: c=area(0.0, error=0.01, 100.0) !prohibido Aquí no se necesita una interface porque area es una función interna. Sí haría falta si se tratara de un procedimiento externo con parámetros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Argumentos opcionales En ciertas ocasiones, no todos los parámetros necesitan estar presentes en una llamada. Un parámetro se puede declarar como opcional: real function area(inicio, fin, error) implicit none real, intent(in), optional :: inicio, & fin, error ... end function area La llamada podría realizarse: a=area(0.0, 100.0, 0.010) b=area(inicio=0.0, fin=100.0, error=0.01) c=area(0.0) d=area(0.0, error=0.01) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Parámetros opcionales La función lógica (intrínseca) present se utiliza para comprobar la presencia de un parámetro opcional: real function area(inicio, fin, error) implicit none real,intent(in),optional ::inicio, & fin, error real ttol ... if (present(error)) then ttol = error else ttol = 0.01 end if end function area No se podría modificar error, porque es intent(in). Por ello se usa una variable local, ttol Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Parámetros opcionales Si el procedimiento es externo y tiene parámetros opcionales, se ha de suministrar una interface. Si la función del ejemplo anterior fuera externa sería necesario el siguiente bloque interface: interface real function area(inicio, fin, error) real, intent(in),optional :: inicio,& fin, error end function area end interface Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Tipos derivados como Argumentos Los parámetros de un procedimiento pueden ser de un tipo derivado si: 1.− El procedimiento es interno a la unidad de programa en la que se define el tipo derivado 2.− el tipo derivado se define en un módulo que es accesible desde el procedimiento Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Parámetros procedurales En Fortran77 un parámetro procedural se ha de declarar como external En Fortran90 un procedimiento que es pasado como parámetro debe ser un procedimiento externo o un procedimiento de módulo No se permite pasar como parámetro un procedimiento interno Para procedimientos externos se recomienda suministrar un bloque interface en la unidad de programa que realiza la llamada Un procedimiento de módulo tiene una interface explícita por defecto Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Argumentos procedurales Ejemplo: La unidad de programa que realiza la llamada: ... interface real function func(x, y) real, intent(in) :: x, y end function func end interface ... call area(func, inicio, fin, error) La función externa: real function func(x, y) implicit none real, intent(in) :: x, y ... end function func Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Cláusula result para funciones Las funciones pueden tener una variable resultado. El identificador de resultado que se utilice dentro de la función ha de ser especificado entre paréntesis al final de la sentencia function. Ejemplo: function suma(a, b, c) result(sum_abc) implicit none real, intent(in) :: a, b, c real :: sum_abc sum_abc = a + b + c end function suma Las funciones directamente recursivas (la recursividad se estudia más adelante) han de tener una variable result Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones que devuelven vectores El resultado de una función no tiene porqué ser un escalar. El tipo de una función que devuelve un vector no se especifica en la sentencia function inicial sino en una declaración de tipo en el cuerpo de la función, en la que hay que especificar las dimensiones del vector: function suma_vec (a, implicit none real, dimension (n) integer, intent(in) real,dimension (n), b b, n) :: suma_vec :: n intent(in) :: a, do i = 1, n suma_vec(i) = a(i) + b(i) end do end function suma_vec Si la función fuera externa, habría que especificar una interface en el programa llamador Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Recursivos Los procedimientos se pueden invocar recursivamente: P1 invoca a P2 y P2 invoca a P1 o bien P1 invoca directamente a P1 (se requiere result) Los procedimientos recursivos han de declararse como tales: recursive function fact(n) result (res) implicit none integer intent(in) :: n integer :: res if (n == 1) then res=1 else res=n * fact(n − 1) endif end function fact ¡La recursividad es Ineficiente! Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Genéricos Cuando se utilizan proc. genéricos, se usa un mismo identificador para el procedimiento y el código que se ejecuta depende del tipo de los parámetros (como en C++) Un procedimiento genérico se define utilizando un bloque interface y usando un identificador genérico para todos los procedimientos definidos dentro de ese bloque interface La forma general es: interface generic_name cuerpo_especifico_de_la_interface cuerpo_especifico_de_la_interface ... end interface Todos los procedimientos de un bloque interface genérico han de diferenciarse de forma no ambigua y por lo tanto todos han de ser subrutinas o todos funciones Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Genéricos Ejemplo: subroutine interc_real implicit none real, intent(inout) :: a, b real :: temp temp = a a = b b = temp end subroutine interc_real subroutine interc_int implicit none integer, intent(inout) :: a, b integer :: temp temp = a a = b b = temp end subroutine interc_int Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Genéricos Interface genérica: interface intercambia subroutine interc_real (a, b) real, intent(inout) :: a, b end subroutine interc_real subroutine interc_int (a, b) integer, intent(inout) :: a, b end subroutine interc_int end interface Llamada: call intercambia(x, y) Vea un ejemplo en ej2_modules/ejemplos/ generic_intercambia.f90 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos Se trata de una característica del lenguaje que incide (positivamente) sobre la estructura de los programas Constituyen una forma de compartir datos y/o procedimientos entre diferentes unidades de programa Los módulos juegan un papel importante en la definición de tipos y operadores asociados La forma general es: module nombre [sentecias_de_especificación] [sentecias_ejecutables] [contains procedimientos_de_módulo] end [module [nombre]] Al módulo se accede a través de la sentencia use Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos: Datos globales En Fortran las variables son habitualmente entidades locales. Utilizando módulos es posible hacer accesibles un conjunto de datos a diferentes unidades de programa: module globales real, save :: a, b, c integer, save :: i, j, k end module globales El atributo save permite declarar datos como globales (es un sustituto del COMMON de Fortran77) Los datos se utilizan en otras unidades de programa a través de la sentencia use: use globales La sentencia use no es ejecutable y debe aparecer al principio de la unidad de programa antes que cualquier otra sentencia y después de program, function o subroutine Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos: Datos globales Una unidad de programa puede invocar código de diferentes módulos utilizando una serie de sentencias use. Nótese que un módulo puede usar a su vez otros módulos, pero un módulo no puede usarse a sí mismo (ni directa ni indirectamente) Ejemplos de uso de la sentencia use: use globales ! Permite acceder a todas las variables ! del módulo use globales, only : a, c ! Permite acceder sólo a las variables a ! y c use globales, r=>a, s=>b ! Permite acceder a las variables a y b ! a través de los identificadores r y s Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos: Procedimientos de módulo Los procedimientos que se especifican dentro de un módulo se llaman procedimientos de módulo Son procedimientos que pueden ser accedidos (utilizados) por otras unidades de programa Puede haber varios procedimientos de módulo contenidos en el mismo módulo Han de estar codificados en Fortran (los externos pueden estar en otro lenguaje) Tienen la misma forma que los procedimientos externos salvo que: Los procedimientos de un módulo deben aparecer después de una sentencia contains La sentencia end ha de tener especificada una subroutine o function Se invocan mediante la sentencia call o referencia a la función, pero sólo desde una unidad de programa que haya declarado con una sentencia use la utilización del módulo en cuestión Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos: Procedimientos de módulo Los procedimientos de módulo son especialmente útiles para un conjunto de tipos derivados y sus correspondientes operaciones module modulo_puntos type puntos real :: x, y end type puntos contains function suma_puntos(p, q) type (puntos), intent(in) :: p, q type (puntos) :: suma_puntos suma_puntos%x = p%x + q%x suma_puntos%y = p%y + q%y end function suma_puntos end module modulo_puntos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos: Procedimientos de módulo El programa principal podría declarar: use modulo_puntos type (puntos) :: px, py, pz ... pz = suma_puntos(px, py) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos: Procedimientos genéricos La utilización de módulos permite parámetros de tipos derivados y por tanto procedimientos genéricos con tipos derivados Veamos como ejemplo, una extensión del procedimiento intercambia genérico que hemos desarrollado, para intercambiar puntos: Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos module intercambio_generico implicit none type puntos real :: x, y end type puntos interface intercambia module procedure interc_real, & interc_int, interc_log, interc_puntos end interface contains subroutine interc_puntos (a,b) implicit none type (puntos), intent(inout) :: a, b type (puntos) :: temp temp = a a = b b = temp end subroutine interc_puntos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos subroutine interc_real implicit none real, intent(inout) :: a,b real :: temp temp = a a = b b = temp end subroutine interc_real ! Rutinas similares para intercambiar ! otros tipos de datos ... end module intercambio_generico Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos: Private y Public Por defecto, todas las entidades de un módulo son accesibles a las unidades de programa que utilicen la sentencia use A veces interesa prohibir el uso de ciertas entidades al programa llamador para forzar al usuario a utilizar las rutinas del módulo en lugar de las suyas propias o también para permitir flexibilidad a la hora de realizar cambios internos sin necesidad de informar a los usuarios del módulo o cambiar la documentación Esto se consigue a través de la sentencia private: private :: sub1, sub2 o el atributo private: integer, private, save :: fil, col Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Sobrecarga de operadores En Fortran90 se puede extender el significado de un operador intrínseco para que actúe sobre tipos de datos adicionales: a ello se le llama sobrecarga de operadores. Para conseguirlo se necesita un bloque interface de la forma: interface operator (op_intrinseco) cuerpo_de_la_interface end interface Por ejemplo, el operador + podría extenderse a variables de tipo carácter para concatenar dos cadenas de caracteres ignorando los espacios sobrantes, y el código podría colocarse en un módulo: Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Sobrecarga de operadores Ahora la expresión cha + chb tiene significado en cualquier programa que use este módulo Obsérvese en el ejemplo el bloque interface. La función que define el operador está en un módulo y no es necesario tener interfaces explícitas para procedimientos de módulo que están dentro del mismo módulo Cuando se da un nombre genérico o un operador para un conjunto de procedimientos, se necesita un bloque de interface. El bloque interface tiene la forma: interface ... lista_de_procedimientos_de_modulo end interface Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Definición de operadores Se pueden definir nuevos operadores Resulta especialmente útil para tipos definidos por el usuario Los operadores definidos han de tener . (punto) al principio y al final. Por ejemplo, en el ejemplo anterior podríamos haber definido .mas. en lugar de sobrecargar + La operación se ha de definir a través de una función que tenga uno o dos parámetros no opcionales con atributo intent(in) (que sean de entrada) Veamos un Ejemplo: calcular la distancia euclídea entre dos elementos del tipo derivado punto: Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Definición de operadores: distancia_principal.f90 program principal implicit none use distancia_mod type(puntos) :: px, py ... distancia = px .dist. py ... end program principal Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Definición de operadores: distancia_mod.f90 module distancia_mod implicit none ... type puntos real :: x, y end type puntos ... interface operator (.dist.) module procedure calcdist end interface ... contains ... function calcdist (px, py) implicit none real :: calcdist type (puntos), intent(in) :: px, py calcdist = & sqrt ((px%x−py%x)**2 +(px%y−py%y)**2 ) end function calcdist ... end module distancia_mod Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos mon_mod.f90 Veamos otro ejemplo que define en un módulo un tipo derivado y todas las operaciones asociadas: module dineros implicit none type pasta integer :: euros, cents end type pasta interface operator (+) module procedure sumar_pasta end interface interface operator (−) module procedure negar_pasta, resta_pasta end interface Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos mon_mod.f90 contains function sumar_pasta(a, b) implicit none type (pasta) :: sumar_pasta type (pasta), intent(in) :: a ,b integer :: acarreo, tmp_cents tmp_cents = a%cents + b%cents acarreo = 0 if (tmp_cents > 100) then tmp_cents = tmp_cents − 100 acarreo = 1 end if sumar_pasta%euros=a%euros + & b%euros+acarreo sumar_pasta%cents = tmp_cents end function sumar_pasta Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos mon_mod.f90 function negar_pasta(a) implicit none type (pasta) :: negar_pasta type (pasta), intent(in) :: a negar_pasta%euros = −a%euros negar_pasta%cents = −a%cents end function negar_pasta Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Módulos mon_mod.f90 function resta_pasta(a, b) implicit none type (pasta) :: resta_pasta type (pasta), intent(in) :: a, b integer :: tmp_euros, tmp_cents, acarreo tmp_cents = a%cents − b%cents tmp_euros = a%euros − b%euros ! Para incorporar acarreos necesarios if ((tmp_cents < 0).and.(tmp_euros > 0)) then tmp_cents = 100 + tmp_cents tmp_euros = tmp_euros − 1 else if ((tmp_cents>0).and.(tmp_euros<0)) then tmp_cents = tmp_cents − 100 tmp_euros = tmp_euros + 1 end if resta_pasta%cents = tmp_cents resta_pasta%euros = tmp_euros end function resta_pasta end module dineros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Sobrecarga del operador de asignación Al usar tipos derivados puede ser necesario extender el significado del operador de asignación (=) real :: ax type (puntos) :: px ... ax = px ! Se asigna un punto a un real ... ! No es válido si no se define Siguiendo con el ejemplo, supongamos que queremos que ax tome el valor máximo de las componentes de px. Esta asignación se ha de hacer a través de una subrutina con 2 parámetros no opcionales, el primero de ellos intent(out) o intent(inout) y el segundo intent(in). Debe crearse un bloque interface de asignación: interface assignment (=) cuerpo_de_la_subrutina_interface end interface Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Sobrecarga del operador de asignación La definición de la asignación se podría colocar en un módulo como: module mod_sobrecarga_assign implicit none type puntos real :: x, y end type puntos ... interface assignment (=) module procedure assign_puntos end interface contains subroutine assign_puntos (ax, px) real, intent(out) :: ax type (puntos), intent(in) :: px ax = max(px%x, px%y) end subroutine assign_puntos ... end module mod_sobrecarga_assign Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Sobrecarga del operador de asignación El programa principal necesita invocar a este módulo con una sentencia use: use mod_sobrecarga_assign real :: ax type (puntos) :: px ... ax = px ! Correcto Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ámbito El ámbito de un identificador (de variable, función, subrutina) o etiqueta es el conjunto de entidades no−solapadas donde el identificador o etiqueta puede utilizarse sin ambigüedad Estas entidades (unidades de ámbito) son: Una definición de tipo (derivado) Un cuerpo de interface de procedimiento, excluyendo las definiciones de tipos y cuerpos de interface definidos dentro de él Una unidad de programa o procedimiento interno, excluyendo las definiciones de tipos, cuerpos de interfaces y subprogramas contenidos en él Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ámbito Etiquetas Cada subprograma, interno o externo tiene su propio conjunto de etiquetas. La misma etiqueta puede usarse en un programa principal y sus procedimientos internos sin ambigüedad. Por lo tanto el ámbito de una etiqueta es un programa principal o un procedimiento excluyendo cualquier procedimiento interno que pueda contener Identificadores El ámbito de un identificador declarado en una unidad de programa se extiende desde desde su cabecera hasta su sentencia end El ámbito de un identificador declarado en un programa principal o subprograma externo se extiende a todos los subprogramas que contenga a menos que el mismo identificador se redefina en ellos El ámbito de un identificador declarado en un subprograma interno es sólo el propio subprograma y no otros subprogramas internos. Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ámbito Identificadores El ámbito del identificador de un subprograma interno, y del número y tipo de sus parámetros se extiende a través de la unidad de programa en que está contenido y por lo tanto a todos los otros subprogramas internos El ámbito de un identificador declarado en un módulo se extiende a todas las unidades de programa que use(n) ese módulo, a menos que el identificador tenga atributo private o que sea renombrado en el programa que usa el módulo o que la sentencia use tenga una cláusula use only El ámbito de un identificador declarado en un módulo se extiende a todos los subprogramas internos excepto aquellos en los que el identificador sea redefinido Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ámbito Consideremos las unidades de ámbito señaladas anteriormente Entidades declaradas en diferentes unidades de ámbito son siempre diferentes, aunque tengan los mismos identificadores y propiedades Dentro de una unidad de ámbito, cada entidad con nombre ha de tener un identificador diferente, con la excepción de los procedimientos genéricos Los identificadores de unidades de programa son globales, de modo que han de ser diferentes entre sí y diferentes de cualquier entidad local a las unidades de programa El ámbito de un identificador de un procedimiento interno se extiende sólo a toda la unidad de programa que lo contiene El ámbito de un identificador declarado en un procedimiento interno es ese procedimiento interno Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ámbito Se dice que los identificadores son accesibles por asociación de anfitrión o por asociación de uso: Asociación de anfitrión: el ámbito de un identificador declarado en una unidad de programa se extiende desde la cabecera de la unidad de programa hasta su sentencia end Asociación por uso: el ámbito de un identificador declarado en un módulo, cuando no tiene el atributo private, se extiende a cualquier unidad de programa que use el módulo Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ámbito Ejemplo module ambito1 ... contains subroutine ambito2 type ambito3 ... end type interface 100 ... end interface real x, y ... contains function ambito5(...) real y y = x + 1.0 100 ... end function ambito5 end subroutine ambito2 end module ambito1 ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito ambito Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 1 1 1 2 3 3 3 3 4 3 2 2 2 5 5 5 5 5 2 1 Estructura de los programas Orden de las sentencias Sentencias PROGRAM , FUNCTI ON, SUBROUTI NE o MODULE Sentencias USE Sentencia I MPLI CI T NONE Sentencias Sentencias PARAMETER I MPLI CI T Definiciones de tipos Sentencias derivados, Sentencias PARAMETER Bloques interface, FORMAT y Sentencias de declaración de tipos, y DATA Sentencias de especificación Sentencias ejecutables Sentencia CONTAI NS Subprogramas internos o Subprogramas del módulo Sentencia END Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructura de los programas Cuando utilizar bloques interface Cuando un módulo o procedimiento externo es invocado: Si el módulo define o sobrecarga un operador o sobrecarga la asignación Si el módulo utiliza un identificador genérico Se utiliza un bloque interface cuando un procedimiento externo: Es invocado con un argumento con nombre y/o opcional es una función que devuelve un vector o un puntero o bien una función de caracteres que no es ni constante ni de longitud conocida Tiene un parámetro que es un vector de forma asumida o un puntero Es argumento de otro subprograma (en este caso no es obligatorio, pero se recomienda) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructura de los programas Resumen Estilo Fortran77: Programa principal con procedimientos externos, posiblemente en una librería No hay interfaces explícitas de modo que el compilador no comprueba inconsistencias en los parámetros de las llamadas a subprograma Fortran90 simple: Programa principal con procedimientos internos Las interfaces son explícitas, de modo que el compilador detecta posibles inconsistencias Fortran90 con módulos: Programa principal y módulo(s) conteniendo interfaces y posiblemente especificaciones y la posibilidad de procedimientos externos (y de librerías precompiladas) Una versión F90 del estilo F77 con interfaces para permitir al compilador la comprobación de inconsistencias en los parámetros Programa principal y módulo(s) conteniendo especificaciones, interfaces y procedimientos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estructura de los programas Resumen Fortran90 con módulos: Un programa F90 estructurado consiste en un programa principal y módulos que contienen especificaciones, interfaces y procedimientos. Los procedimientos externos dejan de ser necesarios La introducción de nuevas características en el lenguaje tales como tipos derivados, sobrecarga, subprogramas internos y módulos hacen posible el desarrollo de código F90 sofisticado Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 4 Proceso de vectores Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Proceso de vectores Índice 4.1 Terminología 4.2 Especificaciones 4.3 Operaciones sobre vectores 4.4 Sentencia y constructor where 4.5 Procedimientos intrínsecos simples 4.6 Secciones de vectores 4.7 Posición del elemento versus indexación 4.8 Vectores de tamaño cero 4.9 Constructores de vectores 4.10 Vectores dinámicos 4.11 Vectores automáticos 4.12 Vectores con forma asumida 4.13 Funciones intrínsecas para operar con vectores 4.14 Ejemplo 4.15 Ejercicios Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Terminología Hablaremos en general de vectores (arrays) para referirnos a vectores multidimensionales (matrices) Fortran90 permite vectores de hasta 7 dimensiones real, dimension(50) :: w real, dimension(5:54) :: x real y(50) real z(11:60) !w, x, y, z vectores de 50 elementos Rango de un vector: número de dimensiones Extensión: número de elementos en una dimensión Forma: vector de extensiones. El vector contiene la extensión de cada dimensión Tamaño: Número de elementos. Es el producto de extensiones 2 vectores son compatibles si tienen la misma forma. Cualquier vector es compatible con un escalar Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Terminología Ejemplo real, dimension :: a(−3:4,7) real, dimension :: b(8,2:8) real, dimension :: d(8,1:8) integer :: c El vector a tiene: Rango: 2 Extensiones: 8 y 7 Forma: (/8, 7/) Tamaño: 56 El vector a es compatible con b y c, pero no con d (d tiene forma (/8, 9/) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Especificaciones tipo [[,dimension (lista_de_extensiones)] [,atributo]... ::] identificadores tipo: tipo básico o derivado dimension es opcional, pero necesario para definir dimensiones por defecto La lista de extensiones da las dimensiones del vector. Puede ser: Una constante entera Una expresión entera usando parámetros formales : para mostrar que el vector es dinámico o de forma asumida Los atributos pueden ser los que ya hemos estudiado: (parameter, public, private, pointer, target, allocatable, dimension(extent−list), intent(inout), optional, save, external, intrinsic) identificadores: Una lista de identificadores de vector que opcionalmente pueden tener dimensiones y valores iniciales Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Especificaciones Inicialización de vectores de 1 dimensión conteniendo 3 elementos: integer, dimension(3) :: & ia=(/1, 2, 3/), ib=(/(i, i=1, 3)/) Declaración de un vector automático lb. la es un vector de argumentos dummy y size una función intrínseca que da el tamaño del vector la logical, dimension(size(la)) :: lb Declaración de 2 vectores bidimensionales dinámicos a y b. La forma (nº de elementos en cada dimensión) se definiría con una sentencia allocate posterior: real, dimension (:,:), allocatable :: a,b Declaración de 2 vectores tridimentionales de forma asumida. La forma se tomaría de los parámetros actuales de la rutina llamadora: real, dimension(:,:,:) :: a,b Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Operaciones sobre vectores En Fortran90 es posible realizar operaciones sobre todos los elementos de un vector sin necesidad de usar bucles Para ello, los vectores implicados deben ser compatibles Las operaciones entre dos vectores compatibles se realizan elemento a elemento y todos los operadores intrínsecos están definidos para vectores compatibles. P. ej.: 3 4 8 5 6 6 * 5 2 1 3 3 1 = 15 8 8 15 18 6 Si uno de los operandos es un escalar, éste se expande para ser compatible con el otro operando. Esta expansión de escalares es útil a la hora de inicializar o escalar vectores Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Operaciones sobre vectores Un concepto fundamental con respecto a las asignaciones en operaciones sobre vectores es que la evaluación de la expresión del lado derecho de la asignación se realiza antes de que ocurra cualquier asignación. Esto es importante cuando aparecen vectores en ambos lados de la asignación: si no fuera así los elementos de los vectores de la parte derecha se podrían ver afectados antes de que la operación se completara. Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Operaciones sobre vectores Consideremos tres vectores del mismo tamaño. Asignemos 0 a todos los elementos y luego hagamos a(i) = a(i)/3.1 + b(i)*sqrt(c(i)) para todo i Solución en Fortran 77: real a(20), b(20), c(20) ... do 10 i=1, 20 a(i)=0 10 continue ... do 20 i=1, 20 a(i)=a(i)/3.1 + b(i)*sqrt(c(i)) 20 20 continue Solución en Fortran 90: real, dimension(20) :: a, b, c ... a = 0 ... a = a / 3.1 + b * sqrt(c) !sqrt Para cada !elemento Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Operaciones sobre vectores Consideremos tres matrices bidimensionales de la misma forma. Multiplicar dos de las matrices elemento a elemento asignando el resultado a la tercera matriz Fortran 77 10 20 real a(5, 5), b(5, 5), c(5, 5) ... do 20 i = 1, 5 do 10 j = 1, 5 c(j, i) = a(j, i) * b(j, i) continue continue Fortran 90 real, dimension (5, 5) :: a, b, c ... c = a * b Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Operaciones sobre vectores Consideremos una matriz tridimensional. Hallar el máximo valor menor que 1000 en la matriz. En Fortran90 el código es: real, dimension(10, 10, 10) :: a amax = maxval(a, mask = (a <1000)) mask es una función que devuelve un vector lógico: sólo los elementos de a que se corresponden con elementos de mask participan en la llamada a maxval Hallar el valor medio de los valores mayores que 3000 en un vector av = sum(a, mask=(a > 3000)) / & count(mask=(a > 3000)) Funciones intrínsecas sobre vectores: maxval − retorna el valor máximo de los elementos de un vector sum − la suma de los elementos del vector count − El número de elementos TRUE Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos intrínsecos elementales Fortran90 permite procedimientos intrínsecos sobre vectores. El procedimiento se aplica a cada elemento del vector (matriz). De nuevo, los operandos deben ser compatibles. Veamos ejemplos: 1.− Hallar la raiz cuadrada de todos los elementos de una matriz: b = sqrt(a) 2.− Hallar la longitud de una cadena dada por un vector de caracteres ch, ignorando los espacios en blanco: length = len_trim(ch) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Sentencia where Se usa para realizar asignaciones sólo si se cumple una condición lógica, y es útil para para realizar operaciones sobre ciertos elementos de un vector. Un ejemplo simple es evitar una división por cero: real, dimension(5, 5) : ra, rb ... where(rb > 0.0) ra = ra / rb Forma general: where(logical−array−expression) & array−variable = array−expression Se evalúa la expresión lógica y todos los elementos de la array−expression que tienen un valor true se evalúan y asignan. Los elementos que resultan false no se cambian. La expresión lógica ha de tener la misma forma que el vector Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Sentencia where También es posible controlar asignaciones sobre un vector a través de un vector lógico. En este caso la forma del constructo where es: where (logical−array−expression) array−assignment−statements end where o bien where (logical−array−expression) array−assignment−statements elsewhere array−assignment−statements end where Ejemplo: real, dimension(5, 5) :: ra, rb ... where(rb > 0.0) ra = ra / rb elsewhere ra = 0.0 end where Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Secciones de vectores Una parte de un vector (lo que se llama una sección) puede referenciarse especificando un rango de subíndices mediante: Un subíndice simple: 0 0 0 0 0 0 X 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 = ra (2, 2) 0 0 Una tripleta de subíndices: [lim_inf]:[lim_sup][:stride] 1 Por defecto se toman los límites declarados y stride=1 Los siguientes ejemplos muestran secciones de vectores utilizando tripletas de subíndices: Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Secciones de vectores 0 0 0 0 0 0 X 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 X 0 0 0 X 0 0 0 0 0 0 0 = ra (2 : 2, 2 : 2) 0 Un elemento. Forma: (/1/) 0 0 0 X = ra (3, 3 : 5) 0 Una Subcolumna. Forma: (/3/) 0 0 0 0 0 0 0 0 0 0 0 X X X X X 0 0 0 0 0 0 0 0 = ra (:, 3) 0 Una columna. Forma: (/5/) 0 0 0 0 0 0 X 0 X 0 X 0 X 0 X 0 X 0 X X X 0 0 0 = ra (1 :: 2, 2 : 4) 0 Stride 2 en filas. Forma: (/3, 3/) 0 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Secciones de vectores Un vector de subíndices. Es una expresión entera de rango 1 (vector de enteros). Cada elemento de la expresión ha de definirse con valores en el rango de los límites del vector padre . Los elementos del vector de subíndices pueden estar en cualquier orden Un ejemplo de expresión entera de rango 1 es: (/3, 2, 12, 2, 1/) Veamos ejemplos de uso: real, dimension :: ra(6), rb(3) integer, dimension (3) :: iv iv = (/ 1, 3, 5 /) !expr. entera de rango 1 ra = (/ 1.2, 3.4, 3.0, 11.2, 1.0, 3.7 /) rb = ra(iv) !iv es el vector de subíndices ! = (/ ra(1), ra(3), ra(5) /) ! = (/ 1.2, 3.0, 1.0 /) ra(iv) = (/1.2, 3.4, 5.6/) != ra((/1, 3, 5/)) = (/1.2, 3.4, 5.6/) != ra(1:5:2) = (/1.2, 3.4, 5.6/) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Secciones de vectores Se permite utilizar varias veces el mismo vector de subíndices. No se pueden repetir elementos en la parte izquierda (muchos a uno), pero sí en la parte derecha (uno a muchos): real, dimension :: ra(6), rb(3) integer, dimension (3) :: iv iv = (/1, 3, 1/) ra(iv) = (/1.2, 3.4, 5.6/) ! Prohibido ! = ra(/1, 3, 1/) = (/1.2, 3.4, 5.6/) rb = ra(iv) ! Permitido ! = ra(/1, 3, 1/) = (/1.2, 3.4, 1.2/) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Asignaciones con vectores Tanto vectores completos como secciones de vectores se pueden usar como operandos en asignaciones con vectores, siempre que sean compatibles. Por ejemplo: real, dimension(5, 5) :: ra, rb, rc integer :: i ... ! Forma (/5, 5/) y escalar ra = rb + rc * i ! Forma (/3, 2/) ra(3:5,3:4) = rb(1::2, 3:5:2) + rc(1:3, :2) ! Forma (/5/) ra(:,1) = rb(:,1) + rb(:,2) + rc(:,3) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Recursividad Es importante saber cómo obtener recursividad en Fortran90. Por ejemplo el código: do i = 2, n x(i) = x(i) + x(i−1) end do No produce el mismo resultado que: x(2:n)= x(2:n) + x(1:n−1) En el primer caso, la asignación es: x(i) = x(i) + x(i−1) + x(i−2) + ... + x(1) Mientras que en el segundo: x(i) = x(i) + x(i−1) !Comprobarlo! En Fortran90 se puede obtener el efecto recursivo del bucle do utilizando la función intrínseca sum, que devuelve la suma de todos los elementos del vector parámetro: x(2:n) = (/(sum(x(1:i)), i= 2,n)/) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Posición del elemento versus indexación Las funciones intrínsecas maxloc y minloc devuelven la posición de los valores máximo y mínimo del vector pasado como parámetro. Si el límite inferior no es 1 hay que tener en cuenta que estas funciones devuelven la posición y no el subíndice: real, dimension (1:8) :: ra real, dimension (−3:4) :: rb integer, dimension (1) :: locmax1, locmax2 real :: max1, max2 ra=(/1.2, 3.4, 5.4, 11.2, 1.0, 3.7, 1.0,1.0/) rb = ra !Para hallar el valor máximo: locmax1 = maxloc(ra) ! = (/ 4 /) locmax2 = maxloc(rb) ! = (/ 4 /) max1 = ra(locmax(1)) ! OK porque el límite inferior de ra es 1 max2 = rb(lbound(rb) + locmax2(1) − 1) ! Se necesita esto si el límite inferior ! no es 1 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores de tamaño cero Si el límite inferior de un vector es mayor que el superior, el vector tiene tamaño cero. Estos vectores siguen las reglas normales Son útiles para operaciones de contorno (no se necesita código especial para tratar los límites de un modo especial): do i=1, n x(i) = b(i) / a(i, i) b(i+1:n) = b(i+1:n) − a(i+1:n, i) * x(i) ! Tamaño cero cuando i=n end do Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Constructores de vectores Un constructor de vectores crea un vector de rango 1 conteniendo valores especificados. Los valores se pueden dar listándolos o bien usando un bucle implícito o una combinación de ambos Forma general: (/ array−constructor−value−list /) Ejemplo: real, dimension(6) :: a a=(/array−constructor−value−list/) Donde array−constructer−value−list puede ser: (/(i, i = 1,6)/) ! = (/1,2,3,4,5,6/) (/7, (i, i=1,4), 9/)! = (/7,1,2,3,4,9/) (/1.0/real(i), i = 1,6)/) !=(/1.0/1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0, 1.0/6.0/) (/((i+j, i=1,3), j=1,2)/) ! = (/((1+j,2+j,3+j),j=1,2)/) ! = (/2,3,4,3,4,5/) (/a(i,2:4),a(1:5:2,i+3)/) !=(/a(i,2),a(i,3),a(i,4),a(1,i+3),a(3,i+3), a(5,i+3)/) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Constructores de vectores Es posible transferir los valores de un vector de rango 1 a un vector de diferente forma utilizando la función reshape, que tiene la forma: reshape(fuente,shape,[,pad][,order]) Donde el parámetro fuente puede ser un array de cualquier clase, y sus elementos se distribuyen para formar un nuevo vector (reshape) con forma shape, (que es devuelto por la función) Si fuente tiene más elementos que el vector al que se asigna, entonces los elementos no deseados se ignoran Si reshape tiene más elementos que fuente, entonces pad ha de estar presente. pad es un vector del mismo tipo que fuente que se usa (quizás repetidamente) para rellenar order permite que los elementos de reshape se coloquen en órdenes diferentes al del vector. Ha de tener el mismo tamaño y forma que shape y contiene las dimensiones de reshape en el orden en que deben recorrerse Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Constructores de vectores Ejemplo real, dimension(3, 2) :: ra ra=reshape((/((i + j, i= 1,3), j= 1,2)/),& shape=(/3, 2/)) !Crea el vector: 2 3 ra = 3 4 4 5 ra=reshape((/((i+j,i=1,3),j=1,2)/),shape= & (/3,2/),order(2,1)) ! El resultado sería: 2 3 ra = 4 3 4 5 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores dinámicos En Fortran77 todo el manejo de memoria era estático Fortran90 Permite obtener y liberar memoria dinámica a través de los vectores dinámicos Permite a los vectores locales a un procedimiento tener tamaños y formas diferentes en cada llamada a través de los vectores automáticos Reduce los recursos globales necesarios para almacenamiento en memoria Simplifica los parámetros de las subrutinas Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores dinámicos Un vector dinámico se declara en una sentencia de declaración de tipo con el atributo allocatable El rango del vector debe especificarse en la declaración incluyendo el número adecuado de : en el atributo dimension Un vector bidimensional se podría declarar: real, dimension(:,:), allocatable :: a La declaración no reserva memoria para el vector allocate (a(0:n, m)) allocate (a(0:n+1, m)) deallocate (a) La forma general de estas sentencias: allocate(allocate−object−list & [,STAT=checkstat]) deallocate(allocate−object−list & [,STAT=checkstat]) Si STAT está presente, toma el valor 0 si la operación se realizó correctamente o un valor positivo si hubo un error Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores dinámicos Ejemplo integer n real, dimension(:,:), allocatable :: ra integer :: checkstat ... read(*, *) nsize1, nsize2 ALLLOCATE(ra(nsize1, nsize2), STAT=checkstat) if (checkstat > 0) then ! ... Hubo un error ... end if ... deallocate (ra) Se pueden alojar/desalojar varios vectores en la misma sentencia if (allocated(a)) deallocate(a) or if (.not. allocated(a)) allocate(a(5, 20)) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores dinámicos Si un vector dinámico se declara con el atributo save: real, dimension(:), allocatable, save :: a el vector estará disponible incluso a la salida del procedimiento en que fue alojado Los vectores dinámicos: han de ser creados y liberados dentro de la misma unidad de programa El resultado de una función no puede ser un vector dinámico No se puede usar vectores dinámicos en una definición de tipo derivado Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores Automáticos Llamaremos vector automático a un vector que tiene forma explícita dentro de un procedimiento y cuyos límites se dan cuando el procedimiento es invocado a través de los parámetros formales a través de variables definidas por asociación por uso o asociación por hospedaje Asociación por uso es cuando las variables declaradas en el cuerpo de un módulo se hacen disponibles a un programa a través de una sentencia use. Asociación por hospedaje es cuando las variables declaradas en una unidad de programa se hacen disponibles a sus procedimientos internos Los vectores automáticos se crean al entrar al procedimiento y se liberan al salir del mismo No existe un mecanismo para comprobar si hay suficiente memoria para un vector automático Es frecuente usar la función intrínseca size al declarar vectores automáticos: size(ARRAY [,DIM]) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores Automáticos Ejemplos subroutine sub(n, a) implicit none integer :: n real, dimension(n, n), intent(inout) :: a real, dimension(n, n) :: work1 real, dimension(size(a, 1)) :: work2 ... end subroutine sub Los vectores work1 y work2 toman su tamaño de los parámetros formales n y a El siguiente ejemplo muestra los límites de un vector automático dependiendo de una variable global definida en un módulo. Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores Automáticos module auto_mod implicit none integer :: n=1 !Por defecto n=1 contains subroutine sub implicit none real, dimension(n) :: w write (*, *) Límites−tamaño de w: & ,lbound(w), ubound(w), size(w) end subroutine sub end module auto_mod program auto_arrays use auto_mod implicit none n = 10 call sub end program auto_arrays Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores Automáticos Supongamos que el programa principal declara un vector de tamaño NxN pero a una subrutina ha de pasar como parámetro una sección de tamaño N1xN1 (N1 < N). Para conseguir esto en Fortran77 hemos de pasar como parámetros tanto N como N1, mientras que en Fortran90 se puede simplificar el código: Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores Automáticos program array ! Fortran77 integer n,n1 parameter (n=10) real a(n,n),work(n,n) real res ... read(*,*) n1 if (n1 .LE. n) then call sub(a,n,n1,res,work) else c ... Hubo un error ... end if ... end program array subroutine sub(a, n, n1, res, work) integer n, n1 real a(n, n) real work(n1, n1) real res ... res=a(...) ... end subroutine sub Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores Automáticos PPROGRAM array !Fortran90 implicit none real, allocatable, dimension(:,:) :: a real :: res integer :: n1, alloc_stat ... read(*,*) n1 allocate(a(n1, n1), STAT=alloc_stat) if (alloc_stat /= 0) then ! ... Hubo un error ... end if call sub(a, n1, res) deallocate(a, STAT=alloc_stat) if (alloc_stat /= 0) then ! ... Hubo un error ... end if ... contains Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores Automáticos contains subroutine sub(a, n1, implicit none integer, intent(in) real, intent(inout) real, dimension(n1, real, dimension(n1, ... res=a(...) ... end subroutine sub end program array res) :: n1 :: res n1), intent(in) :: a n1):: work Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores con forma asumida Un vector de forma asumida es un vector cuya forma no es conocida sino que toma cualquier forma dependiendo de un parámetro actual Cuando se declara un vector de forma asumida cada dimensión se especifica como: [lower_bound]: donde el límite inferior se toma como 1 si se omite Los vectores de forma asumida hacen posible el paso de vectores entre unidades de programa sin necesidad de pasar las dimensiones como parámetros. Si un procedimiento externo tiene un vector de forma asumida como parámetro formal ha de darse un bloque de interface en la unidad de programadora que invoque al procedimiento Consideremos el siguiente subprograma externo con vectores de forma asumida ra, rb y rc Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores con forma asumida subroutine sub(ra, rb, rc) implicit none real, dimension(:,:), intent(in) :: ra ! Forma (10, 10) real, dimension(:,:), intent(in) :: rb ! Forma (5, 5) ! = real, dimension(1:5,1:5) :: rb real, dimension(0:,2:), intent(out) :: rc ! Forma (5, 5) ! = real, dimension (0:4,2:6) :: rc ... end subroutine sub ! El prog. Ppal. Debería tener una interface: real, dimension (0:9,10) :: ra ! Shape (10, 10) interface subroutine sub(ra, rb, rc) real, dimension(:,:),intent(in):: ra,rb real, dimension(0:,2:),intent(out):: rc end subroutine sub end interface ... call sub (ra, ra(0:4,2:6), ra(0:4,2:6)) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ejemplo program array implicit none real, allocatable, dimension(:,:) :: a real :: res integer :: n1 interface subroutine sub(a,res) real,dimension(:,:), intent(in)::a real,dimension(size(a,1),size(a, 2)) :: work end subroutine sub end interface ... read (*, *) n1 allocate (a(n1, n1))! Vector dinámico call sub(a, res) ... contains subroutine sub(a,res) implicit none real, intent(out) :: res real, dimension(:, :), intent(in) :: a ! Vector de forma asumida real,dimension (size(a,1),size(a,2)) :: work ! Vector automático ... res = a(...) Introducción ... a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 end subroutine sub end program array Funciones intrínsecas para vectores Reducciones ALL(MASK[, DIM]) True si todos los elementos son true ANY(MASK[, DIM]) True si algún elemento es True COUNT(MASK[, DIM]) Número de elementos true maxval(ARRAY[, DIM][, MASK]) Máximo del vector MINVAL(ARRAY[, DIM][, MASK]) Mínimo del vector PRODUCT(ARRAY[, DIM][, MASK]) Producto de todos los elementos SUM(ARRAY[, DIM][, MASK]) Suma de todos los elementos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones intrínsecas para vectores Consulta allocated(ARRAY) True si el vector ha sido creado lbound(ARRAY[, DIM]) Límites inferiores del vector shape(fuente) Forma del vector (o escalar) size(ARRAY[, DIM]) Tamaño del vector ubound(ARRAY[, DIM]) Límite superior del vector Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones intrínsecas para vectores Construcción MERGE(TSOURCE, FSOURCE, MASK) Mezcla dos vectores en términos de la máscara pack(ARRAY, MASK[, VECTOR]) Empaqueta elementos en el vector en términos de la máscara SPREAD(fuente, DIM, ncopias) Construye un vector duplicando una sección de otro UNPACK(VECTOR, MASK, FIELD) Desempaqueta elementos de un vector en términos de la máscara Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones intrínsecas para vectores Reshape reshape(fuente, shape[, pad][, order]) Cambia la forma de un vector Posición en el vector MAXLOC(ARRAY[, MASK]) Posición del máximo MINLOC(ARRAY[, MASK]) Posición del mínimo Manipulación de vectores CSHIFT(ARRAY, SHIFT[, DIM]) Realiza una rotación circular EOSHIFT(ARRAY, SHIFT[, BOUNDARY][, DIM]) Rotación “ nd−off” TRANSPOSE(MATRIX) Traspone una matriz Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones intrínsecas para vectores Aritmética vectorial y matricial DOT_PRODUCT(VECTOR_A, VECTOR_B) Producto escalar MATMUL(MATRIX_A, MATRIX_B) Producto de matrices Ejemplos Los siguientes ejemplos ilustran el uso de algunas de estas funciones intrínsecas. Tres estudiantes realizan 4 exámenes. Las calificaciones (sobre 100 puntos) se almacenan en un vector de enteros: 85 76 90 60 score(1 : 3, 1 : 4) = 71 45 50 80 66 45 21 55 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones vectoriales intrínsecas: Ejemplos 85 76 90 60 score(1 : 3, 1 : 4) = 71 45 50 80 66 45 21 55 Máxima nota: maxval (score) ! = 90 Máxima nota para cada estudiante: maxval (score, DIM = 2) ! = (/90, 80, 66/) Alumno con la nota máxima: maxloc (maxval (SCORE, DIM = 2)) ! = maxloc ((/90, 80, 66 /)) = (/ 1 /) Nota media: average = sum(score)/size(score)!=62 ! average es una variable entera Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones vectoriales intrínsecas: Ejemplos 85 76 90 60 score(1 : 3, 1 : 4) = 71 45 50 80 66 45 21 55 Número de calificaciones por encima de la media: above = score > average ! above(3, 4) es un vector lógico T ! above = T T T F F T F F F T F n_gt_average = count (above) ! n_gt_average es un entero ! = 6 Empaquetar todas las notas por encima de la media: ... integer, allocatable, dimension (:) :: & score_gt_average ... allocate (score_gt_average(n_gt_average) scores_gt_average = pack (score, above) ! = (/ 85, 71, 66, 76, 90, 80 /) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones vectoriales intrínsecas: Ejemplos 85 76 90 60 score(1 : 3, 1 : 4) = 71 45 50 80 66 45 21 55 ¿Algún alumno puntuó siempre por encima de la media?: ANY (ALL (above, DIM = 2)) ! = .FALSE. ¿Todos los alumnos puntuaron por encima de la media en cualquiera de los exámenes? ANY (ALL (above, DIM = 1)) ! = .TRUE. Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ejemplo: Conjugado del gradiente program conjugate_gradients implicit none integer :: iters, its, n logical :: converged real :: error, up, alpha, beta real, allocatable :: & a(:,:), b(:), x(:), r(:), & u(:), p(:), xnew(:) read (*,*) n, error, its allocate & (a(n,n),b(n),x(n),r(n),u(n),p(n),xnew(n)) open (10, file=’data’) read (10,*) a read (10,*) b x = 1.0 r = b − MATMUL(a, x) p = r iters = 0 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Ejemplo: Conjugado del gradiente do iters = iters + 1 u = MATMUL(a, p) up = DOT_PRODUCT(r, r) alpha = up / DOT_PRODUCT(p, u) xnew = x + p * alpha r = r − u * alpha beta = DOT_PRODUCT(r, r) / up p = r + p * beta converged = ( maxval(ABS(xnew−x)) / & maxval(ABS(x)) < error ) x = xnew if (converged .OR. iters == its) exit end do write (*,*) iters write (*,*) x end program conjugate_gradients Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 5 Punteros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Punteros Índice 5.1 − Significado de un puntero 5.2 − Especificaciones 5.3 − Asignaciones de punteros 5.4 − Estado de una asociación de punteros 5.5 − Memoria dinámica 5.6 − Argumentos puntero 5.7 − Funciones que devuelven punteros 5.8 − Vectores de punteros 5.9 − Listas enlazadas 5.10 − Ejercicios Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Significado de un puntero Una variable de tipo puntero (o simplemente un puntero) tiene el atributo pointer y puede apuntar a otra variable de un tipo adecuado, que tendrá el atributo target o bien a un área de memoria alojada dinámicamente Los punteros en F90 son diferentes a los de C o Pascal: no contienen un dato en sí mismos y no deberían interpretarse como una dirección. Más bien deberían verse como variables que se asocian dinámicamente (en tiempo de ejecución) con otros datos que sí tienen asignado un espacio de memoria física ( target ) Los beneficios más interesantes de la introducción de punteros son: Una alternativa más flexible a los arrays dinámicos Una herramienta para crear y manipular listas enlazadas y otras estructuras de datos dinámicas Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Especificaciones La forma general de declarar una variable puntero y un destino (target) son: type [[,attribute]...] pointer :: list of pointer variables type [[,attribute]...] target :: list of target variables Donde El tipo especifica el tipo de variables que pueden ser apuntadas por el puntero (incluyendo tipos derivados) La lista de atributos da el resto de atributos del tipo de datos (si tiene alguno/s) Una variable puntero ha de tener el mismo tipo, parámetros y rango que su variable destino Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Especificaciones La declaración de un puntero a vectores especifica el tipo y rango de los vectores a los que puede apuntar (sólo el rango, no los límites del vector) El atributo dimensión de un puntero a vectores no puede especificar una forma explícita o una forma asumida sino que debe tomar la forma de un vector de forma diferida de modo similar a como se hace con los vectores dinámicos. Así por ejemplo la declaración: real, dimension(:), pointer :: p Declara un puntero p, que puede apuntar a vectores de reales de rango 1. La declaración: real, dimension(20), pointer :: p Es errónea y no es admitida por el compilador F90 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Asignaciones de punteros Un puntero puede convertirse en un alias de una variable destino (target) a través de una sentencia de asignación de punteros, que es ejecutable y tiene la forma: pointer => target Donde pointer es una variable con atributo pointer y target es una variable con atributo target o bien atributo pointer Una vez que un puntero se convierte en alias de un destino, se puede utilizar en cualquier punto en lugar de la variable destino Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Asignaciones de punteros Ejemplos: real, real, p1 => print p2 => print pointer :: p1, p2 target :: t1 = 3.4, t2 = 4.5 t1 ! p1 apunta a t1 *, t1, p1 ! ambos valen 3.4 t2 ! p2 apunta a t2 *, t2, p2 ! ambos valen 4.5 t1 p1 3.4 t2 p2 4.5 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Asignaciones de punteros t1 p1 3.4 t2 p2 4.5 p2 => p1 ! p2 apunta al destino de p1 print *, t1, p1, p2 !Todos valen 3.4 t1 p1 p2 3.4 t1 = 5.2 print *, t1, p1, p2 t2 4.5 !Todos valen 5.2 Téngase en cuenta que la asignación: p2 => p1 + 4.3 !Error No está permitida porque no se puede asociar un puntero con una expresión aritmética Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Asignación de punteros / asignaciones normales Comparemos lo anterior con el siguiente código, en el que sólo la última línea es diferente: real, pointer :: p1, p2 real, target :: t1 = 3.4, t2 = 4.5 p1 => t1 ! p1 apunta a t1 p2 => t2 ! p2 apunta a t2 p2 = p1 ! Asignación normal, ! equivalente a t2 = t1 t1 p1 3.4 t2 p2 4.5 Después de que la última asignación se ejecuta, la situación es: t1 p1 3.4 t2 p2 3.4 La sentencia tiene el mismo efecto que t2=t1 puesto que p1 es un alias de t1 y p2 lo es de t2 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Punteros a vectores El destino de un puntero puede ser también un vector. Veamos ejemplos de su uso: real, dimension (:), pointer :: pv1 real, dimension (:, :), pointer :: pv2 real, dimension (−3:5), target :: tv1 real, dimension (5, 10), target :: tv2 integer, dimension(3) :: v = (/4, 1,−3/) pv1 => tv1 ! pv1 es un alias de tv1 pv1 => tv1(:) ! pv1 apunta a tv1 con ! Subíndices de sección pv1 => tv2(4, :) ! pv1 apunta a la 4ª fila ! de tv2 pv2 => tv2(2:4, 4:8) ! pv2 apunta a una ! sección de tv2 pv1 => tv1(1:5:2) ! pv1 apunta a una ! Sección de tv1 pv1 => tv1(v) ! Error Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Punteros a vectores real, dimension (:), pointer :: pv1 real, dimension (−3:5), target :: tv1 pv1 => tv1 ! pv1 es un alias de tv1 tv1(−3:5) pv1(−3:5) pv1 => tv1(:) ! pv1 apunta a tv1 con ! Subíndices de sección tv1(−3:5) pv1(1:9) pv1 => tv1(1:5:2) ! Sección de tv1 ! pv1 apunta a una tv1(1:5:2) pv1(1:3) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Punteros a vectores real, dimension (:), pointer :: pv1 real, dimension (:, :), pointer :: pv2 real, dimension (5, 10), target :: tv2 pv1 => tv(4, :) ! pv1 apunta a la 4ª fila ! de tv2 tv2(4, :) pv1(1:10) pv2 => tv2(2:4, 4:8) ! sección de tv2 ! pv2 apunta a una tv2(2:4, 4:8) pv2(1:3, 1:5) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Punteros a vectores Hay varios aspectos a tener en cuenta: El puntero pv1 se asocia en diferentes momentos con vectores (secciones de vector) de diferentes extensiones. Esto se permite porque lo que cuenta es el rango, no la extensión Si un puntero a vector se hace alias de un vector, sus extensiones son las mismas que las del vector al que apunta. Así con la asignación pv1 => tv1, pv1 tiene los mismos límites que tv1, es decir − 3:5. Si un puntero a vector apunta a una sección de vector, su límite inferior en cada dimensión se renumera siempre a 1. Así con pv1 => tv1(:), donde se use el subíndice de la sección de vector los límites de pv1 son 1:9 en lugar de −3:5; de modo que pv1(1) se interpreta como tv1(−3), pv1(2) es tv1(−2), y así sucesivamente. Esta renumeración también ocurre cuando tv2 se interpreta como la sección tv2(2:4, 4:8) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Punteros a vectores Es lícito asociar un puntero a vector con una sección de vector definida por una tripleta de subíndices, pero no se permite asociarlo con una sección definida por subíndices. Así pv1 => tv1(1:5:2) es correcto con pv1(1) siendo un alias de tv1(1), pv1(2) de tv1(3), y pv1(3) de tv1(5), pero la asignación de punteros: pv1 => tv1(v) ! Error no es admitida por el compilador Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estado de una asociación de punteros Todo puntero tiene uno de los siguientes estados de asociación: 1.− Indefinido − cuando es inicialmente especificado en una sentencia de declaración 2.− Null (disociado) − cuando se hace nulo con una sentencia NULLIFY 3.− Asociado − cuando apunta a un destino Un puntero puede disociarse explícitamente de su destino (target) usando una sentencia NULLIFY: NULLIFY(list of pointers) La función intrínseca associated puede usarse para comprobar el estado de asociación de un puntero usando 1 ó 2 parámetros: associated(p, [,t]) Si el 2º parámetro no aparece, retorna .TRUE. si el puntero p está asociado con agún destino y .FALSE. en caso contrario. El 2º parámetro puede ser un puntero en cuyo caso retorna .TRUE. si ambos punteros están asociados al mismo destino o disociados y .FALSE. en caso contario Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Estado de una asociación de punteros Una restricción de associated es que no se le pueden pasar punteros indefinidos. Por ello se recomienda asociar un puntero después de su declaración o disociarlo explícitamente con NULLIFY Ejemplos: real, pointer :: p, q ! Indefinidos real, target :: t = 3.4 p => t ! p apunta a t q => t ! q también apunta a t print *, associated(p)=",associated(p) !.T. print *,"associated(p,q)=",associated(p,q)!.T. NULLIFY(p) print *,"associated(p)= ", associated(p) !.F. print *,"associated(p,q)=",associated(p, q)!.F. ... p => t ! p apunta a t NULLIFY(p, q) Nótese que la disociación de p no afectó a q a pesar de que ambos apuntaban al mismo objeto. Después de anular un puntero, puede asociársele de nuevo con el mismo u otro objeto Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Memoria dinámica También un puntero puede asociarse con un área de memoria alojada dinámicamente a través de la sentencia allocate. Esta sentencia crea (sin nombre) un área de memoria del tamaño, tipo y rango especificados y con un atributo target: real, pointer :: p real, dimension (:, :), pointer :: pv integer :: m, n ... allocate (p, pv(m, n)) Aquí el puntero p apunta a un área de memoria dinámica con capacidad para almacenar un real. El puntero pv apunta a un vector (matriz) de tamaño mxn La memoria dinámica puede liberarse: deallocate(pv) haciendo que el estado de pv pase a ser NULL Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Memoria dinámica La forma general de estas sentencias es: allocate(pointer[(dim. specification)]... [,STAT = status]) deallocate(pointer... [,STAT = status] Donde pointer es una variable puntero y la especificación de dimensión especifica la extensión de cada dimensión si el puntero tiene los atributos pointer y dimension (es un puntero a un vector). status es un entero que tomará el valor 0 si la demanda/liberación de memoria ocurrió correctamente. Ambas sentencias pueden solicitar/liberar memoria para varios punteros La programación con punteros entraña algunos peligros si no se diseña con precaución: Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Memoria dinámica Referencias suspendidas: ... real, pointer :: p1, p2 allocate (p1) p1 = 3.4 p2 => p1 ... deallocate (p1) ! Las referencias a p2 ... ! ahora serán errores ! y los resultados son ! impredecibles... Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Memoria dinámica Memoria inaccesible: ... real, dimension(:), pointer :: p allocate (p(1000)) ... Si el puntero p es anulado (NULLIFY), se hace apuntar a otra zona de memoria o este código está en un subprograma y el subprograma es abandonado (p no tiene atributo save) sin liberar la memoria, no habrá forma de referenciar ese bloque de memoria y por tanto no podrá ser liberado Solución: liberar cualquier bloque de memoria antes de modificar un puntero que apunte a ella Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Argumentos puntero Los punteros, asociados o no, se pueden pasar como parámetros a los subprogramas pero sólo si se dan las siguientes condiciones: Si un procedimiento tiene un puntero o destino como parámetro formal, la interface al procedimiento ha de ser explícita Si un parámetro formal es un puntero, el parámetro actual ha de ser un puntero con el mismo tipo, parámetros de tipo y rango Un parámetro formal de tipo puntero no puede tener atributo intent Si el parámetro actual es un puntero pero el formal no lo es, el parámetro formal se asocia con el destino del puntero Consideremos el siguiente código: Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Argumentos puntero ...! Unidad de prog. Que invoca a sub1 y sub2 interface ! interface para sub2 subroutine sub2(b) real, dimension(:, :), pointer :: b end subroutine sub2 end interface real, dimension(:, :), pointer :: p ... allocate (p(50, 50)) call sub1(p) call sub2(p) ... subroutine sub1(a) !a no es un puntero sino real, dimension(:, :) :: a ! un vector de ... ! forma asumida end subroutine sub1 subroutine sub2(b) ! b es un puntero real, dimension(:, :), pointer :: b ... deallocate(b) ... end subroutine sub2 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Argumentos puntero Los aspectos a tener en cuenta aquí son: Tanto sub1 como sub2 son procedimientos externos. Puesto que sub2 tiene un parámetro formal puntero, se necesita un bloque interface en la unidad llamadora (no es necesario para sub1). Una alternativa hubiera sido usar un módulo o un procedimiento interno para suministrar una interface explícita por defecto La unidad de programa llamadora hace que el puntero p sea un alias de un vector de 50x50 reales e invoca a sub2. Esto asocia el parámetro formal puntero b con el parámetro actual puntero p. Cuando sub2 libera b se libera también p en el programa llamador y hace que p pase a ser NULL Los vectores dinámicos no pueden usarse como parámetros formales y deben ser alojados y liberados en la misma unidad de programa. Se permite pasar como parámetros actuales vectores dinámicos con memoria asignada, pero no sin que les haya sido asignada memoria Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones que devuelven punteros El resultado de una función puede tener el atributo pointer, lo cual es útil si el tamaño del resultado depende de cálculos realizados en la función. Veamos un ejemplo: Una función que devuelve todos los valores >0 de un vector: ... integer, dimension(100) :: x integer, dimension(:), pointer :: p ... p => gtzero(x) ... contains function gtzero(a) integer, dimension(:), pointer :: gtzero integer, dimension(:) :: a integer :: n ... !n = nº de valores> 0 if (n == 0) NULLIFY(gtzero) else allocate (gtzero(n)) endif ... ! Poner los valores en gtzero end function gtzero ... Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones que devuelven punteros Consideraciones: La función gtzero se ha codificado como un procedimiento interno porque la interface a una función que devuelve un puntero ha de ser explícita El resultado de la función puede utilizarse como una expresión en una sentencia de asignación de punteros (pero ha de asociarse antes con un destino −target− definido). Como resultado el puntero p apunta a un vector dinámico de enteros del tamaño correcto que contiene todos los valores positivos del vector x Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores de punteros Un vector de punteros no se puede declarar directamente: real, dimension(20), pointer :: p !Error No puede hacerse porque pointer es un atributo y no un tipo de datos. Un puntero puede ser una componente de un tipo derivado. Un vector de punteros se declara a través de un tipo derivado: type real_pointer real, dimension(:), pointer :: p end type real_pointer Ahora se puede definir un vector de variables de este tipo: type(real_pointer), dimension(100) :: a Y se puede hacer referencia al i−ésimo puntero: a(i)%p Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Vectores de punteros Un ejemplo en el que cada columna de una matriz triangular inferior se representa mediante un vector dinámico de tamaño creciente: integer, parameter :: n = 10 type(real_pointer), dimension(n) :: a integer :: i do i = 1, n allocate (a(i)%p(i)) end do ! Referencia al i−ésimo puntero Nótese que a(i)%p apunta a un vector dinámico de reales de tamaño i y por lo tanto esta representación utiliza sólo la mitad de la memoria que se necesitaría con un vector bidimensional convencional Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Listas enlazadas Una componente de tipo puntero de un tipo derivado puede apuntar a un objeto del mismo tipo, lo cual permite crear listas enlazadas y otras estructuras de datos dinámicas: type node integer :: value Datos type (node), pointer :: next end type node ! ! Puntero En una estructura de este tipo los nodos − No tienen porqué almacenarse de forma contigua en memoria − Pueden crearse dinámicamente (en tiempo de ejecución) − Pueden insertarse en cualquier posición de la lista − Pueden eliminarse dinámicamente Por todo ello, el tamaño de estas estructuras puede crecer, casi arbitrariamente, conforme se ejecuta el programa Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Listas enlazadas Una lista enlazada consiste habitualmente en elementos de un tipo derivado que contiene uno o varios campos de datos más un campo que es un puntero al siguiente elemento del mismo tipo en la lista cabecera Campos de datos Puntero cola Campos de datos Puntero ... Campos de datos Puntero Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Listas enlazadas program simple_linked_list implicit none type node integer :: value ! Campo de datos type (node), pointer :: next ! Campo puntero end type node integer :: num, status type (node), pointer :: list, current ! build up the list NULLIFY(list) !Inicialmente, vaciar la lista do read *, num !Leer num del teclado if (num == 0) exit !Hasta que se lea un 0 allocate(current, STAT = status) !Crear nodo if (status > 0) stop ’Fallo al crear nodo’ current%value = num current%next => list !Apuntar al anterior list => current !Actualizar head end do ! Recorrer la lista imprimiendo los valores current => list ! Current es un alias de list do if (.not. associated(current)) exit print *, current%value current => current%next end do end program simple_linked_list Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Listas enlazadas !Recorrer la lista eliminando nodos: current => list do if (.not. associated(current)) exit list => current%next deallocate(current) current => list end do Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 6 Nuevas características de entrada/salida Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Entrada/Salida Índice 6.1 − Introducción 6.2 − Entrada/Salida (E/S) sin avance 6.3 − Consultar lista de E/S (INQUIRE) 6.4 − NAMELIST 6.5 − Nuevos descriptores de edición 6.6 − Nuevos especificadores de sentencias 6.7 − Ejercicios Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Introducción Las sentencias de entrada/salida (E/S) en Fortran90 son respectivamente read y write Cada una de ellas puede adoptar 3 formas diferentes: read <ch_var>, <lista_de_entrada> read <etiqueta>, <lista_de_entrada> read *, <lista_de_entrada> print <ch_var>, <lista_de_entrada> print <etiqueta>, <lista_de_entrada> print *, <lista_de_entrada> <ch_var> es una constante de caracteres, una variable de tipo character o un vector de caracteres <etiqueta> es la etiqueta de una sentencia en el código Las listas corresponden a las variables que se desea leer o escribir Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Introducción La primera forma de sentencia de E/S se denomina de formato empotrado porque el formato en sí mismo forma parte de la sentencia: print (<lista_de_descriptores>) , <lista_salida> En la segunda variante, la etiqueta corresponderá con una sentencia format, que contiene el formato que se desea en la operación de E/S La tercera forma es la que se conoce como E/S dirigida por lista. Se trata de la forma más simple y la que más hemos utilizado a lo largo del curso. En esta forma el asterisco indica que se desea un formato de entada o salida acorde con el tipo de los valores a leer/escribir Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Formateadores de E/S Iw Fw .d Ew .d Aw A Lw nX Tc TLn TRn "c 1c2 ...cn " ’c1 c2 ...cn ’ Escribe un entero en los siguientes w caracter es I m pr im e un núm ero r eal en los siguientes w car acter es utilizando d posiciones decim ales I m pr im e un núm ero r eal en los siguientes w car acter es utilizando un form ato de exponente con d posiciones decim ales y 4 dígitos par a el exponente Escribe una cadena de car acter es en los siguientes w car acter es Escribe una cadena de car acter es com enzando en la siguiente posición I m pr im e L−1 espacios en blanco seguidos por T o F par a indicar un v alor lógico I gnora las siguientes n posiciones I m pr im e el siguiente elem ento com enzando en el car ácter c I m pr im e el siguiente elem ento com enzando n posiciones antes ( TL) O después ( TR) de la posición actual I m pr im e la cadena de caracter es c 1 c2 ...cn com enzando en la siguiente posición I m pr im e la cadena de caracter es c 1 c2 ...cn com enzando en la siguiente posición Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 E/S sin avance En Fortran 77, cualquier sentencia read o write involucra a registros completos. Hay ocasiones en que resulta conveniente leer/escribir sólo parte de un registro, y leer/escribir el resto más tarde. En F90 esta capacidad la proporciona la E/S sin avance La E/S sin avance elimina la necesidad de que los registros sean leídos como un todo y de que la longitud de los registros sea conocida de antemano. Se especifica mediante advance=’NO En la sentencia read o write e inhibe el avance automático hasta el siguiente registro al ejecutar la sentencia. Si se especifica advance=’YES’ O no se ha especificado nada, entonces se utiliza la forma normal (con avance) de E/S Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 E/S sin avance Se puede especificar E/S con y sin avance en el mismo registro o fichero. Una aplicación común de esta posibilidad es escribir una pregunta en pantalla sin usar avance, y leer la siguiente posición en la pantalla. Por ejemplo: write(*, ’("Tamaño? ")’, advance=’NO’) read(*, ’(I5)’) size A veces es útil determinar cuantos caracteres han sido leídos en una entrada sin avance. Esto se puede conseguir utilizando el especificador size (en la sentencia read), que tiene la forma: size=character_count Al finalizar la lectura sin avance, a la variable entera character_count se le asigna el número de caracteres leídos, excluyendo caracteres de relleno Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 E/S sin avance Se puede detectar si una lectura sin avance lee más allá del final de un registro utilizando el especificador IOSTAT, que tiene la forma: IOSTAT=io_status Al finalizar una sentencia read, a io_status se le asigna un valor que indica si se ha alcanzado un fin de fichero o fin de registro. Es necesario estudiar la documentación del compilador que se utilice para comprobar el valor de IOSTAT devuelto en estas situaciones Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Consulta de la lista de E/S Se utiliza para determinar la longitud de una lista de elementos de salida sin formato. La forma es: INQUIRE(IOLENGTH=length) output−list La longitud puede usarse como valor para el especificador RECL en una operación open subsiguiente. Por ejemplo: integer :: rec_len ... INQUIRE(IOLENGTH=rec_len) name, title, & age, address, tel ... open(unit=1,file=’TEST’,RECL=rec_len, & FORM=’UNFORMATTED’) ... write(1) name, title, age, address, tel ... Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 NAMELIST NAMELIST da la capacidad de agrupar juntas un conjunto de variables para simplificar la E/S. NAMELIST es una sentencia de especificación y ha de aparecer antes que las sentencias ejecutables. La forma general es: NAMELIST/namelist−group−name/variable− list Se trata de de una característica del lenguaje que debería evitarse siempre que sea posible En sentencias read o write el nombre de lista debe especificarse con el especificador NML o puede sustituir al especificador de formato. No se necesitan listas de E/S. Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 NAMELIST Un registro de E/S para un grupo NAMELIST tiene un formato específico: &namelist−group−name var1=x, var2=y, var3=z Es posible omitir elementos cuando se está introduciendo datos y esos elementos no cambian. Tampoco hay que introducir los elementos en el orden especificado por la sentencia NAMELIST El siguiente ejemplo muestra el grupo llamado clothes: integer :: size=2 character (len=4) :: colour(3) = & (/’ red’,’pink’,’blue’/) NAMELIST /clothes/ size, colour write(*, NML = clothes) La salida sería: &CLOTHES size = 2, COLOUR = redpinkblue/ Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Descriptores de edición Los descriptores de edición especifican exactamente cómo se convertirán en cadenas de caracteres los valores en un dispositivo de salida o fichero interno o cómo se convierten en cadenas de caracteres en un dispositivo de entrada o fichero interno Fortran90 posee los siguientes descriptores de edición nuevos con respecto a F77: EN (Engineering − ingeniería). Análogo a E pero con exponentes divisibles por 3 ES (Scientific). Análogo a E pero con el valor antes del punto decimal en [1, 10] B Binario O Octal Z Hexadecimal G Descriptor Generalizado aplicable a todos los tipos intrínsecos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Descriptores de edición El siguiente ejemplo muestra la diferencia entre los descriptores de edición E, EN, ES y G program e_en_es_g_compare implicit none real, dimension(4) :: & x=(/1.234, −0.5, 0.00678, 98765.4/) print ’(4E14.3/4EN14.3/4ES14.3/4G14.3)’,& x, x, x, x end program e_en_es_g_compare La salida sería: 0.123E+01 −0.500E+00 0.678E−02 0.988E+05 1.234E+00 −500.000E−03 6.780E−03 98.765E+03 1.234E+00 −5.000E−01 6.780E−03 9.877E+04 1.23 −0.500 0.678E−02 0.988E+05 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Nuevos especificadores de sentencias Las sentencias INQUIRE, open, read y write no son nuevas, pero se han añadido unos cuantos especificadores nuevos: INQUIRE POSITION=ASIS, REWIND, APPEND o UNDEFINED Indica la posición en el fichero tal como se especificó en la sentencia open ACTION=read, write, READWRITE o UNDEFINED DELIM=APOSTROPHE, QUOTE, NONE o UNDEFINED Indica el carácter utilizado para delimitar constantes de caracteres con E/S dirigida por listas o por NAMELIST. Por defecto es NONE (ninguna) PAD=YES o NO ‘ ES’ signfica que el registro de entrada ha de rellenarse con blancos. El defecto es PAD=‘ ES’ READWRITE=YES, NO o UNKNOWN Indica si para un fichero está permitido o no leer y escribir o no está determinado Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Nuevos especificadores de sentencias INQUIRE read=YES, NO o UNKNOWN Indica si para un fichero está permitido o no leer o no está determinado write=YES, NO o UNKNOWN Indica si para un fichero está permitido o no escribir o no está determinado open Los especificadores POSITION, ACTION, DELIM y PAD tienen los mismos valores y significados que con INQUIRE. Hay un valor adicional: STATUS=REPLACE Si el fichero a abrir no existe, se crea, y si existe se borra y se crea uno nuevo Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Nuevos especificadores de sentencias read/write NML=namelist_name Se utiliza en lugar del especificador de formato cuando se usa un grupo NAMELIST advance=YES o NO read EOR=label Transfiere el control a la sentencia etiquetada cuando ocurre una condición de fin de registro size=character_count Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 7 Procedimientos intrínsecos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos intrínsecos Índice 7.1 − Procedimientos elementales 7.2 − Funciones de consulta 7.3 − Funciones de transformación 7.4 − Subrutinas intrínsecas no elementales 7.5 − Procedimientos intrínsecos para vectores 7.6 − Ejercicios Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos elementales Se especifican para parámetros escalares, pero también son aplicables a parámetros vectoriales compatibles aplicando el procedimiento elemento a elemento Funciones elementales Funciones Numéricas: ceiling(A) El menor entero mayor que A floor(A) El mayor entero que no exceda A modulo(A, P) Resto de A/P (ambos reales o enteros) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos elementales Funciones de caracteres: achar(I) El carácter en la posición I de la secuencia adjustl(string) Ajusta a la izquierda cambiando blancos adjustr(string) Ajusta a la derecha cambiando blancos iachar(C) Posición del carácter C en la secuencia index(string, substring [,back]) Posición de comienzo de substring dentro de string. Si hay más de una subcadena se retorna la posición de la primera (o de la última si back es true) len_trim(string) Longitud de la cadena eliminando blancos Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos elementales Funciones de caracteres: scan(string, SET [,back]) Índice del carácter más a la izquierda (más a la derecha si back es true) de la cadena que pertenece a SET. Cero si ninguno pertenece verify(string, SET [,back]) La posición del carácter más a la izquierda (más a la derecha si back es true) de la cadena que no está en SET. Cero si todos están en SET Funciones de manipulación de bits BTEST(I, POS) True si el bit POS del entero I es 1 IAND(I, J) Y lógico de los bits de I y J IBCLR(I, POS) Pone a 0 el bit POS de I IBITS(I, POS, len) Extrae una secuencia de len bits de I comenzando en el bit POS Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos elementales Funciones de manipulación de bits IBSET(I,POS) Pone a 1 el bit POS de I IEOR(I,J) O−Exclusiva lógica de los bits de I, J IOR(I,J) O−Inclusiva lógica de los bits de I, J ISHFT(I,SHIFT) Valor de I con sus bits rotados SHIFT posiciones a la izquierda (derecha si es negativo) y con ceros por el extremo opuesto ISHFTC(I,SHIFT[,size]) Valor de I con una rotación circular de sus size bits más a la derecha rotados SHIFT posiciones a la izquierda (derecha si es negativo) NOT(I) Complemento lógito de todos los bits de I Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos elementales Funciones de valores de clase selected_int_kind(R) Clase del parámetro de tipo para el rango de exponente dado. Se retorna −1 si no está disponbile esa clase selected_real_kind(P,R) Clase del parámetro de tipo para la precisión y rango de exponente dados. Se retorna −1 si la precisión no está disponble, −2 si no lo está el rango y − 3 si no lo está ninguno de los dos Funciones de manejo de Punto flotante exponent(X) Exponente de X fraction(X) Parte fraccional de X nearest(X, S) El siguiente número diferente (en la máquina en cuestión) en la dirección dada por el signo de S Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos elementales Funciones de manejo de Punto flotante RRSPACING(X) El recíproco del espaciado relativo de los números más próximos a X SCALE(X I) Convierte X a I (real a entero) SET_exponent(X, I) Real cuyo signo y parte fraccional son los de X y cuya parte de exponente es I SPACING(X) Espaciado absoluto de los números cercanos a X Funciones lógicas logical(L [,kind]) Convierte entre clases de números lógicos Subrutina elemental call MVBITS(FROM, FROMPOS, len, TO,TOPOS) Copia len bits de FROM comenzando en la posición FROMPOS hasta la posición TO, comenzando en la posición TOPOS Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones de consulta associated(pointer[,target]) True si el puntero está asociado con el destino. Si target aparece, sólo es true si está asociado con el destino especificado bit_size(I) Número máximo de bits que pueden almacenarse en un entero kind(X) Valor de clase de tipo para X present(A) True si el parámetro opcional A ha sido pasado a la subrutina Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones de consulta Funciones de consulta numéricas digits(X) Número de dígitos significativos en la representación de X epsilon(X) Número que es casi despreciable comparado con 1 en la representación interna de números del tipo de X huge(X) El mayor número en la representación de números del tipo de X maxexponent(X) Máximo exponente en la representación de números del tipo de X minexponent(X) Mínimo exponente en la representación de números del tipo de X precision(X) Precisión decimal en la representación de X Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones de consulta Funciones de consulta numéricas radix(X) Base de la representación de números del tipo de X range(X) Rango del exponente decimal en la representación que incluye X de tipo entero, real y complejo tiny(X) El menor número positivo en la representación de números del tipo de X Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Funciones de Transformación repeat(string, ncopias) Concatena ncopias de string transfer(fuente, MOLD [,size]) La misma representación física que fuente pero de tipo MOLD trim(string) Elimina los espacios en blanco sobrantes de string Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Subrutinas intrínsecas no elementales call date_and_time([DATE][,TIME][,ZONE][VALUES]) Leer la fecha y la hora del reloj interno random_number(HARVEST) Devuelve un número pseudoaleatorio en el rango [0, 1) random_seed([size][,PUT][,GET]) Inicializa o reinicializa el generador de números pseudoaleatorios system_clock([count][,count_RATE][count_max]) Devuelve un entero del reloj interno Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos intrínsecos para vectores Reducciones ALL(MASK[, DIM]) True si todos los elementos son true ANY(MASK[, DIM]) True si algún elemento es true COUNT(MASK [,DIM]) Número de elementos true MAXVAL(ARRAY [,DIM] [,MASK]) Valor del mayor elemento MINVAL(ARRAY [,DIM] [,MASK]) Valor del menor elemento PRODUCT(ARRAY [,DIM] [,MASK]) Producto de los elementos del vector SUM(ARRAY [,DIM] [,MASK]) Suma de los elementos del vector Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos intrínsecos para vectores Consulta allocated(ARRAY) true si el vector ha sido alojado lbound(ARRAY[,DIM]) Límites inferiores del vector shape(fuente) Forma del vector (o escalar) size(ARRAY[,DIM]) Tamaño del vector ubound(ARRAY[,DIM]) Límites superiores del vector Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos intrínsecos para vectores Construcción MERGE(TSOURCE,FSOURCE,MASK) Mezcla vectores de acuerdo a MASK pack(ARRAY,MASK[,VECTOR]) Empaqueta elementos en VECTOR de acuerdo a MASK SPREAD(fuente,DIM,ncopias) Construye un vector duplicando una sección de otro UNPACK(VECTOR,MASK,FIELD) Desempaqueta elementos de vector de acuerdo a MASK Cambio de forma reshape(fuente,shape[,PAD][,ORDER]) Cambia la forma de un vector Posición en un vector MAXLOC(ARRAY[,MASK]) Posición del elemento máximo MINLOC(ARRAY[,MASK]) Posición del elemento mínimo Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos intrínsecos para vectores Manipulación de vectores CSHIFT(ARRAY,SHIFT[,DIM]) Realiza una rotación circular EOSHIFT(ARRAY,SHIFT[,BOUNDARY][,DIM]) Realiza una rotación sin fin TRANSPOSE(MATRIX) Traspone la matriz Aritmética vectorial y matricial DOT_PRODUCT(VECTOR_A,VECTOR_B) Producto escalar MATMUL(MATRIX_A, MATRIX_B) Producto de matrices Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 8 Características redundantes con respecto a Fortran77 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Características redundantes Índice 8.1 − Forma del código fuente 8.2 − Datos 8.3 − Control 8.4 − Procedimientos 8.5 − Entrada/Salida Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Características Redundantes Fortran90 incluye características redundantes (deprecated) que se pueden seguir usando puesto que no está previsto que desaparezcan en la siguiente revisión, pero se desaconseja su utilización en programas nuevos puesto que en el futuro sí es posible que desaparezcan Estas características redundantes se clasifican dentro de 5 categorías: forma del código fuente, datos, control, procedimientos y E/S Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Forma del código fuente El formato fijo, que estaba basado en el aspecto de una tarjeta perforada ha sido sustituido por el formato libre y éste debería usarse en los programas nuevos. Es posible hacer modificaciones sencillas al formato fijo para producir código que es legal tanto en formato libre como fijo Se recomienda la utilización de módulos en lugar de usar líneas INCLUDE. Esta directiva se utilizaba para incluir ficheros texto en un lugar específico Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Datos Fortran 77 tiene dos formas de variables y constantes reales: real y double precision. Han sido sustituidas por el concepto de tipos de datos parametrizados que dan mayor portabilidad numérica. No debería usarse double precision en programas nuevos El peligroso concepto de tipo implícito y la sentencia IMPLICIT no deberían usarse. Se aconseja el uso de implicit none Se recomienda el uso de la nueva forma de declarar variables usando dos puntos (::) entre el tipo y la lista de variables. Asimismo se recomienda usar los atributos parameter, dimension, etc. en la declaración más que en forma de sentencias Generalmente no se necesita la sentencia DATA puesto que las variables pueden ser inicializadas en una sentencia de declaración Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Datos Los bloques COMMON y BLOCK DATA no deberían usarse puesto que el uso de módulos elimina la necesidad de su utilización. De forma análoga, la sentencia EQUIVALENCE ha dejado de ser necesaria por la introducción de los módulos, manejo dinámico de memoria, punteros y la función intrínseca transfer Se recomienda no utilizar nunca el atributo SEQUENCE Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Control Características obsoletas de F77 son: Sentencia if aritmética Terminación compartida de un do. Terminación de un do en una sentencia diferente de continue o end do Variables do y de control de expresiones de tipo real o double precision Sentencias assign y GO TO asignados Saltos hacia un end if desde fuera de un bloque if return alternado Sentencia pause Estas características no deberían usarse en códigos nuevos o revisados. Pueden reemplazarse por sentencias if, do, case, exit y cycle Con la introducción de modernas estructuras de control y de especificaciones de cadenas de caracteres la necesidad de etiquetas es redundante El constructo do y las sentencias exit y cycle sustituyen el uso de la sentencia continue al final de un bucle do Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Control Las sentencias GO TO y GO TO calculados deberían sustituirse por los constructos if, do y case y las sentencias exit y cycle Se puede utilizar el bucle do combinado con la sentencia exit como forma equivalente a los bucles do while Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Procedimientos Las funciones intrínsecas con nombres específicos para diferentes tipos de datos se han sustituido por versiones genéricas. Aún se necesitan nombres específicos cuando una función intrínseca se utiliza como parámetro actual en una llamada La sentencia ENTRY permite que un procedimiento tenga más de un punto de entrada. En F90 es innecesaria puesto que en un módulo cada punto de entrada se convierte en un procedimiento de módulo La utilización de procedimientos de módulo y procedimientos internos hacen innecesarios los procedimientos externos. Los procedimientos externos y la sentencia external son redundantes en F90 Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Entrada / Salida Los especificadores de formato asignados deberían sustituirse por especificaciones de cadenas de caracteres Los especificadores end, EOR y ERR se utilizan cuando ocurren condiciones anómalas en entrada/salida. Se recomienda el uso de IOSTAT en lugar de éstos La entrada/salida usando Namelist es una característica mal diseñada y se desaconseja su utilización Se desaconseja la utilización de 6 descriptores de edición: D, BN, BZ, P, G y X El descriptor de edición D se sustituye por el E y los BN y BZ por el especificador BLANK Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Entrada / Salida El descriptor de edición P permite que los datos numéricos se escalen tanto al hacer entrada o salida. Esto podría conducir a confusión y por tanto se desaconseja El descriptor de edición G es un descriptor generalizado que se puede utilizar al leer o escribir valores de cualquier tipo intrínseco. Se aconseja la utilización de los descritptores I, E, EN, F, L o A puesto que a través de éstos se comprueba que los tipos de datos son los correctos El descritptor de edición X tiene el mismo efecto que el TR y se recomienda el uso de este último Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 9 Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Contenidos del Curso 1.− Introducción 2.− Código fuente, tipos y estructuras de control 3.− Procedimientos y Módulos 4.− Proceso de vectores 5.− Punteros 6.− Nuevas características de entrada/salida 7.− Procedimientos intrínsecos 8.− Características redundantes 9.− Desarrollos futuros Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Desarrollos Futuros Índice 9.1 − Fortran95 9.2 − Arquitecturas paralelas Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Fortran95 Fortran95 se esperaba que hubiera sido simplemente una actualización de F90 consistente fundamentalmente en clarificaciones y correcciones de aquél. El mayor cambio significativo se espera que sea Fortran2000 Sin embargo Fortran95 debería suministrar algunas características nuevas: Sentencia y constructo FORALL FORALL permite asignaciones vectoriales más simples: FORALL (i=1:n) a(i,i)=i FORALL (i=1:n,j=1:n,y(i,j)/=0 .and. & i/=j) x(i,j)=1.0/y(i,j) FORALL (i=1:n) a(i,i)=i b(i)=i*i end Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Fortran95 El atributo PURE que permite una utilización segura de procedimientos en las sentencias FORALL Funciones intrínsecas para la consulta del tiempo de CPU: call CPU_TIME(t1) Parámetros dinámicos en los subprogramas where anidados: where (mask1) ... where (mask2) ... elsewhere ... end where elsewhere ... end where Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Fortran95 Inicialización de entidades Estado inicial para punteros y tipos: real, pointer :: P(:)=>NULL() type string character, pointer :: ch(:)=>NULL() ENDTYPE Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Arquitecturas paralelas Es muy importante en la actualidad que un nuevo estándar como lenguaje de programación permita una compilación y ejecución eficiente tanto en supercomputadores como en arquitecturas convencionales. F90 se dice que es eficiente en arquitecturas convencionales y vectoriales, pero es menos eficiente en arquitecturas paralelas. Sin embargo las tendencias arquitectónicas se han desplazado desde las máquinas vectoriales a los computadores masivamente paralelos. Este interés en arquitecturas paralelas ha conducido al desarrollo de tres estándares de facto: High Performance Fortran (HPF) OpenMP Message Passing Interface (MPI) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 HPF El objetivo de High Performance Fortran (HPF) es suministrar una serie de extensiones a Fortran90 para soportar: Expresión de paralelismo de datos Máxima eficiencia sobre máquinas MIMD y SIMD con acceso no uniforme a memoria Sintonización de código para diferentes arquitecturas Desviación mínima de otros estándares de programación Definir interfaces abiertas a otros lenguajes Potenciar la incorporación de conocimientos de la comunidad científica de computación de altas prestaciones Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 HPF Fotran 90 soporta paralelismo de datos a través de las operaciones sobre vectores y funciones intrínsecas sobre vectores. HPF extiende este soporte con: Directivas de compilación para alineamiento y distribución de datos Características de ejecucón concurrente utilizando la sentencia FORALL La directiva INDEPENDENT que permite al programador informar al compilador del comportamiento de un bucle do o de una sentencia FORALL Funciones intrínsecas para consultar detalles específicos de la arquitectura Una librería de rutinas para soportar operaciones globales Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 OpenMP La API de OpenMP da soporte para programación en paralelo en diversas plataformas de memoria compartida tanto en Fortran como en C/C++ Definida de forma conjunta por un grupo de fabricantes de software y hardware, OpenMP es un modelo portable y escalable que suministra a los programadores en paralelo una interface simple y flexible para el desarrollo de aplicaciones paralelas. http://www.openmp.org/h ttp://www.compunity.org/ Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Un ejemplo en OpenMP * Copy new solution into old !$omp parallel !$omp do do j=1,m do i=1,n uold(i,j) = u(i,j) enddo enddo * Compute stencil, residual, & update !$omp do private(resid) reduction(+:error) do j = 2,m−1 do i = 2,n−1 * Evaluate residual resid = (ax*(uold(i−1,j) + uold(i+1,j)) & + ay*(uold(i,j−1) + uold(i,j+1)) & + b * uold(i,j) − f(i,j))/b * Update solution u(i,j) = uold(i,j) − omega * resid * Accumulate residual error error = error + resid*resid end do enddo !$omp enddo nowait !$omp end parallel Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 MPI MPI (Message Passing Interface) es un estándar propuesto para: Paso de mensajes explícito Programas de aplicaciones Arquitecturas MIMD de memoria distribuida Redes de estaciones de trabajo Se necesita un estándar de este tipo por diferentes motivos: Portabilidad y facilidad de uso Es el momento adecuado para definir un estándar en este campo Construcción de librerías de programas Es un prerequisito para el desarrollo de la industria del software concurrente Suministra a los vendedores de hardware con un conjunto bien definido de rutinas que han de implementar eficientemente Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 MPI MPI contiene: Paso de mensajes punto a punto Rutinas de comunicación colectiva Para movimiento de datos (versiones uno a todos y todos a todos de las rutinas de broadcast, scatter y gather) Cómputos globales (rutinas reduce y scan) Soporte para grupos de procesadores y para contextos de comunicaciones Las comunicaciones combinan contextos y grupos para la seguridad de mensajes y de threads de ejecución Soporte para topologías de aplicación (mallas y grafos) Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002 Referencias Máquina de cálculo científico de la ULL: http://www.ccti.ull.es/cpu/ Fortran 77 http://www.ccti.ull.es/cpu/f77/f77.htm Fortran 90 http://www.ccti.ull.es/cpu/f90/f90.htm Procedimientos intrínsecos en Fortran 90 http://www.ccti.ull.es/cpu/f90/f90_refer ence_manual_9.txt HPF http://www.ccti.ull.es/cpu/hpf/hpf.htm MPI http://www−unix.mcs.anl.gov/mpi/index.html Introducción a las Herramientas Informáticas Unix para el Desarrollo de la Investigación. 2002