2 GEO764 - Programação avançada em Geofísica Argumento mudo tipo conjunto ] Dois tipos de conjunto podem ser usados como argumento mudo. ] Forma explícita: todos limites especificados. REAL, DIMENSION(8,8), INTENT(IN)::f_expl O argumento efetivo associado deve ser similar em tamanho e forma. ] Forma assumida: nenhum limite é especificado. Eles são herdados do argumento efetivo. REAL, DIMENSION(:,:), INTENT(IN)::f_as Uma interface explícita deve ser fornecida. ] O argumento mudo não pode ser ALLOCATABLE. FORTRAN 90: Aula no 5 Procedimentos (continuação) março de 07 Hédison K. Sato Conjunto explícito como argumento O argumento efetivo e o mudo têm formas e tamanhos similares. PROGRAM Main IMPLICIT NONE INTEGER, DIMENSION(8,8) :: A1 INTEGER, DIMENSION(64) :: A2 INTEGER, DIMENSION(16,32):: A3 ... CALL subby(A1) ! Certo CALL subby(A2) ! Errado CALL subby(A3(::2,::4)) ! Certo CALL subby(RESHAPE(A2,(/8,8/))) ! Certo ... CONTAINS SUBROUTINE subby(f_expl) INTEGER, DIMENSION(8,8), INTENT(IN):: f_expl ... END SUBROUTINE subby END PROGRAM Main 3 Conjunto como argumento mudo de forma assumida PROGRAM Main IMPLICIT NONE INTEGER, DIMENSION(40) :: X INTEGER, DIMENSION(40,40) :: Y ... CALL jogos(X, Y) CALL jogos(X(1:39:2), Y(2:4,4:4)) CALL jogos(X(1:39:2), Y(2:4,4)) ... CONTAINS SUBROUTINE jogos(a, b) REAL, INTENT(IN):: a(:), b(:,:) ... END SUBROUTINE jogos END PROGRAM Main ! Inválido ] O argumento efetivo não deve estar vetorialmente subscrito, nem ser um conjunto de tamanho assumido. ] No procedimento, o limite inferior inicia em 1. 4 5 Conjuntos automáticos Conjuntos automáticos ] Conjuntos que dependem de argumentos mudos, denominados conjuntos automáticos, PROGRAM Main SIZE e argumentos IMPLICIT NONE mudos podem ser INTEGER :: IX(10,20), IY(3,7) usados para declarar ... conjuntos automáticos CALL une_bus_riot(IX,2,3) CALL une_bus_riot(IY,7,2) A1 e A2 podem ter CONTAINS diferentes tamanhos SUBROUTINE une_bus_riot(A,M,N) em chamadas distintas. INTEGER, INTENT(IN):: M,N INTEGER, INTENT(INOUT):: A(:,:) ! Assumido REAL:: A1(M,N), A2(SIZE(A,1),SIZE(A,2)) ! AUTO ... END SUBROUTINE une_bus_riot END PROGRAM Main \ seus tamanhos são determinados pelos argumentos mudos, e \ eles não podem ter o atributo SAVE, nem ser iniciados. 7 Atributo SAVE e conjuntos SUBROUTINE sub1(dim) REAL,ALLOCATABLE,DIMENSION(:,:),SAVE:: X INTEGER, INTENT(in) ::dim REAL,DIMENSION(dim) :: Y ... IF(.NOT.ALLOCATED(X)) ALLOCATE(X(20,20)) ] Como X tem o atributo SAVE, ele irá reter sua marca de alocado entre as chamadas, caso contrário, ele desapareceria. ] Como Y depende de argumento mudo, ele não pode ter o atributo SAVE. 6 Argumento mudo tipo caracter8 de comprimento explícito ] Neste caso, ele deve, em ordem e variedade, concordar com o argumento efetivo. Todavia, pode ser mais curto. \ PROGRAM Main IMPLICIT NONE CHARACTER(LEN=3), DIMENSION(10):: word ... CALL char_example(word(3), word(6:)) CONTAINS SUBROUTINE char_example(wird, werds) CHARACTER(LEN=10) :: wird CHARACTER(LEN=10) :: werds(:) ... END SUBROUTINE char_example END PROGRAM Main Argumento mudo tipo caracter9 de comprimento assumido ] O argumento mudo caracter pode herdar seu comprimento do argumento efetivo. ] A variedade e ordem precisam, ainda, coincidir. 10 Função retornando conjunto ] Funções podem devolver um conjunto. \ PROGRAM Main IMPLICIT NONE INTEGER, PARAMETER :: m=6 INTEGER, DIMENSION(m,m) :: im1, im2 ... im2=fun(im1,1) DIMENSION não pode CONTAINS aparecer junto a “function” FUNCTION fun(ima,scal) INTEGER, INTENT(IN) :: scal, ima(:,:) INTEGER, DIMENSION(SIZE(ima,1),SIZE(IMA,2))::fun fun=ima*scal END FUNCTION fun END PROGRAM Main \ PROGRAM Main IMPLICIT NONE CHARACTER(LEN=10):: var1 CHARACTER(LEN=20):: var2 CALL char_lady(var1); CALL char_lady(var2) CONTAINS SUBROUTINE char_lady(word) CHARACTER(LEN=*), INTENT(IN):: word ... PRINT*,”Comprimento do arg. e’”, LEN(word) END SUBROUTINE char_lady END PROGRAM Main 11 Função tipo caracter ] Pode retornar uma cadeia caracter. \ FUNCTION reverse(word) CHARACTER(LEN=*), INTENT(IN):: word CHARACTER(LEN=LEN(word)) :: reverse INTEGER :: lw lw=LEN(word) DO i=1,lw reverse(lw+1-i:lw+1-i)=word(i:i) END DO END FUNCTION reverse ] O comprimento da função é determinada por um argumento mudo. 12 Função com efeito colateral ] Considerando INTEGER FUNCTION itera1(a,b) ... a=a*a ! modificação do argumento itera1=a/b e INTEGER FUNCTION itera2(a,b) ... a=a*2 ! modificação do argumento itera2=a/b 13 Procedimentos recursivos 14 Exemplo de função recursiva ] O procedimento recursivo pode chamar a si próprio, tanto direta como indiretamente. ] É uma técnica que produz soluções elegantes. ] Pode incorrer em certa sobrecarga computacional. ] A recursividade deve ser explicitamente declarada. ] A declaração da função precisa conter a palavra-chave RESULT, e a declaração de tipo, se houver, se referirá tanto ao nome da função, como a variável contendo o resultado. ] Cálculo do fatorial usando n! = n ( n - 1)! \ PROGRAM Main IMPLICIT NONE PRINT*, fact(12) CONTAINS RECURSIVE FUNCTION fact(n) RESULT(n_fact) INTEGER, INTENT(IN) :: n INTEGER :: n_fact ! também define fact IF(n > 0)THEN; n_fact=n*fact(n-1) ELSE; n_fact=1 END IF END FUNCTION fact END PROGRAM Main 15 Simulação de uma pilha 16 Implementação de uma pilha 2 push(2) 2 push(6) 6 push(1) 2 1 6 2 Pos 2 6 Pos 1 1 6 2 pop 6 2 6 pop 2 2 6 1 push(6) Pos 2 6 1 2 6 Pos Pos 2 pop push(2) Pos push(1) pop 2 Pos pop Pos pop O topo da pilha é marcado pela seta. O dado entra à sua direita. No “pop”, sai o dado localizado à sua esquerda. 17 Programa sobre pilha: exemplo 18 Módulos: reutilização ] A conversão em MODULE permite seu uso em qualquer lugar. Isto denomina-se encapsulamento. PROGRAM pilha INTEGER, PARAMETER:: size=100 INTEGER SAVE:: store(size), pos=0 ... CONTAINS SUBROUTINE push(i) INTEGER, INTENT(IN) :: i IF(pos<size) THEN; pos=pos+1; store(pos)=i ELSE; STOP ’Erro: pilha cheia’; END IF END SUBROUTINE push SUBROUTINE pop(i) INTEGER, INTENT(OUT) :: i IF(pos>0) THEN; i=store(pos); pos=pos-1 ELSE; STOP ’Erro: pilha vazia’; END IF END SUBROUTINE pop END PROGRAM pilha \ MODULE stack IMPLICIT NONE INTEGER, PARAMETER:: size=100 INTEGER SAVE:: store(size), pos=0 CONTAINS SUBROUTINE push(i) ...... END SUBROUTINE push SUBROUTINE pop(i) ...... END SUBROUTINE pop END MODULE stack 19 Módulos: reutilização ] A pilha pode, agora, ser acessada por outros programas. O comando USE o anexa ao programa. \ PROGRAM Uso_do_Stack USE stack IMPLICIT NONE ... CALL push(14); CALL push(21) CALL pop(i); CALL pop(j) ... END PROGRAM Uso_do_Stack 20 Reutilização - Módulo II ] Pontos levantados no “slide” anterior: \ Dentro de um módulo, funções e subrotinas denominam-se procedimentos módulo. \ Procedimentos módulo podem conter procedimentos internos (como PROGRAMs) \ Objetos em módulo que retenham seus valores devem ter o atributo SAVE. \ Módulos podem também ser usados (USE) por procedimentos e outros módulos. \ Módulos podem ser compilados separadamente, mas antes do programa que os utiliza. 21 Restringindo a visibilidade 22 Restringindo a visibilidade ] No exemplo da pilha, o programa principal tem acesso a store e pos e, assim, pode modificá-los. Isto é perigoso. Os atributos de visibilidade podem ser controlados. PRIVATE :: pos, store, size ! invisível PUBLIC :: pop, push ! visível ] Alternativamente, a questão da visibilidade pode ser feita com um comando ou atributo: PUBLIC ! visível como regra geral INTEGER, PRIVATE, SAVE:: store(size),pos INTEGER, PRIVATE, PARAMETER:: size=100 Assim, no programa principal: CALL push(21) ! OK CALL pop(i) ! OK pos=23 ! proibido store(pos)=99 ! proibido ] Este atributo torna o módulo mais seguro e permite que os elementos internos do módulo sejam alterados sem modificar o programa do usuário. 23 Facilidade renomear no USE ] O comando USE atribui nomes a objetos de um módulo cujas definições públicas estejam acessíveis. Sintaxe: USE <nome_do_módulo> & [,<novo_nome> => <nome_usado>...] ] Exemplo: USE stack, integer_pop => pop O objeto pop passa a ter integer_pop como nome. 24 Comando USE ONLY ] Outra forma de se evitar o choque de nomes, é usar somente os objetos necessários. Sintaxe: USE <nome_do_módulo> [, ONLY: <lista>...] a <lista> também pode conter troca de nome (=>) ] Exemplo: USE stack, ONLY:pos, integer_pop => pop Somente pos e pop passam a ser acessíveis. pop passa a ter integer_pop como nome. O comando ONLY dá ao compilador a opção de incluir somente as entidades requisitadas. 25 Módulo: Forma geral Módulos: uma perspectiva ] A unidade de programa MODULE facilita: MODULE modulo ! Definição de tipos, dados globais, ... CONTAINS SUBROUTINE sub(...) ! comandos executáveis CONTAINS SUBROUTINE int1(...); ...; END SUBROUTINE SUBROUTINE int2(...); ...; END SUBROUTINE END SUBROUTINE sub FUNCTION fun(...) ! comandos executáveis CONTAINS ! etc END FUNCTION fun END MODULE modulo \ A declaração de objetos globais. \ A declaração de procedimentos, incluindo as definições de operadores. \ A extensão semântica. \ O controle do acesso às características acima referidas, por diferentes programas ou unidades de programa. \ O empacotamento de conjuntos completos. 27 FIM ] Fazer os exercícios. 26