FORTRAN

 

HISTÓRICO

 

Para mais informações referentes a historia, acesse o link abaixo:

http://www.eq.uc.pt/~dilupo3/Hist.html

RECURSOS DO FORTRAN90

 

§         Formato livre

§         Nomes de variáveis mais flexíveis

§         Interfaces (comunicação mais segura e eficiente entre os subprogramas)

§         Definição e/ou extensão de operadores pelo usuário

§         Novas operações envolvendo conjuntos ou partes do conjunto

§         Funções intrínsecas novas

§         Novas construções de controle

§         Módulos: classes – definições globais e locais

§         Tipos derivados definidos pelo usuário

§         Novos recursos de entrada e saída

§         Recursividade

§         Portabilidade numérica enriquecida

§         Memória dinâmica e ponteiros

 

ALGUMAS DIFERENÇAS ENTRE

FORTRAN77 E FORTRAN90

 

IDENTIFICADORES

 

Os nomes podem conter mais de 31 caracteres devendo começar sempre com uma letra.

            As letras maiúsculas e minúsculas são indistinguíveis. Aceitam dígitos de 0 até 9.

            Os espaços em brancos e o símbolo underscore ( _ ) são significantes e podem ser utilizados.

            As linhas em branco são significantes e devem ser colocados como sendo comentários.

            As linhas podem conter mais de 132 caracteres.

            Alguns conjuntos de caracteres são considerados como os que constam na tabela1:

 

Tabela1: Caracteres considerados em Fortran90

Caracter

nome

Caracter

nome

 

Espaço em branco

:

Dois pontos

=

Sinal de igual

!

Ponto de exclamação

+

Sinal de adição

 %

Sinal de porcentagem

-

Sinal de subtração

&

E comercial

*

Asterístico

;

Ponto e vírgula

/

Barra inclinada

<

Menor que

(

Parênteses a esquerda

>

Maior que

)

Parênteses a direita

?

Ponto de interogação

,

Vírgula

$

Sinal de dólar

.

Ponto final

