2 GEO764 - Programação avançada em Geofísica Entrada e saída no Fortran 90 ] É extenso em assuntos relativos a E/S. ] Permite um grande número de arquivos conectados a um programa, tanto para leitura como escrita. ] Um arquivo é conectado por meio de uma unidade lógica, denotado por um número. ] Cada unidade tem diversas propriedades: FORTRAN 90: Aula no 9 Miscelânea mar-07 \ \ \ \ nome: nome do arquivo conectado ação: se para leitura, escrita, leitura e escrita, etc. estado: existente, novo, substituir, etc. método de acesso: seqüencial, direto. Hédison K. Sato 3 Comando OPEN Comando OPEN: exemplo ] A sintaxe é: OPEN([UNIT=]<inteiro>, FILE=<filename>, & ERR=<label>, STATUS=<status>, ACCESS=<method>,& ACTION=<mode>,RECL=<int-expr>) onde ] <filename> é uma cadeia de caracteres, ] <status> é ’OLD’, ’NEW’, ’REPLACE’, ’SCRATCH’, ’UNKNOWN’ é ’DIRECT’ ou ’SEQUENTIAL’ ] <mode> é ’READ’, ’WRITE’ ou ’READWRITE’ ] se o acesso é direto, <int-expr> precisa ser dado. ] <method> 4 ou ] OPEN(17, FILE=’output.dat’, ERR=10, & STATUS=’REPLACE’, ACCESS=’SEQUENTIAL’,& ACTION=’WRITE’) ] OPEN(14, FILE=’input.dat’, ERR=10, & STATUS=’OLD’, ACCESS=’DIRECT’,& ACTION=’READ’,RECL=nlength) 5 Comando READ 6 Comando READ ] Nem todas especificações podem ser simultâneas. rótulo de um comando executável, <advance-mode> é ’YES’ ou ’NO’ <num-chars> é o número de caracteres lido, <int-expr> é o número do registro (p/ acesso direto) Exemplo: ] <label> READ([UNIT=]<inteiro>, [FMT=]<format>, & IOSTAT=<int-variable>, ERR=<label>, & END=<label>, EOR=<label>, & ADVANCE=<advance-mode>, REC=<int-expr>, & SIZE=<num-chars>) <input-list> ] ] ] ] onde READ(14,FMT=’(3(F10.7,1X))’,REC=iexp) a,b,c READ(*,’(A)’,ADVANCE=’NO’,EOR=12,SIZE=nch) str é um número ou *, ] <format> é uma cadeia de caracteres ou o rótulo de um FORMAT, ] <int-variable> armazena um código de retorno, zero significa “sem erro”, ] <unit> 7 Comando WRITE ] Nem todas especificações podem ser simultâneas. WRITE([UNIT=]<inteiro>, [FMT=]<format>, & IOSTAT=<int-variable>, ERR=<label>, & ADVANCE=<advance-mode>, REC=<int-expr>) & <output-list> onde é um número ou *, ] <format> é uma cadeia de caracteres ou o rótulo de um FORMAT, ] <int-variable> armazena um código de retorno, zero significa “sem erro”, ] <unit> 8 Comando WRITE rótulo de um comando executável, ] <advance-mode> é ’YES’ ou ’NO’ ] <int-expr> é o número do registro (p/ acesso direto) ] Exemplo: ] <label> WRITE(17,FMT=’(I4)’,IOSTAT=istat,ERR=10) IVAL WRITE(*,’(A)’,ADVANCE=’NO’) ’Yello’ Comando FORMAT especificação FMT 9 10 Descritores de edição ] Sumário: w caracteres de dado inteiro Iw Fw.d w caracteres de dado real. (d número de decimais) Ew.dw caracteres de dado real. (d número de decimais) w caracteres de dado lógico Lw w caracteres de dado caracter A[w ] nX pula n caracteres (n espaços) ] Por exemplo: ] FMT= pode especificar tanto o número da linha do comando FORMAT, uma expressão tipo caracter ou um * (asterisco). ] O Fortran 90 tem uma rica sintaxe para formatação. Aqui serão vistos alguns deles. WRITE(17, FMT=”(2X,2I4,1X,’NOME ’,A7)”) I,J,STR READ(14,*) x,y WRITE(*,FMT=10) a,b 10 FORMAT(’vals’, 2(F15.6,2x)) WRITE(*,FMT=’(2X,2(I4,1X),’’name ’’,& A4,F13.5,1X,E13.5)’) & 77778,3,’ABCDEFGHI’,14.45,14.566666666 imprime o dado é formatado por meio de descritores de edição. No exemplo, o seguinte é escrito 11-195 NOME Philip vals -1.051330 **** 3 name ABCD 14.45000 0.14566E+02 333356.000033 11 Outros comandos de E/S ] ] ] ] ] CLOSE - desfaz a conexão da unidade do número especificado no comando. REWIND - reposiciona o apontador no início do arquivo. BACKSPACE - o apontador é reposicionado um registro em direção ao início do arquivo. ENDFILE - força a gravação de um “end-of-file”. Esses comandos têm outros especificações tais como o IOSTAT REWIND(14) BACKSPACE(UNIT=14) ENDFILE(17) CLOSE(UNIT=17,IOSTAT=ival) 12 Procedimentos externos ] ] ] O Fortran 90 admite o procedimento externo (similar ao velho estilo de programação do Fortran 77). Evidentemente, este procedimento não faz parte de um programa ou módulo, devendo ser denotado como sendo um procedimento externo (EXTERNAL). Assim: \ \ \ \ eles podem ser compilados separadamente, podem necessitar uma interface explícita para ser fornecida ao programa usuário, podem ser utilizados como argumentos (somando-se aos intrínsecos), devem conter o especificador IMPLICIT NONE. Sintaxe de subrotina externa não recursiva 13 14 Subrotina externa: exemplo ] SUBROUTINE Ext_1(...) !... CONTAINS ! Procedimentos internos SUBROUTINE Int_1(...) ! comandos executáveis END SUBROUTINE Int_1 ... FUNCTION Int_n(...) ! comandos executáveis END FUNCTION Int_n Um procedimento externo pode chamar um outro procedimento externo. SUBROUTINE sub1(a,b,c) IMPLICIT NONE EXTERNAL sum_sq ! declara ou use INTERFACE REAL :: a,b,c ...; CALL sum_sq(a,b,c,s); ... END SUBROUTINE sub1 chama SUBROUTINE sum_sq(aa,bb,cc,ss) REAL, INTENT(IN) :: aa,bb,cc REAL, INTENT(OUT):: ss ss = aa*aa + bb*bb + cc*cc END SUBROUTINE sum_sq END SUBROUTINE Ext_1 SUBROUTINE Ext_2(...) ! etc... END SUBROUTINE Ext_2 Sintaxe de uma função não recursiva ] Primeiro modelo: 15 Sintaxe de uma função não recursiva ] [<prefixo>] FUNCTION <nome-proc>([<arg-mudos>]) <declaração dos argumentos mudos> <declaração dos objetos locais> ... <comandos executáveis, atribuição do resultado> [CONTAINS <comandos executáveis, atribuição do resultado> [CONTAINS <definições internas ao procedimento>] END [FUNCTION [<nome-proc>]] ] Segundo modelo: FUNCTION <nome-proc>([<arg-mudos>]) <declaração dos argumentos mudos> <declaração do tipo do resultado> <declaração dos objetos locais> ... <definições internas ao procedimento>] END [FUNCTION [<nome-proc>]] O <prefixo> especifica o tipo do resultado. ] O <nome-proc> precisa ser declarado. 16 17 Exemplo de função externa ] Interfaces de procedimentos A função é ativada pela sua presença na expressão, no local em que o resultado é exigido. É possível prover uma interface explícita para um procedimento externo. Assim, considerando a seguinte subrotina, ] ] total = total + maior(a, b, c) ] 18 SUBROUTINE expsum(n,k,x,sum) USE KIND_VALS: ONLY long IMPLICIT NONE INTEGER, INTENT(IN):: n REAL(long), INTENT(IN) :: k,x REAL(long), INTENT(OUT):: sum REAL(long), SAVE:: cool_time ... END SUBROUTINE expsum As funções externas devem ser declaradas como EXTERNAL, senão a INTERFACE deve ser fornecida. INTEGER, EXTERNAL:: largest ] A função é descrita como INTEGER FUNCTION & maior(i,j,k) IMPLICIT NONE; INTEGER, & INTENT(IN):: i,j,k maior = max(i, j, k) END FUNCTION maior FUNCTION maior(i,j,k) IMPLICIT NONE; INTEGER, & INTENT(IN):: i,j,k INTEGER:: maior maior = max(i, j, k) END FUNCTION maior Interfaces de procedimentos (cont.) ] A interface propriamente dita é formada com os comandos que aparecem no intervalo contendo as declarações INTERFACE ! p/ procedimentos externos SUBROUTINE expsum(n,k,x,sum) ! interface USE KIND_VALS: ONLY long INTEGER, INTENT(IN):: n ! interface REAL(long), INTENT(IN) :: k,x ! interface REAL(long), INTENT(OUT):: sum ! interface END SUBROUTINE expsum ! interface END INTERFACE ] As interfaces substituem qualquer comando EXTERNAL e são desnecessários para os procedimentos internos. ! interface ! interface ! interface ! interface ! interface 19 20 O quê aparece na interface? ] ] Uma interface contém somente: \ o cabeçalho SUBROUTINE ou FUNCTION \ o tipo da função (se não estiver definido no cabeçalho), \ declaração dos argumentos mudos, incluindo os atributos. \ o comando END SUBROUTINE ou END FUNCTION As interfaces somente são necessárias para procedimentos externos e eliminam a necessidade de qualquer outra forma de declaração para os procedimentos em questão. 21 Exemplo de interface ] Interfaces obrigatórias O programa inclui uma interface explícita PROGRAM exemplo_de_interface IMPLICIT NONE INTERFACE SUBROUTINE expsum(n,k,x,sum) INTEGER, INTENT(IN):: n REAL, INTENT(IN) :: k,x REAL, INTENT(OUT):: sum END SUBROUTINE expsum END INTERFACE REAL:: sum ...; CALL expnum( 10,0.5,0.1,sum); ... END PROGRAM exemplo_de_interface ] As interfaces explícitas permite compilações separadas, otimizações e verificação dos tipos. Procedimentos como argumentos ] Os procedimentos externos usados como argumentos precisam ser declarados no local da chamada (CALL) como \ INTRINSIC: para os procedimentos internamente construídos. INTRINSIC MVBITS ; REAL, INTRINSIC:: ASIN \ EXTERNAL: para os procedimentos externos ou mudos 22 23 ] Interfaces explícitas são obrigatórias se o procedimento externo tiver \ argumentos mudos que sejam conjuntos de forma a determinar, apontadores ou alvos, \ argumentos opcionais, \ conjuntos ou apontador como resultado (função), \ um resultado que tem uma especificação de comprimento LEN=* herdada (funções caracter). ] e quando a referência: \ tem uma palavra-chave como argumento, \ é uma atribuição definida, \ é uma chamada para um nome genérico, \ é uma chamada para um operador definido (função) Exemplos de procedimentos como argumentos PROGRAM main IMPLICIT NONE INTRINSIC ASIN REAL, EXTERNAL:: my_sin EXTERNAL diffo1 CALL subby(ASIN,my_sin,diffo1,SIN(0.5)) END PROGRAM main EXTERNAL my_subby ; INTEGER, EXTERNAL:: my_fun ] Se o nome de um procedimento interno é usado em um comando EXTERNAL, então somente o procedimento externo homônimo é visível no escopo; o procedimento intrínseco fica indisponível. ] Nos dois casos, o procedimento específico, não o genérico, pode ser usado como argumento efetivo. Procedimentos internos não podem aparecer como argumentos. SUBROUTINE subby(fun1,fun2,sub1,x) IMPLICIT NONE REAL, INTENT(IN):: x REAL, EXTERNAL:: fun1, fun2; EXTERNAL sub1 PRINT *, fun1(x), fun2(x) CALL sub1(fun2(x),fun1,x) END SUBROUTINE subby 24 Exemplos de procedimentos como argumentos (cont.) 25 Comando DATA SUBROUTINE diffo1(y,f,x) IMPLICIT NONE ; REAL, INTENT(IN):: x, y REAL, EXTERNAL:: f PRINT *, ”Diffo1 = ”, y - f(x) END SUBROUTINE diffo1 ] O comando DATA é bom para iniciar seções de conjuntos de forma irregular, complicada. DATA <lista-var-1>/<lista-1-dados>/, & ... <lista-var-n>/<lista-n-dados>/ ] O número de constantes em cada <lista-dados> precisa ser igual ao número de variáveis e elementos de conjuntos da <lista-var> correspondente. Qualquer objeto iniciado por um comando DATA tem o atributo SAVE. REAL FUNCTION my_sin(x) ... END FUNCTION my_sin 27 Exemplo de comando DATA ] Como exemplo, considere iniciar um conjunto 100 × 100 com todos os valores das extremidades iguais a um e o restante, nulo. Este não é um caso simples a ser feito com outro comando, como é com o DATA: REAL:: matriz(100,100) DATA matriz(1, 1:100)/100*1.0/ DATA matriz(100,1:100)/100*1.0/ DATA matriz(2:99, 1)/98*1.0/ DATA matriz(2:99, 100)/98*1.0/ DATA matriz(2:99,2:99)/9604*0.0/ ] A expressão 100*1.0 significa “100 ocorrências de 1.0”, o * é a especificação de repetição. Neste contexto, não deve ser confundido com a multiplicação. 26 Comando DATA laço DO implícito ] No comando DATA, a <lista-var> pode ser especificada por meio de um laço DO implícito. Iniciar um matriz com uma constante ao longo da diagonal e zero nos demais elementos é simples usando este método. A seção é especificada por um laço genioso que é mais expressivo do que a sintaxe de conjunto permitem. REAL:: diag(100,100) DATA (diag(i,i),i=1,100) / 100* 1.0/ DATA ((diag(i,j),diag(j,i), j=i+1,100),i=1,100)& /9900*0.0/ 28 29 Comando GO TO ] ] ] ] ] ] Comando GOTO: exemplo É poderoso mas permite desvios indisciplinados. Pode ser usado para criar desvios para quase todos os locais de uma unidade de programa. Pode ser perigoso. Pode resultar códigos sem estrutura. Pode ser bastante útil. A sintaxe básica é: GOTO <rótulo-numérico> O rótulo precisa existir e estar no mesmo escopo junto a um comando executável. ] ] Usar para tratar situações de exceção em procedimento. SUBROUTINE sub(ierror) INTEGER, INTENT(OUT):: ierror ... ALLOCATE(a(100),STAT=ierror) IF(ierror>0) THEN PRINT*, ”Falha na alocação” RETURN END IF ... END SUBROUTINE ] STOP poderia ter sido usado em lugar do RETURN: STOP ”sub: falha na alocação” A mensagem é opcional. Pode ser uma constante inteira com até 5 dígitos. Considere o seguinte exemplo de uso atroz do GOTO GOTO 10 ! pulo p/ frente 23 CONTINUE i = i-1 IF(I.EQ.0) GOTO 99 10 PRINT*, ”Linha 10” 69 j = j-1 ! “loop” ... IF(j.NE.0) GOTO 69 GOTO 23 ! desvio para trás 99 CONTINUE ] 31 RETURN e STOP 30 Este trecho de código mostra pulos p/ frente, p/ trás e a simulação de um laço DO. O melhor uso do GOTO é sair de uma estrutura muito embutida, em situações críticas. Fortran 95 FORALL ] Comando e estrutura FORALL ] ] FORALL (i=1:100,j=2:100) e(i,j)=b(i,j)+f(i,j) FORALL (i=1:100:3,j=2:100:2,a(i,j)>0) b(i,j)=c(i,j)+d(i,j) e(i,j)=b(i,j)+f(i,j) END FORALL ] Na estrutura FORALL, além de atribuições, podem ser usados os comandos e estruturas WHERE e FORALL Cada comando é executado por completo, em paralelo, antes do seguinte. ] 32 Fortran 95 FORALL (cont.) ] ] 33 34 EFEITO COLATERAL PROIBIDO O FORALL dispõe uma alternativa eficiente para a construção elemento a elemento de um conjunto. Permite explicitar elementos de conjuntos, seções, subcadeias, ou alvos apontados com função dos subscritos dos elementos. ] ] FORALL (<lista-de-triplas>[,<máscara-escalar>]) onde cada tripla é índice=subscrito:subscrito[:passo] ] O comando considera, como no caso do WHERE, que as operações cálculo e atribuição são executadas em qualquer ordem sempre com o mesmo resultado, o que quer dizer, em paralelo. ] 35 EFEITO COLATERAL PROIBIDO ] A chamada a uma função não deve redefinir o valor de uma variável que aparece no mesmo comando ou afete o valor de outra função no mesmo comando. \ Ex.: ] Com relação a esta regra, o comando if, if (expressão lógica) comando é tratado como equivalente a if (expressão lógica) then comando Fortran 95 PURE ] d=max(dist(p,q), dist(q,r)) endif \ O mesmo se aplica para o comando where ] Esta regra permite que quaisquer expressões, argumentos de um único procedimento, sejam avaliadas em qualquer ordem. Para facilitar a compilação otimizada, a regra padrão do Fortran proíbe dependências a certos efeitos colaterais. A regra especifica ser desnecessária a avaliação parcial ou total de todos operandos de uma expressão, se o valor da expressão puder ser determinada de outra forma. \ Ex.: x>y .or. fun(z) ! x, y e z reais e fun uma função lógica A chamada da função é dispensável se x é maior que y. Desta forma, z é indeterminado se o seu valor é modificado por fun. Similarmente, é dispensável a avaliação de subscrito ou subcadeia de um conjunto de tamanho nulo ou objeto caracter de comprimento nulo ] ] A palavra PURE, adicionada aos comandos function e subroutine, assegura que o procedimento não tem efeitos colaterais, ou seja, ficam assegurados que \ Não altera qualquer dos argumentos mudos \ Não altera qualquer parte de uma variável do hospedeiro ou associação \ Não contém variável local com o atributo save \ Não realiza operação com um arquivo externo \ Não contém o comando stop Ex.: \ pure function dist(p,q) Para maiores detalhes, consulte Metcalf e Reid (2000) 36 Fortran 95 ELEMENTAL ] ] ] ] 37 Denomina-se “elemental” os operadores e funções intrínsecas capazes de serem aplicados a escalares e conjuntos. Ex.: c=a+b; c=sin(a) onde a, b e c podem ser conjuntos similares Estende esta característica para os procedimentos não intrínsecos. Ex.: type estat real :: media, var end type estat Fortran 95 ELEMENTAL ] ] ] ] 38 No exemplo anterior, a função tem dois argumentos. Assim, ela é capaz de operar sobre dados com as seguintes combinações de ordem: \ 0-0, 0-1, 1-0, 1-1, 0-2, 2-0, 2-2, ..., 0-7, 7-0, 7-7 22 combinações! \ Se restrito ao Fortran90, teriam que ser escritas 22 versões. A função elementar tem o atributo “pure” também. Não é permitido uma função elementar ter o caráter recursivo. Para maiores detalhes, consulte Metcalf e Reid (2000) elemental function soma(a,b) type (estat) :: soma type (estat), intent(in):: a, b soma%media=a%media+b%media soma%var=a%var+b%var end function soma Fortran 95 Miscelânea ] ] ] O Fortran 95 possui uma função intrínseca NULL para atribuir valor inicial nulo aos apontadores, em lugar do indefinido. \ Também tem mecanismos para atribuir valores iniciais aos componentes dos tipos derivados. O Fortran 95 permite o uso das funções definidas pelo usuário nas expressões de especificação, desde que sejam PURE. Uso da <especificação> no comando END INTERFACE END INTERFACE <especifição> 39 Fortran 95 Miscelânea ] Características removidas em relação às versões anteriores: \ \ \ \ \ Comandos ASSIGN e GOTO atribuídos Comando PAUSE Variáveis de controle do tipo real no comando DO Descritor de edição H (para especificação de formato) Desvio para o ENDIF, de fora do bloco IF 40 41 FIM ] Referências Metcalf, M. e Reid, John, 2000, Fortran 90/95 explained, Oxford Univ. Press. ] Fazer os exercícios.