`

apóstrofe

 

LINHAS DE CONTINUAÇÃO

 

            As linhas de continuação podem ser feitas colocando-se o símbolo & no final da primeira linha. No entanto devido a problemas de portabilidade em alguns casos recomenda-se utilizar a forma concatenada.

 

EXEMPLO :   PRINT *, `Esta constante possui caracter muito longo sendo mais` //

                         +  ` recomendável o uso de uma linha de continuação`

 

            O Fortran90 permite que se utilize mais de 39 linhas de continuação.

 

LINHAS DE COMANDO MÚLTIPLOS

 

            Mais de um comando pode ser colocado na mesma linha colocando-se o separador de comandos cujo símbolo é ( ; ).

 

EXEMPLO:  i=i+1; j=j*k

 

            Se forem colocados vários símbolos (;) seguidos apenas um será considerado.

            Caso este símbolo seja colocado no final de uma linha também será ignorado.

COMENTÁRIOS

 

            As linhas de comentários são feitas utilizando o símbolo ! no início da linha. Quando estes comentários são inseridos ao longo do programa este símbolo deve ser colocado no início e no fim.

 

OPERADORES LÓGICOS

 

            Em Fortran90 os operadores lógicos podem ser representados por símbolos como mostra a tabela2:

 

 

Tabela2: Operadores lógicos utilizados em Fortran77 e seu correspondente em Fortran90

OPERADORES LÓGICOS

SÍMBOLO EM FORTRAN77

SÍMBOLO EM FORTRAN90

Maior

.GT.

>

Menor

.LT.

<

Maior ou igual

.GE.

>=

Menor ou igual

.LE.

<=

Igual

.EQ.

= =

Não igual

.NE.

/=

 

 

 


EXEMPLO:  IF ((a <=  6) .OR. (b > 5)) THEN

 

EXEMPLO DE UM PROGRAMA EM FORTRAN90 NO

FORMATO LIVRE

 

PROGRAM área_e_circunferência_de_circulo

! Este programa encontra e mostra a área e a circunferência de um circulo.

!O programa utiliza o raio do circulo e a unidade de medida definidos pelo usuário.

!

!Declarações

REAL pi ; PARAMETER (pi=3.141593)  ! linhas de comando múltiplos

REAL r, área, circunferência

CHARACTER *12 unidade

!

!Leitura dos valores de raio e unidade.

PRINT *, `Entre com a unidade a ser utilizada (entre apóstrofes)` ; READ *, unidade

PRINT *, `Entre com o raio ( em `, unidade, `)`  ; READ *, r

!

!Encontrando a área

área=pi*r**2

!

!Encontrando a circunferência

circunferência=2.0*pi*r

!

!Imprimir os valores da área e da circunferência

PRINT *, `A área é de`, área, unidades, `quadrados`

PRINT *, `A circunferência é de`, circunferência, ` `, unidade

!

END

 

COMANDOS E ATRIBUTOS EM FORTRAN90

 

Em fortran90 alguns comandos de especificações que são comandos não executáveis que servem apenas para declarar atribuições de alguns objetos podem ser utilizados como comandos de declaração de tipos. Abordaremos a seguir alguns destes comandos.

 

 INCLUDE

            Apesar de não ser propriamente um comando permite ao processador incluir linhas neste ponto do programa. Muito utilizado ao incluir subprogramas dentro do programa principal. Este texto inserido pode conter outros INCLUDE, cadeia de INCLUDEs, cuja quantidade permitida depende de cada processador.

            A primeira linha após o INCLUDE não pode ser uma linha de continuação e a última linha não pode ser continuada.

 

COMANDOS DE DECLARAÇÃO DE TIPOS

 

            Estes comandos servem para declarar as propriedades específicas dos dados de alguns objetos ou funções. Pode-se utilizar os tipos utilizados em Fortran77 como o INTEGER, REAL, LOGICAL, CHARACTER e em FORTRAN90 temos os acréscimo de BYTE e TYPE além dos seguintes atributos:

ALLOCATABLE, DIMENSION, EXTERNAL, INTENT, INTRINSIC, OPTIONAL, PARAMETER, POINTER, PRIVATE, PUBLIC, SAVE, TARGET, e outros que variam de compilador para compilador.

            Existem compatibilidade entre os atributos que constam na tabela3:

 

Tabela3: Compatibilidade de alguns comandos.

atributos

Compatível com:

ALLOCATABLE

DIMENSION, PRIVATE, PUBLIC, SAVE, TARGET

DIMENSION

ALLOCATABLE,  INTENT, OPTIONAL, POINTER, PRIVATE, PUBLIC, SAVE, TARGET

EXTERNAL

OPTIONAL, PRIVATE, PUBLIC

INTENT

DIMENSION, OPTIONAL, TARGET

INTRINSIC

PRIVATE, PUBLIC

OPTIONAL

DIMENSION, EXTERNAL, INTENT, POINTER, TARGET

PARAMETER

PRIVATE, PUBLIC

POINTER

DIMENSION, OPTIONAL, PRIVATE, PUBLIC, SAVE

PRIVATE

ALLOCATABLE, DIMENSION, EXTERNAL, INTRINSIC, PARAMETER, POINTER, SAVE, TARGET

 

            Uma forma recomendada para otimizar os programas é de não misturar os tipos de variáveis na execução de uma operação no corpo do programa. Por exemplo, a forma em que é armazenada na memória as variáveis do tipo INTEGER e REAL são diferentes o que acaba provocando uma adaptação forçada de um dos tipos em outro para que o programa seja executado. Assim, recomenda-se que esses tipos não sejam misturados em uma operação aritmética. EXEMPLO:  y = 2.0 * 5.4 + 1.0

 

ALLOCATABLE

 

            Este commando especifica que um conjunto com tamanho indeterminado. O tamanho é especificado quando o comando ALLOCATE for executado. Quando o conjunto de tamanho indeterminado não for mais necessário este pode ser retirado executando o comando DEALLOCATE. Este comando pode aparecer como um atributo ou um comando nas seguintes sintaxes:

Comando de declaração de tipo

Tipo ALLOCATABLE[, lista_atr] :: conjunto[(tamanho)]

Em que:  tipo é o tipo de dados  e  lista_atr é a lista de atributos específicos cujo uso é opcional.

EXEMPLO: REAL, ALLOCATABLE :: Z ( : , : , : )

 

Comando

ALLOCATABLE [ :: ] conjunto[(tamanho)]

EXEMPLO: REAL A, B ( : )

                     ALLOCATABLE :: A ( : , : ), B

 

COMMON

            Este comando define um ou mais áreas contíguas, ou blocos de um armazenamento físico que pode ser acessado por qualquer programa executável. O comando COMMON define também a ordem em que as variáveis e os conjuntos são armazenados em cada bloco prevenindo a perda de dados.

            O bloco do COMMON pode ser nomeado ou não, estes últimos são geralmente chamados de ‘blank common’. Os blocos COMMON possuem a seguinte sintaxe:

 

COMMON /nome_do_bloco/ lista_variáveis

 

EXEMPLO: 

INTEGER A(20)

REAL Y(20)

COMMON / QUANTA/ A, Y

 

Não é recomendável o uso deste comando.

DATA

            Este comando atribui os valores iniciais para alguns variáveis antes da execução do programa. Possui a seguinte sintaxe:

DATA lista_variáveis /lista_de_constantes/

 

EXEMPLO:

 DIMENSION A(10,10)

 DATA A / 100*1.0/

 DATA ((A (i,j), i = 1,5,2), j=1,5) /15 * 1.0/

 

DIMENSION

            Este comando especifica que o objeto é um conjunto e define seu tamanho. Pode ser declarado como um comando de atribuição ou um comando propriamente dito. Sua sintaxe tem a seguinte forma:

Comando de declaração de tipo

Tipo DIMENSION (especificação do conjunto), lista_atributos :: nome_do_conjunto

EXEMPLO: REAL, DIMENSION(10,10) :: A

                     REAL, ALLOCATABLE, DIMENSION ( : ) :: E

 

Comando

DIMENSION [ :: ] nome_do_conjunto

EXEMPLO: DIMENSION MARK (4,4,4,4)

 

EQUIVALENCE

            Este comando especifica que a mesma área de armazenamento da memória serão compartilhados por dois ou mais objetos em um programa. Possui a seguinte sintaxe:

 

EQUIVALENCE (lista_variáveis)

 

EXEMPLO:

            INTEGER A(20)

            REAL Y(20)

            EQUIVALENCE (A,Y)

 

OBS. O comando EQUIVALENCE pode ser utilizado por tipos diferentes de números como no exemplo acima mas não podemos misturar variáveis do tipo CHARACTER com REAL e INTEGER.

            No entanto, este comando não pode ser utilizado com:  argumentos, conjuntos que  com comando ALLOCATABLE, ponteiro, nome de função ou resultado desta,  nome constante, componente de estrutura.

            Portanto, apesar da sua existência seu uso em computação científica não é recomendável.

 

EXTERNAL

           

            Este comando permite que programas ou argumentos externos sejam utilizados com argumentos atualizados. EXTERNAL pode ser utilizado como comando de declaração de tipos ou como comando segundo a sintaxe:

 

Comando de declaração de tipos

Tipo EXTERNAL [,lista_atr] :: nome_do_procedimento_externo

EXEMPLO:

PROGRAM test

¼

INTEGER, EXTERNAL :: beta

LOGICAL, EXTERNAL :: cós

¼

CALL sub(beta)

 

Comando

EXTERNAL nome_do_procedimento_externo

EXEMPLO:

EXTERNAL FACET

CALL BAR(FACET)

 

OBS. Como comando de declaração de tipos somente funções podem ser declarados como EXTERNAL.

            Um nome declarado como EXTERNAL assume-se que é o nome de um procedimento externo ao programa assim, mesmo que o nome seja igual a de alguma função intrínseca o programa irá procurar algum procedimento externo com esse nome.

            O nome de um programa de blocos não deve ser utilizado no comando de declaração de tipos.

 

INTENT

 

            Este comando especifica a intenção de utilizar um ou mais argumentos. Ele pode ser um comando de declaração de tipo ou um comando próprio seguindo as seguintes sintaxes:

 

Comando de declaração de tipos

Tipo INTENT (especificadores) [ , lista_atributos] :: nome_argumentos

EXEMPLO:

SUBROUTINE teste (i,j)

    INTEGER, INTENT (IN) :: I  

    INTEGER, INTENT (OUT), DIMENSION ( i ) :: j

    ¼

 

Comando

INTENT (especificadores) [ :: ] nome_argumentos

EXEMPLO:

SUBROUTINE teste ( a, b, x )

  INTENT (INOUT) :: a, b

  ¼

os especificadores podem ser:

 

OBS. O comando INTENT deve ser utilizado na parte das especificações de um subprograma ou no corpo da interface.

OPTIONAL

 

            Este commando permite a omissão de argumentos em um procedimento. OPTIONAL pode tanto ser um comando de declaração de tipos ou um comando seguindo a seguinte sintaxe:

 

Comando de declaração de tipos

Tipo OPTIONAL [ , lista_atributos] :: nome-argumentos

EXEMPLO:

SUBROUTINE teste (a)

REAL, OPTIONAL, DIMENSION (-10 : 2) :: a

END SUBROUTINE

 

Comando

OPTIONAL [ :: ] nome_argumentos

EXEMPLO:

SUBROUTINE teste (a, b, l, x)

   OPTIONAL :: b

   ¼

  IF ( .NOT. PRESENT(b) ) THEN

            B=1.0

  END IF

 

OBS. O atributo OPTIONAL só pode aparecer em um subprograma ou no corpo de interface.

 

POINTER

 

            Este comando especifica que o objeto é um ponteiro. Um ponteiro não contém os dados, mas aponta para uma variável escalar ou um conjunto onde os dados estão armazenados. Este comando pode assumir as formas de comando propriamente dito ou comando de declaração de tipos segundo as seguintes sintaxes:

 

Comando de declaração de tipos

Tipo POINTER [ , lista_atributos] :: pointer [(dimensão_do_conjunto)]

EXEMPLO:

TYPE (SYSTEM), POINTER :: CURRENT, LAST

REAL, DIMENSION ( : , : ), POINTER :: i, j, reverse

 

Comando

POINTER [ :: ] pointer [(dimensão_do_conjunto)]

EXEMPLO:

TYPE (SYSTEM) :: TODAYS

POINTER :: TODAYS, a ( : , : )

 

OBS. Um ponteiro não deve ser referido ou definido se não for associado com um alvo que pode ser referido ou definido. Um objeto com atributo de POINTER não possui um local para armazená-lo inicialmente. Caso o ponteiro seja um conjunto e tenha o atributo DIMENSION no programa deve ser declarado que este é um conjunto de tamanho indefinido inicialmente.

POINTER não pode ser utilizado nos comandos DATA e EQUIVALENCE, por exemplo.

 

PRIVATE e PUBLIC

 

            Este comando especifica a acessibilidade dos elementos contidos no MODULE. Este comando também assume as duas forma citadas como nos demais comandos segundo a sintaxe:

 

Comando de declaração de tipos

Tipo PRIVATE [ , lista_atributos] :: entidade

Tipo PUBLIC [ , lista_atributos] :: entidade

EXEMPLO:

REAL, PRIVATE :: A, B, C

 

Comando

PRIVATE [[::] entidade]

PUBLIC [[::] entidade]

EXEMPLO:

MODULE SOME_DATA

            REAL ALL_B

            PUBLIC ALL_B

            TYPE RESTRICTED_DATA

                        REAL LOCAL_C

                        DIMENSION LOCAL_C (50)

            END TYPE RESTRICTED

            PRIVATE RESTRICTED_DATA

END MODULE

 

OBS. Se um tipo derivado for declarado como PRIVATE como no exemplo anterior seus components também serão privados e não serão acessíveis fora do módulo. Assim, no exemplo acima, embora os dados e as definições do modulo sejam acessíveis pois foi declarado como PUBLIC os componentes e as especificações do tipo derivado não são.

 

SAVE

            O commando SAVE permite que os valores e as definições dos objetos utilizados em um subprogramas sejam retidos após a execução dos comandos RETURN e END. Isto serve para melhorar a portabilidade dos subprogramas. No entanto, este comando não pode ser utilizado para: blank common, um objeto que esteja dentro de um bloco COMMON, um argumento, um procedimento, um resultado de uma função, um objeto do comando PARAMETER. Um comando SAVE não tem efeito sobre os dados de um programa principal. Este comando segue duas sintaxes:

 

Comando de declaração de tipos

Tipo SAVE [ , lista_atributos] :: [nome_objeto]

EXEMPLO:

SUBROUTINE teste ( )

            REAL, SAVE :: x, y

 

Comando

SAVE [nome_objeto]

EXEMPLO:

SAVE A, /BLOCK_B/ , C

 

TARGET

 

            Este comando especifica que um objeto pode se tornar um alvo de um ponteiro e segue as seguintes sintaxes:

 

Comando de declaração de tipos

Tipo TARGET [ , lista_atributos] :: nome_do_objeto(especificação de conjunto)

EXEMPLO:

TYPE (SYSTEM), TARGET :: FIRST

REAL, DIMENSION (20,20), TARGET :: C, D

 

Comando

TARGET [ :: ] nome_do_objeto(especificações do conjunto)

EXEMPLO:

TARGET :: C (50,50), D

 

Estrutura de Controle

 

CASE

 

O comando CASE é uma outra alternativa de se selecionar a estrutura do programa de forma similar ao comando IF. A linha deve começar com o comando SELECT CASE seguido da variável que determina qual das alternativas deve ser executado. Este comando deve ser finalizado com o comando END SELECT. Apesar de ser mais fácil que o comando IF a variável controladora deve ser do tipo INTEGER ou CHARACTER.

A sua sintaxe é a seguinte:

 

SELECT CASE (variável controladora)

CASE (opção 1)

Bloco de comandos da opção 1

CASE (opção 2)

Bloco de comandos da opção 2

...

CASE DEFAULT

Bloco de comandos do Default

END SELECT

 

EXEMPLO:

 

PROGRAM preco_de_entrada

!Este programa mostra o preço do espetaculo de acordo com o numero

!da cadeira escolhida. Para a cadeira de numero 50 o preço e de 50.00 reais

!de 100 a 140 e de 200 a 240, o preço e de 25.00 reais, para 300 a 340 e 20.00

!reais e de 400 a 440 reais e de 15.00 reais.

INTEGER section

PRINT *, `Entre com o numero da cadeira escolhida`; READ *, section

SELECT CASE (section)

CASE (50)

PRINT *, `preco=50.00`

CASE (100:140, 200:240)

PRINT *, `preco=25.00`

CASE (300:340)

PRINT *, `preco=20.00`

CASE (400:440)

PRINT *, `preco=15.00`

CASE DEFAULT

PRINT *, `numero de cadeira invalida`

END SELECT

END

 

Loops do DO e Repetições em programas

 

            Existem algumas diferenças significantes entre as estruturas dos loops do comando DO em Fortran77 e fortran90.  Em fortran90 somente as variáveis do tipo INTEGER devem ser utilizados como variáveis controladoras dos loops enquanto que em fortran77, embora seja desencorajada, também é possível o uso de variáveis tipo REAL.

 

WHILE

            Este é um commando padrão de Fortran90 embora algumas versões de Fortran77 permitam o seu uso. É utilizado para repetições de um determinado comando ou blocos de comandos enquanto uma determinada condição seja satisfeita.

            A sua sintaxe em Fortran90 é a seguinte:

 

DO WHILE (condição)

            Blocos de comando

END DO

 EXEMPLO:

 

PROGRAM repetições

!Este programa pede para digitar um numero e executa-o ate que

!o numero digitado seja 0.

INTEGER n

DO WHILE ( n .NE. 0)

            PRINT *, `Entre com o valor de n: `

            READ *, n

END DO

 

EXIT e CYCLE

            Em fortran90 o comando EXIT permite a saída do loop que estiver sendo executado assim como a repetição do loop através do comando CYCLE. No exemplo abaixo, o loop do comando DO é executado normalmente até a leitura do décimo valor. Se o valor lido for igual a 0 (zero) o comando EXIT é executado provocando a saída do comando DO. Caso o valor lido seja negativo, o comando CYCLE é executado ignorando os demais linhas de comandos seguintes e provocando a execução imediata do próximo loop.

 

EXEMPLO:

 produto=1

DO i=1,10

            PRINT *, `Entre com o valor do dado`

            READ *, item

            IF (item = 0) EXIT

            IF (item < 0) CYCLE

            produto = produto * item

END DO

 Neste caso, para execução de loops infinitos, Fortran90 permite a omissão da variável controladora do loop.

 produto=1

DO

            PRINT *, `Entre com o valor do dado`

            READ *, item

            IF (item = 0) EXIT

            IF (item < 0) CYCLE

            produto = produto * item

END DO

SUBPROGRAMAS/ SUBROTINAS

 

Funções definidas pelo usuário

            Em Fortran90 o usuário pode definir funções que podem ser utilizadas nos programas. Estas funções possuem a seguinte sintaxe:

 

Tipo_da_função FUNCTION nome_da_função (lista de argumentos)

Interface da função

Declarações de variáveis da lista de argumentos

Declarações de variáveis locais

Corpo da função

 

EXEMPLO:

REAL FUNCTION DOAREA (R)

!Esta função calcula a área de um círculo utilizando o raio R.

!Precondition: o R deve ser definido

!Poscondition: o resultado da função deve ser apenas o valor da área do círculo.

!

!Declaração de variáveis da lista de argumentos

REAL R

!

!Declaração de variáveis locais

REAL pi

PARAMETER (pi=3.14159)

!

!Corpo da função

DOAREA = pi * R ** 2

!

!saída da função

RETURN

END

            Para que o resultado da função seja transferido para o programa principal, o nome_da_função deve ser necessariamente igual ao nome da variável que recebe o resultado da função como mostra o exemplo acima.

            O último comando executado por uma função deve ser o RETURN para que o controle seja imediatamente transferido ao programa que utilizou a referida função.

            No início da função indica que a função DOAREA fornece um resultado do tipo REAL que deve possuir apenas uma variável, R, compartilhada pelo programa principal. A interface da função é necessária pois fornece as informações necessárias sobre o que esta função executa. Deverá existir uma linha que diga quais as informações necessárias para que esta função funcione chamada de precondition e uma outra linha dizendo qual o resultado que a função deve fornecer caso esta funcione chamada de poscondition.

 

Chamando as funções definidas pelo usuário

 

            Estas funções não deixam de ser um subprograma. Assim, elas devem ser chamadas para serem executadas pelo programa principal. A forma utilizada é a mesma das funções de uma biblioteca colocando-o em uma expressão.

 

EXEMPLO:

 

PROGRAM CIRCLE

!Este programa calcula e imprime a área de um circulo.

!

!Declarações

REAL radius, area

CHARACTER *12 units

REAL DOAREA

 

!Leitura dos valores de radius e units

PRINT *, `Entre com a unidade a ser utilizada (entre apóstrofes)`

READ *, units

PRINT *, `Entre com o raio ( em `, units, `)`

READ *, radius

!

!Encontrando a área

area = DOAREA(radius)

!

!Imprimindo os valores de área

PRINT *, `A área é de `, area, units, `quadrados`

!

STOP

END

 

            Pode-se verificar que os nomes das variáveis, entre parênteses, que são as compartilhadas entre a função e o programa principal são diferentes. Isto porque temos células de memórias para a variável radius no programa principal e uma célula de memória para o argumento R na função. Assim, quando o valor da variável radius é definido no programa principal este não afeta o valor do argumento R da função que só é definido quando a função DOAREA é chamada. Assim, a cada chamada da função este valor é redefinido. Da mesma forma, as variáveis locais possuem uma outra célula de memória para armazenar os valores atribuídos e desta maneira devem ser declarados separadamente dos argumentos compartilhados.

            Algumas regras devem ser obedecidas em relação ao programa principal e a função.

1-     o número de variáveis utilizados no programa principal devem ser os mesmos dos usados na função.

2-     Cada argumento deve ser do mesmo tipo e na mesma ordem dos argumentos correspondentes na função.

3-     Não esquecer de declarar o tipo do resultado fornecido pela função no programa principal que deve ser igual ao indicado na própria função.

4-     Não esquecer de declarar os tipos de todos os argumentos da função na própria função.

 

Subprogramas recursivos

 

Um subprograma recursivo é aquele que chama a ele mesmo. A função a seguir é um subprograma recursivo. Observa-se que neste exemplo, a função não possui mais o tipo do resultado apresentado no entanto possui o comando RECURSIVE indicando que esta função é do tipo recursivo. Além do nome e dos argumentos utilizados para obter o resultado da função, RESULT(res), temos entre eles o nome factorial(N) que é o `resultado recursivo`.

 

EXEMPLO:

 

RECURSIVE FUNCTION factorial (N) RESULT (res)

! Calcula o fatorial de N recursivamente

! Precondition: N deve ser maior ou igual a 0

! Poscondition: res é o resultado final

!

!declaração de argumentos

INTEGER N, res

!

IF (N <= 1) THEN

            res= 1

ELSE

            res= N * factorial (N-1)

END IF

!

RETURN

END

 

Subprograma interno

 

            Em fortran90 tem-se a possibilidade de declarar um ou mais subprogramas internos antes do comando END do programa principal. O primeiro subprograma deve vir precedido do comando CONTAINS e neste caso, as variáveis dos subprogramas não necessitam ser redeclarados nos subprogramas.

            A sua sintexe é:

 

CONTAINS

            SUBROUTINE nome_da_subrotina (argumentos)

                 Declarações locais

                 Corpo da subrotina

            END SUBROUTINE

 

            FUNCTION nome_da_função (argumentos)

                 Declarações locais

                 Corpo da função

 

            END FUNCTION

 

EXEMPLO:

 

PROGRAM ordenar

!Coloca dois valores em ordem crescente

!

!declarações

REAL x, y

!

PRINT *, `digite dois números quaisquer`

READ *, x, y

!

CALL arrumar

PRINT *, `O menor valor é`, x

PRINT *, `O maior valor é`, y

STOP

!

CONTAINS

            SUBROUTINE arrumar

            !ordena os valores de x e y

                REAL temp

                IF (x > y) THEN

                        temp=x

                        x=y

                        y=temp

                END IF

                RETURN

            END SUBROUTINE arrumar

!

END

 

CONJUNTOS / ARRAYS

 

            Em Fortran90 é se possível trabalhar com os conjuntos como se fossem um único objeto. Assim, pode-se realizar todas as operações com conjuntos facilitando a sua escrita.

 

Declarações

         A declaração de conjuntos pode ser feita segundo as notaçães de Fortran77.

            REAL X (6)

            Ou então pelo Fortran90 acrescentando o comando DIMENSION.

                        REAL, DIMENSION(6) :: X

 

Isto permite que o compilador associe 6 espaços na memória chamado X que devem ser adjacentes um em relação ao outro. Para referir-se a um único elemento deste vetor deve-se especificar o nome do conjunto e identificar o elemento desejado. Assim, a notação X(3) indica o terceiro elemento do conjunto X.

O armazenamento dos conjuntos na memória é a seguinte:

Para conjuntos unidimensionais como o vetor X(6) temos

 

X(1)

X(2)

X(3)

X(4)

X(5)

X(6)

16.0

12.0

28.0

26.0

2.5

12.0

 

            O subscrito é utilizado para diferenciar os elementos do conjunto individualmente e permitir a manipulação destes. Qualquer valor inteiro pode ser utilizado como subscrito.

             Em Fortran77 cada operação aritmética ou operação relacional deveria ser feita de elemento por elemento. Em Fortran90 um operador pode efetuar esta operação sobre todos os elementos do conjunto.

 

EXEMPLO

 

INTEGER A(10), B(10), C(10)

C = A + B

 

            Os conjuntos possui alguns comandos específicos para eles além de novas funções intrínsecas específicas para estes.

 

WHERE

            Permite limitar os conjuntos para apenas alguns elementos. Este comando serve tanto para conjuntos unidimensionais como para conjunto multidimensionais.

            A sua sintaxe:

 

WHERE expressão_lógica_de_conjunto

            Operações executadas com o conjunto

ELSEWHERE

            Operações executadas com conjunto

END WHERE

 

EXEMPLO:

 

WHERE (A > B)

            C = A - B

ELSEWHERE

            C = B - A

END WHERE

 

            Todas as funções intrínsecas existentes podem ser utilizadas para os conjuntos. No entanto, em Fortran90 existem algumas novas funções intrínsecas específicos para conjuntos. A seguir apresentamos algumas funções intrínsecas para conjuntos unidimensionais.

 

 

Funções intrínsecas

Execução

MAXVAL (A)

Mostra o maior valor do conjunto A

MINVAL (A)

Mostra o menor valor do conjunto A

DOT_PRODUCT (A,B)

Mostra o produto entre os conjuntos A e B

SUM (A)

Mostra a soma dos elementos de A

PRODUCT (A)

Mostra o produto dos elementos de A

ALL (T)

Mostra .TRUE. caso todos os elementos de T sejam verdadeiros

ANY (T)

Mostra .TRUE. caso qualquer elemento de T for verdadeiro

COUNT (T)

Conta quantos elementos em T seja .TRUE.

  

CONJUNTOS MULTIDIMENSIONAIS

 

Declarações

            Neste caso, as declarações podem ser como as do Fortran77. Assim um conjunto bi-dimensional TABLE com tamanhos 7, 5 seria declarada como:

 

REAL TABLE (7,5)

 Ou em Fortran90 utilizando a notação do DIMENSION

 

REAL, DIMENSION (7,5) :: TABLE

Para conjuntos bidimensionais a armazenagem do conjunto na memória se procede da seguinte maneira:

            Para um conjunto chamado BAN (3,4) temos:

1

BAN(1,1)

4

BAN(1,2)

7

BAN(1,3)

10

BAN(1,4)

2

BAN(2,1)

5

BAN(2,2)

8

BAN(2,3)

11

BAN(2,4)

3

BAN(3,1)

6

BAN(3,2)

9

BAN(3,3)

12

BAN(3,4)

                            ­                    ­

                        Posições na memória

 

E através dos subscritos podem-se acessar um subconjunto deste da como nos exemplos a seguir:

 

BAN (1:2, 2:4)   ! um conjunto bidimensional com linha de subscrito 1 a 2 e colunas

     de subscrito 2 a 4

BAN ( : ,  :3)      ! um conjunto bimensional com linhas de subscrito 1 a 3 e colunas

     de subscrito 1 a 3

 

            Todas as funções intrínsecas podem ser utilizadas nos conjuntos multidimensionais com exeção do DOT_PRODUT. Além destes existem outras funções intrínsecas para conujuntos multidimensionais como:

 

Funções intrínsecas

Execução

LBOUND (M)

Mostra uma fila do conjunto cujos elementos representam os menores subscritos de cada dimensão

SHAPE (M)

Mostra a fila do conjunto cujos elementos representam o número de elementos em cada dimensão

SIZE (M)

Mostra o número de elementos do conjunto M

UBOUND (M)

Mostra uma fila do conjunto cujos elementos representam os maiores subscritos de cada dimensão

 

Para matrizes tem-se outras funções específicas como:

MATMUL ( M, P)  -  multiplica a matriz M pela matriz P

TRANSPOSE ( N) – faz a transposta da matriz N

 

            Um dos ‘gargalos’ existentes nas programações em Fortran são as linhas de comando que utilizam os loops do DO além das operações de I/O .  Assim, em Fortran90, sua leitura direta dos dados de um conjunto permitem que sejam minimizadas as operações com as linhas do DO eliminando as linhas de comando com os loops necessários para leitura de dados. Uma outra maneira de otimizar o programa é agrupar as operações de entrada e saída de modo a não ficarem espalhadas ao longo do programa principalmente dentro dos blocos de DO. Isto serve para que as operações de entrada sejam feitas de uma vez e não aos poucos.

 

MODULES

 

         Fortran90 permite ao programador encapsular um conjunto de declarações para variáveis e conjuntos e subprogramas a utilizar estes dados. Os módulos podem ser utilizados para simplificar as especificações do COMMON.

            Um módulo pode ser nomeado e conter declarações de conjuntos, variáveis e dados com PARAMETER como mostra o exemplo a seguir:

 

MODULE blank

            INTEGER max_size

            PARAMETER (max_size = 100)

            INTEGER score (max_size)

END MODULE blank

 

Cada modulo deve ser salvo no seu próprio arquivo fonte e compilado separadamente.

Para se obter acesso a todas as declarações deste módulo chamando-o utilizando o comando USE. Como por exemplo, para chamar o MODULE blank basta utilizar uma linha de comando como segue:

USE blank

 

 

EXEMPLO:

MODULE mod_A

            REAL : : a, b, c, d

END MODULE mod_A

 

PROGRAM test

            USE mod_A

            CALL sub_1

¼

CONTAINS

            SUBROUTINE sub_1

                        USE mod_A

                        ¼

                        WRITE (*,*) f

            END SUBROUTINE sub_1

END PROGRAM test

TIPOS DERIVADOS

 

            Um tipo derivado especifica o nome e o tipo das variáveis a serem definidos pelo usuário. Este mecanismo permite esconder as estruturas de algumas variáveis definidas pelo usuário além de modificar estas variáveis localmente sem propagá-las pelo programa. Devem ser definidos antes das demais declarações e possui a seguinte sintaxe

 

TYPE nome

            Definição dos componentes

END TYPE

 

O exemplo a seguir mostra um tipo derivado  contendo dois componentes.

 

TYPE employee

            INTEGER id

            CHARACTER name

END TYPE employee

 

TYPE [[, acesso]:: ] nome

            Definição dos componentes

            Definição dos componentes

END TYPE [nome]

 

acesso – pode ser PRIVATE ou PUBLIC. Estes acessos só podem ser empregados se este tipo derivado for uma parte das especificações de um módulo.

nome – é o nome do tipo derivado. Este nome deve ser diferente de qualquer tipo intrínseco ou de qualquer outro tipo derivado que pode ser utilizado pelo módulo.

definição dos componentes – é um ou mais declarações definindo os componentes do tipo derivado.

A definição do primeiro componente pode ser precedida ou não pelo comando PRIVATE ou SEQUENCE. Caso o comando SEQUENCE seja utilizado, todos os tipos derivados especificados nas declarações devem ser do tipo ‘sequence’.

 ALOCAÇÃO DINÂMICA

 

            Conjuntos com comandos ALLOCATABLE e alvos de ponteiros podem ser criados dinamicamente e liberados utilizando os comandos ALLOCATE e DEALLOCATE.

            Ponteiros são associados com alvos (targets) pelos ponteiros ou criando-se alvos. Podem ser desassociados dinamicamente de seus alvos pelo uso do comando NULLIFY.

 

ALLOCATE

 

            Este comando cria um espaço na memória para colocar conjuntos ou alvos de ponteiros. Possui a seguinte sintaxe:

 

ALLOCATE (objeto (tamanho), STAT=sv)

 

sv  significa que o status de alocação a ser estocada é uma variável do tipo escalar inteira.

EXEMPLO:

INTEGER J, N, ALLOC_ERR

REAL, ALLOCATABLE :: A ( : ), B ( : , : )

¼

ALLOCATE ( A (0 : 80) , B (-3:J+1, N), STAT = ALLOC_ERR

 

DEALLOCATE

 

            Este comando libera os locais alocados para um conjunto pelos comandos ALLOCATE e pelos TARGET. Possui a seguinte sintaxe:

 

DEALLOCATE (objeto_alocado, STAT = sv)

 

EXEMPLO:

INTEGER ALLOC_ERR

REAL, ALLOCATABLE :: A ( : ), B ( : , : )

¼

ALLOCATE ( A ( 10 ) , B (-2 : 8 ,  1 : 5 ))

¼

DEALLOCATE ( A, B, STAT = ALLOC_ERR)

OBS. Quando a variável STAT é especificada, o comando DEALLOCATE não retira os objetos alocados provocando um erro que acarreta ao término da execução do programa. Para evitar tais casos, recomenda-se que todas as alocações e dealocações sejam feitas de maneira explícitas e que para todo ALLOCATE seja feita um DEALLOCATE.

            Em um subprograma, a execução dos comandos RETURN ou END torna um conjunto criado como sendo indefinido a não ser que se utilize o comando SAVE, é uma unidade de um MODULE que permite acesso pelos outros programas em execução, é um blank common, é um bloco de common que aparece em um outro programa em execução, ou um valor de retorno de uma função com atribuição de POINTER.

 

EXEMPLO EMPREGANDO OS COMANDOS ALLOCATE E DEALLOCATE

¼

! Este programa recebe um valor inteiro e retorna os valores de raiz quadrada.

INTEGER( KIND = 4 ) :: N

READ ( 5, *) N

CALL MAT (N)

END

 

!Subrotina MAT utiliza a variável do tipo inteira do programa principal

! e calcula a raiz quadrada dos números 1 a N.

 

SUBROUTINE MAT(N)

REAL (KIND = 4), ALLOCATABLE :: SQR ( : )   !declaração do conjunto

                                                       !         unidimensional SQR como allocatable

ALLOCATE ( SQR (N))               !cria um espaço de armazenagem para SQR

!

DO j = 1, N

         SQR( j ) = SQRT (FLOATJ (j)) !FLOATJ converte inteiro em real

ENDDO

WRITE (6, *) SQR                  !mostra os valores calculados

DEALLOCATE (SQR)            !libera os espaços de armazenamento do SQR

END SUBROUTINE MAT

 

NULLIFY

            Este comando desassocia um pointeiro do seu alvo. Possui a sintaxe:

NULLIFY (objeto_ponteiro)

EXEMPLO:

 REAL, TARGET :: TAR ( 0 : 50 )

REAL, POINTER :: PTR_A ( : ), PTR_B ( : )

PTR_A Þ TAR

PTR_B Þ TAR

¼

NULLIFY (PTR_A)

 Após a execução somente o PTR_A será desassociado enquanto o PTR_B continuará associado com a variável TAR.

 

Referências Bibliográficas

 

 

  1. DEC Fortran90: Language Reference Manual, Digital Equipment Corporation, Massachusetts 1995.

 

  1. Koffman, E.B.; Friedman, F.L.; In FORTRAN, fifth edition update; Addison Wesley Longman, Inc., Massachusetts 1997.

 

  1. Whitaker, F.;  Kûsel, R.; Okamoto, S.; Introdução a Computação de Alto Desempenho, apostila do CENAPAD-SP, Campinas, 2002.

 Conteúdo extraído majoritariamente do seguinte site:

www.dfisica.fc.unesp.br/escola/Apostila-Fortran90.doc

 

COMPILADORES

 

Para Linux:

http://www.intel.com/software/products/compilers/downloads/forlin.htm

Para Windows:

http://baixaki.ig.com.br/site/detail4984.htm

 

Integrantes do grupo: André Luis Mello, Diego Muniz, D`jean Araújo