Introdu¸˜o ao Fortran 90/95
ca

Apostila preparada para a disciplina de Modelos Computacionais da F´
ısica I, ministrada para o Curso de Licenciatura em F´
ısica do Departamento de F´
ısica, Instituto de F´
ısica e Matem´tica, Funda¸˜o Universidade
a
ca
Federal de Pelotas, Pelotas - RS.

In´
ıcio: Janeiro de 2005.

Vers˜o: 12 de abril de 2010
a
Sum´rio
a
Referˆncias Bibliogr´ficas
e
a

v

1 Introdu¸˜o
ca
1.1 As origens da Linguagem Fortran . . . . . . . . . .
1.2 O padr˜o Fortran 90 . . . . . . . . . . . . . . . . .
a
1.2.1 Recursos novos do Fortran 90 . . . . . . . .
1.2.2 Recursos em obsolescˆncia do Fortran 90 .
e
1.2.3 Recursos removidos do Fortran 90 . . . . .
1.3 Uma revis˜o menor: Fortran 95 . . . . . . . . . . .
a
1.3.1 Recursos novos do Fortran 95 . . . . . . . .
1.3.2 Recursos em obsolescˆncia do Fortran 95 .
e
1.3.3 Recursos removidos do Fortran 95 . . . . .
1.4 O Fortran no S´culo XXI: Fortran 2003 . . . . . .
e
1.4.1 Recursos novos do Fortran 2003 . . . . . . .
1.4.2 Recursos em obsolescˆncia do Fortran 2003
e
1.4.3 Recursos removidos do Fortran 2003 . . . .
1.5 O novo padr˜o: Fortran 2008 . . . . . . . . . . . .
a
1.5.1 Recursos novos do Fortran 2008 . . . . . . .
1.6 Coment´rios sobre a bibliografia . . . . . . . . . .
a
1.7 Observa¸˜es sobre a apostila e agradecimentos . .
co

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

1
1
2
3
3
4
4
4
5
5
5
6
6
6
7
7
7
8

2 Formato do C´digo-Fonte
o
2.1 Formato do programa-fonte . .
2.2 Nomes em Fortran 90/95 . . .
2.3 Entrada e sa´ padr˜es . . . .
ıda
o
2.4 Conjunto de caracteres aceitos

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

9
. 9
. 11
. 11
. 12

3 Tipos de Vari´veis
a
3.1 Declara¸˜o de tipo de vari´vel . . . . . . . . . .
ca
a
3.2 Vari´veis do tipo INTEGER . . . . . . . . . . . .
a
3.3 Vari´veis do tipo REAL . . . . . . . . . . . . . .
a
3.4 Vari´veis do tipo COMPLEX . . . . . . . . . . . .
a
3.5 Vari´veis do tipo CHARACTER . . . . . . . . . . .
a
3.6 Vari´veis do tipo LOGICAL . . . . . . . . . . . .
a
3.7 O conceito de esp´cie (kind) . . . . . . . . . . .
e
3.7.1 Fortran 77 . . . . . . . . . . . . . . . . .
3.7.2 Fortran 90/95 . . . . . . . . . . . . . . .
3.7.2.1 Compilador Intel® Fortran
3.7.2.2 Compilador gfortran . . . . .
3.7.2.3 Compilador F . . . . . . . . . .
3.7.2.4 Literais de diferentes esp´cies .
e
3.7.3 Fun¸˜es intr´
co
ınsecas associadas ` esp´cie
a
e
3.7.3.1 KIND(X) . . . . . . . . . . . .
3.7.3.2 SELECTED_REAL_KIND(P,R) . .
3.7.3.3 SELECTED_INT_KIND(R) . . . .
3.8 Tipos derivados . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

i

13
13
14
14
15
15
16
17
17
17
17
19
19
21
22
22
22
23
23
ii

´
SUMARIO

4 Express˜es e Atribui¸˜es Escalares
o
co
4.1 Regras b´sicas . . . . . . . . . . . . . . . . . .
a
4.2 Express˜es num´ricas escalares . . . . . . . . .
o
e
4.3 Atribui¸˜es num´ricas escalares . . . . . . . . .
co
e
4.4 Operadores relacionais . . . . . . . . . . . . . .
4.5 Express˜es e atribui¸˜es l´gicas escalares . . . .
o
co o
4.6 Express˜es e atribui¸˜es de caracteres escalares
o
co

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

27
27
28
29
30
30
32

5 Comandos e Construtos de Controle de Fluxo
5.1 Comandos obsoletos do Fortran 77 . . . . . . .
5.1.1 R´tulos (statement labels) . . . . . . . .
o
5.1.2 Comando GO TO incondicional . . . . . .
5.1.3 Comando GO TO computado . . . . . . .
5.1.4 Comando IF aritm´tico . . . . . . . . .
e
5.1.5 Comandos ASSIGN e GO TO atribu´ . .
ıdo
5.1.6 La¸os DO rotulados . . . . . . . . . . . .
c
5.2 Comando e construto IF . . . . . . . . . . . . .
5.2.1 Comando IF . . . . . . . . . . . . . . .
5.2.2 Construto IF . . . . . . . . . . . . . . .
5.3 Construto DO . . . . . . . . . . . . . . . . . . .
5.3.1 Construto DO ilimitado . . . . . . . . . .
5.3.2 Instru¸˜o EXIT . . . . . . . . . . . . . .
ca
5.3.3 Instru¸˜o CYCLE . . . . . . . . . . . . .
ca
5.4 Construto CASE . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

35
35
35
36
36
36
36
37
37
38
38
39
41
41
42
42

6 Processamento de Matrizes
6.1 Terminologia e especifica¸˜es de matrizes . . . . .
co
6.2 Express˜es e atribui¸˜es envolvendo matrizes . . .
o
co
6.3 Se¸˜es de matrizes . . . . . . . . . . . . . . . . . .
co
6.3.1 Subscritos simples . . . . . . . . . . . . . .
6.3.2 Tripleto de subscritos . . . . . . . . . . . .
6.3.3 Vetores de subscritos . . . . . . . . . . . . .
6.4 Atribui¸˜es de matrizes e sub-matrizes . . . . . . .
co
6.5 Matrizes de tamanho zero . . . . . . . . . . . . . .
6.6 Construtores de matrizes . . . . . . . . . . . . . . .
6.6.1 A fun¸˜o intr´
ca
ınseca RESHAPE. . . . . . . . .
6.6.2 A ordem dos elementos de matrizes . . . . .
6.7 Rotinas intr´
ınsecas elementais aplic´veis a matrizes
a
6.8 Comando e construto WHERE . . . . . . . . . . . . .
6.8.1 Comando WHERE . . . . . . . . . . . . . . .
6.8.2 Construto WHERE . . . . . . . . . . . . . . .
6.9 Matrizes aloc´veis . . . . . . . . . . . . . . . . . .
a
6.10 Comando e construto FORALL . . . . . . . . . . . .
6.10.1 Comando FORALL . . . . . . . . . . . . . . .
6.10.2 Construto FORALL . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

45
45
49
51
52
52
52
53
53
55
56
56
57
57
57
58
59
62
62
62

7 Rotinas Intr´
ınsecas
7.1 Categorias de rotinas intr´
ınsecas . . . . . . . . . . . . .
7.2 Declara¸˜o e atributo INTRINSIC . . . . . . . . . . . . .
ca
7.3 Fun¸˜es inquisidoras de qualquer tipo . . . . . . . . . .
co
7.4 Fun¸˜es elementais num´ricas . . . . . . . . . . . . . . .
co
e
7.4.1 Fun¸˜es elementais que podem converter . . . . .
co
7.4.2 Fun¸˜es elementais que n˜o convertem . . . . . .
co
a
7.5 Fun¸˜es elementais matem´ticas . . . . . . . . . . . . .
co
a
7.6 Fun¸˜es elementais l´gicas e de caracteres . . . . . . . .
co
o
7.6.1 Convers˜es caractere-inteiro . . . . . . . . . . . .
o
7.6.2 Fun¸˜es de compara¸˜o l´xica . . . . . . . . . . .
co
ca e
7.6.3 Fun¸˜es elementais para manipula¸˜es de strings
co
co
7.6.4 Convers˜o l´gica . . . . . . . . . . . . . . . . . .
a o
7.7 Fun¸˜es n˜o-elementais para manipula¸˜o de strings . .
co
a
ca

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

65
65
65
66
66
66
67
67
68
68
69
69
69
69

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
´
SUMARIO

7.8

7.9

7.10
7.11
7.12

7.13

7.14

7.15
7.16
7.17

iii

7.7.1 Fun¸˜o inquisidora para manipula¸˜o de strings . . . . .
ca
ca
7.7.2 Fun¸˜es transformacionais para manipula¸˜o de strings
co
ca
Fun¸˜es inquisidoras e de manipula¸˜es num´ricas . . . . . . .
co
co
e
7.8.1 Modelos para dados inteiros e reais . . . . . . . . . . . .
7.8.2 Fun¸˜es num´ricas inquisidoras . . . . . . . . . . . . . .
co
e
7.8.3 Fun¸˜es elementais que manipulam quantidades reais . .
co
7.8.4 Fun¸˜es transformacionais para valores de esp´cie (kind)
co
e
Rotinas de manipula¸˜o de bits . . . . . . . . . . . . . . . . . .
ca
7.9.1 Fun¸˜o inquisidora . . . . . . . . . . . . . . . . . . . . .
ca
7.9.2 Fun¸˜es elementais . . . . . . . . . . . . . . . . . . . . .
co
7.9.3 Subrotina elemental . . . . . . . . . . . . . . . . . . . .
Fun¸˜o de transferˆncia . . . . . . . . . . . . . . . . . . . . . .
ca
e
Fun¸˜es de multiplica¸˜o vetorial ou matricial . . . . . . . . . .
co
ca
Fun¸˜es transformacionais que reduzem matrizes . . . . . . . .
co
7.12.1 Caso de argumento unico . . . . . . . . . . . . . . . . .
´
7.12.2 Argumento opcional DIM . . . . . . . . . . . . . . . . . .
7.12.3 Argumento opcional MASK . . . . . . . . . . . . . . . . .
Fun¸˜es inquisidoras de matrizes . . . . . . . . . . . . . . . . .
co
7.13.1 Status de aloca¸˜o . . . . . . . . . . . . . . . . . . . . .
ca
7.13.2 Limites, forma e tamanho . . . . . . . . . . . . . . . . .
Fun¸˜es de constru¸˜o e manipula¸˜o de matrizes . . . . . . . .
co
ca
ca
7.14.1 Fun¸˜o elemental MERGE . . . . . . . . . . . . . . . . . .
ca
7.14.2 Agrupando e desagrupando matrizes . . . . . . . . . . .
7.14.3 Alterando a forma de uma matriz . . . . . . . . . . . .
7.14.4 Fun¸˜o transformacional para duplica¸˜o . . . . . . . .
ca
ca
7.14.5 Fun¸˜es de deslocamento matricial . . . . . . . . . . . .
co
7.14.6 Transposta de uma matriz . . . . . . . . . . . . . . . . .
Fun¸˜es transformacionais para localiza¸˜o geom´trica . . . . .
co
ca
e
Fun¸˜o transformacional para dissocia¸˜o de ponteiro . . . . .
ca
ca
Subrotinas intr´
ınsecas n˜o-elementais . . . . . . . . . . . . . . .
a
7.17.1 Rel´gio de tempo real . . . . . . . . . . . . . . . . . . .
o
7.17.2 Tempo da CPU . . . . . . . . . . . . . . . . . . . . . . .
7.17.3 N´meros aleat´rios . . . . . . . . . . . . . . . . . . . . .
u
o

8 Sub-Programas e M´dulos
o
8.1 Unidades de programa . . . . . . . . . . . . . . . . . . . . . .
8.1.1 Programa principal . . . . . . . . . . . . . . . . . . . .
8.1.2 Rotinas externas . . . . . . . . . . . . . . . . . . . . .
8.1.3 M´dulos . . . . . . . . . . . . . . . . . . . . . . . . . .
o
8.2 Sub-programas . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.1 Fun¸˜es e subrotinas . . . . . . . . . . . . . . . . . . .
co
8.2.2 Rotinas internas . . . . . . . . . . . . . . . . . . . . .
8.2.3 Argumentos de sub-programas . . . . . . . . . . . . .
8.2.4 Comando RETURN . . . . . . . . . . . . . . . . . . . . .
8.2.5 Atributo e declara¸˜o INTENT . . . . . . . . . . . . . .
ca
8.2.6 Rotinas externas e bibliotecas . . . . . . . . . . . . . .
8.2.7 Interfaces impl´
ıcitas e expl´
ıcitas . . . . . . . . . . . . .
8.2.8 Argumentos com palavras-chave . . . . . . . . . . . .
8.2.9 Argumentos opcionais . . . . . . . . . . . . . . . . . .
8.2.10 Tipos derivados como argumentos de rotinas . . . . .
8.2.11 Matrizes como argumentos de rotinas . . . . . . . . .
8.2.11.1 Matrizes como argumentos em Fortran 77 . .
8.2.11.2 Matrizes como argumentos em Fortran 90/95
8.2.12 sub-programas como argumentos de rotinas . . . . . .
8.2.13 Fun¸˜es de valor matricial . . . . . . . . . . . . . . . .
co
8.2.14 Recursividade e rotinas recursivas . . . . . . . . . . .
8.2.15 Atributo e declara¸˜o SAVE . . . . . . . . . . . . . . .
ca
8.2.16 Fun¸˜es de efeito lateral e rotinas puras . . . . . . . .
co
8.2.17 Rotinas elementais . . . . . . . . . . . . . . . . . . . .
Autor: Rudi Gaelzer – IFM/UFPel

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

69
70
70
70
70
71
71
72
72
72
73
73
73
74
74
74
74
75
75
75
75
75
75
76
76
76
76
76
77
77
77
78
78

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

79
79
79
81
81
81
81
83
83
84
84
86
86
88
91
92
92
92
94
97
98
101
103
104
106

Impresso: 12 de abril de 2010
´
SUMARIO

iv
8.3

8.4

M´dulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
o
8.3.1 Dados globais . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.3.2 Rotinas de m´dulos . . . . . . . . . . . . . . . . . . . . . . . .
o
8.3.3 Atributos e declara¸˜es PUBLIC e PRIVATE . . . . . . . . . . . .
co
8.3.4 Interfaces e rotinas gen´ricas . . . . . . . . . . . . . . . . . . .
e
8.3.5 Estendendo rotinas intr´
ınsecas via blocos de interface gen´ricos
e
ˆ
Ambito (Scope) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ˆ
8.4.1 Ambito dos r´tulos . . . . . . . . . . . . . . . . . . . . . . . . .
o
ˆ
8.4.2 Ambito dos nomes . . . . . . . . . . . . . . . . . . . . . . . . .

9 Comandos de Entrada/Sa´ de Dados
ıda
9.1 Comandos de Entrada/Sa´
ıda: introdu¸˜o r´pida
ca a
9.2 Declara¸˜o NAMELIST . . . . . . . . . . . . . . . .
ca
9.3 Unidades l´gicas . . . . . . . . . . . . . . . . . .
o
9.4 Comando OPEN . . . . . . . . . . . . . . . . . . .
9.5 Comando READ . . . . . . . . . . . . . . . . . . .
9.6 Comandos PRINT e WRITE . . . . . . . . . . . . .
9.7 Comando FORMAT e especificador FMT= . . . . . .
9.8 Descritores de edi¸˜o . . . . . . . . . . . . . . . .
ca
9.8.1 Contadores de repeti¸˜o . . . . . . . . . .
ca
9.8.2 Descritores de edi¸˜o de dados . . . . . .
ca
9.8.3 Descritores de controle de edi¸˜o . . . . .
ca
9.8.4 Descritores de edi¸˜o de strings . . . . . .
ca
9.9 Comando CLOSE . . . . . . . . . . . . . . . . . .
9.10 Comando INQUIRE . . . . . . . . . . . . . . . . .
9.11 Outros comandos de posicionamento . . . . . . .
9.11.1 Comando BACKSPACE . . . . . . . . . . . .
9.11.2 Comando REWIND . . . . . . . . . . . . . .
9.11.3 Comando ENDFILE . . . . . . . . . . . . .

Autor: Rudi Gaelzer – IFM/UFPel

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

107
108
111
113
114
117
118
118
118

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

121
121
125
129
129
132
133
134
135
135
136
139
144
146
146
148
149
149
149

Impresso: 12 de abril de 2010
Referˆncias Bibliogr´ficas
e
a
[1] Intel® Fortran Compiler for Linux. http://www.intel.com/software/products/compilers/flin/docs/manuals.htm.
Acesso em: 01 jun. 2005.
[2] CHAPMAN, STEPHEN J. Fortran 95/2003 for Scientists and Engineers. McGraw-Hill, 2007, xxvi +
976 pp., 3rd. Edi¸˜o.
ca
[3] MARSHALL, A. C. Fortran 90 Course Notes. http://www.liv.ac.uk/HPC/HTMLFrontPageF90.html,
1996. Acesso em: 01 jun. 2005.
[4] METCALF, MICHAEL, REID, JOHN. Fortran 90/95 Explained. New York : Oxford University Press,
1996, 345 + xv pp.
[5] PAGE, CLIVE G. Professional Programer’s Guide to Fortran77.
prof77.pdf, Leicester, 2001. Acesso em: 01 jun. 2005.

http://www.star.le.ac.uk/ cgp/-

[6] RAMSDEN,
S.,
LIN,
F.,
PETTIPHER,
M.
A.,
NOLAND,
OKE, J. M.
Fortran 90. A Conversion Course for Fortran
http://www.hpctec.mcc.ac.uk/hpctec/courses/Fortran90/F90course.html, 1995.
jun. 2005.

G.
S.,
BRO77 Programmers.
Acesso em: 01

[7] REID,
JOHN.
The
New
Features
of
Fortran
2003.
Publicado
http://www.fortranplus.co.uk/resources/john reid new 2003.pdf, 2004. Acesso em: 03 Jun. 2006.

v

em:
vi

Autor: Rudi Gaelzer – IFM/UFPel

ˆ
´
REFERENCIAS BIBLIOGRAFICAS

Impresso: 12 de abril de 2010
Cap´
ıtulo 1

Introdu¸˜o
ca
”I don’t know what the technical characteristics of the standard language for scientific and
engineering computation in the year 2000 will be... but I know it will be called Fortran.”
John Backus
Esta apostila destina-se ao aprendizado da Linguagem de Programa¸˜o Fortran 95.
ca

1.1

As origens da Linguagem Fortran

Programa¸˜o no per´
ca
ıodo inicial do uso de computadores para a solu¸˜o de problemas em f´
ca
ısica, qu´
ımica, engenharia, matem´tica e outras ´reas da ciˆncia era um processo complexo e tedioso ao extremo.
a
a
e
Programadores necessitavam de um conhecimento detalhado das instru¸˜es, registradores, endere¸os de meco
c
m´ria e outros constituintes da Unidade Central de Processamento (CPU1 ) do computador para o qual
o
eles escreviam o c´digo. O C´digo-Fonte era escrito em um nota¸˜o num´rica denominada c´digo octal.
o
o
ca
e
o
Com o tempo, c´digos mnemˆnicos foram introduzidos, uma forma de programa¸˜o conhecida como c´digo
o
o
ca
o
num´rico ou c´digo Assembler. Estes c´digos eram traduzidos em instru¸˜es para a CPU por programas
e
o
o
co
conhecidos como Assemblers. Durante os anos 50 ficou claro que esta forma de programa¸˜o era de todo
ca
inconveniente, no m´
ınimo, devido ao tempo necess´rio para se escrever e testar um programa, embora esta
a
forma de programa¸˜o possibilitasse um uso otimizado dos recursos da CPU.
ca
Estas dificuldades motivaram que um time de programadores da IBM, liderados por John Backus, desenvolvessem uma das primeiras chamadas linguagem de alto-n´
ıvel, denominada FORTRAN (significando
FORmula TRANslation). Seu objetivo era produzir uma linguagem que fosse simples de ser entendida e
usada, mas que gerasse um c´digo num´rico quase t˜o eficiente quanto a linguagem Assembler. Desde o
o
e
a
in´
ıcio, o Fortran era t˜o simples de ser usado que era poss´ programar f´rmulas matem´ticas quase como
a
ıvel
o
a
se estas fossem escritas de forma simb´lica. Isto permitiu que programas fossem escritos mais rapidamente
o
que antes, com somente uma pequena perda de eficiˆncia no processamento, uma vez que todo cuidado era
e
dedicado na constru¸˜o do compilador, isto ´, no programa que se encarrega de traduzir o c´digo-fonte em
ca
e
o
Fortran para c´digo Assembler ou octal.
o
Mas o Fortran foi um passo revolucion´rio tamb´m porque o programadores foram aliviados da tarefa
a
e
tediosa de usar Assembler, assim concentrando-se mais na solu¸˜o do problema em quest˜o. Mais imporca
a
tante ainda, computadores se tornaram acess´
ıveis a qualquer cientista ou engenheiro disposto a devotar um
pequeno esfor¸o na aquisi¸˜o de um conhecimento b´sico em Fortran; a tarefa da programa¸˜o n˜o estava
c
ca
a
ca a
mais restrita a um corpus pequeno de programadores especialistas.
O Fortran disseminou-se rapidamente, principalmente nas ´reas da f´
a
ısica, engenharia e matem´tica,
a
uma vez que satisfazia uma necessidade premente dos cientistas. Inevitavelmente, dialetos da linguagem
foram desenvolvidos, os quais levaram a problemas quando havia necessidade de se trocar programas entre
diferentes computadores. O dialeto de Fortran otimizado para processadores fabricados pela IBM, por
exemplo, geralmente gerava erro quando se tentava rodar o mesmo programa em um processador Burroughs,
ou em outro qualquer. Assim, em 1966, ap´s quatro anos de trabalho, a Associa¸˜o Americana de Padr˜es
o
ca
o
(American Standards Association), posteriormente Instituto Americano Nacional de Padr˜es (American
o
National Standards Institute, ou ANSI) originou o primeiro padr˜o para uma linguagem de programa¸˜o,
a
ca
agora conhecido como Fortran 66. Essencialmente, era uma subconjunto comum de v´rios dialetos, de
a
tal forma que cada dialeto poderia ser reconhecido como uma extens˜o do padr˜o. Aqueles usu´rios que
a
a
a
desejavam escrever programas port´veis deveriam evitar as extens˜es e restringir-se ao padr˜o.
a
o
a
1 Do

inglˆs: Central Processing Unit.
e

1
2

1.2. O padr˜o Fortran 90
a

O Fortran trouxe consigo v´rios outros avan¸os, al´m de sua facilidade de aprendizagem combinada com
a
c
e
um enfoque em execu¸˜o eficiente de c´digo. Era, por exemplo, uma linguagem que permanecia pr´xima
ca
o
o
(e explorava) o hardware dispon´
ıvel, ao inv´s de ser um conjunto de conceitos abstratos. Ela tamb´m
e
e
introduziu, atrav´s das declara¸˜es COMMON e EQUIVALENCE, a possibilidade dos programadores controlarem
e
co
a aloca¸˜o da armazenagem de dados de uma forma simples, um recurso que era necess´rio nos prim´rdios da
ca
a
o
computa¸˜o, quando havia pouco espa¸o de mem´ria, mesmo que estas declara¸˜es sejam agora consideradas
ca
c
o
co
potencialmente perigosas e o seu uso desencorajado. Finalmente, o c´digo fonte permitia espa¸os em branco
o
c
na sua sintaxe, liberando o programador da tarefa de escrever c´digo em colunas rigidamente definidas e
o
permitindo que o corpo do programa fosse escrito da forma desejada e visualmente mais atrativa.
A prolifera¸ao de dialetos permaneceu um problema mesmo ap´s a publica¸˜o do padr˜o Fortran 66. A
c˜
o
ca
a
primeira dificuldade foi que muitos compiladores n˜o aderiram ao padr˜o. A segunda foi a implementa¸˜o,
a
a
ca
em diversos compiladores, de recursos que eram essenciais para programas de grande escala, mas que eram
ignorados pelo padr˜o. Diferentes compiladores implementavam estes recursos de formas distintas.
a
Esta situa¸˜o, combinada com a existˆncia de falhas evidentes na linguagem, tais como a falta de consca
e
tru¸˜es estruturadas de programa¸˜o, resultaram na introdu¸˜o de um grande n´mero de pr´-processadores.
co
ca
ca
u
e
Estes eram programas que eram capazes de ler o c´digo fonte de algum dialeto bem definido de Fortran e
o
gerar um segundo arquivo com o texto no padr˜o, o qual ent˜o era apresentado ao compilador nesta forma.
a
a
Este recurso provia uma maneira de estender o Fortran, ao mesmo tempo retendo a sua portabilidade. O
problema era que embora os programas gerados com o uso de um pr´-processador fossem port´veis, podendo
e
a
ser compilados em diferentes computadores, o c´digo gerado era muitas vezes de uma dificuldade proibitiva
o
para a leitura direta.
Estas dificuldades foram parcialmente removidas pela publica¸˜o de um novo padr˜o, em 1978, conhecido
ca
a
como Fortran 77. Ele inclu´ diversos novos recursos que eram baseados em extens˜es comerciais ou pr´ıa
o
e
processadores e era, portanto, n˜o um subconjunto comum de dialetos existentes, mas sim um novo dialeto
a
por si s´. O per´
o
ıodo de transi¸˜o entre o Fortran 66 e o Fortran 77 foi muito mais longo que deveria,
ca
devido aos atrasos na elabora¸˜o de novas vers˜es dos compiladores e os dois padr˜es coexistiram durante
ca
o
o
um intervalo de tempo consider´vel, que se estendeu at´ meados da d´cada de 80. Eventualmente, os
a
e
e
fabricantes de compiladores passaram a liber´-los somente com o novo padr˜o, o que n˜o impediu o uso de
a
a
a
programas escritos em Fortran 66, uma vez que o Fortran 77 permitia este c´digo antigo por compatibilidade.
o
Contudo, diversas extens˜es n˜o foram mais permitidas, uma vez que o padr˜o n˜o as incluiu na sua sintaxe.
o
a
a a

1.2

O padr˜o Fortran 90
a

Ap´s trinta anos de existˆncia, Fortran n˜o mais era a unica linguagem de programa¸˜o dispon´ para
o
e
a
´
ca
ıvel
os programadores. Ao longo do tempo, novas linguagens foram desenvolvidas e, onde elas se mostraram
mais adequadas para um tipo particular de aplica¸˜o, foram adotadas em seu lugar. A superioridade do
ca
Fortran sempre esteve na ´rea de aplica¸˜es num´ricas, cient´
a
co
e
ıficas, t´cnicas e de engenharia. A comunidade
e
de usu´rios do Fortran realizou um investimento gigantesco em c´digos, com muitos programas em uso
a
o
freq¨ente, alguns com centenas de milhares ou milh˜es de linhas de c´digo. Isto n˜o significava, contudo,
u
o
o
a
que a comunidade estivesse completamente satisfeita com a linguagem. V´rios programadores passaram a
a
migrar seus c´digos para linguagens tais como Pascal, C e C++. Para levar a cabo mais uma moderniza¸˜o
o
ca
da linguagem, o comitˆ t´cnico X3J3, aprovado pela ANSI, trabalhando como o corpo de desenvolvimento
e e
do comitˆ da ISO (International Standards Organization, Organiza¸˜o Internacional de Padr˜es) ISO/IEC
e
ca
o
JTC1/SC22/WG5 (doravante conhecido como WG5), preparou um novo padr˜o, inicialmente conhecido
a
como Fortran 8x, e agora como Fortran 90.
Quais eram as justificativas para continuar com o processo de revis˜o do padr˜o da linguagem Fortran?
a
a
Al´m de padronizar extens˜es comerciais, havia a necessidade de moderniza¸˜o, em resposta aos desenvole
o
ca
vimentos nos conceitos de linguagens de programa¸˜o que eram explorados em outras linguagens tais como
ca
APL, Algol, Pascal, Ada, C e C++. Com base nestas, o X3J3 podia usar os ´bvios benef´
o
ıcios de conceitos
tais como ocultamento de dados. Na mesma linha, havia a necessidade de fornecer uma alternativa ` peria
gosa associa¸˜o de armazenagem de dados, de abolir a rigidez agora desnecess´ria do formato fixo de fonte,
ca
a
bem como de aumentar a seguran¸a na programa¸˜o. Para proteger o investimento em Fortran 77, todo o
c
ca
padr˜o anterior foi mantido como um subconjunto do Fortran 90.
a
Contudo, de forma distinta dos padr˜es pr´vios, os quais resultaram quase inteiramente de um esfor¸o
o
e
c
de padronizar pr´ticas existentes, o Fortran 90 ´ muito mais um desenvolvimento da linguagem, na qual s˜o
a
e
a
introduzidos recursos que s˜o novos em Fortran, mas baseados em experiˆncias em outras linguagens. Os
a
e
recursos novos mais significativos s˜o a habilidade de manipular matrizes usando uma nota¸˜o concisa mais
a
ca
poderosa e a habilidade de definir e manipular tipos de dados definidos pelo programador. O primeiro destes
recursos leva a uma simplifica¸˜o na escrita de muitos problemas matem´ticos e tamb´m torna o Fortran
ca
a
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 1. Introdu¸˜o
ca

3

uma linguagem mais eficiente em supercomputadores. O segundo possibilita aos programadores a express˜o
a
de seus problemas em termos de tipos de dados que reproduzem exatamente os conceitos utilizados nas sua
elabora¸˜es.
co

1.2.1

Recursos novos do Fortran 90

Um resumo dos novos recursos ´ dado a seguir:
e
ˆ O Fortran 90 possui uma maneira para rotular alguns recursos antigos como em obsolescˆncia (isto ´,
e
e
tornando-se obsoletos).
ˆ Opera¸˜es de matrizes.
co
ˆ Ponteiros.
ˆ Recursos avan¸ados para computa¸˜o num´rica usando um conjunto de fun¸˜es inquisidoras num´ricas.
c
ca
e
co
e
ˆ Parametriza¸˜o dos tipos intr´
ca
ınsecos, permitindo o suporte a inteiros curtos, conjuntos de caracteres
muito grandes, mais de duas precis˜es para vari´veis reais e complexas e vari´veis l´gicas agrupadas.
o
a
a
o
ˆ Tipos de dados derivados, definidos pelo programador, compostos por estruturas de dados arbitr´rias
a
e de opera¸˜es sobre estas estruturas.
co
ˆ Facilidades na defini¸˜o de coletˆneas denominadas m´dulos, uteis para defini¸˜es globais de dados e
ca
a
o
´
co
para bibliotecas de subprogramas.
ˆ Exigˆncia que o compilador detecte o uso de constru¸˜es que n˜o se conformam com a linguagem ou
e
co
a
que estejam em obsolescˆncia.
e
ˆ Um novo formato de fonte, adequado para usar em um terminal.
ˆ Novas estruturas de controle, tais como SELECT CASE e uma nova forma para os la¸os DO.
c
ˆ A habilidade de escrever subprogramas internos e subprogramas recursivos e de chamar subprogramas
com argumentos opcionais.
ˆ Aloca¸ao dinˆmica de dados (matrizes autom´ticas, matrizes aloc´veis e ponteiros).
c˜
a
a
a
ˆ Melhoramentos nos recursos de entrada/sa´ de dados.
ıda
ˆ V´rios novos subprogramas intr´
a
ınsecos.

Todos juntos, estes novos recursos contidos em Fortran 90 ir˜o assegurar que o padr˜o continue a ser bem
a
a
sucedido e usado por um longo tempo. O Fortran 77 continua sendo suportado como um subconjunto
durante um per´
ıodo de adapta¸˜o.
ca
Os procedimentos de trabalho adotados pelo comitˆ X3J3 estabelecem um per´
e
ıodo de aviso pr´vio antes
e
que qualquer recurso existente seja removido da linguagem. Isto implica, na pr´tica, um ciclo de revis˜o, que
a
a
para o Fortran ´ de cerca de cinco anos. A necessidade de remo¸˜o de alguns recursos ´ evidente; se a unica
e
ca
e
´
a¸˜o adotada pelo X3J3 fosse de adicionar novos recursos, a linguagem se tornaria grotescamente ampla,
ca
com muitos ´
ıtens redundantes e sobrepostos. A solu¸˜o finalmente adotada pelo comitˆ foi de publicar como
ca
e
uma apˆndice ao padr˜o um conjunto de duas listas mostrando quais os ´
e
a
ıtens que foram removidos e quais
s˜o os candidatos para uma eventual remo¸˜o.
a
ca
A primeira lista cont´m os recursos removidos (deleted features). A segunda lista cont´m os recursos
e
e
em obsolescˆncia (obsolescent features), os quais s˜o considerados obsoletos e redundantes, sendo assim
e
a
candidatos ` remo¸˜o na pr´xima revis˜o da linguagem.
a
ca
o
a

1.2.2

Recursos em obsolescˆncia do Fortran 90
e

Os recursos em obsolescˆncia do Fortran 90 s˜o:
e
a
ˆ IF aritm´tico;
e
ˆ desvio para uma declara¸˜o END IF a partir de um ponto fora de seu bloco;
ca
ˆ vari´veis reais e de dupla precis˜o nas express˜es de controle de um comando DO;
a
a
o
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
4

1.3. Uma revis˜o menor: Fortran 95
a
ˆ finaliza¸˜o compartilhada de blocos DO, bem como finaliza¸˜o por uma declara¸˜o ou comando distintos
ca
ca
ca
de um CONTINUE ou de um END DO;
ˆ declara¸˜o ASSIGN e comando GO TO atribu´
ca
ıdo;
ˆ RETURN alternativo;
ˆ comando PAUSE;
ˆ especificadores FORMAT atribu´
ıdos;
ˆ descritor de edi¸˜o H.
ca

1.2.3

Recursos removidos do Fortran 90

Uma vez que Fortran 90 cont´m o Fortran 77 como subconjunto, esta lista permaneceu vazia para o
e
Fortran 90.

1.3

Uma revis˜o menor: Fortran 95
a

Seguindo a publica¸˜o do padr˜o Fortran 90 em 1991, dois significativos desenvolvimentos posteriores
ca
a
referentes ` linguagem Fortran ocorreram. O primeiro foi a continuidade na opera¸˜o dos dois comitˆs de
a
ca
e
regulamenta¸˜o do padr˜o da linguagem: o X3J3 e o WG5; o segundo desenvolvimento foi a cria¸˜o do
ca
a
ca
F´rum Fortran de Alta Performance (High Performance Fortran Forum, ou HPFF).
o
Logo no inicio de suas delibera¸˜es, os comitˆs concordaram na estrat´gia de definir uma revis˜o menor
co
e
e
a
no Fortran 90 para meados da d´cada de 90, seguida por uma revis˜o de maior escala para o in´ dos anos
e
a
ıcio
2000. Esta revis˜o menor passou a ser denominada Fortran 95.
a
O HPFF teve como objetivo a defini¸˜o de um conjunto de extens˜es ao Fortran tais que permitissem a
ca
o
constru¸˜o de c´digos port´veis quando se fizesse uso de computadores paralelos para a solu¸˜o de problemas
ca
o
a
ca
envolvendo grandes conjuntos de dados que podem ser representados por matrizes regulares. Esta vers˜o
a
do Fortran ficou conhecida como o Fortran de Alta Performance (High Performance Fortran, ou HPF),
tendo como linguagem de base o Fortran 90, n˜o o Fortran 77. A vers˜o final do HPF consiste em um
a
a
conjunto de instru¸˜es que cont´m o Fortran 90 como subconjunto. As principais extens˜es est˜o na forma
co
e
o
a
de diretivas, que s˜o vistas pelo Fortran 90 como coment´rios, mas que s˜o reconhecidas por um compilador
a
a
a
HPF. Contudo, tornou-se necess´ria tamb´m a inclus˜o de elementos adicionais na sintaxe, uma vez que
a
e
a
nem todos os recursos desejados puderam ser acomodados simplesmente na forma de diretivas.
`
A medida que os comitˆs X3J3 e WG5 trabalhavam, este comunicavam-se regularmente com o HPFF.
e
Era evidente que, para evitar o surgimento de dialetos divergentes de Fortran, havia a necessidade de
incorporar a sintaxe nova desenvolvida pelo HPFF no novo padr˜o da linguagem. De fato, os recursos do
a
HPF constituem as novidades mais importantes do Fortran 95. As outras mudan¸as consistem em corre¸˜es,
c
co
clarifica¸˜es e interpreta¸˜es do novo padr˜o. Estas se tornaram prementes quando os novos compiladores
co
co
a
de Fortran 90 foram lan¸ados no mercado e utilizados; notou-se uma s´rie de erros e detalhes obscuros que
c
e
demandavam repara¸˜es. Todas estas mudan¸as foram inclu´
co
c
ıdas no novo padr˜o Fortran 95, que teve a sua
a
vers˜o inicial lan¸ada no pr´prio ano de 1995.2
a
c
o
O Fortran 95 ´ compat´
e
ıvel com o Fortran 90, exceto por uma pequena altera¸˜o na fun¸˜o intr´
ca
ca
ınseca
SIGN (se¸˜o 7.4.2) e a elimina¸˜o de recursos t´
ca
ca
ıpicos do Fortran 77, declarados em obsolescˆncia no Fortran
e
90. Os detalhes do Fortran 95 foram finalizados em novembro de 1995 e o novo padr˜o ISO foi finalmente
a
publicado em outubro de 1996.

1.3.1

Recursos novos do Fortran 95

Os novos recursos do Fortran 95 est˜o discutidos ao longo desta apostila. Em rela¸˜o ao Fortran 90,
a
ca
foram introduzidos os seguintes recursos:
ˆ Concordˆncia aprimorada com o padr˜o de aritm´tica de ponto flutuante bin´ria da IEEE (IEEE 754
a
a
e
a
ou IEC 559-1989).
ˆ Rotinas (procedures) puras (se¸˜o 8.2.16).
ca
ˆ Rotinas (procedures) elementais (se¸˜o 8.2.17).
ca
2 Fortran

95, Commitee Draft, May 1995. ACM Fortran Forum, v. 12, n. 2, June 1995.

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 1. Introdu¸˜o
ca

5

ˆ Dealoca¸˜o autom´tica de matrizes aloc´veis (p´gina 61).
ca
a
a
a
ˆ Comando e construto FORALL (se¸˜o 6.10).
ca
ˆ Extens˜es do construto WHERE (p´gina 58).
o
a
ˆ Fun¸˜es especificadoras.
co
ˆ Inicializa¸˜o de ponteiro e a fun¸˜o NULL (se¸˜o 7.16).
ca
ca
ca
ˆ Inicializa¸˜o de componentes de tipo derivado (p´gina 25).
ca
a
ˆ Fun¸˜es elementares CEILING, FLOOR e SIGN (se¸˜es 7.4.1 e 7.4.2).
co
co
ˆ Fun¸˜es transformacionais (7.15).
co
ˆ Subrotina intr´
ınseca CPU_TIME (se¸˜o 7.17.2).
ca
ˆ Coment´rio na entrada de uma lista NAMELIST (p´gina 128).
a
a
ˆ Descritores de edi¸˜o com largura de campo m´
ca
ınimo.
ˆ Especifica¸˜o gen´rica na cl´usula END INTERFACE.
ca
e
a

1.3.2

Recursos em obsolescˆncia do Fortran 95
e

Os recursos abaixo entraram na lista em obsolescˆncia do Fortran 95 e, portanto, pouco ou nada foram
e
comentados ao longo desta Apostila.
ˆ Formato fixo de fonte.
ˆ Comando GO TO computado.
ˆ Declara¸˜o de vari´vel de caractere na forma CHARACTER*.
ca
a
ˆ Declara¸˜es DATA entre comandos execut´veis.
co
a
ˆ Fun¸˜es definidas em uma linha (statement functions).
co
ˆ Extens˜o assumida de caracteres quando estas s˜o resultados de fun¸˜es.
a
a
co

1.3.3

Recursos removidos do Fortran 95

Cinco recursos foram removidos do padr˜o da linguagem Fortran 95 e, portanto, n˜o ser˜o mais aceitos
a
a
a
por compiladores que respeitam o padr˜o Fortran 95.
a
ˆ ´
Indices de la¸os DO do tipo real (qualquer esp´cie).
c
e
ˆ Declara¸˜o ASSIGN e comando GO TO atribu´ e uso de um inteiro atribu´ por ASSIGN em uma
ca
ıdo
ıdo
declara¸˜o FORMAT.
ca
ˆ Desvio para uma declara¸˜o END IF a partir de um ponto fora do bloco.
ca
ˆ Comando PAUSE.
ˆ Descritor de edi¸˜o H.
ca

1.4

O Fortran no S´culo XXI: Fortran 2003
e

O Fortran 2003 ´ novamente uma revis˜o grande do padr˜o anterior: Fortran 95. A vers˜o curta (draft) do
e
a
a
a
novo padr˜o foi divulgada em finais de 20033 e tornou-se desde ent˜o o novo padr˜o da linguagem, embora at´
a
a
a
e
o presente momento nenhum compilador apresenta suporte completo do novo padr˜o. As grandes novidades
a
introduzidas foram: um direcionamento ainda maior para programa¸˜o orientada a objeto, a qual oferece
ca
uma maneira efetiva de separar a programa¸˜o de um c´digo grande e complexo em tarefas independentes
ca
o
e que permite a constru¸˜o de novo c´digo baseado em rotinas j´ existentes e uma capacidade expandida
ca
o
a
de interface com a linguagem C, necess´ria para que os programadores em Fortran possam acessar rotinas
a
escritas em C e para que programadores de C possam acessar rotinas escritas em Fortran.
Esta Apostila n˜o ir´ abordar os novos recursos introduzidos pelo Fortran 2003, limitando-se a list´-los.
a a
a
3 Ver

o draft em: http://www.dkuug.dk/jtc1/sc22/open/n3661.pdf.

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
6

1.4. O Fortran no S´culo XXI: Fortran 2003
e

1.4.1

Recursos novos do Fortran 2003

Os principais recursos introduzidos pelo padr˜o s˜o:
a a
ˆ Aprimoramentos dos tipos derivados: tipos derivados parametrizados, controle melhorado de acessibilidade, construtores de estrutura aperfei¸oados e finalizadores.
c
ˆ Suporte para programa¸˜o orientada a objeto: extens˜o de tipo e heran¸a (inheritance), polimorfismo
ca
a
c
(polymorphism), aloca¸˜o dinˆmica de tipo e rotinas (procedures) ligadas a tipo.
ca
a
ˆ Aperfei¸oamentos na manipula¸˜o de dados: componentes aloc´veis de estruturas, argumentos mudos
c
ca
a
aloc´veis, parˆmetros de tipo deferidos (deferred type parameters), atributo VOLATILE, especifica¸˜o
a
a
ca
expl´
ıcita de tipo em construtores de matrizes e declara¸˜es de aloca¸˜o, aperfei¸oamentos em ponteiros,
co
ca
c
express˜es de inicializa¸˜o estendidas e rotinas intr´
o
ca
ınsecas aperfei¸oadas.
c
ˆ Aperfei¸oamentos em opera¸˜es de Entrada/Sa´ (E/S) de dados: transferˆncia ass´
c
co
ıda
e
ıncrona, acesso
de fluxo (stream access), opera¸˜es de transferˆncia especificadas pelo usu´rio para tipos derivados,
co
e
a
controle especificado pelo usu´rio para o arredondamento em declara¸˜es FORMAT, constantes nomeadas
a
co
para unidades pr´-conectadas, o comando FLUSH, regulariza¸˜o de palavras-chave e acesso a mensagens
e
ca
de erro.
ˆ Ponteiros de rotinas (procedure pointers).
ˆ Suporte para as exce¸˜es do padr˜o de aritm´tica bin´ria de ponto flutuante ISO/IEC 559, anteriorco
a
e
a
mente conhecido como padr˜o IEEE 754.
a
ˆ Interoperabilidade com a linguagem de programa¸˜o C.
ca
ˆ Suporte aperfei¸oado para internacionaliza¸˜o: acesso ao conjunto de caracteres de 4 bytes ISO 10646
c
ca
and escolha de v´
ırgula ou ponto como separador de parte inteira e parte decimal em opera¸˜es de E/S
co
num´ricas formatadas.
e
ˆ Integra¸˜o aperfei¸oada com o sistema operacional hospedeiro: acesso a argumentos de linha de coca
c
mando, vari´veis de ambiente e mensagens de erro do processador.
a

1.4.2

Recursos em obsolescˆncia do Fortran 2003
e

Nesta lista permanecem ´
ıtens que j´ estavam na lista de obsolescˆncia do Fortran 95. Os crit´rios para
a
e
e
inclus˜o nesta lista continuam sendo: recursos redundantes e para os quais m´todos melhores estavam
a
e
dispon´
ıveis no Fortran 95. A lista dos ´
ıtens em obsolescˆncia do Fortran 2003 ´:
e
e
ˆ IF aritm´tico.
e
ˆ END DO compartilhado por dois ou mais la¸os e t´rmino de um la¸o em uma cl´usula distinta de END
c
e
c
a
DO ou CONTINUE.
ˆ RETURN alternativo.
ˆ Comando GO TO computado.
ˆ Fun¸˜es definidas em uma linha (statement functions).
co
ˆ Declara¸˜es DATA entre comandos execut´veis.
co
a
ˆ Fun¸˜es de caractere de extens˜o assumida.
co
a
ˆ Formato fixo da fonte.
ˆ Forma CHARACTER* da declara¸˜o CHARACTER.
ca

1.4.3

Recursos removidos do Fortran 2003

Um recurso ´ removido do novo padr˜o se este for considerado redundante e praticamente sem uso pela
e
a
comunidade, devido a novos recursos muito mais uteis na constru¸˜o do c´digo.
´
ca
o
A lista de recursos removidos no Fortran 2003, divulgada no draft, repete os recursos removidos do
Fortran 95. Portanto, nenhum outro recurso foi removido.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 1. Introdu¸˜o
ca

1.5

7

O novo padr˜o: Fortran 2008
a

Embora ainda n˜o exista nenhum compilador que suporte completamente o padr˜o atual, Fortran 2003,
a
a
j´ est´ em fase de conclus˜o as discuss˜es a respeito do padr˜o futuro: Fortran 2008. A vers˜o curta (draft)
a
a
a
o
a
a
do novo padr˜o deve ser divulgada ao final do ano de 2008.
a
O Fortran 2008, embora pelo procedimento adotado pelos comitˆs X3J3/WG5 devesse ser uma revis˜o
e
a
menor do Fortran 2003, pode vir a apresentar algumas novidades substanciais, tais como as co-matrizes (coarrays). Os detalhes completos dos novos recursos ainda n˜o foram plenamente divulgados para o p´blico
a
u
em geral, mas alguns dos ´
ıtens que ir˜o compor o novo padr˜o, por consenso, est˜o listados a seguir.
a
a
a

1.5.1

Recursos novos do Fortran 2008

Com base em material de divulga¸˜o obtido na World Wide Web, os seguintes recursos ser˜o inclu´
ca
a
ıdos:
ˆ Co-matrizes (co-arrays).
ˆ BITS, originalmente denominados objetos sem tipo (TYPELESS).
ˆ Macros inteligentes (no lugar de m´dulos parametrizados).
o
ˆ Atributo CONTIGUOUS.
ˆ La¸os DO concorrentes (DO CONCURRENT).
c
ˆ Interoperabilidade de ponteiros, objetos aloc´veis, matrizes de forma assumida e argumentos opcionais.
a
ˆ Execu¸ao de programas externos.
c˜
ˆ Ponteiro aloc´vel em resolu¸˜o gen´rica
a
ca
e
ˆ Rotina interna como argumento real
ˆ Inicializa¸˜o de ponteiros com alvos distintos de NULL().
ca
ˆ Rotinas intr´
ınsecas estendidas.
ˆ Opera¸˜o de E/S recursivas a distintas unidades.
ca
ˆ ...

1.6

Coment´rios sobre a bibliografia
a

Para escrever esta apostila, fiz uso de um n´mero restrito de publica¸˜es, algumas das quais s˜o de livre
u
co
a
acesso atrav´s da internet.
e
ˆ Para informa¸˜es a respeito do padr˜o existente na linguagem Fortran 77, a qual foi substitu´ pelo
co
a
ıda
Fortran 90/95, utilizei freq¨entemente o livro de Clive Page: Professional Programer’s Guide to Fortran
u
77 [5].
ˆ A principal fonte de informa¸˜o sobre o padr˜o do Fortran 90/95 foi o amplo livro de Michael Metcalf
ca
a
e John Reid: Fortran 90/95 Explained [4].
ˆ O curso virtual de Fortran 90 oferecido pela Universidade de Liverpool [3].
ˆ O curso virtual de Fortran 90 para programadores que j´ conhecem o Fortran 77, oferecido pela
a
Universidade de Manchester [6].
ˆ O manual de referˆncia ` Linguagem Fortran 90/95 que acompanha o compilador intel tamb´m foi
e
a
e
freq¨entemente consultado [1].
u
ˆ Informa¸˜es divulgadas sobre o Fortran 2003 foram obtidas do livreto de John Reid [7] e do livro de
co
Stephen Chapman: Fortran 95/2003 for Scientists and Engineers [2].
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
8

1.7

1.7. Observa¸˜es sobre a apostila e agradecimentos
co

Observa¸˜es sobre a apostila e agradecimentos
co

Por se tratar de uma obra em constante revis˜o, esta apostila pode conter (e conter´, invariavelmente)
a
a
uma s´rie de erros de ortografia, pontua¸˜o, acentua¸˜o, etc. Em particular, o texto n˜o foi ainda revisado
e
ca
ca
a
para se conformar com o novo acordo ortogr´fico da Lingua Portuguesa. Certos pontos poderiam tamb´m
a
e
ser melhor discutidos e podem conter at´ informa¸˜es n˜o completamente corretas.
e
co
a
Durante o desenvolvimento e divulga¸˜o desta apostila, algumas pessoas contribuiram com o seu aprica
moramento ao apontar erros e inconsistˆncias e ao oferecer sugest˜es quanto a sua estrutura e conte´do.
e
o
u
Qualquer contribui¸˜o ´ bem vinda e pode ser enviada ao endere¸o eletrˆnico: rudi@ufpel.edu.br.
ca e
c
o
Gostaria de agradecer publicamente as contribui¸˜es das seguintes pessoas: Leandro Tezani.
co

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 2

Formato do C´digo-Fonte
o
Neste cap´
ıtulo estuda-se, inicialmente, um formato b´sico para o programa-fonte em Fortran 90/95 e os
a
tipos de vari´veis e suas caracter´
a
ısticas b´sicas.
a

2.1

Formato do programa-fonte

Em Fortran h´ trˆs formatos b´sicos de arquivos que s˜o utilizados:
a e
a
a
Programa-Fonte. Trata-se do programa e/ou dos subprogramas escritos pelo programador, usando algum
tipo de editor de texto, de acordo com as regras definidas pela linguagem de programa¸˜o de alto
ca
n´
ıvel.
Programa-Objeto. Trata-se do programa-fonte compilado pelo compilador. Esta ´ a transcri¸˜o realizada
e
ca
pelo compilador do programa-fonte fornecido pelo programador para uma linguagem de baixo n´
ıvel,
como Assembler ou outro c´digo diretamente interpret´vel pela CPU. O programa-objeto n˜o pode
o
a
a
ainda ser executado; ´ necess´rio ainda passar-se pela fase do linking (tradu¸˜o livre: linkagem).
e
a
ca
Programa execut´vel. Ap´s a fase de compila¸˜o, onde os programas objetos s˜o criados, o agente de
a
o
ca
a
compila¸˜o aciona o linker, o qual consiste em um programa especial que agrupa os programas objetos
ca
de forma a criar um arquivo final, o programa execut´vel, o qual pode ser ent˜o executado pelo
a
a
programador.
Nesta se¸˜o ser´ apresentada a estrutura b´sica de um programa-fonte em Fortran 90/95.
ca
a
a
O Fortran 90/95 suporta duas formas de c´digo-fonte: o formato antigo do Fortran 77, agora denominado
o
formato fixo e o novo formato livre.
Fortran 77: O formato fixo foi utilizado pelo Fortran desde a primeira vers˜o at´ o Fortran 77. Este
a
e
formato foi determinado pelas restri¸˜es impostas pelos cart˜es perfurados, que eram a unica op¸˜o para
co
o
´
ca
entrar com o c´digo fonte. A estrutura do formato fixo ´ a seguinte:
o
e
Colunas 1-5: r´tulos (labels) para desvio de processamento do programa.
o
Coluna 6: caractere de continua¸˜o de linha.
ca
Colunas 7-72: c´digo fonte.
o
H´, ainda, a possibilidade de incluir o caractere “C” ou “c” na coluna 1, o que instrui o compilador a ignorar
a
tudo que segue neste linha. Esta ´ a forma encontrada para se colocar coment´rios dentro do c´digo fonte.
a
a
o
Fortran 90/95: Nestas revis˜es, a linguagem passou a suportar o formato livre, com as seguintes caraco
ter´
ısticas.
ˆ No formato livre n˜o h´ uma coluna espec´
a a
ıfica para iniciar o programa. Pode-se come¸ar a escrever
c
o c´digo a partir da coluna 1 e a linha de c´digo pode se estender at´ a coluna 132. Al´m disso, os
o
o
e
e
caracteres em branco s˜o irrelevantes em qualquer lugar do c´digo, exceto quanto estiverem sendo
a
o
utilizados entre ap´strofes. Neste caso, cada caractere em branco ser´ avaliado na composi¸˜o final do
o
a
ca
string.

9
10

2.1. Formato do programa-fonte
ˆ Mais de uma instru¸˜o pode ser colocada na mesma linha. O separador de linhas padr˜o ´ o pontoca
a e
e-v´
ırgula “;”. M´ltiplos “;” em uma linha, com ou sem brancos, s˜o considerados como um separador
u
a
simples. Desta forma, a seguinte linha de c´digo ´ interpretada como 3 linhas em seq¨ˆncia:
o
e
ue

A = 0; B = 0; C = 0
ˆ O caractere ampersand “&” ´ a marca de continua¸˜o, isto ´, ele indica que a linha com instru¸˜es
e
ca
e
co
imediatamente posterior ´ continua¸˜o da linha onde o “&” foi digitado. Desta forma, s˜o permitidas
e
ca
a
at´ 39 linhas adicionais de c´digo. Como exemplo, a seguinte linha de c´digo:
e
o
o

X = (-Y + ROOT_OF_DISCRIMINANT)/(2.0*A)
tamb´m pode ser escrita usando o “&”:
e
X =
(-Y + ROOT_OF_DISCRIMINANT)
/(2.0*A)

&
&

ˆ Para entrar com coment´rios em qualquer ponto do c´digo-fonte, o usu´rio deve digitar o ponto de
a
o
a
exclama¸˜o “!” em qualquer coluna de uma linha. Todo o restante da linha ser´ desprezado pelo
ca
a
compilador. Exemplo:

X = Y/A - B ! Soluciona a equa¸~o linear.
ca
O programa “Alˆ Mam˜e”.
o
a
Como primeiro exemplo de programa em Fortran 90/95, considere o seguinte c´digo-fonte:
o
program p r i m e i r o
i m p l i c i t none
print * , ”Alˆ Mam˜e”
o
a
end program p r i m e i r o
A forma mais simples de um programa em Fortran 90/95 ´ a seguinte:
e
PROGRAM <nome_do_programa>
<declara¸~es de nomes de vari´veis>
co
a
<comandos execut´veis>
a
END PROGRAM <nome_do_programa>
Comparando com o exemplo do programa primeiro, a declara¸˜o
ca
PROGRAM primeiro
´ sempre a primeira instru¸˜o de um programa. Ela serve para identificar o c´digo ao compilador.
e
ca
o
Em seguida vˆm as declara¸~es de nomes de vari´veis. Neste ponto, s˜o definidos os nomes das
e
co
a
a
vari´veis a ser usadas pelo programa. Caso n˜o seja necess´rio declarar vari´veis, como no programa
a
a
a
a
primeiro, ´ recomend´vel incluir, pelo menos, a instru¸˜o implicit none. Esta instrui o compilador a
e
a
ca
exigir que todas as vari´veis usadas pelo programa tenham o seu tipo explicitamente definido.1
a
Ap´s declaradas as vari´veis, vˆm os comandos execut´veis. No caso do programa primeiro, o unico
o
a
e
a
´
comando execut´vel empregado foi
a
print *, “Al^ Mam~e”
o
a
o qual tem como conseq¨ˆncia a impress˜o do texto “Alˆ Mam˜e” na tela do monitor, o qual ´ a chamada
ue
a
o
a
e
sa´ padr˜o.
ıda
a
Finalmente, o programa ´ encerrado com a instru¸˜o
e
ca
end program primeiro
Os recursos utilizados no programa primeiro ser˜o explicados com mais detalhes neste e nos pr´ximos
a
o
cap´
ıtulos da apostila.
1 Os

tipos de vari´veis suportados pelo Fortran 95 s˜o discutidos no cap´
a
a
ıtulo 3.

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 2. Formato do C´digo-Fonte
o

2.2

11

Nomes em Fortran 90/95

Um programa em Fortran 90/95 faz referˆncia a muitas entidades distintas, tais como programas, sube
programas, m´dulos, vari´veis, etc. Os nomes destas entidades devem consistir em caracteres alfanum´ricos,
o
a
e
de 1 a 31 caracteres. Os caracteres alfanum´ricos v´lidos s˜o:
e
a
a
ˆ Letras (a - z; A - Z).
ˆ Numerais (0 - 9).
ˆ O caractere underscore “ ”.

A unica restri¸˜o ´ que o primeiro caractere seja uma letra. Os seguintes exemplos s˜o v´lidos:
´
ca e
a a
A
A_COISA
X1
MASSA
Q123
TEMPO_DE_VOO
j´ estes exemplos n˜o s˜o v´lidos:
a
a a a
1A (come¸a com numeral)
c
A COISA (espa¸o em branco)
c
$SINAL (cont´m caractere n˜o alfanum´rico).
e
a
e

2.3

Entrada e sa´ padr˜es
ıda
o

O Fortran 90 possui trˆs comandos de entrada/sa´ de dados. A maneira mais direta de definir valores
e
ıda
de vari´veis ou de exibir os valores destas ´ atrav´s dos dispositivos de entrada/sa´ padr˜es.
a
e
e
ıda
o
O dispositivo padr˜o de entrada de dados ´ o teclado. O comando de leitura para o programa ler os
a
e
valores das vari´veis ´:
a
e
READ *, <lista de nomes de vari´veis>
a
READ(*,*) <lista de nomes de vari´veis>
a
onde na lista de nomes de vari´veis est˜o listados os nomes das vari´veis que dever˜o receber seus
a
a
a
a
valores via teclado. O usu´rio deve entrar com os valores das vari´veis separando-as por v´
a
a
ırgulas.
O dispositivo padr˜o de sa´ de dados ´ a tela do monitor. H´ dois comandos de sa´ padr˜o de dados:
a
ıda
e
a
ıda
a
PRINT *, [’<mensagem>’[,]][<lista de nomes de vari´veis>]
a
WRITE(*,*) [’<mensagem>’[,]][<lista de nomes de vari´veis>]
a
O programa a seguir instrui o computador a ler o valor de uma vari´vel real a partir do teclado e, ent˜o,
a
a
imprimir o valor desta na tela do monitor:
program l e v a l o r
i m p l i c i t none
real : : a
print * , ”I n f o r m e o v a l o r de a : ”
read * , a
print * , ”Valor l i d o : ” , a
end program l e v a l o r
No programa acima, foi declarada a vari´vel real a, cujo valor ser´ lido pelo computador, a partir do teclado,
a
a
´
e ent˜o impresso na tela do monitor. E importante salientar que a instru¸˜o implicit none deve ser sempre
a
ca
a segunda linha de um programa, sub-programa ou m´dulo, aparecendo antes do restante das declara¸˜es
o
co
de vari´veis.
a
Esta se¸˜o apresentou somente um uso muito simples dos recursos de Entrada/Sa´ de dados. Uma
ca
ıda
descri¸˜o mais completa destes recursos ser´ realizada no cap´
ca
a
ıtulo 9 na p´gina 121.
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
12

2.4. Conjunto de caracteres aceitos
Tabela 2.1: Caracteres especiais do Fortran 90/95

Caractere
=
+
*
/
(
)
,
.
$
:

2.4

Nome/Fun¸˜o
ca
Igual
Soma
Subtra¸˜o
ca
Multiplica¸˜o
ca
Divis˜o
a
Parˆnteses esquerdo
e
Parˆnteses direito
e
V´
ırgula
Ponto decimal
Cifr˜o
a
Dois pontos

Caractere
!
“
%
&
;
?
**
’
<
>

Nome/Fun¸˜o
ca
Espa¸o em branco
c
Exclama¸˜o
ca
Aspas
Porcentagem
E comercial (ampersand)
Ponto e v´
ırgula
Ponto de interroga¸˜o
ca
Potˆncia
e
Ap´strofe
o
Menor que
Maior que

Conjunto de caracteres aceitos

No Fortran 90/95, os elementos b´sicos, denominados de tokens, s˜o os caracteres alfanum´ricos, os 10
a
a
e
d´
ıgitos ar´bicos, o underscore “ ” e o conjunto de caracteres especiais apresentados na tabela 2.1. Dentro da
a
sintaxe da linguagem, n˜o existem diferen¸as entre letras mai´sculas e min´sculas.
a
c
u
u

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 3

Tipos de Vari´veis
a
Em Fortran, h´ cinco tipos intr´
a
ınsecos de vari´veis: trˆs tipos num´ricos, inteiros, reais e complexos (em
a
e
e
inglˆs INTEGER, REAL e COMPLEX) e dois tipos n˜o num´ricos, caracteres e l´gicos (em inglˆs CHARACTER e
e
a
e
o
e
LOGICAL). O primeiro grupo de vari´veis ´ utilizado em opera¸˜es matem´ticas e ´ o mais utilizado. O
a
e
co
a
e
segundo grupo ´ utilizado para opera¸˜es que envolvem manipula¸˜es de texto ou opera¸˜es l´gicas.
e
co
co
co o
Em Fortran 90/95, cada um dos cinco tipos intr´
ınsecos possui um valor inteiro n˜o negativo denominado
a
parˆmetro de esp´cie do tipo (em inglˆs, kind type parameter ). A norma padr˜o da linguagem determina
a
e
e
a
que qualquer processador deve suportar pelo menos duas esp´cies para os tipos REAL e COMPLEX e pelo menos
e
uma esp´cie para os tipos INTEGER, CHARACTER e LOGICAL.
e
Um outro avan¸o do Fortran 90 sobre o predecessor Fortran 77 consiste na habilidade em definir novos
c
tipos de vari´veis, baseados nos tipos intr´
a
ınsecos. Estas s˜o os chamados tipos derivados ou estruturas, os
a
quais consistem em combina¸˜es de partes compostas por tipos intr´
co
ınsecos e/ou por outros tipos derivados,
permitindo gerar objetos de complexidade crescente.
Neste cap´
ıtulo, vamos inicialmente definir o uso b´sicos dos tipos intr´
a
ınsecos de vari´veis, seguindo pela
a
defini¸˜o das esp´cies de vari´veis mais comuns, terminando por definir os tipos derivados.
ca
e
a

3.1

Declara¸˜o de tipo de vari´vel
ca
a

Como j´ foi colocado anteriormente, ´ uma boa praxe de programa¸˜o iniciar o setor de declara¸˜es de
a
e
ca
co
vari´veis com a declara¸˜o
a
ca
IMPLICIT NONE
a qual impede a possibilidade de haver nomes de vari´veis n˜o definidos, os quais possuem o seu tipo
a
a
impl´
ıcito, uma pr´tica corriqueira em Fortran 77.
a
A forma geral de uma declara¸˜o de tipo de vari´veis ´:
ca
a
e
<tipo>[([KIND=]<par^metro de esp´cie>)][,<lista de atributos>] ::
a
e

<lista de entidades>

onde <tipo> especifica o tipo de vari´vel, <par^metro de esp´cie> especifica a esp´cie da vari´vel, <lista
a
a
e
e
a
de atributos> ´ um dos seguintes:
e
PARAMETER
PUBLIC
PRIVATE
POINTER
TARGET
ALLOCATABLE

DIMENSION(<lista de extens~es>)
o
INTENT(<inout>)
OPTIONAL
SAVE
EXTERNAL
INTRINSIC

e cada entidade ´
e
<nome do objeto> [(lista de extens~es)] [*char-len] [= express~o de inicializa¸~o]
o
a
ca
ou
<nome da fun¸~o> [*char-len]
ca
onde <nome do objeto> ´ o nome da vari´vel, seguindo a regra de nomes v´lidos definida no cap´
e
a
a
ıtulo 2.
Os objetos restantes, em particular <par^metro de esp´cie> e <lista de atributos>, ser˜o estudados
a
e
a
ao longo do desenvolvimento desta apostila.
13
14

3.2. Vari´veis do tipo INTEGER
a

3.2

Vari´veis do tipo INTEGER
a

Este tipo de vari´vel armazena apenas a parte inteira de um n´mero, exemplos de n´meros inteiros
a
u
u
v´lidos, tamb´m denominados literais s˜o:
a
e
a
123, 89312, 5.
As declara¸˜es b´sicas de nomes de vari´veis de tipo inteiro s˜o:
co
a
a
a
Fortran 77: INTEGER <lista de nomes de vari´veis>
a
Fortran 90/95: INTEGER ::

<lista de nomes de vari´veis>
a

O tipo de dados inteiro possui valores que pertencem ao conjunto dos n´meros inteiros.
u
Programa exemplo:
program i n t e i r o
i m p l i c i t none
integer : : x
! O v a l o r d i g i t a d o n˜ o pode c o n t e r ponto ( . ) Caso i s t o
a
! aco nte¸ a , v a i g e r a r um e r r o de e x e c u ¸ ˜ o no programa ,
c
ca
! a b o r t a n d o o mesmo .
read * , x
print * , ”Valor l i d o : ” , x
end program i n t e i r o

3.3

Vari´veis do tipo REAL
a

O tipo de vari´vel real ´ composto de quatro partes, assim dispostas:
a
e
1. uma parte inteira, com ou sem sinal,
2. um ponto decimal,
3. uma parte fracion´ria e
a
4. um expoente, tamb´m com ou sem sinal.
e
Um ou ambos os itens 1 e 3 devem estar presentes. O item 4 ou est´ ausente ou consiste na letra E seguida
a
por um inteiro com ou sem sinal. Um ou ambos os itens 2 e 4 devem estar presentes. Exemplos de literais
reais s˜o:
a
-10.6E-11 (representando −10, 6 × 10−11 )
1.
-0.1
1E-1 (representando 10−1 ou 0,1)
3.141592653
Os literais reais s˜o representa¸˜es do conjunto dos n´meros reais e o padr˜o da linguagem n˜o especifica
a
co
u
a
a
o intervalo de valores aceitos para o tipo real e nem o n´mero de d´
u
ıgitos significativos na parte fracion´ria
a
(item 3) que o processador suporta, uma vez que estes valores dependem do tipo de processador em uso.
Valores comuns s˜o: intervalo de n´meros entre 10−38 a 10+38 , com uma precis˜o de cerca de 7 (sete) d´
a
u
a
ıgitos
decimais.
As declara¸˜es b´sicas do tipo real s˜o:
co
a
a
Fortran 77: REAL <lista de nomes de vari´veis>
a
Fortran 90/95: REAL ::

<lista de nomes de vari´veis>
a

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 3. Tipos de Vari´veis
a

15

Programa exemplo:
program v a r r e a l
i m p l i c i t none
r e a l : : a , b= 1 0 . 5 e−2 ! V a r i ´ v e l b ´ i n i c i a l i z a d a a 1 0 . 5 e −2.
a
e
print * , ’ Valor de a : ’
read * , a
print * , ’ Valor de a : ’ , a
print * , ’ Valor de b : ’ , b
end program v a r r e a l

3.4

Vari´veis do tipo COMPLEX
a

O Fortran, como uma linguagem destinada para c´lculos cient´
a
ıficos ou em engenharia, tem a vantagem
de possuir um terceiro tipo intr´
ınseco: n´meros complexos. Este tipo ´ concebido como um par de literais,
u
e
os quais s˜o ou inteiros ou reais, separados por v´
a
ırgula “,” e contidos entre parˆnteses “(“ e “)”. Os literais
e
complexos representam n´meros contidos no conjunto dos n´meros complexos, isto ´, n´meros do tipo
u
u
e u
√
e
e
a
u
z = x + iy, onde i = −1, x ´ a parte real e y ´ a parte imagin´ria do n´mero complexo z. Assim, um
literal complexo deve ser escrito:
(<parte real>,<parte imagin´ria>)
a
Exemplos de literais complexos s˜o:
a
(1.,3.2) (representando 1 + 3, 2i)
(1.,.99E-2) (representando 1 + 0, 99 × 10−2 i)
(1.0,-3.7)
Uma outra grande vantagem do Fortran ´ que toda a ´lgebra de n´meros complexos j´ est´ implementada
e
a
u
a a
a n´ de compilador. Assim, se for realizado o produto de dois n´meros complexos (x1,y1) e (x2,y2), o
ıvel
u
resultado ser´ o literal complexo dado por (x1*x2 - y1*y2,x1*y2 + x2*y1). O mesmo acontecendo com
a
as outras opera¸˜es alg´bricas.
co
e
As declara¸˜es b´sicas do tipo complexo s˜o:
co
a
a
Fortran 77: COMPLEX <lista de nomes de vari´veis>
a
Fortran 90/95: COMPLEX ::

<lista de nomes de vari´veis>
a

Programa exemplo:
program va r c o m pl ex a
i m p l i c i t none
complex : : a= (5 , −5) , b , c ! V a r i ´ v e l a ´ i n i c i a l i z a d a a (5 , −5).
a
e
print * , ”Valor de b : ”
! O v a l o r de b d e v e s e r e n t r a d o como um l i t e r a l complexo .
! Exemplo : ( − 1 . 5 , 2 . 5 )
read * , b
c= a * b
print * , ”O v a l o r de c : ” , c
! V e r i f i q u e o r e s u l t a d o no p a p e l .
end program va r c o m pl ex a

3.5

Vari´veis do tipo CHARACTER
a

O tipo padr˜o consiste em um conjunto de caracteres contidos em um par de ap´strofes ou aspas. Os
a
o
caracteres n˜o est˜o restritos ao conjunto de caracteres padr˜o definidos na se¸˜o 2.4. Qualquer caractere
a
a
a
ca
que possa ser representado pelo processador ´ aceito, exceto os caracteres de controle tais como o return.
e
Os ap´strofes ou aspas servem como delimitadores dos literais de caractere e n˜o s˜o considerados parte
o
a a
integrante do conjunto. Ao contr´rio das normas usuais, um espa¸o em branco ´ diferente de dois ou mais.
a
c
e
Exemplos de literais de caractere:
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
16

3.6. Vari´veis do tipo LOGICAL
a
’bom Dia’
’bomDia’
’BRASIL’
“Fortran 90”
As declara¸˜es mais utilizadas para o tipo caractere s˜o:
co
a

Fortran 77: character*<comprimento> <lista de nomes de vari´veis>
a
ou
character <nome 1>*<comp. 1>, [<nome 2>*<comp. 2>, ...]
Fortran 90/95: character(len=<comprimento>) ::

<lista de nomes de vari´veis>
a

onde <comprimento> indica a quantidade de caracteres contidos nas vari´veis. Todas as vari´veis definidas
a
a
por esta declara¸˜o tˆm o mesmo n´mero de caracteres. Se for informado um literal maior que <comprica e
u
mento>, este ser´ truncado; se for informado um literal menor que o declarado, o processador ir´ preencher
a
a
o espa¸o restante ` direita com espa¸os em branco.
c
a
c
Programa exemplo:
program l e c a r a c t e r e
i m p l i c i t none
character ( len =10) : : s t r r e a d
print * , ”Entre com t e x t o ” :
read ’ ( a ) ’ , s t r r e a d
print * , ”Texto l i d o : ” , s t r r e a d
end program l e c a r a c t e r e
´
E importante mencionar aqui a regra particular para o formato de fonte dos literais de caractere que s˜o
a
escritos em mais de uma linha:
1. Cada linha deve ser encerrada com o caractere “&” e n˜o pode ser seguida por coment´rio.
a
a
2. Cada linha de continua¸˜o deve ser precedida tamb´m pelo caractere “&”.
ca
e
3. Este par “&&” n˜o faz parte do literal.
a
4. Quaisquer brancos seguindo um & em final de linha ou precedendo o mesmo caractere em in´
ıcio de
linha n˜o s˜o partes do literal.
a a
5. Todo o restante, incluindo brancos, fazem parte do literal.
Como exemplo temos:
car_longo =
’O tempo que eu hei sonhado
& Quantos anos foi de vida!
& Ah, quanto do meu passado
& Foi s´ a vida mentida
o
& De um futuro imaginado!
&
& Aqui ` beira do rio
a
& Sossego sem ter raz~o.
a
& Este seu correr vazio
& Figura, an^nimo e frio,
o
& A vida, vivida em v~o.’
a

3.6

&
&
&
&
&
&
&
&
&
&
&

Vari´veis do tipo LOGICAL
a

O tipo l´gico define vari´veis l´gicas. Uma vari´vel l´gica s´ pode assumir dois valores, verdadeiro e
o
a
o
a
o
o
falso. A representa¸˜o dos dois estado poss´
ca
ıveis de uma vari´vel l´gica s˜o:
a
o
a
ˆ .TRUE. ⇒ Verdadeiro
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 3. Tipos de Vari´veis
a

17

ˆ .FALSE. ⇒Falso.

As declara¸˜es do tipo l´gico s˜o:
co
o
a
Fortran 77: logical <lista de nomes de vari´veis>
a
Fortran 90/95: logical ::

<lista de nomes de vari´veis>
a

Programa exemplo:
program l o g i c o
i m p l i c i t none
l o g i c a l : : a= . t r u e .
i f ( a ) then
print * , ”A v a r i ´ v e l ´ v e r d a d e i r a . ”
a
e
end i f
end program l o g i c o

3.7

O conceito de esp´cie (kind)
e

Em Fortran, al´m dos 5 tipos de vari´veis definidos nas se¸˜es 3.2 a 3.6, ´ poss´ definir extens˜es a
e
a
co
e
ıvel
o
um determinado tipo, cujas declara¸˜es dependem da vers˜o do Fortran utilizada e do processador no qual
co
a
o programa ser´ executado.
a

3.7.1

Fortran 77

Em Fortran 77 as extens˜es mais comuns e as correspondentes declara¸˜es s˜o:
o
co
a
ˆ vari´veis reais de precis˜o dupla: real*8 <lista de nomes de vari´veis> ou double precision
a
a
a
<lista de nomes de vari´veis>.
a
ˆ vari´veis reais de precis˜o estendida (ou qu´drupla): real*16 <lista de nomes de vari´veis>.
a
a
a
a
ˆ vari´veis complexas de precis˜o dupla: complex*16 <lista de nomes de vari´veis>.
a
a
a

As diferen¸as entre estas extens˜es e os correspondentes tipos originais ser˜o ilustradas a seguir.
c
o
a

3.7.2

Fortran 90/95

Em Fortran 90/95, cada um dos cinco tipos intr´
ınsecos, INTEGER, REAL, COMPLEX, CHARACTER e LOGICAL possui associado um valor inteiro n˜o negativo denominado parˆmetro de esp´cie do tipo (kind type
a
a
e
parameter). Por exigˆncia do padr˜o, um processador deve suportar, no m´
e
a
ınimo, duas esp´cies para os tipos
e
REAL e COMPLEX e uma esp´cie para os tipos INTEGER, CHARACTER e LOGICAL.
e
Os valores da esp´cie s˜o dependentes do processador e/ou do compilador empregado. Contudo, h´
e
a
a
fun¸˜es intr´
co
ınsecas fornecidas pelo compilador que verificam as precis˜es suportadas pelo processador e que
o
podem ser usadas para definir o valor do parˆmetro KIND, possibilitando assim a portabilidade do c´digo,
a
o
isto ´, a possibilidade deste rodar em diferentes arquiteturas usando uma precis˜o m´
e
a
ınima especificada pelo
programador.
Para demonstrar como diferentes compiladores implementam e usam o parˆmetro de esp´cie, ser˜o cona
e
a
siderados os compiladores Intel® Fortran Compiler for linux (vers˜o 9.1), gfortran e o compilador
a
F, todos gratu´
ıtos.
3.7.2.1

Compilador Intel® Fortran

O compilador Intel® Fortran oferece os seguintes tipos intr´
ınsecos, juntamente com as respectivas
declara¸˜es de tipo e esp´cie:
co
e
Tipo Inteiro. H´ 04 parˆmetros de esp´cie para o tipo inteiro.
a
a
e
Declara¸˜o: INTEGER([KIND=]<n>) [::] <lista de nomes de vari´veis>
ca
a
Sendo <n> das esp´cies 1, 2, 4 ou 8. Se o parˆmetro de esp´cie ´ explicitado, as vari´veis na <lista de
e
a
e e
a
nomes de vari´veis> ser˜o da esp´cie escolhida. Em caso contr´rio, a esp´cie ser´ o inteiro padr˜o:
a
a
e
a
e
a
a
INTEGER(KIND=4); ou seja, a declara¸˜o INTEGER :: <lista de nomes de vari´veis> equivale a
ca
a
INTEGER(KIND=4) :: <lista de nomes de vari´veis>.
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
18

3.7. O conceito de esp´cie (kind)
e

® Fortran.

Tabela 3.1: Tabela de armazenamento de vari´veis para o compilador Intel
a

Tipo e Esp´cie
e
INTEGER(KIND=1)
INTEGER(KIND=2)
INTEGER(KIND=4)
INTEGER(KIND=8)
REAL(KIND=4)
REAL(KIND=8)
REAL(KIND=16)

Armazenamento (bytes)
1=8 bits
2
4
8
4
8
16

Tipo e Esp´cie
e
LOGICAL(KIND=1)
LOGICAL(KIND=2)
LOGICAL(KIND=4)
LOGICAL(KIND=8)
COMPLEX(KIND=4)
COMPLEX(KIND=8)
COMPLEX(KIND=16)

Armazenamento (bytes)
1
2
4
8
8
16
32

® Fortran.

Programa 3.1: Testa distintas esp´cies suportadas pelo compilador Intel
e

program t e s t a k i n d i n t e l
i m p l i c i t none
integer , parameter : : dp= 8 , qp= 16
real : : r s i m p l e s
r e a l ( kind= dp ) : : r d u p l a
r e a l ( kind= qp ) : : r quad
!
! C a l c u l a a r a i z quadrada de 2 em d i v e r s a s p r e c i s ˜ e s .
o
r s i m p l e s= s q r t ( 2 . 0 )
! Precis˜o simples
a
r d u p l a= s q r t ( 2 . 0 dp ) ! P r e c i s ˜ o d u p l a
a
r quad= s q r t ( 2 . 0 qp )
! P r e c i s ˜ o q u ´ d r u p l a ou e s t e n d i d a .
a
a
!
! Imprime r e s u l t a d o s na t e l a .
print * , r s i m p l e s
print * , r d u p l a
print * , r quad
!
end program t e s t a k i n d i n t e l

Tipo Real. H´ 03 parˆmetros de esp´cie para o tipo real.
a
a
e
Declara¸˜o: REAL([KIND=]<n>) [::] <lista de nomes de vari´veis>
ca
a
Sendo <n> igual a 4, 8 ou 16. Caso o parˆmetro de esp´cie n˜o seja especificado, a esp´cie ser´ o real
a
e
a
e
a
padr˜o: REAL(KIND= 4).
a
Tipo Complexo. H´ 03 parˆmetros de esp´cie para o tipo complexo.
a
a
e
Declara¸˜o: COMPLEX([KIND=]<n>) [::] <lista de nomes de vari´veis>
ca
a
Sendo <n> igual a 4, 8 ou 16. Caso o parˆmetro de esp´cie n˜o seja explicitado, a esp´cie ser´ o
a
e
a
e
a
complexo padr˜o: COMPLEX(KIND= 4).
a
Tipo L´gico. H´ 04 parˆmetros de esp´cie para o tipo l´gico.
o
a
a
e
o
Declara¸˜o: LOGICAL([KIND=]<n>) [::] <lista de nomes de vari´veis>
ca
a
Sendo <n> igual a 1, 2, 4 ou 8.
Tipo Caractere. H´ somente uma esp´cie do tipo caractere.
a
e
Declara¸˜o: CHARACTER([KIND=1],[LEN=]<comprimento>) [::]
ca

<lista de nomes de vari´veis>
a

Cada esp´cie distinta ocupa um determinado espa¸o de mem´ria na CPU. Para o compilador Intel®
e
c
o
Fortran, o espa¸o ocupado est´ descrito na tabela 3.1.
c
a
O programa 3.1 a seguir ilustra do uso e as diferen¸as de algumas op¸˜es de esp´cies de tipos de vari´veis.
c
co
e
a
O mesmo programa tamb´m indica o uso de alguns atributos na declara¸˜o de vari´veis, tais como na
e
ca
a
declara¸˜o
ca
INTEGER, PARAMETER ::

DP= 2

O atributo PARAMETER indica que as vari´veis declaradas nesta senten¸a devem se comportar como constantes
a
c
matem´ticas, isto ´, n˜o podem ser alteradas no programa por nenhuma atribui¸˜o de vari´veis (ver cap´
a
e a
ca
a
ıtulo
4). Na mesma declara¸˜o, j´ est´ sendo inicializado o valor do parˆmetro DP, sendo este igual a 2.
ca a
a
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 3. Tipos de Vari´veis
a

19

Tabela 3.2: Tabela de armazenamento de vari´veis para o compilador gfortran da funda¸ao GNU.
a
c˜

Tipo e Esp´cie
e
INTEGER(KIND=1)
INTEGER(KIND=2)
INTEGER(KIND=4)
INTEGER(KIND=8)
INTEGER(KIND=16)1
REAL(KIND=4)
REAL(KIND=8)
REAL(KIND=10)

Armazenamento (bytes)
1=8 bits
2
4
8
16
4
8
10

Tipo e Esp´cie
e
LOGICAL(KIND=1)
LOGICAL(KIND=2)
LOGICAL(KIND=4)
LOGICAL(KIND=8)
LOGICAL(KIND=16)
COMPLEX(KIND=4)
COMPLEX(KIND=8)
COMPLEX(KIND=10)

Armazenamento (bytes)
1
2
4
8
16
8
16
20

O mesmo exemplo tamb´m ilustra o uso da fun¸˜o impl´
e
ca
ıcita SQRT(X):
R_SIMPLES= SQRT(2.0)
a qual calculou a raiz quadrada da constante 2.0 e atribuiu o resultado ` vari´vel R_SIMPLES.
a
a
3.7.2.2

Compilador gfortran

Gfortran ´ o compilador Fortran 95 da GNU (Funda¸˜o Gnu is Not Unix.), inicialmente desenvolvido
e
ca
como alternativa ao compilador f95 distribu´ pelas vers˜es comerciais do Unix. Atualmente, o gfortran
ıdo
o
´ parte integrante da plataforma de desenvolvimento de software GCC (GNU Compiler Collection), que
e
´ composta por compiladores de diversas linguagens distintas, tais como Fortran 95, C/C++, Java, Ada,
e
entre outros. O comando gfortran consiste simplesmente em um script que invoca o programa f951, o qual
traduz o c´digo-fonte para assembler, invocando em seguida o linkador e as bibliotecas comuns do pacote
o
GCC.
No gfortran, os parˆmetros de esp´cie s˜o determinados de forma semelhante ao compilador Intel®
a
e
a
Fortran, discutido na se¸˜o 3.7.2.1, ou seja, o parˆmetro indica o n´mero de bytes necess´rios para armaca
a
u
a
zenar cada vari´vel da respectiva esp´cie de tipo. As esp´cies suportadas pelo gfortran s˜o descritas na
a
e
e
a
tabela 3.2.
O programa testa_kind_gfortran a seguir (programa 3.2) ilustra o uso e as diferen¸as entre as diversas
c
esp´cies de tipos de dados no compilador gfortran.
e
3.7.2.3

Compilador F

Como exemplo do uso do parˆmetro de esp´cie, a tabela 3.3 ilustra os valores suportados pelo compilador
a
e
F, conforme fornecidos pelo guia do usu´rio2 . H´ duas possibilidades para os n´meros da esp´cie:
a
a
u
e
1. o modo padr˜o de opera¸˜o, tamb´m denominado seq¨encial, o qual pode, por´m, ser especificado
a
ca
e
u
e
explicitamente no momento da compila¸˜o com a chave -kind=sequential;
ca
2. o esquema de numera¸˜o bytes, o qual deve ser especificado no momento da compila¸˜o com a chave
ca
ca
-kind=byte:
alunos|fulano>F -kind=byte <nome programa>.f90 -o <nome programa>
O exemplo a seguir, programa testa_kind_F, ilustra do uso e as diferen¸as de algumas op¸˜es de esp´cies
c
co
e
de tipos de vari´veis.
a
program t e s t a k i n d F
i m p l i c i t none
integer , parameter : : dp= 2
real : : r s i m p l e s
r e a l ( kind= dp ) : : r d u p l a
complex : : c s i m p l e s
complex ( kind= dp ) : : c d u p l a
!
! C a l c u l a a r a i z quadrada de 2 em d i v e r s a s p r e c i s ˜ e s .
o
r s i m p l e s= s q r t ( 2 . 0 )
! Precis˜o simples
a
1 Em
2 The

plataformas de 64 bits, tais como a fam´ de processadores Intel® Core— 2.
ılia
F Compiler and Tools (http://www.fortran.com/imagine1/ftools.pdf).

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
20

3.7. O conceito de esp´cie (kind)
e

Programa 3.2: Testa distintas esp´cies suportadas pelo compilador gfortran .
e

program t e s t a k i n d g f o r t r a n
i m p l i c i t none
integer , parameter : : i 1= 1 , i 2= 2 , i 4= 4 , i 8= 8 , i 1 6= 16
integer , parameter : : dp= 8 , qp= 10
integer ( kind= i 1 ) : : v i 1
integer ( kind= i 2 ) : : v i 2
integer ( kind= i 4 ) : : v i 4
integer ( kind= i 8 ) : : v i 8
integer ( kind= i 1 6 ) : : v i 1 6
real : : r s i m p l e s
r e a l ( kind= dp ) : : r d u p l a
r e a l ( kind= qp ) : : r quad
complex : : c s i m p l e s
complex ( kind= dp ) : : c d u p l a
complex ( kind= qp ) : : c quad
!
! Mostra maiores numeros r e p r e s e n t a v e i s do t i p o i n t e i r o .
v i 1= huge ( 1 i 1 )
v i 2= huge ( 1 i 2 )
v i 4= huge ( 1 i 4 )
v i 8= huge ( 1 i 8 )
v i 1 6= huge ( 1 i 1 6 )
print * , ’ E s p e c i e s I n t e i r a s : ’
print * , vi1 , vi2 , v i 4
print * , v i 8
print * , v i 1 6
! Mostra maiores numeros r e p r e s e n t a v e i s do t i p o r e a l .
r s i m p l e s= huge ( 1 . 0 )
! Precisao simples
r d u p l a= huge ( 1 . 0 dp ) ! P r e c i s a o d u p l a
r quad= huge ( 1 . 0 qp ) ! P r e c i s a o e s t e n d i d a
!
! C a l c u l a a r a i z quadrada de ( 2 , 2 ) em d i v e r s a s p r e c i s o e s .
c s i m p l e s= s q r t ( ( 2 . 0 , 2 . 0 ) )
c d u p l a=
s q r t ( ( 2 . 0 dp , 2 . 0 dp ) )
c quad=
s q r t ( ( 2 . 0 qp , 2 . 0 qp ) )
!
print * ,
print * , ’ E s p e c i e s R e a i s e Complexas : ’
print * , r s i m p l e s
print * , r d u p l a
print * , r quad
print * , c s i m p l e s
print * , c d u p l a
print * , c quad
!
end program t e s t a k i n d g f o r t r a n

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 3. Tipos de Vari´veis
a

21

Tabela 3.3: Valores de esp´cies (kind) de tipos de vari´veis suportados pelo compilador F.
e
a

Tipo
Real
Real
Real3
Complex
Complex
Complex
Logical
Logical
Logical
Logical
Integer
Integer
Integer
Integer
Character

N´ mero do Kind
u
(Sequencial)
¨
1
2
3
1
2
3
1
2
3
4
1
2
3
4
1

N´ mero do Kind
u
(Byte)
4
8
16
4
8
16
1
2
4
8
1
2
4
8
1

r d u p l a= s q r t ( 2 . 0 )
! Precis˜o dupla
a
!
! N´ meros c o m p l ex o s : p a r t e r e a l : r a i z de 2 .
u
c s i m p l e s= cmplx ( s q r t ( 2 . 0 ) , s q r t ( 3 . 0 ) )
c d u p l a= cmplx ( s q r t ( 2 . 0 ) , s q r t ( 3 . 0 ) )
!
! Imprime r e s u l t a d o s na t e l a .
print * , r s i m p l e s
print * , r d u p l a
print * , c s i m p l e s
print * , c d u p l a
!
end program t e s t a k i n d F

3.7.2.4

Descri¸˜o
ca
Real precis˜o simples (padr˜o)
a
a
Real precis˜o dupla
a
Real precis˜o qu´drupla
a
a
Complexo precis˜o simples (padr˜o)
a
a
Complexo precis˜o dupla
a
Complexo precis˜o qu´drupla
a
a
L´gico 1 byte
o
L´gico 2 bytes
o
L´gico 4 bytes (padr˜o)
o
a
L´gico 8 bytes
o
Inteiro 1 byte
Inteiro 2 bytes
Inteiro 4 bytes (padr˜o)
a
Inteiro 8 bytes
Caractere, 1 byte por caractere

P ar te i m a g i n a r i a : r a i z de 3 .
´

Literais de diferentes esp´cies
e

Para disting¨ir as esp´cies dos literais (ou constantes) dentre diferentes n´meros fornecidos ao compilador,
u
e
u
utiliza-se o sufixo _<k>, sendo <k> o parˆmetro da esp´cie do tipo:
a
e
Literais inteiros. Constante inteiras, incluindo a esp´cie, s˜o especificadas por:
e
a
[<s>]<nnn...>[_<k>]
onde: <s> ´ um sinal (+ ou −); obrigat´rio se negativo, opcional se positivo. <nnn...> ´ um conjunto
e
o
e
de d´
ıgitos (0 a 9); quaisquer zeros no in´ s˜o ignorados. _<k> ´ um dos parˆmetros de esp´cie do
ıcio a
e
a
e
tipo: 1, 2, 4 ou 8; esta op¸˜o explicita a esp´cie do tipo ` qual o literal pertence.
ca
e
a
Literais reais. Constantes reais s˜o especificadas de diferentes maneiras, dependendo se possuem ou n˜o
a
a
parte exponencial. A regra b´sica para a especifica¸˜o de um literal real j´ foi definida na se¸˜o 3.3.
a
ca
a
ca
Para explicitar a esp´cie do tipo real ` qual o literal pertence, deve-se incluir o sufixo _<k>, onde <k>
e
a
´ um dos parˆmetros de esp´cie do tipo: 4, 8 ou 16. Por exemplo:
e
a
e
2.0_8: para indicar tipo real, esp´cie 8.
e
Literais complexos. A regra b´sica para a especifica¸˜o de um literal complexo j´ foi definida na se¸˜o
a
ca
a
ca
3.4. Para explicitar a esp´cie do tipo ` qual o literal pertence, deve-se incluir o sufixo _<k>, onde <k>
e
a
´ um dos parˆmetros de esp´cie do tipo: 4, 8 ou 16, em cada uma das partes real e imagin´ria do
e
a
e
a
literal complexo. Por exemplo:
(1.0_8,3.5345_8): para indicar tipo complexo, esp´cie 8.
e
Literais l´gicos. Uma constante l´gica pode tomar uma das seguintes formas:
o
o
.TRUE.[_<k>]
3 Vari´veis
a

reais e complexas de precis˜o qu´drupla n˜o s˜o suportadas por todas as vers˜es do compilador F.
a
a
a a
o

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
22

3.7. O conceito de esp´cie (kind)
e
.FALSE.[_<k>]
onde <k> ´ um dos parˆmetros de esp´cie do tipo: 1, 2, 4 ou 8.
e
a
e

3.7.3

Fun¸˜es intr´
co
ınsecas associadas ` esp´cie
a
e

Embora as declara¸˜es de esp´cie do tipo possam variar para diferentes compiladores, o padr˜o da
co
e
a
linguagem estabelece um conjunto de fun¸˜es intr´
co
ınsecas que facilitam a determina¸˜o e a declara¸˜o destas
ca
ca
esp´cies de uma forma totalmente port´vel, isto ´, independente de compilador e/ou arquitetura.
e
a
e
As fun¸˜es intr´
co
ınsecas descritas nesta e nas subsequentes se¸˜es ser˜o novamente abordadas no cap´
co
a
ıtulo
7, onde ser˜o apresentadas todas as rotinas intr´
a
ınsecas fornecidas pelo padr˜o da linguagem Fortran 95.
a
3.7.3.1

KIND(X)

A fun¸˜o intr´
ca
ınseca KIND(X), a qual tem como argumento uma vari´vel ou constante de qualquer tipo
a
intr´
ınseco, retorna o valor inteiro que identifica a esp´cie da vari´vel X. Por exemplo,
e
a
program t e s f u n k i n d
i m p l i c i t none
integer : : i , j
integer , parameter : : dp= 2
real : : y
r e a l ( kind= dp ) : : x
!
i= kind ( x ) ! i= 2
j= kind ( y ) ! Depende do s i s t e m a ( j =1 para c o m p i l a d o r F ) .
print * , i
print * , j
end program t e s f u n k i n d
Outros exemplos:
KIND(0)
KIND(0.0)
KIND(.FALSE.)
KIND(’A’)
KIND(0.0D0)

3.7.3.2

!
!
!
!
!
!
!
!
!
!

Retorna a esp´cie padr~o do tipo inteiro.
e
a
(Dependente do processador).
Retorna a esp´cie padr~o do tipo real.
e
a
(Depende do processador).
Retorna a esp´cie padr~o do tipo l´gico.
e
a
o
(Depende do processador).
Fornece a esp´cie padr~o de caractere.
e
a
(Sempre igual a 1).
Usualmente retorna a esp´cie do tipo real de precis~o dupla.
e
a
(Pode n~o ser aceito por todos compiladores).
a

SELECTED_REAL_KIND(P,R)

A fun¸˜o intr´
ca
ınseca SELECTED_REAL_KIND(P,R) tem dois argumentos opcionais: P e R. A vari´vel P
a
especifica a precis˜o (n´mero de d´
a
u
ıgitos decimais) m´
ınima requerida e R especifica o intervalo de varia¸˜o
ca
m´
ınimo da parte exponencial da vari´vel.
a
A fun¸˜o SELECTED_REAL_KIND(P,R) retorna o valor da esp´cie que satisfaz, ou excede minimamente, os
ca
e
requerimentos especificados por P e R. Se mais de uma esp´cie satisfaz estes requerimentos, o valor retornado
e
´ aquele com a menor precis˜o decimal. Se a precis˜o requerida n˜o for dispon´
e
a
a
a
ıvel, a fun¸˜o retorna o valor
ca
-1; se o intervalo da exponencial n˜o for dispon´
a
ıvel, a fun¸˜o retorna -2 e se nenhum dos requerimentos for
ca
dispon´
ıvel, o valor -3 ´ retornado.
e
Esta fun¸˜o, usada em conjunto com a declara¸˜o de esp´cie, garante uma completa portabilidade ao
ca
ca
e
programa, desde que o processador tenha dispon´
ıveis os recursos solicitados. O exemplo a seguir ilustra o
uso desta fun¸˜o intr´
ca
ınseca e outros recursos.
program t e s s e l e c t e d
integer , parameter : : i 1 0= s e l e c t e d r e a l k i n d ( 1 0 , 2 0 0 )
integer , parameter : : dp= 8
r e a l ( kind= i 1 0 ) : : a , b , c
r e a l ( kind= dp ) : : d
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 3. Tipos de Vari´veis
a

23

print * , i 1 0
a= 2 . 0 i 1 0
b= s q r t ( 5 . 0 i 1 0 )
c= 3 . 0 e 1 0 i 1 0 ,
d= 1 . 0 e201 dp
print * , a
print * , b
print * , c
print * , d
end program t e s s e l e c t e d
Pode-se ver que a precis˜o requerida na vari´vel I10 ´ dispon´ na esp´cie correspondente ` precis˜o dupla
a
a
e
ıvel
e
a
a
de uma vari´vel real para os compiladores mencionados (ver, por exemplo, tabela 3.2). Um outro recurso
a
dispon´ ´ a possibilidade de especificar constantes de uma determinada esp´cie, como na atribui¸˜o
ıvel e
e
ca
A= 2.0_I10
A constante A foi explicitamente especificada como pertencente ` esp´cie I10 seguindo-se o valor num´rico
a
e
e
com um underscore e com o parˆmetro de esp´cie do tipo (I10). Deve-se notar tamb´m que a defini¸˜o da
a
e
e
ca
esp´cie I10, seguida da declara¸˜o das vari´veis A, B e C como sendo desta esp´cie, determina o intervalo
e
ca
a
e
m´
ınimo de varia¸˜o da parte exponencial destas vari´veis. Se o parˆmetro da esp´cie associada ` constante
ca
a
a
e
a
I10 for distinto do parˆmetro DP, a vari´vel D n˜o poderia ter sido declarada tamb´m da esp´cie I10, pois
a
a
a
e
e
a atribui¸˜o
ca
D= 1.0E201_I10
iria gerar uma mensagem de erro no momento da compila¸˜o, uma vez que a parte exponencial excede
ca
o intervalo definido para a esp´cie I10 (200). Contudo, para alguns compiladores, como o gfortran, a
e
compila¸˜o ir´ resultar em I10 = DP, tornando desnecess´ria uma das declara¸˜es acima. Este exemplo
ca
a
a
co
demonstra a flexibilidade e a portabilidade propiciada pelo uso da fun¸˜o intr´
ca
ınseca SELECTED_REAL_KIND.
3.7.3.3

SELECTED_INT_KIND(R)

A fun¸˜o intr´
ca
ınseca SELECTED_INT_KIND(R) ´ usada de maneira similar ` fun¸˜o SELECTED_REAL_KIND.
e
a
ca
Agora, a fun¸˜o tem um unico argumento R, o qual especifica o intervalo de n´meros inteiros requerido.
ca
´
u
Assim, SELECTED_INT_KIND(r) retorna o valor da esp´cie que representa, no m´
e
ınimo, valores inteiros no
intervalo −10r a +10r . Se mais de uma esp´cie satisfaz o requerimento, o valor retornado ´ aquele com o
e
e
menor intervalo no expoente r. Se o intervalo n˜o for dispon´
a
ıvel, o valor -1 ´ retornado.
e
O exemplo a seguir mostra a declara¸ao de um inteiro de uma maneira independente do sistema:
c˜
INTEGER, PARAMETER :: I8= SELECTED_INT_KIND(8)
INTEGER(KIND= I8) :: IA, IB, IC
As vari´veis inteiras IA, IB e IC podem ter valores entre −108 a +108 no m´
a
ınimo, se dispon´
ıvel pelo
processador.

3.8

Tipos derivados

Uma das maiores vantagens do Fortran 90/95 sobre seus antecessores est´ na disponibilidade ao proa
gramador de definir seus pr´prios tipos de vari´veis. Estas s˜o os chamados tipos derivados, tamb´m
o
a
a
e
freq¨entemente denominados de estruturas.
u
A forma geral da declara¸˜o de um tipo derivado ´:
ca
e
TYPE [[,<acesso> ] ::] <nome do tipo >
[PRIVATE]
<declara¸~es de componentes >
co
END TYPE [<nome do tipo >]
onde cada <declara¸˜o de componentes> tem a forma
ca
<tipo >[[, <atributos >] ::] <lista de componentes >
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
24

3.8. Tipos derivados

onde aqui o <tipo> pode ser um tipo de vari´vel intr´
a
ınseca ou outro tipo derivado. A declara¸˜o de uma
ca
lista de vari´veis do tipo derivado <nome do tipo> ´ feita atrav´s da linha:
a
e
e
TYPE (<nome do tipo >) [::] <lista de nomes>
Para tentar-se entender o uso de uma vari´vel de tipo derivado, vamos definir um novo tipo: PONTO, o qual
a
ser´ constru´ a partir de trˆs valores reais, representando os valores das coordenadas x, y e z do ponto no
a
ıdo
e
espa¸o cartesiano:
c
program d e f t i p o d e r
i m p l i c i t none
type : : ponto
real : : x , y , z
end type ponto
!
type ( ponto ) : : c e n t r o , a p i c e
!
a p i c e%x= 0 . 0
a p i c e%y= 1 . 0
a p i c e%z= 0 . 0
c e n t r o = ponto ( 0 . 0 , 0 . 0 , 0 . 0 )
!
print * , a p i c e
print * , c e n t r o
!
end program d e f t i p o d e r
No exemplo acima, definiu-se o tipo derivado PONTO, composto por trˆs componentes reais x, y e z. Em
e
seguida, declarou-se duas vari´veis como sendo do tipo PONTO: CENTRO e APICE. A seguir, atribuiu-se os
a
valores para estas vari´veis. Finalmente, mandou-se imprimir na tela o valor das vari´veis.
a
a
Como foi mostrado na atribui¸˜o APICE%X= 0.0, cada componente da vari´vel de tipo derivado pode ser
ca
a
referenciada individualmente por meio do caractere seletor de componente, “%”. J´ a vari´vel CENTRO teve
a
a
os valores de suas componentes definidos pelo construtor de estrutura:
CENTRO= PONTO(0.0,0.0,0.0)
ou seja, CENTRO%X= 0.0, CENTRO%Y= 0.0 e CENTRO%Z= 0.0.
Estruturas definidas desta forma podem ser interessantes quando o programador quer classificar determinados objetos caracterizados por parˆmetros e/ou qualificadores representados por vari´veis de diferentes
a
a
´
tipos. E poss´
ıvel construirem-se estruturas progressivamente mais complicadas definindo-se novos tipos
derivados que englobam aqueles previamente definidos. Por exemplo,
TYPE :: RETA
TYPE (PONTO) :: P1,P2
END TYPE RETA
TYPE (RETA) :: DIAGONAL_PRINCIPAL
!
DIAGONAL_PRINCIPAL%P1%X= 0.0
DIAGONAL_PRINCIPAL%P1%Y= 0.0
DIAGONAL_PRINCIPAL%P1%Z= 0.0
!
DIAGONAL_PRINCIPAL%P2= PONTO(1.0,1.0,1.0)
Aqui foi definido o tipo RETA no espa¸o cartesiano, a qual ´ totalmente caracterizada por dois pontos, P1 e P2,
c
e
os quais, por sua vez s˜o ternas de n´meros do tipo (x, y, z). Definiu-se ent˜o a vari´vel DIAGONAL_PRINCIPAL
a
u
a
a
como sendo do tipo RETA e definiu-se os valores dos dois pontos no espa¸o P1 e P2 que caracterizam a diagonal
c
principal. Note o uso de dois seletores de componente para definir o valor da coordenada x do ponto P1
da DIAGONAL_PRINCIPAL. Note, por outro lado, o uso do construtor de estrutura para definir a posi¸˜o do
ca
ponto P2, como componente da diagonal principal.
O exemplo a seguir, define o tipo ALUNO, caracterizado por NOME, CODIGO de matr´
ıcula, notas parciais
N1, N2 e N3 e m´dia final MF. O programa lˆ as notas e calcula e imprime a m´dia final do aluno.
e
e
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 3. Tipos de Vari´veis
a

25

! Dados a c e r c a de a l u n o s usando t i p o d e r i v a d o .
program a l u n o s
i m p l i c i t none
type : : a l u n o
character ( len= 2 0 ) : : nome
integer : : c o d i g o
r e a l : : n1 , n2 , n3 , mf
end type a l u n o
type ( a l u n o ) : : d i s c e n t e
!
print * , ’Nome : ’
read ’ ( a ) ’ , d i s c e n t e%nome
print * , ’ c o d i g o : ’
read * , d i s c e n t e%c o d i g o
print * , ’ Notas : N1 , N2 , N3 : ’
read * , d i s c e n t e%n1 , d i s c e n t e%n2 , d i s c e n t e%n3
d i s c e n t e%mf= ( d i s c e n t e%n1 + d i s c e n t e%n2 + d i s c e n t e%n3 ) / 3 . 0
print * , ’ ’
print *,’−−−−−−−−−−−> ’ , d i s c e n t e%nome , ’ ( ’ , d i s c e n t e%c o d i g o , ’ ) <−−−−−−−−−−−’
print * , ’
Media f i n a l : ’ , d i s c e n t e%mf
end program a l u n o s
Em Fortran 95, tornou-se poss´
ıvel inicializar os valores dos componentes dos tipos derivados. O valor
deve ser especificado quando o componente ´ declarado como parte da defini¸˜o do tipo. Se o componente
e
ca
n˜o for um ponteiro, a inicializa¸˜o ´ feita de forma usual, com um sinal de igual seguido da express˜o de
a
ca e
a
inicializa¸˜o. Se o componente for um ponteiro, a unica inicializa¸˜o admitida ´ o s´
ca
´
ca
e
ımbolo de atribui¸˜o de
ca
um ponteiro (=>), seguida pela fun¸˜o intr´
ca
ınseca NULL() (se¸˜o 7.16). Em ambos os casos os caracteres ::
ca
s˜o exigidos.
a
Uma inicializa¸˜o n˜o deve necessariamente se aplicar a todos os componentes de um tipo derivado. Um
ca a
exemplo v´lido seria:
a
TYPE :: ENTRY
REAL
:: VALOR= 2.0
INTEGER
INDEX
TYPE(ENTRY), POINTER :: NEXT => NULL()
END TYPE ENTRY
Dada uma declara¸˜o de matriz tal como
ca
TYPE(ENTRY), DIMENSION(100) :: MATRIZ
os sub-objetos tais como MATRIZ(3)%VALOR ter˜o automaticamente o valor 2.0 e a seguinte opera¸˜o, que
a
ca
usa uma fun¸˜o intr´
ca
ınseca ASSOCIATED(MATRIX(3)%NEXT) vai retornar o valor .FALSE. (ver se¸˜o 7.3).
ca
Se as declara¸˜es de tipos derivados estiverem aninhadas, as inicializa¸˜es associadas a componentes s˜o
co
co
a
reconhecidas em todos os n´
ıveis. Assim,
TYPE :: NODO
INTEGER
CONTA
TYPE(ENTRY) ELEMENTO
END TYPE NODO
TYPE(NODO) N
ocasiona que o componente N%ELEMENTO%VALOR ter´ automaticamente o valor 2.0.
a
Os componentes do tipo derivado continuam podendo ser inicializados em declara¸˜es de vari´veis do
co
a
tipo, tais como
TYPE(ENTRY), DIMENSION(100) :: MATRIZ= ENTRY(HUGE(0.0), HUGE(0), NULL())
em cuja situa¸˜o a inicializa¸˜o inicial ´ ignorada.
ca
ca
e

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
26

Autor: Rudi Gaelzer – IFM/UFPel

3.8. Tipos derivados

Impresso: 12 de abril de 2010
Cap´
ıtulo 4

Express˜es e Atribui¸˜es Escalares
o
co
Em uma express˜o, o programa descreve as opera¸˜es que devem ser executadas pelo computador. O
a
co
resultado desta express˜o pode ent˜o ser atribu´ a uma vari´vel. H´ diferentes conjuntos de regras para
a
a
ıdo
a
a
express˜es e atribui¸˜es, dependendo se as vari´veis em quest˜o s˜o num´ricas, l´gicas, caracteres ou de tipo
o
co
a
a a
e
o
derivado; e tamb´m se as express˜es s˜o escalares ou matriciais.
e
o
a
Cada um dos conjunto de regras para express˜es escalares ser´ agora discutido.
o
a

4.1

Regras b´sicas
a

Uma express˜o em Fortran 90/95 ´ formada de operandos e operadores, combinados de tal forma que
a
e
estes seguem as regras de sintaxe. Os operandos podem ser constantes, vari´veis ou fun¸˜es e uma express˜o,
a
co
a
por si mesma, tamb´m pode ser usada como operando.
e
Uma express˜o simples envolvendo um operador unit´rio ou mon´dico tem a seguinte forma:
a
a
a
operador operando
um exemplo sendo
-Y
J´ uma express˜o simples envolvendo um operador bin´rio (ou di´dico) tem a forma:
a
a
a
a
operando operador operando
um exemplo sendo
X + Y
Uma express˜o mais complicada seria
a
operando operador operando operador operando
onde operandos consecutivos s˜o separados por um unico operador. Cada operando deve ter valor definido e
a
´
o resultados da express˜o deve ser matematicamente definido; por exemplo, divis˜o por zero n˜o ´ permitido.
a
a
a e
A sintaxe do Fortran estabelece que as partes de express˜es sem parˆnteses sejam desenvolvidas da
o
e
esquerda para a direita para operadores de igual precedˆncia, com a exce¸˜o do operador “**” (ver se¸˜o
e
ca
ca
4.2). Caso seja necess´rio desenvolver parte de uma express˜o, ou sub-express˜o, antes de outra, parˆnteses
a
a
a
e
podem ser usados para indicar qual sub-express˜o deve ser desenvolvida primeiramente. Na express˜o
a
a
operando operador (operando operador operando)
a sub-express˜o entre parˆnteses ser´ desenvolvida primeiro e o resultado usado como um operando para o
a
e
a
primeiro operador, quando ent˜o a express˜o completa ser´ desenvolvida usando a norma padr˜o, ou seja,
a
a
a
a
da esquerda para a direita.
Se uma express˜o ou sub-express˜o n˜o ´ contida entre parˆnteses, ´ permitido ao processador desenvolver
a
a a e
e
e
uma express˜o equivalente, a qual ´ uma express˜o que resultar´ no mesmo valor, exceto por erros de
a
e
a
a
arredondamento num´rico. As duas opera¸˜es a seguir s˜o, em princ´
e
co
a
ıpio, equivalentes:
27
28

4.2. Express˜es num´ricas escalares
o
e
A/B/C ou A/(B*C)

Poss´
ıveis diferen¸as nos resultados das opera¸˜es acima consistem em diferentes erros de arredondamento
c
co
e/ou tempo de processamento, caso o processador consiga multiplicar mais rapidamente que dividir.
Se dois operadores seguem-se imediatamente, como em
operando operador operador operando
a unica interpreta¸˜o poss´ ´ que o segundo operador ´ mon´dico. Portanto, a sintaxe pro´ que um
´
ca
ıvel e
e
a
ıbe
operador bin´rio siga outro operador, somente um operador unit´rio.
a
a

4.2

Express˜es num´ricas escalares
o
e

Uma express˜o num´rica ´ aquela cujos operandos s˜o um dos trˆs tipos num´ricos: inteiro, real e
a
e
e
a
e
e
complexo. A tabela 4.1 apresenta os operadores, em ordem de precedˆncia, e o seu respectivo significado.
e
Estes operadores s˜o conhecidos como operadores num´ricos intr´
a
e
ınsecos.
Na tabela 4.1, as linhas horizontais confinam os operadores de igual precedˆncia e a ordem de precedˆncia
e
e
´ dada de cima para baixo. O operador de potencia¸˜o “**” ´ o de maior precedˆncia; os operadores de
e
ca
e
e
multiplica¸˜o “*” e divis˜o “/” tˆm a mesma precedˆncia entre si e possuem precedˆncia sobre os operadores
ca
a
e
e
e
de adi¸˜o “+” e subtra¸˜o “-”, os quais tˆm a mesma precedˆncia entre si.
ca
ca
e
e
Na ausˆncia de parˆnteses, ou dentro destes, no caso de sub-express˜es, a opera¸˜o com a maior precee
e
o
ca
dˆncia ´ o c´lculo das fun¸˜es, seguidos das exponencia¸˜es que ser˜o realizadas antes de multiplica¸˜es ou
e
e
a
co
co
a
co
divis˜es e estas, por sua vez, antes de adi¸˜es ou subtra¸˜es.
o
co
co
Uma express˜o num´rica especifica uma computa¸˜o usando constantes, vari´veis ou fun¸˜es, seguindo
a
e
ca
a
co
o seguinte conjunto de regras:
ˆ Os operadores de subtra¸˜o “-” e de adi¸˜o “+” podem ser usados como operadores unit´rios, como em
ca
ca
a
-VELOCIDADE
ˆ Uma vez que n˜o ´ permitido na nota¸˜o matem´tica ordin´ria, uma subtra¸˜o ou adi¸˜o unit´ria
a e
ca
a
a
ca
ca
a
n˜o pode seguir imediatamente ap´s outro operador. Quando isto ´ necess´rio, deve-se fazer uso de
a
o
e
a
parˆnteses. Por exemplo, as opera¸˜es matem´ticas a seguir:
e
co
a
x−y deve ser digitada: X**(-Y);
x(−y) deve ser digitada : X*(-Y).
Como j´ foi mencionado na se¸˜o 4.1, um operador bin´rio tamb´m n˜o pode seguir outro operador.
a
ca
a
e
a
ˆ Os parˆnteses devem indicar os agrupamentos, como se escreve em uma express˜o matem´tica. Os
e
a
a
parˆnteses indicam que as opera¸˜es dentro deles devem ser executadas prioritariamente:
e
co
3
(a + b) (x + y)2 + w2 deve ser digitada: (A+B)*((X+Y)**2 + W**2)**3 ou (A+B)*(((X+Y)**2 +
W**2)**3)
ˆ Os parˆnteses n˜o podem ser usados para indicar multiplica¸˜o, sendo sempre necess´rio o uso do
e
a
ca
a
operador “*”. Qualquer express˜o pode ser envolvida por parˆnteses exteriores, que n˜o a afetam:
a
e
a
X + Y ´ equivalente a ((X) + Y) ou equivalente a ((X + Y))
e
Contudo, o n´mero de parˆnteses ` esquerda deve sempre ser igual ao n´mero de parˆnteses ` direita.
u
e
a
u
e
a
ˆ Nenhum operador pode ser deixado impl´
ıcito:
5*T ou T*5: correto
5T, 5(T) ou T5: incorreto.
ˆ De acordo com a tabela 4.1, a qual fornece o ordenamento dos operadores, a opera¸˜o matem´tica
ca
a
2x2 + y pode ser expressa de, no m´
ınimo, duas maneiras equivalentes:
2*X**2 + Y ou 2*(X**2) + Y ou ainda (2*(x**2)) + Y.

Tabela 4.1: Operadores num´ricos escalares
e

Operador
**
*
/
+
Autor: Rudi Gaelzer – IFM/UFPel

Opera¸˜o
ca
Potencia¸˜o
ca
Multiplica¸˜o
ca
Divis˜o
a
Adi¸˜o
ca
Subtra¸˜o
ca
Impresso: 12 de abril de 2010
Cap´
ıtulo 4. Express˜es e Atribui¸˜es Escalares
o
co
Tabela 4.2: Tipos de resultados de A .op.

Tipo de A

Tipo de B

I
I
I
R
R
R
C
C
C

I
R
C
I
R
C
I
R
C

Tipo de A

Tipo de B

I
I
I
R
R
R
C
C
C

I
R
C
I
R
C
I
R
C

Valor de A
usado na .op.
A
REAL(A,KIND(B))
CMPLX(A,0,KIND(B))
A
A
CMPLX(A,0,KIND(B)
A
A
A

29

B, onde .op. ´ +, -, * ou /.
e

Valor de B
usado na .op.
B
B
B
REAL(B,KIND(A)
B
B
CMPLX(B,0,KIND(A)
CMPLX(B,0,KIND(A)
B

Tipo de
resultado
I
R
C
R
R
C
C
C
C

Tabela 4.3: Tipos de resultados de A**B.

Valor de A
usado na .op.
A
REAL(A,KIND(B))
CMPLX(A,0,KIND(B))
A
A
CMPLX(A,0,KIND(B)
A
A
A

Valor de B
usado na .op.
B
B
B
B
B
B
B
CMPLX(B,0,KIND(A)
B

Tipo de
resultado
I
R
C
R
R
C
C
C
C

ˆ A exce¸˜o ` regra esquerda-para-direita para operadores de igual precedˆncia ocorre para a potencia¸˜o
ca a
e
ca
“**”. A express˜o
a
A**B**C
´ v´lida e ´ desenvolvida da direita para a esquerda como
e a
e
A**(B**C).
ˆ Para dados inteiros, o resultado de qualquer divis˜o ser´ truncado para zero, isto ´, para o valor inteiro
a
a
e
cuja magnitude ´ igual ou logo inferior ` magnitude do valor exato. Assim, o resultado de:
e
a
6/3 ´ 2
e
8/3 ´ 2
e
-8/3 ´ -2.
e
Este fato deve sempre ser levado em conta quando divis˜es de inteiros est˜o sendo realizadas. Por isto,
o
a
o valor de 2**3 ´ 8, enquanto que o valor de 2**(-3) ´ 0.
e
e
ˆ A regra padr˜o do Fortran 90 tamb´m permite que uma express˜o num´rica contenha operandos
a
e
a
e
num´ricos de diferentes tipos ou esp´cies. Esta ´ uma express˜o de modo misto. Exceto quando
e
e
e
a
elevando um valor real ou complexo a uma potˆncia inteira, o objeto do tipo mais fraco (ou mais
e
simples) de vari´vel dos dois tipos envolvidos em uma express˜o ser´ convertido, ou coagido, para o
a
a
a
tipo mais forte. O resultado ser´ tamb´m do tipo mais forte. Por exemplo, se A ´ real e I ´ inteiro, a
a
e
e
e
express˜o A*I tem, inicialmente, I sendo convertido a real, antes que a multiplica¸˜o seja efetuada e o
a
ca
resultado da mesma ´ do tipo real. As tabelas 4.2 e 4.3 ilustram os resultados de diferentes opera¸˜es
e
co
num´ricas escalares.
e
ˆ Com rela¸˜o ` ultima opera¸˜o mencionada na tabela 4.3, no case de um valor complexo ser eleca a ´
ca
vado a uma potˆncia tamb´m complexa, o resultado corresponder´ ao valor principal, isto ´, ab =
e
e
a
e
exp(b(log |a| + i arg a)), com −π < arg a < π.

4.3

Atribui¸oes num´ricas escalares
c˜
e

A forma geral de uma atribui¸˜o num´rica escalar ´
ca
e
e
<nome vari´vel> = <express~o>
a
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
30

4.4. Operadores relacionais

onde <nome vari´vel> ´ o nome de uma vari´vel num´rica escalar e <express~o> ´ uma express˜o num´rica.
a
e
a
e
a e
a
e
Se <express~o> n˜o ´ do mesmo tipo ou esp´cie da <vari´vel>, a primeira ser´ convertida ao tipo e esp´cie
a
a e
e
a
a
e
da ultima antes que a atribui¸˜o seja realizada, de acordo com as regras dadas na tabela 4.4.
´
ca
Deve-se notar que se o tipo da vari´vel for inteiro mas a express˜o n˜o, ent˜o a atribui¸˜o ir´ resultar
a
a a
a
ca
a
em perda de precis˜o, exceto se o resultado for exatamente inteiro. Da mesma forma, atribuindo uma
a
express˜o real a uma vari´vel real de uma esp´cie com precis˜o menor tamb´m causar´ perda de precis˜o.
a
a
e
a
e
a
a
Similarmente, a atribui¸˜o de uma express˜o complexa a uma vari´vel n˜o complexa resultar´, no m´
ca
a
a
a
a
ınimo,
na perda da parte imagin´ria. Por exemplo, os valores de I e A ap´s as atribui¸˜es
a
o
co
I= 7.3
A= (4.01935, 2.12372)

! I do tipo inteiro.
! A do tipo real.

s˜o, respectivamente, 7 e 4.01935.
a

4.4

Operadores relacionais

A tabela 4.5 apresenta os operadores relacionais escalares, utilizados em opera¸˜es que envolvem a
co
compara¸˜o entre duas vari´veis ou express˜es. Na coluna 1 da tabela, ´ apresentado o significado do
ca
a
o
e
operador, na coluna 2 a sua forma escrita com caracteres alfanum´ricos e, na coluna 3, a sua forma escrita
e
com caracteres especiais.
Fortran 77: somente a forma apresentada na coluna 2 ´ v´lida.
e a
Fortran 90/95: qualquer uma das duas formas ´ v´lida; por´m, a forma apresentada na coluna 3 ´ a mais
e a
e
e
moderna e recomend´vel, sendo a outra considerada obsoleta.
a
Se uma ou ambas as express˜es forem complexas, somente os operadores == e /= (ou .EQ. e .NE.) s˜o
o
a
dispon´
ıveis.
O resultado de uma compara¸˜o deste tipo tem como resultado um dos dois valores l´gicos poss´
ca
o
ıveis em
uma ´lgebra booleana: .TRUE. e .FALSE. e este tipo de teste ´ de crucial importˆncia no controle do fluxo
a
e
a
do programa. Exemplos de express˜es relacionais s˜o dados abaixo, sendo I e J do tipo inteiro, A e B do
o
a
tipo real e CHAR1 do tipo caractere padr˜o:
a
I .LT. 0
A < B
A + B > I - J
CHAR1 == ’Z’

!
!
!
!

express~o
a
express~o
a
express~o
a
express~o
a

relacional
relacional
relacional
relacional

inteira
real
de modo misto
de caractere

Os operadores num´ricos tˆm precedˆncia sobre os operadores relacionais. Assim, as express˜es num´ricas,
e
e
e
o
e
caso existam, s˜o desenvolvidas antes da compara¸˜o com os operadores relacionais. No terceiro exemplo
a
ca
acima, como as express˜es envolvem dois tipos distintos, cada express˜o ´ desenvolvida separadamente e
o
a e
ent˜o ambas s˜o convertidas ao tipo e esp´cie da soma dos resultados de cada express˜o, de acordo com a
a
a
e
a
tabela 4.2, antes que a compara¸˜o seja feita. Portanto, no exemplo, o resultado de (I - J) ser´ convertido
ca
a
a real.
Para compara¸˜es de caracteres, as esp´cies devem ser as mesmas e as as letras (ou n´meros ou caracteres
co
e
u
especiais) s˜o comparados da esquerda para a direita at´ que uma diferen¸a seja encontrada ou ambos os
a
e
c
caracteres sejam idˆnticos. Se os comprimentos diferem, a vari´vel mais curta ´ suposta preenchida por
e
a
e
brancos ` direita.
a

4.5

Express˜es e atribui¸oes l´gicas escalares
o
c˜
o

Constantes, vari´veis e fun¸˜es l´gicas podem aparecer como operandos em express˜es l´gicas. Os
a
co
o
o
o
operadores l´gicos, em ordem decrescente de precedˆncia, s˜o:
o
e
a

Tabela 4.4: Convers˜o num´rica para o comando de atribui¸ao <nome vari´vel> = <express~o>.
a
e
c˜
a
a

Tipo de <vari´vel>
a
I
R
C
Autor: Rudi Gaelzer – IFM/UFPel

Valor atribu´
ıdo
INT(<express~o>,KIND(<nome vari´vel>)
a
a
REAL(<express~o, KIND(<nome vari´vel>)
a
a
CMPLX(<express~o>,KIND(<nome vari´vel>)
a
a
Impresso: 12 de abril de 2010
Cap´
ıtulo 4. Express˜es e Atribui¸˜es Escalares
o
co

31

Tabela 4.5: Operadores relacionais em Fortran 90/95

Significado
Maior que
Menor que
Igual a
Maior ou igual
Menor ou igual
Diferente de

Forma obsoleta
.GT.
.LT.
.EQ.
.GE.
.LE.
.NE.

Forma moderna
>
<
==
>=
<=
/=

Operador unit´rio:
a
.NOT. (nega¸˜o l´gica)
ca o
Operadores bin´rios:
a
.AND. (intersec¸˜o l´gica, E l´gico)
ca o
o
.OR. (uni˜o l´gica, OU l´gico)
a o
o
.EQV. (equivalˆncia l´gica)
e
o
.NEQV. (n˜o-equivalˆncia l´gica).
a
e
o
Dada ent˜o uma declara¸˜o de vari´veis l´gicas do tipo
a
ca
a
o
LOGICAL :: I,J,K,L
ent˜o as seguintes express˜es l´gicas s˜o v´lidas:
a
o o
a a
.NOT. J
J .AND. K
I .OR. L .AND. .NOT. J
(.NOT. K .AND. J .NEQV. .NOT. L) .OR. I
Na primeira express˜o o .NOT. ´ usado como operador unit´rio. Na terceira express˜o, as regras de precedˆna
e
a
a
e
cia implicam em que a sub-express˜o L .AND. .NOT. J seja desenvolvida primeiro, e o resultado combinado
a
com I. Na ultima express˜o, as duas sub-express˜es .NOT. K .AND. J e .NOT. L ser˜o desenvolvidas e
´
a
o
a
comparadas para testar n˜o-equivalˆncia; o resultado da compara¸˜o ser´ combinado com I.
a
e
ca
a
O resultado de qualquer express˜o l´gica ´ .TRUE. ou .FALSE., e este valor pode ent˜o ser atribu´ a
a o
e
a
ıdo
uma vari´vel l´gica, tal como no exemplo abaixo:
a
o
FLAG= (.NOT. K .EQV. L) .OR. J
O resultado de uma express˜o l´gica envolvendo duas vari´veis l´gicas A e B, por exemplo, pode ser inferido
a o
a
o
facilmente atrav´s da consulta `s Tabelas-Verdade 4.6 – 4.8.
e
a
Uma vari´vel l´gica pode ter um valor pr´-determinado por uma atribui¸˜o no corpo de comandos do
a
o
e
ca
programa:
FLAG= .TRUE.
ou no corpo de declara¸˜es de vari´veis:
co
a
LOGICAL :: FLAG= .FALSE., BANNER= .TRUE., POLE
Nos exemplos acima, todos os operando e resultados foram do tipo l´gico. Nenhum outro tipo de vari´vel
o
a
pode participar de uma opera¸˜o l´gica intr´
ca o
ınseca, ou atribui¸˜o.
ca
Os resultados de diversas express˜es relacionais podem ser combinados em uma express˜o l´gica, seguida
o
a o
de atribui¸˜o, como no caso:
ca

Tabela 4.6: Tabela-Verdade .NOT.

A
T
F

.NOT. A
F
T

Autor: Rudi Gaelzer – IFM/UFPel

Tabela 4.7: Tabela-Verdade .AND.

A
T
T
F
F

B
T
F
T
F

A .AND. B
T
F
F
F

Tabela 4.8: Tabela-Verdade .OR.

A
T
T
F
F

B
T
F
T
F

A .OR. B
T
T
T
F

Impresso: 12 de abril de 2010
32

4.6. Express˜es e atribui¸˜es de caracteres escalares
o
co
REAL :: A, B, X, Y
LOGICAL :: COND
.
.
.
COND= A > B .OR. X < 0.0 .AND. Y > 1.0

onde os operadores relacionais tˆm precedˆncia sobre os operadores l´gicos. Contudo, o uso mais freq¨ente de
e
e
o
u
express˜es que envolvem operadores num´ricos, relacionais e l´gicos ocorre em testes destinados a determinar
o
e
o
o fluxo do programa, como no caso do comando IF, exemplificado abaixo e que ser´ discutido em mais
a
detalhes no cap´
ıtulo 5:
REAL :: A= 0.0, B= 1.0, X= 2.5, Y= 5.0
.
.
.
IF((A < B) .AND. (X - Y > 0.0))THEN
.
.
.
IF((B**2 < 10.0) .OR. (A > 0.0))THEN
.
.
.
No primeiro teste IF acima, o resultado, levando em conta a hierarquia das precedˆncias nas diferentes
e
opera¸˜es, ´ .FALSE. e os comandos contidos ap´s a cl´usula THEN n˜o ser˜o executados. J´ no segundo
co
e
o
a
a
a
a
exemplo, o resultado ´ .TRUE. e os comandos ap´s o THEN ser˜o executados.
e
o
a

4.6

Express˜es e atribui¸oes de caracteres escalares
o
c˜

O unico operador intr´
´
ınseco para express˜es de caracteres ´ o operador de concatena¸˜o “//”, o qual tem
o
e
ca
o efeito de combinar dois operandos de caracteres em um unico caractere resultante, de extens˜o igual `
´
a
a
soma das extens˜es dos operandos originais. Por exemplo, o resultado da concatena¸˜o das constantes de
o
ca
caractere ’AB’ e ’CD’, escrita como
’AB’//’CD’
´ a constante ’ABCD’.
e
Uma outra opera¸˜o poss´
ca
ıvel com vari´veis de caracteres ´ a extra¸˜o de “peda¸os” (substrings) das
a
e
ca
c
vari´veis, os quais consistem em um determinado grupo de caracteres contidos na vari´vel.
a
a

Substrings de caracteres.
Consideremos a seguinte declara¸˜o da vari´vel de caractere HINO, a qual tem o comprimento igual a 236
ca
a
caracteres e cujo valor ´ atribu´ no momento da declara¸˜o:
e
ıdo
ca
CHARACTER(LEN=236):: HINO = &
’Qual aurora precursora, do farol da divindade,
&Foi o 20 de setembro, o precursor da liberdade.
&Mostremos valor, const^ncia, nesta ´mpia, injusta guerra.
a
ı
&Sirvam nossas fa¸anhas, de modelo ` toda Terra (...)
c
a

&
&
&
’

Pode-se isolar qualquer parte da vari´vel HINO usando-se a nota¸˜o de substring
a
ca
HINO(I:J)
onde I e J s˜o vari´veis inteiras, as quais localizam explicitamente os caracteres de I a J em HINO. Os dois
a
a
pontos “:” s˜o usados para separar os dois ´
a
ındices da substring e s˜o sempre obrigat´rios, mesmo que se
a
o
queira isolar somente um caractere da vari´vel. Alguns exemplos de substrings da vari´vel HINO s˜o:
a
a
a
HINO(6:11)
HINO(60:79)
HINO(140:140)

!Correspondente a ’aurora’
!Correspondente a ’Foi o 20 de setembro’
!Correspondente a ’^’
a

As constantes de caracteres resultantes das substrings podem ser ent˜o atribu´
a
ıdas a outras vari´veis de
a
caracteres. H´ valores padr˜o para os ´
a
a
ındices das substrings. Se o ´
ındice inferior ´ omitido, o valor 1 ´
e
e
assumido; se o valor superior ´ omitido, um valor correspondente ao comprimento da vari´vel ´ assumido.
e
a
e
Assim,
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 4. Express˜es e Atribui¸˜es Escalares
o
co

33

HINO(:50) ´ equivalente a HINO(1:50)
e
HINO(100:) ´ equivalente a HINO(100:236).
e
Pode-se tamb´m fazer concatena¸˜es com substrings:
e
co
HINO(6:11)//HINO(69:79) gera a constante ’aurora de setembro’
TROCADILHO= HINO(153:157)//’s’//HINO(191:199) atribui ` TROCADILHO o valor ’´mpias
a
ı
fa¸anhas’.
c
Se o resultado da express˜o no lado direito for menor que o tamanho da vari´vel, o valor ´ atribu´ `
a
a
e
ıdo a
vari´vel come¸ando-se pela esquerda e o espa¸o restante ´ preenchido por brancos:
a
c
c
e
CHARACTER(LEN= 10) :: PARTE1, PARTE2
PARTE1= HINO(178:183)
! Resulta em PARTE1= ’Sirvam

’

Ao passo que se o resultado da express˜o foi maior que o tamanho da vari´vel, esta ser´ preenchida coma
a
a
pletamente e o restante do valor ser´ truncado:
a
PARTE2= HINO(:22)

! Resulta em PARTE2= ’Qual auror’

Finalmente, ´ poss´ substituir parte de uma vari´vel de caractere usando-se uma substring da mesma em
e
ıvel
a
uma atribui¸ao:
c˜
HINO(50:113)= ’AAAAAAAAAAARRRRRRRRRRRRRGGGGGGGGGGGGGHHHHHHHHHHHH!!!!!$%#$%%&%#%$#’
de tal forma que resulta,
HINO = ’Qual aurora precursora, do farol da divindade, AAAAAAAAAAA&
&RRRRRRRRRRRRRGGGGGGGGGGGGGHHHHHHHHHHHH!!!!!$%#$%%&%#%$#
&
&Mostremos valor, const^ncia, nesta ´mpia, injusta guerra. &
a
ı
&Sirvam nossas fa¸anhas, de modelo ` toda Terra (...)
c
a
’
Os lados esquerdo e direito de uma atribui¸˜o podem ser sobrepor. Neste caso, ser˜o sempre os valores
ca
a
antigos os usados no lado direito da express˜o. Por exemplo,
a
PARTE2(3:5) = PARTE2(1:3)
resulta em PARTE2= ’QuQuaauror’.
Compara¸˜es e uso de operadores relacionais com vari´veis/constantes de caracteres s˜o poss´
co
a
a
ıveis entre
caracteres unicos, inclusive com os operadores > e <. Neste caso, n˜o se trata de testar qual caractere ´ maior
´
a
e
ou menor que outro. Em um sistema computacional, caracteres possuem uma propriedade denominada
seq¨ˆncia de intercala¸ao,1 a qual ordena o armazenamento destes caracteres pelo sistema.
ue
c˜
O Fortran 90/95 determina que a seq¨ˆncia de intercala¸˜o para qualquer arquitetura deve satisfazer as
ue
ca
seguintes condi¸˜es:
co
ˆ A precede (´ menor) que B, que precede C ... precede Y, que precede Z.
e
ˆ 0 precede 1, que precede 2 ... precede 8, que precede 9.
ˆ Espa¸o em branco precede A e Z precede 0; ou branco precede 0 e 9 precede A.
c

Se letras min´sculas s˜o dispon´
u
a
ıveis, ent˜o
a
ˆ a precede b, que precede c, ... precede y, que precede z.
ˆ Espa¸o em branco precede a e z precede 0; ou branco precede 0 e 9 precede a.
c

Assim, n˜o h´ regra que estabele¸a que os n´meros devem preceder ou n˜o as letras, nem tampouco h´
a a
c
u
a
a
regra de precedˆncia para caracteres especiais.
e
De acordo com estas regras, as express˜es relacionais
o
’A’ < ’B’
’0’ < ’1’
1 Collating

sequence.

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
34

4.6. Express˜es e atribui¸˜es de caracteres escalares
o
co
Tabela 4.9: Tabela de c´digos ASCII de 7 bits.
o

Dec
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Hex
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F

Char
NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
TAB
LF
VT
FF
CR
SO
SI
DLE
DC1
DC2
DC3
DC4
NAK
SYN
ETB
CAN
EM
SUB
ESC
FS
GS
RS
US

(null)
(start of heading)
(start of text)
(end of text)
(end of transmission)
(enquiry)
(acknowledge)
(bell)
(backspace)
(horizontal tab)
(line feed, new line)
(vertical tab)
(form feed, new page)
(carriage return)
(shift out)
(shift in)
(data link escape)
(device control 1)
(device control 2)
(device control 3)
(device control 4)
(negative acknowledge)
(synchronous idle)
(end of trans. block)
(cancel)
(end of medium)
(substitute)
(escape)
(file separator)
(group separator)
(record separator)
(unit separator)

Dec
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

Hex
20
21
22
23
24
25
26
27
28
29
2A
2B
2C
2D
2E
2F
30
31
32
33
34
35
36
37
38
39
3A
3B
3C
3D
3E
3F

Char
Space
!
“
#
$
%
&
’
(
)
*
+
,
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?

Dec
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

Hex
40
41
42
43
44
45
46
47
48
49
4A
4B
4C
4D
4E
4F
50
51
52
53
54
55
56
57
58
59
5A
5B
5C
5D
5E
5F

Char
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[

]
ˆ

Dec
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

Hex
60
61
62
63
64
65
66
67
68
69
6A
6B
6C
6D
6E
6F
70
71
72
73
74
75
76
77
78
79
7A
7B
7C
7D
7E
7F

fornecem ambas o resultado T (true).
Fortran 90/95 fornece acesso tamb´m ` seq¨ˆncia de intercala¸˜o original da tabela ASCII2 atrav´s de
e a
ue
ca
e
fun¸˜es intr´
co
ınsecas (se¸˜o 7.6.1). ASCII consiste em uma padroniza¸˜o para um encodeamento de caracteres3
ca
ca
de 7 bits (originalmente), baseado no alfabeto inglˆs. C´digos ASCII representam textos em computadores,
e
o
equipamentos de comunica¸˜o e outros dispositivos eletrˆnicos que trabalham com texto. A tabela 4.9 mosca
o
tra os caracteres ASCII originais, juntamente com os seus identificadores nos sistemas num´ricos decimal,
e
hexadecimal e octal, bem como o c´digo html correspondente. Os primeiros 32 (0 – 31) caracteres mais o
o
caractere 127 s˜o caracteres de controle, destinados ` comunica¸˜o com perif´ricos; estes n˜o geram caraca
a
ca
e
a
teres que podem ser impressos. J´ os caracteres restantes (32 – 126) comp˜e-se de caracteres alfanum´ricos
a
o
e
mais caracteres especiais.

2 American
3 Character

Standard Code for Information Interchange (ASCII).
encoding.

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010

Char
‘
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
˜
DEL
Cap´
ıtulo 5

Comandos e Construtos de Controle
de Fluxo
Nos cap´
ıtulos anteriores foi descrito como comandos de atribui¸˜o devem ser escritos e como estes podem
ca
ser ordenados um ap´s o outro para formar uma seq¨ˆncia de c´digo, a qual ´ executada passo-a-passo. Na
o
ue
o
e
maior parte das computa¸˜es, contudo, esta seq¨ˆncia simples de comandos ´, por si s´, inadequada para a
co
ue
e
o
formula¸˜o do problema. Por exemplo, podemos desejar seguir um de dois poss´
ca
ıveis caminhos em uma se¸˜o
ca
de c´digo, dependendo se um valor calculado ´ positivo ou negativo. Como outro exemplo, podemos querer
o
e
somar 1000 elementos de uma matriz; escrever 1000 adi¸˜es e atribui¸˜es ´ uma tarefa claramente tediosa
co
co e
e n˜o muito eficiente. Ao inv´s, a habilidade de realizar uma itera¸˜o sobre uma unica adi¸˜o ´ necess´ria.
a
e
ca
´
ca e
a
Podemos querer passar o controle de uma parte do programa a outra ou ainda parar completamente o
processamento.
Para estes prop´sitos, recursos s˜o dispon´
o
a
ıveis em Fortran que possibilitam o controle do fluxo l´gico
o
atrav´s dos comandos no programa. Os recursos contidos em Fortran 90 correspondem aos que agora s˜o
e
a
geralmente reconhecidos como os mais apropriados para uma linguagem de programa¸˜o moderna. Sua
ca
forma geral ´ a de um construto de bloco (do inglˆs block construct), o qual ´ um construto (uma constru¸˜o
e
e
e
ca
ou estrutura) que come¸a com uma palavra-chave inicial, pode ter palavras-chave intermedi´rias e que
c
a
termina com uma palavra-chave final que identifica a palavra inicial. Cada seq¨ˆncia de comandos entre as
ue
palavras-chave ´ chamada de um bloco. Um bloco pode ser vazio, embora tais casos sejam raros.
e
Construtos execut´veis podem ser aninhados (em inglˆs, nested ) ou encadeados, isto ´, um bloco pode
a
e
e
conter um outro construto execut´vel. Neste caso, o bloco deve conter o construto interno por inteiro.
a
Execu¸˜o de um bloco sempre inicia com o seu primeiro comando execut´vel.
ca
a
Os primeiros comandos de controle de fluxo a ser mencionados ser˜o aqueles que foram definidos tanto
a
no Fortran 77 quanto no Fortran 90/95, seguidos daqueles que somente existem no Fortran 90/95.

5.1

Comandos obsoletos do Fortran 77

Os comandos descritos nesta se¸˜o fazem parte do padr˜o do Fortran 77 mas que s˜o considerados
ca
a
a
obsoletos no Fortran 90/95. O seu uso em um programa escrito nas ultimas vers˜es da linguagem ´ fortemente
´
o
e
desencorajado e, para alguns compiladores, proibido. A raz˜o para este status de obsoleto ´ porque estes
a
e
comandos facilmente geram dificuldades e d˜o margem a confus˜o durante a leitura do programa. Algumas
a
a
raz˜es para o status de obsoleto para estes comandos s˜o apresentadas abaixo.
o
a

5.1.1

R´tulos (statement labels)
o

Um r´tulo consiste em um n´mero inteiro, de 1 a 99999, inserido entre as colunas 1 e 5 de um programa
o
u
ou sub-programa em Fortran 77 escrito, portanto, no formato fixo. Este r´tulo enfatiza o ponto do c´digo
o
o
onde ele se encontra. H´ trˆs raz˜es para se usar um r´tulo:
a e
o
o
1. O final de um la¸o DO ´ especificado por um r´tulo determinado no in´ do mesmo la¸o.
c
e
o
ıcio
c
2. Todo comando FORMAT deve possuir um r´tulo, pois esta ´ a maneira como os comandos READ e WRITE
o
e
fazem referˆncia ao mesmo.
e
3. Qualquer comando execut´vel pode possuir um r´tulo afixado, de tal forma que o fluxo do c´digo pode
a
o
o
ser transferido ao mesmo. Isto ´ realizado, por exemplo, pelo comando GO TO.
e
35
36

5.1. Comandos obsoletos do Fortran 77

Exemplo:
c (F77) L^ n´meros de um arquivo de entrada at´ que ele termine, ent~o os soma.
e u
e
a
SUMA= 0.0
100
READ(UNIT= IN, FMT= 200, END= 9999) VALOR
200
FORMAT(F20.0)
SOMA= SOMA + VALOR
GO TO 100
9999 CONTINUE
WRITE(UNIT= *, FMT=*)’SOMA dos valores ´:’, SOMA
e
O comando CONTINUE significa, literalmente, “continue”, isto ´, ele apenas instrui o programa a continuar a
e
partir daquele ponto.

5.1.2

Comando GO TO incondicional

O comando GO TO incondicional simplesmente transfere o fluxo do c´digo para um comando rotulado em
o
algum outro ponto do programa. Sua forma geral ´:
e
GO TO <r´tulo>
o
Um exemplo de aplica¸˜o deste comando pode ser visto acima. A unica exce¸˜o para seu uso ´ a proibi¸˜o
ca
´
ca
e
ca
de transferir o fluxo para dentro de um bloco IF ou la¸o DO; entretanto, ´ permitido transferir o fluxo com
c
e
o comando GO TO, ou outro, para fora de um bloco IF ou la¸o DO.
c
O uso do GO TO incondicional torna poss´ escrever-se programas com uma estrutura bastante indisıvel
ciplinada. Tais programas s˜o usualmente dif´
a
ıceis de ser compreendidos e corrigidos. Bons programadores
usam este comando raras vezes ou nunca. Contudo, no Fortran 77 em algumas situa¸˜es n˜o era poss´
co
a
ıvel
evit´-lo, devido a falta de alternativas de estruturas de controle.
a

5.1.3

Comando GO TO computado

O comando GO TO computado ´ uma alternativa para um bloco IF para as situa¸˜es em que um n´mero
e
co
u
grande de op¸˜es devem ser consideradas e elas podem ser selecionadas por uma express˜o de valores inteiros.
co
a
A forma geral do comando ´:
e
GO TO (<r´tulo 1>, <r´tulo 2>, ..., <r´tulo N>)[,] <express~o inteira>
o
o
o
a
A <express~o inteira> ´ desenvolvida; se o seu resultado ´ 1 (um), o controle ´ transferido ao comando
a
e
e
e
afixado ao <r´tulo 1>; se o resultado ´ 2 (dois), o controle ´ transferido ao comando afixado ao <r´tulo
o
e
e
o
2> e assim por diante. Se o resultado da express˜o ´ menor que um ou maior que N (havendo N r´tulos na
a e
o
lista), o comando n˜o tem efeito e o fluxo do programa continua com o pr´ximo comando em seq¨ˆncia. O
a
o
ue
mesmo r´tulo pode estar presente mais de uma vez na lista.
o
O GO TO computado sofre das mesmas desvantagens que o GO TO incondicional, uma vez que se suas
ramifica¸˜es forem usadas sem cuidado, o programa se torna ileg´ de t˜o confuso.
co
ıvel
a

5.1.4

Comando IF aritm´tico
e

A forma geral do comando IF aritm´tico ´:
e
e
IF (<express~o aritm´tica>) <r´tulo 1>,<r´tulo 2>,<r´tulo 3>
a
e
o
o
o
Este comando geralmente fornece uma ramifica¸˜o com trˆs possibilidades, embora dois dos r´tulos possam
ca
e
o
ser iguais, o que o torna uma ramifica¸˜o de duas possibilidades. A <express~o aritm´tica> pode ser
ca
a
e
inteira, real ou real de precis˜o dupla. O controle do fluxo ´ transferido ao comando afixado ao <r´tulo 1>
a
e
o
se o valor for negativo, ao <r´tulo 2> se for zero e ao <r´tulo 3> se for positivo.
o
o

5.1.5

Comandos ASSIGN e GO TO atribu´
ıdo

Estes dois comandos s˜o normalmente usados juntos. O comando ASSIGN atribui o valor de um r´tulo a
a
o
uma vari´vel inteira. Quando isto ´ realizado, a vari´vel n˜o mais possui um valor aritm´tico, mas se torna
a
e
a
a
e
o pr´prio r´tulo. Se o r´tulo ´ afixado a um comando execut´vel, a vari´vel somente pode ser usada em um
o
o
o
e
a
a
comando GO TO atribu´
ıdo; se ´ afixado a um comando FORMAT, a vari´vel somente pode ser usada em um
e
a
comando READ ou WRITE. As formas gerais destes comandos s˜o:
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 5. Comandos e Construtos de Controle de Fluxo

37

ASSIGN <r´tulo> TO <vari´vel inteira>
o
a
GO TO <vari´vel inteira> [,] [(<r´tulo>,<r´tulo>,...,<r´tulo>)]
a
o
o
o
Um GO TO atribu´ pode ser usado para fornecer uma liga¸˜o para e a partir de uma se¸˜o de um programa
ıdo
ca
ca
ou sub-programa, atuando assim como um subrotina interna.

5.1.6

La¸os DO rotulados
c

O comando DO controla um bloco de comandos os quais s˜o executados repetidas vezes, uma vez para
a
cada valor de uma vari´vel denominada vari´vel de controle do la¸o (loop-control variable). O n´mero de
a
a
c
u
itera¸˜es depende dos parˆmetros do comando DO no cabe¸alho do la¸o.
co
a
c
c
A primeira vers˜o de um bloco ou la¸o DO cont´m um r´tulo que indica o ultimo comando do la¸o. A
a
c
e
o
´
c
forma geral do cabe¸alho de um la¸o DO rotulado pode ter uma das duas formas seguintes:
c
c
DO <r´tulo> [,] <vari´vel> = <in´cio>, <limite>, <passo>
o
a
ı
DO <r´tulo> [,] <vari´vel> = <in´cio>, <limite>
o
a
ı
Na segunda forma, o tamanho do passo ´ implicitamente igual a um. O <r´tulo> marca o ultimo comando
e
o
´
do la¸o. Ele deve estar afixado a um comando execut´vel em alguma linha posterior do programa ou subc
a
programa. A regra permite que este comando seja qualquer comando execut´vel, exceto outro comando de
a
controle (como o IF, por exemplo), mas ´ recomend´vel que se use o comando CONTINUE, cuja fun¸˜o foi
e
a
ca
exemplificada na se¸˜o 5.1.1.
ca
A <vari´vel> ´ a vari´vel de controle do la¸o ou ´
a
e
a
c
ındice do la¸o; ela deve ser uma vari´vel escalar (n˜o
c
a
a
um elemento de matriz) e pode ser dos tipos inteiro, real ou dupla precis˜o.
a
Os valores de <in´cio>, <limite> e <passo> podem ser express˜es tamb´m dos tipos inteiro, real ou
ı
o
e
precis˜o dupla. Se o valor do <passo> estiver presente, este n˜o pode ser zero; se for omitido, o seu valor ´
a
a
e
assumido igual a um. O n´mero de itera¸˜es a ser realizadas ´ calculado antes do in´ da primeira itera¸˜o
u
co
e
ıcio
ca
e ´ dado pela f´rmula:
e
o
itera¸~es = MAX(0,INT((limite - in´cio + passo)/passo))
co
ı
onde a fun¸˜o impl´
ca
ıcita INT toma a parte inteira do argumento por truncagem e a fun¸˜o MAX toma o maior
ca
valor dos seus dois argumentos. Nota-se que se o valor de limite ´ menor que in´cio, o n´mero de itera¸˜es
e
ı
u
co
´ zero, exceto no case de passo ser negativo. Um n´mero nulo de itera¸˜es ´ permitido, mas isto significa
e
u
co e
que o conte´do do la¸o n˜o ser´ executado e o controle do fluxo ´ transferido ao primeiro comando ap´s
u
c a
a
e
o
o r´tulo. A vari´vel de controle do la¸o n˜o necessariamente assume o valor limite, especialmente se o
o
a
c a
tamanho do passo for maior que um e/ou do tipo real com valor fracion´rio.
a
Comandos dentro do la¸o podem alterar o valor das express˜es usadas para o in´cio, limite ou passo,
c
o
ı
mas o n´mero de itera¸˜es n˜o ´ alterado, uma vez que este ´ determinado antes do in´
u
co
a e
e
ıcio da primeira
itera¸˜o. A vari´vel de controle do la¸o pode ser usada em express˜es mas um novo valor n˜o pode ser
ca
a
c
o
a
atribu´ a ela dentro do la¸o.
ıdo
c
Dois exemplos de aplica¸˜es de la¸os DO rotulados:
co
c
c Soma dos quadrados dos N primeiros elementos da matriz X.
SOMA= 0.0
DO 15, I= 1,N
SOMA= SOMA + X(I)**2
15
CONTINUE
------------------------------C Inicializa as componentes da matriz FIELD iguais a zero.
c Exemplo de la¸os DO encadeados.
c
REAL FIELD(NX, NY)
DO 50, IY= 1,NY
DO 40, IX= 1,NX
FIELD(IX, IY)= 0.0
40
CONTINUE
50
CONTINUE

5.2

Comando e construto IF

O comando IF fornece um mecanismo para controle de desvio de fluxo, dependendo de uma condi¸˜o.
ca
H´ duas formas: o comando IF e o construto IF, sendo o ultimo uma forma geral do primeiro.
a
´
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
38

5.2. Comando e construto IF

5.2.1

Comando IF

No comando IF, o valor de uma express˜o l´gica escalar ´ testado e um unico comando ´ executado se
a o
e
´
e
e somente se o seu valor for verdadeiro. A forma geral ´:
e
IF (<express~o relacional e/ou l´gica>) <comando execut´vel>
a
o
a
O <comando execut´vel> ´ qualquer, exceto aqueles que marcam o in´
a
e
ıcio ou o final de um bloco, como
por exemplo IF, ELSE IF, ELSE, END IF, outro comando IF ou uma declara¸˜o END. Temos os seguintes
ca
exemplos:
IF (FLAG) GO TO 6
IF(X-Y > 0.0) X= 0.0
IF(COND .OR. P < Q .AND. R <= 1.0) S(I,J)= T(J,I)

5.2.2

Construto IF

Um construto IF permite que a execu¸ao de uma seq¨ˆncia de comandos (ou seja, um bloco) seja
c˜
ue
realizada, dependendo de uma condi¸˜o ou de um outro bloco, dependendo de outra condi¸˜o. H´ trˆs
ca
ca
a e
formas usuais para um construto IF. A forma mais simples tem a seguinte estrutura geral:
[<nome>:] IF (<express~o relacional e/ou l´gica>) THEN
a
o
<bloco>
END IF [<nome>]
onde <bloco> denota uma seq¨ˆncia de linhas de comandos execut´veis. O bloco ´ executado somente se o
ue
a
e
resultado da <express~o relacional e/ou l´gica> for verdadeiro. O construto IF pode ter um <nome>,
a
o
o qual deve ser um nome v´lido em Fortran 90/95. O <nome> ´ opcional, mas se for definido no cabe¸alho
a
e
c
do construto, ele deve ser tamb´m empregado no final, denotado pela declara¸˜o END IF <nome>. Como
e
ca
exemplo, temos:
SWAP: IF (X < Y) THEN
TEMP= X
X= Y
Y= TEMP
END IF SWAP
As trˆs linhas de texto entre “SWAP: IF ...” e “END IF SWAP” ser˜o executadas somente se X < Y. Pode-se
e
a
incluir outro construto IF ou outra estrutura de controle de fluxo no bloco de um construto IF.
A segunda forma usada para o construto IF ´ a seguinte:
e
[<nome>:] IF (<express~o relacional e/ou l´gica>) THEN
a
o
<bloco 1>
ELSE [<nome>]
<bloco 2>
END IF [<nome>]
Na qual o <bloco 1> ´ executado se o resultado da <express~o relacional e/ou l´gica> for verdadeira;
e
a
o
caso contr´rio, o <bloco 2> ser´ executado. Este construto permite que dois conjuntos distintos de instrua
a
¸˜es sejam executados, dependendo de um teste l´gico. Um exemplo de aplica¸˜o desta forma intermedi´ria
co
o
ca
a
seria:
IF (X < Y) THEN
X= -Y
ELSE
Y= -Y
END IF
Neste exemplo, se o resultado de X < Y for verdadeiro, ent˜o X= -Y, sen˜o (ou seja, X >= Y) a a¸˜o ser´ Y=
a
a
ca
a
-Y.
A terceira e final vers˜o usa a instru¸˜o ELSE IF para realizar uma s´rie de testes independentes, cada
a
ca
e
um dos quais possui um bloco de comandos associado. Os testes s˜o realizados um ap´s o outro at´ que um
a
o
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 5. Comandos e Construtos de Controle de Fluxo

39

deles seja satisfeito, em cujo caso o bloco associado ´ executado, enquanto que os outros s˜o solenemente
e
a
ignorados. Ap´s, o controle do fluxo ´ transferido para a instru¸˜o END IF. Caso nenhuma condi¸˜o seja
o
e
ca
ca
satisfeita, nenhum bloco ´ executado, exceto se houver uma instru¸˜o ELSE final, que abarca quaisquer
e
ca
possibilidades n˜o satisfeitas nos testes realizados no construto. A forma geral ´:
a
e
[<nome>:] IF (<express~o relacional e/ou l´gica>) THEN
a
o
<bloco>
[ELSE IF (<express~o relacional e/ou l´gica>) THEN [<nome>]
a
o
<bloco>]
...
[ELSE [<nome>]
<bloco>]
END IF [<nome>]
Pode haver qualquer n´mero (inclusive zero) de instru¸˜es ELSE IF e, no m´ximo, uma instru¸˜o ELSE.
u
co
a
ca
Novamente, o <nome> ´ opcional, mas se for adotado no cabe¸alho do construto, ent˜o deve ser mencionado
e
c
a
em todas as circunstˆncias ilustradas acima. O exemplo a seguir ilustra o encadeamento de construtos
a
IF. Estruturas ainda mais complicadas s˜o poss´
a
ıveis, mas neste caso ´ recomend´vel adotar nomes para os
e
a
construtos, como forma de facilitar a leitura e compreens˜o do programa.
a
IF (I < 0) THEN
IF (J < 0) THEN
X= 0.0
Y= 0.0
ELSE
Z= 0.0
END IF
ELSE IF (K < 0) THEN
Z= 1.0
ELSE
X= 1.0
Y= 1.0
END IF
O programa-exemplo a seguir (programa 5.1) faz uso de construtos IF para implementar o c´lculo do fatorial
a
de um n´mero natural, j´ utilizando o construto DO, abordado na se¸˜o 5.3.
u
a
ca

5.3

Construto DO

Um la¸o DO ´ usado quando for necess´rio calcular uma s´rie de opera¸˜es semelhantes, dependendo ou
c
e
a
e
co
n˜o de algum parˆmetro que ´ atualizado em cada in´ da s´rie. Por exemplo, para somar o valor de um
a
a
e
ıcio
e
polinˆmio de grau N em um dado ponto x:
o
N

P (x) = a0 + a1 x + a2 x2 + · · · + aN xN =

ai xi .
i=0

Outro tipo de opera¸˜es freq¨entemente necess´rias s˜o aquelas que envolvem opera¸˜es matriciais, como o
co
u
a
a
co
produto de matrizes, triangulariza¸˜o, etc. Para este tipo de opera¸˜es repetidas, ´ conveniente usar-se um
ca
co
e
la¸o DO para implement´-las, ao inv´s de escrever o mesmo bloco de opera¸˜es N vezes, como aconteceria
c
a
e
co
se fosse tentado implementar a soma do polinˆmio atrav´s das seguintes express˜es:
o
e
o
REAL
POL=
POL=
POL=
...
POL=

:: POL,A0,A1,A2,...,AN
A0
POL + A1*X
POL + A2*X**2
POL + AN*X**N

Esta forma do la¸o DO n˜o usa r´tulos, como a forma definida na se¸˜o 5.1.6. A forma geral de um construto
c
a
o
ca
DO ´ a seguinte:
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
40

5.3. Construto DO
Programa 5.1: Programa que utiliza os construtos IF e DO.

program i f f a t
! C a l c u l a o f a t o r i a l de um n´ mero n a t u r a l .
u
i m p l i c i t none
integer : : i , f a t , j
!
print * , ”Entre com v a l o r : ”
read * , i
i f ( i < 0 ) then
print * , ”N˜o ´ p o s s´ v e l c a l c u l a r o f a t o r i a l . ”
a e
ı
e l s e i f ( i == 0 ) then
print * , ” f a t ( ” , i , ”)= ” , 1
else
f a t= 1
do j= 1 , i
f a t= f a t * j
end do
print * , ” f a t ( ” , i , ”)= ” , f a t
end i f
end program i f f a t

[<nome>:] DO [<vari´vel> = <express~o 1>, <express~o 2> [, <express~o 3>]]
a
a
a
a
<bloco>
END DO [<nome>]
onde <vari´vel> ´ uma vari´vel inteira e as trˆs express˜es contidas no cabe¸alho do construto devem ser
a
e
a
e
o
c
do mesmo tipo. No cabe¸alho acima, cada uma das express˜es indica:
c
o
<express~o 1>: o valor inicial da <vari´vel>;
a
a
<express~o 2>: o valor m´ximo, ou limite, da <vari´vel> (n˜o necessariamente deve ser o ultimo valor
a
a
a
a
´
assumido pela vari´vel);
a
<express~o 3>: o passo, ou incremento, da vari´vel em cada nova itera¸˜o.
a
a
ca
Este construto tamb´m ´ aceito no Fortran 77, exceto pela possibilidade de se definir um <nome>. Como no
e e
caso de um la¸o DO rotulado, o n´mero de itera¸˜es ´ definido antes de se executar o primeiro comando do
c
u
co e
<bloco> e ´ dado pelo resultado da conta
e
MAX((<express~o 2> - <express~o 1> + <express~o 3>)/<express~o 3>,0).
a
a
a
a
Novamente, se o resultado do primeiro argumento da fun¸˜o MAX acima for negativo, o la¸o n˜o ser´ execa
c a
a
cutado. Isto pode acontecer, por exemplo, se <express~o 2> for menor que <express~o 1> e o passo
a
a
<express~o 3> for positivo. Novamente, se o passo <express~o 3> for omitido, este ser´ igual a 1. O
a
a
a
exemplo abaixo ilustra o uso de express˜es no cabe¸alho do construto:
o
c
DO I= J + 4, M, -K**2
...
END DO
Como se pode ver, o incremento pode ser negativo, o que significa, na pr´tica, que os comandos do bloco
a
somente ser˜o executados se M <= J + 4. O exemplo a seguir ilustra um bloco DO onde a vari´vel I somente
a
a
assume valores ´
ımpares:
DO I= 1, 11, 2
...
END DO
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 5. Comandos e Construtos de Controle de Fluxo

41

Programa 5.2: Exemplo de uso do construto DO.

! M o d i f i c a o p a s s o de um l a ¸ o DO d e n t r o do b l o c o .
c
program mod passo
i m p l i c i t none
integer : : i , j
! Bloco sem m o d i f i c a ¸ ˜ o de p a s s o .
ca
do i= 1 , 10
print * , i
end do
! Bloco com m o d i f i c a ¸ ˜ o do p a s s o .
ca
j= 1
do i= 1 , 1 0 , j
i f ( i > 5 ) j= 3
print * , i , j
end do
end program mod passo

Como no caso do DO rotulado, caso alguma das express˜es envolvam o uso de vari´veis, estas podem ser
o
a
modificadas no bloco do la¸o, inclusive o passo das itera¸˜es. Entretanto, o n´mero de itera¸˜es e o passo
c
co
u
co
a ser realmente tomado n˜o s˜o modificados, uma vez que foram pr´-determinados antes do in´
a a
e
ıcio das
itera¸˜es. O programa abaixo (programa 5.2) exemplifica este fato:
co
Abaixo, temos um outro exemplo que ilustra o funcionamento do la¸o DO:
c
FAT= 1
DO I= 2, N
FAT= FAT*I
END DO
Neste exemplo, o n´mero de itera¸˜es ser´
u
co
a
MAX(N-2+1,0) = MAX(N-1,0).
Caso N < 2, o la¸o n˜o ser´ executado, e o resultado ser´ FAT= 1. Caso N >= 2, o valor inicial da vari´vel
c a
a
a
a
inteira I ´ 2, esta ´ usada para calcular um novo valor para a vari´vel FAT, em seguida a vari´vel I ser´
e
e
a
a
a
incrementada por 1 e o novo valor I= 3 ser´ usado novamente para calcular o novo valor da vari´vel FAT.
a
a
Desta forma, a vari´vel I ser´ incrementada e o bloco executado at´ que I= N + 1, sendo este o ultimo valor
a
a
e
´
de I e o controle ´ transferido para o pr´ximo comando ap´s a declara¸˜o END DO. O exemplo ilustrado
e
o
o
ca
acima retornar´, na vari´vel FAT, o valor do fatorial de N.
a
a
Temos os seguintes casos particulares e instru¸˜es poss´
co
ıveis para um construto DO.

5.3.1

Construto DO ilimitado

Como caso particular de um construto DO, a seguinte instru¸˜o ´ poss´
ca e
ıvel:
[<nome>:] DO
<bloco>
END DO [<nome>]
Neste caso, o conjunto de comandos contidos no <bloco> ser˜o realizados sem limite de n´mero de itera¸˜es,
a
u
co
exceto se algum teste ´ inclu´ dentro do bloco, o que possibilita um desvio de fluxo para a primeira instru¸˜o
e
ıdo
ca
ap´s o END DO. Uma instru¸˜o que realiza este tipo de desvio ´ a instru¸˜o EXIT, descrita a seguir.
o
ca
e
ca

5.3.2

Instru¸˜o EXIT
ca

Esta instru¸˜o permite a sa´
ca
ıda, por exemplo, de um la¸o sem limite, mas o seu uso n˜o est´ restrito a
c
a
a
este caso particular, podendo ser usada em um construto DO geral. A forma geral desta instru¸˜o ´:
ca e
EXIT [<nome>]
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
42

5.4. Construto CASE

onde o <nome> ´ opcional, mas deve ser usado caso ele exista e, neste caso, ele serve para denotar de qual
e
construto a sa´ deve ser feita. Isto ocorre, por exemplo, no caso de construtos encadeados. Execu¸˜o de
ıda
ca
um EXIT transfere controle ao primeiro comando execut´vel ap´s o END DO [<nome>] correspondente.
a
o
Como exemplo, temos:
DO
...
I= I + 1
IF(I == J) EXIT
...
END DO

5.3.3

Instru¸˜o CYCLE
ca

A forma geral desta instru¸˜o ´:
ca e
CYCLE [<nome>]
a qual transfere controle ` declara¸˜o END DO do construto correspondente sem ocorrer a execu¸˜o dos comana
ca
ca
dos posteriores a instru¸˜o. Assim, se outras itera¸˜es devem ser realizadas, estas s˜o feitas, incrementando`
ca
co
a
se o valor de <vari´vel> (caso exista) pelo passo dado pela <express~o 3>. O programa a seguir ilustra
a
a
o uso desta instru¸˜o.
ca
program d o c y c l e
i m p l i c i t none
integer : : i n d e x= 1
do
i n d e x= i n d e x + 1
i f ( i n d e x == 2 0 ) cycle
i f ( i n d e x == 3 0 ) e xi t
print * , ”Valor do ´ n d i c e : ” , i n d e x
ı
end do
end program d o c y c l e

5.4

Construto CASE

Fortran 90/95 fornece uma outra alternativa para selecionar uma de diversas op¸˜es: trata-se do construto
co
CASE. A principal diferen¸a entre este construto e um bloco IF est´ no fato de somente uma express˜o ser
c
a
a
calculada para decidir o fluxo e esta pode ter uma s´rie de resultados pr´-definidos. A forma geral do
e
e
construto CASE ´:
e
[<nome>:] SELECT CASE (<express~o>)
a
[CASE (<seletor>) [<nome>]
<bloco>]
...
[CASE DEFAULT
<bloco>]
END SELECT [<nome>]
A <express~o> deve ser escalar e pode ser dos tipos inteiro, l´gico ou de caractere e o valor especificado
a
o
por cada <seletor> deve ser do mesmo tipo. No caso de vari´veis de caracteres, os comprimentos podem
a
diferir, mas n˜o a esp´cie. Nos casos de vari´veis inteiras ou l´gicas, a esp´cie pode diferir. A forma mais
a
e
a
o
e
simples do <seletor> ´ uma constante entre parˆnteses, como na declara¸˜o
e
e
ca
CASE (1)
Para express˜es inteiras ou de caracteres, um intervalo pode ser especificado separando os limites inferior e
o
superior por dois pontos “: “
CASE (<inf> : <sup>)
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 5. Comandos e Construtos de Controle de Fluxo

43

Um dos limites pode estar ausente, mas n˜o ambos. Caso um deles esteja ausente, significa que o bloco de
a
comandos pertencente a esta declara¸˜o CASE ´ selecionado cada vez que a <express~o> calcula um valor
ca
e
a
que ´ menor ou igual a <sup>, ou maior ou igual a <inf>, respectivamente. Um exemplo ´ mostrado abaixo:
e
e
SELECT CASE
CASE (:-1)
N_SINAL=
CASE (0)
N_SINAL=
CASE (1:)
N_SINAL=
END SELECT

(NUMERO)

! NUMERO ´ do tipo inteiro.
e
! Todos os valores de NUMERO menores que 0.

-1
! Somente NUMERO= 0.
0
! Todos os valores de NUMERO > 0.
1

A forma geral do <seletor> ´ uma lista de valores e de intervalos n˜o sobrepostos, todos do mesmo tipo
e
a
que <express~o>, entre parˆnteses, tal como
a
e
CASE (1, 2, 7, 10:17, 23)
Caso o valor calculado pela <express~o> n˜o pertencer a nenhuma lista dos seletores, nenhum dos blocos ´
a
a
e
executado e o controle do fluxo passa ao primeiro comando ap´s a declara¸˜o END SELECT. J´ a declara¸˜o
o
ca
a
ca
CASE DEFAULT
´ equivalente a uma lista de todos os valores poss´
e
ıveis de <express~o> que n˜o foram inclu´
a
a
ıdos nos outros
seletores do construto. Portanto, somente pode haver um CASE DEFAULT em um dado construto CASE. O
exemplo a seguir ilustra o uso desta declara¸˜o:
ca
SELECT CASE (CH)
! CH ´ do tipo de caractere.
e
CASE (’C’, ’D’, ’R’:)
CH_TYPE= .TRUE.
CASE (’I’:’N’)
INT_TYPE= .TRUE.
CASE DEFAULT
REAL_TYPE= .TRUE.
END SELECT
No exemplo acima, os caracteres ’C’, ’D’, ’R’ e todos os caracteres ap´s o ultimo indicam nomes de
o
´
vari´veis do tipo de caractere. Os caracteres ’I’ e ’N’ indicam vari´veis do tipo inteiro, e todos os outros
a
a
caracteres alfab´ticos indicam vari´veis reais.
e
a
O programa-exemplo abaixo mostra o uso deste construto. Note que os seletores de caso somente testam
o primeiro caractere da vari´vel NOME, embora esta tenha um comprimento igual a 5.
a
program c a s e s t r i n g
i m p l i c i t none
character ( len= 5 ) : : nome
print * , ”Entre com o nome ( 5 c a r a c t e r e s ) : ”
read ”( a5 ) ” , nome
s e l e c t case ( nome )
case ( ”a ” : ”z ”)
! S e l e c i o n a nome que come¸ a com l e t r a s m i n u s c u l a s .
c
´
print * , ”P a l a v r a i n i c i a com L e t r a m i n u s c u l a . ”
´
case ( ”A” : ”Z ”)
! S e l e c i o n a nome que come¸ a com l e t r a s m a i u s c u l a s .
c
´
print * , ”P a l a v r a i n i c i a com l e t r a s m a i u s c u l a . ”
´
case ( ”0 ” : ”9 ”)
! S e l e c i o n a n´ meros .
u
print * , ”P a l a v r a i n i c i a com n´ meros ! ! ! ”
u
case default
! Outros t i p o s de c a r a c t e r e s .
print * , ”P a l a v r a i n i c i a com C a r a c t e r e s e s p e c i a i s ! ! ! ”
end s e l e c t
end program c a s e s t r i n g
J´ o programa abaixo, testa o sinal de n´meros inteiros:
a
u
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
44

5.4. Construto CASE

program t e s t a c a s e
i m p l i c i t none
integer : : a
print * , ”Entre com a ( i n t e i r o ) : ”
read * , a
s e l e c t case ( a )
case (: −1)
print * , ”Menor que z e r o . ”
case ( 0 )
print * , ” I g u a l a z e r o . ”
case ( 1 : )
print * , ”Maior que z e r o . ”
end s e l e c t
end program t e s t a c a s e
O programa abaixo ilustra o uso de alguns dos construtos discutidos neste cap´
ıtulo.
! Imprime uma t a b e l a de c o n v e r s ˜ o das e s c a l a s C e l s i u s e F a h r e n h e i t
a
!
e n t r e l i m i t e s de t e m p e r a t u r a e s p e c i f i c a d o s .
program conv temp
i m p l i c i t none
character ( len= 1 ) : : s c a l e
integer : : low temp , high temp , temp
real : : c e l s i u s , f a r e n h e i t
!
r e a d l o o p : do
! Lˆ e s c a l a e l i m i t e s .
e
print * , ” E s c a l a de t e m p e r a t u r a s (C/F ) : ”
read ”( a ) ” , s c a l e
! Confere v a l i d a d e dos dados .
i f ( s c a l e /= ”C” . and . s c a l e /= ”F”) then
print * , ” E s c a l a n˜ o v ´ l i d a ! ”
a
a
e xi t r e a d l o o p
end i f
print * , ” L i m i t e s ( temp . i n f e r i o r , temp . s u p e r i o r ) : ”
read * , low temp , high temp
!
! La¸ o s o b r e os l i m i t e s de t e m p e r a t u r a .
c
do temp= low temp , high temp
! E s c o l h e f ´ r m u l a de c o n v e r s ˜ o
o
a
s e l e c t case ( s c a l e )
case ( ”C”)
c e l s i u s= temp
f a r e n h e i t= 9 * c e l s i u s / 5 . 0 + 3 2 . 0
case ( ”F”)
f a r e n h e i t= temp
c e l s i u s= 5 * ( f a r e n h e i t − 3 2 ) / 9 . 0
end s e l e c t
! Imprime t a b e l a
print * , c e l s i u s , ”g r a u s C correspondem a ” , f a r e n h e i t , ”g r a u s F . ”
end do
end do r e a d l o o p
!
! Finaliza¸˜o .
ca
print * , ” F i n a l dos dados v ´ l i d o s . ”
a
end program conv temp

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 12 de abril de 2010
Cap´
ıtulo 6

Processamento de Matrizes
A defini¸ao e o processamento de matrizes e vetores sempre foi um recurso presente em todas as linguagens
c˜
de programa¸˜o, inclusive no Fortran 77. Uma novidade importante introduzida no Fortran 90/95 ´ a
ca
e
capacidade estendida de processamento das mesmas. Agora ´ poss´ trabalhar diretamente com a matriz
e
ıvel
completa, ou com se¸˜es da mesma, sem ser necess´rio o uso de la¸os DO. Novas fun¸˜es intr´
co
a
c
co
ınsecas agora
atuam de forma elemental (em todos os elementos) em matrizes e fun¸˜es podem retornar valores na forma
co
de matrizes. Tamb´m est˜o dispon´
e
a
ıveis as possibilidades de matrizes aloc´veis, matrizes de forma assumida
a
e matrizes dinˆmicas.
a
Estes e outros recursos ser˜o abordados neste e nos pr´ximos cap´
a
o
ıtulos.

6.1

Terminologia e especifica¸oes de matrizes
c˜

Uma matriz ou vetor 1 ´ um outro tipo de objeto composto suportado pelo Fortran 77/90/95. Uma
e
matriz consiste de um conjunto retangular de elementos, todos do mesmo tipo e esp´cie do tipo. Uma outra
e
defini¸˜o equivalente seria: uma matriz ´ um grupo de posi¸˜es na mem´ria do computador as quais s˜o
ca
e
co
o
a
acessadas por interm´dio de um unico nome, fazendo-se uso dos subscritos da matriz. Este tipo de objeto
e
´
´ util quando for necess´rio se fazer referˆncia a um n´mero grande, por´m a princ´
e ´
a
e
u
e
ıpio desconhecido, de
vari´veis do tipo intr´
a
ınseco ou outras estruturas, sem que seja necess´rio definir um nome para cada vari´vel.
a
a
O Fortran 77/90/95 permite que uma matriz tenha at´ sete subscritos, cada um relacionado com uma
e
dimens˜o da matriz. As dimens˜es de uma matriz podem ser especificadas usando-se tanto o atributo
a
o
DIMENSION quanto a declara¸˜o DIMENSION.
ca
Os ´
ındices de cada subscrito da matriz s˜o constantes ou vari´veis inteiras e, por conven¸˜o, eles come¸am
a
a
ca
c
em 1, exceto quando um intervalo distinto de valores ´ especificado, atrav´s do fornecimento de um limite
e
e
inferior e um limite superior.
A declara¸˜o de matrizes difere ligeiramente entre o Fortran 77 e o Fortran 90/95.
ca
Fortran 77. Uma matriz pode ser definida tanto na declara¸˜o de tipo intr´
ca
ınseco quanto com o uso da
declara¸˜o DIMENSION:
ca
INTEGER NMAX
INTEGER POINTS(NMAX),MAT_I(50)
REAL R_POINTS(0:50),A
DIMENSION A(NMAX,50)
CHARACTER COLUMN(5)*25, ROW(10)*30
No ultimo exemplo acima, o vetor COLUMN possui 5 componentes, COLUMN(1), COLUMN(2), ..., COLUMN(5),
´
cada um destes sendo uma vari´vel de caractere de comprimento 25. J´ o vetor ROW possui 10 componentes,
a
a
cada um sendo uma vari´vel de caractere de comprimento 30. A matriz real A possui 2 dimens˜es, sendo
a
o
NMAX linhas e 50 colunas. Todas as matrizes neste exemplo tˆm seus ´
e
ındices iniciando em 1, exceto pela
matriz R_POINTS, a qual inicia em 0: R_POINTS(0), R_POINTS(1), ..., R_POINTS(50). Ou seja, este
vetor possui 51 componentes.
1 Nome

usualmente para uma matriz de uma dimens˜o.
a

45
46

6.1. Terminologia e especifica¸˜es de matrizes
co

Fortran 90/95. As formas de declara¸˜es de matrizes em Fortran 77 s˜o aceitas no Fortran 90/95. Por´m,
co
a
e
´ recomend´vel que estas sejam declaradas na forma de atributos de tipos de vari´veis. Por exemplo,
e
a
a
REAL, DIMENSION(50) :: W
REAL, DIMENSION(5:54) :: X
CHARACTER(LEN= 25), DIMENSION(5) :: COLUMN
CHARACTER(LEN= 30), DIMENSION(10) :: ROW
Antes de prosseguir, ser´ introduzida a terminologia usada com rela¸˜o a matrizes.
a
ca
Posto. O posto (rank ) de uma matriz ´ o n´mero de dimens˜es da mesma. Assim, um escalar tem posto
e
u
o
0, um vetor tem posto 1 e uma matriz tem posto maior ou igual a 2.
Extens˜o. A extens˜o (extent) de uma matriz se refere a uma dimens˜o em particular e ´ o n´mero de
a
a
a
e
u
componentes naquela dimens˜o.
a
Forma. A forma (shape) de uma matriz ´ um vetor cujos componentes s˜o a extens˜o de cada dimens˜o
e
a
a
a
da matriz.
Tamanho. O tamanho (size) de um matriz ´ o n´mero total de elementos que comp˜e a mesma. Este
e
u
o
n´mero pode ser zero, em cujo caso esta se denomina matriz nula.
u
Duas matrizes s˜o ditas serem conform´veis se elas tˆm a mesma forma. Todas as matrizes s˜o conform´veis
a
a
e
a
a
com um escalar, uma vez que o escalar ´ expandido em uma matriz com a mesma forma (ver se¸˜o 6.2).
e
ca
Por exemplo, as seguintes matrizes:
REAL, DIMENSION(-3:4,7) :: A
REAL, DIMENSION(8,2:8) :: B
REAL, DIMENSION(8,0:8) :: D
INTEGER :: C
A matriz A possui:
ˆ posto 2;
ˆ extens˜es 8 e 7;
o
ˆ forma (/8,7/), onde os s´
ımbolos “(/” e “/)” s˜o os construtores de matrizes, isto ´, eles definem ou
a
e
inicializam os valores de um vetor ou matriz. Estes construtores de matrizes ser˜o descritos com mais
a
detalhes na se¸˜o 6.6.
ca
ˆ Tamanho 56.

Al´m disso, A ´ conform´vel com B e C, uma vez que a forma de B tamb´m ´ (/8,7/) e C ´ um escalar.
e
e
a
e e
e
Contudo, A n˜o ´ conform´vel com D, uma vez que esta ultima tem forma (/8,9/).
a e
a
´
A forma geral da declara¸˜o de uma ou mais matrizes ´ como se segue:
ca
e
<tipo>[[, DIMENSION(<lista de extens~es>)] [, < outros atributos>] ::]
o

<lista de nomes>

Entretanto, a forma recomend´vel da declara¸˜o ´ a seguinte:
a
ca e
<tipo>, DIMENSION(<lista de extens~es>) [, <outros atributos>] :: <lista de noo
mes>
Onde <tipo> pode ser um tipo intr´
ınseco de vari´vel ou de tipo derivado (desde que a defini¸˜o do tipo
a
ca
derivado esteja acess´
ıvel). A <lista de extens~es> fornece as dimens˜es da matriz atrav´s de:
o
o
e
ˆ constantes inteiras;
ˆ express˜es inteiras usando vari´veis mudas (dummy) ou constantes;
o
a
ˆ somente o caractere “:” para indicar que a matriz ´ aloc´vel ou de forma assumida.
e
a

Os <outros atributos> podem ser quaisquer da seguinte lista:
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

47

PARAMETER
ALLOCATABLE
INTENT(INOUT)
OPTIONAL
SAVE
EXTERNAL
INTRINSIC
PUBLIC
PRIVATE
POINTER
TARGET
Os atributos contidos na lista acima ser˜o abordados ao longo deste e dos pr´ximos cap´
a
o
ıtulos. Os atributos
em vermelho: POINTER e TARGET consistem em recursos avan¸ados do Fortran 90/95 que ser˜o discutidos
c
a
em separado.
Finalmente, segue a <lista de nomes> v´lidos no Fortran, onde os mesmos s˜o atribu´
a
a
ıdos `s matrizes.
a
Os seguintes exemplos mostram a forma da declara¸˜o de diversos tipos diferentes de matrizes, alguns dos
ca
quais s˜o novos no Fortran 90/95 e ser˜o abordados adiante.
a
a
1. Inicializa¸˜o de vetores contendo 3 elementos:
ca
INTEGER :: I
INTEGER, DIMENSION(3) :: IA= (/1,2,3/), IB= (/(I, I=1,3)/)
2. Declara¸˜o da matriz autom´tica LOGB. Aqui, LOGA ´ uma matriz qualquer (“muda” ou “dummy”) e SIZE
ca
a
e
´ uma fun¸˜o intr´
e
ca
ınseca que retorna um escalar inteiro correspondente ao tamanho do seu argumento:
LOGICAL, DIMENSION(SIZE(LOGA)) :: LOGB
3. Declara¸ao das matrizes dinˆmicas, ou aloc´veis, de duas dimens˜es A e B. A forma das matrizes ser´
c˜
a
a
o
a
definida a posteriori por um comando ALLOCATE:
REAL, DIMENSION(:,:), ALLOCATABLE :: A,B
4. Declara¸ao das matrizes de forma assumida de trˆs dimens˜es A e B. A forma das matrizes ser´ assumida
c˜
e
o
a
a partir das informa¸˜es transferidas pela rotina que aciona o sub-programa onde esta declara¸˜o ´
co
ca e
feita.
REAL, DIMENSION(:,:,:) :: A,B
Matrizes de tipos derivados. A capacidade de se misturar matrizes com defini¸˜es de tipos derivados
co
possibilita a constru¸˜o de objetos de complexidade crescente. Alguns exemplos ilustram estas possibilidades.
ca
Um tipo derivado pode conter um ou mais componentes que s˜o matrizes:
a
TYPE :: TRIPLETO
REAL :: U
REAL, DIMENSION(3) :: DU
REAL, DIMENSION(3,3) :: D2U
END TYPE TRIPLETO
TYPE(TRIPLETO) :: T
Este exemplo serve para declarar, em uma unica estrutura, um tipo de vari´vel denominado TRIPLETO, cujos
´
a
componentes correspondem ao valor de uma fun¸˜o de 3 vari´veis, suas 3 derivadas parciais de primeira
ca
a
ordem e suas 9 derivadas parciais de segunda ordem. Se a vari´vel T ´ do tipo TRIPLETO, T%U ´ um escalar
a
e
e
real, mas T%DU e T%D2U s˜o matrizes do tipo real.
a
´
E poss´ agora realizar-se combina¸˜es entre matrizes e o tipo derivado TRIPLETO para se obter objetos
ıvel
co
mais complexos. No exemplo abaixo, declara-se um vetor cujos elementos s˜o TRIPLETOs de diversas fun¸˜es
a
co
distintas:
TYPE(TRIPLETO), DIMENSION(10) :: V
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
48

6.1. Terminologia e especifica¸˜es de matrizes
co

Assim, a referˆncia ao objeto V(2)%U fornece o valor da fun¸˜o correspondente ao segundo elemento do
e
ca
vetor V; j´ a referˆncia V(5)%D2U(1,1) fornece o valor da derivada segunda em rela¸˜o ` primeira vari´vel
a
e
ca a
a
da fun¸˜o correspondente ao elemento 5 do vetor V, e assim por diante.
ca
O primeiro programa a seguir exemplifica um uso simples de matrizes:
! D e c l a r a um v e t o r , d e f i n e v a l o r e s aos e l e m e n t o s do mesmo e imprime
!
e s t e s v a l o r e s na t e l a .
program e x 1 a r r a y
i m p l i c i t none
integer , parameter : : dp= s e l e c t e d r e a l k i n d ( 1 0 , 2 0 0 )
integer : : i
real , dimension ( 1 0 ) : : vr
r e a l ( kind= dp ) , dimension ( 1 0 ) : : vd
!
do i= 1 , 1 0
vr ( i )= s q r t ( r e a l ( i ) )
vd ( i )= s q r t ( r e a l ( i ) )
end do
print * , ”Raiz quadrada dos 10 p r i m e i r o s i n t e i r o s , em p r e c i s a o s i m p l e s : ”
print * , vr
! Imprime t o d o s os componentes do v e t o r .
print * , ” ”
print * , ”Raiz quadrada dos 10 p r i m e i r o s i n t e i r o s , em p r e c i s a o dupla : ”
print * , vd
end program e x 1 a r r a y

O segundo programa-exemplo, a seguir, est´ baseado no programa alunos, descrito na se¸˜o 3.8. Agora,
a
ca
ser´ criado um vetor para armazenar os dados de um n´mero fixo de alunos e os resultados somente ser˜o
a
u
a
impressos ap´s a aquisi¸˜o de todos os dados.
o
ca
! Dados a c e r c a de a l u n o s usando t i p o d e r i v a d o .
program a l u n o s v e t
i m p l i c i t none
integer : : i , n d i s c= 5 ! Mude e s t e v a l o r , c a s o s e j a maior .
type : : a l u n o
character ( len= 2 0 ) : : nome
integer : : c o d i g o
r e a l : : n1 , n2 , n3 , mf
end type a l u n o
type ( a l u n o ) , dimension ( 5 ) : : d i s c
!
do i= 1 , n d i s c
print * , ”Nome : ”
read ”( a ) ” , d i s c ( i )%nome
print * , ” c ´ d i g o : ”
o
read * , d i s c ( i )% c o d i g o
print * , ”Notas : N1 , N2 , N3 : ”
read * , d i s c ( i )%n1 , d i s c ( i )%n2 , d i s c ( i )%n3
d i s c ( i )%mf= ( d i s c ( i )%n1 + d i s c ( i )%n2 + d i s c ( i )%n3 ) / 3 . 0
end do
do i= 1 , n d i s c
print * , ” ”
print * , ”−−−−−−−−−−−> ” , d i s c ( i )%nome , ” ( ” , d i s c ( i )%c o d i g o , ”) <−−−−−−−−−−−”
print * , ”
M´dia f i n a l : ” , d i s c ( i )%mf
e
end do
end program a l u n o s v e t

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

6.2

49

Express˜es e atribui¸oes envolvendo matrizes
o
c˜

Com o Fortran 77 n˜o era poss´ desenvolver express˜es envolvendo o conjunto de todos os elemento de
a
ıvel
o
uma matriz simultaneamente. Ao inv´s disso, cada elemento da matriz deveria ser envolvido na express˜o
e
a
separadamente, em um processo que com frequˆncia demandava o uso de diversos la¸os DO encadeados.
e
c
Quando a opera¸˜o envolvia matrizes grandes, com 100 × 100 elementos ou mais, tais processos podiam ser
ca
extremamente dispendiosos do ponto de vista do tempo necess´rio para a realiza¸˜o de todas as opera¸˜es
a
ca
co
desejadas, pois os elementos da(s) matriz(es) deveriam ser manipulado de forma seq¨encial. Al´m disso,
u
e
o c´digo tornava-se gradualmente mais complexo para ser lido e interpretado, ` medida que o n´mero de
o
a
u
opera¸˜es envolvidas aumentava.
co
Um desenvolvimento novo, introduzido no Fortran 90, ´ a sua habilidade de realizar opera¸˜es envolvendo
e
co
a matriz na sua totalidade, possibilitando o tratamento de uma matriz como um objeto unico, o que, no
´
m´
ınimo, facilita enormemente a constru¸˜o, leitura e interpreta¸˜o do c´digo. Uma outra vantagem, ainda
ca
ca
o
mais importante, resulta deste novo modo de encarar matrizes. Com o desenvolvimento dos processadores
e das arquiteturas de computadores, entraram em linha, recentemente, sistemas compostos por mais de um
processador, os quais fazem uso da id´ia de processamento distribu´ ou, em outras palavras, processamento
e
ıdo
paralelo. As normas definidas pelo comitˆ X3J3 para o padr˜o da linguagem Fortran 90/95 sup˜e que come
a
o
piladores usados em sistemas distribu´
ıdos devem se encarregar de distribuir automaticamente os processos
num´ricos envolvidos nas express˜es com matrizes de forma equilibrada entre os diversos processadores que
e
o
comp˜e a arquitetura. A evidente vantagem nesta estrat´gia consiste no fato de que as mesmas opera¸˜es
o
e
co
num´ricas s˜o realizadas de forma simultˆnea em diversos componentes distintos das matrizes, acelerando
e
a
a
substancialmente a eficiˆncia do processamento. Com a filosofia das opera¸˜es sobre matrizes inteiras, a
e
co
tarefa de implantar a paraleliza¸˜o do c´digo num´rico fica, essencialmente, a cargo do compilador e n˜o
ca
o
e
a
do programador. Uma outra vantagem deste enfoque consiste na manuten¸˜o da portabilidade dos c´digos
ca
o
num´ricos.
e
Para que as opera¸˜es envolvendo matrizes inteiras sejam poss´
co
ıveis, ´ necess´rio que as matrizes consie
a
deradas sejam conform´veis, ou seja, elas devem todas ter a mesma forma. Opera¸˜es entre duas matrizes
a
co
conform´veis s˜o realizadas na maneira elemental (distribuindo as opera¸˜es entre os diversos processadores,
a
a
co
se existirem) e todos os operadores num´ricos definidos para opera¸˜es entre escalares tamb´m s˜o definidos
e
co
e
a
para opera¸oes entre matrizes.
c˜
Por exemplo, sejam A e B duas matrizes 2 × 3:
A=

348
566

521
331

, B=

,

o resultado da adi¸˜o de A por B ´:
ca
e
A+B=

869
897

A*B =

15 8 8
15 18 6

A/B =

3/5 2 8
5/3 2 6

,

o resultado da multiplica¸˜o ´:
ca e

e o resultado da divis˜o ´:
a e
.

Se um dos operandos ´ um escalar, ent˜o este ´ distribu´ em uma matriz conform´vel com o outro
e
a
e
ıdo
a
operando. Assim, o resultado de adicionar 5 a A ´:
e
A+5=

348
566

+

555
555

=

8 9 13
10 11 11

.

Esta distribui¸˜o de um escalar em uma matriz conform´vel ´ util no momento da inicializa¸˜o dos elementos
ca
a e´
ca
de uma matriz.
Da mesma forma como acontece com express˜es e atribui¸˜es escalares, em uma linha de programa¸˜o
o
co
ca
como a seguir,
A= A + B
sendo A e B matrizes, a express˜o do lado direito ´ desenvolvida antes da atribui¸˜o do resultado da expresa
e
ca
s˜o ` matriz A. Este ordenamento ´ importante quando uma matriz aparece em ambos os lados de uma
a a
e
atribui¸˜o, como no caso do exemplo acima.
ca
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
50

6.2. Express˜es e atribui¸˜es envolvendo matrizes
o
co

As vantagens do processamento de matrizes inteiras, presente no Fortran 90/95 mas ausente no Fortran
77, podem ser contempladas atrav´s da compara¸˜o de alguns exemplos de c´digos desenvolvidos em ambas
e
ca
o
as revis˜es da linguagem. Nestes c´digos ser˜o tamb´m apresentadas algumas fun¸˜es intr´
o
o
a
e
co
ınsecas do Fortran
90/95 que operam em matrizes, elemento a elemento. Uma descri¸˜o completa das rotinas intr´
ca
ınsecas ´
e
apresentada no cap´
ıtulo 7.
1. Considere trˆs vetores, A, B e C, todos do mesmo comprimento. Inicialize todos os elementos de A a
e
zero e realize as atribui¸˜es A(I)= A(I)/3.1 + B(I)*SQRT(C(I)) para todos os valores de I
co
Solu¸˜o Fortran 77.
ca
REAL A(20), B(20), C(20)
...

10
...

20

DO 10 I= 1, 20
A(I)= 0.0
CONTINUE
DO 20 I= 1, 20
A(I)= A(I)/3.1 + B(I)*SQRT(C(I))
CONTINUE

Solu¸˜o Fortran 90/95.
ca
REAL, DIMENSION(20) :: A= 0.0, B, C
...
A= A/3.1 + B*SQRT(C)
Note como o c´digo ficou mais reduzido e f´cil de ser lido. Al´m disso, a fun¸˜o intr´
o
a
e
ca
ınseca SQRT opera
sobre cada elemento do vetor C.
2. Considere trˆs matrizes bi-dimensionais com a mesma forma. Multiplique duas matrizes entre si,
e
elemento a elemento, e atribua o resultado a uma terceira matriz.
Solu¸˜o Fortran 77.
ca
REAL A(5,5), B(5,5), C(5,5)
...

10
20

DO 20 I= 1, 5
DO 10 J= 1, 5
C(J,I)= A(J,I) + B(J,I)
CONTINUE
CONTINUE

Solu¸˜o Fortran 90/95.
ca
REAL, DIMENSION(5,5) :: A, B, C
...
C= A + B
3. Considere uma matriz tri-dimensional. Encontre o maior valor menor que 1000 nesta matriz.
Solu¸˜o Fortran 77.
ca
REAL A(5,5,5)
REAL VAL_MAX
...
VAL_MAX=
DO 30 K=
DO 20
DO

10
20
30

0.0
1, 5
J= 1, 5
10 I= 1, 5
IF((A(I,J,K) .GT. VAL_MAX) .AND.
&
(A(I,J,K) .LT. 1000.0))VAL_MAX= A(I,J,K)
CONTINUE
CONTINUE
CONTINUE

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

51

Solu¸˜o Fortran 90/95.
ca
REAL, DIMENSION(5,5,5) :: A
REAL :: VAL_MAX
...
VAL_MAX= MAXVAL(A, MASK=(A<1000.0))
Note que no Fortran 95 conseguiu-se fazer em uma linha o que necessitou de 8 linhas no Fortran 77.
A fun¸˜o intr´
ca
ınseca MAXVAL devolve o valor m´ximo entre os elementos de uma matriz. O argumento
a
opcional MASK=(...) estabelece uma m´scara, isto ´, uma express˜o l´gica envolvendo a(s) matriz(es).
a
e
a o
Em MASK=(A<1000.0), somente aqueles elementos de A que satisfazem a condi¸˜o de ser menores que
ca
1000 s˜o levados em considera¸˜o.
a
ca
4. Encontre o valor m´dio dos elementos maiores que 3000 na matriz A do exemplo anterior.
e
Solu¸˜o Fortran 77.
ca
REAL A(5,5,5)
REAL MEDIA,ACUM
INTEGER CONTA
...
ACUM= 0.0
CONTA= 0
DO 30 K= 1, 5
DO 20 J= 1, 5
DO 10 I= 1, 5
IF(A(I,J,K) .GT. 3000.0)THEN
ACUM= ACUM + A(I,J,K)
CONTA= CONTA + 1
END IF
10
CONTINUE
20
CONTINUE
30
CONTINUE
MEDIA= ACUM/REAL(CONTA)
Solu¸˜o Fortran 90/95.
ca
REAL, DIMENSION(5,5,5) :: A
REAL :: MEDIA
...
MEDIA= SUM(A,MASK=(A>3000.0))/COUNT(MASK=(A>3000.0))
Agora, conseguiu-se realizar em uma linha de c´digo em Fortran 90 o que necessitou de 13 linhas em
o
Fortran 77.
Os ultimos dois exemplos fizeram uso das seguintes fun¸˜es intr´
´
co
ınsecas (ver se¸˜o 7.12):
ca
MAXVAL - retorna o valor m´ximo de uma matriz.
a
SUM - retorna a soma de todos os elementos de uma matriz.
COUNT - retorna o n´mero de elementos da matriz que satisfazem a m´scara.
u
a

6.3

Se¸˜es de matrizes
co

Uma sub-matriz, tamb´m chamada se¸˜o de matriz, pode ser acessada atrav´s da especifica¸˜o de um
e
ca
e
ca
intervalo de valores de subscritos da matriz. Uma se¸˜o de matriz pode ser acessada e operada da mesma
ca
forma que a matriz completa, mas n˜o ´ poss´
a e
ıvel fazer-se referˆncia direta a elementos individuais ou a
e
subse¸˜es da se¸˜o.
co
ca
Se¸˜es de matrizes podem ser extra´
co
ıdas usando-se um dos seguintes artif´
ıcios:
ˆ Um subscrito simples.
ˆ Um tripleto de subscritos.
ˆ Um vetor de subscritos.

Estes recursos ser˜o descritos a seguir.
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
52

6.3. Se¸˜es de matrizes
co

6.3.1

Subscritos simples

Um subscrito simples seleciona um unico elemento da matriz. Considere a seguinte matriz 5 × 5, deno´
minada RA. Ent˜o o elemento X pode ser selecionado atrav´s de RA(2,2):
a
e


00000
0 X 0 0 0


RA =  0 0 0 0 0  =⇒ RA(2, 2) = X.


0 0 0 0 0
00000

6.3.2

Tripleto de subscritos

A forma de um tripleto de subscritos ´ a seguinte, sendo esta forma geral v´lida para todas as dimens˜es
e
a
o
definidas para a matriz:
[<limite inferior>] : [<limite superior>] : [<passo>]
Se um dos limites, inferior ou superior (ou ambos) for omitido, ent˜o o limite ausente ´ assumido como o
a
e
limite inferior ou superior da correspondente dimens˜o da matriz da qual a se¸˜o est´ sendo extra´
a
ca
a
ıda; se o
<passo> for omitido, ent˜o assume-se <passo>=1.
a
Os exemplos a seguir ilustram v´rias se¸˜es de matrizes usando-se tripletos. Os elementos das matrizes
a
co
marcados por X denotam a se¸˜o a ser extra´
ca
ıda. Novamente, no exemplo ser´ utilizada a matriz 5 × 5
a
denominada RA.


00000


0 X 0 0 0


RA =  0 0 0 0 0  =⇒RA(2:2,2:2) = X; Elemento simples, escalar, forma: (/1/).




0 0 0 0 0
00000


00000


0 0 0 0 0


RA =  0 0 X X X  =⇒RA(3,3:5); se¸˜o de linha da matriz, forma: (/3/).
ca




0 0 0 0 0
00000


00X00


0 0 X 0 0


RA =  0 0 X 0 0  =⇒RA(:,3); coluna inteira, forma: (/5/).




0 0 X 0 0
00X00


0XXX0
0 0 0 0 0


RA =  0 X X X 0  =⇒RA(1::2,2:4); se¸˜es de linhas com passo 2, forma: (/3,3/).
co


0 0 0 0 0
0XXX0

6.3.3

Vetores de subscritos

Um vetor de subscritos ´ uma express˜o inteira de posto 1, isto ´, um vetor. Cada elemento desta
e
a
e
express˜o deve ser definido com valores que se encontrem dentro dos limites dos subscritos da matriz-m˜e.
a
a
Os elementos de um vetor de subscritos podem estar em qualquer ordem.
Um exemplo ilustrando o uso de um vetor de subscritos, denominado IV, ´ dado a seguir:
e
REAL, DIMENSION(6) ::
REAL, DIMENSION(3) ::
INTEGER, DIMENSION(3)
RB= RA(IV)
! IV ´ o
e

RA= (/ 1.2, 3.4, 3.0, 11.2, 1.0, 3.7 /)
RB
:: IV= (/ 1, 3, 5 /) ! Express~o inteira de posto 1.
a
vetor de subscritos.

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

53

! Resulta:
!RB= (/ RA(1), RA(3), RA(5) /), ou
!RB= (/ 1.2, 3.0, 1.0 /).
Um vetor de subscritos pode tamb´m estar do lado esquerdo de uma atribui¸˜o:
e
ca
IV= (/ 1, 3, 5 /)
RA(IV)= (/ 1.2, 3.4, 5.6 /) !Atribui¸~es dos elementos 1, 3 e 5 de RA.
co
! Resulta:
! RA(1)= 1.2; RA(3)= 3.4; RA(5)= 5.6
! Os elementos 2, 4 e 6 de RA n~o foram definidos.
a

6.4

Atribui¸oes de matrizes e sub-matrizes
c˜

Tanto matrizes inteiras quanto se¸˜es de matrizes podem ser usadas como operandos (isto ´, podem
co
e
estar tanto no lado esquerdo quanto do lado direito de uma atribui¸˜o) desde que todos os operandos sejam
ca
conform´veis (p´gina 46). Por exemplo,
a
a
REAL, DIMENSION(5,5) :: RA, RB, RC
INTEGER :: ID
...
RA= RB + RC*ID !Forma (/5,5/).
...
RA(3:5,3:4)= RB(1::2,3:5:2) + RC(1:3,1:2)
!Forma (/3,2/):
!RA(3,3)= RB(1,3) + RC(1,1)
!RA(4,3)= RB(3,3) + RC(2,1)
!RA(5,3)= RB(5,3) + RC(3,1)
!RA(3,4)= RB(1,5) + RC(1,2)
!etc.
...
RA(:,1)= RB(:,1) + RB(:,2) + RC(:3)
!Forma (/5/).
Um outro exemplo, acompanhado de figura, torna a opera¸˜o com sub-matrizes conform´veis mais clara.
ca
a
REAL, DIMENSION(10,20) :: A,B
REAL, DIMENSION(8,6) :: C
...
C= A(2:9,5:10) + B(1:8,15:20) !Forma (/8,6/).
...
A figura 6.1 ilustra como as duas sub-matrizes s˜o conform´veis neste caso e o resultado da soma das duas
a
a
se¸˜es ser´ atribu´ ` matriz C, a qual possui a mesma forma.
co
a
ıdo a
O programa-exemplo 6.1 mostra algumas opera¸˜es e atribui¸˜es b´sicas de matrizes:
co
co
a

6.5

Matrizes de tamanho zero

Matrizes de tamanho zero, ou matrizes nulas tamb´m s˜o permitidas em Fortran 90/95. A no¸˜o de
e
a
ca
uma matriz nula ´ util quando se quer contar com a possibilidade de existˆncia de uma matriz sem nenhum
e´
e
elemento, o que pode simplificar a programa¸˜o do c´digo em certas situa¸˜es. Uma matriz ´ nula quando
ca
o
co
e
o limite inferior de uma ou mais de suas dimens˜es ´ maior que o limite superior.
o e
Por exemplo, o c´digo abaixo resolve um sistema linear de equa¸˜es que j´ est˜o na forma triangular:
o
co
a
a
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)
END DO
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
54

6.5. Matrizes de tamanho zero
A(1,20)

A(1,1)
A(2,5)

A(2,10)

A(9,5)

A(9,10)

Resultado

A(10,1)

A(20,20)
+

B(1,1)

B(1,15)

=

8x6

B(1,20)

B(8,15)

B(10,1)

B(20,20)

Figura 6.1: A soma de duas se¸oes de matrizes conform´veis.
c˜
a

Quando I assume o valor N, as sub-matrizes B(N+1:N) e A(N+1:N,N) se tornam nulas. Se esta possibilidade
n˜o existisse, seria necess´ria a inclus˜o de linhas adicionais de programa¸˜o.
a
a
a
ca
As matrizes nulas seguem as mesmas regras de opera¸˜o e atribui¸˜o que as matrizes usuais, por´m elas
ca
ca
e
ainda devem ser conform´veis com as matrizes restantes. Por exemplo, duas matrizes nulas podem ter o
a
mesmo posto mas formas distintas; as formas podem ser (/2,0/) e (/0,2/). Neste caso, estas matrizes n˜o
a
s˜o conform´veis. Contudo, uma matriz ´ sempre conform´vel com um escalar, assim a atribui¸˜o
a
a
e
a
ca

Programa 6.1: Express˜es e atribui¸oes envolvendo matrizes.
o
c˜

program t e s t a a t r m a t r
i m p l i c i t none
real , dimension ( 3 , 3 ) : : a
real , dimension ( 2 , 2 ) : : b
integer : : i , j
!
do i= 1 , 3
do j= 1 , 3
a ( i , j )= s i n ( r e a l ( i ) ) + c o s ( r e a l ( j ) )
end do
end do
b= a ( 1 : 2 , 1 : 3 : 2 )
print * , ”Matriz A: ”
print ” ( 3 ( f 1 2 . 5 ) ) ” , ( ( a ( i , j ) , j= 1 , 3 ) , i= 1 , 3 )
Print * , ”Matriz B : ”
print ” ( 2 ( f 1 2 . 5 ) ) ” , ( ( b ( i , j ) , j= 1 , 2 ) , i= 1 , 2 )
end program t e s t a a t r m a t r

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

55

<matriz nula>= <escalar>
´ sempre v´lida.
e
a

6.6

Construtores de matrizes

Um construtor de matrizes cria um vetor (matriz de posto 1) contendo valores constantes. Estes construtores servem, por exemplo, para inicializar os elementos de um vetor, como foi exemplificado na p´gina
a
47. Outro exemplo de uso dos construtores de matrizes est´ na defini¸˜o de um vetor de subscritos, como
a
ca
foi abordado na se¸˜o 6.3.3.
ca
A forma geral de um construtor de matrizes ´ a seguinte:
e
(/ <lista de valores do construtor> /)
onde <lista de valores do construtor> pode ser tanto uma lista de constantes, como no exemplo
IV= (/ 1, 3, 5 /)
como pode ser um conjunto de express˜es num´ricas:
o
e
A= (/ I+J, 2*I, 2*J, I**2, J**2, SIN(REAL(I)), COS(REAL(J)) /)
ou ainda um comando DO impl´
ıcito no construtor, cuja forma geral ´ a seguinte:
e
(<lista de valores do construtor>, <vari´vel>= <exp1>, <exp2>, [<exp3>])
a
onde <vari´vel> ´ uma vari´vel escalar inteira e <exp1>, <exp2> e <exp3> s˜o express˜es escalares inteiras.
a
e
a
a
o
A interpreta¸˜o dada a este DO impl´
ca
ıcito ´ que a <lista de valores dos construtor> ´ escrita um n´mero
e
e
u
de vezes igual a
MAX((<exp2> - <exp1> + <exp3>)/<exp3>, 0)
sendo a <vari´vel> substitu´ por <exp1>, <exp1> + <exp3>, ..., <exp2>, como acontece no construto DO
a
ıda
(se¸˜o 5.3). Tamb´m ´ poss´ encadear-se DO’s impl´
ca
e e
ıvel
ıcitos. A seguir, alguns exemplos s˜o apresentados:
a
(/ (i, i= 1,6) /) ! Resulta: (/ 1, 2, 3, 4, 5, 6 /)

(/ 7, (i, i= 1,4), 9 /) ! Resulta: (/ 7, 1, 2, 3, 4, 9 /)

(/ (1.0/REAL(I), I= 1,6) /)
! Resulta: (/ 1.0/1.0, 1.0/2.0, 1.0/3.0, 1.0/4.0, 1.0/5.0, 1.0/6.0 /)

! DO’s impl´citos encadeados:
ı
(/ ((I, I= 1,3), J= 1,3) /)
! Resulta: (/ 1, 2, 3, 1, 2, 3, 1, 2, 3 /)

(/ ((I+J, I= 1,3), J= 1,2) /)
! = (/ ((1+J, 2+J, 3+J), J= 1,2) /)
! Resulta: (/ 2, 3, 4, 3, 4, 5 /)
Um construtor de matrizes pode tamb´m ser criado usando-se tripletos de subscritos:
e
(/ A(I,2:4), A(1:5:2,I+3) /)
! Resulta: (/ A(I,2), A(I,3), A(I,4), A(1,I+3), A(3,I+3), A(5,I+3) /)
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
56

6.6. Construtores de matrizes

B(1,1)

B(1,1)

B(1,3)

B(1,4)

B(2,1)

B(2,2)

B(2,3)

B(2,4)

B(3,1)

B(3,2)

B(3,3)

B(3,4)

B(4,1)

B(4,2)

B(4,3)

B(4,4)

B(5,1)

B(5,2)

B(5,3)

B(5,4)

Figura 6.2: O ordenamento dos elementos da matriz B(5,4).

6.6.1

A fun¸˜o intr´
ca
ınseca RESHAPE.

Uma matriz de posto maior que um pode ser constru´ a partir de um construtor de matrizes atrav´s
ıda
e
do uso da fun¸˜o intr´
ca
ınseca RESHAPE. Por exemplo,
RESHAPE( SOURCE= (/ 1, 2, 3, 4, 5, 6 /), SHAPE= (/ 2, 3 /) )
gera a matriz de posto 2:
135
246
a qual ´ uma matriz de forma (/ 2, 3 /), isto ´, 2 linhas e 3 colunas. Um outro exemplo seria:
e
e
REAL, DIMENSION(3,2) :: RA
RA= RESHAPE( SOURCE= (/ ((I+J, I= 1,3), J= 1,2) /), SHAPE= (/ 3,2 /) )
de onde resulta




23
RA =  3 4 
45

Usando a fun¸˜o RESHAPE, o programa-exemplo da p´gina 53 apresenta uma forma mais concisa:
ca
a
program t e s t a a t r m a t r
i m p l i c i t none
real , dimension ( 3 , 3 ) : : a
real , dimension ( 2 , 2 ) : : b
integer : : i , j
!
a= r e s h a p e ( s o u r c e= ( / ( ( s i n ( r e a l ( i ))+ c o s ( r e a l ( j ) ) , i= 1 , 3 ) , j= 1 , 3 ) / ) , &
shape= ( / 3 , 3 / ) )
b= a ( 1 : 2 , 1 : 3 : 2 )
print * , ”Matriz A: ”
print ” ( 3 ( f 1 2 . 5 ) ) ” , ( ( a ( i , j ) , j= 1 , 3 ) , i= 1 , 3 )
Print * , ”Matriz B : ”
print ” ( 2 ( f 1 2 . 5 ) ) ” , ( ( b ( i , j ) , j= 1 , 2 ) , i= 1 , 2 )
end program t e s t a a t r m a t r

6.6.2

A ordem dos elementos de matrizes

A maneira como a fun¸˜o RESHAPE organizou os elementos das matrizes na se¸˜o 6.6.1 seguiu a denoca
ca
minada ordem dos elementos de matriz, a qual ´ a maneira como a maioria dos compiladores de Fortran
e
armazena os elementos de matrizes em espa¸os cont´
c
ıguos de mem´ria. Este ordenamento ´ obtido variandoo
e
se inicialmente o ´
ındice da primeira dimens˜o da matriz, depois variando-se o ´
a
ındice da segunda dimens˜o e
a
assim por diante. Em uma matriz com 2 dimens˜es isto ´ obtido variando-se inicialmente as linhas e depois
o
e
as colunas. A figura 6.2 ilustra este procedimento com a matriz B(5,4).
Em uma matriz com mais de 2 dimens˜es, o ordenamento ´ realizado da mesma maneira. Assim, dada
o
e
a matriz
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

57

REAL, DIMENSION(-10:5, -20:1, 0:1, -1:0, 2, 2, 2) :: G
o ordenamento segue a ordem:
G(-10,-20,0,-1,1,1,1)

→ G(-9,-20,0,-1,1,1,1)

→ G(-8,-20,0,-1,1,1,1)

→...→ G(5,-20,0,-1,1,1,1)

→

G(-10,-19,0,-1,1,1,1)

→ G(-9,-19,0,-1,1,1,1)

→ G(-8,-19,0,-1,1,1,1)

→...→ G(5,-19,0,-1,1,1,1)

→

G(-10,-18,0,-1,1,1,1)

→

→ G(-8,-15,0,-1,1,1,1)

→...→ G(5,1,1,0,2,2,1)

→

G(-10,1,1,0,2,2,2)

→ G(-9,1,1,0,2,2,2)

→

→...→ G(5,1,1,0,2,2,2)

...

...

Em muitas situa¸˜es, ´ mais r´pido escrever-se um c´digo que processa matrizes seguindo o ordenamento
co e
a
o
dos elementos. As fun¸˜es intr´
co
ınsecas do Fortran 90/95 que manipulam matrizes inteiras foram concebidas
de forma a levar em conta este fato.

6.7

Rotinas intr´
ınsecas elementais aplic´veis a matrizes
a

O Fortran 90/95 permite a existˆncia de rotinas (fun¸˜es ou subrotinas) intr´
e
co
ınsecas elementais, isto ´,
e
rotinas que se aplicam a cada elemento de uma matriz. Matrizes podem, ent˜o, ser usadas como argumentos
a
de rotinas intr´
ınsecas, da mesma forma que escalares. Este tipo de recurso n˜o existem no Fortran 77.
a
As opera¸˜es definidas na rotina intr´
co
ınseca ser˜o aplicadas a cada elemento da matriz separadamente.
a
Novamente, caso mais de uma matriz apare¸a no argumento da rotina, estas devem ser conform´veis.
c
a
A seguir, alguns exemplos de rotinas intr´
ınsecas elementais. A lista completa destas rotinas pode ser
obtida no cap´
ıtulo 7.
1. Calcule as ra´ quadradas de todos os elementos da matriz A. O resultado ser´ atribu´ ` matriz B,
ızes
a
ıdo a
a qual ´ conform´vel com A.
e
a
REAL, DIMENSION(10,10) :: A, B
...
B= SQRT(A)
2. Calcule a exponencial de todos os argumentos da matriz A. Novamente, o resultado ser´ atribu´ a
a
ıdo
B.
COMPLEX, DIMENSION(5,-5:15, 25:125) :: A, B
...
B= EXP(A)
3. Encontre o comprimento da string (vari´vel de caractere) excluindo brancos no final da vari´vel para
a
a
todos os elementos da matriz CH.
CHARACTER(LEN= 80), DIMENSION(10) :: CH
INTEGER :: COMP
...
COMP= LEN_TRIM(CH)

6.8

Comando e construto WHERE

Em muitas situa¸˜es, ´ desej´vel realizar-se opera¸˜es somente para alguns elementos de uma matriz;
co
e
a
co
por exemplo, somente para aqueles elementos que s˜o positivos.
a

6.8.1

Comando WHERE

O comando WHERE fornece esta possibilidade. Um exemplo simples ´:
e
REAL, DIMENSION(10,10) :: A
...
WHERE (A > 0.0) A= 1.0/A
o qual fornece a rec´
ıproca (inversa) de todos os elementos positivos de A, deixando os demais inalterados. A
forma geral do comando ´
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
58

6.8. Comando e construto WHERE
WHERE (<express~o l´gica matriz>) <vari´vel matriz>= <express~o matriz>
a
o
a
a

A <express~o l´gica matriz> deve ter a mesma forma que a <vari´vel matriz>. A express˜o l´gica ´
a
o
a
a o
e
desenvolvida inicialmente e ent˜o somente aqueles elementos da <vari´vel matriz> que satisfazem o teste
a
a
l´gico s˜o operados pela <express~o matriz>. Os restantes permanecem inalterados.
o
a
a

6.8.2

Construto WHERE

Uma unica express˜o l´gica de matriz pode ser usada para determinar uma seq¨ˆncia de opera¸˜es e
´
a o
ue
co
atribui¸˜es em matrizes, todas com a mesma forma. A sintaxe deste construto ´:
co
e
WHERE (<express~o l´gica matriz>)
a
o
<opera¸~es atribui¸~es matrizes>
co
co
END WHERE
Inicialmente, a <express~o l´gica matriz> ´ desenvolvida em cada elemento da matriz, resultando em
a
o
e
uma matriz l´gica tempor´ria, cujos elementos s˜o os resultados da <express~o l´gica matriz>. Ent˜o,
o
a
a
a
o
a
cada opera¸˜o e atribui¸˜o de matriz no bloco do construto ´ executada sob o controle da m´scara deterca
ca
e
a
minada pela matriz l´gica tempor´ria; isto ´, as <opera¸~es atribui¸~es matrizes> ser˜o realizadas em
o
a
e
co
co
a
cada elemento das matrizes do bloco que corresponda ao valor .TRUE. da matriz l´gica tempor´ria.
o
a
Existe tamb´m uma forma mais geral do construto WHERE que permite a execu¸˜o de atribui¸˜es a
e
ca
co
elementos de matrizes que n˜o satisfazem o teste l´gico no cabe¸alho:
a
o
c
WHERE (<express~o l´gica matriz>)
a
o
<opera¸~es atribui¸~es matrizes 1>
co
co
ELSEWHERE
<opera¸~es atribui¸~es matrizes 2>
co
co
END WHERE
O bloco <opera¸~es atribui¸~es matrizes 1> ´ executado novamente sob o controle da m´scara defico
co
e
a
nida na <express~o l´gica matriz> e somente elementos que satisfazem esta m´scara s˜o afetados. Em
a
o
a
a
seguida, as <opera¸~es atribui¸~es matrizes 2> s˜o executadas sob o controle da m´scara definida por
co
co
a
a
.NOT. <express~o l´gica matriz>, isto ´, novas atribui¸˜es s˜o realizadas sobre elementos que n˜o satisa
o
e
co
a
a
fazem o teste l´gico definido no cabe¸alho.
o
c
Um exemplo simples do construto WHERE ´:
e
WHERE (PRESSURE <= 1.0)
PRESSURE= PRESSURE + INC_PRESSURE
TEMP= TEMP + 5.0
ELSEWHERE
RAINING= .TRUE.
END WHERE
Neste exemplo, PRESSURE, INC_PRESSURE, TEMP e RAINING s˜o todas matrizes com a mesma forma, embora
a
n˜o do mesmo tipo.
a
O programa-exemplo 6.2 mostra outra aplica¸˜o do construto WHERE.
ca
Um recurso ausente no Fortran 90 mas incorporado no Fortran 95 ´ o mascaramento na instru¸˜o
e
ca
ELSEWHERE, juntamente com a possibilidade de conter qualquer n´mero de instru¸˜es ELSEWHERE mascaradas
u
co
mas, no m´ximo, uma instru¸˜o ELSEWHERE sem m´scara, a qual deve ser a ultima. Todas as express˜es
a
ca
a
´
o
l´gicas que definem as m´scaras devem ter a mesma forma. Adicionalmente, os construtos WHERE podem ser
o
a
encadeados e nomeados; neste caso, as condi¸˜es l´gicas de todas as m´scaras devem ter a mesma forma. O
co o
a
seguinte exemplo ilustra este recurso:
ATRIB1: WHERE (<cond 1>)
<corpo 1>
!Mascarado por <cond 1>
ELSEWHERE (<cond 2>) ATRIB1
<corpo 2>
!Masc. por <cond 2> .AND. .NOT. <cond 1>
ATRIB2:
WHERE (<cond 4>)
<corpo 4>
!Masc. por <cond 2> .AND. .NOT. <cond 1> .AND. <cond 4>
ELSEWHERE ATRIB2
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

59

Programa 6.2: Exemplo do construto WHERE.

program t e s t a w h e r e
i m p l i c i t none
real , dimension ( 3 , 3 ) : : a
integer : : i , j
!
a= r e s h a p e ( s o u r c e= ( / ( ( s i n ( r e a l ( i+j ) ) , i= 1 , 3 ) , j= 1 , 3 ) / ) , shape= ( / 3 , 3 / ) )
print * , ”Matriz A o r i g i n a l : ”
print * , a ( 1 , : )
print * , a ( 2 , : )
print * , a ( 3 , : )
!
where ( a >= 0 . 0 )
a= s q r t ( a )
elsewhere
a= a ** 2
end where
print * , ”Matriz A m o d i f i c a d a : ”
print * , a ( 1 , : )
print * , a ( 2 , : )
print * , a ( 3 , : )
end program t e s t a w h e r e

<corpo 5>
!Masc. por
...
!
.AND.
END WHERE ATRIB2
...
ELSEWHERE (<cond 3>) ATRIB1
<corpo 3>
!Masc. por
...
!
.AND.
ELSEWHERE ATRIB1
<corpo 6>
!Masc. por
...
!
.AND.
END WHERE ATRIB1

6.9

<cond 2> .AND. .NOT. <cond 1>
.NOT. <cond 4>

<cond 3> .AND. .NOT. <cond 1>
.NOT. <cond 2>
.NOT. <cond 1> .AND. .NOT. <cond 2>
.NOT. <cond 3>

Matrizes aloc´veis
a

Uma novidade importante introduzida no Fortran 90/95 ´ a habilidade de se declarar vari´veis dinˆmicas;
e
a
a
em particular, matrizes dinˆmicas. Fortran 90 fornece tanto matrizes aloc´veis quanto matrizes autom´ticas,
a
a
a
ambos os tipos sendo matrizes dinˆmicas. Usando matrizes aloc´veis, ´ poss´ alocar e de-alocar espa¸o de
a
a
e
ıvel
c
mem´ria conforme necess´rio. O recurso de matrizes autom´ticas permite que matrizes locais em uma fun¸˜o
o
a
a
ca
ou subrotina tenham forma e tamanho diferentes cada vez que a rotina ´ invocada. Matrizes autom´ticas
e
a
s˜o discutidas no cap´
a
ıtulo 8.
Matrizes aloc´veis permitem que grandes fra¸˜es da mem´ria do computador sejam usadas somente
a
co
o
quando requerido e, posteriormente, liberadas, quando n˜o mais necess´rias. Este recurso oferece um uso de
a
a
mem´ria muito mais eficiente que o Fortran 77, o qual oferecia somente aloca¸˜o est´tica (fixa) de mem´ria.
o
ca
a
o
Al´m disso, o c´digo torna-se muito mais robusto, pois a forma e o tamanho das matrizes podem ser decididos
e
o
durante o processamento do c´digo.
o
Uma matriz aloc´vel ´ declarada na linha de declara¸˜o de tipo de vari´vel com o atributo ALLOCATABLE.
a
e
ca
a
O posto da matriz deve tamb´m ser declarado com a inclus˜o dos s´
e
a
ımbolos de dois pontos “:”, um para
cada dimens˜o da matriz. Por exemplo, a matriz de duas dimens˜es A ´ declarada como aloc´vel atrav´s da
a
o
e
a
e
declara¸˜o:
ca
REAL, DIMENSION(:,:), ALLOCATABLE :: A
Esta forma de declara¸˜o n˜o aloca espa¸o de mem´ria imediatamente ` matriz, como acontece com as
ca a
c
o
a
declara¸˜es usuais de matrizes. O status da matriz nesta situa¸˜o ´ not currently allocated, isto ´, correnco
ca e
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
60

6.9. Matrizes aloc´veis
a

temente n˜o alocada. Espa¸o de mem´ria ´ dinamicamente alocado durante a execu¸˜o do programa, logo
a
c
o
e
ca
antes da matriz ser utilizada, usando-se o comando ALLOCATE. Este comando especifica os limites da matriz,
seguindo as mesmas regras definidas na se¸˜o 6.1. A seguir s˜o dados dois exemplos de uso deste comando:
ca
a
ALLOCATE (A(0:N,M))
ou usando express˜es inteiras:
o
ALLOCATE (A(0:N+1,M))
Como se pode ver, esta estrat´gia confere uma flexibilidade grande na defini¸˜o de matrizes ao programador.
e
ca
O espa¸o alocado ` matriz com o comando ALLOCATE pode, mais tarde, ser liberado com o comando
c
a
DEALLOCATE. Este comando requer somente nome da matriz previamente alocada. Por exemplo, para
liberar o espa¸o na mem´ria reservado para a matriz A, o comando fica
c
o
DEALLOCATE (A)
Tanto os comandos ALLOCATE e DEALLOCATE possuem o especificador opcional STAT, o qual retorna o status
do comando de aloca¸˜o ou de-aloca¸˜o. Neste caso, a forma geral do comando ´:
ca
ca
e
ALLOCATE (<lista de objetos alocados> [, STAT= <status>])
DEALLOCATE (<lista de objetos alocados> [, STAT= <status>])
onde <status> ´ uma vari´vel inteira escalar. Se STAT= est´ presente no comando, <status> recebe o valor
e
a
a
zero se o procedimento do comando ALLOCATE/DEALLOCATE foi bem sucedido ou um valor positivo se houve
um erro no processo. Se o especificador STAT= n˜o estiver presente e ocorra um erro no processo, o programa
a
´ abortado. Finalmente, ´ poss´
e
e
ıvel alocar-se ou de-alocar-se mais de uma matriz simultaneamente, como
indica a <lista de objetos alocados>.
Um breve exemplo do uso destes comandos seria:
REAL, DIMENSION(:), ALLOCATABLE :: A, B
REAL, DIMENSION(:,:), ALLOCATABLE :: C
INTEGER :: N
...
ALLOCATE (A(N), B(2*N), C(N,2*N))
B(:N)= A
B(N+1:)= SQRT(A)
DO I= 1,N
C(I,:)= B
END DO
DEALLOCATE (A, B, C)
Matrizes aloc´veis tornam poss´
a
ıvel o requerimento freq¨ente de declarar uma matriz tendo um n´mero
u
u
vari´vel de elementos. Por exemplo, pode ser necess´rio ler vari´veis, digamos tam1 e tam2 e ent˜o declarar
a
a
a
a
uma matriz com tam1 × tam2 elementos:
INTEGER :: TAM1, TAM2
REAL, DIMENSION (:,:), ALLOCATABLE :: A
INTEGER :: STATUS
...
READ*, TAM1, TAM2
ALLOCATE (A(TAM1,TAM2), STAT= STATUS)
IF (STATUS > 0)THEN
... ! Comandos de processamento de erro.
END IF
... ! Uso da matriz A.
DEALLOCATE (A)
...
No exemplo acima, o uso do especificador STAT= permite que se tome providˆncias caso n˜o seja poss´
e
a
ıvel
alocar a matriz, por alguma raz˜o.
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

61

Como foi mencionado anteriormente, uma matriz aloc´vel possui um status de aloca¸˜o. Quando a matriz
a
ca
´ declarada, mas ainda n˜o alocada, o seu status ´ unallocated ou not currently allocated. Quando a matriz
e
a
e
aparece no comando ALLOCATE, o seu status passa a allocated ; uma vez que ela ´ de-alocada, o seu status
e
retorna a not currently allocated. Assim, o comando ALLOCATE somente pode ser usado em matrizes n˜o
a
correntemente alocadas, ao passo que o comando DEALLOCATE somente pode ser usado em matrizes alocadas;
caso contr´rio, ocorre um erro.
a
´
E poss´
ıvel verificar se uma matriz est´ ou n˜o correntemente alocada usando-se a fun¸˜o intr´
a
a
ca
ınseca
ALLOCATED. Esta ´ uma fun¸˜o l´gica com um argumento, o qual deve ser o nome de uma matriz aloc´vel.
e
ca o
a
Usando-se esta fun¸˜o, comandos como os seguintes s˜o poss´
ca
a
ıveis:
IF (ALLOCATED(A)) DEALLOCATE (A)
ou
IF (.NOT. ALLOCATED(A)) ALLOCATE (A(5,20))
Um terceiro status de aloca¸˜o, poss´ no Fortran 90 mas n˜o no Fortran 95, ´ o undefined, o qual ocorria
ca
ıvel
a
e
quando uma matriz era alocada dentro de uma rotina e n˜o era de-alocada antes de retornar ao programa
a
que chamou a rotina. O que ocorria era que em subseq¨entes chamadas desta rotina a matriz com o status
u
undefined n˜o mais podia ser utilizada. No Fortran 95, todas as matrizes aloc´veis definidas em rotinas s˜o
a
a
a
automaticamente colocadas no status unallocated quando da sa´ da rotina. Contudo, um boa pr´tica de
ıda
a
programa¸˜o consiste em sempre de-alocar todas as matrizes alocadas dentro de uma rotina.
ca
Finalmente, h´ trˆs restri¸˜es no uso de matrizes aloc´veis:
a e
co
a
1. Matrizes aloc´veis n˜o podem ser argumentos mudos de uma rotina e devem, portanto, ser alocadas e
a
a
de-alocadas dentro da mesma unidade de programa (ver cap´
ıtulo 8).
2. O resultado de uma fun¸˜o n˜o pode ser uma matriz aloc´vel (embora possa ser uma matriz).
ca a
a
3. Matrizes aloc´veis n˜o podem ser usadas na defini¸˜o de um tipo derivado (esta restri¸˜o foi retirada
a
a
ca
ca
no Fortran 2003.
O programa-exemplo a seguir ilustra o uso de matrizes aloc´veis.
a
program t e s t a a l o c
i m p l i c i t none
integer , dimension ( : , : ) , a l l o c a t a b l e : : b
integer : : i , j , n= 2
!
print * , ”Valor i n i c i a l de n : ” , n
allocate (b(n , n ))
b= n
print * , ”Valor i n i c i a l de B : ”
print ” ( 2 ( i 2 ) ) ” , ( ( b ( i , j ) , j= 1 , n ) , i= 1 , n )
deallocate ( b )
n= n + 1
print * , ”Segundo v a l o r de n : ” , n
allocate (b(n , n ))
b= n
print * , ”Segundo v a l o r de B : ”
print ” ( 3 ( i 2 ) ) ” , ( ( b ( i , j ) , j= 1 , n ) , i= 1 , n )
deallocate ( b )
n= n + 1
print * , ” T e r c e i r o v a l o r de n : ” , n
a l l o c a t e ( b ( n+1,n+1))
b= n + 1
print * , ” T e r c e i r o v a l o r de B : ”
print ” ( 5 ( i 2 ) ) ” , ( ( b ( i , j ) , j= 1 , n+1) , i= 1 , n+1)
end program t e s t a a l o c

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
62

6.10. Comando e construto FORALL

6.10

Comando e construto FORALL

Quando um construto DO como o seguinte:
DO I= 1, N
A(I,I)= X(I)
END DO

!A tem posto 2 e X tem posto 1.

´ executado, o processador deve realizar cada itera¸˜o sucessiva em ordem, com uma atribui¸˜o ap´s a
e
ca
ca
o
outra. Isto representa um impedimento severo na otimiza¸˜o do c´digo em uma plataforma paralelizada.
ca
o
Este problema foi enfocado com a constru¸ao do HPF (High Performance Fortran), o qual consiste em
c˜
uma vers˜o do Fortran 90 destinada a sistemas de computa¸˜o paralela. Posteriormente, alguns avan¸os
a
ca
c
realizados pelo HPF, em rela¸˜o ao Fortran 90, foram incorporados do padr˜o do Fortran 95; entre eles,
ca
a
a instru¸˜o FORALL. A id´ia ´ oferecer ao programador uma estrutura que possibilite os mesmos recursos
ca
e e
obtidos com la¸os DO, por´m que sejam automaticamente paraleliz´veis, quando o programa estiver rodando
c
e
a
em uma plataforma paralela.

6.10.1

Comando FORALL

As instru¸˜es do exemplo acima s˜o implementadas atrav´s de um comando FORALL da seguinte maneira:
co
a
e
FORALL (I= 1:N) A(I,I)= X(I)
a qual especifica que as atribui¸˜es individuais sejam realizadas em qualquer ordem, inclusive simultaneaco
mente, caso o programa rode em uma plataforma paralela. O comando FORALL pode ser visto como uma
atribui¸˜o de matrizes expressa com a ajuda de ´
ca
ındices. Neste exemplo em particular, deve-se notar que
as atribui¸˜es n˜o poderiam ser representadas de maneira simples atrav´s de uma atribui¸˜o de matrizes
co
a
e
ca
inteiras, tal como A= X, porque as matrizes A e X n˜o tˆm a mesma forma. Outros exemplos do comando
a e
s˜o:
a
FORALL (I= 1:N, J= 1:M) A(I,J)= I + J
FORALL (I= 1:N, J= 1:N, Y(I,J) /= 0.0) X(J,I)= 1.0/Y(I,J)
O primeiro exemplo poderia ser implementado com o uso da fun¸˜o intr´
ca
ınseca RESHAPE, mas o uso do FORALL
possibilita a paraleliza¸˜o do programa execut´vel. J´ o segundo exemplo n˜o poderia ser implementado
ca
a
a
a
com opera¸˜o de matriz inteira (tal como X= 1.0/Y) porque, em primeiro lugar, a matriz X tˆm elementos
ca
e
transpostos em rela¸˜o ` matriz Y. Em segundo lugar, a m´scara Y(I,J) /= 0.0 n˜o est´ presente na
ca a
a
a
a
opera¸˜o de matriz inteira; somente ´ poss´ introduzir esta m´scara com o uso do FORALL.
ca
e
ıvel
a
A forma geral do comando FORALL ´ a seguinte:
e
FORALL (<´ndice>= <menor>:<maior>[:<passo>] [,<´ndice>= <meı
ı
nor>:<maior>[:<passo>]] &
[...] [, <express~o escalar l´gica>]) <opera¸~es atribui¸~es matrizes>
a
o
co
co
as condi¸˜es impostas a <´ndice>, <menor>, <maior>, <passo> e <express~o escalar l´gica> s˜o as
co
ı
a
o
a
mesmas impostas ao construto FORALL e ser˜o explicadas na descri¸˜o da forma geral do mesmo.
a
ca

6.10.2

Construto FORALL

O construto FORALL tamb´m existe. Ele permite que diversas atribui¸˜es sejam executadas em ordem.
e
co
Por exemplo, dadas as seguintes opera¸˜es com sub-matrizes:
co
A(2:N-1, 2:N-1)= A(2:N-1, 1:N-2) + A(2:N-1, 3:N) &
+ A(1:N-2, 2:N-1) + A(3:N, 2:N-1)
B(2:N-1, 2:N-1)= A(2:N-1, 2:N-1)
tamb´m podem ser implementadas com o uso do construto FORALL:
e
FORALL (I= 2:N-1, J= 2:N-1)
A(I,J)= A(I,J-1) + A(I, J+1) + A(I-1, J) + A(I+1, J)
B(I,J)= A(I,J)
END FORALL
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 6. Processamento de Matrizes

63

Neste exemplo, cada elemento de A ´ igualado ` soma dos quatro vizinhos mais pr´ximos e ´ feita ent˜o
e
a
o
e
a
uma c´pia em B. A vers˜o com o FORALL ´ melhor leg´
o
a
e
ıvel e pode ser executado em qualquer ordem,
inclusive simultaneamente. Devido a isto, quando o corpo do construto possui mais de uma instru¸˜o, o
ca
processador executa todas express˜es e atribui¸˜es da primeira linha antes de passar a executar a instru¸˜o
o
co
ca
da linha seguinte. N˜o ocorre erro na atribui¸˜o, porque inicialmente as express˜es s˜o desenvolvidas, em
a
ca
o
a
qualquer ordem, seus resultados guardados em local de armazenagem tempor´ria na mem´ria e s´ no final
a
o
o
as atribui¸˜es s˜o feitas, tamb´m em qualquer ordem.
co
a
e
Construtos FORALL podem ser encadeados. A seq¨ˆncia
ue
FORALL (I= 1:N-1)
FORALL (J= I+1:N)
A(I,J)= A(J,I)
END FORALL
END FORALL
atribui a transposta do triˆngulo inferior de A ao triˆngulo superior de A.
a
a
Um construto FORALL pode conter um comando ou construto WHERE. Cada comando no corpo de um
construto WHERE ´ executado em seq¨ˆncia. Por exemplo,
e
ue
FORALL (I= 1:N)
WHERE (A(I,:) == 0) A(I,:)= I
B(I,:)= I/A(I,:)
END FORALL
Aqui, cada elemento nulo de A ´ substitu´ pelo valor do ´
e
ıdo
ındice das linhas e, seguindo a opera¸˜o completa, os
ca
elementos das linhas de B s˜o definidos como as rec´
a
ıprocas dos correspondentes elementos de A multiplicados
pelo respectivo ´
ındice.
A sintaxe mais geral do construto FORALL ´:
e
[<nome>:] FORALL (<´ndice>= <menor>:<maior>[:<passo>], &
ı
[, <´ndice>= <menor>:<maior>[:<passo>]] [...] &
ı
[, <express~o l´gica escalar>])
a
o
<corpo>
END FORALL [<nome>]
onde <´ndice> ´ uma vari´vel inteira escalar, a qual permanece v´lida somente dentro do <corpo> do
ı
e
a
a
construto, ou seja, outras vari´veis podem ter o mesmo nome do <´ndice> mas est˜o separadas e n˜o s˜o
a
ı
a
a a
acess´
ıveis de dentro do FORALL.2 O <´ndice> n˜o pode ser redefinido dentro do construto. As express˜es
ı
a
o
<menor>, <maior> e <passo> devem ser express˜es escalares inteiras e formar uma seq¨ˆncia de valores como
o
ue
para uma se¸˜o de matriz (se¸˜o 6.3); eles n˜o podem fazer referˆncia a um ´
ca
ca
a
e
ındice no mesmo cabe¸alho,
c
mas podem fazer referˆncia a um ´
e
ındice de um FORALL mais externo. Uma vez tendo as express˜es inteiras
o
sido desenvolvidas, a <express~o l´gica escalar>, se presente, ´ desenvolvida para cada combina¸˜o dos
a
o
e
ca
valores dos ´
ındices. Aqueles para os quais o resultado ´ .TRUE. s˜o ativados em cada comando no <corpo>
e
a
do construto.
O <corpo> consiste em um ou mais dos seguintes: express˜es e atribui¸˜es de elementos de matrizes,
o
co
comandos ou construtos WHERE e outros comandos ou construtos FORALL. Usualmente, o sub-objeto (submatriz, por exemplo) no lado esquerdo de uma atribui¸˜o no <corpo> far´ referˆncia a cada <´ndice> dos
ca
a
e
ı
construtos nos quais ele est´ imerso, como parte da identifica¸˜o do sub-objeto. Nenhum dos comandos no
a
ca
<corpo> pode conter uma ramifica¸˜o ou ser acess´
ca
ıvel atrav´s de algum comando de desvio de fluxo, tal
e
como o GO TO. Rotinas externas podem ser acessadas de dentro do <corpo> ou de dentro do cabe¸alho do
c
construto (na m´scara, por exemplo). Todas as rotinas invocadas dentro desta estrutura devem ser puras
a
(se¸˜o 8.2.16).
ca
O programa-exemplo 6.3 (programa tesforall) ilustra uma aplica¸˜o simples do construto FORALL,
ca
enquanto que o programa 6.4 (programa tesforall2) calcula a transposta de uma matriz. Pode-se notar
aqui que o comando FORALL n˜o acarreta em erro, uma vez que as atribui¸˜es s˜o inicialmente armazenadas
a
co
a
em espa¸o tempor´rio e somente no final s˜o transferidas aos componentes da matriz A.
c
a
a

2O

que ´ denominado de ambito (scope).
e
ˆ

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
64

6.10. Comando e construto FORALL

Programa 6.3: Exemplo simples do construto FORALL.

program t e s f o r a l l
i m p l i c i t none
integer , dimension ( 3 0 ) : : a , b
integer : : n
!
f o r a l l ( n =1:30)
a ( n)= n
b ( n)= a(30−n+1)
end f o r a l l
print * , ’ Vetor a : ’
print * , a
print * , ’ ’
print * , ’ Vetor b : ’
print * , b
end program t e s f o r a l l

Programa 6.4: Calcula a transposta de uma matriz utilizando o comando FORALL.

program t e s f o r a l l 2
i m p l i c i t none
integer , dimension ( 3 , 3 ) : : a
integer : : i , j
a= r e s h a p e ( s o u r c e= ( / ( i , i= 1 , 9 ) / ) , shape= ( / 3 , 3 / ) )
print * , ”Matriz A: ”
print * , a ( 1 , : )
print * , a ( 2 , : )
print * , a ( 3 , : )
f o r a l l ( i= 1 : 3 , j= 1 : 3 ) a ( i , j )= a ( j , i )
print * , ”T ra ns po s ta de A: ”
print * , a ( 1 , : )
print * , a ( 2 , : )
print * , a ( 3 , : )
end program t e s f o r a l l 2

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 7

Rotinas Intr´
ınsecas
Em uma linguagem de programa¸˜o destinada a aplica¸˜es cient´
ca
co
ıficas h´ uma exigˆncia ´bvia para que as
a
e
o
fun¸˜es matem´ticas mais requisitadas sejam oferecidas como parte da pr´pria linguagem, ao inv´s de terem
co
a
o
e
de ser todas implementadas pelo programador. Al´m disso, ao serem fornecidas como parte do compilador,
e
espera-se que estas fun¸˜es tenham sido altamente otimizadas e testadas.
co
A eficiˆncia das rotinas intr´
e
ınsecas quando estas manipulam matrizes em computadores vetoriais ou
paralelos deve ser particularmente marcante, porque uma unica chamada ` rotina deve causar um n´mero
´
a
u
grande de opera¸˜es individuais sendo feitas simultaneamente, sendo o c´digo que as implementa otimizado
co
o
para levar em conta todos os recursos de hardware dispon´
ıveis.
No padr˜o do Fortran 90/95 h´ mais de cem rotinas intr´
a
a
ınsecas ao todo. Elas se dividem em grupos
distintos, os quais ser˜o descritos em certo detalhe. Certos compiladores em particular poder˜o oferecer
a
a
ainda mais rotinas, al´m das oferecidas pelo padr˜o da linguagem; contudo, o pre¸o a pagar ´ a falta de
e
a
c
e
portabilidade de programas que usam rotinas fora do grupo-padr˜o. Al´m disso, rotinas extras somente
a
e
poder˜o ser oferecidas ao usu´rio atrav´s de m´dulos (cap´
a
a
e
o
ıtulo 8).
Ao longo deste cap´
ıtulo, as rotinas intr´
ınsecas ser˜o naturalmente divididas em fun¸˜es e subrotinas. A
a
co
distin¸˜o entre estas duas classes de rotinas ser´ discutida com mais detalhes no cap´
ca
a
ıtulo 8.

7.1

Categorias de rotinas intr´
ınsecas

H´ quatro categorias de rotinas intr´
a
ınsecas:
Rotinas elementais. S˜o especificadas para argumentos escalares, mas podem tamb´m ser aplicadas a
a
e
matrizes conform´veis. No caso de uma fun¸˜o elemental, cada elemento da matriz resultante, caso
a
ca
exista, ser´ obtido como se a fun¸˜o tivesse sido aplicada a cada elemento individual da matriz que
a
ca
foi usada como argumento desta fun¸˜o. No caso de uma subrotina elemental com um argumento
ca
matricial, cada argumento com intento IN ou INOUT deve ser uma matriz e cada elemento resultante
ser´ obtido como se a subrotina tivesse sido aplicada a cada elemento da matriz que ´ passada como
a
e
argumento ` subrotina.
a
Fun¸˜es inquisidoras. Retornam propriedades dos seus argumentos principais que n˜o dependem dos seus
co
a
valores, somente do seu tipo e/ou esp´cie.
e
Fun¸˜es transformacionais. S˜o fun¸˜es que n˜o s˜o nem elementais nem inquisidoras. Elas usualmente
co
a
co
a a
tˆm argumentos matriciais e o resultado tamb´m ´ uma matriz cujos elementos dependem dos elemene
e e
tos dos argumentos.
Rotinas n˜o-elementais. Rotinas que n˜o se enquadram em nenhum dos tipos acima.
a
a
As rotinas intr´
ınsecas ser˜o descritas posteriormente com base nesta categoriza¸˜o.
a
ca

7.2

Declara¸˜o e atributo INTRINSIC
ca

Um nome pode ser especificado como o nome de uma rotina intr´
ınseca com a declara¸˜o INTRINSIC, o
ca
qual possui a forma geral:
INTRINSIC <lista de nomes intr´nsecos>
ı
65
66

7.3. Fun¸˜es inquisidoras de qualquer tipo
co

onde <lista de nomes intr´nsecos> ´ uma lista de nomes de rotinas intr´
ı
e
ınsecas. O uso desta declara¸˜o
ca
´ recomendado quando se quer enfatizar ao compilador que certos nomes s˜o destinados a rotinas intr´
e
a
ınsecas. Isto pode ser util quando o programador est´ estendendo a defini¸˜o de uma rotina intr´
´
a
ca
ınseca, em
um procedimento denominado sobrecarga de operador (operator overloading), o qual faz uso de interfaces
gen´ricas (generic interfaces). Para mais detalhes nestes recursos avan¸ados, ver Metcalf & Reid (1996)
e
c
[4]. Alternativamente, uma ou mais fun¸˜es intr´
co
ınsecas podem ser declaradas com o atributo INTRINSIC,
no lugar da declara¸˜o.
ca
O atributo ou declara¸˜o INTRINSIC s˜o excludentes em rela¸˜o ao atributo ou declara¸˜o EXTERNAL
ca
a
ca
ca
(se¸˜o 8.2.12).
ca

7.3

Fun¸˜es inquisidoras de qualquer tipo
co

As seguintes s˜o fun¸˜es inquisidoras, com argumentos que podem ser de qualquer tipo:
a
co
ASSOCIATED(POINTER[,TARGET]). Quanto TARGET est´ ausente, a fun¸˜o retorna o valor .TRUE. se o pona
ca
teiro (pointer) est´ associado com um alvo (target) e retorna o valor .FALSE. em caso contr´rio. O
a
a
status de associa¸˜o de ponteiro de POINTER n˜o deve ser indefinido. Se TARGET estiver presente, este
ca
a
deve ter o mesmo tipo, esp´cie e posto de POINTER. O valor da fun¸˜o ´ .TRUE. se POINTER estiver
e
ca e
associado a TARGET ou .FALSE. em caso contr´rio. No caso de matrizes, .TRUE. ´ obtido somente se as
a
e
formas s˜o idˆnticas e elementos de matriz correspondentes, na ordem de elementos de matriz, est˜o
a
e
a
associadas umas com as outras. Se o comprimento do caractere ou tamanho da matriz s˜o iguais a
a
zero, .FALSO. ´ obtido. Um limite diferente, como no caso de ASSOCIATED(P,A) seguindo a atribuie
¸˜o de ponteiro P => A(:) quando LBOUND(A)= 0, ´ insuficiente para causar um resultado .FALSE..
ca
e
TARGET pode ser tamb´m um ponteiro, em cujo caso seu alvo ´ comparado com o alvo de POINTER; o
e
e
status de associa¸˜o de ponteiro de TARGET n˜o deve ser indefinido e se ou POINTER ou TARGET est˜o
ca
a
a
dissociados, o resultado ´ .FALSE.
e
PRESENT(A). Pode ser chamada em um sub-programa que possui um argumento mudo opcional A (ver
se¸˜o 8.2.9) ou acesse este argumento mudo a partir de seu hospedeiro. A fun¸˜o retorna o valor
ca
ca
.TRUE. se o argumento est´ presente na chamada do sub-programa ou .FALSE. em caso contr´rio. Se
a
a
um argumento mudo opcional ´ usado como um argumento real na chamada de outra rotina, ele ´
e
e
considerado tamb´m ausente pela rotina chamada.
e
KIND(X). Tem o argumento X de qualquer tipo e esp´cie e o seu resultado tem o tipo inteiro padr˜o e de
e
a
valor igual ao valor do parˆmetro de esp´cie de X.
a
e

7.4

Fun¸˜es elementais num´ricas
co
e

H´ 17 fun¸oes elementais destinadas ` realiza¸˜o de opera¸˜es num´ricas simples, muitas das quais
a
c˜
a
ca
co
e
realizam convers˜o de tipo de vari´veis para alguns ou todos os argumentos.
a
a

7.4.1

Fun¸˜es elementais que podem converter
co

Se o especificador KIND estiver presente nas fun¸˜es elementais seguintes, este deve ser uma express˜o
co
a
inteira e fornecer um parˆmetro de esp´cie de tipo que seja suportado pelo processador.
a
e
ABS(A). Retorna o valor absoluto de um argumento dos tipos inteiro, real ou complexo. O resultado ´ do
e
tipo inteiro se A for inteiro e ´ real nos demais casos. O resultado ´ da mesma esp´cie que A.
e
e
e
AIMAG(Z). Retorna a parte imagin´ria do valor complexo Z. O tipo do resultado ´ real e a esp´cie ´ a mesma
a
e
e e
que Z.
AINT(A[,KIND]). Trunca um valor real A em sentido ao zero para produzir um valor real cujos valores
decimais s˜o iguais a zero. Se o argumento KIND estiver presente, o resultado ´ da esp´cie dada por
a
e
e
este; caso contr´rio, retorna o resultado na esp´cie padr˜o do tipo real.
a
e
a
ANINT(A[,KIND]). Retorna um real cujo valor ´ o n´mero completo (sem parte fracion´ria) mais pr´ximo
e
u
a
o
de A. Se KIND estiver presente, o resultado ´ do tipo real da esp´cie definida; caso contr´rio, o resultado
e
e
a
ser´ real da esp´cie padr˜o.
a
e
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 7. Rotinas Intr´
ınsecas

67

CEILING(A). Retorna o menor inteiro maior ou igual ao seu argumento real. Se KIND estiver presente, o
resultado ser´ do tipo inteiro com a esp´cie definida pelo parˆmetro; caso contr´rio, o resultado ser´
a
e
a
a
a
inteiro da esp´cie padr˜o.
e
a
CMPLX(X[,Y][,KIND]). Converte X ou (X,Y) ao tipo complexo com a esp´cie definida pelo argumento KIND,
e
caso presente, ou na esp´cie padr˜o do tipo complexo em caso contr´rio. Se Y for ausente, X pode ser
e
a
a
dos tipos inteiro, real ou complexo. Se Y estiver presente, tanto X quanto Y devem ser dos tipos inteiro
ou real.
FLOOR(A[,KIND]). Retorna o maior inteiro menor ou igual a seu argumento real A. Se KIND estiver presente,
o resultado ´ do tipo inteiro da esp´cie definida; caso contr´rio, o resultado ´ inteiro da esp´cie padr˜o.
e
e
a
e
e
a
INT(A[,KIND]). Converte ao tipo inteiro da esp´cie padr˜o ou dada pelo argumento KIND. O argumento A
e
a
pode ser:
ˆ inteiro, em cujo caso INT(A)= A;
ˆ real, em cujo caso o valor ´ truncado em sentido ao zero, ou
e
ˆ complexo, em cujo caso somente a parte real ´ considerada e esta ´ truncada em sentido ao zero.
e
e

NINT(A[,KIND]). Retorna o valor inteiro mais pr´ximo do real A. Se KIND estiver presente, o resultado ´
o
e
do tipo inteiro da esp´cie definida; caso contr´rio, o resultado ser´ inteiro da esp´cie padr˜o.
e
a
a
e
a
REAL(A[,KIND]). Converte ao tipo real da esp´cie dada pelo argumento KIND. O argumento A pode ser dos
e
tipos inteiro, real ou complexo. Se A for complexo, a parte imagin´ria ´ ignorada. Se o argumento
a
e
KIND estiver ausente, o resultado ser´ da esp´cie padr˜o do tipo real se A for inteiro ou real e da mesma
a
e
a
esp´cie de A se este for complexo.
e

7.4.2

Fun¸˜es elementais que n˜o convertem
co
a

As seguintes s˜o fun¸˜es elementais cujos resultados s˜o do tipo e da esp´cie iguais aos do primeiro ou
a
co
a
e
unico argumento. Para aquelas que possuem mais de um argumento, todos devem ser do mesmo tipo e
´
esp´cie.
e
CONJG(Z). Retorna o conjugado do valor complexo Z.
DIM(X,Y). Retorna MAX(X-Y,0) para argumentos que s˜o ambos inteiros ou ambos reais.
a
MAX(A1,A2[,A3,...]). Retorna o m´ximo (maior valor) entre dois ou mais valores inteiros ou reais.
a
MIN(A1,A2[,A3,...]). Retorna o m´
ınimo (menor valor) entre dois ou mais valores inteiros ou reais.
MOD(A,P). Retorna o restante de A m´dulo P, ou seja, A-INT(A/P)*P. Se P=0, o resultado depende do
o
processador. A e P devem ambos ser inteiros ou ambos reais.
MODULO(A,P). Retorna A m´dulo P quando A e P s˜o ambos inteiros ou ambos reais; isto ´, A-FLOOR(A/P)*P
o
a
e
no caso real ou A-FLOOR(A÷P)*P no caso inteiro, onde ÷ representa divis˜o matem´tica ordin´ria. Se
a
a
a
P=0, o resultado depende do processador.
SIGN(A,B). Retorna o valor absoluto de A vezes o sinal de B. A e B devem ser ambos inteiros ou ambos
reais. Se B= 0 e ´ inteiro, seu sinal ´ assumido positivo. Se o processador n˜o tem a capacidade de
e
e
a
disting¨ir entre zeros reais positivos ou negativos ent˜o, para B= 0.0 o sinal ´ assumido positivo.
u
a
e

7.5

Fun¸˜es elementais matem´ticas
co
a

As seguintes s˜o fun¸˜es elementais que calculam o conjunto imagem de fun¸˜es matem´ticas elementares.
a
co
co
a
O tipo e esp´cie do resultado s˜o iguais aos do primeiro argumento, o qual, usualmente, ´ o unico.
e
a
e ´
ACOS(X). Retorna a fun¸˜o arco cosseno (ou cos−1 ) para valores reais do argumento X (|X| ≤ 1). O resultado
ca
´ obtido em radianos no intervalo 0 ≤ ACOS(X) ≤ π.
e
ASIN(X). Retorna a fun¸˜o arco seno (ou sin−1 ) para valores reais do argumento X (|X| ≤ 1). O resultado ´
ca
e
obtido em radianos no intervalo −π/2 ≤ ASIN(X) ≤ π/2.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
68

7.6. Fun¸˜es elementais l´gicas e de caracteres
co
o

ATAN(X). Retorna a fun¸˜o arco tangente (ou tan−1 ) para valores reais do argumento X (−∞ < X < ∞). O
ca
resultado ´ obtido em radianos no intervalo −π/2 ≤ ATAN(X) ≤ π/2.
e
ATAN2(Y,X). Retorna a fun¸˜o arco tangente (ou tan−1 ) para pares de argumentos reais, X e Y, ambos do
ca
mesmo tipo e esp´cie. O resultado ´ o valor principal do argumento do n´mero complexo (X,Y),
e
e
u
expresso em radianos no intervalo −π < ATAN2(Y, X) ≤ π. Os valores de X e Y n˜o devem ser simultaa
neamente nulos.
COS(X). Retorna o valor da fun¸˜o cosseno para um argumento dos tipos real ou complexo. A unidade do
ca
argumento X ´ suposta ser radianos.
e
COSH(X). Retorna o valor da fun¸˜o cosseno hiperb´lico para um argumento X real.
ca
o
EXP(X). Retorna o valor da fun¸˜o exponencial para um argumento X real ou complexo.
ca
LOG(X). Retorna o valor da fun¸˜o logaritmo natural para um argumento X real ou complexo. No caso real,
ca
X deve ser positivo. No caso complexo, X n˜o pode ser nulo e a parte imagin´ria do resultado (Zi ) est´
a
a
a
no intervalo −π < Zi ≤ π.
LOG10(X). Retorna o valor da fun¸˜o logaritmo de base 10 para um argumento X real e positivo.
ca
SIN(X). Retorna o valor da fun¸˜o seno para um argumento dos tipos real ou complexo. A unidade do
ca
argumento X ´ suposta ser radianos.
e
SINH(X). Retorna o valor da fun¸˜o seno hiperb´lico para um argumento X real.
ca
o
SQRT(X). Retorna o valor da fun¸˜o raiz quadrada para um argumento X real ou complexo. No caso real,
ca
X n˜o pode ser negativo. No caso complexo, o resultado consiste na raiz principal, ou seja, a parte
a
real do resultado ´ positiva ou nula. Quando a parte real do resultado for nula, a parte imagin´ria ´
e
a
e
positiva ou nula.
TAN(X). Retorna o valor da fun¸˜o tangente para um argumento X real. A unidade do argumento ´ suposta
ca
e
ser radianos.
TANH(X). Retorna o valor da fun¸˜o tangente hiperb´lica para um argumento X real.
ca
o

7.6
7.6.1

Fun¸˜es elementais l´gicas e de caracteres
co
o
Convers˜es caractere-inteiro
o

As seguintes s˜o fun¸˜es elementais para converter um unico caractere em um inteiro e vice-versa.
a
co
´
ACHAR(I). O resultado ´ do tipo de caractere padr˜o de comprimento um e retorna o caractere que est´ na
e
a
a
posi¸˜o especificada pelo valor inteiro I na tabela ASCII de caracteres (tabela 4.9). I deve estar no
ca
intervalo 0 ≤ I ≤ 127; caso contr´rio, o resultado depende do processador.
a
CHAR(I[,KIND]). O resultado ´ do tipo caractere de comprimento um. A esp´cie ´ dada pelo argumento
e
e
e
opcional KIND, se presente ou, em caso contr´rio, ser´ a esp´cie padr˜o. A fun¸˜o retorna o caractere na
a
a
e
a
ca
posi¸˜o I (tipo inteiro) da seq¨ˆncia de caracteres interna do processador associada com o parˆmetro
ca
ue
a
de esp´cie relevante. I deve estar no intervalo 0 ≤ I ≤ n − 1, onde n ´ o n´mero de caracteres na
e
e
u
seq¨ˆncia interna do processador.
ue
IACHAR(C). O resultado ´ do tipo inteiro padr˜o e retorna a posi¸˜o do caractere C na tabela ASCII. Se C
e
a
ca
n˜o est´ na tabela, o resultado depende do processador.
a
a
ICHAR(C). O resultado ´ do tipo inteiro padr˜o e retorna a posi¸˜o do caractere C na seq¨ˆncia interna do
e
a
ca
ue
processador associada com a esp´cie de C.
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 7. Rotinas Intr´
ınsecas

7.6.2

69

Fun¸˜es de compara¸˜o l´xica
co
ca e

As seguintes fun¸˜es elementais aceitam strings de caracteres da esp´cie padr˜o, realizam uma comparaco
e
a
¸˜o l´xica baseada na tabela ASCII e retornam um resultado l´gico da esp´cie padr˜o. Se as strings tiverem
ca e
o
e
a
comprimentos distintos, a mais curta ´ complementada com espa¸os em branco.
e
c
LGE(STRING_A,STRING_B). Retorna o valor .TRUE. se STRING_A segue STRING_B na seq¨ˆncia estabelecida
ue
pela tabela ASCII, ou a iguala. O resultado ´ .FALSE. em caso contr´rio.
e
a
LGT(STRING_A,STRING_B). Retorna o valor .TRUE. se STRING_A segue STRING_B na seq¨ˆncia estabelecida
ue
pela tabela ASCII. O resultado ´ .FALSE. em caso contr´rio.
e
a
LLE(STRING_A,STRING_B). Retorna o valor .TRUE. se STRING_A precede STRING_B na seq¨ˆncia estabeleue
cida pela tabela ASCII, ou a iguala. O resultado ´ .FALSE. em caso contr´rio.
e
a
LLT(STRING_A,STRING_B). Retorna o valor .TRUE. se STRING_A precede STRING_B na seq¨ˆncia estabeleue
cida pela tabela ASCII. O resultado ´ .FALSE. em caso contr´rio.
e
a

7.6.3

Fun¸˜es elementais para manipula¸oes de strings
co
c˜

As seguintes s˜o fun¸˜es elementais que manipulam strings. Os argumentos STRING, SUBSTRING e SET
a
co
s˜o sempre do tipo de caractere e, quando dois est˜o presentes, ambos devem ser da mesma esp´cie. O
a
a
e
resultado ´ da mesma esp´cie de STRING.
e
e
ADJUSTL(STRING). Ajusta uma string ` esquerda. Ou seja, remove os espa¸os em branco no in´ da string
a
c
ıcio
e coloca o mesmo n´mero de brancos no final da string.
u
ADJUSTR(STRING). Ajusta uma string ` direita. Ou seja, remove os espa¸os em branco no final da string e
a
c
coloca o mesmo n´mero de brancos no in´ da string.
u
ıcio
INDEX(STRING,SUBSTRING[,BACK]). Retorna um valor do tipo inteiro padr˜o, o qual consiste na posi¸˜o
a
ca
inicial de SUBSTRING como uma substring de STRING, ou zero se tal substring n˜o existe. Se BACK
a
(vari´vel l´gica) est´ ausente, ou se est´ presente com o valor .FALSE., a posi¸˜o inicial da primeira das
a
o
a
a
ca
substrings ´ retornada; o valor 1 ´ retornado se SUBSTRING tem comprimento zero. Se BACK est´ pree
e
a
sente com valor .TRUE., a posi¸˜o inicial da ultima das substrings ´ retornada; o valor LEN(STRING)+1
ca
´
e
´ retornado se SUBSTRING tem comprimento zero.
e
LEN_TRIM(STRING). Retorna um valor inteiro padr˜o correspondente ao comprimento de STRING, ignorando
a
espa¸os em branco no final do argumento.
c
SCAN(STRING,SET[,BACK]). Retorna um valor inteiro padr˜o correspondente ` posi¸˜o de um caractere de
a
a
ca
STRING que esteja em SET, ou zero se n˜o houver tal caractere. Se a vari´vel l´gica BACK est´ ausente,
a
a
o
a
ou presente com valor .FALSE., a posi¸˜o mais ` esquerda deste caractere ´ retornada. Se BACK est´
ca
a
e
a
presente com valor .TRUE., a posi¸˜o mais ` direita deste caractere ´ retornada.
ca
a
e
VERIFY(STRING,SET[,BACK]). Retorna o valor inteiro padr˜o 0 se cada caractere em STRING aparece em
a
SET, ou a posi¸˜o de um caractere de STRING que n˜o esteja em SET. Se a vari´vel l´gica BACK est´
ca
a
a
o
a
ausente, ou presente com valor .FALSE., a posi¸˜o mais ` esquerda de tal caractere ´ retornada. Se
ca
a
e
BACK est´ presente com valor .TRUE., a posi¸˜o mais ` direita de tal caractere ´ retornada.
a
ca
a
e

7.6.4

Convers˜o l´gica
a o

A fun¸˜o elemental a seguir converte de uma esp´cie do tipo l´gico em outra.
ca
e
o
LOGICAL(L[,KIND]). Retorna o valor l´gico idˆntico ao valor de L. A esp´cie do resultado ´ definida pelo
o
e
e
e
argumento opcional KIND, caso esteja presente, ou ´ da esp´cie padr˜o em caso contr´rio.
e
e
a
a

7.7
7.7.1

Fun¸˜es n˜o-elementais para manipula¸˜o de strings
co
a
ca
Fun¸˜o inquisidora para manipula¸˜o de strings
ca
ca

LEN(STRING). Trata-se de uma fun¸˜o inquisidora que retorna um valor inteiro padr˜o escalar que corresca
a
ponde ao n´mero de caracteres em STRING se esta ´ escalar ou de um elemento de STRING se a mesma
u
e
´ uma matriz. O valor de STRING n˜o precisa estar definido.
e
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
70

7.8. Fun¸˜es inquisidoras e de manipula¸˜es num´ricas
co
co
e

7.7.2

Fun¸˜es transformacionais para manipula¸˜o de strings
co
ca

Existem duas fun¸˜es que n˜o s˜o elementais porque o comprimento do resultado depende do valor de
co
a a
um argumento.
REPEAT(STRING,NCOPIES). Forma a string que consiste na concatena¸˜o de NCOPIES c´pias de STRING,
ca
o
onde NCOPIES ´ do tipo inteiro e seu valor n˜o deve ser negativo. Ambos argumentos devem ser
e
a
escalares.
TRIM(STRING). Retorna STRING com todos os espa¸os em branco no final da vari´vel removidos. STRING
c
a
deve ser escalar.

7.8

Fun¸˜es inquisidoras e de manipula¸˜es num´ricas
co
co
e

7.8.1

Modelos para dados inteiros e reais

As fun¸˜es inquisidoras e de manipula¸˜es num´ricas s˜o definidas em termos de modelos de representa¸˜o
co
co
e
a
ca
de n´meros inteiro e reais para cada esp´cie suportada pelo processador.
u
e
Para cada esp´cie do tipo inteiro, o modelo ´:
e
e
q

wk × rk−1 ,

i=s×

(7.1)

k=1

onde s = ±1, q ´ um inteiro positivo, r ´ um inteiro maior que um (usualmente 2) e cada valor de wk ´ um
e
e
e
inteiro no intervalo 0 ≤ wk < r.
Para cada esp´cie do tipo real, o modelo ´:
e
e
x=0
e

p

fk × b−k ,

e

x=s×b ×

(7.2)

k=1

onde s = ±1, p e b s˜o inteiros maiores que um, e ´ um inteiro no intervalo emin ≤ e ≤ emax e cada fk ´ um
a
e
e
inteiro no intervalo 0 ≤ fk < b, exceto f1 , que ´ n˜o nulo.
e a
Os valores de todos os parˆmetros nestes modelos s˜o escolhidos para o processador de tal forma que o
a
a
modelo melhor se ajuste ao hardware, desde que todos os n´meros sejam represent´veis.
u
a

7.8.2

Fun¸˜es num´ricas inquisidoras
co
e

H´ nove fun¸˜es inquisidoras que retornam valores para os modelos de dados associados com seus argua
co
mentos. Cada fun¸˜o tem um unico argumento que pode ser escalar ou matricial e todas retornam um valor
ca
´
escalar. O valor per se do argumento n˜o precisa ser definido, somente o seu tipo e esp´cie.
a
e
DIGITS(X). Para X real ou inteiro, retorna o inteiro padr˜o cujo valor ´ o n´mero de d´
a
e
u
ıgitos significantes
no modelo que inclui X; isto ´, retorna p para X real ou q para X inteiro.
e
EPSILON(X). Para X real, retorna um resultado real com o mesmo tipo de X e que ´ quase indisting¨´ do
e
uıvel
valor 1.0 no modelo que inclui X. Ou seja, a fun¸˜o calcula b1−p .
ca
HUGE(X). Para X real ou inteiro, retorna o maior valor represent´vel no modelo que inclui X. O resultado
a
possui o mesmo tipo e esp´cie de X. O valor ´
e
e
1 − b−p bemax
para X real ou
rq − 1
para X inteiro.
MAXEXPONENT(X). Para X real, retorna o inteiro padr˜o emax , ou seja, o expoente m´ximo no modelo que
a
a
inclui X.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 7. Rotinas Intr´
ınsecas

71

MINEXPONENT(X). Para X real, retorna o inteiro padr˜o emin , ou seja, o expoente m´
a
ınimo no modelo que
inclui X.
PRECISION(X). Para X real ou complexo, retorna um inteiro padr˜o que cont´m a precis˜o decimal equia
e
a
valente no modelo que representa n´meros reais da mesma esp´cie de X. O valor da fun¸˜o ´
u
e
ca e
INT((p − 1)) ∗ LOG10(b))+k, onde k ´ 1 se b ´ uma potˆncia inteira de 10 ou 0 em outro caso.
e
e
e
RADIX(X). Para X real ou inteiro, retorna o inteiro padr˜o que ´ a base no modelo que inclui X. Isto ´,
a
e
e
retorna b para X real ou r para X inteiro.
RANGE(X). Para X inteiro, real ou complexo, retorna o inteiro padr˜o que cont´m o intervalo de expoentes
a
e
decimais nos modelos representando n´meros reais ou inteiro da mesma esp´cie de X. O valor da
u
e
fun¸˜o ´ INT(LOG10(huge)) para X inteiro e
ca e
INT(MIN(LOG10(huge), −LOG10(tiny)))
para X real, onde huge e tiny s˜o, respectivamente, o maior e o menor n´meros positivos nos modelos.
a
u
TINY(X). Para X real, retorna o menor n´mero positivo,
u
bemin −1
no modelo que inclui X. O resultado ´ do mesmo tipo e esp´cie de X.
e
e

7.8.3

Fun¸˜es elementais que manipulam quantidades reais
co

H´ sete fun¸˜es elementais cujo primeiro ou unico argumento ´ do tipo real e que retorna valores relacia
co
´
e
onados aos componentes dos modelos de valores associados ao valor do argumento.
EXPONENT(X). Retorna o inteiro padr˜o cujo valor ´ a parte de expoente e de X quando representado como
a
e
um n´mero de modelo. Se X=0, o resultado tamb´m ´ nulo.
u
e e
FRACTION(X). Retorna uma quantidade real da mesma esp´cie que X e cujo valor ´ a parte fracion´ria de X
e
e
a
quando representado como um n´mero de modelo; isto ´, a fun¸˜o retorna Xb−e .
u
e
ca
NEAREST(X,S). Retorna uma quantidade real da mesma esp´cie que X e cujo valor ´ o n´mero distinto mais
e
e
u
pr´ximo de X no sentido dado pelo sinal da quantidade real S. O valor de S n˜o pode ser nulo.
o
a
RRSPACING(X). Retorna uma quantidade real da mesma esp´cie que X cujo valor ´ a rec´
e
e
ıproca do espa¸ac
mento relativo dos n´meros de modelo pr´ximos a X; isto ´, a fun¸˜o retorna |Xb−e | bp .
u
o
e
ca
SCALE(X,I). Retorna uma quantidade real da mesma esp´cie que X cujo valor ´ XbI , onde b ´ a base do
e
e
e
modelo para X e I ´ do tipo inteiro.
e
SET_EXPONENT(X,I). Retorna uma quantidade real da mesma esp´cie que X cuja parte fracion´ria ´ a parte
e
a e
fracion´ria da representa¸˜o de X e cuja parte exponencial ´ I; isto ´, a fun¸˜o retorna Xb1−e .
a
ca
e
e
ca
SPACING(X). Retorna uma quantidade real da mesma esp´cie que X cujo valor ´ o espa¸amento absoluto do
e
e
c
modelo de n´meros pr´ximos a X. O resultado ´ be−p se X ´ n˜o nulo e este resultado est´ dentro do
u
o
e
e a
a
intervalo de n´meros represent´veis. Caso contr´rio, a fun¸˜o retorna TINY(X).
u
a
a
ca

7.8.4

Fun¸˜es transformacionais para valores de esp´cie (kind)
co
e

H´ duas fun¸˜es que retornam o menor valor do parˆmetro de esp´cie que ir´ satisfazer um dado rea
co
a
e
a
querimento num´rico. As fun¸˜es tˆm argumentos e resultados escalares; por´m s˜o classificadas como
e
co
e
e
a
transformacionais. Estas fun¸˜es j´ foram discutidas na se¸˜o 3.7.3.
co a
ca
SELECTED_INT_KIND(R). Retorna o inteiro escalar padr˜o que ´ o valor do parˆmetro da esp´cie para um
a
e
a
e
dado do tipo inteiro capaz de representar todos os valor inteiros n no intervalo −10R < n < 10R , onde R
´ um inteiro escalar. Se mais de uma esp´cie for dispon´
e
e
ıvel, a esp´cie com menor intervalo exponencial
e
´ escolhida. Se nenhuma esp´cie ´ dispon´
e
e e
ıvel, o resultado ´ -1.
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
72

7.9. Rotinas de manipula¸˜o de bits
ca

SELECTED_REAL_KIND([P][,R]). Retorna o inteiro escalar padr˜o que ´ o valor do parˆmetro da esp´cie
a
e
a
e
para um dado do tipo real com precis˜o decimal (conforme retornada pela fun¸˜o PRECISION) no
a
ca
m´
ınimo igual a P e intervalo de expoente decimal (conforme retornado pela fun¸˜o RANGE) no m´
ca
ınimo
igual a R. Se mais de uma esp´cie for dispon´
e
ıvel, a esp´cie com a menor precis˜o decimal ´ escolhida.
e
a
e
Tanto P quanto R s˜o inteiros escalares; pelo menos um destes deve estar presente. Se n˜o houver
a
a
esp´cie dispon´
e
ıvel, o resultado ´:
e
-1: se a precis˜o requerida n˜o for dispon´
a
a
ıvel;
-2: se um intervalo de expoente grande o suficiente n˜o for dispon´
a
ıvel;
-3: se ambos n˜o forem dispon´
a
ıveis.

7.9

Rotinas de manipula¸˜o de bits
ca

H´ onze rotinas para manipular bits contidos em quantidades inteiras. Estas rotinas s˜o elementais,
a
a
quando apropriado. As rotinas s˜o baseadas em um modelo no qual um valor inteiro ´ representado por s
a
e
bits wk , com k = 0, 1, . . . , s − 1, em uma seq¨ˆncia da direita para a esquerda, baseada no valor n˜o-negativo
ue
a
s−1

wk × 2k .
k=0

Este modelo ´ v´lido somente no contexto destas rotinas intr´
e a
ınsecas e ´ idˆntico ao modelo de n´meros
e e
u
inteiros (7.1) quando r ´ uma potˆncia inteira de 2 e ws−1 = 0; mas quando ws−1 = 1 os modelos diferem.
e
e

7.9.1

Fun¸˜o inquisidora
ca

BIT_SIZE(I). Retorna o n´mero de bits no modelo para bits dentro de um inteiro da mesma esp´cie que
u
e
I. O resultado ´ um inteiro escalar da mesma esp´cie que I.
e
e

7.9.2

Fun¸˜es elementais
co

BTEST(I,POS). Retorna o valor l´gico da esp´cie padr˜o .TRUE. se o bit POS do inteiro I tem valor 1 e retorna
o
e
a
.FALSE. em outra situa¸˜o. POS deve ser um inteiro com valor no intervalo 0 ≤ POS < BIT SIZE(I).
ca
IAND(I,J). Retorna o l´gico AND de todos os bits em I e bits correspondentes em J, de acordo com a
o
tabela-verdade
I
1100
J
1010
I AND(I, J) 1 0 0 0
I e J devem ser do mesmo tipo; o resultado tamb´m ser´ do mesmo tipo.
e
a
IBCLR(I,POS). Retorna um inteiro do mesmo tipo que I e valor igual ao de I exceto que o bit POS ´ levado
e
a 0. POS deve ser um inteiro com valor no intervalo 0 ≤ POS < BIT SIZE(I).
IBITS(I,POS,LEN). Retorna um inteiro do mesmo tipo que I e valor igual aos LEN bits de I iniciando no
bit POS ajustado ` direita e com todos os outros bits iguais a 0. POS e LEN devem ser inteiros positivos
a
tais que POS + LEN ≤ BIT SIZE(I).
IBSET(I,POS). Retorna um inteiro do mesmo tipo que I e valor igual ao de I exceto que o bit POS ´ levado
e
a 1. POS deve ser um inteiro com valor no intervalo 0 ≤ POS < BIT SIZE(I).
IEOR(I,J). Retorna o OU l´gico exclusivo de todos os bits de I e correspondentes bits em J, de acordo com
o
a tabela-verdade
I
1100
J
1010
I EOR(I, J) 0 1 1 0
I e J devem ser do mesmo tipo; o resultado tamb´m ser´ do mesmo tipo.
e
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 7. Rotinas Intr´
ınsecas

73

IOR(I,J). Retorna o OU l´gico inclusivo de todos os bits de I e correspondentes bits em J, de acordo com
o
a tabela-verdade
I
1100
J
1010
I IOR(I, J) 1 1 1 0
I e J devem ser do mesmo tipo; o resultado tamb´m ser´ do mesmo tipo.
e
a
ISHFT(I,SHIFT). Retorna um inteiro do mesmo tipo que I e valor igual ao de I exceto que os bits s˜o
a
deslocados SHIFT posi¸˜es para a esquerda (-ISHIFT desloca para a direita se SHIFT for positivo).
co
Zeros s˜o inseridos a partir da extremidade oposta. SHIFT deve ser um inteiro com valor que satisfaz
a
a inegualdade |SHIFT| ≤ BIT SIZE(I).
ISHFTC(I,SHIFT[,SIZE]). Retorna um inteiro do mesmo tipo que I e valor igual ao de I exceto que os
SIZE bits mais ` direita (ou todos os bits se SIZE for ausente) s˜o deslocados de forma circular SHIFT
a
a
posi¸˜es para a esquerda (-ISHIFT desloca para a direita se SHIFT for positivo). Zeros s˜o inseridos
co
a
a partir da extremidade oposta. SHIFT deve ser um inteiro com valor que n˜o excede o valor de SIZE
a
ou BIT_SIZE(I), se SIZE estiver ausente.
NOT(I). Retorna o complemento l´gico de todos os bits em I, de acordo com a tabela-verdade
o
I
01
NOT(I) 1 0

7.9.3

Subrotina elemental

MVBITS(FROM,FROMPOS,LEN,TO,TOPOS). Copia a seq¨ˆncia de bits em FROM que inicia na posi¸˜o FROMPOS
ue
ca
e tem comprimento LEN para TO, iniciando na posi¸˜o TOPOS. Os outros bits de TO permanecem
ca
inalterados. FROM, FROMPOS, LEN e TOPOS s˜o todos inteiros com intent IN e devem ter valores que
a
satisfazem as inegualdades: LEN ≥ 0, FROMPOS+LEN ≤ BIT_SIZE(FROM), FROMPOS ≥ 0, TOPOS ≥ 0 e
TOPOS+LEN ≤ BIT_SIZE(TO). TO ´ um inteiro com intent INOUT; ele deve ser da mesma esp´cie que
e
e
FROM. A mesma vari´vel pode ser especificada para FROM e TO.
a

7.10

Fun¸˜o de transferˆncia
ca
e

A fun¸˜o de transferˆncia permite que dados de um tipo sejam transferidos a outro tipo sem que a
ca
e
representa¸˜o f´
ca ısica dos mesmos seja alterada. Esta fun¸˜o pode ser util, por exemplo, ao se escrever um
ca
´
sistema de armazenamento e recupera¸˜o de dados; o sistema pode ser escrito para uma dado tipo, por
ca
exemplo, inteiro, e os outros tipos s˜o obtidos atrav´s de transferˆncias de e para este tipo.
a
e
e
TRANSFER(SOURCE,MOLD[,SIZE]). Retorna um valor do tipo e esp´cie de MOLD. Quando SIZE estiver aue
sente, o resultado ´ escalar se MOLD for escalar e ´ de posto 1 e tamanho suficiente para armazenar toda
e
e
a SOURCE se MOLD for uma matriz. Quando SIZE estiver presente, o resultado ´ de posto 1 e tamanho
e
SIZE. Se a representa¸˜o f´
ca ısica do resultado ´ t˜o ou mais longa que o tamanho de SOURCE, o resultado
e a
cont´m SOURCE como sua parte inicial e o resto ´ indefinido; em outros casos, o resultado ´ a parte
e
e
e
inicial de SOURCE. Como o posto do resultado depende se SIZE ´ ou n˜o especificado, o argumento em
e
a
si n˜o pode ser um argumento opcional.
a

7.11

Fun¸oes de multiplica¸˜o vetorial ou matricial
c˜
ca

H´ duas fun¸˜es transformacionais que realizam multiplica¸˜es vetorial ou matricial. Elas possuem dois
a
co
co
argumentos que s˜o ambos de um tipo num´rico (inteiro, real ou complexo) ou ambas do tipo l´gico. O
a
e
o
resultado ´ do mesmo tipo e esp´cie como seria resultante das opera¸˜es de multiplica¸˜o ou .AND. entre
e
e
co
ca
dois escalares. As fun¸˜es SUM e ANY, usadas nas defini¸˜es abaixo, s˜o definidas na se¸˜o 7.12.1 abaixo.
co
co
a
ca
DOT_PRODUCT(VETOR_A,VETOR_B). Requer dois argumentos, ambos de posto 1 e do mesmo tamanho. Se
VETOR_A ´ dos tipos inteiro ou real, a fun¸˜o retorna SUM(VETOR_A*VETOR_B); se VETOR_A ´ do tipo
e
ca
e
complexo, a fun¸˜o retorna SUM(CONJG(VETOR_A)*VETOR_B); e se VETOR_A ´ do tipo l´gico, a fun¸˜o
ca
e
o
ca
retorna ANY(VETOR_A .AND. VETOR_B).
MATMUL(MATRIZ_A,MATRIZ_B). Realiza a multiplica¸˜o escalar. Para argumentos num´ricos, trˆs casos s˜o
ca
e
e
a
poss´
ıveis:
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
74

7.12. Fun¸˜es transformacionais que reduzem matrizes
co
1. MATRIZ_A tem forma (/n,m/) e MATRIZ_B tem forma (/m,k/). O resultado tem forma (/n,k/)
e o elemento (i, j) tem o valor dado por SUM(MATRIZ_A(I,:)*MATRIZ_B(:,J)).
2. MATRIZ_A tem forma (/m/) e MATRIZ_B tem forma (/m,k/). O resultado tem forma (/k/) e o
elemento j tem o valor dado por SUM(MATRI_A*MATRIZ_B(:,J)).
3. MATRIZ_A tem forma (/n,m/) e MATRIZ_B tem forma (/m/). O resultado tem forma (/n/) e o
elemento i tem o valor dado por SUM(MATRIZ_A(I,:)*MATRIZ_B).
Para argumentos l´gicos, as formas s˜o as mesmas que para argumentos num´ricos e os valores s˜o
o
a
e
a
determinados pela substitui¸˜o da fun¸˜o SUM e do operador “*” pela fun¸˜o ANY e pelo operador .AND..
ca
ca
ca

7.12

Fun¸oes transformacionais que reduzem matrizes
c˜

H´ sete fun¸˜es transformacionais que executam opera¸˜es em matrizes, tais como somar seus elementos.
a
co
co

7.12.1

Caso de argumento unico
´

Nas suas formas mais simples, estas fun¸˜es tˆm um unico argumento matricial e o resultado ´ um valor
co
e
´
e
escalar. Todas, exceto COUNT tem o resultado do mesmo tipo e esp´cie que o argumento.
e
ALL(MASK). Retorna o valor .TRUE. se todos os elementos da matriz l´gica MASK forem verdadeiros ou se
o
MASK for nula; caso contr´rio, retorna o valor .FALSE.
a
ANY(MASK). Retorna o valor .TRUE. se algum dos elementos da matriz l´gica MASK for verdadeiro e o valor
o
.FALSE. se todos os elementos forem falsos ou se a matriz for nula.
COUNT(MASK). Retorna o valor inteiro padr˜o igual ao n´mero de elementos da matriz MASK que tˆm o valor
a
u
e
.TRUE.
MAXVAL(ARRAY). Retorna o valor m´ximo dentre os elementos da matriz ARRAY, a qual pode ser inteira
a
ou real. Se ARRAY for nula, a fun¸˜o retorna o valor negativo de maior magnitude suportado pelo
ca
processador.
MINVAL(ARRAY). Retorna o valor m´
ınimo dentre os elementos da matriz ARRAY, a qual pode ser inteira
ou real. Se ARRAY for nula, a fun¸˜o retorna o valor positivo de maior magnitude suportado pelo
ca
processador.
PRODUCT(ARRAY). Retorna o produto de todos os elementos de uma matriz inteira, real ou complexa. A
fun¸˜o retorna o valor 1 se ARRAY for nula.
ca
SUM(ARRAY). Retorna a soma de todos os elementos de uma matriz inteira, real ou complexa. A fun¸˜o
ca
retorna o valor 0 se ARRAY for nula.

7.12.2

Argumento opcional DIM

Todas as fun¸˜es acima tˆm um segundo argumento opcional DIM, o qual ´ um inteiro escalar. Se
co
e
e
este argumento est´ presente, a opera¸˜o ´ aplicada a todas as se¸˜es de posto 1 que varrem atrav´s da
a
ca e
co
e
dimens˜o DIM para produzir uma matriz de posto reduzido por um e extens˜es iguais `s extens˜es nas outras
a
o
a
o
dimens˜es. Por exemplo, se A ´ uma matriz real de forma (/4,5,6/), SUM(A,DIM=2) ´ uma matriz real de
o
e
e
forma (/4,6/) e o seu elemento (i, j) tem o valor dado por SUM(A(I,:,J)).

7.12.3

Argumento opcional MASK

As fun¸˜es MAXVAL, MINVAL, PRODUCT e SUM tˆm um terceiro argumento opcional; uma matriz l´gica
co
e
o
MASK. Se esta matriz estiver presente, ela deve ter a mesma forma que o primeiro argumento e a opera¸˜o
ca
´ aplicada aos elementos do primeiro argumento correspondentes aos elementos verdadeiros de MASK. Por
e
exemplo, SUM(A, MASK= A>0) soma todos os elementos positivos da matriz A. O argumento MASK afeta
somente o valor da fun¸˜o e n˜o afeta o desenvolvimento de argumentos que s˜o express˜es matriciais.
ca
a
a
o
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 7. Rotinas Intr´
ınsecas

7.13

75

Fun¸oes inquisidoras de matrizes
c˜

H´ cinco fun¸˜es que inquirem sobre os limites, forma, tamanho e status de aloca¸˜o de uma matriz de
a
co
ca
qualquer tipo. Uma vez que o resultado depende somente nas propriedades da matriz, o valor desta n˜o
a
necessita ser definido.

7.13.1

Status de aloca¸˜o
ca

ALLOCATED(ARRAY). Retorna, quando a matriz aloc´vel ARRAY est´ correntemente alocada, o valor .TRUE.;
a
a
na outra situa¸˜o, o valor .FALSE. ´ retornado. Se os status da aloca¸˜o ´ indefinido, o resultado
ca
e
ca e
tamb´m ´ indefinido.
e e

7.13.2

Limites, forma e tamanho

As fun¸˜es a seguir inquirem sobre as propriedades de uma matriz. No caso de uma matriz aloc´vel,
co
a
esta deve estar alocada. No caso de um ponteiro (pointer), ele deve estar associado a um alvo (target).
Uma se¸˜o de matriz ou uma express˜o matricial ´ assumida ter limite inferior 1 e limite superior igual `s
ca
a
e
a
extens˜es.
o
LBOUND(ARRAY[,DIM]). Quando DIM ´ ausente, retorna uma matriz inteira padr˜o de posto um, a qual
e
a
cont´m os limites inferiores. Quando DIM ´ presente, este deve ser um inteiro escalar e o resultado ´
e
e
e
um escalar inteiro padr˜o com o valor do limite inferior na dimens˜o DIM. Como o posto do resultado
a
a
depende da presen¸a de DIM, o argumento da fun¸˜o n˜o pode ser, por sua vez, um argumento mudo
c
ca a
opcional.
SHAPE(SOURCE). Retorna um vetor inteiro padr˜o contendo a forma da matriz ou escalar SOURCE. No caso
a
de um escalar, o resultado tem tamanho zero.
SIZE(ARRAY[,DIM]). Retorna um escalar inteiro padr˜o igual ao tamanho da matriz ARRAY ou a extens˜o
a
a
ao longo da dimens˜o DIM, caso este argumento esteja presente.
a
UBOUND(ARRAY[,DIM]). Similar a LBOUND exceto que retorna limites superiores.

7.14

Fun¸oes de constru¸˜o e manipula¸˜o de matrizes
c˜
ca
ca

H´ oito fun¸˜es que constroem ou manipulam matrizes de qualquer tipo.
a
co

7.14.1

Fun¸˜o elemental MERGE
ca

MERGE(TSOURCE,FSOURCE,MASK). Trata-se de uma fun¸˜o elemental. TSOURCE pode ter qualquer tipo e
ca
FSOURCE deve ser do mesmo tipo e esp´cie. MASK deve ser do tipo l´gico. O resultado ´ TSOURCE se
e
o
e
MASK ´ verdadeiro ou FSOURCE no contr´rio.
e
a

7.14.2

Agrupando e desagrupando matrizes

A fun¸˜o transformacional PACK agrupa dentro de um vetor aqueles elemento de uma matriz que s˜o
ca
a
selecionados por uma matriz l´gica conforme e a fun¸˜o transformacional UNPACK executa a opera¸˜o reversa.
o
ca
ca
Os elementos s˜o tomados na ordem dos elementos das matrizes.
a
PACK(ARRAY,MASK[,VECTOR]). Quando VECTOR ´ ausente, retorna um vetor contendo os elementos de ARRAY
e
correspondentes aos valores verdadeiros de MASK na ordem dos elementos das matrizes. MASK pode ser
um escalar de valor .TRUE.; em cujo caso, todos os elementos s˜o selecionados. Se VECTOR ´ presente,
a
e
este deve ser um vetor do mesmo tipo e esp´cie de ARRAY e tamanho no m´
e
ınimo igual ao n´mero t de
u
elementos selecionados. O resultado, neste caso, tem tamanho igual ao tamanho n do VECTOR; se t <
n, elementos i do resultado para i > t s˜o os elementos correspondentes de VECTOR.
a
UNPACK(VECTOR,MASK,FIELD). Retorna uma matriz do tipo e esp´cie de VECTOR e da forma de MASK. MASK
e
deve ser uma matriz l´gica e VECTOR deve ser um vetor de tamanho no m´
o
ınimo igual ao n´mero de
u
elementos verdadeiros de MASK. FIELD deve ser do mesmo tipo e esp´cie de VECTOR e deve ou ser
e
escalar ou ter a mesma forma que MASK. O elemento do resultado correspondendo ao i -´simo elemento
e
verdadeiro de MASK, na ordem dos elementos da matriz, ´ o i -´simo elemento de VECTOR; todos os
e
e
outros s˜o iguais aos correspondentes elementos de FIELD se este for uma matriz ou igual a FIELD se
a
este for um escalar.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
76

7.15. Fun¸˜es transformacionais para localiza¸˜o geom´trica
co
ca
e

7.14.3

Alterando a forma de uma matriz

A fun¸˜o transformacional RESHAPE permite que a forma de uma matriz seja alterada, com a poss´
ca
ıvel
permuta¸˜o dos ´
ca
ındices.
RESHAPE(SOURCE,SHAPE[,PAD][,ORDER]). Retorna uma matriz com forma dada pelo vetor inteiro SHAPE e
tipo e esp´cie iguais aos da matriz SOURCE. O tamanho de SHAPE deve ser constante e seus elementos
e
n˜o podem ser negativos. Se PAD est´ presente, esta deve ser uma matriz do mesmo tipo e esp´cie
a
a
e
de SOURCE. Se PAD estiver ausente ou for uma matriz de tamanho zero, o tamanho do resultado n˜o
a
deve exceder o tamanho de SOURCE. Se ORDER estiver ausente, os elementos da matriz resultante,
arranjados na ordem de elementos de matrizes (se¸˜o 6.6.2), s˜o os elementos de SOURCE, seguidos
ca
a
por c´pias de PAD, tamb´m na ordem de elementos de matrizes. Se ORDER estiver presente, este deve
o
e
ser um vetor inteiro com um valor que ´ uma permuta¸˜o de (1, 2, ..., n); os elementos R(s1 , . . . , sn )
e
ca
do resultado, tomados na ordem dos ´
ındices para a matriz tendo elementos R(sordem(1) , . . . , sordem(n) ),
s˜o aqueles de SOURCE na ordem de elementos de matriz seguidos por c´pias de PAD, tamb´m na
a
o
e
ordem de elementos de matriz. Por exemplo, se ORDER tem o valor (/3,1,2/), os elementos R(1,1,1),
R(1,1,2), ..., R(1,1,k ), R(2,1,1), R(2,1,2), ... correspondem aos elementos de SOURCE e PAD na
ordem de elementos de matriz.

7.14.4

Fun¸˜o transformacional para duplica¸˜o
ca
ca

SPREAD(SOURCE,DIM,NCOPIES). Retorna uma matriz do tipo e esp´cie de SOURCE e de posto acrescido por
e
um. SOURCE pode ser escalar ou matriz. DIM e NCOPIES s˜o inteiros escalares. O resultado cont´m
a
e
MAX(NCOPIES,0) c´pias de SOURCE e o elemento (r1 , . . . , rn+1 ) do resultado ´ SOURCE(s1 , . . . , sn ), onde
o
e
(s1 , . . . , sn ) ´ (r1 , . . . , rn+1 ) com subscrito DIM omitido (ou a pr´pria SOURCE se esta for um escalar).
e
o

7.14.5

Fun¸oes de deslocamento matricial
c˜

CSHIFT(ARRAY,SHIFT[,DIM]). Retorna uma matriz do mesmo tipo, esp´cie e forma de ARRAY. DIM ´ um
e
e
escalar inteiro. Se DIM for omitido, o seu valor ser´ assumido igual a 1. SHIFT ´ do tipo inteiro e deve
a
e
ser um escalar se ARRAY tiver posto um. Se SHIFT ´ escalar, o resultado ´ obtido deslocando-se toda
e
e
se¸˜o vetorial que se estende ao longo da dimens˜o DIM de forma circular SHIFT vezes. O sentido do
ca
a
deslocamento depende do sinal de SHIFT e pode ser determinado a partir do caso com SHIFT= 1 e
ARRAY de posto um e tamanho m, quando o elemento i do resultado ´ ARRAY(i + 1), i= 1, 2, ..., m-1 e
e
o elemento m ´ ARRAY(1). Se SHIFT for uma matriz, esta deve ter a forma de ARRAY com a dimens˜o
e
a
DIM omitida; desta forma, SHIFT oferece um valor distinto para cada deslocamento.
´ e
EOSHIFT(ARRAY,SHIFT[,BOUNDARY][,DIM]). E idˆntica a CSHIFT, exceto que um deslocamento final ´ exee
cutado e valores de borda s˜o inseridos nas lacunas assim criadas. BOUNDARY pode ser omitida quando
a
ARRAY tiver tipo intr´
ınsecos, em cujo caso o valor zero ´ inserido para os casos inteiro, real e complexo;
e
.FALSE. no caso l´gico e brancos no caso de caracteres. Se BOUNDARY estiver presente, deve ser do
o
mesmo tipo e esp´cie de ARRAY; ele pode ser um escalar e prover todos os valores necess´rios ou pode
e
a
ser uma matriz cuja forma ´ a de ARRAY com dimens˜o DIM omitida e prover um valor separado para
e
a
cada deslocamento.

7.14.6

Transposta de uma matriz

A fun¸˜o TRANSPOSE executa a transposi¸ao matricial para qualquer matriz de posto dois.
ca
c˜
TRANSPOSE(MATRIX). Retorna uma matriz do mesmo tipo e esp´cie da matriz de posto dois MATRIX. Elee
mento (i,j ) do resultado ´ igual a MATRIX(i,j ).
e

7.15

Fun¸oes transformacionais para localiza¸˜o geom´trica
c˜
ca
e

H´ duas fun¸˜es transformacionais que localizam as posi¸˜es dos valores m´ximos e m´
a
co
co
a
ınimos de uma
matriz inteira ou real.
MAXLOC(ARRAY,DIM[,MASK]) ou MAXLOC(ARRAY[,MASK]). Retorna um vetor inteiro padr˜o de tamanho
a
igual ao posto de ARRAY. Seu valor ´ a seq¨ˆncia de subscritos de um elemento de valor m´ximo (dentre
e
ue
a
aqueles correspondentes aos elementos de valor .TRUE. da matriz l´gica MASK, caso esta exista), como
o
se todos os limites inferiores de ARRAY fossem iguais a 1. Se houver mais de um elemento com o mesmo
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 7. Rotinas Intr´
ınsecas

77

valor m´ximo, o primeiro na ordem de elementos de matriz ´ assumido. Caso o argumento DIM esteja
a
e
presente, este ´ um escalar inteiro padr˜o que indica a dimens˜o ao longo da qual o valor m´ximo deve
e
a
a
a
ser procurado. O compilador pode disting¨ir sem aux´ caso o segundo argumento seja DIM ou MASK
u
ılio
pelo fato de que o tipo de vari´vel ´ distinto.
a
e
MINLOC(ARRAY,DIM[,MASK]) ou MAXLOC(ARRAY[,MASK]). Retorna um vetor inteiro padr˜o de tamanho
a
igual ao posto de ARRAY. Seu valor ´ a seq¨ˆncia de subscritos de um elemento de valor m´
e
ue
ınimo (dentre
aqueles correspondentes aos elementos de valor .TRUE. da matriz l´gica MASK, caso esta exista), como
o
se todos os limites inferiores de ARRAY fossem iguais a 1. Se houver mais de um elemento com o mesmo
valor m´
ınimo, o primeiro na ordem de elementos de matriz ´ assumido.
e

7.16

Fun¸˜o transformacional para dissocia¸˜o de ponteiro
ca
ca

Em Fortran 95, a fun¸˜o NULL est´ dispon´ para fornecer status de dissociado a ponteiros.
ca
a
ıvel
NULL([MOLDE]). Retorna um pointer dissociado. O argumento MOLDE ´ um ponteiro de qualquer tipo e que
e
pode ter qualquer status, inclusive de indefinido. O tipo, esp´cie e posto do resultado s˜o aqueles
e
a
de MOLDE se ele est´ presente; em caso contr´rio, s˜o aqueles do objeto com o qual o ponteiro est´
a
a
a
a
associado.

7.17

Subrotinas intr´
ınsecas n˜o-elementais
a

H´ cinco subrotinas intr´
a
ınsecas n˜o elementais, as quais foram escolhidas ser subrotinas no lugar de
a
fun¸˜es devido ` necessidade destas retornarem diversas informa¸˜es atrav´s de seus argumentos.
co
a
co
e

7.17.1

Rel´gio de tempo real
o

H´ duas subrotinas que retornam informa¸˜o acerca do rel´gio de tempo real; a primeiro ´ baseada no
a
ca
o
e
padr˜o ISO 8601 (Representa¸˜o de datas e tempos). Assume-se que exista um rel´gio b´sico no sistema
a
ca
o
a
que ´ incrementado por um para cada contagem de tempo at´ que um valor m´ximo COUNT_MAX ´ alcan¸ado
e
e
a
e
c
e da´ na pr´xima contagem de tempo, este ´ zerado. Valores padronizados s˜o retornados em sistemas sem
ı,
o
e
a
rel´gio. Todos os argumentos tˆm inten¸˜o OUT (se¸˜o 8.2.5). Adicionalmente, h´ uma subrotina que acessa
o
e
ca
ca
a
o rel´gio interno do processador.
o
Acesso a qualquer argumento opcional pode ser realizado atrav´s do uso das palavras-chave (se¸˜es 8.2.8
e
co
e 8.2.9).
CALL DATE_AND_TIME([DATE][,TIME][,ZONE][,VALUES]). Retorna os seguintes valores (com valores-padr˜o
a
nulos ou -HUGE(0), conforme apropriado, caso n˜o haja rel´gio):
a
o
DATE ´ uma vari´vel escalar de caractere da esp´cie padr˜o que cont´m a data na forma ccyymmdd,
e
a
e
a
e
correspondendo ao s´culo, ano, mˆs e dia, respectivamente.
e
e
TIME ´ uma vari´vel escalar de caractere padr˜o que cont´m o tempo na forma hhmmss.sss, correse
a
a
e
pondendo a horas, minutos, segundos e milisegundos, respectivamente.
ZONE ´ uma vari´vel escalar de caractere padr˜o que ´ fixada como a diferen¸a entre o tempo local e
e
a
a
e
c
o Tempo Coordenado Universal (UTC, de Coordinated Universal Time, tamb´m conhecido como
e
Tempo M´dio de Greenwich, ou Greenwich Mean Time) na forma Shhmm, correspondendo ao
e
sinal, horas e minutos, respectivamente. Por exemplo, a hora local de Bras´ corresponde a UTC=
ılia
-0300.
VALUES ´ um vetor inteiro padr˜o que cont´m a seguinte seq¨ˆncia de valores: o ano, o mˆs do ano,
e
a
e
ue
e
o dia do mˆs, a diferen¸a temporal em minutos com rela¸˜o ao UTC, a hora do dia, os minutos
e
c
ca
da hora, os segundos do minuto e os milisegundos do segundo.
CALL SYSTEM_CLOCK([COUNT][,COUNT_RATE][,COUNT_MAX]). Retorna o seguinte:
COUNT ´ uma vari´vel escalar inteira padr˜o que cont´m o valor, dependente do processador, que
e
a
a
e
correspondem ao valor corrente do rel´gio do processador, ou -HUGE(0) caso n˜o haja rel´gio.
o
a
o
Na primeira chamada da subrotina, o processador pode fixar um valor inicial igual a zero.
COUNT_RATE ´ uma vari´vel escalar inteira padr˜o que cont´m o n´mero de contagens por segundo do
e
a
a
e
u
rel´gio, ou zero caso n˜o haja rel´gio.
o
a
o
COUNT_MAX ´ uma vari´vel escalar inteira padr˜o que cont´m o valor m´ximo que COUNT pode assumir,
e
a
a
e
a
ou zero caso n˜o haja rel´gio.
a
o
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
78

7.17. Subrotinas intr´
ınsecas n˜o-elementais
a

7.17.2

Tempo da CPU

Em Fortran 95, h´ uma subrotina intr´
a
ınseca n˜o-elemental que retorna o tempo do processador.
a
CALL CPU_TIME(TIME). Retorna o seguinte:
TIME ´ uma vari´vel real escalar padr˜o ` qual ´ atribu´ uma aproxima¸˜o (dependente de procese
a
a a
e
ıda
ca
sador) do tempo do processador em segundos, ou um valor negativo (dependente de processador)
caso n˜o haja rel´gio.
a
o

7.17.3

N´ meros aleat´rios
u
o

Uma seq¨ˆncia de n´meros pseudo-aleat´rios ´ gerada a partir de uma semente que ´ fornecida como um
ue
u
o
e
e
vetor de n´meros inteiros. A subrotina RANDOM_NUMBER retorna os n´meros pseudo-aleat´rios e a subrotina
u
u
o
RANDOM_SEED permite que uma inquiri¸˜o seja feita a respeito do tamanho ou valor do vetor-semente e, ent˜o,
ca
a
redefinir o mesmo. As subrotinas fornecem uma interface a uma seq¨ˆncia que depende do processador.
ue
CALL RANDOM_NUMBER(COLHE) Retorna um n´mero pseudo-aleat´rio a partir da distribui¸˜o uniforme de
u
o
ca
n´meros no intervalo 0 ≤ x < 1 ou um vetor destes n´meros. COLHE tem inten¸˜o OUT, pode ser um
u
u
ca
escalar ou vetor e deve ser do tipo real.
CALL RANDOM_SEED([SIZE][,PUT][,GET]). Tem os argumentos abaixo. N˜o mais de um argumento pode
a
ser especificado; caso nenhum argumento seja fornecido, a semente ´ fixada a um valor dependente do
e
processador.
SIZE tem inten¸˜o OUT e ´ um inteiro escalar padr˜o que o processador fixa com o tamanho n do
ca
e
a
vetor-semente.
PUT tem inten¸˜o IN e ´ um vetor inteiro padr˜o de tamanho n que ´ usado pelo processador para
ca
e
a
e
fixar uma nova semente. Um processador pode fixar o mesmo valor de semente para mais de um
valor de PUT.
GET tem inten¸˜o OUT e ´ um vetor inteiro padr˜o de tamanho n que o processador fixa como o valor
ca
e
a
atual da semente.

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8

Sub-Programas e M´dulos
o
Como foi visto nos cap´
ıtulos anteriores, ´ poss´ escrever um programa completo em Fortran em um
e
ıvel
unico arquivo, ou como uma unidade simples. Contudo, se o c´digo ´ suficientemente complexo, pode ser
´
o
e
necess´rio que um determinado conjunto de instru¸˜es seja realizado repetidas vezes, em pontos distintos
a
co
do programa. Um exemplo desta situa¸˜o seria a defini¸˜o de uma fun¸˜o extr´
ca
ca
ca
ınseca, ou seja, n˜o contida
a
no conjunto de fun¸˜es intr´
co
ınsecas discutidas no cap´
ıtulo 7. Neste caso, ´ melhor quebrar o programa em
e
unidades distintas.
Cada uma das unidades de programa corresponde a um conjunto completo e consistente de tarefas que
podem ser, idealmente, escritas, compiladas e testadas individualmente, sendo posteriormente inclu´
ıdas
no programa principal para gerar um arquivo execut´vel. Em Fortran h´ dois tipos de estruturas que se
a
a
encaixam nesta categoria: subrotinas e fun¸˜es (externas ou extr´
co
ınsecas).
Em Fortran 77, havia somente dois tipos de unidades de programas distintas:
ˆ Programa principal.
ˆ Rotinas externas.

Em Fortran 90/95, existem, ao todo, trˆs unidades distintas de programa:
e
ˆ Programa principal.
ˆ Rotinas externas.
ˆ M´dulos.
o

Cada uma destas unidades de programas ser˜o discutidas nas se¸˜es seguintes.
a
co
Neste cap´
ıtulo (e nos posteriores), os termos rotina (procedure) e sub-programa ser˜o usados alternadaa
mente para indicar de forma gen´rica tanto subrotinas quanto fun¸˜es. Outros textos podem vir a tratar
e
co
estes dois termos como representando entidades ligeiramente distintas.

8.1

Unidades de programa

Tanto em Fortran 77 quanto em Fortran 90/95, um c´digo execut´vel ´ criado a partir de um e somente
o
a
e
um programa principal, o qual pode invocar rotinas externas e, no caso do Fortran 90/95, pode usar tamb´m
e
m´dulos. A unica unidade de programa que deve necessariamente existir sempre ´ o programa principal.
o
´
e
Com a introdu¸˜o do Fortran 90/95, quaisquer uma destas trˆs unidades de programas podem tamb´m
ca
e
e
invocar rotinas internas, as quais tˆm estrutura semelhante `s rotinas externas, por´m n˜o podem ser
e
a
e
a
testadas isoladamente. Um diagrama ilustrativo das trˆs unidades de programas existentes no Fortran
e
90/95 pode ser visto na figura 8.1.
Uma descri¸˜o mais completa das unidades de programas ´ dada a seguir.
ca
e

8.1.1

Programa principal

Todo c´digo execut´vel deve ser composto a partir de um, e somente um, programa principal. Opcioo
a
nalmente, este pode invocar sub-programas. Um programa principal possui a seguinte forma:
79
80

8.1. Unidades de programa
Programa
Principal

Modulo

Rotina
Externa

Rotina de
Modulo
Rotina
Interna
Figura 8.1: As trˆs unidades de programa, as quais podem possuir tamb´m rotinas internas.
e
e

[PROGRAM <nome do programa>
[<declara¸~es de vari´veis>]
co
a
[<comandos execut´veis>]
a
[CONTAINS
<sub-programas internos>
END [PROGRAM [<nome do programa>]]
A declara¸˜o PROGRAM ´ opcional, por´m o seu uso ´ recomendado.1 O unico campo n˜o opcional na estrutura
ca
e
e
e
´
a
de um programa, na defini¸˜o do padr˜o da linguagem, ´ a instru¸˜o END, a qual possui dois prop´sitos:
ca
a
e
ca
o
indicar ao compilador que o programa chegou ao fim e, quando da execu¸˜o do c´digo, provoca a parada do
ca
o
mesmo.
Nos cap´
ıtulos anteriores, j´ foram dados v´rios exemplos da estrutura do programa principal e, portanto,
a
a
maiores detalhes n˜o s˜o necess´rios aqui.
a a
a
A declara¸˜o CONTAINS indica a presen¸a de um ou mais sub-programas internos. Estes ser˜o descritos
ca
c
a
em mais detalhes na se¸˜o 8.2.2. Se a execu¸˜o do ultimo comando anterior a CONTAINS n˜o provoca um
ca
ca
´
a
desvio de percurso na execu¸˜o do programa, atrav´s de uma instru¸˜o GO TO, por exemplo, o controle passa
ca
e
ca
por sobre os sub-programas internos ao comando END e o programa p´ra.
a
O comando END pode ser rotulado e ser ent˜o atingido por um desvio de execu¸˜o, como no exemplo
a
ca
...
GO TO 100
...
100 END PROGRAM
em cuja situa¸˜o o programa tamb´m termina. Contudo, este estilo de programa¸˜o ´ t´
ca
e
ca e ıpico do Fortran 77,
mas n˜o ´ recomendado pelo padr˜o do Fortran 90/95.
a e
a
O comando STOP. Outra forma de interromper a execu¸˜o do programa ´ atrav´s do comando STOP, o
ca
e
e
qual pode ser rotulado, pode ser parte de um comando ou construto IF e ´ um comando que pode aparecer
e
no programa principal ou em um sub-programa.
1 No

caso do compilador F, ´ obrigat´rio.
e
o

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

81

Caso haja v´rios comandos STOP em uma mesma unidade, estes podem ser disting¨idos por um c´digo
a
u
o
de acesso, que se trata de uma constante de caractere ou uma string de at´ 5 d´
e
ıgitos. Isto originar´ uma
a
mensagem na sa´ padr˜o indicando o ponto onde a execu¸˜o foi terminada. A seguir, dois exemplos deste
ıda
a
ca
caso:
STOP ’Dados incompletos.
STOP 12345

8.1.2

Programa interrompido.’

Rotinas externas

Rotinas externas s˜o chamadas de dentro de um programa principal ou de outra unidade, usualmente
a
com o intuito de executar uma tarefa bem definida dentro dos objetivos cumpridos pelo programa completo.
Rotinas externas s˜o escritas em arquivos distintos, separados do arquivo do programa principal.
a
Durante o processo de cria¸˜o do programa execut´vel, estas rotinas podem ser compiladas conjuntaca
a
mente com o programa principal ou em separado. Nesta ultima situa¸˜o, os programas objetos criados
´
ca
durante compila¸˜es pr´vias das rotinas externas s˜o linkados junto com o programa objeto do programa
co
e
a
principal. Embora seja poss´ colocar-se mais de uma rotina externa no mesmo arquivo, esta pr´tica n˜o
ıvel
a
a
´ recomendada.
e

8.1.3

M´dulos
o

O terceiro tipo de unidade de programa, exclusivo no Fortran 90/95, ´ o m´dulo. Trata-se de uma
e
o
maneira de se agrupar dados globais, tipos derivados e suas opera¸˜es associadas, blocos de interface, grupos
co
NAMELIST (se¸˜o 9.2) e rotinas internas. Tudo associado com uma determinada tarefa pode ser coletado
ca
dentro de um m´dulo e acessado quando necess´rio. Aquelas partes que s˜o restritas ao funcionamento
o
a
a
interno da tarefa e n˜o s˜o do interesse direto do programador podem ser feitas “invis´
a a
ıveis” a este, o que
permite que o funcionamento interno do m´dulo possa ser alterado sem a necessidade de alterar o programa
o
que o usa, prevenindo-se assim altera¸˜o acidental dos dados.
ca
Um m´dulo tem a seguinte forma:
o
MODULE <nome m´dulo>
o
<declara¸~es de vari´veis>
co
a
[CONTAINS
<rotinas de m´dulo>
o
END [MODULE [<nome m´dulo>]]
o
Assim como para END PROGRAM, ´ recomendado o uso da forma completa do comando END.
e
Uma discuss˜o mais extensa acerca dos m´dulos em Fortran 90/95 ser´ feita na se¸˜o 8.3.
a
o
a
ca

8.2

Sub-programas

sub-programas podem ser subrotinas ou fun¸˜es. Como j´ foi mencionado, tarefas que podem ser delico
a
mitadas por um n´mero finito de opera¸˜es e que devem ser realizadas repetidas vezes durante a execu¸˜o
u
co
ca
de um programa devem ser escritas como sub-programas.
Uma fun¸˜o retorna um unico valor, o qual pode ser um escalar ou uma matriz, e esta usualmente n˜o
ca
´
a
altera os valores de seus argumentos2 . Neste sentido, uma fun¸˜o em Fortran age como uma fun¸˜o em
ca
ca
an´lise matem´tica. J´ uma subrotina pode executar uma tarefa mais complexa e retornar diversos valores
a
a
a
atrav´s de seus argumentos, os quais podem ser modificados ao longo da computa¸˜o da subrotina.
e
ca

8.2.1

Fun¸˜es e subrotinas
co

Exceto pela declara¸˜o inicial, os sub-programas apresentam uma forma semelhante a de um programa
ca
principal. Um sub-programa pode ser uma subrotina:
[PURE] [ELEMENTAL] [RECURSIVE] SUBROUTINE <nome subrotina> [(<lista argumentos mudos>)]
[<declara¸~es de vari´veis>]
co
a
2 Situa¸˜es
co

onde este requisito pode ser relaxado e como estabelecer salvaguardas s˜o discutidas na se¸˜o 8.2.16.
a
ca

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
82

8.2. Sub-programas
[<comandos execut´veis>]
a
[CONTAINS
<sub-programas internos>]
END [SUBROUTINE [<nome subrotina>]]

ou pode ser uma fun¸˜o:
ca
[PURE] [ELEMENTAL] [<tipo>] [RECURSIVE] FUNCTION <nome fun¸~o> &
ca
(<lista argumentos mudos>)[RESULT (<nome resultado>)]
[<declara¸~es de vari´veis>]
co
a
[<comandos execut´veis>]
a
[CONTAINS
<sub-programas internos>]
END [FUNCTION [<nome fun¸~o>]]
ca
Os diversos constituintes das formas gerais apresentadas acima ser˜o discutidos em detalhes nas se¸˜es
a
co
seguintes. Por enquanto, ser˜o apresentados alguns dos atributos usualmente empregados no campo de
a
<declara¸~es de vari´veis> de um sub-programa. Al´m dos atributos j´ vistos, relacionados com as
co
a
e
a
declara¸˜es de tipo e esp´cie de vari´veis, dos atributos DIMENSION e ALLOCATABLE, os seguintes atributos
co
e
a
podem ser usados:
INTENT([IN][OUT][INOUT])
OPTIONAL
SAVE
EXTERNAL
INTRINSIC
POINTER
TARGET
A declara¸˜o CONTAINS cumpre exatamente o mesmo papel cumprido dentro do programa principal. O efeito
ca
do comando END em um sub-programa consiste em retornar o controle ` unidade que o chamou, ao inv´s
a
e
de interromper a execu¸˜o do programa. Aqui tamb´m recomenda-se o uso da forma completa do comando
ca
e
para deixar claro ao compilador e ao programador qual parte do programa est´ sendo terminada.
a
Uma fun¸˜o ´ ativada ou chamada de forma semelhante como se usa uma fun¸˜o em an´lise matem´tica.
ca e
ca
a
a
Por exemplo, dada a fun¸˜o BESSELJ(n,x), a qual calcula Jn (x), o valor da fun¸˜o de Bessel do primeiro
ca
ca
tipo de ordem n no ponto x. Esta fun¸˜o pode ser chamada para atribuir seu valor a uma vari´vel escalar
ca
a
ou a um elemento de matriz:
y= BESSELJ(n,x)
sendo que o tipo e esp´cie de y devem, em princ´
e
ıpio, concordar com o tipo e esp´cie do resultado de
e
BESSELJ(n,x). Contudo, caso isto n˜o ocorra, valem as regras de convers˜o definidas no cap´
a
a
ıtulo 4. Uma
fun¸˜o pode tamb´m fazer o papel de um operando em uma express˜o:
ca
e
a
y= BESSELJ(n,x) + 2*BESSELJ(n,x**2)
ou ainda servir de argumento para uma outra rotina.
Uma subrotina, devido ao fato de esta retornar, em geral, mais de um valor em cada chamada, n˜o pode
a
ser operada como uma fun¸˜o em an´lise matem´tica mas deve, isto sim, ser chamada atrav´s da instru¸˜o
ca
a
a
e
ca
CALL. Supondo que exista a subrotina BASCARA, a qual calcula as ra´
ızes de um polinˆmio de segundo grau,
o
x1 e x2, estas ser˜o obtidas atrav´s da chamada:
a
e
CALL BASCARA(A0,A1,A2,X1,X2)
onde os argumentos da subrotina ser˜o discutidos na se¸˜o 8.2.3 e posteriores. Por exemplo, ´ poss´
a
ca
e
ıvel
usar-se uma fun¸˜o como argumento da subrotina:
ca
CALL BASCARA(A0,A1,BESSELJ(n,x),x1,x2)
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

8.2.2

83

Rotinas internas

J´ foi observado nas se¸˜es anteriores que rotinas internas podem ser definidas dentro de quaisquer
a
co
unidades de programa. Uma rotina interna possui a seguinte estrutura:
[RECURSIVE] SUBROUTINE <nome subrotina> [(<lista argumentos mudos>)]
[<declara¸~es de vari´veis>]
co
a
[<comandos execut´veis>]
a
END SUBROUTINE [<nome subrotina>]]
ou
[<tipo>] [RECURSIVE] FUNCTION <nome fun¸~o> (<lista argumentos mudos>) &
ca
[RESULT (<nome resultado>)]
[<declara¸~es de vari´veis>]
co
a
[<comandos execut´veis>]
a
END FUNCTION [<nome fun¸~o>]]
ca
Nota-se agora que as declara¸˜es FUNCTION e SUBROUTINE agora s˜o obrigat´rias no comando END. Uma
co
a
o
determinada unidade de programa pode conter qualquer n´mero de rotinas internas, por´m estas, por sua
u
e
vez, n˜o podem conter outras rotinas internas.
a
Cabe aqui uma men¸˜o a respeito da diferen¸a entre uma rotina interna e uma rotina de m´dulo. Esta
ca
c
o
ultima tamb´m ´ inclu´ depois da palavra-chave CONTAINS, em um m´dulo, mas pode conter rotinas
´
e e
ıda
o
internas a ela.
Uma rotina interna automaticamente tem acesso a todas as entidades do hospedeiro, tais como vari´veis,
a
e possuem tamb´m a habilidade de chamar as outras rotinas deste. Contudo, uma determinada rotina
e
interna n˜o possui acesso `s entidades de outra rotina interna.
a
a
Um exemplo simples do uso de uma fun¸˜o interna ´ apresentado a seguir. Note que a vari´vel a ´
ca
e
a
e
declarada no programa principal, tornando-se assim uma vari´vel declarada tamb´m dentro do ˆmbito da
a
e
a
fun¸˜o calc_a_raiz:
ca
program r o t i n t
i m p l i c i t none
real : : x , a
!
print * , ”Entre com o v a l o r de x : ”
read * , x
print * , ”Entre com o v a l o r de a : ”
read * , a
print * , ”O r e s u l t a d o de a + s q r t ( x ) ´ : ”
e
print * , c a l c a r a i z ( x )
print * , ”O r e s u l t a d o de a + s q r t (1+ x * * 2 ) ´ : ”
e
print * , c a l c a r a i z ( 1 . 0 + x * * 2 )
CONTAINS
function c a l c a r a i z ( y )
real
:: calc a raiz
real , intent ( in ) : : y
c a l c a r a i z= a + s q r t ( y )
return
end function c a l c a r a i z
end program r o t i n t
No restante deste cap´
ıtulo, ser˜o descritas v´rias propriedades que se aplicam a sub-programas internos,
a
a
externos e a rotinas de m´dulos.
o

8.2.3

Argumentos de sub-programas

Argumentos de sub-programas fornecem um meio alternativo para que duas unidades de programa compartilhem os mesmos dados. Estes consistem em uma lista de vari´veis escalares ou matriciais, constantes,
a
express˜es escalares ou matriciais e at´ mesmo os nomes de outras rotinas. Os argumentos de um subo
e
programa s˜o muitas vezes denominados vari´veis mudas (dummy variables). Estes devem coincidir com
a
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
84

8.2. Sub-programas

os argumentos transferidos a partir da unidade que chama a rotina em tipo, esp´cie e forma. Contudo, os
e
nomes n˜o necessitam ser os mesmos, como se pode ver no exemplo acima. Com base no mesmo exemplo,
a
poder-se-ia realizar duas chamadas da fun¸˜o calc_a_raiz:
ca
...
read*, a,x
print*, calc_a_raiz(x)
print*, calc_a_raiz(a + x**2)
...
Sempre que poss´
ıvel, ´ recomendado que o nome do argumento transferido ao sub-programa seja igual ao
e
nome da vari´vel muda. O ponto importante ´ que sub-programas podem ser escritos de forma independente
a
e
uns dos outros. A associa¸˜o das vari´veis mudas com os argumentos verdadeiros ocorrem somente quando
ca
a
a rotina ´ chamada. Desta forma, bibliotecas de sub-programas podem ser constru´
e
ıdos, possibilitando que
estes sejam usados em diferentes programas (ver se¸˜o 8.2.6).
ca
O programa-exemplo bascara1, apresentado na p´gina 85, implementa, de forma ingˆnua, o c´lculo das
a
e
a
ra´
ızes de um polinˆmio de segundo grau atrav´s da F´rmula de B´scara usando uma subrotina interna.
o
e
o
a
Exemplos semelhantes a este ser˜o usados para ilustrar o uso de rotinas em outras unidades de programa.
a

8.2.4

Comando RETURN

No padr˜o da linguagem, um sub-programa pode ser encerrado pelo comando END, sendo o controle do
a
fluxo retornado ` unidade que chamou este sub-programa. Contudo, o meio recomendado de se retornar
a
controle a partir de um sub-programa consiste na utiliza¸˜o do comando RETURN, o qual pode surgir em
ca
mais de um ponto da rotina, ao contr´rio do END.
a
Como no caso dos comandos STOP e END, o RETURN pode ser rotulado, pode fazer parte de um construto
como o IF e ´ um comando execut´vel. O RETURN n˜o pode aparecer entre os comandos execut´veis do
e
a
a
a
programa principal.

8.2.5

Atributo e declara¸˜o INTENT
ca

No programa bascara1, (programa 8.1) as vari´veis mudas a0, a1 e a2 foram utilizadas para transferir `
a
a
subrotina informa¸˜o acerca dos coeficientes do polinˆmio de 2º grau. Por isto, estes nomes foram declarados
ca
o
ter a inten¸˜o INTENT(IN). Por outro lado, a subrotina devolveu ao programa os valores das ra´
ca
ızes reais
(caso existam) atrav´s das vari´veis mudas r1 e r2, as quais foram declaradas ter a inten¸˜o INTENT(OUT).
e
a
ca
Uma terceira possibilidade seria a existˆncia de uma vari´vel cujo valor ´ inicialmente transferido para
e
a
e
dentro da subrotina, modificado por esta e, ent˜o transferido para fora da subrotina. Neste caso, esta
a
vari´vel deveria ser declarada com a inten¸˜o INTENT(INOUT).
a
ca
Se uma vari´vel muda ´ especificada com atributo INTENT(IN), o seu valor n˜o pode ser alterado pela
a
e
a
rotina, seja atrav´s de atribui¸˜o de valor a partir de uma express˜o, ou atrav´s de sua transferˆncia para
e
ca
a
e
e
uma outra rotina que, por sua vez, alteraria este valor.
Se a vari´vel ´ especificada com INTENT(OUT), o seu valor ´ indefinido na chamada da rotina, sendo este
a
e
e
ent˜o definido durante a execu¸˜o da mesma e finalmente transferido ` unidade que chamou a rotina.
a
ca
a
Se a vari´vel ´ especificada com INTENT(INOUT), esta tem o seu valor inicial transferido na chamada da
a
e
rotina, o valor pode ser alterado e, ent˜o, o novo valor pode ser devolvido ` unidade que chamou a rotina.
a
a
´
E recomendado que a inten¸˜o de todas as vari´veis mudas seja declarada. Em fun¸˜es, vari´veis mudas
ca
a
co
a
somente podem ser declaradas com INTENT(IN).
Como alternativa ao uso do atributo INTENT(INOUT), pode-se declarar a inten¸˜o de nomes de argumentos
ca
mudos de rotinas, que n˜o sejam sub-programas mudos, atrav´s da declara¸˜o INTENT(INOUT), a qual tem
a
e
ca
a forma geral:
INTENT(<inout>) [::] <lista nomes argumentos mudos>
Por exemplo,
SUBROUTINE SOLVE(A, B, C, X, Y, Z)
REAL :: A, B, C, X, Y, Z
INTENT(IN) :: A, B, C
INTENT(OUT) :: X, Y, Z
...
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

85

Programa 8.1: Exemplo de emprego de rotinas internas.

program b a s c a r a 1
i m p l i c i t none
logical : : controle
real : : a , b , c
r e a l : : x1 , x2 ! R a i z e s r e a i s .
!
do
print * , ”Entre com o s v a l o r e s dos c o e f i c i e n t e s ( a , b , c ) , ”
print * , ”onde a * x ** 2 + b * x + c . ”
read * , a , b , c
c a l l b a s c a r a ( a , b , c , c o n t r o l e , x1 , x2 )
i f ( c o n t r o l e ) then
print * , ”As r a i z e s ( r e a i s ) s a o : ”
print * , ”x1=” , x1
print * , ”x2=” , x2
e xi t
else
print * , ”As r a i z e s s a o complexas . Tente novamente . ”
end i f
end do
CONTAINS
subroutine b a s c a r a ( a2 , a1 , a0 , r a i z e s r e a i s , r1 , r 2 )
! V a r i a v e i s mudas :
real , intent ( in )
: : a0 , a1 , a2
l o g i c a l , intent ( out ) : : r a i z e s r e a i s
real , intent ( out )
: : r1 , r 2
! Variaveis l o ca is :
real : : d i s c
!
r a i z e s r e a i s= t e s t a d i s c ( a2 , a1 , a0 )
i f ( . not . r a i z e s r e a i s ) return
d i s c= a1 * a1 − 4 * a0 * a2
r 1= 0.5 * ( − a1 − s q r t ( d i s c ) ) / a2
r 2= 0.5 * ( − a1 + s q r t ( d i s c ) ) / a2
return
end subroutine b a s c a r a
!
function t e s t a d i s c ( c2 , c1 , c0 )
logical : : testa disc
! V a r i a v e i s mudas :
real , intent ( in ) : : c0 , c1 , c2
i f ( c1 * c1 − 4 * c0 * c2 >= 0 . 0 ) then
t e s t a d i s c= . t r u e .
else
t e s t a d i s c= . f a l s e .
end i f
return
end function t e s t a d i s c
end program b a s c a r a 1

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
86

8.2. Sub-programas

8.2.6

Rotinas externas e bibliotecas

Em muitas situa¸˜es, uma determinada rotina ´ escrita com o intuito de ser utilizada em diversas
co
e
aplica¸˜es distintas. Um exemplo seria uma rotina gen´rica que calcula a integral de uma fun¸˜o qualquer
co
e
ca
entre dois pontos reais. Nesta situa¸˜o, ´ mais interessante manter a rotina como uma entidade distinta do
ca e
programa principal, para que esta possa ser utilizada por outras unidades de programas.
Por isto, uma ou mais rotinas podem ser escritas em um arquivo em separado, constituindo uma unidade
de programa pr´pria, j´ mencionada na se¸˜o 8.1.2. Esta unidade pode ent˜o ser compilada em separado,
o
a
ca
a
quando ser´ ent˜o gerado o programa-objeto correspondente a esta parte do c´digo. Este programa-objeto
a
a
o
´ ent˜o acessado pelo programa linkador para gerar o programa execut´vel, ligando a(s) rotina(s) contida(s)
e
a
a
nesta unidade com as outras unidades que fazem referˆncia `(s) mesma(s). O procedimento para realizar
e
a
esta linkagem ´ realizado, usualmente, de duas maneiras distintas:
e
1. O(s) programa-objeto(s) ´(s˜o) linkado(s) diretamente com as demais unidades de programa. Neste
e a
caso, o compilador e o linkador identificam a existˆncia do programa-objeto pela sua extens˜o, fornecida
e
a
na linha de comando que demanda a cria¸˜o do c´digo execut´vel. A extens˜o de um programa-objeto
ca
o
a
a
´ usualmente *.o em sistemas operacionais Linux/Unix ou *.obj em sistemas DOS/Windows.
e
2. O programa-objeto rec´m criado ´ armazenado, inicialmente, em uma biblioteca de programas-objeto
e
e
criados anteriormente. Ent˜o, no momento de se gerar o c´digo execut´vel a partir de um programaa
o
a
fonte, o linkador ´ instru´ com o nome e o endere¸o da biblioteca que cont´m o(s) programa-objeto(s)
e
ıdo
c
e
da(s) rotina(s) chamadas pelo programa principal e/ou por outras unidades de programas. O linkador
procura nesta biblioteca pelos nomes das rotinas invocadas e incorpora o c´digo destas (e somente
o
destas) ao programa execut´vel.
a
Com base nesta filosofia, o programa bascara1, apresentado na p´gina 8.1, pode ser ent˜o desmembrado
a
a
em trˆs arquivos distintos, dois contendo a subrotina bascara e a fun¸˜o testa_disc e um contendo o
e
ca
programa principal bascara2, apresentados na p´gina 87. Note o uso do atributo EXTERNAL para indicar
a
que o nome TESTA_DISC consiste em uma fun¸˜o externa do tipo l´gico.
ca
o

8.2.7

Interfaces impl´
ıcitas e expl´
ıcitas

No exemplo apresentado na p´gina 87, o nome testa_disc ´ identificado como pertencente a uma fun¸˜o
a
e
ca
l´gica pelo atributo EXTERNAL:
o
...
LOGICAL, EXTERNAL :: TESTA_DISC
...
Caso esta declara¸˜o n˜o fosse realizada, o compilador iria gerar uma mensagem de erro indicando que este
ca a
nome n˜o foi declarado.
a
Uma outra maneira de declarar um nome como pertencente a uma fun¸˜o externa ´ usando a declara¸˜o
ca
e
ca
EXTERNAL, em vez do atributo. Esta ´ a forma utilizada no Fortran 77. Desta maneira, o mesmo resultado
e
seria obtido atrav´s das seguintes linhas:
e
...
LOGICAL :: TESTA_DISC
EXTERNAL :: TESTA_DISC
...
A unica diferen¸a entre o exemplo acima e o mesmo tipo de declara¸˜o em um programa Fortran 77 consiste
´
c
ca
na ausˆncia dos (::) no ultimo caso.
e
´
Em ambas as op¸˜es anteriores, somente ´ fornecido ao compilador o nome da fun¸˜o. Nenhum controle
co
e
ca
existe sobre os argumentos da fun¸˜o testa_disc e da subrotina bascara. Por isto, seria poss´ o programa
ca
ıvel
bascara2 chamar a subrotina bascara tentando transferir vari´veis complexas, por exemplo, quando os
a
argumentos mudos da subrotina esperam vari´veis reais. Esta falta de controle, n˜o somente quanto ao
a
a
tipo e esp´cie das vari´veis transferidas a rotinas externas, mas tamb´m quanto ao n´mero e a ordem dos
e
a
e
u
argumentos, ´ inerente ao Fortran 77; nenhum mecanismo de controle existe para auxiliar o compilador e o
e
linkador na tarefa de determinar a coerˆncia entre as diferentes unidades de programas.
e
Para gerar chamadas a sub-programas de forma correta, o compilador necessita conhecer certos detalhes
destes sub-programas, como os seus nomes e o n´mero, tipo e esp´cie dos argumentos. Em Fortran 90/95,
u
e
esta tarefa ´ desempenhada pelos blocos de interface.
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

87

! Chamada p e l a s u b r o t i n a b a s c a r a para t e s t a r s e r a´ z e s s˜ o r e a i s .
ı
a
!
function t e s t a d i s c ( c2 , c1 , c0 )
i m p l i c i t none
logical : : testa disc
! V a r i a v e i s mudas :
´
real , intent ( in ) : : c0 , c1 , c2
i f ( c1 * c1 − 4 * c0 * c2 >= 0 . 0 ) then
t e s t a d i s c= . t r u e .
else
t e s t a d i s c= . f a l s e .
end i f
return
end function t e s t a d i s c
! C a l c u l a as r a´ z e s r e a i s , c a s o ex is t a m , de um p o l i n ˆ n i o de grau 2 .
ı
o
! Usa f u n c ˜ o t e s t a d i s c .
¸a
!
subroutine b a s c a r a ( a2 , a1 , a0 , r a i z e s r e a i s , r1 , r 2 )
i m p l i c i t none
! V a r i a v e i s mudas :
´
real , intent ( in )
: : a0 , a1 , a2
l o g i c a l , intent ( out ) : : r a i z e s r e a i s
real , intent ( out )
: : r1 , r 2
! Fun¸ ˜ o e x t e r n a :
ca
l o g i c a l , external : : t e s t a d i s c
! Variaveis l o ca i s :
´
real : : d i s c
!
r a i z e s r e a i s= t e s t a d i s c ( a2 , a1 , a0 )
i f ( . not . r a i z e s r e a i s ) return
d i s c= a1 * a1 − 4 * a0 * a2
r 1= 0.5 * ( − a1 − s q r t ( d i s c ) ) / a2
r 2= 0.5 * ( − a1 + s q r t ( d i s c ) ) / a2
return
end subroutine b a s c a r a
! C a l c u l a as r a´ z e s r e a i s de um p o l i n ˆ m i o de grau 2 .
ı
o
program b a s c a r a 2
i m p l i c i t none
logical : : controle
real : : a , b , c
r e a l : : x1 , x2 ! R a´z e s r e a i s .
ı
!
do
print * , ”Entre com o s v a l o r e s dos c o e f i c i e n t e s ( a , b , c ) , ”
print * , ”onde a * x ** 2 + b * x + c . ”
read * , a , b , c
c a l l b a s c a r a ( a , b , c , c o n t r o l e , x1 , x2 )
i f ( c o n t r o l e ) then
print * , ”As r a´ z e s ( r e a i s ) s ˜ o : ”
ı
a
print * , ”x1=” , x1
print * , ”x2=” , x2
e xi t
else
print * , ”As r a´ z e s s ˜ o complexas . Tente novamente . ”
ı
a
end i f
end do
end program b a s c a r a 2
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
88

8.2. Sub-programas

No caso de rotinas intr´
ınsecas, sub-programas internos e m´dulos, esta informa¸˜o ´ sempre conhecida
o
ca e
pelo compilador; por isso, diz-se que as interfaces s˜o expl´
a
ıcitas. Contudo, quando o compilador chama uma
rotina externa, esta informa¸˜o n˜o ´ conhecida de antem˜o e da´ a interface ´ dita impl´
ca a e
a
ı
e
ıcita. Um bloco de
interface, ent˜o, fornece a informa¸˜o necess´ria ao compilador. A forma geral de um bloco de interface ´:
a
ca
a
e
INTERFACE
<corpo interface>
END INTERFACE
Nesta forma, este bloco de interface n˜o pode ser nomeado. Assim, a interface deixa de ser impl´
a
ıcita e se
torna expl´
ıcita.
O <corpo interface> consiste das declara¸˜es FUNCTION ou SUBROUTINE, declara¸˜es dos tipos e esco
co
p´cies dos argumentos dos sub-programas e do comando END FUNCTION ou END SUBROUTINE. Em outras
e
palavras, consiste, normalmente, em uma c´pia exata do sub-programa sem seus comandos execut´veis ou
o
a
rotinas internas, cujas interfaces sempre s˜o expl´
a
ıcitas. Por exemplo,
INTERFACE
FUNCTION FUNC(X)
REAL
:: FUNC
REAL, INTENT(IN) :: X
END FUNCTION FUNC
END INTERFACE
Neste exemplo, o bloco fornece ao compilador a interface da fun¸˜o FUNC.
ca
Existe uma certa flexibilidade na defini¸ao de um bloco de interfaces. Os nomes (mas n˜o os tipos e
c˜
a
esp´cies) das vari´veis podem ser distintos dos nomes mudos definidos na rotina ou usados na chamada da
e
a
mesma e outras especifica¸˜es podem ser inclu´
co
ıdas, como por exemplo para uma vari´vel local ` rotina.
a
a
Contudo, rotinas internas e comandos DATA ou FORMAT n˜o podem ser inclu´
a
ıdos.
Um bloco de interfaces pode conter as interfaces de mais de um sub-programa externo e este bloco pode
ser colocado na unidade de programa que chama as rotinas externas ou atrav´s do uso de m´dulos, como
e
o
ser´ discutido na se¸˜o 8.3. Em qualquer unidade de programa, o bloco de interfaces ´ sempre colocado
a
ca
e
ap´s as declara¸˜es de vari´veis mudas ou de vari´veis locais.
o
co
a
a
Em certas situa¸˜es, ´ necess´rio fornecer a uma rotina externa o nome de outra rotina externa como
co
e
a
um de seus argumentos. Isto pode ser realizado de duas maneiras:
1. Usando o atributo ou declara¸˜o EXTERNAL, como foi realizado na subrotina bascara, na p´gina 8.2.6.
ca
a
2. Com o uso de um bloco de interface. Neste caso, a interface indicar´ ao compilador que um determinado
a
nome consiste, na verdade, no nome de um outro sub-programa.
As situa¸˜es onde isto pode ocorrer s˜o discutidas na se¸˜o 8.2.12
co
a
ca
Como exemplo do uso de interfaces expl´
ıcitas ser´ apresentado o programa bascara3, o qual chama
a
novamente as rotinas bascara e testa_disc. Este programa est´ listado nas p´ginas 89 e 90.
a
a

8.2.8

Argumentos com palavras-chave

Argumentos com palavras-chave (keyword arguments) s˜o um recurso j´ utilizado em comandos de Ena
a
trada/Sa´ (E/S) no Fortran 77:
ıda
READ(UNIT= 5, FMT= 101, END= 9000) X,Y,Z
onde UNIT, FMT e END s˜o as palavras-chave. Elas indicam, respectivamente, o n´mero da unidade de acesso
a
u
para leitura, o r´tulo do comando de formato e o r´tulo para onde o controle de fluxo deve ser desviado
o
o
quando se atingir o ponto final de entrada dos dados.
Em Fortran 90/95, argumentos com palavras-chave podem ser utilizados n˜o somente em comandos
a
de E/S, mas tamb´m em rotinas. Quando uma rotina tem diversos argumentos, palavras-chave s˜o um
e
a
excelente recurso para evitar confus˜o entre os mesmos. A grande vantagem no uso de palavras-chave est´
a
a
em que n˜o ´ necess´rio lembrar a ordem dos argumentos. Contudo, ´ necess´rio conhecer os nomes dos
a e
a
e
a
argumentos mudos definidos no campo de declara¸˜es da rotina.
co
Por exemplo, dada a seguinte fun¸˜o interna:
ca
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

89

! Chamada p e l a s u b r o t i n a b a s c a r a para t e s t a r s e r a´ z e s s˜ o r e a i s .
ı
a
!
function t e s t a d i s c ( c2 , c1 , c0 )
i m p l i c i t none
logical : : testa disc
! V a r i a v e i s mudas :
´
real , intent ( in ) : : c0 , c1 , c2
i f ( c1 * c1 − 4 * c0 * c2 >= 0 . 0 ) then
t e s t a d i s c= . t r u e .
else
t e s t a d i s c= . f a l s e .
end i f
return
end function t e s t a d i s c

! C a l c u l a as r a´ z e s r e a i s , c a s o ex is t a m , de um p o l i n ˆ n i o de grau 2 .
ı
o
! Usa f u n c ˜ o t e s t a d i s c .
¸a
!
subroutine b a s c a r a ( a2 , a1 , a0 , r a i z e s r e a i s , r1 , r 2 )
i m p l i c i t none
! V a r i a v e i s mudas :
´
real , intent ( in )
: : a0 , a1 , a2
l o g i c a l , intent ( out ) : : r a i z e s r e a i s
real , intent ( out )
: : r1 , r 2
! Variaveis l o ca i s :
´
real : : d i s c
INTERFACE
function t e s t a d i s c ( c2 , c1 , c0 )
logical : : testa disc
real , intent ( in ) : : c0 , c1 , c2
end function t e s t a d i s c
END INTERFACE
!
r a i z e s r e a i s= t e s t a d i s c ( a2 , a1 , a0 )
i f ( . not . r a i z e s r e a i s ) return
d i s c= a1 * a1 − 4 * a0 * a2
r 1= 0.5 * ( − a1 − s q r t ( d i s c ) ) / a2
r 2= 0.5 * ( − a1 + s q r t ( d i s c ) ) / a2
return
end subroutine b a s c a r a

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
90

8.2. Sub-programas

! C a l c u l a as r a´ z e s r e a i s de um p o l i n ˆ m i o de grau 2 .
ı
o
program b a s c a r a 3
i m p l i c i t none
logical : : controle
real : : a , b , c
r e a l : : x1 , x2 ! R a´z e s r e a i s .
ı
INTERFACE
subroutine b a s c a r a ( a2 , a1 , a0 , r a i z e s r e a i s , r1 , r 2 )
real , intent ( in )
: : a0 , a1 , a2
l o g i c a l , intent ( out ) : : r a i z e s r e a i s
real , intent ( out )
: : r1 , r 2
end subroutine b a s c a r a
END INTERFACE
!
do
print * , ”Entre com o s v a l o r e s dos c o e f i c i e n t e s ( a , b , c ) , ”
print * , ”onde a * x ** 2 + b * x + c . ”
read * , a , b , c
c a l l b a s c a r a ( a , b , c , c o n t r o l e , x1 , x2 )
i f ( c o n t r o l e ) then
print * , ”As r a´ z e s ( r e a i s ) s ˜ o : ”
ı
a
print * , ”x1=” , x1
print * , ”x2=” , x2
e xi t
else
print * , ”As r a´ z e s s ˜ o complexas . Tente novamente . ”
ı
a
end i f
end do
end program b a s c a r a 3

...
CONTAINS
FUNCTION AREA(INICIO, FINAL, TOL)
REAL
:: AREA
REAL, INTENT(IN) :: INICIO, FINAL, TOL
...
END FUNCTION AREA
esta pode ser chamada por quaisquer uma das trˆs seguintes atribui¸˜es:
e
co
A= AREA(0.0, 100.0, 1.0E-5)
B= AREA(INICIO= 0.0, TOL= 1.0E-5, FINAL= 100.0)
C= AREA(0.0, TOL= 1.0E-5, FINAL= 100.0)
VALOR= 100.0
ERRO= 1.0E-5
D= AREA(0.0, TOL= ERRO, FINAL= VALOR)
onde A, B, C e D s˜o vari´veis declaradas previamente como reais. Todos os argumentos antes da primeira
a
a
palavra-chave devem estar ordenados na ordem definida pela fun¸˜o. Contudo, se uma palavra-chave ´
ca
e
utilizada, esta n˜o necessita estar na ordem da defini¸˜o. Al´m disso, o valor atribu´ ao argumento mudo
a
ca
e
ıdo
pode ser uma constante, uma vari´vel ou uma express˜o, desde que a interface seja obedecida. Depois
a
a
que uma palavra-chave ´ utilizada pela primeira vez, todos os argumentos restantes tamb´m devem ser
e
e
transferidos atrav´s de palavras-chave. Conseq¨entemente, a seguinte chamada n˜o ´ v´lida:
e
u
a e a
C= AREA(0.0, TOL= 1.0E-5, 100.0) ! N~o ´ v´lido.
a e a
O exemplo acima n˜o ´ v´lido porque tentou-se transferir o valor 100.0 sem haver a informa¸˜o da palavraa e a
ca
chave.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

91

Uma vez que o compilador n˜o ser´ capaz de realizar as associa¸˜es apropriadas exceto se este conhecer as
a
a
co
palavras-chave (nomes dos argumentos mudos), a interface do sub-programa deve ser expl´
ıcita caso palavraschave sejam utilizadas. No caso de rotinas internas ou rotinas de m´dulo, a interface j´ ´ expl´
o
ae
ıcita. No caso
de rotinas externas, faz-se necess´rio o uso de um bloco de interfaces.
a

8.2.9

Argumentos opcionais

Em algumas situa¸˜es, nem todos os argumentos de um sub-programa necessitam ser transferidos durante
co
uma chamada do mesmo. Um argumento que n˜o necessita ser transferido em todas as chamadas poss´
a
ıveis
de um sub-programa ´ denominado opcional. Estes argumentos opcionais podem ser declarados pelo atributo
e
OPTIONAL na declara¸˜o do tipo de vari´veis.
ca
a
Mantendo o exemplo da fun¸˜o AREA acima, a seguinte defini¸˜o pode ser feita:
ca
ca
...
CONTAINS
FUNCTION AREA(INICIO, FINAL, TOL)
REAL
:: AREA
REAL, INTENT(IN), OPTIONAL :: INICIO, FINAL, TOL
...
END FUNCTION AREA
a qual agora tem as seguintes chamadas v´lidas, entre outras:
a
A=
B=
C=
D=

AREA(0.0, 100.0, 1.0E-2)
AREA(INICIO= 0.0, FINAL= 100.0, TOL= 1.0E-2)
AREA(0.0)
AREA(0.0, TOL= 1.0E-2)

onde se fez uso tanto da associa¸˜o posicional para os valores dos argumentos, quanto da associa¸˜o via o
ca
ca
uso de palavras-chave.
Um argumento obrigat´rio (que n˜o ´ declarado opcional) deve aparecer exatamente uma vez na lista
o
a e
de argumentos da chamada de uma rotina, ou na ordem posicional ou na lista de palavras-chave. J´ um
a
argumento opcional pode aparecer, no m´ximo uma vez, ou na lista posicional de argumentos ou na lista
a
de palavras-chave.
Da mesma forma como na se¸˜o 8.2.8, a lista de palavras-chave pode aparecer em qualquer ordem; por´m,
ca
e
depois que o primeiro argumento ´ transferido via uma palavra-chave, todos os restantes, obrigat´rios ou
e
o
opcionais, devem ser transferidos da mesma forma.
A rotina necessita de algum mecanismo para detectar se um argumento opcional foi transferido na
sua chamada, para que esta possa tomar a medida adequada no caso de presen¸a ou de ausˆncia. Este
c
e
mecanismo ´ fornecido pela fun¸˜o intr´
e
ca
ınseca PRESENT (se¸˜o 7.3). Por exemplo, na fun¸˜o AREA acima,
ca
ca
pode ser necess´rio verificar a existˆncia da vari´vel TOL para definir a tolerˆncia do c´lculo ou usar um
a
e
a
a
a
valor padr˜o caso ela n˜o tenha sido transferida:
a
a
...
REAL :: TTOL
...
IF(PRESENT(TOL))THEN
TTOL= TOL
ELSE
TTOL= 1.0E-3
END IF
...
A vari´vel TTOL ´ utilizada aqui porque ela pode ser redefinida, ao passo que a vari´vel TOL n˜o, uma vez
a
e
a
a
que ela foi declarada com INTENT(IN).
Como no caso dos argumento com palavras-chave, se a rotina ´ externa e possui algum argumento
e
opcional, um bloco de interface deve ser fornecido em algum momento. Este n˜o ´ o caso da fun¸˜o AREA,
a e
ca
uma vez que ela ´ interna. Contudo se externa ela o fosse, dever-se-ia declarar o seguinte bloco de interface:
e
INTERFACE
FUNCTION AREA(INICIO, FINAL, TOL)
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
92

8.2. Sub-programas
REAL
:: AREA
REAL, INTENT(IN), OPTIONAL :: INICIO, FINAL, TOL
END FUNCTION AREA
END INTERFACE

8.2.10

Tipos derivados como argumentos de rotinas

Argumentos de rotinas podem ser do tipo derivado se este est´ definido em somente uma unica unidade
a
´
de programa. Isto pode ser obtido de duas maneiras:
1. A rotina ´ interna ` unidade de programa na qual o tipo derivado ´ definido.
e
a
e
2. O tipo derivado ´ definido em um m´dulo o qual ´ acessado pela rotina.
e
o
e

8.2.11

Matrizes como argumentos de rotinas

Um outro recurso importante em Fortran ´ a capacidade de usar matrizes como argumentos mudos de
e
sub-programas. Se um argumento mudo de uma rotina ´ uma matriz, ent˜o o argumento real pode ser:
e
a
ˆ o nome da matriz (sem subscritos);
ˆ um elemento de matriz.

A primeira forma transfere a matriz inteira; a segunda forma, a qual transfere somente uma se¸˜o que inicia
ca
no elemento especificado, ´ descrita em mais detalhes a seguir.
e
8.2.11.1

Matrizes como argumentos em Fortran 77

O Fortran 77 j´ possu´ diversos recursos para realizar a transferˆncia de matrizes entre sub-programas.
a
ıa
e
Estes recursos foram posteriormente estendidos com a defini¸˜o do novo padr˜o com o Fortran 90/95.
ca
a
O uso mais simples e comum de argumentos mudos matriciais consiste em tornar dispon´ o conte´do
ıvel
u
completo de uma matriz em uma rotina. Se as matrizes usadas como argumentos reais ser˜o todas do mesmo
a
tamanho, ent˜o as matrizes mudas na rotina podem usar limites fixos (aloca¸˜o est´tica). Por exemplo:
a
ca
a
SUBROUTINE PROD(X, Y, Z)
C Calcula o produto dos vetores X e Y, com 100 elementos cada,
C resultando no vetor Z do mesmo tamanho.
REAL X(100), Y(100), Z(100)
DO 10, I= 1,100
Z(I)= X(I)*Y(I)
15
CONTINUE
END
Esta subrotina pode ser chamada por um programa semelhante a este:
PROGRAM CHAMA_PROD
REAL A(100), B(100), C(100)
READ(UNIT=*, FMT=*) A,B
CALL PROD(A, B, C)
WRITE(UNIT=*, FMT=*)C
END
Este uso de matrizes como argumentos mudos de sub-programas ´ perfeitamente leg´
e
ıtimo, por´m inflex´
e
ıvel,
porque n˜o permite o uso de matrizes de qualquer outro tamanho. Para possibilitar uma flexibilidade
a
maior, o Fortran 77 introduziu dois mecanismos que possibilitaram uma aloca¸˜o dinˆmica no tamanho de
ca
a
matrizes usadas como argumentos mudos de sub-programas. Estes mecanismos s˜o as matrizes ajust´veis
a
a
e as matrizes de tamanho assumido. A aloca¸˜o dinˆmica, entretanto, ´ parcial, porque as matrizes reais
ca
a
e
transferidas aos sub-programas deveriam ter seu tamanho definido por aloca¸˜o est´tica em algum ponto
ca
a
dentro das unidades de programas que chamavam as rotinas.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

93

Matrizes ajust´veis
a
Consiste na generaliza¸˜o dos argumentos matriciais de uma rotina para permitir o uso de matrizes de
ca
qualquer tamanho. Neste caso, as express˜es inteiras que definem os limites em cada dimens˜o das matrizes
o
a
mudas s˜o inclu´
a
ıdas nas declara¸˜es destas dentro da rotina, usando vari´veis inteiras que s˜o transferidas
co
a
a
junto com as matrizes nos argumentos da rotina ou atrav´s do uso de um bloco COMMON (ver se¸˜o 8.3.1). O
e
ca
exemplo a seguir mostra como isto ´ realizado:
e
SUBROUTINE PROD(NPTS, X, Y, Z)
REAL X(NPTS), Y(NPTS), Z(NPTS)
DO 15, I= 1, NPTS
...
END
Esta subrotina pode ser invocada pela seguinte linha no programa principal ou em outra unidade de programa:
CALL PROD(100, A, B, C)
as matrizes A, B e C devem ter o seu tamanho alocado de forma est´tica nesta ou em alguma outra unidade
a
de programa anterior, conforme j´ foi mencionado.
a
O recurso das matrizes ajust´veis pode ser estendido de forma trivial para cobrir o caso de matrizes
a
multi-dimensionais, com limites inferior e superior distintos. Por exemplo,
SUBROUTINE MULTI(MAP, K1, L1, K2, L2, TRACO)
DOUBLE PRECISION MAP(K1:L1, K2:L2)
REAL TRACO(L1-K1+1)
Como o exemplo mostra, os limites das dimens˜es das matrizes mudas pode ser express˜es inteiras envolvendo
o
o
n˜o somente constantes mas tamb´m vari´veis inteiras transferidas ` rotina ou na lista de argumentos ou
a
e
a
a
atrav´s de um bloco COMMON.
e
O mecanismo de matrizes ajust´veis pode ser usado para matrizes de qualquer tipo. Uma matriz ajust´vel
a
a
tamb´m pode ser transferida a uma outra rotina como um argumento real com, se necess´rio, os limites das
e
a
dimens˜es sendo passados de forma concomitante.
o
Matrizes de tamanho assumido
Podem haver circunstˆncias onde seja impratic´vel o uso tanto de matrizes fixas quanto de matrizes
a
a
ajust´veis como argumentos mudos de um sub-programa. A circunstˆncia mais freq¨ente ocorre quando o
a
a
u
tamanho real da matriz ´ desconhecido quando a rotina ´ inicialmente chamada. Neste caso, uma matriz
e
e
de tamanho assumido ´ a alternativa existente em Fortran 77.
e
Estas matrizes tamb´m somente s˜o permitidas como argumentos mudos de sub-programas, mas neste
e
a
caso a matriz ´, efetivamente, declarada como tendo tamanho desconhecido. Por exemplo:
e
REAL FUNCTION SOMADOIS(TABELA, ANGULO)
REAL TABELA(*)
N= MAX(1, NINT(SIN(ANGULO)*500.0))
SOMADOIS= TABELA(N) + TABELA(N+1)
END
Neste caso, a fun¸˜o somente sabe que a matriz TABELA ´ unidimensional, com um limite inferior igual
ca
e
a um. Isto ´ tudo que a fun¸˜o necessita saber para acessar os elementos apropriados N e N + 1. Ao
e
ca
executar a fun¸˜o, ´ responsabilidade do programador assegurar que o valor do ANGULO nunca ir´ resultar
ca e
a
em um subscrito fora do intervalo correto. Este ´ sempre um problema quando se usa matrizes de tamanho
e
assumido, porque o compilador n˜o tem nenhuma informa¸˜o a respeito do limite superior da matriz.
a
ca
Uma matriz de tamanho assumido somente pode ter o limite superior de sua ultima dimens˜o especificado
´
a
por um asterisco; todas as outras dimens˜es devem ter seus limites definidos pelas regras usuais ou serem
o
definidos na forma de matrizes ajust´veis.
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
94

8.2. Sub-programas

Se¸˜es de matrizes
co
As regras do Fortran requerem que as extens˜es de uma matriz, usada como argumento real de uma
o
rotina, sejam, no m´
ınimo, iguais `s respectivas extens˜es da matriz muda declarada na rotina. Entretanto,
a
o
a matriz real pode ter extens˜es maiores e as regras permitem tamb´m uma discordˆncia entre os limites
o
e
a
inferior e superior das matrizes real e muda. Por exemplo:
PROGRAM CONFUS
REAL X(-1:50), Y(10:1000)
READ(UNIT=*, FMT=*)X, Y
CALL SAIDA(X)
CALL SAIDA(Y)
END
C
SUBROUTINE SAIDA(MATRIZ)
REAL MATRIZ(50)
WRITE(UNIT=*,FMT=*)MATRIZ
END
O resultado deste programa ser´ escrever na sa´ padr˜o inicialmente os elementos X(-1) a X(48), uma vez
a
ıda
a
que este ultimo coresponde ` posi¸˜o na mem´ria de MATRIZ(50). Em seguida, o programa escreve Y(10)
´
a
ca
o
a Y(59). Esta subrotina ir´ funcionar de forma semelhante na se¸˜o de uma matriz bi-dimensional:
a
ca
PROGRAM DOIS_D
REAL D(100,20)
...
NFATIA= 15
CALL SAIDA(D(1,NFATIA))
...
Neste exemplo, a se¸˜o da matriz dos elementos D(1,15) a D(50,15)ser escrita na sa´ padr˜o. Isto ocorre
ca
ıda
a
atrav´s da varia¸˜o dos ´
e
ca
ındices das linhas, porque esta ´ a ordem dos elementos de matrizes em Fortran (ver
e
se¸˜o 6.6.2).
ca
O uso de um elemento de matriz como argumento real, quando o argumento mudo da rotina ´ uma
e
matriz completa consiste uma pr´tica que facilmente incorre em erro e, portanto, deve ser evitada.
a
8.2.11.2

Matrizes como argumentos em Fortran 90/95

Com a defini¸˜o do novo padr˜o Fortran 90/95, os recursos para uso de matrizes como argumentos mudos
ca
a
de sub-programas foi ampliado em rela¸˜o aos mecanismos j´ existentes no Fortran 77.
ca
a
No Fortran 90/95, como j´ foi visto na se¸˜o 6.9, a aloca¸˜o do tamanho das matrizes pode ser reaa
ca
ca
lizada de maneira inteiramente dinˆmica, sendo o espa¸o na mem´ria da CPU alocado em tempo real de
a
c
o
processamento. Para fazer uso deste novo recurso, o Fortran 90/95 definiu dois novos mecanismos para a
defini¸˜o de matrizes mudas vari´veis como argumentos de sub-programas: as matrizes de forma assumida,
ca
a
as quais generalizam as matrizes de tamanho assumido do Fortran 77 e os objetos autom´ticos, os quais n˜o
a
a
s˜o argumentos da rotina, mas tem suas extens˜es definidas pelas matrizes mudas desta.
a
o
Matrizes de forma assumida
Novamente como no caso de matrizes ajust´veis ou de tamanho assumido, as formas dos argumentos
a
reais e mudos ainda devem concordar. Contudo, agora uma matriz muda pode assumir a forma (n˜o somente
a
o tamanho) da matriz real usada no argumento da rotina. Tal matriz muda ´ denominada matriz de forma
e
assumida. Quando a forma ´ declarada com a especifica¸˜o DIMENSION, cada dimens˜o tem a sintaxe:
e
ca
a
[<lim inferior>]:
isto ´, pode-se definir o limite inferior da dimens˜o onde <lim inferior>, no caso mais geral, ´ uma
e
a
e
express˜o inteira que pode depender dos outros argumentos da rotina ou de vari´veis globais definidas em
a
a
m´dulos (ou em blocos COMMON, mas o seu uso ´ desaconselhado no Fortran 90/95). Se <lim inferior> ´
o
e
e
omitido, o valor padr˜o ´ 1. Deve-se notar que ´ a forma da matriz que ´ transferida, n˜o os seus limites.
a e
e
e
a
Por exemplo:
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

95

PROGRAM TESTA_MATRIZ
IMPLICIT NONE
REAL, DIMENSION(0:10, 0:20) :: A
...
CALL SUB_MATRIZ(A)
...
CONTAINS
SUBROUTINE SUB_MATRIZ(DA)
REAL, DIMENSION(:,:), INTENT(INOUT) :: DA
...
END SUBROUTINE SUB_MATRIZ
END PROGRAM TESTA_MATRIZ
A subrotina SUB_MATRIZ declara a matriz de forma assumida DA. A correspondˆncia entre os elementos da
e
matriz real A e a matriz muda DA ´: A(0,0)↔DA(1,1) . . . A(I,J)↔DA(I+1,J+1) . . . A(10,20)↔DA(11,21).
e
Para que houvesse a mesma correspondˆncia entre os elemento de A e DA, seria necess´rio declarar esta ultima
e
a
´
como:
REAL, DIMENSION(0:,0:), INTENT(INOUT) :: DA
Neste caso, a correspondˆncia seria a desejada: A(0,0)↔DA(0,0) . . . A(I,J)↔DA(I,J) . . . A(10,20)↔DA(10,20).
e
Para se definir matrizes de forma assumida, ´ necess´rio que a interface seja expl´
e
a
ıcita na unidade que
chama a rotina. A matriz real pode ter sido declarada, na unidade que chama a rotina ou em outra
unidade anterior, como uma matriz aloc´vel. Como exemplo, considere a seguinte rotina externa, seguida
a
do programa que a chama, programa 8.2, listado na p´gina 96:
a
subroutine sub ( ra , rb , rc , max a )
i m p l i c i t none
real , dimension ( : , : ) , intent ( in )
real , dimension ( : , : ) , intent ( out )
real , intent ( out )
!
max a= maxval ( r a )
r c= 0 . 5 * rb
return
end subroutine sub

: : ra , rb
: : rc
: : max a

Objetos autom´ticos
a
Uma rotina com argumentos mudos que s˜o matrizes cujos tamanhos variam de uma chamada a outra
a
pode tamb´m precisar de matrizes locais (n˜o mudas) cujos tamanhos variem ao sabor dos tamanhos das
e
a
matrizes mudas. Um exemplo simples ´ a matriz TEMP na subrotina abaixo, destinada a trocar os elementos
e
entre duas matrizes:
SUBROUTINE TROCA(A,B)
IMPLICIT NONE
REAL, DIMENSION(:), INTENT(INOUT) :: A, B
REAL, DIMENSION(SIZE(A)) :: TEMP
!A fun¸~o SIZE fornece o tamanho de TEMP.
ca
TEMP= A
A= B
B= TEMP
RETURN
END SUBROUTINE TROCA
Matrizes como a TEMP, cujas extens˜es variam da maneira apresentada s˜o chamadas matrizes autom´ticas
o
a
a
e s˜o exemplos de objetos autom´ticos de dados. Estes s˜o objetos de dados cujas declara¸˜es dependem do
a
a
a
co
valor de express˜es n˜o-constantes e que n˜o s˜o argumentos mudos de rotinas.
o
a
a a
Um outro objeto autom´tico, relacionado com vari´veis de caracteres, surge atrav´s do comprimento
a
a
e
vari´vel de um caractere:
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
96

8.2. Sub-programas
Programa 8.2: Exemplifica o uso de matrizes de forma assumida.

program p r o g s u b
i m p l i c i t none
real , dimension ( 0 : 9 , 1 0 ) : : a
real , dimension ( 5 , 5 )
:: c
real
: : valor max
integer : : i
INTERFACE
subroutine sub ( ra , rb , rc , max a )
real , dimension ( : , : ) , intent ( in )
: : ra , rb
real , dimension ( : , : ) , intent ( out ) : : r c
real , intent ( out )
: : max a
end subroutine sub
END INTERFACE
!
a= r e s h a p e ( s o u r c e =(/( c o s ( r e a l ( i ) ) , i= 1 , 1 0 0 ) / ) , shape= ( / 1 0 , 1 0 / ) )
c a l l sub ( a , a ( 0 : 4 , : 5 ) , c , valor max )
print * , ”A m a t r i z a : ”
do i= 0 , 9
print * , a ( i , : )
end do
print * , ” ”
print * , ”O maior v a l o r em a : ” , valor max
print * , ” ”
print * , ”A m a t r i z c : ”
do i= 1 , 5
print * , c ( i , : )
end do
end program p r o g s u b

SUBROUTINE EXEMPLO(PALAVRA1)
IMPLICIT NONE
CHARACTER(LEN= *)
:: PALAVRA1
CHARACTER(LEN= LEN(PALAVRA1)) :: PALAVRA2
...
como um exemplo. Se este objeto consiste em uma fun¸˜o de caractere de tamanho vari´vel, a interface
ca
a
deve ser expl´
ıcita, como no programa-exemplo loren abaixo.
A defini¸˜o dos limites das dimens˜es de um objeto autom´tico pode ser realizada tamb´m de argumentos
ca
o
a
e
mudos ou de vari´veis definidas por associa¸˜o por uso ou por associa¸˜o ao hospedeiro. Associa¸˜o por uso
a
ca
ca
ca
ocorre quando vari´veis globais p´blicas declaradas no corpo de um m´dulo s˜o disponibilizadas ` rotina
a
u
o
a
a
program l o r e n
i m p l i c i t none
character ( len= * ) , parameter : : a= ”S´ um pequeno exemplo . ”
o
print * , dobro ( a )
CONTAINS
function dobro ( a )
character ( len= * ) , intent ( in ) : : a
character ( len= 2 * len ( a )+2)
: : dobro
dobro= a // ” ” // a
return
end function dobro
end program l o r e n

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

97

atrav´s da instru¸˜o USE; enquanto que associa¸˜o ao hospedeiro ocorre quando vari´veis declaradas em
e
ca
ca
a
uma unidade de programa s˜o disponibilizadas `s suas rotinas internas.
a
a
Matrizes autom´ticas s˜o automaticamente criadas (alocadas) na entrada da rotina e automaticamente
a
a
dealocadas na sa´
ıda. Assim, o tamanho das matrizes autom´ticas pode variar em diferentes chamadas da
a
rotina. Note que n˜o h´ mecanismo para verificar a disponibilidade de mem´ria para a cria¸˜o de matrizes
a a
o
ca
autom´ticas. Caso n˜o haja mem´ria suficiente, o programa ´ interrompido. Al´m disso, uma matriz
a
a
o
e
e
autom´tica n˜o pode aparecer em uma declara¸˜o SAVE (se¸˜o 8.2.15) ou NAMELIST, ou possuir o atributo
a
a
ca
ca
SAVE na sua declara¸˜o. Al´m disso, a matriz n˜o pode ser inicializada na sua declara¸˜o.
ca
e
a
ca
O seguinte programa-exemplo usa matrizes aloc´veis, de forma assumida e autom´ticas:
a
a
subroutine sub mat ( a , r e s )
i m p l i c i t none
real , dimension ( : , : ) , intent ( in ) : : a ! M a t r i z de forma assumida
real , intent ( out ) : : r e s
real , dimension ( s i z e ( a , 1 ) , s i z e ( a , 2 ) ) : : temp ! M a t r i z a u t o m a t i c a
´
!
temp= s i n ( a )
r e s= minval ( a+temp )
return
end subroutine sub mat
program m a t r i z a u t
i m p l i c i t none
real , dimension ( : , : ) , a l l o c a t a b l e : : a
real
: : res
integer : : n , m, i
INTERFACE
subroutine sub mat ( a , r e s )
real , dimension ( : , : ) , intent ( in ) : : a
real , intent ( out ) : : r e s
real , dimension ( s i z e ( a , 1 ) , s i z e ( a , 2 ) ) : : temp
end subroutine sub mat
END INTERFACE
print * , ”Entre com di m e n s ˜ e s da m a t r i z : ”
o
read * , n ,m
a l l o c a t e ( a ( n ,m) )
a= r e s h a p e ( s o u r c e =(/( tan ( r e a l ( i ) ) , i= 1 , n *m) / ) , shape= ( / n ,m/ ) )
print * , ”Matriz a : ”
do i= 1 , n
print * , a ( i , : )
end do
c a l l sub mat ( a , r e s )
print * , ” ”
print * , ”O menor v a l o r de a + s i n ( a ) ´ : ” , r e s
e
end program m a t r i z a u t

8.2.12

sub-programas como argumentos de rotinas

At´ este ponto, os argumentos de uma rotina forma supostos ser vari´veis ou express˜es. Contudo, uma
e
a
o
outra possibilidade ´ um ou mais argumentos sendo nomes de outras rotinas que ser˜o invocadas. Um
e
a
exemplo de situa¸˜o onde ´ necess´rio mencionar o nome de uma rotina como argumento de outra ´ quando
ca
e
a
e
a segunda executa a integra¸˜o num´rica da primeira. Desta forma, ´ poss´
ca
e
e
ıvel escrever-se um integrador
num´rico gen´rico, que integra qualquer fun¸˜o que satisfa¸a a interface imposta a ela.
e
e
ca
c
Um exemplo de uso do nome de uma rotina como argumento ocorre abaixo. a fun¸˜o MINIMO calcula o
ca
m´
ınimo (menor valor) da fun¸˜o FUNC em um intervalo:
ca
FUNCTION MINIMO(A, B, FUNC)
! Calcula o m´nimo de FUNC no intervalo [A,B].
ı
REAL :: MINIMO
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
98

8.2. Sub-programas
REAL, INTENT(IN) :: A, B
INTERFACE
FUNCTION FUNC(X)
REAL :: FUNC
REAL, INTENT(IN) :: X
END FUNCTION FUNC
END INTERFACE
REAL :: F,X
...
F= FUNC(X) !Invoca¸~o da fun¸~o.
ca
ca
...
END FUNCTION MINIMO

Note o uso de um bloco de interface para indicar ao compilador que o nome FUNC corresponde a uma fun¸˜o
ca
definida pelo usu´rio.
a
Em Fortran 77, como n˜o havia o recurso de blocos de interface, a indica¸˜o que o nome FUNC corresponde
a
ca
a uma fun¸˜o externa ´ realizada atrav´s da declara¸˜o EXTERNAL. Assim, no exemplo acima, no lugar da
ca
e
e
ca
interface apareceria:
...
REAL FUNC
EXTERNAL FUNC
...
para indicar a fun¸˜o externa. A mesma alternativa continua v´lida em Fortran 90/95, onde, al´m da
ca
a
e
declara¸˜o, pode-se usar tamb´m a palavra-chave EXTERNAL como atributo de um nome. Contudo, como j´
ca
e
a
foi mencionado na se¸˜o 8.2.7, o simples uso da declara¸˜o ou atributo EXTERNAL n˜o possibilita o controle
ca
ca
a
nos argumentos desta fun¸˜o, ao contr´rio do que ocorre quando a interface ´ expl´
ca
a
e
ıcita.
Um exemplo de programa que chama a fun¸˜o MINIMO seria o seguinte:
ca
PROGRAM MIN
IMPLICIT NONE
REAL :: MENOR
INTERFACE
FUNCTION FUN(X)
REAL :: FUN
REAL, INTENT(IN) :: X
END FUNCTION FUN
END INTERFACE
...
MENOR= MINIMO(1.0, 2.0, FUN)
...
END PROGRAM MIN
O uso de um bloco de interface n˜o ´ necess´rio se a interface de FUN for expl´
a e
a
ıcita, como no caso de uma
rotina de m´dulo.
o
No exemplo acima, a fun¸˜o FUN n˜o pode ser interna, porque estas n˜o s˜o admitidas quando os seus
ca
a
a a
nomes s˜o usados como argumentos de outras rotinas. Ou seja, somente rotinas externas ou de m´dulos s˜o
a
o
a
aceitas quando os seus nomes s˜o transferidos a outras rotinas como argumentos.
a
O programa-exemplo das p´ginas 99 e 100 descreve uma subrotina que gera uma matriz de pontos a
a
partir de uma fun¸˜o fornecida pelo programador.
ca

8.2.13

Fun¸oes de valor matricial
c˜

Fun¸˜es, al´m de fornecer os resultados usuais na forma de valores dos tipos intr´
co
e
ınsecos inteiro, real,
complexo, l´gico e de caractere, podem tamb´m fornecer como resultado valores de tipo derivado, matrizes
o
e
e ponteiros. No caso de fun¸˜es de valor matricial, o tamanho do resultado pode ser determinado de forma
co
semelhante ` maneira como matrizes autom´ticas s˜o declaradas.
a
a
a
Considere o seguinte exemplo de uma fun¸˜o de valor matricial:
ca
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

99

! Usa s u b r o t i n a p l o t a e chama a f u n ¸ ˜ o e x t e r n a Meu F .
ca
!
program t e s p l o t a
i m p l i c i t none
integer : : pts , j
real
: : yi , y f
real , dimension ( : , : ) , a l l o c a t a b l e : : xy
INTERFACE
subroutine p l o t a ( f , xi , xf , npt , p l o t )
integer , intent ( in ) : : npt
real , intent ( in )
: : xi , x f
real , dimension ( 2 , npt ) , intent ( out ) : : p l o t
INTERFACE
function f ( x )
real : : f
real , intent ( in ) : : x
end function f
END INTERFACE
end subroutine p l o t a
!
function Meu F ( y )
r e a l : : Meu F
real , intent ( in ) : : y
end function Meu F
END INTERFACE
!
print * , ”Entre com o n´ mero de p o n t o s : ”
u
read * , p t s
print * , ”Entre com o s l i m i t e s i n f e r i o r e s u p e r i o r : ”
read * , yi , y f
a l l o c a t e ( xy ( 2 , p t s ) )
!
c a l l p l o t a ( Meu F , yi , yf , pts , xy )
!
do j= 1 , p t s
print * , xy ( : , j )
end do
end program t e s p l o t a

! Fun¸ ˜ o sen ( exp ( x ) ) .
ca
function Meu F ( x )
r e a l : : Meu F
real , intent ( in ) : : x
!
Meu F= s i n ( exp ( x ) )
return
end function Meu F

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
100

8.2. Sub-programas

! Gera uma m a t r i z de p o n t o s de uma f u n ¸ ˜ o q u a l q u e r d e s t i n a d a ` p l o t a g e m
ca
a
! do g r a f i c o d e s t a f u n ¸ ˜ o .
´
ca
! Parˆ metros :
a
! f : Fun¸ ˜ o e x t e r n a a s e r p l o t a d a .
ca
! x i : Ponto i n i c i a l ( e n t r a d a ) .
! x f : Ponto f i n a l ( e n t r a d a ) .
! npt : N´mero de p o n t o s a s e r g e r a d o s ( e n t r a d a )
u
!
p l o t : m a t r i z de forma (/ npt , 2 /) contendo as a b c i s s a s e ordena da s dos
!
p o n t o s ( s a´d a ) .
ı
!
subroutine p l o t a ( f , xi , xf , npt , p l o t )
i m p l i c i t none
integer , intent ( in ) : : npt
real , intent ( in )
: : xi , x f
real , dimension ( 2 , npt ) , intent ( out ) : : p l o t
INTERFACE
function f ( x )
real : : f
real , intent ( in ) : : x
end function f
END INTERFACE
! Variaveis l o ca i s :
´
integer : : i
real
: : passo , x
!
p a s s o= ( x f − x i ) / r e a l ( npt − 1 )
x= x i
do i= 1 , npt
p l o t ( 1 , i )= x
p l o t ( 2 , i )= f ( x )
x= x + p a s s o
end do
return
end subroutine p l o t a

PROGRAM TES_VAL_MAT
IMPLICIT NONE
INTEGER, PARAMETER :: M= 6
INTEGER, DIMENSION(M,M) :: IM1, IM2
...
IM2= FUN_VAL_MAT(IM1,1) !Chama fun¸~o matricial.
ca
...
CONTAINS
FUNCTION FUN_VAL_MAT(IMA, SCAL)
INTEGER, DIMENSION(:,:), INTENT(IN) :: IMA
INTEGER, INTENT(IN) :: SCAL
INTEGER, DIMENSION(SIZE(IMA,1),SIZE(IMA,2)) :: FUN_VAL_MAT
FUN_VAL_MAT= IMA*SCAL
END FUNCTION FUN_VAL_MAT
END PROGRAM TES_VAL_MAT

Neste exemplo, o limites das dimens˜es de FUN_VAL_MAT s˜o herdadas do argumento verdadeiro transferido
o
a
a
` fun¸˜o e usadas para determinar o tamanho da matriz resultante.
ca
Para que o compilador conhe¸a a forma da matriz resultante, a interface de uma fun¸˜o de valor matricial
c
ca
deve ser expl´
ıcita em todas as unidades onde esta fun¸˜o ´ invocada.
ca e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

8.2.14

101

Recursividade e rotinas recursivas

Recursividade ocorre quando rotinas chamam a si mesma, seja de forma direta ou indireta. Por exemplo,
sejam as rotinas A e B. Recursividade pode ocorrer de duas formas:
Recursividade direta: A invoca A diretamente.
Recursividade indireta: A invoca B, a qual invoca A.
Qualquer cadeia de invoca¸˜es de rotinas com um componente circular (isto ´, invoca¸˜o direta ou indireta)
co
e
ca
exibe recursividade. Embora recursividade seja uma t´cnica bonita e sucinta para implementar uma grande
e
variedade de problemas, o uso incorreto da mesma pode provocar uma perda na eficiˆncia da computa¸˜o
e
ca
do c´digo.
o
Fortran 77
Em Fortran 77, recursividade direta n˜o ´ permitida. Qualquer tentativa de for¸ar uma rotina a chamar
a e
c
a si pr´pria resultar´ em erro de compila¸˜o. Em grande parte dos textos, afirma-se que recursividade
o
a
ca
indireta tamb´m n˜o ´ poss´ 3 . Contudo, recursividade pode ser simulada em Fortran 77 quando uma
e
a e
ıvel
rotina chama a si pr´pria usando n˜o o seu nome real mas atrav´s de um argumento mudo, como no exemplo
o
a
e
abaixo:4
PROGRAM MAIN
INTEGER N, X
EXTERNAL SUB1
COMMON /GLOBALS/ N
X= 0
PRINT*, ’Entre n´mero de repeti¸~es:’
u
co
READ(*,*) N
CALL SUB1(X, SUB1)
END PROGRAM MAIN
------------------------------------------SUBROUTINE SUB1(X, SUBMUDO)
INTEGER N, X
EXTERNAL SUBMUDO
COMMON /GLOBALS/ N
IF(X .LT. N)THEN
X= X + 1
PRINT*, ’X=’, X
CALL SUBMUDO(X, SUBMUDO)
END IF
RETURN
END SUBROUTINE SUB1
Como a subrotina SUB1 n˜o sabe que ao invocar o argumento mudo SUBMUDO, o qual ´ o nome de uma
a
e
rotina externa, vai estar na verdade invocando a si pr´pria, o compilador n˜o ir´ gerar mensagem de erro e
o
a a
o c´digo ir´ funcionar em grande parte das plataformas. Por exemplo, se o valor de N for definido igual a 5,
o
a
o resultado ser´
a
X = 1
X = 2
...
X = 5
o que demonstra que ´ poss´ simular-se recursividade mesmo em Fortran 77.
e
ıvel
Fortran 90/95
Em Fortran 90/95, por outro lado, recursividade ´ suportada como um recurso expl´
e
ıcito da linguagem.
3 Ver,

por exemplo, o texto de Clive Page [5, se¸ao 4.3].
c˜
Fortran Examples http://www.esm.psu.edu/~ajm138/fortranexamples.html, consultada em 07/06/2005.

4 Referˆncia:
e

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
102

8.2. Sub-programas

Recursividade direta. Para fins de eficiˆncia na execu¸˜o do c´digo, rotinas recursivas devem ser explie
ca
o
citamente declaradas usando-se a palavra-chave
RECURSIVE SUBROUTINE ...
ou
RECURSIVE FUNCTION ...
A declara¸˜o de uma fun¸˜o recursiva ´ realizada com uma sintaxe um pouco distinta da at´ ent˜o abordada:
ca
ca
e
e
a
uma fun¸˜o explicitamente declarada recursiva deve conter tamb´m a palavra-chave RESULT, a qual especifica
ca
e
o nome de uma vari´vel ` qual o valor do resultado do desenvolvimento da fun¸˜o deve ser atribu´
a
a
ca
ıdo, em
lugar do nome da fun¸˜o propriamente dito.
ca
A palavra-chave RESULT ´ necess´ria, uma vez que n˜o ´ poss´ usar-se o nome da fun¸˜o para retornar
e
a
a e
ıvel
ca
o resultado, pois isso implicaria em perda de eficiˆncia no c´digo. De fato, o nome da palavra-chave deve ser
e
o
usado tanto na declara¸˜o do tipo e esp´cie do resultado da fun¸˜o quanto para atribui¸˜o de resultados e em
ca
e
ca
ca
express˜es escalares ou matriciais. Esta palavra-chave pode tamb´m ser usada para fun¸˜es n˜o recursivas.
o
e
co
a
Cada vez que uma rotina recursiva ´ invocada, um conjunto novo de objetos de dados locais ´ criado,
e
e
o qual ´ eliminado na sa´ da rotina. Este conjunto consiste de todos os objetos definidos no campo de
e
ıda
declara¸˜es da rotina ou declarados implicitamente, exceto aqueles com atributos DATA ou SAVE (ver se¸˜o
co
ca
8.2.15). Fun¸˜es de valor matricial recursivas s˜o permitidas e, em algumas situa¸˜es, a chamada de uma
co
a
co
fun¸˜o recursiva deste tipo ´ indisting¨´ de uma referˆncia a matrizes.
ca
e
uıvel
e
O exemplo tradicional do uso de rotinas recursivas consiste na implementa¸˜o do c´lculo do fatorial de
ca
a
um inteiro positivo. A implementa¸˜o ´ realizada a partir das seguintes propriedades do fatorial:
ca e
0! = 1;

N ! = N (N − 1)!

A seguir, o c´lculo do fatorial ´ implementado tanto na forma de uma fun¸˜o quanto na forma de uma
a
e
ca
subrotina recursivas:
RECURSIVE FUNCTION FAT(N) RESULT (N_FAT)
IMPLICIT NONE
INTEGER :: N_FAT !Define tamb´m o tipo de FAT.
e
INTEGER, INTENT(IN) :: N
IF(N == 0)THEN
N_FAT= 1
ELSE
N_FAT= N*FAT(N-1)
END IF
RETURN
END FUNCTION FAT
---------------------------------------------RECURSIVE SUBROUTINE FAT(N, N_FAT)
IMPLICIT NONE
INTEGER, INTENT(IN) :: N
INTEGER, INTENT(INOUT) :: N_FAT
IF(N == 0)THEN
N_FAT= 1
ELSE
CALL FAT(N - 1, N_FAT)
N_FAT= N*N_FAT
END IF
RETURN
END SUBROUTINE FAT
Recursividade indireta. Uma rotina tamb´m pode ser invocada por recursividade indireta, isto ´, uma
e
e
rotina chama outra a qual, por sua vez, invoca a primeira. Para ilustrar a utilidade deste recurso, sup˜e-se
o
que se queira realizar uma integra¸˜o num´rica bi-dimensional quando se disp˜e somente de um c´digo que
ca
e
o
o
executa integra¸˜o unidimensional. Um exemplo de fun¸˜o que implementaria integra¸˜o unidimensional ´
ca
ca
ca
e
dado a seguir. O exemplo usa um m´dulo, o qual ´ uma unidade de programa que ser´ discutido na se¸˜o
o
e
a
ca
8.3:
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

103

FUNCTION INTEGRA(F, LIMITES)
! Integra F(x) de LIMITES(1) a LIMITES(2).
implicit none
REAL, DIMENSION(2), INTENT(IN) :: LIMITES
INTERFACE
FUNCTION F(X)
REAL :: F
REAL, INTENT(IN) :: X
END FUNCTION F
END INTERFACE
...
INTEGRA= <implementa¸~o integra¸~o num´rica>
ca
ca
e
RETURN
END FUNCTION INTEGRA
-------------------------------------------MODULE FUNC
IMPLICIT NONE
REAL :: YVAL
REAL, DIMENSION(2) :: LIMX, LIMY
CONTAINS
FUNCTION F(XVAL)
REAL :: F
REAL, INTENT(IN) :: XVAL
F= <express~o envolvendo XVAL e YVAL>
a
RETURN
END FUNCTION F
END MODULE FUNC
-----------------------------------------FUNCTION FY(Y)
! Integra em X, para um valor fixo de Y.
USE FUNC
REAL :: FY
REAL, INTENT(IN) :: Y
YVAL= Y
FY= INTEGRA(F, LIMX)
RETURN
END FUNCTION FY
Com base nestas trˆs unidades de programa, um programa pode calcular a integral sobre o retˆngulo no
e
a
plano (x, y) atrav´s da chamada:
e
AREA= INTEGRA(FY, LIMY)

8.2.15

Atributo e declara¸˜o SAVE
ca

A declara¸˜o ou o atributo SAVE s˜o utilizados quando se deseja manter o valor de uma vari´vel local
ca
a
a
em um sub-programa ap´s a sa´
o
ıda. Desta forma, o valor anterior desta vari´vel est´ acess´
a
a
ıvel quando o
sub-programa ´ invocado novamente.
e
Como exemplo, a subrotina abaixo cont´m as vari´veis locais CONTA, a qual conta o n´mero de chamadas
e
a
u
da subrotina e ´ inicializada a zero e a vari´vel A, que ´ somada ao valor do argumento.
e
a
e
SUBROUTINE CONTA_SOMA(X)
IMPICIT NONE
REAL, INTENT(IN) :: X
REAL, SAVE :: A
INTEGER :: CONTA= 0 !Inicializa o contador.
...
CONTA= CONTA + 1
IF(CONTA == 1)THEN
A= 0.0
Autor: Rudi Gaelzer – IFM/UFPel

Mant´m o valor da vari´vel.
e
a

Impresso: 13 de abril de 2010
104

8.2. Sub-programas
ELSE
A= A + X
END IF
...
RETURN
END SUBROUTINE CONTA_SOMA

Neste exemplo, tanto a vari´vel A quanto CONTA tˆm o seu valor mantido quando a subrotina ´ abandonada.
a
e
e
Isto ´ garantido porque a vari´vel A ´ declarada com o atributo SAVE. J´ a vari´vel CONTA n˜o precisa ser
e
a
e
a
a
a
declarada com o mesmo atributo porque ela tem o seu valor inicializado na declara¸˜o. De acordo com o paca
dr˜o da linguagem, as vari´veis que tˆm o seu valor inicializado no momento da declara¸˜o automaticamente
a
a
e
ca
adquirem o atributo SAVE.
Alternativamente ao uso do atributo, pode-se declarar uma lista de nomes de vari´veis com a mesma
a
propriedade atrav´s da declara¸˜o SAVE. Desta forma, a vari´vel A, no exemplo acima, podia ser declarada
e
ca
a
atrav´s das linhas:
e
...
REAL :: A
SAVE :: A
...
A forma geral desta declara¸˜o ´:
ca e
SAVE [[::] <lista nomes vari´veis>]
a
onde uma declara¸˜o SAVE sem a subseq¨ente <lista nomes vari´veis> equivale ` mesma declara¸˜o
ca
u
a
a
ca
aplicada a todos os nomes da rotina, em cujo caso nenhuma outra vari´vel pode ser declarada com o
a
atributo SAVE.
O atributo SAVE n˜o pode ser especificado para um argumento mudo, um resultado de fun¸˜o ou um
a
ca
objeto autom´tico. O atributo pode ser especificado para um ponteiro, em cuja situa¸˜o seu status de
a
ca
associa¸˜o ´ preservado. Pode ser aplicado tamb´m a uma matriz aloc´vel, em cuja situa¸˜o o status de
ca e
e
a
ca
aloca¸˜o e valores s˜o preservados. Uma vari´vel preservada em um sub-programa recursivo ´ compartilhada
ca
a
a
e
por todas as instˆncias da rotina.
a
O comando ou atributo SAVE podem aparecer no campo de declara¸˜es de um programa principal, mas
co
neste caso o seu efeito ´ nulo. O uso pr´tico deste recurso est´ restrito `s outras unidades de programa.
e
a
a
a

8.2.16

Fun¸oes de efeito lateral e rotinas puras
c˜

Na se¸˜o 8.2, foi mencionado que fun¸˜es normalmente n˜o alteram o valor de seus argumentos. Enca
co
a
tretanto, em certas situa¸˜es esta a¸˜o ´ permitida. Fun¸˜es que alteram o valor de seus argumentos s˜o
co
ca e
co
a
denominadas fun¸˜es de efeito lateral (side-effect functions).
co
Para auxiliar na otimiza¸˜o do c´digo, o padr˜o da linguagem estabelece uma proibi¸˜o no uso de fun¸˜es
ca
o
a
ca
co
de efeito lateral quando o uso de tal fun¸˜o em uma express˜o altera o valor de um outro operando na mesma
ca
a
express˜o, seja este operando uma vari´vel ou um argumento de uma outra fun¸˜o. Caso este tipo de fun¸˜o
a
a
ca
ca
fosse poss´ neste caso, a atribui¸˜o
ıvel
ca
RES= FUN1(A,B,C) + FUN2(A,B,C)
onde ou FUN1 ou FUN2, ou ambas, alterassem o valor de um ou mais argumentos, a ordem de execu¸˜o desta
ca
express˜o seria importante; o valor de RES seria diferente caso FUN1 fosse calculada antes de FUN2 do que
a
seria caso a ordem de c´lculo fosse invertida. Exemplos de fun¸˜es de efeito lateral s˜o dados a seguir:
a
co
a
FUNCTION FUN1(A,B,C)
INTEGER :: FUN1
REAL, INTENT(INOUT) :: A
REAL, INTENT(IN)
:: B,C
A= A*A
FUN1= A/B
RETURN
END FUNCTION FUN1
----------------------------------Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

105

FUNCTION FUN2(A,B,C)
INTEGER :: FUN2
REAL, INTENT(INOUT) :: A
REAL, INTENT(IN)
:: B,C
A= 2*A
FUN2= A/C
RETURN
END FUNCTION FUN2
Nota-se que ambas as fun¸˜es alteram o valor de A; portanto, o valor de RES ´ totalmente dependente na
co
e
ordem de execu¸˜o da express˜o.
ca
a
Como o padr˜o da linguagem n˜o estabelece uma ordem para a execu¸˜o das opera¸˜es e desenvolvia
a
ca
co
mentos em uma express˜o, este efeito lateral ´ proibido neste caso. Isto possibilita que os compiladores
a
e
executem as opera¸˜es na ordem que otimiza a execu¸˜o do c´digo.
co
ca
o
O uso de fun¸˜es de efeito lateral em comandos ou construtos FORALL (se¸˜o 6.10), por exemplo, acarco
ca
retaria em um impedimento severo na otimiza¸˜o da execu¸˜o do comando em um processador paralelo,
ca
ca
efetivamente anulando o efeito desejado pela defini¸˜o deste recurso.
ca
Para controlar esta situa¸˜o, o programador pode assegurar ao compilador que uma determinada rotina
ca
(n˜o somente fun¸˜es) n˜o possui efeitos laterais ao incluir a palavra-chave PURE ` declara¸˜o SUBROUTINE
a
co
a
a
ca
ou FUNCTION:
PURE SUBROUTINE ...
--------------------------PURE FUNCTION ...
Em termos pr´ticos, esta palavra-chave assegura ao compilador que:
a
ˆ se a rotina ´ uma fun¸˜o, esta n˜o altera os seus argumentos mudos;
e
ca
a
ˆ a rotina n˜o altera nenhuma parte de uma vari´vel acessada por associa¸˜o ao hospedeiro (rotina
a
a
ca
interna) ou associa¸˜o por uso (m´dulos);
ca
o
ˆ a rotina n˜o possui nenhuma vari´vel local com o atributo SAVE;
a
a
ˆ a rotina n˜o executa opera¸˜es em um arquivo externo;
a
co
ˆ a rotina n˜o cont´m um comando STOP.
a
e

Para assegurar que estes requerimentos sejam cumpridos e que o compilador possa facilmente verificar o seu
cumprimento, as seguintes regras adicionais s˜o impostas:
a
ˆ qualquer argumento mudo que seja o nome de uma rotina e qualquer rotina invocada devem tamb´m
e
ser puras e ter a interface expl´
ıcita;
ˆ as inten¸˜es de um argumento mudo qualquer devem ser declaradas, exceto se este seja uma rotina ou
co
um ponteiro, e a inten¸˜o deve sempre ser IN no caso de uma fun¸˜o;
ca
ca
ˆ qualquer rotina interna de uma rotina pura tamb´m deve ser pura;
e
ˆ uma vari´vel que ´ acessada por associa¸˜o ao hospedeiro ou por uso ou ´ um argumento mudo de
a
e
ca
e
inten¸ao IN n˜o pode ser o alvo de uma atribui¸˜o de ponteiro; se a vari´vel ´ do tipo derivado com
c˜
a
ca
a
e
uma componente de ponteiro, ela n˜o pode estar no lado direito de uma atribui¸˜o e ela n˜o pode
a
ca
a
estar associada como o argumento real de um argumento mudo que seja um ponteiro ou que tenha
inten¸oes OUT ou INOUT.
c˜

Esta ultima regra assegura que um ponteiro local n˜o pode causar um efeito lateral.
´
a
A principal raz˜o para se permitir subrotinas puras est´ na possibilidade de seu uso em construtos
a
a
FORALL. Por´m, ao contr´rio de fun¸˜es, uma subrotina pura pode ter argumentos mudos com inten¸˜es
e
a
co
co
OUT ou INOUT ou atributo POINTER. A sua existˆncia tamb´m oferece a possibilidade de se fazer chamadas
e
e
a subrotinas de dentro de fun¸˜es puras.
co
Uma rotina externa ou muda que seja usada como rotina pura deve possuir uma interface expl´
ıcita que
a caracterize inequivocamente como tal. Contudo, a rotina pode ser usada em outros contextos sejam o uso
de um bloco de interface ou com uma interface que n˜o a caracterize como pura. Isto permite que rotinas
a
em bibliotecas sejam escritas como puras sem que elas sejam obrigatoriamente usadas como tal.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
106

8.2. Sub-programas

Todas as fun¸˜es intr´
co
ınsecas (cap´
ıtulo 7) s˜o puras e, portanto, podem ser chamadas livremente de dentro
a
de qualquer rotina pura. Adicionalmente, a subrotina intr´
ınseca elemental MVBITS (se¸˜o 7.9.3) tamb´m ´
ca
e e
pura.
O atributo PURE ´ dado automaticamente a qualquer rotina que seja definida com o atributo ELEMENTAL
e
(se¸˜o 8.2.17).
ca

8.2.17

Rotinas elementais

Na se¸˜o 6.7 j´ foi introduzida a no¸˜o de rotinas intr´
ca
a
ca
ınsecas elementais, as quais s˜o rotinas com argua
mentos mudos escalares que podem ser invocadas com argumentos reais matriciais, desde que os argumentos
matriciais tenham todos a mesma forma (isto ´, que sejam conform´veis). Para uma fun¸˜o, a forma do
e
a
ca
resultado ´ a forma dos argumentos matriciais.
e
O Fortran 95 estende este conceito a rotinas n˜o-intr´
a
ınsecas. Uma rotina elemental criada pelo programador deve ter um dos seguintes cabe¸alhos:
c
ELEMENTAL SUBROUTINE ...
-------------------------ELEMENTAL FUNCTION ...
Um exemplo ´ fornecido abaixo. Dado o tipo derivado INTERVALO:
e
TYPE :: INTERVALO
REAL :: INF, SUP
END TYPE INTERVALO
pode-se definir a seguinte fun¸˜o elemental:
ca
ELEMENTAL FUNCTION SOMA_INTERVALOS(A,B)
INTRINSIC NONE
TYPE(INTERVALO)
:: SOMA_INTERVALOS
TYPE(INTERVALO), INTENT(IN) :: A, B
SOMA_INTERVALOS%INF= A%INF + B%INF
SOMA_INTERVALOS%SUP= A%SUP + B%SUP
RETURN
END FUNCTION SOMA_INTERVALOS
a qual soma dois intervalos de valores, entre um limite inferior e um limite superior. Nota-se que os argumentos mudos s˜o escritos como escalares, mas a especifica¸˜o ELEMENTAL possibilita o uso de matrizes
a
ca
conform´veis como argumentos reais. Neste caso, as opera¸˜es de soma dos intervalos s˜o realizadas coma
co
a
ponente a componente das matrizes A e B da maneira mais eficiente poss´
ıvel.
Uma rotina n˜o pode ser ao mesmo tempo elemental e recursiva.
a
Uma rotina elemental deve satisfazer todos os requisitos de uma rotina pura; de fato, ela j´ possui
a
automaticamente o atributo PURE. Adicionalmente, todos os argumentos mudos e resultados de fun¸˜o
ca
devem ser vari´veis escalares sem o atributo POINTER. Se o valor de um argumento mudo ´ usado em uma
a
e
declara¸˜o, especificando o tamanho ou outra propriedade de alguma vari´vel, como no exemplo
ca
a
ELEMENTAL FUNCTION BRANCO(N)
IMPLICIT NONE
INTEGER, INTENT(IN) :: N
CHARACTER(LEN= N)
:: BRANCO
BRANCO= ’ ’
RETURN
END FUNCTION BRANCO
esta fun¸˜o deve ser chamada com argumento real escalar, uma vez que um argumento real matricial
ca
resultaria em uma matriz cujos elementos seriam caracteres de comprimentos vari´veis.
a
Uma rotina externa elemental deve possuir uma interface expl´
ıcita que sempre a caracterize de forma
inequ´
ıvoca como elemental. Isto ´ exigido para que o compilador possa determinar o mecanismo de chamada
e
que acomode os elementos de matriz de forma mais eficiente. Isto contrasta com o caso de uma rotina pura,
onde a interface nem sempre necessita caracterizar a rotina como pura.
No caso de uma subrotina elemental, se algum argumento real ´ matriz, todos os argumentos com
e
inten¸˜es OUT ou INOUT devem ser matrizes. No exemplo abaixo,
co
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

107

ELEMENTAL SUBROUTINE TROCA(A,B)
IMPLICIT NONE
REAL, INTENT(INOUT) :: A, B
REAL :: TEMP
TEMP= A
A= B
B= TEMP
RETURN
END SUBROUTINE TROCA
chamar esta subrotina com um argumento escalar e um matricial est´ obviamente errado, uma vez que o
a
mecanismo de distribuir o valor da vari´vel escalar por uma matriz conform´vel com o outro argumento n˜o
a
a
a
pode ser aplicado aqui.
Se a referˆncia a uma rotina gen´rica (se¸˜o 8.3.4) ´ consistente tanto com uma rotina elemental quanto
e
e
ca
e
com uma n˜o-elemental, a segunda vers˜o ´ invocada, pois espera-se que a vers˜o elemental de uma rotina
a
a e
a
rode, em geral, mais lentamente.
Finalmente, uma rotina elemental n˜o pode ser usada como um argumento real de outra rotina.
a

8.3

M´dulos
o

Uma das novidades mais importantes introduzidas pelo Fortran 90 ´ um novo tipo de unidade de proe
grama denominada m´dulo. Um m´dulo ´ um recurso muito poderoso para transferir dados entre subo
o
e
programas e para organizar a arquitetura global de um programa grande e complexo.
A funcionalidade de um m´dulo pode ser explorada por qualquer unidade de programa que deseja fazer
o
uso (atrav´s de uma instru¸˜o USE) dos recursos disponibilizados por este. Os recursos que podem ser
e
ca
inclu´
ıdos em um m´dulo s˜o os seguintes:
o
a
Declara¸˜o de objetos globais. M´dulos devem ser empregados no lugar das declara¸˜es COMMON e INca
o
co
CLUDE, comuns no Fortran 77. Se dados globais s˜o necess´rios, por exemplo para transferir valores
a
a
entre rotinas, ent˜o estes s˜o s˜o tornados vis´
a
a a
ıveis sempre que o m´dulo ´ usado. Objetos em um
o
e
m´dulo podem ser inicializados com valores est´ticos, de tal forma que estes mantˆm seu valor em
o
a
e
diferentes unidades que usam o mesmo m´dulo.
o
Blocos de interfaces. Na maior parte das situa¸˜es ´ vantajoso congregar todos os blocos de interfaces
co e
em um ou poucos m´dulos e ent˜o usar o m´dulo sempre que uma interface expl´
o
a
o
ıcita ´ necess´ria. Isto
e
a
pode realizado em conjunto com a cl´usula ONLY.
a
Rotinas de m´dulos. Rotinas podem ser definidas internamente em um m´dulo, sendo estas tornadas
o
o
acess´
ıveis a qualquer unidade de programa que USE o m´dulo. Esta estrat´gia ´ mais vantajosa que
o
e
e
usar uma rotina externa porque em um m´dulo a interface das rotinas internas ´ sempre expl´
o
e
ıcita.
Acesso controlado a objetos. Vari´veis, rotinas e declara¸˜es de operadores podem ter a sua visibilidade
a
co
controlada por declara¸˜es ou atributos de acesso dentro de um m´dulo. Desta forma, ´ poss´
co
o
e
ıvel
especificar que um determinado objeto seja vis´
ıvel somente no interior do m´dulo. Este recurso ´
o
e
freq¨entemente utilizado para impedir que um usu´rio possa alterar o valor de um objeto de ˆmbito
u
a
a
puramente interno ao m´dulo.
o
Interfaces gen´ricas. Um m´dulo pode ser usado para definir um nome gen´rico para um conjunto de
e
o
e
rotinas, com interfaces distintas, mas que executem todas a mesma fun¸˜o. Interfaces gen´ricas podem
ca
e
ser usadas tamb´m para estender a funcionalidade de rotinas intr´
e
ınsecas.
Sobrecarga de operadores. Um m´dulo pode ser usado tamb´m para redefinir a opera¸˜o executada
o
e
ca
pelos operadores intr´
ınsecos da linguagem (= + - * / **) ou para definir novos tipos de operadores.
Extens˜o semˆntica. Um m´dulo de extens˜o semˆntica ´ uma cole¸˜o de defini¸˜es de tipos derivaa
a
o
a
a
e
ca
co
dos, rotinas e operadores sobrecarregados tais que, quando agregados a uma unidade de programa,
permitem que o usu´rio use esta funcionalidade estendida como se fizesse parte da linguagem padr˜o.
a
a
A forma geral de um m´dulo ´:
o
e
MODULE <nome m´dulo>
o
<declara¸~es vari´veis>
co
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
108

8.3. M´dulos
o
<comandos execut´veis>
a
[CONTAINS
<rotinas de m´dulo>]
o
END [MODULE [<nome m´dulo>]]
o

8.3.1

Dados globais

Em Fortran, vari´veis s˜o usualmente entidades locais. Contudo, em muitas situa¸˜es ´ necess´rio que
a
a
co e
a
alguns objetos tenham o seu valor compartilhado entre diferentes unidades de programa. A maneira mais
usual de se realizar este compartilhamento ´ atrav´s da lista de argumentos de uma rotina. Entretanto,
e
e
facilmente surge uma situa¸˜o onde uma vari´vel n˜o pode ser compartilhada como argumento de um subca
a
a
programa. Neste momento, ´ necess´ria uma outra estrat´gia para se definir dados globais. Esta necessidade
e
a
e
j´ era corriqueira no Fortran 77.
a
Fortran 77
A maneira mais usada no Fortran 77 para compartilhar dados globais ´ atrav´s de blocos common.
e
e
Um bloco common ´ uma lista de vari´veis armazenadas em uma ´rea da mem´ria do computador que ´
e
a
a
o
e
identificada atrav´s de um nome e que pode ser acessada diretamente em mais de uma unidade de programa.
e
A necessidade de se criar um bloco common surge, muitas vezes, com o uso de rotinas de bibliotecas de
aplica¸˜o generalizada, as quais s˜o definidas com um conjunto restrito de argumentos. Muitas vezes, faz-se
ca
a
necess´rio transferir informa¸˜o entre estas rotinas ou entre rotinas que usam as bibliotecas de maneira n˜o
a
ca
a
prevista na lista de argumentos.
Por exemplo, seja a subrotina INTEG, a qual realiza a integra¸˜o num´rica unidimensional de uma fun¸˜o
ca
e
ca
F(x) qualquer, no intervalo (A,B):
SUBROUTINE INTEG(F,A,B,RES)
REAL*8 A, B, F, RES, TEMP
EXTERNAL F
...
TEMP= F(X)
...
RES= <resultado>
END SUBROUTINE INTEG
Caso o programador queira integrar a fun¸˜o g(x) = cos(αx) no intervalo [0, 1], ele n˜o poder´ informar
ca
a
a
ao integrador o valor de α na lista de argumentos da subrotina INTEG. A solu¸˜o est´ no uso de um bloco
ca
a
common:
REAL*8 FUNCTION G(X)
REAL*8 X, ALFA
COMMON /VAR/ ALFA
G= COS(ALFA*X)
RETURN
END FUNCTION G
onde VAR ´ o nome que identifica o espa¸o de mem´ria onde o valor de ALFA ser´ armazenado. Assim, o
e
c
o
a
programa pode realizar a integra¸˜o usando o mesmo bloco common:
ca
PROGRAM INTEGRA
REAL*8 G, A, INT
EXTERNAL G
COMMON /VAR/ A
...
PRINT*, ’Entre com o valor de alfa:’
READ(*,*) A
C
CALL INTEG(G,0.0D0,1.0D0,INT)
C
...
END PROGRAM INTEGRA
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

109

Note que o bloco VAR aparece tanto no programa quanto na fun¸˜o; por´m n˜o h´ necessidade de ele aparecer
ca
e
a a
na subrotina INTEG.
A forma geral de um bloco common ´:
e
COMMON /<nome common>/ <lista vari´veis>
a
onde <nome common> ´ qualquer nome v´lido em Fortran e <lista vari´veis> ´ uma lista de vari´veis
e
a
a
e
a
que podem ser escalares, elementos de matrizes, se¸˜es de matrizes ou matrizes completas. Neste ultimo
co
´
´
caso, somente se utiliza o nome da matriz. E claro que a informa¸˜o acerca da natureza e tipo das vari´veis
ca
a
listadas no bloco common deve ser fornecida por declara¸˜es adequadas de vari´veis.
co
a
A grande desvantagem desta forma descentralizada de definir-se dados globais est´ no fato de que em
a
todas as unidades de programa que utilizam um dado bloco common, as vari´veis listadas nele devem cona
cordar em n´mero, ordem, natureza e tipo. Caso o programador esteja desenvolvendo um c´digo complexo,
u
o
composto por um n´mero grande de unidades que usam o mesmo bloco common, e ele sinta a necessidade
u
de alterar de alguma forma a lista de vari´veis em uma determinada unidade, ele dever´ buscar em todas
a
a
unidades restantes que fazem referˆncia ao mesmo bloco e realizar a mesma altera¸˜o; caso contr´rio, mesmo
e
ca
a
que o programa compile e linke sem erro, ´ quase certo que as vari´veis ser˜o compartilhadas de forma incoe
a
a
´ a
erente entre as diferentes unidade de programa e este acabe gerando resultados incorretos. E f´cil perceber
que este controle torna-se sucessivamente mais dif´ ` medida que a complexidade do programa aumenta.
ıcil a
Os blocos common s˜o ainda aceitos em Fortran 90/95; por´m, o seu uso n˜o ´ recomendado, pela raz˜o
a
e
a e
a
exposta acima.
Fortran 90/95
O uso de um m´dulo fornece um mecanismo centralizado de defini¸˜o de objetos globais. Por exemplo,
o
ca
suponha que se queira ter acesso `s vari´veis inteiras I, J e K e `s vari´veis reais A, B e C em diferentes
a
a
a
a
unidades de programa. Um m´dulo que permitira o compartilhamento destas vari´veis ´ o seguinte:
o
a
e
MODULE GLOBAIS
IMPLICIT NONE
INTEGER :: I, J, K
REAL
:: A, B, C
END MODULE GLOBAIS
Estas vari´veis se tornam acess´
a
ıveis a outras unidades de programa (inclusive outros m´dulos) atrav´s da
o
e
instru¸˜o USE, isto ´:
ca
e
USE GLOBAIS
A instru¸˜o USE ´ n˜o execut´vel e deve ser inserida logo ap´s o cabe¸alho da unidade de programa (PROGRAM,
ca
e a
a
o
c
FUNCTION, SUBROUTINE ou MODULE) e antes de qualquer outra instru¸˜o n˜o execut´vel, tal como uma
ca
a
a
declara¸˜o de vari´veis. Uma unidade de programa pode invocar um n´mero arbitr´rio de m´dulos usando
ca
a
u
a
o
uma s´rie de instru¸˜es USE. Um m´dulo pode usar outros m´dulos, por´m um m´dulo n˜o pode usar a si
e
co
o
o
e
o
a
pr´prio, seja de forma direta ou indireta.
o
Assim, o m´dulo GLOBAIS pode ser usado da seguinte forma:
o
FUNCTION USA_MOD(X)
USE GLOBAIS
IMPLICIT NONE
REAL
:: USA_MOD
REAL, INTENT(IN) :: X
USA_MOD= I*A - J*B + K*C - X
RETURN
END FUNCTION USA_MOD
O vantagem de um m´dulo sobre um bloco COMMON para compartilhar objetos globais ´ evidente. A defio
e
ni¸˜o dos nomes, tipos e esp´cies das vari´veis ´ realizada em uma unica unidade de programa, a qual ´
ca
e
a
e
´
e
simplesmente usada por outras, estabelecendo assim um controle centralizado sobre os objetos.
O uso de vari´veis de um m´dulo pode causar problemas se o mesmo nome ´ usado para diferentes
a
o
e
vari´veis em partes diferentes de um programa. A declara¸˜o USE pode evitar este problema ao permitir a
a
ca
especifica¸˜o de um nome local distinto daquele definido no m´dulo, por´m que ainda permita o acesso aos
ca
o
e
dados globais. Por exemplo,
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
110

8.3. M´dulos
o
...
USE GLOBAIS, R => A, S => B
...
USA_MOD= I*R - J*S + K*C - X
...

Aqui, os nomes R e S s˜o usado para acessar as vari´veis globais A e B, definidas no m´dulo, caso estes
a
a
o
nomes ultimos sejam usados para diferentes vari´veis na mesma unidade de programa. Os s´
´
a
ımbolos “=>“
promovem a liga¸˜o do nome local com o nome no m´dulo. Tudo se passa como se R fosse o apelido de A e S
ca
o
o apelido de B nesta unidade de programa. Os ponteiros em Fortran 90/95 tamb´m atuam como apelidos,
e
por´m, neste caso, pode-se usar tanto o nome verdadeiro de uma vari´vel quanto o nome de um ponteiro
e
a
que aponta a ela.
Existe tamb´m uma forma da declara¸˜o USE que limita o acesso somente a certos objetos dentro de um
e
ca
m´dulo. Este recurso n˜o ´ exatamente igual ao uso dos atributos PUBLIC ou PRIVATE (se¸˜o 8.3.3), uma
o
a e
ca
vez que ele atua somente na unidade que acessa o m´dulo, e n˜o sobre o m´dulo em geral. O recurso requer
o
a
o
o uso do qualificador ONLY, seguido de dois pontos “:” e uma <lista only>:
USE <nome m´dulo>, ONLY: <lista only>
o
Por exemplo para tornar somente as vari´veis A e C do m´dulo GLOBAIS acess´
a
o
ıveis em uma dada unidade de
programa, a declara¸˜o fica:
ca
...
USE GLOBAIS, ONLY: A, C
...
Os dois ultimos recursos podem ser tamb´m combinados:
´
e
...
USE GLOBAIS, ONLY: R => A
...
para tornar somente a vari´vel A acess´
a
ıvel, por´m com o nome R. Uma unidade de programa pode ter mais
e
de uma declara¸ao USE referindo-se ao mesmo m´dulo. Por conseguinte, deve-se notar que que um USE com
c˜
o
o qualificador ONLY n˜o cancela uma declara¸ao USE menos restritiva.
a
c˜
Um uso freq¨ente de m´dulos para armazenar dados globais consiste em defini¸˜es de parˆmetros de
u
o
co
a
esp´cie de tipo, constantes universais matem´ticas e/ou f´
e
a
ısicas e outros objetos est´ticos, como no exemplo
a
abaixo:
! *** Module E s p c o n s t ***
! D e f i n e e s p ´ c i e s de t i p o p a d r o e s e c o n s t a n t e s u n i v e r s a i s .
e
˜
!
M D L esp const
O UE
!
INTEGER, P R M T R : : I4B = SELECTED INT KIND ( 9 )
A A EE
INTEGER, P R M T R : : I2B = SELECTED INT KIND ( 4 )
A A EE
INTEGER, P R M T R : : I1B = SELECTED INT KIND ( 2 )
A A EE
integer , parameter : : sp= kind ( 1 . 0 )
integer , parameter : : dp= s e l e c t e d r e a l k i n d ( 2 * precision ( 1 . 0 s p ) )
integer , parameter : : qp= s e l e c t e d r e a l k i n d ( 2 * precision ( 1 . 0 dp ) )
complex ( kind= dp ) , parameter : : z1= ( 1 . 0 dp , 0 . 0 dp ) , z i= ( 0 . 0 dp , 1 . 0 dp )
REAL(DP) , P R M T R : : PI=
A A EE
3.14159265358979323846264338327950288419717
REAL(DP) , P R M T R : : PID2=
A A EE
1.57079632679489661923132169163975144209858
REAL(DP) , P R M T R : : TWOPI=
A A EE
6.28318530717958647692528676655900576839434
r e a l ( dp ) , parameter : : r t p i=
1.77245385090551602729816748334114518279755
REAL(DP) , P R M T R : : SQRT2=
A A EE
1.41421356237309504880168872420969807856967
r e a l ( dp ) , parameter : : e u l e r e= 2 . 7 1 8 2 8 1 8 2 8 4 5 9 0 4 5 2 3 5 3 6 0 2 8 7 4 7 1 3 5 2 6 6 2 4 9 7 7 5 7 2 5
REAL(SP ) , P R M T R : : PI S=
A A EE
3.14159265358979323846264338327950288419717
REAL(SP ) , P R M T R : : PID2 S= 1 . 5 7 0 7 9 6 3 2 6 7 9 4 8 9 6 6 1 9 2 3 1 3 2 1 6 9 1 6 3 9 7 5 1 4 4 2 0 9 8 5 8
A A EE
REAL(SP ) , P R M T R : : TWOPI s= 6 . 2 8 3 1 8 5 3 0 7 1 7 9 5 8 6 4 7 6 9 2 5 2 8 6 7 6 6 5 5 9 0 0 5 7 6 8 3 9 4 3 4
A A EE
r e a l ( sp ) , parameter : : r t p i s= 1 . 7 7 2 4 5 3 8 5 0 9 0 5 5 1 6 0 2 7 2 9 8 1 6 7 4 8 3 3 4 1 1 4 5 1 8 2 7 9 7 5 5
Autor: Rudi Gaelzer – IFM/UFPel

dp
dp
dp
dp
dp
dp
sp
sp
sp
sp

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

111

Programa 8.3: Ilustra uso de m´dulo para armazenar dados globais.
o

M D L modu1
O UE
i m p l i c i t none
real , parameter : : p i= 3 . 1 4 1 5 9 2 6 5 3 6
real , parameter : : e u l e r e= 2 . 7 1 8 2 8 1 8 2 8
END M D L modu1
O UE
! *****************************************
program mod1
use modu1
i m p l i c i t none
real : : x
do
print * , ”Entre com o v a l o r de x : ”
read * , x
print * , ”s e n ( p i * x)= ” , s e n ( )
print * , ” l n ( e * x)= ” , l n ( )
end do
CONTAINS
function s e n ( )
real : : sen
s e n= s i n ( p i * x )
return
end function s e n
!
function l n ( )
real : : ln
l n= l o g ( e u l e r e * x )
return
end function l n
end program mod1

REAL(SP ) , P R M T R : : SQRT2 S= 1 . 4 1 4 2 1 3 5 6 2 3 7 3 0 9 5 0 4 8 8 0 1 6 8 8 7 2 4 2 0 9 6 9 8 0 7 8 5 6 9 6 7 s p
A A EE
!
! Fundamental p h y s i c a l c o n s t a n t s , o b t a i n e d from NIST :
!
h t t p : / / p h y s i c s . n i s t . gov / cuu / C o n s t a n t s / i n d e x . html
r e a l ( dp ) , parameter : : rmemp= 5 . 4 4 6 1 7 0 2 1 7 3 e−4 dp ! E l e c t r o n −p r o t o n mass r a t i o .
r e a l ( dp ) , parameter : : rmpme= 1 8 3 6 . 1 5 2 6 7 2 6 1 dp ! Protron−e l e c t r o n mass r a t i o .
END M D L e s p c o n s t
O UE
O programa-exemplo mod1.f90 (programa 8.3), ilustra o uso de um m´dulo para armazenar dados
o
globais.

8.3.2

Rotinas de m´dulos
o

Rotinas podem ser definidas em m´dulos e estas s˜o denominadas rotinas de m´dulos. Estas podem ser
o
a
o
tanto subrotinas quanto fun¸˜es e ter a mesma forma de rotinas internas definidas dentro de outras unidades
co
de programa. O n´mero de rotinas de m´dulo ´ arbitr´rio.
u
o
e
a
Rotinas de m´dulo podem ser chamadas usando o comando CALL usual ou fazendo referˆncia ao nome
o
e
de uma fun¸˜o. Contudo, estas somente s˜o acess´
ca
a
ıveis a unidades de programa que fazem uso do m´dulo
o
atrav´s da instru¸˜o USE.
e
ca
Uma rotina de m´dulo pode invocar outras rotinas de m´dulo contidas no mesmo m´dulo. As vari´veis
o
o
o
a
declaradas no m´dulo antes da palavra-chave CONTAINS s˜o diretamente acess´
o
a
ıveis a todas as rotinas deste,
por associa¸˜o ao hospedeiro. Contudo, vari´veis declaradas localmente em um determinado sub-programa
ca
a
de m´dulo s˜o opacas aos outros sub-programas. Caso o m´dulo invoque outro m´dulo com uma instru¸˜o
o
a
o
o
ca
USE antes da palavra-chave CONTAINS, estes objetos tamb´m se tornam acess´
e
ıveis a todas as rotinas de
m´dulo. Por outro lado, uma determinada rotina de m´dulo pode usar localmente outro m´dulo (n˜o o
o
o
o
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
112

8.3. M´dulos
o

hospedeiro), em cuja situa¸˜o os objetos somente s˜o acess´
ca
a
ıveis localmente. Em suma, uma rotina de m´dulo
o
possui todas as propriedades de rotinas internas em outras unidades de programa, exceto que uma rotina
de m´dulo pode conter, por sua vez, rotinas internas a ela. Por exemplo, o seguinte m´dulo ´ v´lido:
o
o
e a
MODULE INTEG
IMPLICIT NONE
REAL :: ALFA ! Vari´vel global.
a
CONTAINS
FUNCTION FF(X)
REAL :: FF
REAL, INTENT(IN) :: X
FF= EXP(-ALFA*X*X)
FF= FF*X2(X)
RETURN
CONTAINS
FUNCTION X2(Y)
REAL :: X2
REAL, INTENT(IN) :: Y
X2= Y**2
RETURN
END FUNCTION X2
END FUNCTION FF
END MODULE INTEG
A outra grande diferen¸a est´ no fato de que as interfaces das rotinas de m´dulo s˜o expl´
c
a
o
a
ıcitas no ˆmbito
a
deste. Todavia, quando uma outra unidade de programa usa o m´dulo, todas os objetos p´blicos nele cono
u
tidos se tornam acess´
ıveis a esta, resultando que as interfaces das rotinas de m´dulo s˜o automaticamente
o
a
expl´
ıcitas tamb´m para a unidade de programa que o invoca. Portanto, um m´dulo ´ considerado a unie
o
e
dade ideal para armazenar grupos de sub-programas criados para desempenhar uma determinada tarefa,
juntamente com os objetos globais associados a estes sub-programas.
Ao se compilar um arquivo contendo um m´dulo, os compiladores automaticamente geram um novo
o
tipo de arquivo, geralmente com a extens˜o *.mod, onde as informa¸˜es contidas no m´dulo, tais como
a
co
o
vari´veis globais e interfaces, s˜o armazenadas. Quando uma outra unidade de programa faz referˆncia a
a
a
e
este m´dulo, o compilador busca estas informa¸˜es no arquivo .mod . Desta forma, cria-se um mecanismo
o
co
para verificar se as vari´veis e as interfaces est˜o sendo corretamente utilizadas pela unidade que chama o
a
a
m´dulo. Quando o m´dulo n˜o define um rotina interna, n˜o ´ necess´rio guardar o arquivo objeto (*.o
o
o
a
a e
a
ou *.obj) associado, bastando guardar o arquivo *.mod. Por esta raz˜o, muitos compiladores oferecem
a
uma chave extra de compila¸˜o atrav´s da qual nenhum arquivo objeto ´ criado, mas somente o arquivo de
ca
e
e
m´dulo.
o
Rotinas de m´dulo pode ser uteis por diversas raz˜es. Por exemplo, um m´dulo que define a estrutura de
o
´
o
o
um conjunto particular de dados pode tamb´m incluir rotinas especiais, necess´rias para operar com estes
e
a
dados; ou um m´dulo pode ser usado para conter uma biblioteca de rotinas relacionadas entre si.
o
Como exemplo, um m´dulo pode ser usado para “adicionar” vari´veis de tipo derivado:
o
a
MODULE MOD_PONTO
IMPLICIT NONE
TYPE :: PONTO
REAL :: X, Y
END TYPE PONTO
CONTAINS
FUNCTION ADPONTOS(P,Q)
TYPE(POINT) :: ADPONTOS
TYPE(POINT), INTENT(IN) :: P, Q
ADPONTOS%X= P%X + Q%X
ADPONTOS%Y= P%Y + Q%Y
RETURN
END FUNCTION ADPONTOS
END MODULE MOD_PONTO
Neste caso, o programa principal usa este m´dulo:
o
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

113

Programa 8.4: Ilustra o uso de rotinas de m´dulo.
o

M D L modu2
O UE
i m p l i c i t none
real , parameter : : p i= 3 . 1 4 1 5 9 2 6 5 3 6
real , parameter : : e u l e r e= 2 . 7 1 8 2 8 1 8 2 8
real : : x
CONTAINS
function s e n ( )
real : : sen
s e n= s i n ( p i * x )
return
end function s e n
!
function l n ( )
real : : ln
l n= l o g ( e u l e r e * x )
return
end function l n
END M D L modu2
O UE
! *****************************************
program mod2
use modu2
i m p l i c i t none
do
print * , ”Entre com o v a l o r de x : ”
read * , x
print * , ”s e n ( p i * x)= ” , s e n ( )
print * , ” l n ( e * x)= ” , l n ( )
end do
end program mod2

PROGRAM P_PONTO
USE MOD_PONTO
IMPLICIT NONE
TYPE(POINT) :: PX, PY, PZ
...
PZ= ADPONTO(PX,PY)
...
END PROGRAM P_PONTO
O recurso avan¸ado de sobrecarga de operador (operator overloading) permite redefinir a opera¸˜o de adi¸˜o
c
ca
ca
(+), por exemplo, dentro do ˆmbito do m´dulo M_PONTO, de tal forma que o processo de adi¸˜o de duas
a
o
ca
vari´veis do tipo PONTO automaticamente iria chamar a fun¸˜o ADPONTO. Desta forma, ao inv´s do programa
a
ca
e
chamar esta fun¸˜o, bastaria realizar a opera¸˜o:
ca
ca
PZ= PX + PY
Entretanto, este recurso n˜o ser´ discutido aqui.
a
a
O programa-exemplo mod2.f90 (programa 8.4) ´ igual ao mod1.f90, por´m usando rotinas de m´dulo.
e
e
o

8.3.3

Atributos e declara¸˜es PUBLIC e PRIVATE
co

Usualmente, todas as entidades em um m´dulo est˜o dispon´
o
a
ıveis para qualquer unidade de programa
que chame este m´dulo com a instru¸˜o USE. Contudo, em certas situa¸˜es ´ recomend´vel proibir o uso
o
ca
co e
a
de certas entidades (objetos globais e/ou rotinas) contidas no m´dulo para for¸ar o usu´rio a invocar as
o
c
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
114

8.3. M´dulos
o

rotinas de m´dulo que realmente deveriam ser acess´
o
ıveis a este, ou para permitir flexibilidade no aperfei¸oc
amento das entidades contidas no m´dulo sem haver a necessidade de informar o usu´rio a respeito destes
o
a
aperfei¸oamentos.
c
Este controle ´ exercido atrav´s dos atributos ou declara¸˜es PUBLIC ou PRIVATE. Por exemplo, abaixo
e
e
co
temos a declara¸˜es de vari´veis com dois atributos distintos:
co
a
REAL, PUBLIC :: X, Y, Z
INTEGER, PRIVATE :: U, V, W
Dentro deste conjunto de vari´veis, somente X, Y e Z s˜o acess´
a
a
ıveis ` unidade de programa que acessa este
a
m´dulo.
o
Outra maneira de se estabelecer o controle de acesso ´ atrav´s de declara¸˜es, as quais listam os nomes
e
e
co
dos objetos que s˜o p´blicos ou privados:
a u
PUBLIC :: X, Y, Z
PRIVATE :: U, V, W
A forma geral da declara¸˜o ´:
ca e
PUBLIC [[::] <lista acesso>]
PRIVATE [[::] <lista acesso>]
Caso nenhum controle ´ estabelecido em um m´dulo, seja atrav´s de um atributo ou de uma declara¸˜o,
e
o
e
ca
todas as entidades tˆm o atributo PUBLIC.
e
Se uma declara¸˜o PUBLIC ou PRIVATE n˜o possui uma lista de entidades, esta confirma ou altera o
ca
a
acesso padr˜o. Assim, a declara¸˜o
a
ca
PUBLIC
confirma o acesso padr˜o, ao passo que a declara¸˜o
a
ca
PRIVATE
altera o acesso padr˜o. Desta forma, uma seq¨ˆncia de declara¸˜es como as abaixo:
a
ue
co
...
PRIVATE
PUBLIC <lista acesso>
...
confere aos nomes na <lista acesso> o atributo PUBLIC enquanto que todas as entidades restantes no
m´dulo s˜o privadas, podendo ser acessadas somente dentro do ˆmbito do m´dulo.
o
a
a
o

8.3.4

Interfaces e rotinas gen´ricas
e

Outro recurso poderoso introduzido pelo Fortran 90 ´ a habilidade do programador definir suas pr´e
o
prias rotinas gen´ricas, de tal forma que um unico nome ´ suficiente para invocar uma determinada rotina,
e
´
e
enquanto que a a¸˜o que realmente ´ executada quando este nome ´ usado depende do tipo de seus argumenca
e
e
tos. Embora possam ser declaradas em quaisquer unidades de programa, rotinas gen´ricas s˜o usualmente
e
a
definidas em m´dulos.
o
Uma rotina gen´rica ´ definido usando-se um bloco interfaces e um nome gen´rico ´ usado para todas as
e
e
e
e
rotinas definidas dentro deste bloco de interfaces. Assim, a forma geral ´:
e
INTERFACE <nome gen´rico>
e
<bloco interface rotina espec´fica 1>
ı
<bloco interface rotina espec´fica 2>
ı
...
END INTERFACE <nome gen´rico>
e
onde <bloco interface rotina espec´fica 1>, etc, s˜o os blocos das interfaces das rotinas espec´
ı
a
ıficas,
isto ´, que se referem a um dado conjunto de tipos de vari´veis, e que s˜o acessadas atrav´s do <nome
e
a
a
e
gen´rico>. As rotinas per se podem se encontrar em outras unidades; por exemplo, elas podem ser rotinas
e
externas. O uso do <nome gen´rico> no final do bloco somente ´ permitido a partir do Fortran 95.
e
e
Como um m´dulo ´ a unidade de programa ideal para armazenar todas estas rotinas espec´
o
e
ıficas relacionadas entre si e como as interfaces das rotinas de m´dulo s˜o sempre expl´
o
a
ıcitas, estas rotinas gen´ricas s˜o,
e
a
em geral, definidas dentro de m´dulos. Neste caso, a declara¸˜o
o
ca
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

115

MODULE PROCEDURE <lista nomes rotinas>
´ inclu´ no bloco de interface para nomear as rotinas de m´dulo que s˜o referidas atrav´s do nome gen´rico.
e
ıda
o
a
e
e
Assim, a declara¸˜o geral ´:
ca
e
INTERFACE <nome gen´rico>
e
[<blocos interfaces>]
[MODULE PROCEDURE <lista nomes rotinas>]
! Em Fortran 95 blocos de interfaces e declara¸~es MODULE PROCEDURE
co
!
podem aparecer em qualquer ordem.
END INTERFACE [<nome gen´rico>]
e
! Somente em Fortran 95 o nome gen´rico ´ aceito aqui.
e
e
Deve-se notar que todos os nomes na <lista nomes rotinas> devem ser de rotinas de m´dulo acess´
o
ıveis;
portanto, elas n˜o necessariamente devem estar definidas no mesmo m´dulo onde a interface gen´rica ´
a
o
e
e
estabelecida, bastando que elas sejam acess´
ıveis por associa¸˜o de uso.
ca
Para demonstrar o poderio de uma interface gen´rica, ser´ utilizada novamente a subrotina TROCA, a qual
e
a
foi definida primeiramente na p´gina 95 e depois, na forma de uma subrotina elemental, na se¸˜o 8.2.17.
a
ca
O m´dulo gentroca na p´gina 116 define o nome gen´rico de uma s´rie de subrotinas elementais TROCA
o
a
e
e
associadas a vari´veis dos tipos real, inteiro, l´gico e do tipo derivado ponto, o qual ´ definido no mesmo
a
o
e
m´dulo.
o
Este m´dulo ´ utilizado ent˜o em duas situa¸˜es distintas. Na primeira vez, o m´dulo ser´ utilizado para
o
e
a
co
o
a
a
trocar o valor de duas vari´veis escalares do tipo ponto, como no programa usa gentroca.f90 na p´gina
a
117.
Posteriormente, o mesmo m´dulo ser´ utilizado para trocar os elementos de duas matrizes inteiras,
o
a
como no programa usa_gt_mat.f90, tamb´m listado na p´gina 117.
e
a

Uma declara¸˜o MODULE PROCEDURE somente ´ permitida se um <nome gen´rico> ´ fornecido. Por´m,
ca
e
e
e
e
o nome gen´rico pode ser igual ao nome de uma das rotinas declaradas na <lista nomes rotinas>. Em
e
conjunto com esta propriedade, o nome gen´rico definido em um m´dulo pode ser o mesmo de outro nome
e
o
gen´rico acess´ ao m´dulo, inclusive no caso onde o nome gen´rico corresponde ao de uma rotina intr´
e
ıvel
o
e
ınseca.
Neste caso, o m´dulo estar´ estendendo o intervalo de aplica¸˜o de uma rotina intr´
o
a
ca
ınseca.
As rotinas `s quais s˜o dadas um certo nome gen´rico devem ser todas ou subrotinas ou fun¸˜es, incluindo
a
a
e
co
as intr´
ınsecas quando uma rotina intr´
ınseca ´ estendida. Quaisquer duas rotinas n˜o-intr´
e
a
ınsecas associadas
ao mesmo nome gen´rico devem ter argumentos que diferem de tal forma que qualquer invoca¸˜o ´ feita de
e
ca e
forma inequ´
ıvoca. As regras s˜o que:
a
1. uma delas tenha mais argumentos obrigat´rios mudos de um tipo, esp´cie e posto particulares que a
o
e
outra ou
2. que ao menos uma delas tenha um argumento mudo obrigat´rio tal que
o
(a) corresponda por posi¸˜o na lista de argumentos a um argumento mudo que n˜o esteja presente
ca
a
na outra, ou esteja presente com um tipo e/ou esp´cie distinta ou com posto distinto, e
e
(b) corresponda por nome a um argumento mudo que n˜o esteja presente na outra, ou presente com
a
tipo e/ou esp´cie diferente ou com posto diferente.
e
Para o caso (2), ambas as regras s˜o necess´rias para descartar a possibilidade de invoca¸˜o amb´
a
a
ca
ıgua por
uso de palavras-chave. Como exemplo onde haver´ ambig¨idade, o exemplo abaixo:
a
u
!Exemplo de defini¸~o amb´gua de nome gen´rico
ca
ı
e
INTERFACE F
MODULE PROCEDURE FXI, FIX
END INTERFACE F
CONTAINS
FUNCTION FXI(X,I)
REAL :: FXI
REAL, INTENT(IN) :: X
INTEGER, INTENT(IN) :: I
...
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
116

8.3. M´dulos
o

! D e f i n e nome g e n ´ r i c o para t r o c a de duas v a r i ´ v e i s q u a i s q u e r .
e
a
M D L gentroca
O UE
i m p l i c i t none
type : : ponto
real : : x , y
end type ponto
!
INTERFACE t r o c a
M D L PROCEDURE t r o c a p o n t o , t r o c a r e a l , t r o c a i n t , t r o c a l o g
O UE
END INTERFACE t r o c a
!
CONTAINS
e l e m e n t a l subroutine t r o c a p o n t o ( a , b )
type ( ponto ) , intent ( inout ) : : a , b
type ( ponto ) : : temp
temp= a
a= b
b= temp
end subroutine t r o c a p o n t o
!
e l e m e n t a l subroutine t r o c a r e a l ( a , b )
real , intent ( inout ) : : a , b
r e a l : : temp
temp= a
a= b
b= temp
end subroutine t r o c a r e a l
!
e l e m e n t a l subroutine t r o c a i n t ( a , b )
integer , intent ( inout ) : : a , b
integer : : temp
temp= a
a= b
b= temp
end subroutine t r o c a i n t
!
e l e m e n t a l subroutine t r o c a l o g ( a , b )
l o g i c a l , intent ( inout ) : : a , b
l o g i c a l : : temp
temp= a
a= b
b= temp
end subroutine t r o c a l o g
END M D L g e n t r o c a
O UE

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

117

program u s a g e n t r o c a
use g e n t r o c a
type ( ponto ) : : b= ponto ( 1 . 0 , 0 . 0 ) , c= ponto ( 1 . 0 , 1 . 0 )
print * , ’ V a l o r e s o r i g i n a i s : ’
print * , b , c
call troca (b , c )
print * , ’ Novos v a l o r e s : ’
print * , b , c
end program u s a g e n t r o c a

program u s a g t m a t
use g e n t r o c a
integer , dimension ( 2 , 2 ) : : b ,
b= r e s h a p e ( s o u r c e= ( / ( ( i+j ,
c= r e s h a p e ( s o u r c e= ( / ( ( i+j ,
print * , ’ V a l o r e s o r i g i n a i s : ’
do i= 1 , 2
print * , b ( i , : ) , ”
”,c(i
end do
call troca (b , c )
print * , ’ Novos v a l o r e s : ’
do i= 1 , 2
print * , b ( i , : ) , ”
”,c(i
end do
end program u s a g t m a t

c
i= 1 , 2 ) , j= 1 , 2 ) / ) , shape= ( / 2 , 2 / ) )
i= 3 , 4 ) , j= 3 , 4 ) / ) , shape= ( / 2 , 2 / ) )

,:)

,:)

END FUNCTION FXI
!
FUNCTION FIX(I,X)
REAL :: FIX
REAL, INTEN(IN) :: X
INTEGER, INTENT(IN) :: I
...
END FUNCTION FIX
Neste caso, a chamada ao nome gen´rico F ser´ n˜o-amb´
e
a a
ıgua no caso de argumentos posicionais:
A= F(INT,VAR)
por´m ser´ amb´
e
a
ıgua para chamada usando palavras-chave:
A= F(I= INT, X= VAR)
Se uma invoca¸˜o gen´rica ´ amb´
ca
e
e
ıgua entre uma rotina intr´
ınseca e uma n˜o-intr´
a
ınseca, esta ultima ´ sempre
´
e
invocada.

8.3.5

Estendendo rotinas intr´
ınsecas via blocos de interface gen´ricos
e

Como j´ foi mencionado, uma rotina intr´
a
ınseca pode ser estendida ou tamb´m redefinida. Uma rotina
e
intr´
ınseca estendida suplementa as rotinas intr´
ınsecas espec´
ıficas j´ existentes. Uma rotina intr´
a
ınseca redefinida substitui uma rotina intr´
ınseca espec´
ıfica existente. Desta forma ´ poss´ ampliar um determinado
e
ıvel
c´lculo de uma fun¸˜o, por exemplo, para interfaces n˜o previstas pelo padr˜o da linguagem (extens˜o)
a
ca
a
a
a
e/ou substituir o processo de c´lculo do valor da fun¸˜o por um c´digo distinto daquele implementado no
a
ca
o
compilador (substitui¸˜o).
ca
Quando um nome gen´rico ´ igual ao nome gen´rico de uma rotina intr´
e
e
e
ınseca e o nome ´ declarado com
e
o atributo ou declara¸˜o INTRINSIC (ou aparece em um contexto intr´
ca
ınseco), a interface gen´rica estende a
e
rotina gen´rica intr´
e
ınseca.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
ˆ
8.4. Ambito (Scope)

118

Quando um nome gen´rico ´ igual ao nome gen´rico de uma rotina intr´
e
e
e
ınseca e este nome n˜o possui o
a
atributo INTRINSIC (nem possui este atributo pelo contexto), a rotina gen´rica redefine a rotina gen´rica
e
e
intr´
ınseca.
Como exemplo, o m´dulo EXT_SINH abaixo estende o c´lculo da fun¸˜o seno hiperb´lico para um arguo
a
ca
o
mento escalar complexo, enquanto que o padr˜o da linguagem somente considera argumentos reais (se¸˜o
a
ca
7.5):
MODULE EXT_SINH
IMPLICIT NONE
INTRINSIC :: SINH
!
INTERFACE SINH
MODULE PROCEDURE SINH_C
END INTERFACE SINH
!
CONTAINS
FUNCTION SINH_C(Z)
COMPLEX
:: SINH_C
COMPLEX, INTENT(IN) :: Z
REAL :: X,Y
X= REAL(Z)
Y= AIMAG(Z)
SINH_C= CMPLX(SINH(X)*COS(Y),COSH(X)*SIN(Y))
RETURN
END FUNCTION SINH_C
END MODULE EXT_SINH

8.4

ˆ
Ambito (Scope)

J´ foi mencionado neste texto, em diversos lugares, o ˆmbito de um certo nome de vari´vel. O ˆmbito
a
a
a
a
de um objeto nomeado ou de um r´tulo ´ o conjunto de unidades de ambito, que n˜o se sobrep˜e, onde o
o
e
ˆ
a
o
nome deste objeto pode ser usado sem ambig¨idade.
u
Uma unidade de ˆmbito ´ qualquer um dos seguintes:
a
e
ˆ uma defini¸˜o de tipo derivado;
ca
ˆ o corpo de um bloco de interfaces de rotinas, excluindo quaisquer defini¸˜es de tipo derivado e blocos
co
de interfaces contidos dentro deste, ou
ˆ uma unidade de programa ou sub-programa, excluindo defini¸˜es de tipo derivado, blocos de interfaces
co
e rotinas internas contidas dentro desta unidade.

8.4.1

ˆ
Ambito dos r´tulos
o

Toda unidade de programa ou sub-programa, interno ou externo, tem seu conjunto independente de
r´tulos. Portanto, o mesmo r´tulo pode ser usado em um programa principal e em seus sub-programas
o
o
internos sem ambig¨idade.
u
Assim, o ˆmbito de um r´tulo ´ um programa principal ou sub-programa, excluindo quaisquer suba
o
e
programas internos que eles contenham. O r´tulo pode ser usado sem ambig¨idade em qualquer ponto entre
o
u
os comandos execut´veis de seu ˆmbito.
a
a

8.4.2

ˆ
Ambito dos nomes

O ˆmbito de um nome declarado em uma unidade de programa estende-se do cabe¸alho da unidade de
a
c
programa ao seu comando END. O ˆmbito de um nome declarado em um programa principal ou rotina externa
a
estende-se a todos os sub-programas que eles contˆm, exceto quando o nome ´ redeclarado no sub-programa.
e
e
O ˆmbito de um nome declarado em uma rotina interna ´ somente a pr´pria rotina, e n˜o os outros
a
e
o
a
sub-programas internos. O ˆmbito do nome de um sub-programa interno e do n´mero e tipos dos seus
a
u
argumentos estende-se por toda a unidade de programa que o cont´m, inclusive por todos os outros sube
programas internos.
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 8. Sub-Programas e M´dulos
o

119

O ˆmbito de um nome declarado em um m´dulo estende-se a todas as unidades de programa que usam
a
o
este m´dulo, exceto no caso em que a entidade em quest˜o tenha o atributo PRIVATE, ou ´ renomeada na
o
a
e
unidade de programa que usa o m´dulo ou quando a instru¸˜o USE apresenta o qualificador ONLY e a entidade
o
ca
em quest˜o n˜o esteja na <lista only>. O ˆmbito de um nome declarado em um m´dulo estende-se a todos
a a
a
o
os sub-programas internos, excluindo aqueles onde o nome ´ redeclarado.
e
Considerando a defini¸˜o de unidade de ˆmbito acima,
ca
a
ˆ Entidades declaradas em diferentes unidades de ˆmbito s˜o sempre distintas, mesmo que elas tenham
a
a
o mesmo nome e propriedades.
ˆ Dentro de uma unidade de ˆmbito, cada entidade nomeada deve possuir um nome distinto, com a
a
exce¸˜o de nomes gen´ricos de rotinas.
ca
e
ˆ Os nomes de unidades de programas s˜o globais; assim, cada nome deve ser distinto dos outros e
a
distinto de quaisquer entidades locais na unidade de programa.
ˆ O ˆmbito do nome de uma rotina interna estende-se somente por toda a unidade de programa que a
a
cont´m.
e
ˆ O ˆmbito de um nome declarado em uma rotina interna ´ esta rotina interna.
a
e

Este conjunto de regras resume a defini¸˜o de ˆmbito de um nome.
ca
a
Nomes de entidades s˜o acess´
a
ıveis por associa¸˜o ao hospedeiro ou associa¸˜o por uso quando:
ca
ca
Associa¸˜o ao hospedeiro. O ˆmbito de um nome declarado em uma unidade de programa estende-se
ca
a
do cabe¸alho da unidade de programa ao comando END.
c
Associa¸˜o por uso. O ˆmbito de um nome declarado em um m´dulo, o qual n˜o possui o atributo
ca
a
o
a
PRIVATE, estende-se a qualquer unidade de programa que usa o m´dulo.
o
Nota-se que ambos os tipos de associa¸˜o n˜o se estende a quaisquer rotinas externas que possam ser
ca
a
invocadas e n˜o incluem quaisquer rotinas internas onde o nome ´ redeclarado.
a
e
Um exemplo contendo 5 unidades de ˆmbito ´ ilustrado a seguir:
a
e
MODULE AMBITO1
...
CONTAINS
SUBROUTINE AMBITO2
TYPE :: AMBITO3
...
END TYPE AMBITO3
INTERFACE
...
END INTERFACE
...
CONTAINS
FUNCTION AMBITO5(...)
...
END FUNCTION AMBITO5
END SUBROUTINE AMBITO2
END MODULO AMBITO1

Autor: Rudi Gaelzer – IFM/UFPel

!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!

Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito
Ambito

1
1
1
2
3
3
3
2
4
2
2
2
5
5
5
2
1

Impresso: 13 de abril de 2010
120

Autor: Rudi Gaelzer – IFM/UFPel

ˆ
8.4. Ambito (Scope)

Impresso: 13 de abril de 2010
Cap´
ıtulo 9

Comandos de Entrada/Sa´ de
ıda
Dados
O Fortran 90/95 possui um conjunto rico de instru¸˜es de entrada/sa´ (E/S) de dados. Entretanto,
co
ıda
este cap´
ıtulo ir´ apresentar apenas um conjunto de instru¸˜es que implementam um processo b´sico de E/S.
a
co
a
Muitos programas necessitam de dados iniciais para o seu processamento. Depois que os c´lculos estivea
rem completos, os resultados naturalmente precisam ser impressos, mostrados graficamente ou salvos para
uso posterior. Durante a execu¸˜o de um programa, algumas vezes h´ uma quantidade grande de dados
ca
a
produzidos por uma parte do programa, os quais n˜o podem ser todos armazenados na mem´ria de acesso
a
o
aleat´rio (RAM) do computador. Nesta situa¸˜o tamb´m se usam os comandos de E/S da linguagem.
o
ca
e
O Fortran 90/95 possui muitos comandos de E/S. Os mais utilizados s˜o:
a
ˆ OPEN
ˆ READ
ˆ WRITE
ˆ PRINT
ˆ CLOSE
ˆ REWIND
ˆ BACKSPACE

estes comandos est˜o todos embutidos dentro da linguagem a qual possui, adicionalmente, recursos de
a
formata¸˜o que instruem a maneira como os dados s˜o lidos ou escritos.
ca
a
At´ este ponto, todos os exemplos abordados executaram opera¸˜es de E/S de dados com teclado (ene
co
trada) e terminal (sa´
ıda). Adicionalmente, Fortran 90/95 permite que diversos outros objetos, como arquivos
de dados, estejam conectados a um programa para leitura e/ou escrita. Neste cap´
ıtulo, ser˜o abordados os
a
processos de E/S em arquivos de dados, por ser este o uso mais freq¨ente deste recurso. Outros tipos de
u
usos incluem sa´ direta de dados em impressoras, plotters, programas gr´ficos, recursos de multimeios,
ıda
a
etc.
Devido ` variedade de usos dos comandos de E/S, ´ interessante que se fa¸a inicialmente uma introdu¸˜o
a
e
c
ca
simples ao assunto, abordando os usos mais freq¨entes dos processos com arquivos externos, para posterioru
mente entrar-se em maiores detalhes. Com este intuito, a se¸˜o 9.1 cont´m esta introdu¸˜o r´pida, ao passo
ca
e
ca a
que as se¸˜es posteriores (9.3 – 9.11) abordam o assunto de uma forma bem mais abrangente.
co

9.1

Comandos de Entrada/Sa´
ıda: introdu¸˜o r´pida
ca a

Na se¸˜o 2.3 na p´gina 11 j´ foram apresentadas a entrada (teclado) e a sa´ (tela do monitor) padr˜es
ca
a
a
ıda
o
do Fortran. Usado desta forma, o recurso ´ demasiado limitado. O programador possui controle muito
e
restrito, por exemplo, sobre onde, na tela, o resultado deve ser apresentado e sobre o n´mero de casas
u
decimais que deve ser utilizado para representar o valor. Adicionalmente, o programador est´ limitado ao
a
teclado para o fornecimento de parˆmetros ao programa.
a
Um uso mais desej´vel dos recursos de E/S do Fortran consiste na habilidade de ler e gravar dados, por
a
exemplo, em arquivos residentes no disco r´
ıgido do computador ou em outra m´
ıdia ` qual o mesmo tem
a
121
122

9.1. Comandos de Entrada/Sa´
ıda: introdu¸˜o r´pida
ca a

acesso. Nesta se¸˜o, o acesso de E/S a arquivos ser´ brevemente discutido na forma de tarefas atribu´
ca
a
ıdas
ao programador.

Tarefa 1. Sa´ formatada na tela do monitor
ıda
Considera-se inicialmente o seguinte programa que realiza sa´ no formato livre na tela:
ıda
program F out
i m p l i c i t none
integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 )
r e a l ( dp ) : : a , b , c
a= 1 . 0 dp / 7 . 0 dp
b= s q r t ( 2 . 0 dp )
c= 4 * atan ( 1 . 0 dp )
print * , a , b , c
end program F out
Os resultados deste programa s˜o apresentados da seguinte maneira na tela do monitor:
a
0.142857142857143

1.41421356237310

3.14159265358979

Observa-se que h´ um n´mero grande de espa¸os em branco antes e entre os valores dos resultados e todos
a
u
c
s˜o apresentados com o n´mero total de d´
a
u
ıgitos represent´veis para uma vari´vel real de dupla precis˜o.
a
a
a
O programa a seguir apresenta os mesmos resultados, por´m de maneiras mais organizadas:
e
program F o u t f o r m a t a d o
i m p l i c i t none
integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 )
r e a l ( dp ) : : a , b , c
a= 1 . 0 dp / 7 . 0 dp
b= s q r t ( 2 . 0 dp )
c= 4 * atan ( 1 . 0 dp )
print ”( f 7 . 5 , 1 x , f 9 . 7 , 1 x , f 1 1 . 9 ) ” , a , b , c
print ”( f 7 . 7 , 1 x , f 9 . 9 , 1 x , e11 . 5 ) ” , a , b , c
print ” ( ’ a= ’ , f 7 . 5 , 2 x , ’ b= ’ , f 9 . 7 , 3 x , ’ c= ’ , f 1 1 . 9 ) ” , a , b , c
end program F o u t f o r m a t a d o
Agora, os resultados s˜o:
a
0.14286 1.4142136 3.141592654
******* ********* 0.31416 E +01
a = 0.14286 b = 1.4142136
c = 3.141592654
Nos trˆs resultados, o segundo argumento dos comandos WRITE indica a formata¸˜o na sa´
e
ca
ıda, conforme
determinada pelo especificador FMT=,1 o qual n˜o ´ obrigat´rio se o formato dos dados aparecer como
a e
o
segundo elemento de um comando de E/S. A formata¸˜o dos dados de sa´ ´ determinada pela seq¨ˆncia
ca
ıda e
ue
de descritores de edi¸˜o (X, F e E), os quais tˆm os seguintes significados:
ca
e
ˆ Os descritores 1X, 2X e 3X indicam quantos espa¸os em branco (respectivamente 1, 2 e 3) devem ser
c
deixados na sa´ dos dados.
ıda
ˆ Os descritores F e E s˜o descritores de edi¸˜o de dados e eles se aplicam ao dados na lista de vari´veis
a
ca
a
(A, B e C) na mesma ordem em que aparecem, ou seja, na sa´ 1, F7.5 determina a edi¸˜o da vari´vel
ıda
ca
a
A, F9.7 determina a adi¸˜o de B e F11.9 determina a edi¸˜o de C.
ca
ca
ˆ O descritor F7.5 indica que a vari´vel deve ser impressa no formato de ponto flutuante, com um total
a
de 7 algarismos alfanum´ricos, contando o ponto decimal e o sinal (se houver), destinando 5 d´
e
ıgitos
para a parte fracion´ria da vari´vel A. Exemplos de n´meros de ponto flutuante v´lidos s˜o:
a
a
u
a
a
5 d´
ıgitos

F7.5: 0.14286

7 d´
ıgitos

F9.7: -.1414214

7 caracteres
1 Discutido

9 caracteres

9 d´
ıgitos

F12.9: -3.141592654
12 caracteres

em detalhes na se¸˜o 9.7 na p´gina 134.
ca
a

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

123

ˆ O descritor E11.5, que aparece na sa´ 2 determinando o formato de sa´ da vari´vel C, indica a
ıda
ıda
a
sa´ na forma de ponto flutuante com parte exponencial. O resultado impresso (0.31416E+01) possui
ıda
uma extens˜o total de 11 algarismos alfanum´ricos, contando o ponto decimal, o sinal (se houver),
a
e
o s´
ımbolo da parte exponencial (E), o sinal da parte exponencial (+) e o seu valor, com duas casas
decimais (01). Restam, ent˜o, somente 5 d´
a
ıgitos para a parte fracion´ria. Caso a extens˜o total do
a
a
descritor, descontado o n´mero de d´
u
ıgitos na parte fracion´ria, n˜o for suficiente para imprimir a parte
a
a
exponencial e mais o sinal, ocorre um estouro de campo, indicado pelos asteriscos nos resultados das
vari´veis A e B. Exemplos v´lidos de n´meros no formato exponencial s˜o:
a
a
u
a
6 d´
ıgitos

5 d´
ıgitos

E11.5: 0.31416 E+01

E13.6: -4. 430949 E-12

11 caracteres

13 caracteres

ˆ Finalmente, as constantes de caractere ’A= ’, ’B= ’ e ’C= ’ que aparecem na formata¸˜o da sa´
ca
ıda
3 s˜o impressas ipsis literis na sa´ padr˜o e na mesma ordem em que aparecem, relativamente a si
a
ıda
a
pr´prias e `s vari´veis.
o
a
a

Uma exposi¸ao completa de todos os descritores ´ realizada na se¸˜o 9.8 na p´gina 135.
c˜
e
ca
a

Tarefa 2. Entrada formatada a partir do teclado
Entrada formatada a partir do teclado n˜o ´ uma tarefa muito pr´tica, pois uma instru¸˜o do tipo
a e
a
ca
READ(*,FMT=’(1X,F7.5,5X,F9.6,3X,F11.8)’)A, B, C
iria requerer a digita¸˜o dos valores das vari´veis exatamente nas posi¸˜es assinaladas e com as extens˜es
ca
a
co
o
e partes fracion´rias exatamente como determinadas pelos descritores. Por exemplo, se A= 2.6, B= -3.1 e
a
C= 10.8, seria necess´rio digitar
a
2.60000

-3.100000

10.80000000

para preencher todos os d´
ıgitos e espa¸os determinados pelos descritores de formata¸˜o.
c
ca

Tarefa 3. Sa´ de dados em um arquivo
ıda
Da mesma maneira que um programa-fonte ´ gravado em um arquivo situado no disco r´
e
ıgido do computador, ´ poss´ gravar dados em arquivos a partir de um programa ou, de forma alternativa, ler dados
e
ıvel
contidos em arquivos situados no disco.
Para possibilitar acesso de E/S em um arquivo ´ necess´rio que o programador:
e
a
ˆ Identifique o nome do arquivo, fornecendo o caminho completo, caso o arquivo resida em um diret´rio
o
(pasta) distinto do programa execut´vel.
a
ˆ Informe ao sistema sobre o tipo de acesso e uso que ser´ feito do arquivo.
a

´
ˆ Associe instru¸˜es individuais de leitura ou grava¸˜o com o arquivo em uso. E poss´ existir mais de
co
ca
ıvel
um arquivo simultaneamente acess´ para E/S, al´m das interfaces j´ utilizadas (teclado e monitor).
ıvel
e
a
ˆ Quando as opera¸˜es de E/S estiverem conclu´
co
ıdas, ´ necess´rio instruir ao sistema n˜o ´ mais necess´rio
e
a
a e
a
acessar o(s) arquivo(s).

O programa exemplo a seguir grava informa¸˜es formatadas ao arquivo EX1.DAT. A extens˜o .DAT simplesco
a
mente identifica o arquivo como sendo de dados. Se o arquivo n˜o existir, este ´ criado e tornado acess´
a
e
ıvel;
se ele existe, ent˜o os dados previamente contidos nele podem ser substitu´
a
ıdos por novos.
program A rq Sa i
i m p l i c i t none
integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 )
r e a l ( dp ) : : a , b , c
a= 1 . 0 dp / 7 . 0 dp
b= s q r t ( 2 . 0 dp )
c= 4 * atan ( 1 . 0 dp )
open ( 1 0 , f i l e=”ex1 . dat ”)
write ( 1 0 , fmt=”( f 7 . 5 , 1 x , f 9 . 7 , 1 x , f 1 1 . 9 ) ”) a , b , c
close (10)
end program A rq Sa i
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
124

9.1. Comandos de Entrada/Sa´
ıda: introdu¸˜o r´pida
ca a

Alterando os valores das vari´veis A, B e C, altera-se os valores gravados no arquivo EX1.DAT.
a
Os comandos-chave neste exemplo s˜o:
a
OPEN(10, FILE="EX1.DAT"). O comando OPEN habilita acesso ao arquivo EX1.DAT para o sistema. O
arquivo est´ situado no mesmo diret´rio que o programa e este ser´ criado caso n˜o exista previamente,
a
o
a
a
sendo poss´ ent˜o a grava¸˜o no mesmo, ou, caso ele j´ exista, ter´ acesso de leitura e/ou escrita.
ıvel
a
ca
a
a
O n´mero 11 indica a unidade l´gica que ser´ acessada. Doravante, o arquivo EX1.DAT ser´ sempre
u
o
a
a
identificado pelo programa atrav´s deste n´mero.
e
u
O modo como o acesso ao arquivo ´ feito pode ser alterado de diversas maneiras. A se¸˜o 9.4 descreve
e
ca
todos os especificadores poss´
ıveis do comando OPEN.
WRITE(10, FMT="(F7.5,1X,F9.7,1X,F11.9)") A, B, C. Este comando ´ aqui utilizado no lugar de PRINT
e
para realizar um processo de escrita formatada no arquivo associado ` unidade l´gica 10. A formata¸˜o
a
o
ca
´ fornecida pela lista de descritores de formata¸˜o que seguem a palavra-chave FMT=. O papel destes
e
ca
descritores j´ foi esclarecido.
a
O comando essencialmente grava os valores das vari´veis A, B e C de maneira formatada no arquivo
a
associado a unidade 10.
`
CLOSE(10). Finalmente, este comando informa ao computador que n˜o ser´ mais necess´rio acessar o
a
a
a
arquivo associado ` unidade l´gica 10 e que tal associa¸˜o deve ser interrompida.
a
o
ca

Tarefa 4. Leitura/escrita de dados em arquivos. Vers˜o 1: n´ mero conhecido
a
u
de linhas
O programa a seguir lˆ os dados gravados no arquivo EX1.DAT, criado a partir do programa ARQ_SAI, e
e
usa estes dados para definir valores de outros, os quais ser˜o gravados no arquivo EX2.DAT.
a
program A r q S a i 2
i m p l i c i t none
integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 )
r e a l ( dp ) : : a , b , c ! Dados de e n t r a d a .
r e a l ( dp ) : : d , e , f ! Dados de s a i d a .
open ( 1 0 , f i l e=”ex1 . dat ” , status=” o l d ”)
open ( 1 1 , f i l e=”ex2 . dat ” , status=”new ”)
read ( 1 0 , fmt=”( f 7 . 5 , 1 x , f 9 . 7 , 1 x , f 1 1 . 9 ) ”) a , b , c
print * , ”Os v a l o r e s l i d o s foram : ”
print * , ”a= ” , a
print * , ”b= ” , b
print * , ”c= ” , c
d= a + b + c
e= b ** 2 + c o s ( c )
f= s q r t ( a ** 2 + b ** 3 + c * * 5 )
write ( 1 1 , fmt=” ( 3 ( e11 . 5 , 1 x ) ) ”) d , e , f
end program A r q S a i 2
No programa ARQ_SAI_2 aparecem as seguintes instru¸˜es que ainda n˜o foram discutidas:
co
a
STATUS="OLD/NEW". Estas cl´usulas, que aparecem nos comandos OPEN, indicam o status exigido para o
a
arquivo a ser acessado. STATUS="OLD" indica que o arquivo deve existir no momento de acesso. Caso
isto n˜o aconte¸a, ocorre uma mensagem de erro e o programa ´ interrompido. STATUS="NEW" indica
a
c
e
que o arquivo n˜o deve existir previamente e, ent˜o, deve ser criado. Novamente, se estas condi¸˜es
a
a
co
n˜o se cumprirem, o programa p´ra.
a
a
READ(10, FMT="(F7.5,1X,F9.7,1X,F11.9)") A, B, C. Observa-se aqui o uso de uma entrada formatada
com o comando READ. A formata¸˜o das vari´veis A, B e C j´ foi discutida. Deve-se enfatizar novamente
ca
a
a
que a formata¸˜o especificada pelo FMT= deve possibilitar a leitura correta dos dados no arquivo
ca
associado a unidade l´gica 10.
`
o
WRITE(11, FMT="(3(E11.5,1X))") D, E, F. O aspecto ainda n˜o abordado neste comando WRITE ´ o uso
a
e
do contador de repeti¸˜o 3, o qual indica que as vari´veis D, E e F devem ser gravado no arquivo
ca
a
associado a unidade 11 com a formata¸ao dada por "E11.5,1X" repetido 3 vezes consecutivas.
`
c˜
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

125

Finalmente, deve-se mencionar que os comandos CLOSE(10) e CLOSE(11) n˜o foram utilizados. Isto ´
a
e
permitido, uma vez que, neste caso, a associa¸˜o das unidades l´gicas aos arquivos ser´ interrompida com
ca
o
a
o final da execu¸˜o do programa. Contudo, em certas situa¸˜es ´ necess´rio associar uma unidade l´gica
ca
co e
a
o
previamente empregada a um outro arquivo, o que neste caso obriga o programador a fazer uso do comando
CLOSE.
Modifica¸˜es posteriores no programa necessitar˜o tamb´m a elimina¸˜o do arquivo EX2.DAT, devido `
co
a
e
ca
a
cl´usula STATUS="NEW".
a

Tarefa 5. Leitura/escrita de dados em arquivos. Vers˜o 2: n´ mero desconhecido
a
u
de linhas
Quando o n´mero de linhas no arquivo de entrada n˜o ´ previamente conhecido, ´ necess´rio um procediu
a e
e
a
mento diferente daquele adotado na Tarefa 4. O programa 9.1 ilustra dois poss´
ıveis m´todos a ser adotados,
e
os quais utilizam as op¸˜es IOSTAT ou END do comando READ (se¸˜o 9.5). Em ambos, aloca-se inicialmente
co
ca
uma matriz tempor´ria com o posto adequado e com um n´mero tal de elementos que seja sempre maior
a
u
ou igual ao n´mero m´ximo de linhas que podem estar contidas no arquivo de entrada. Ap´s a leitura
u
a
o
dos dados na matriz tempor´ria, o n´mero de linhas no arquivo tornou-se conhecido e aloca-se, ent˜o, uma
a
u
a
matriz definitiva com o n´mero correto de elementos. O segundo exemplo faz uso de um r´tulo (se¸˜o
u
o
ca
5.1.1), que embora n˜o seja um procedimento recomendado em Fortran 90/95, ´ completamente equivalente
a
e
ao primeiro exemplo.
Existem maneiras mais inteligentes de realizar esta tarefa, sem que seja necess´rio definir-se uma matriz
a
tempor´ria. Por´m, estas maneiras envolvem o uso de ponteiros e listas encadeadas (linked lists) os quais
a
e
constituem recursos mais avan¸ados e que n˜o foram ainda abordados nesta apostila.
c
a
Os exemplos abordados nas Tarefas 1 — 5 constituem um conjunto pequeno, por´m freq¨ente, de usos
e
u
dos comando de E/S. A descri¸˜o completa destes recursos pode ser obtida nas se¸˜es 9.3—9.11 posteriores.
ca
co

9.2

Declara¸˜o NAMELIST
ca

Em certas situa¸˜es, quando h´ por exemplo um n´mero grande de parˆmetros sendo transferidos em
co
a
u
a
processos de E/S, pode ser util definir-se uma lista rotulada de valores destinados ` transferˆncia. O Fortran
´
a
e
90 introduziu, com este fim, a declara¸˜o NAMELIST, que define um ou mais grupos de vari´veis referenciadas
ca
a
com o mesmo nome. Esta declara¸˜o ´ empregada em conjunto com opera¸˜es de E/S executadas por
ca e
co
comandos READ e WRITE.
A forma geral da declara¸˜o, que pode aparecer em qualquer unidade de programa, ´:
ca
e
NAMELIST /<nome-grupo-namelist>/ <lista-nomes-vari´veis> &
a
[[,] /<nome-grupo-namelist>/ <lista-nomes-vari´veis> [,] ...]
a
Como se pode notar, ´ poss´ definir-se mais de um grupo NAMELIST na mesma declara¸˜o. O primeiro
e
ıvel
ca
campo substitu´
ıvel: <nome-grupo-namelist> , ´ o nome do grupo para uso subseq¨ente nos comandos
e
u
de E/S. A <lista-nomes-vari´veis> , como o nome indica, lista os nomes das vari´veis que comp˜e o
a
a
o
grupo. N˜o podem constar desta lista nomes de matrizes mudas de forma assumida, ou objetos autom´ticos,
a
a
vari´veis de caractere de extens˜o vari´vel, matrizes aloc´veis, pointers, ou ser um componente de qualquer
a
a
a
a
profundidade de uma estrutura que seja um ponteiro ou que seja inacess´
ıvel. Um exemplo v´lido de <listaa
nomes-vari´veis> ´:
a
e
REAL :: TV, CARPETE
REAL, DIMENSION(10) :: CADEIRAS
...
NAMELIST /ITENS_DOMESTICOS/ CARPETE, TV, CADEIRAS
Outro exemplo v´lido:
a
NAMELIST /LISTA1/ A, B, C /LISTA2/ X, Y, Z
´
E poss´
ıvel tamb´m continuar a mesma <lista-nomes-vari´veis> de um dado grupo em mais de uma
e
a
declara¸˜o contidas no campo de declara¸˜es da unidade de programa. Assim,
ca
co
NAMELIST /LISTA/ A, B, C
NAMELIST /LISTA/ D, E, F
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
126

9.2. Declara¸˜o NAMELIST
ca

Programa 9.1: Programa que ilustra leitura de arquivo com n´mero desconhecido de linhas.
u

! **************************** PROGRAMA ARQ SAI 3 ******************************
! Le um a r q u i v o de dados com um numero c o n h e c i d o de e l e m e n t o s por l i n h a ,
!
mas com um numero d e s c o n h e c i d o de l i n h a s no formato l i v r e , usando
!
matrizes temporarias .
! A l e i t u r a do a r q u i v o e r e a l i z a d a de 2 maneiras d i s t i n t a s :
!
1 . Usando a opcao IOSTAT .
!
2 . Usando a opcao END.
! O programa e n t a o imprime na t e l a os dados e o numero de l i n h a s l i d o .
!
! Autor : Rudi G a e l z e r
! Data : Maio /2008
!
program A r q S a i 3
i m p l i c i t none
integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 )
integer : : c o n t r o l e , i , npt1= 0 , npt2= 0
character ( len= 1 ) : : c h a r
r e a l ( kind=dp ) , dimension ( : , : ) , a l l o c a t a b l e : : temp1 , temp2 , matriz1 , m a t r i z 2
a l l o c a t e ( temp1 ( 2 , 1 0 0 0 ) , temp2 ( 2 , 1 0 0 0 ) ) ! Aloca m a t r i z e s t e m p o r a r i a s .
! Estima um l i m i t e s u p e r i o r no numero
!
de l i n h a s .
! Metodo 1 : usando opcao IOSTAT .
open ( 1 0 , f i l e =’ ex3 . dat ’ , status =’ old ’ )
do
read ( 1 0 , * , i o s t a t= c o n t r o l e ) temp1 ( 1 , npt1 +1) , temp1 ( 2 , npt1 +1)
i f ( c o n t r o l e < 0 ) e xi t
! F i n a l de a r q u i v o d e t e c t a d o .
npt1= npt1 + 1
end do
close (10)
a l l o c a t e ( m a t r i z 1 ( 2 , npt1 ) )
m a t r i z 1= temp1 ( : , : npt1 )
write ( * , fmt=” ( ’ Matriz 1 l i d a : ’ , / ) ”)
print ’ ( 2 ( e10 . 3 , 1 x ) ) ’ , ( m a t r i z 1 ( : , i ) , i= 1 , npt1 )
deallocate ( temp1 )
! L i b e r a e s p a c o de memoria ocupado por
!
temp1 .
print ’ ( / , a ) ’ , ’ P r e s s i o n e ENTER/R T R para c o n t i n u a r . ’
EU N
read ( * , ’ ( a ) ’ ) c h a r
! Metodo 2 : usando opcao END.
open ( 1 0 , f i l e =’ ex3 . dat ’ , status =’ old ’ )
do
read ( 1 0 , * , end= 1 0 0 ) temp2 ( 1 , npt2 +1) , temp2 ( 2 , npt2 +1)
npt2= npt2 + 1
end do
100 continue
! Linha i d e n t i f i c a d a com o r o t u l o 1 0 0 .
close (10)
a l l o c a t e ( m a t r i z 2 ( 2 , npt2 ) )
m a t r i z 2= temp2 ( : , : npt2 )
print ’ ( ”Matriz 2 l i d a : ” , / ) ’
print ’ ( 2 ( e10 . 3 , 1 x ) ) ’ , ( m a t r i z 2 ( : , i ) , i= 1 , npt1 )
deallocate ( temp2 )
! L i b e r a e s p a c o de memoria ocupado por
!
temp2 .
print ’ ( / , ”O numero t o t a l de l i n h a s l i d a s e ’ ’ : ” , / , &
”Matriz 1 : ” , i 4 , 3x , ”Matriz 2 : ” , i 4 ) ’ , npt1 , npt2
end program A r q S a i 3

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

127

´ equivalente a uma unica declara¸˜o NAMELIST com os 6 nomes de vari´veis listados na mesma ordem acima.
e
´
ca
a
Al´m disso, um objeto de um grupo NAMELIST pode tamb´m pertencer a outros grupos.
e
e
Se o tipo, parˆmetro de tipo ou forma de uma vari´vel de um grupo ´ especificado em uma declara¸˜o
a
a
e
ca
na mesma unidade de programa , esta declara¸˜o deve constar antes da declara¸˜o NAMELIST, ou ser uma
ca
ca
declara¸˜o de tipo impl´
ca
ıcito que regule o tipo e esp´cie das vari´veis que iniciam com aquele caractere
e
a
explicitado na declara¸˜o.
ca
Um grupo namelist pode possuir o atributo p´blico ou privado, concedido atrav´s das declara¸˜es PUBLIC
u
e
co
ou PRIVATE. Contudo, se o grupo possuir o atributo p´blico, nenhum membro seu pode ser declarado com
u
o atributo privado ou possuir componentes privados.
Para se executar uma opera¸˜o de E/S em algum registro (como um arquivo, por exemplo) que contenha
ca
um ou mais grupos namelist, o registro sempre ir´ iniciar com o caractere &, seguido, sem espa¸o, pelo
a
c
<nome-grupo-namelist>, vindo ent˜o a lista dos nomes das vari´veis, sendo cada nome seguido por sinais de
a
a
igual e, ent˜o pelo valor da vari´vel, podendo ser precedido ou seguido por espa¸os em branco. Constantes
a
a
c
de caractere devem ser sempre delimitadas em registros de entrada. A lista de nomes e valores de um
determinado grupo ´ sempre encerrada com o caractere / inserido fora de uma constante de caractere.
e
Os comandos READ e WRITE, ao serem empregados em conjunto com um namelist, n˜o possuem uma lista
a
expl´
ıcita de vari´veis ou constantes a ser transferidas, mas sim o nome do grupo NAMELIST como segundo
a
parˆmetro posicional ou com o especificador NML= contendo o nome do grupo, no lugar do especificador
a
FMT=. Um exemplo de registro de entrada ´:
e
INTEGER :: NO_DE_OVOS, LITROS_DE_LEITE, QUILOS_DE_ARROZ
NAMELIST /FOME/ NO_DE_OVOS, LITROS_DE_LEITE, QUILOS_DE_ARROZ
READ(5, NML=FOME)
O associado exemplo de registro (arquivo) de entrada ´:
e
&FOME LITROS_DE_LEITE= 5, NO_DE_OVOS= 12 /
Nota-se no registro acima que a ordem de atribui¸˜o de valores aos nomes n˜o ´ necessariamente a mesma
ca
a e
da declara¸˜o NAMELIST. Al´m disso, a vari´vel QUILOS_DE_ARROZ n˜o tem seu valor atribu´ no registro.
ca
e
a
a
ıdo
Quando isso acontece com uma ou mais vari´veis da lista o valor destas permanece inalterado.
a
Os valores de uma matriz podem ser atribu´
ıdos atrav´s do nome da mesma seguida por = e a lista de
e
constantes que ser˜o atribu´
a
ıdos aos elementos da matriz de acordo com o ordenamento padr˜o da linguagem,
a
descrito na se¸˜o 6.6.2. Se a vari´vel for de tipo derivado, a lista de valores deve tamb´m seguir a ordem
ca
a
e
´
e o tipo e esp´cie dos componentes constantes da declara¸˜o do tipo. E poss´ tamb´m definir-se o valor
e
ca
ıvel
e
de um elemento isolado ou de uma se¸˜o de matriz, ou qualquer sub-objeto, sem alterar os valores dos
ca
demais elementos, usando um designador de sub-objeto, tal como um tripleto de subscritos. Neste caso, os
elementos do tripleto devem todos ser constantes inteiras escalares, sem parˆmetros de esp´cie de tipo
a
e
Na grava¸˜o (sa´
ca
ıda) do registro, todos os componentes do grupo s˜o escritos no arquivo especificado,
a
precedidos por & e o nome do grupo, na mesma ordem da declara¸˜o da <lista-nomes-vari´veis> , com os
ca
a
nomes explicitamente escritos em letras mai´sculas. O registro ´ finalizado com o caractere /. Um exemplo
u
e
de sa´ de um namelist ´:
ıda
e
INTEGER :: NUMERO, I
INTEGER, DIMENSION(10) :: LISTA= (/ 14, (0, I= 1,9) /)
NAMELIST /SAI/ NUMERO, LISTA
WRITE(6, NML=SAI)
o qual produz o seguinte registro no arquivo associado ` unidade l´gica 6:
a
o
&SAI NUMERO=1 , LISTA=14, 9*0 /
Nota-se que os 9 elementos 0 do vetor LISTA s˜o registrados usando-se a nota¸˜o compacta 9*0. Esta
a
ca
nota¸˜o tamb´m ´ v´lida em registros de entrada.
ca
e e a
Em um processo de leitura de registros (usando o comando READ, por exemplo), n˜o ´ permitida a mistura
a e
de registros em um NAMELIST com registros que n˜o pertencem a nenhum grupo, como em uma entrada
a
formatada ou n˜o-formatada. Contudo, em um processo de sa´ de registros (comando WRITE), pode-se
a
ıda
misturar os tipos de registros.
Todos os nomes de grupos, nomes de objetos e nomes de componentes s˜o interpretados sem considerar o
a
caso de capitaliza¸˜o. A lista de valores n˜o pode ter um n´mero excedente de ´
ca
a
u
ıtens, mas ela pode conter um
n´mero inferior, como j´ foi mencionado. Se o objeto ´ do tipo caractere e o valor tiver uma extens˜o menor
u
a
e
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
128

9.2. Declara¸˜o NAMELIST
ca

que a declarada, espa¸os em branco preenchem o restante do campo. Matrizes ou objetos de tamanho zero
c
(se¸˜o 6.5) n˜o podem constar no registro de entrada de um NAMELIST. Se ocorrer uma m´ltipla atribui¸˜o
ca
a
u
ca
de um mesmo objeto, o ultimo valor ´ assumido.
´
e
Por fim, coment´rios podem ser inclu´
a
ıdos no registro de entrada em seguida a um nome a uma v´
ırgula
que separa os nomes. O coment´rio ´ introduzido, como ´ costumeiro a partir do caractere !. Uma linha
a
e
e
de coment´rio, iniciada com o caractere !, tamb´m ´ permitida, desde que esta n˜o ocorra em um contexto
a
e e
a
de uma constante de caractere.
O programa Testa_NAMELIST abaixo ilustra praticamente todos os recursos discutidos nesta se¸˜o a
ca
respeito de listas NAMELIST.
program Testa NAMELIST
i m p l i c i t none
integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 )
integer : : n o d e o v o s , l i t r o s d e l e i t e , q u i l o s d e a r r o z= 1 2 , numero
! Note que q u i l o s d e a r r o z f o i i n i c i a l i z a d o .
integer , dimension ( 1 0 ) : : l i s t a i n t 1 , l i s t a i n t 2
real , dimension ( 1 0 ) : : a l e a t , v e t t e s= 1 . 0
r e a l ( dp ) : : pi , e e u l e r , m e l e c t r o n , c vacuum
logical : : tes
character ( len= 1 0 ) : : nome
namelist / fome / nome , n o d e o v o s , l i t r o s d e l e i t e , q u i l o s d e a r r o z
namelist / s a i / numero , l i s t a i n t 1 , l i s t a i n t 2 , v e t t e s
namelist / c t e s / t e s , pi , e e u l e r , m e l e c t r o n , c vacuum
!
open ( 1 0 , f i l e= ”Dados . e n t ” , status= ” o l d ”)
open ( 1 1 , f i l e= ”Dados . dat ”)
read ( 1 0 , nml= fome )
read ( 1 0 , nml= s a i )
read ( 1 0 , nml= c t e s )
! Mostra na t e l a os v a l o r e s l i d o s .
print ’ ( a ) ’ , ” L i s t a / fome / l i d a : ”
write ( * , nml= fome )
print ’ ( / a ) ’ , ” L i s t a / s a i / l i d a : ”
write ( * , nml= s a i )
print ’ ( / a ) ’ , ” L i s t a / c t e s / l i d a : ”
write ( * , nml= c t e s )
print ’ ( / a ) ’ , ”Para c o n f i r m a r : ”
print ’ ( ”Vetor v e t t e s : ” , 1 0 ( f 4 . 2 , x ) ) ’ , v e t t e s
print ’ ( / , ” l i s t a 1 : ” , 1 0 i 3 ) ’ , l i s t a i n t 1
print ’ ( / , ” l i s t a 2 : ” , 1 0 i 3 ) ’ , l i s t a i n t 2
! A l t e r a a l g u n s v a l o r e s e g r a v a as l i s t a s no a r q u i v o .
c a l l random number ( a l e a t )
print ’ ( / , ” L i s t a de No . a l e a t o r i o s : ” , / , 1 0 ( f 7 . 5 , x ) ) ’ , a l e a t
l i s t a i n t 1= l i s t a i n t 2 ** 2
l i s t a i n t 2= a l e a t * l i s t a i n t 2
write ( 1 1 , nml= s a i )
write ( 1 1 , nml= c t e s )
write ( 1 1 , nml= fome ) ! V e r i f i q u e Dados . d a t .
end program Testa NAMELIST
Um exemplo de arquivo de entrada Dados.ent que pode ser fornecido ao programa Testa_NAMELIST ´
e
o seguinte:
&fome
l i t r o s d e l e i t e= 10 ,
n o d e o v o s= 2 4 ,
nome= ”Rancho ”
/
&s a i
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

129

numero= 5 0 ,
l i s t a i n t 1= 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 1 0 ,
l i s t a i n t 2= 3 * 1 , 3 * 5 , 4 * 8 ,
v e t t e s (4:8)= 5*2.0
/
&c t e s
t e s= . t r u e . ,
PI=
3.14159265358979323846264338327950288419717 ,
e e u l e r=
2 . 7 1 8 2 8 1 8 2 8 4 5 9 0 4 5 2 3 5 3 6 0 2 8 7 4 7 1 3 5 2 6 6 2 4 9 7 7 5 7 2 5 , ! Euler ’ s number .
m e l e c t r o n= 9 . 1 0 9 3 8 2 1 5 e −28 ,
! E l e c t r o n r e s t mass ( g ) .
c vacuum=
2 . 9 9 7 9 2 4 5 8 e10
! Speed o f l i g h t i n vacuum (cm/ s ) .
/

9.3

Unidades l´gicas
o

Em Fortran, um arquivo est´ conectado a uma unidade l´gica denotada por um n´mero inteiro. Este
a
o
u
n´mero deve ser positivo e est´ freq¨entemente limitado entre 1 e 100, dependendo do compilador. Cada
u
a
u
unidade l´gica possui muitas propriedades. Por exemplo,
o
FILE. O nome do arquivo conectado ` unidade. O nome ´ especificado pelo comando OPEN.
a
e
ACTION. Especifica o tipo de a¸˜o que pode ser executada sobre o arquivo. Estas compreendem leitura,
ca
escrita ou ambas. Se um arquivo ´ aberto para um tipo de a¸˜o e outro tipo ´ tentado, uma mensagem
e
ca
e
de erro ser´ gerada. Por exemplo, n˜o ´ permitida escrita sobre um arquivo aberto somente para
a
a e
leitura.
STATUS. Estabelece o status de um arquivo. Estes s˜o: velho (old), novo (new) substitui¸˜o (replace), entre
a
ca
outros. Caso um arquivo tente ser acessado com um status incorreto, uma mensagem de erro ´ gerada.
e
ACCESS. Forma de acesso a um arquivo: direto ou seq¨encial. Alguns arquivos pode ser acessados por
u
ambos os m´todos, como ´ o caso de arquivos em discos remov´
e
e
ıveis ou discos r´
ıgidos. J´ outras m´
a
ıdias
permite acesso somente seq¨encial, como ´ o caso de uma fita magn´tica.
u
e
e
´
Sequencial. E o acesso usual. Os processos de leitura/escrita principiam no in´
ıcio do arquivo e
¨
seguem, linha a linha, at´ o seu final.
e
Direto. Cada linha ´ acessada por um n´mero, denominado n´mero de grava¸˜o (record number) o
e
u
u
ca
qual deve ser especificado no comando de leitura/escrita.
O n´mero m´ximo de arquivos que podem ser abertos simultaneamente para E/S tamb´m ´ especificado
u
a
e e
pelo manual do compilador.

9.4

Comando OPEN

O comando OPEN ´ usado para conectar um dado arquivo a uma unidade l´gica. Freq¨entemente ´
e
o
u
e
poss´ pr´-conectar um arquivo antes que o programa comece a rodar; neste caso, n˜o ´ necess´rio usarıvel e
a e
a
se o comando OPEN. Contudo, isto depende de conhecimento pr´vio a respeito dos n´meros-padr˜o das
e
u
a
unidades l´gicas para E/S, o que geralmente depende do processador e dos sistema operacional em uso.
o
Para sistemas linux, as unidades pr´-conectadas s˜o, usualmente:
e
a
Uso
Mensagens de erro
Entrada padr˜o
a
Sa´ padr˜o
ıda
a

Designa¸˜o
ca
stderr
stdin
stdout

N´ mero da unidade l´gica
u
o
0
5
6

Sempre que poss´
ıvel, ´ recomendado evitar-se o uso de unidade pr´-conectadas, o que torna o programa
e
e
mais port´vel.
a
A sintaxe do comando ´:
e
OPEN([UNIT=] <int-exp> [,<op-list>])
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
130

9.4. Comando OPEN

onde <int-exp> ´ uma express˜o escalar inteira que especifica o n´mero da unidade l´gica externa e <ope
a
u
o
list> ´ uma lista de especificadores opcional, formada por um conjunto de palavras-chave. Se a palavrae
chave “UNIT=” for inclu´
ıda, ela pode aparecer em qualquer posi¸˜o no campo de argumentos do comando
ca
OPEN. Um especificador n˜o pode aparecer mais de uma vez. Nos especificadores, todas as entidades s˜o
a
a
escalares e todos os caracteres s˜o da esp´cie padr˜o. Em express˜es de caractere, todos os brancos precea
e
a
o
dentes s˜o ignorados e, exceto no caso do especificador “FILE=”, quaisquer letras mai´sculas s˜o convertidas
a
u
a
a
`s correspondentes letras min´sculas. Os especificadores s˜o:
u
a
FILE= <fln>, onde <fln> ´ uma express˜o de caractere que fornece o nome do arquivo. O nome deve
e
a
coincidir exatamente com o arquivo, inclusive com o caminho, caso o arquivo esteja em um diret´rio
o
distinto do diret´rio de trabalho. Se este especificador ´ omitido e a unidade n˜o ´ conectada a uma
o
e
a e
arquivo, o especificador “STATUS=” deve ser especificado com o valor SCRATCH e o arquivo conectado `
a
unidade ir´ depender do sistema.
a
IOSTAT= <ios>, onde <ios> ´ uma vari´vel inteira padr˜o que ´ fixada a zero se o comando executou
e
a
a
e
corretamente e a um valor positivo em caso contr´rio.
a
ERR= <r´tulo-erro>, onde <r´tulo-erro> ´ o r´tulo de um comando na mesma unidade de ˆmbito, para
o
o
e o
a
o qual o controle do fluxo ser´ transferido caso ocorra algum erro na execu¸˜o do comando OPEN.
a
ca
STATUS= <status>, onde <status> ´ uma express˜o de caracteres que fornece o status do arquivo. O
e
a
status pode ser um dos seguintes:
’OLD’– Arquivo deve existir.
’NEW’– Arquivo n˜o deve existir. O arquivo ser´ criado pelo comando OPEN. A partir deste momento,
a
a
o seu status se torna ’OLD’.
’REPLACE’– Se o arquivo n˜o existe, ele ser´ criado. Se o arquivo j´ existe, este ser´ eliminado e um
a
a
a
a
novo arquivo ´ criado com o mesmo nome. Em ambos os casos, o status ´ ent˜o alterado para
e
e
a
’OLD’.
’SCRATCH’– O arquivo ´ tempor´rio e ser´ deletado quando este for fechado com o comando CLOSE
e
a
a
ou na sa´ da unidade de programa.
ıda
’UNKNOWN’– Status do arquivo desconhecido; depende do sistema. Este ´ o valor padr˜o do especifie
a
cador, caso este seja omitido.
O especificador “FILE=” deve estar presente se ’NEW’ ou ’REPLACE’ s˜o especificados ou se ’OLD’ ´
a
e
especificado e a unidade n˜o est´ conectada.
a
a
ACCESS= <acc>, onde <acc> ´ uma express˜o de caracteres que fornece o valor ’SEQUENTIAL’ ou ’DIRECT’.
e
a
Para um arquivo que j´ exista, este valor deve ser uma op¸˜o v´lida. Se o arquivo ainda n˜o existe, ele
a
ca a
a
ser´ criado com o m´todo de acesso apropriado. Se o especificador ´ omitido, o valor ’SEQUENTIAL’ ´
a
e
e
e
assumido. O significado das especifica¸˜es ´:
co e
’DIRECT’– O arquivo consiste em registros acessados por um n´mero de identifica¸˜o. Neste caso, o
u
ca
tamanho do registro deve ser especificado por “RECL=”. Registros individuais podem ser especificados e atualizados sem alterar o restante do arquivo.
’SEQUENTIAL’– O arquivo ´ escrito/lido seq¨encialmente, linha a linha.
e
u
FORM= <fm>, onde <fm> ´ uma express˜o de caracteres que fornece os valores ’FORMATTED’ ou ’UNFORMATe
a
TED’, determinando se o arquivo deve ser conectado para E/S formatada ou n˜o formatada. Para
a
um arquivo que j´ exista, o valor deve ser uma op¸˜o v´lida. Se o arquivo ainda n˜o existe, ele ser´
a
ca a
a
a
criado com um conjunto de forma que incluem o forma especificada. Se o especificador ´ omitido, os
e
valores-padr˜o s˜o:
a a
’FORMATTED’– Para acesso seq¨encial.
u
’UNFORMATTED’– Para conex˜o de acesso direto.
a
RECL= <rl>, onde <rl> ´ uma express˜o inteira cujo valor deve ser positivo.
e
a
ˆ Para arquivo de acesso direto, a op¸˜o especifica o tamanho dos registros e ´ obrigat´rio.
ca
e
o
ˆ Para arquivo seq¨encial, a op¸˜o especifica o tamanho m´ximo de um registro, e ´ opcional com
u
ca
a
e
um valor padr˜o que depende do processador.
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

131

– Para arquivos formatados, o tamanho ´ o n´mero de caracteres para registros que contenham
e
u
somente caracteres-padr˜o.
a
– Para arquivos n˜o formatados, o tamanho depende do sistema, mas o comando INQUIRE
a
(se¸˜o 9.10) pode ser usado para encontrar o tamanho de uma lista de E/S.
ca
Em qualquer situa¸˜o, para um arquivo que j´ exista, o valor especificado deve ser permitido para
ca
a
o arquivo. Se o arquivo ainda n˜o existe, ele ´ criado com um conjunto permitido de tamanhos de
a
e
registros que incluem o valor especificado.
BLANK= <bl>, onde <bl> ´ uma express˜o de caracteres que fornece os valores ’NULL’ ou ’ZERO’. A
e
a
conex˜o deve ser com E/S formatada. Este especificador determina o padr˜o para a interpreta¸˜o de
a
a
ca
brancos em campos de entrada num´ricos.
e
’NULL’– Os brancos s˜o ignorados, exceto que se o campo for completamente em branco, ele ´ intera
e
pretado como zero.
’ZERO’– Os brancos s˜o interpretados como zeros.
a
Se o especificados ´ omitido, o valor padr˜o ´ ’NULL’.
e
a e
POSITION= <pos>, onde <pos> ´ uma express˜o de caracteres que fornece os valores ’ASIS’, ’REWIND’ ou
e
a
’APPEND’. O m´todo de acesso deve ser seq¨encial e se o especificador ´ omitido, o valor padr˜o ´
e
u
e
a e
’ASIS’. Um arquivo novo ´ sempre posicionado no seu in´
e
ıcio. Para um arquivo que j´ existe e que j´
a
a
est´ conectado:
a
’ASIS’– O arquivo ´ aberto sem alterar a posi¸˜o corrente de leitura/escrita no seu interior.
e
ca
’REWIND’– O arquivo ´ posicionado no seu ponto inicial.
e
’APPEND’– O arquivo ´ posicionado logo ap´s o registro de final de arquivo, possibilitando a inclus˜o
e
o
a
de dados novos.
Para um arquivo que j´ existe mas que n˜o est´ conectado, o efeito da especifica¸˜o ’ASIS’ no
a
a
a
ca
posicionamento do arquivo ´ indeterminado.
e
ACTION= <act>, onde <act> ´ uma express˜o de caracteres que fornece os valores ’READ’, ’WRITE’ ou
e
a
’READWRITE’.
’READ’– Se esta especifica¸˜o ´ escolhida, os comandos WRITE, PRINT e ENDFILE n˜o devem ser usados
ca e
a
para esta conex˜o.
a
’WRITE’– Se esta especifica¸˜o ´ escolhida, o comando READ n˜o pode ser usado.
ca e
a
’READWRITE’– Se esta especifica¸˜o ´ escolhida, n˜o h´ restri¸˜o.
ca e
a a
ca
Se o especificador ´ omitido, o valor padr˜o depende do processador.
e
a
DELIM= <del>, onde <del> ´ uma express˜o de caracteres que fornece os valores ’APOSTROPHE’, ’QUOTE’
e
a
ou ’NONE’. Se ’APOSTROPHE’ ou ’QUOTE’ s˜o especificados, o caractere correspondente ser´ usado
a
a
para delimitar constantes de caractere escritos com formata¸˜o de lista ou com o uso da declara¸˜o
ca
ca
NAMELIST, e ser´ duplicado onde ele aparecer dentro de tal constante de caractere. Al´m disso, caraca
e
teres fora do padr˜o ser˜o precedidos por valores da esp´cie. Nenhum caractere delimitador ser´ usado
a
a
e
a
e nenhuma duplica¸˜o ser´ feita se a especifica¸˜o for ’NONE’. A especifica¸˜o ’NONE’ ´ o valor padr˜o
ca
a
ca
ca
e
a
se este especificador for omitido. O especificador somente pode aparecer em arquivos formatados.
PAD= <pad>, onde <pad> ´ uma express˜o de caracteres que fornece os valores ’YES’ ou ’NO’.
e
a
’YES’– Um registro de entrada formatado ser´ considerado preenchido por brancos sempre que uma
a
lista de entrada e a formata¸˜o associada especificarem mais dados que aqueles que s˜o lidos no
ca
a
registro.
’NO’– Neste caso, o tamanho do registro de entrada deve ser n˜o menor que aquele especificado pela
a
lista de entrada e pela formata¸˜o associada, exceto na presen¸a de um especificador ADVANCE=
ca
c
’NO’ e uma das especifica¸˜es “EOR=” ou “IOSTAT=”.
co
O valor padr˜o se o especificador ´ omitido ´ ’YES’. Para caracteres n˜o padronizados, o caractere de
a
e
e
a
branco que preenche o espa¸o restante depende do processador.
c
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
132

9.5. Comando READ

A seguir, temos um exemplo do uso deste comando:
OPEN(17, FILE= ’SAIDA.DAT’, ERR= 10, STATUS= ’REPLACE’, &
ACCESS= ’SEQUENTIAL’, ACTION= ’WRITE’)
Neste exemplo, um arquivo SAIDA.DAT ´ aberto para escrita, ´ conectado ao n´mero de unidade l´gica 17,
e
e
u
o
o arquivo ´ acessado linha a linha e ele j´ existe mas deve ser substitu´
e
a
ıdo. O r´tulo 10 deve pertencer a um
o
comando execut´vel v´lido.
a
a
OPEN(14, FILE= ’ENTRADA.DAT’, ERR= 10, STATUS= ’OLD’,
RECL=IEXP, ACCESS= ’DIRECT’, ACTION= ’READ’)

&

Aqui, o arquivo ENTRADA.DAT ´ aberto somente para leitura na unidade 14. O arquivo ´ diretamente acessado
e
e
e deve ser um arquivo previamente existente.

9.5

Comando READ

Este ´ o comando que executa a leitura formatada de dados. At´ agora, o comando foi utilizado para
e
e
leitura na entrada padr˜o, que usualmente ´ o teclado:
a
e
READ*, <lista>
onde o asterisco “*” indica a entrada padr˜o e <lista> ´ a lista de vari´veis cujo valor ´ lido do teclado.
a
e
a
e
Este comando ser´ agora generalizado para uma forma com ou sem unidade l´gica. Sem o n´mero de
a
o
u
unidade l´gica o comando fica:
o
READ <format> [,<lista>]
e com o n´mero de unidade fica:
u
READ([UNIT=]<u>, [FMT=] <format>[, IOSTAT= <ios>] &
[, ERR= <err-label>][, END= <end-label>]
&
[, EOR= <eor-label>][, ADVANCE= <mode>]
&
[, REC= <int-exp>][, SIZE= <size>][, NML= <grp>]) <lista>
Os argumentos do comando s˜o os seguintes:
a
UNIT= <u>, onde <u> ´ um n´mero de unidade l´gica v´lido ou “*” para a entrada padr˜o. Caso esta
e
u
o
a
a
especifica¸˜o seja o primeiro argumento do comando, a palavra-chave ´ opcional.
ca
e
FMT= <format>, onde <format> ´ uma string de caracteres formatadores, um r´tulo v´lido em Fortran ou
e
o
a
“*” para formato livre. Caso esta especifica¸˜o seja o segundo argumento do comando, a palavra-chave
ca
´ opcional.
e
IOSTAT= <ios>, onde <ios> ´ uma vari´vel inteira padr˜o que armazena o status do processo de leitura.
e
a
a
Os valores poss´
ıveis s˜o:
a
<ios> = 0, quando o comando ´ executado sem erros.
e
<ios> > 0, quando ocorre um erro na execu¸˜o do comando.
ca
<ios> < 0, quando uma condi¸˜o de final de registro ´ detectada em entrada sem avan¸o ou quando
ca
e
c
uma condi¸˜o de final de arquivo ´ detectada.
ca
e
ERR= <err-label>, ´ um r´tulo v´lido para onde o controle de fluxo ´ transferido quando ocorre um erro
e
o
a
e
de leitura.
END= <end-label>, ´ um r´tulo v´lido para onde o controle de fluxo ´ transferido se uma condi¸˜o de final
e
o
a
e
ca
de arquivo ´ encontrada. Esta op¸˜o somente existe no comando READ com acesso seq¨encial.
e
ca
u
EOR= <eor-label>, ´ um r´tulo v´lido para onde o controle de fluxo ´ transferido se uma condi¸˜o de
e
o
a
e
ca
final de registro ´ encontrada. Esta op¸˜o somente existe no comando READ com acesso seq¨encial e
e
ca
u
formatado e somente se a especifica¸˜o ADVANCE= ’NO’ tamb´m estiver presente.
ca
e
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

133

ADVANCE= <mode>, onde <mode> possui dois valores: ’YES’ ou ’NO’. A op¸˜o ’NO’ especifica que cada
ca
comando READ inicia um novo registro na mesma posi¸˜o; isto ´, implementa entrada de dados sem
ca
e
avan¸o (non-advancing I/O). A op¸˜o padr˜o ´ ’YES’, isto ´ a cada leitura o arquivo ´ avan¸ado
c
ca
a e
e
e
c
em uma posi¸˜o. Se a entrada sem avan¸o ´ usada, ent˜o o arquivo deve estar conectado para acesso
ca
c e
a
seq¨encial e o formato deve ser expl´
u
ıcito.
REC= <int-exp>, onde <int-exp> ´ uma express˜o inteira escalar cujo valor ´ o n´mero de ´
e
a
e
u
ındice do
registro lido durante acesso direto. Se REC estiver presente, os especificadores END e NML e o formato
livre “*” n˜o podem ser tamb´m usados.
a
e
SIZE= <size>, onde <size> ´ uma vari´vel escalar inteira padr˜o, a qual guarda o n´mero de caracteres
e
a
a
u
lidos. Este especificador somente existe no comando READ e somente se a especifica¸˜o ADVANCE= ’NO’
ca
tamb´m estiver presente.
e
NML= <grp>, onde <grp> ´ o nome de um grupo NAMELIST previamente definido em uma declara¸˜o NAMEe
ca
LIST. O nome <grp> n˜o ´ uma constante de caracteres e sim um nome v´lido em Fortran2 .
a e
a
Dado o seguinte exemplo:
READ(14, FMT= ’(3(F10.7,1X))’, REC=IEXP) A, B, C
este comando especifica que o registro identificado pela vari´vel inteira IEXP seja lido na unidade 14. O
a
registro deve ser composto por 3 n´meros reais designados pelos descritores F10.7, separados por um espa¸o
u
c
em branco. Estes 3 n´meros ser˜o atribu´
u
a
ıdos `s vari´veis A, B e C. Outro exemplo:
a
a
READ(*, ’(A)’, ADVANCE= ’NO’, EOR= 12, SIZE= NCH) STR
especifica que a leitura ´ sem avan¸o na unidade padr˜o; isto ´, o cursor na tela do monitor ir´ permanecer
e
c
a
e
a
na mesma linha h´ medida que a string STR ser´ lida. O comando lˆ uma constante de caractere porque o
a
a
e
descritor no formato ´ “A”. Em uma situa¸˜o normal, isto ´, leitura com avan¸o, o cursor seria posicionado
e
ca
e
c
no in´ da pr´xima linha na tela. A vari´vel NCH guarda o comprimento da string e o r´tulo 12 indica o
ıcio
o
a
o
ponto onde o programa deve se encaminhar se uma condi¸˜o de final de registro ´ encontrada.
ca
e

9.6

Comandos PRINT e WRITE

Em compara¸˜o com o comando READ, o comando WRITE suporta os mesmos argumentos, com exce¸˜o
ca
ca
do especificador SIZE.
At´ agora, foi usada somente forma do comando PRINT para a sa´ padr˜o de dados, que usualmente ´
e
ıda
a
e
a tela do monitor:
PRINT*, <lista>
O mesmo comando, generalizado para sa´ formatada fica,
ıda
PRINT <format> [, <lista>]
J´ a sintaxe mais geral do comando ´:
a
e
WRITE([UNIT=]<u>, [FMT=] <format>[, IOSTAT= <ios>] &
[, ERR= <err-label>][, ADVANCE= <mode>]
&
[, REC= <int-exp>][, NML= <grp>]) <lista>
Os especificadores deste comando executam, na sua maioria, as mesmas fun¸˜es executadas pelos especifico
cadores do comando READ, com exce¸˜o dos seguintes, os quais especificam fun¸˜es ligeiramente distintas:
ca
co
UNIT= <u>, onde <u> ´ um n´mero de unidade l´gica v´lido ou “*” para a sa´ padr˜o. Caso esta especie
u
o
a
ıda
a
fica¸˜o seja o primeiro argumento do comando, a palavra-chave ´ opcional.
ca
e
IOSTAT= <ios>, onde <ios> ´ uma vari´vel inteira padr˜o que armazena o status do processo de escrita.
e
a
a
Os valores poss´
ıveis s˜o:
a
<ios> = 0, quando o comando ´ executado sem erros.
e
2 Ver

se¸˜o 9.2.
ca

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
134

9.7. Comando FORMAT e especificador FMT=
<ios> > 0, quando ocorre um erro na execu¸˜o do comando.
ca
<ios> < 0, quando uma condi¸˜o de final de registro ´ detectada em escrita sem avan¸o ou quando
ca
e
c
uma condi¸˜o de final de arquivo ´ detectada.
ca
e

ERR= <err-label>, ´ um r´tulo v´lido para onde o controle de fluxo ´ transferido quando ocorre um erro
e
o
a
e
de escrita.
ADVANCE= <mode>, onde <mode> possui dois valores: ’YES’ ou ’NO’. A op¸˜o ’NO’ especifica que cada
ca
comando WRITE inicia um novo registro na mesma posi¸˜o; isto ´, implementa sa´ de dados sem
ca
e
ıda
avan¸o (non-advancing I/O). A op¸˜o padr˜o ´ ’YES’, isto ´ a cada escrita, o arquivo ´ avan¸ado
c
ca
a e
e
e
c
em uma posi¸˜o. Se a sa´ sem avan¸o ´ usada, ent˜o o arquivo deve estar conectado para acesso
ca
ıda
c e
a
seq¨encial e o formato deve ser expl´
u
ıcito.
REC= <int-exp>, onde <int-exp> ´ uma express˜o inteira escalar cujo valor ´ o n´mero de ´
e
a
e
u
ındice do
registro a ser escrito durante acesso direto. Se REC estiver presente, os especificadores END e NML e o
formato livre “*” n˜o podem ser tamb´m usados.
a
e
NML= <grp>, onde <grp> ´ o nome de um grupo NAMELIST previamente definido em uma declara¸˜o NAMEe
ca
LIST. O nome <grp> n˜o ´ uma constante de caracteres e sim um nome v´lido em Fortran3 .
a e
a
Considere o seguinte exemplo,
WRITE(17, FMT= ’(I4)’, IOSTAT= ISTAT, ERR= 10) IVAL
aqui, ’(I4)’ descreve format de dado inteiro com 4 d´
ıgitos, ISTAT ´ uma vari´vel inteira que indica o status
e
a
do processo de escrita; em caso de erro, o fluxo ´ transferido ao r´tulo 10. IVAL ´ a vari´vel cujo valor ´
e
o
e
a
e
escrito na unidade 17. Outro exemplo seria:
WRITE(*,’(A)’, ADVANCE= ’NO’) ’Entrada: ’
Como a especifica¸˜o de escrita sem avan¸o foi escolhida, o cursor ir´ permanecer na mesma linha que a
ca
c
a
string ’Entrada: ’. Em circunstˆncias normais, o cursor passaria ao in´
a
ıcio da linha seguinte na tela.
Nota-se tamb´m o descritor de formato de constante de caracteres expl´
e
ıcito.
Como exemplo do uso dos comandos de E/S apresentados nas se¸˜es 9.4 – 9.6, o programa a seguir abre
co
um novo arquivo seq¨encial chamado notas.dat. O programa ent˜o lˆ o nome de um estudante, seguido
u
a e
por 3 notas, as quais s˜o introduzidas pelo teclado (entrada padr˜o), escrevendo, finalmente, as notas e a
a
a
m´dia final em NOTAS.DAT e no monitor (sa´ padr˜o), na mesma linha do nome. O processo de leitura e
e
ıda
a
escrita ´ repetido at´ que um estudante com o nome ’Fim’ ´ introduzido.
e
e
e
P O R M Notas
RGA
IMPLICIT N N
O E
C A A T R(LEN=20) : : name
H R CE
REAL : : mark1 , mark2 , mark3
OPEN (UNIT=4,FILE=’NOTAS.DAT’ )
DO
READ( * , * ) name, mark1 , mark2 , mark3
IF (name == ’ Fim ’ )EXIT
WRITE(UNIT=4,F T= * ) name, mark1 , mark2 , mark3 , ( mark1 + mark2 + mark3 ) / 3 . 0
M
WRITE(UNIT= * ,F T= * ) name, mark1 , mark2 , mark3 , ( mark1 + mark2 + mark3 ) / 3 . 0
M
END DO
CLOSE(UNIT=4)
END P O R M Notas
RGA

9.7

Comando FORMAT e especificador FMT=

O especificador FMT= em um comando READ ou WRITE pode conter ou o s´
ımbolo de formato livre “*”,
ou uma constante de caracteres que indica o formato ou um r´tulo que indica a linha onde se encontra um
o
comando FORMAT.
Dado o seguinte exemplo,
3 Ver

se¸˜o 9.2.
ca

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

135

WRITE(17, FMT= ’(2X,2I4,1X,”nome ”,A7)’)I, J, STR
este comando escreve no arquivo SAIDA.DAT, aberto em um exemplo anterior, as trˆs vari´veis I, J e STR de
e
a
acordo com o formato especificado: “2 espa¸os em branco (2X), 2 objetos inteiros de 4 d´
c
ıgitos em espa¸os
c
entre eles (2I4), um espa¸o em branco (1X) a constante de caractere ’nome ’ e, finalmente, 7 caracteres
c
de um objeto de caracteres (A7)”. As vari´veis a ser realmente escritas s˜o tomadas da lista de E/S ap´s a
a
a
o
lista de especifica¸˜es do comando.
co
Outro exemplo:
READ(14,*)X, Y
Este comando lˆ dos valores do arquivo ENTRADA.DAT usando formato livre e atribuindo os valores `s vari´veis
e
a
a
X e Y.
Finalmente, no exemplo:
WRITE(*,FMT= 10)A, B
10 FORMAT(’Valores: ’,2(F15.6,2X))
O comando WRITE acima usa o formato especificado no r´tulo 10 para escrever na sa´ padr˜o os valores
o
ıda
a
das vari´veis A e B. O formato de sa´ pode ser descrito como: “2 instˆncias de: um objeto real com 15
a
ıda
a
colunas ao todo com uma precis˜o de 6 casas decimais (F15.6), seguido por 2 espa¸os em branco (2X)”.
a
c
O formato de E/S de dados ´ definido fazendo-se uso dos descritores de edi¸˜o, abordados na pr´xima
e
ca
o
se¸˜o.
ca

9.8

Descritores de edi¸˜o
ca

Nos exemplos apresentados nas se¸˜es anteriores, alguns descritores de edi¸˜o j´ foram mencionados.
co
ca a
Estes editores fornecem uma especifica¸˜o precisa sobre como os valores devem ser convertidos em uma
ca
string escrita em um dispositivo externo (monitor, impressora, etc) ou em um arquivo interno (disco r´
ıgido,
CD-RW, fita, etc), ou convertido de uma string em um dispositivo de entrada de dados (teclado, etc) ou
arquivo interno para as diferentes representa¸˜es de tipos de vari´veis suportados pela linguagem.
co
a
Com algumas exce¸˜es, descritores de edi¸˜o aparecem em uma lista separados por v´
co
ca
ırgulas e somente
no caso em que a lista de E/S for vazia ou contiver somente matrizes de tamanho zero que os descritores
podem estar totalmente ausentes.
Em um processador que suporta tanto caracteres mai´sculos quanto min´sculos, os descritores de edi¸˜o
u
u
ca
s˜o interpretados de forma independente com rela¸˜o ao caso.
a
ca
Descritores de edi¸˜o dividem-se em trˆs classes:
ca
e
Descritores de edi¸˜o de dados: I, B, O, Z, F, E, EN, ES, D, G, L, A.
ca
Descritores de controle: T, TL, TR, X, S, SP, SS, BN, BZ, P, :, /.
Descritores de edi¸˜o de strings: H, ’c’, “c” (onde c ´ uma constante de caractere).
ca
e
Estes descritores ser˜o discutidos em mais detalhes a seguir.
a

9.8.1

Contadores de repeti¸˜o
ca

Os descritores de edi¸˜o de dados podem ser precedidos por um contador de repeti¸˜o: uma constante
ca
ca
inteira positiva (sem sinal), como no exemplo
10F12.3
a qual indica 10 constantes reais com 12 posi¸˜es ao todo e com precis˜o de 3 casas decimais cada. Dos
co
a
descritores de edi¸˜o restantes, somente a barra “/” pode ter um contador de repeti¸˜o associado. Um
ca
ca
contador de repeti¸˜o tamb´m pode ser aplicado a um grupo de descritores de edi¸˜o, delimitado por
ca
e
ca
parˆnteses:
e
PRINT ’(4(I5,F8.2))’, (I(J), A(J), J= 1,4)
o que ´ equivalente a escrever:
e
PRINT ’(I5,F8.2,I5,F8.2,I5,F8.2,I5,F8.2)’, (I(J), A(J), J= 1,4)
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
136

9.8. Descritores de edi¸˜o
ca
Tabela 9.1: Descritores de edi¸ao que convertem os tipos intr´
c˜
ınsecos.

Descritor
A
B
D
E
EN
ES
F
G
I
L
O
Z

Tipo de dados convertidos
Caractere
Inteiro de/para base bin´ria
a
Real
Real com expoente
Real com nota¸˜o de engenharia
ca
Real com nota¸˜o cient´
ca
ıfica
Real de ponto flutuante (sem expoente)
Todos os tipo intr´
ınsecos
Inteiro
L´gico
o
Inteiro de/para base octal
Inteiro de/para base hexadecimal

Note tamb´m o la¸o DO implicado (implied-Do list)
e
c
(I(J), A(J), J= 1,4)
o que equivale a escrever
I(1), A(1), I(2), A(2), I(3), A(3), I(3), A(3)
Contadores de repeti¸˜o como estes podem ser encadeados:
ca
PRINT ’(2(2I5,2F8.2))’, (I(J),I(J+1),A(J),A(J+1), J=1,4,2)
Pode-se ver que esta nota¸˜o possibilita compactar a formata¸˜o de E/S de dados.
ca
ca
Se uma especifica¸˜o de formato ´ usada com uma lista de E/S que cont´m mais elementos que o
ca
e
e
n´mero de descritores de formata¸˜o, incluindo os contadores de repeti¸˜o, um novo registro ir´ come¸ar
u
ca
ca
a
c
e a especifica¸˜o de formato ser´ repetida at´ que todos os elementos forem cobertos. Isto acontece, por
ca
a
e
exemplo, no comando abaixo:
PRINT ’(10I8)’, (I(J), J= 1, 100)

9.8.2

Descritores de edi¸˜o de dados
ca

Cada tipo intr´
ınseco de vari´veis em Fortran ´ convertido por um conjunto espec´
a
e
ıfico de descritores, com
exce¸˜o do descritor G, que pode converter qualquer tipo intr´
ca
ınseco. A tabela 9.1 apresenta uma descri¸˜o
ca
das convers˜es.
o
Formato dos descritores de edi¸˜o de dados.
ca
Um descritor de edi¸˜o de dados pode assumir uma das seguintes formas em uma lista de formata¸˜o de
ca
ca
E/S:
[<r>]<c><w>
[<r>]<c><w>.<m>
[<r>]<c><w>.<d>
[<r>]<c><w>.<d>[E<e>]
onde os campos <r>, <w>, <d> e <e> devem ser todos constantes inteiras positivas (sem sinal). Parˆmetros
a
de esp´cie de tipo n˜o podem ser especificados. O significado dos campos ´ o seguinte:
e
a
e
<r> ´ o contador de repeti¸˜o. O seu valor pode variar entre 1 e 2147483647 (2**31 - 1). Se <r> for
e
ca
omitido, ele ´ assumido igual a 1.
e
<c> ´ um dos descritores: I, B, O, Z, F, EN, ES, D, G, L, A.
e
<w> ´ o n´mero total de d´
e
u
ıgitos no campo (ou a largura do campo). Se <w> for omitido, ´ assumido um
e
valor padr˜o que pode variar com o sistema, por´m <w> n˜o pode ser nulo.
a
e
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

137

<m> ´ o n´mero m´
e
u
ınimo de d´
ıgitos que devem aparecer no campo (incluindo zeros precedentes). O intervalo
permitido para <m> inicia em 0 mas o valor final depende do sistema.
<d> ´ o n´mero de d´
e
u
ıgitos ` direita do ponto decimal (os d´
a
ıgitos significativos). O intervalo de <d> inicia
em 0 mas o valor final depende do sistema. O n´mero de d´
u
ıgitos significativos ´ afetado se um fator
e
de escala ´ especificado para o descritor de edi¸˜o.
e
ca
E identifica um campo de expoente.
<e> ´ o n´mero de d´
e
u
ıgitos no expoente. O intervalo de <e> inicia em 1 mas o valor final depende do sistema.
Os descritores de edi¸˜o de dados tˆm as seguintes formas espec´
ca
e
ıficas:
Tipo de dado
Inteiro
Real e Complexo
L´gico
o
Caractere

Descritores de dado
I<w>[.<m>], B<w>[.<m>], O<w>[.<m>],
Z<w>[.<m>], G<w>.<d>[E<e>]
F<w>.<d>, E<w>.<d>[E<e>], EN<w>.<d>[E<e>],
ES<w>.<d>[E<e>], D<w>.<d>, G<w>.<d>[E<e>]
L<w>, G<w>.<d>[E<e>]
A[<w>], G<w>.<d>[E<e>]

O campo <d> deve ser especificado com os descritores F, E, D e G mesmo se <d> for zero. O ponto
decimal tamb´m ´ exigido. Para uma constante de caractere, o campo <w> ´ opcional, independente do
e e
e
tamanho da constante.
Para todos os descritores num´ricos, se o campo de escrita for muito estreito para conter o n´mero
e
u
completo, de acordo com a descri¸˜o fornecida, o campo ´ preenchido por <w> asteriscos.
ca
e
Na sa´ os n´meros s˜o geralmente escritos deslocados para a direita no espa¸o de campo especificado
ıda
u
a
c
por <w>; isto ´ feito preenchendo de espa¸os em branco ` esquerda, caso necess´rio. Valores negativos s˜o
e
c
a
a
a
sempre escritos com o sinal de menos.
Na entrada os n´meros tamb´m deveriam ser lidos a partir da direita. Espa¸os em branco ` esquerda
u
e
c
a
s˜o ignorados. Se o campo ´ todo composto por espa¸os em branco, o registro ser´ lido como zero.
a
e
c
a
N´ meros inteiros (I<w>[.<m>], B<w>[.<m>], O<w>[.<m>], Z<w>[.<m>])
u
Na sua forma b´sica, I<w>, o inteiro ser´ lido ou escrito no campo de largura <w> ajustado ` direita.
a
a
a
Representando um espa¸o em branco por , o valor -99 escrito sob o controle de I5 ir´ ser aparecer como
c
a
-99, com o sinal contando como uma posi¸˜o no campo.
ca
Para impress˜o, uma forma alternativa deste descritor permite que o n´mero de d´
a
u
ıgitos a ser impressos
sejam especificados exatamente, mesmo que alguns deles tenham que ser zeros. Trata-se da forma I<w>.<m>,
onde <m> indica o n´mero m´
u
ınimo de d´
ıgitos a ser impressos. Neste caso, o valor 99 impresso sob o controle
de I5.3 aparecer´ como 099. O valor <m> pode ser zero, em cuja situa¸˜o o campo ser´ preenchido por
a
ca
a
brancos se o n´mero impresso for 0. Na entrada, I<w>.<m> ´ interpretado exatamente da mesma forma que
u
e
I<w>.
Inteiros tamb´m podem ser convertidos pelos descritores B<w>[.<m>], O<w>[.<m>] e Z<w>[.<m>]. Estes
e
s˜o similares ao descritor I, por´m destinados a representar o n´mero inteiro nos sistemas num´ricos bin´rio,
a
e
u
e
a
octal e hexadecimal, respectivamente.
N´ meros reais (F<w>.<d>, E<w>.<d>[E<e>], EN<w>.<d>[E<e>], ES<w>.<d>[E<e>], D<w>.<d>)
u
A forma b´sica, F<w>.<d>, gera um n´mero real de ponto flutuante. O ponto decimal conta como uma
a
u
posi¸˜o no campo. Na entrada de dados, se a string possui um ponto decimal, o valor de <d> ´ ignorado. Por
ca
e
exemplo, a leitura da string 9.3729 com o descritor F8.3 causa a transferˆncia do valor 9.3729. Todos
e
os d´
ıgitos s˜o usados, mas arredondamento pode ocorrer devido ` representa¸˜o finita de um n´mero pelo
a
a
ca
u
computador.
H´ outras duas formas de entrada de n´meros aceit´veis pelo descritor F<w>.<d>:
a
u
a
1. N´mero sem ponto decimal. Neste caso, os <d> d´
u
ıgitos mais ` direita ser˜o tomados como a parte
a
a
fracion´rio do n´mero. Por exemplo, a string -14629ser´ lida pelo descritor F7.2 como -146.29.
a
u
a
2. N´mero real na forma padr˜o; a qual envolve uma parte exponencial (se¸˜o 3.3), como o n´mero
u
a
ca
u
-14.629E-2 ou sua forma variante, onde o expoente sempre tem sinal e o indicador de expoente
“E” ´ omitido: -14.629-2. Neste caso, o campo <d> ser´ novamente ignorado e o n´mero na forma
e
a
u
exponencial ser´ escrita na forma de ponto flutuante. Sob o controle do descritor F9.1, a string anterior
a
ser´ convertida ao n´mero 0.14629.
a
u
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
138

9.8. Descritores de edi¸˜o
ca

Estas propriedades aplicam-se ` entrada de dados.
a
Na sa´ de dados, os valores s˜o arredondados seguindo as regras normais de aritm´tica. Assim, o valor
ıda
a
e
10.9336, sob o controle do descritor F8.3 ir´ aparecer escrito como 10.934 e sob o controle de F4.0 ir´
a
a
aparecer como 11. (note o ponto).
O descritor de edi¸˜o E possui duas formas, E<w>.<d> e E<w>.<d>E<e> e ´ uma maneira mais apropriada
ca
e
de transferir n´meros abaixo de 0.01 ou acima de 1000.
u
As regras para estes descritores na entrada de dados s˜o idˆnticas `s do descritor F<w>.<d>. Na sa´
a
e
a
ıda
com o descritor E<w>.<d>, uma string de caractere contendo a parte inteira com valor absoluto menor que
um e quatro caracteres que consistem ou no E seguido por um sinal e dois d´
ıgitos ou de um sinal seguido por
trˆs d´
e ıgitos. Assim, o n´mero 1.234 × 1023 , convertido pelo descritor E10.4 vai gerar a string .1234E + 24
u
ou .1234 + 024. A forma contendo a letra E n˜o ´ usada se a magnitude do expoente exceder 99. Por
a e
exemplo, E10.4 ir´ imprimir o n´mero 1.234 × 10−150 como .1234 − 149. Alguns processadores p˜e um
a
u
o
zero antes do ponto decimal. Note que agora o valor de <w> deve ser grande o suficiente para acomodar,
al´m dos d´
e
ıgitos, o sinal (se for negativo), o ponto decimal, a letra E (caso poss´
ıvel), o sinal do expoente e o
expoente. Assim, caso se tentasse imprimir o n´mero anterior com o descritor F9.4, apareceria *********.
u
Na segunda forma do descritor, E<w>.<d>E<e>, o campo <e> determina o n´mero de d´
u
ıgitos no expoente.
Esta forma ´ obrigat´ria para n´meros cujos expoentes tˆm valor absoluto maior que 999. Assim, o n´mero
e
o
u
e
u
1.234 × 101234 , com o descritor E12.4E4 ´ transferido como a string .1234E + 1235.
e
O descritor de edi¸˜o EN implementa a nota¸˜o de engenharia. Ele atua de forma semelhante ao descritor
ca
ca
E, exceto que na sa´ o expoente decimal ´ m´ltiplo de 3, a parte inteira ´ maior ou igual a 1 e menor que
ıda
e u
e
1000 e o fator de escala n˜o tem efeito. Assim, o n´mero 0.0217 transferido sob EN9.2 ser´ convertido a
a
u
a
21.70E-03 ou 21.70-003.
O descritor de edi¸˜o ES implementa a nota¸˜o cient´
ca
ca
ıfica. Ele atua de forma semelhante ao descritor E,
exceto que na sa´ o valor absoluto da parte inteira ´ maior ou igual a 1 e menor que 10 e o fator de escala
ıda
e
n˜o tem efeito. Assim, o n´mero 0.0217 transferido sob ES9.2 ser´ convertido a 2.17E-02 ou 2.17E-002.
a
u
a
N´ meros complexos (F<w>.<d>, E<w>.<d>[E<e>], EN<w>.<d>[E<e>], ES<w>.<d>[E<e>], D<w>.<d>)
u
N´meros complexos podem ser editados sob o controle de pares dos mesmos descritores de n´meros reais.
u
u
Os dois descritores n˜o necessitam ser idˆnticos. O valor complexo (0.1,100.), convertido sob o controle
a
e
de F6.1,8.1 seria convertido a 0.1 .1E+03. Os dois descritores podem ser separados por uma constante
de caracteres e descritores de controle de edi¸˜o.
ca
Valores l´gicos (L<w>)
o
Valores l´gicos podem ser editados usando o descritor L<w>. este define um campo de tamanho <w> o
o
qual, na entrada consiste de brancos opcionais, opcionalmente seguidos por um ponto decimal, seguido por
T ou F. Opcionalmente, este caractere pode ser seguido por caracteres adicionais. Assim, o descritor L7
permite que as strings .TRUE. e .FALSE. sejam lidas com o seu significado correto.
Na sa´
ıda, um dos caracteres T ou F ir´ aparecer na posi¸˜o mais ` direita do campo.
a
ca
a
Vari´veis de caracteres A[<w>]
a
Valores de caracteres podem ser editados usando o descritor A com ou sem o campo <w>. Sem o campo,
a largura do campo de entrada ou sa´ ´ determinado pelo tamanho real do ´
ıda e
ıtem na lista de E/S, medido
em termos do n´mero de caracteres de qualquer esp´cie.
u
e
Por outro lado, usando-se o campo <w> pode-se determinar o tamanho desejado da string lida ou escrita.
Por exemplo, dada a palavra TEMPORARIO, temos os seguintes resultados no processo de escrita:
Descritor
A
A11
A8

Registro escrito
TEMPORARIO
TEMPORARIO
TEMPORAR

Ou seja, quando o campo do descritor ´ menor que o tamanho real do registro, este ´ escrito com os caracteres
e
e
mais ` esquerda. Por outro lado, em caso de leitura da mesma string, as seguintes formas ser˜o geradas:
a
a
Descritor
A
A11
A8
Autor: Rudi Gaelzer – IFM/UFPel

Registro lido
TEMPORARIO
TEMPORARIO
TEMPORAR
Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

139

Todos os caracteres transferidos sob o controle de um descritor A ou A<w> tˆm a esp´cie do ´
e
e
ıtem na lista
de E/S. Al´m disso, este descritor ´ o unico que pode ser usado para transmitir outros tipos de caracteres,
e
e ´
distintos dos caracteres padr˜es.
o
Descritor geral G<w>.<d>[E<e>]
O descritor de edi¸˜o geral pode ser usado para qualquer tipo intr´
ca
ınseco de dados. Quando usado para
os tipos real ou complexo, a sua a¸˜o ´ idˆntica ` do descritor E<w>.<d>[E<e>], exceto que na sa´ de
ca e e
a
ıda
dados, quando a magnitude (n) do valor est´ no intervalo
a
0.1 − 0.5 × 10−<d>−1 ≤ n < 10<d> − 0.5
ou zero quando <d>= 0, s˜o convertidas como com o descritor F, seguidos pelo mesmo n´mero de brancos que
a
u
o descritor E teria reservado ` parte exponencial. Esta forma ´ util para escrever valores cujas magnitudes
a
e´
n˜o s˜o bem conhecidas previamente e quando a convers˜o do descritor F ´ prefer´ ` do descritor E.
a a
a
e
ıvel a
Quando o descritor G ´ usado para os tipos inteiro, l´gico e de caracteres, ele segue as regras dos
e
o
respectivos descritores de edi¸˜o .
ca
Tipos derivados
Valores de tipos derivados s˜o editados pela seq¨ˆncia apropriada de descritores de edi¸˜o correspondena
ue
ca
tes aos tipos intr´
ınsecos dos componentes do tipo derivado. Como exemplo,
TYPE :: STRING
INTEGER
:: COMP
CHARACTER(LEN= 20) :: PALAVRA
END TYPE STRING
TYPE(STRING) :: TEXTO
READ(*, ’(I2,A)’)TEXTO
Edi¸˜o de tamanho m´
ca
ınimo de campo
Para possibilitar que os registros de sa´ contenham o m´
ıda
ınimo poss´ de espa¸o n˜o usado, os descriıvel
c a
tores I, F, B, O e Z podem especificar um tamanho de campo igual a zero, como em I0 ou F0.3. Isto n˜o
a
denota um campo de tamanho nulo, mas um campo com o tamanho m´
ınimo necess´rio para conter o valor
a
de sa´ em quest˜o. Este recurso existe para que o programador n˜o precise se preocupar se o tamanho de
ıda
a
a
um campo ´ suficiente para conter o dado, em cuja situa¸˜o o uso padr˜o destes descritores iria gerar uma
e
ca
a
sa´ composta somente por asteriscos.
ıda
Descritor de edi¸˜o de string de caracteres
ca
Uma constante de caracteres da esp´cie padr˜o, sem um parˆmetro de esp´cie especificado, pode ser
e
a
a
e
transferida a um arquivo de sa´ inserindo-a na especifica¸˜o de formato, como no exemplo:
ıda
ca
PRINT”(’Este ´ um exemplo!’)”
e
O qual vai gerar o registro de sa´
ıda:
Este ´ um exemplo
e
cada vez que o comando seja executado. Descritores de edi¸˜o de string de caracteres n˜o podem ser usados
ca
a
em entrada de dados.

9.8.3

Descritores de controle de edi¸˜o
ca

Um descritor de controle de edi¸˜o age de duas formas: determinando como texto ´ organizado ou
ca
e
afetando as convers˜es realizadas por descritores de edi¸˜o de dados subseq¨entes.
o
ca
u
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
140

9.8. Descritores de edi¸˜o
ca

Formato dos descritores de controle de edi¸˜o
ca
Um descritor de controle de edi¸˜o pode assumir uma das seguintes formas em uma lista de formata¸˜o
ca
ca
de E/S:
<c>
<c><n>
<n><c>
onde:
<c> ´ um dos seguintes c´digos de formato: T, TL, TR, X, S, SP, SS, BN, BZ, P, dois pontos (:) e a barra (/).
e
o
<n> ´ um n´mero de posi¸˜es de caracteres. Este n´mero n˜o pode ser uma vari´vel; deve ser uma constante
e
u
co
u
a
a
inteira positiva sem especifica¸˜o de parˆmetro de esp´cie de tipo. O intervalo de <n> inicia em 1 at´
ca
a
e
e
um valor que depende do sistema. Em processadores Intel de 32 bits, por exemplo, o maior valor ´
e
<n>= 2**15 - 1.
Em geral, descritores de controle de edi¸˜o n˜o s˜o repet´
ca a a
ıveis. A unica exce¸˜o ´ a barra (/), a qual pode
´
ca e
tamb´m ser precedida por um contador de repeti¸˜o.
e
ca
Os descritores de controle possuem a seguintes formas espec´
ıficas quanto `s suas fun¸˜es:
a
co
Tipo de controle
Posicional
Sinal
Interpreta¸˜o de brancos
ca
Fator de escala
Miscelˆneo
a

Descritores de controle
T<n>, TL<n>, TR<n>, <n>X
S, SP, SS
BN, BZ
<k>P
:, /

O descritor P ´ uma exce¸˜o ` sintaxe geral dos descritores. Ele ´ precedido por um fator de escala (<k>),
e
ca a
e
em vez de um especificador de posi¸˜o.
ca
Descritores de controle de edi¸˜o tamb´m podem ser agrupados em parˆnteses e precedidos por um
ca
e
e
contador de repeti¸˜o do grupo.
ca
Edi¸˜o posicional
ca
Os descritores T, TL, TR e X especificam a posi¸˜o onde o pr´ximo caractere ´ transferido de ou para um
ca
o
e
registro.
Na sa´ estes descritores n˜o executam a convers˜o e transferˆncia de caracteres propriamente dita, al´m
ıda,
a
a
e
e
de n˜o afetarem o tamanho do registro. Se caracteres s˜o transferidos a posi¸˜es na posi¸˜o especificada por
a
a
co
ca
um destes descritores, ou ap´s esta, posi¸˜es saltadas e que n˜o eram previamente preenchidas por brancos
o
co
a
passam a ser preenchidas. O resultado ´ como se o registro por completo estava inicialmente preenchido por
e
brancos.
Edi¸˜o T
ca
O descritor T especifica uma posi¸˜o de caractere em um registro de E/S. Ele toma a seguinte forma:
ca
T<n>
onde <n> ´ uma constante positiva que indica a posi¸˜o de caractere do registro, relativa ao limite ` esquerda
e
ca
a
do tabulador.
Na entrada, o descritor posiciona o registro externo a ser lido na posi¸˜o de caractere especificada por
ca
<n>. Na sa´
ıda, o descritor indica que a transferˆncia de dados inicia na <n>-´sima posi¸˜o de caractere do
e
e
ca
registro externo.
Exemplos. Suponha que um arquivo possua um registro contendo o valor ABC
de leitura seja executado:

XYZe o seguinte comando

CHARACTER(LEN= 3) :: VALOR1, VALOR2
...
READ(11,’(T7,A3,T1,A3)’)VALOR1, VALOR2
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

141

Os valores lidos ser˜o VALOR1= ’XYZ’ e VALOR2= ’ABC’.
a
Suponha agora que o seguinte comando seja executado:
PRINT 25
25 FORMAT(T51,’COLUNA 2’,T21,’COLUNA 1’)
a seguinte linha ´ impressa na tela do monitor (ou na sa´ padr˜o):
e
ıda
a

00000000011111111112222222222333333333344444444445555555555666666666677777777778
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
COLUNA 1
COLUNA 2
Deve-se notar que as constantes de caractere foram impressas iniciando nas colunas 20 e 50 e n˜o nas colunas
a
21 e 51. Isto ocorreu porque o primeiro caractere do registro impresso foi reservado como um caractere de
controle. Este ´ o comportamento padr˜o na sa´ de dados.
e
a
ıda
Edi¸˜o TL
ca
O descritor TL especifica uma posi¸˜o de caractere ` esquerda da posi¸˜o corrente no registro de E/S. O
ca
a
ca
descritor toma a seguinte forma:
TL<n>
onde <n> ´ uma constante inteira positiva indicando a <n>-´sima posi¸˜o ` esquerda do caractere corrente.
e
e
ca a
Se <n> ´ maior ou igual ` posi¸˜o corrente, o pr´ximo caractere acessado ´ o primeiro caractere do registro.
e
a
ca
o
e
Exemplo. No exemplo anterior, temos:
PRINT 25
25 FORMAT(T51,’COLUNA 2’,T21,’COLUNA 1’,TL20,’COLUNA 3’)
o que gera na tela:

00000000011111111112222222222333333333344444444445555555555666666666677777777778
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
COLUNA 3
COLUNA 1
COLUNA 2
Edi¸˜o TR
ca
O descritor TR especifica uma posi¸˜o de caractere ` direita da posi¸˜o corrente no registro de E/S. O
ca
a
ca
descritor toma a seguinte forma:
TR<n>
onde <n> ´ uma constante inteira positiva indicando a <n>-´sima posi¸˜o ` direita do caractere corrente.
e
e
ca a
Edi¸˜o X
ca
O descritor X especifica uma posi¸˜o de caractere ` direita da posi¸˜o corrente no registro de E/S. Este
ca
a
ca
descritor ´ equivalente ao descritor TR. O descritor X toma a seguinte forma:
e
<n>X
onde <n> ´ uma constante inteira positiva indicando a <n>-´sima posi¸˜o ` direita do caractere corrente.
e
e
ca a
Na sa´
ıda, este descritor n˜o gera a grava¸˜o de nenhum caractere quando ele se encontra no final de uma
a
ca
especifica¸˜o de formato.
ca
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
142

9.8. Descritores de edi¸˜o
ca

Edi¸˜o de sinal
ca
Os descritores S, SP e SS controlam a sa´ do sinal de mais (+) opcional dentro de campos de sa´
ıda
ıda
num´ricos. Estes descritores n˜o tˆm efeito durante a execu¸˜o de comandos de entrada de dados.
e
a e
ca
Dentro de uma especifica¸˜o de formato, um descritor de edi¸˜o de sinal afeta todos os descritores de
ca
ca
dados subseq¨entes I, F, E, EN, ES, D e G at´ que outro descritor de edi¸˜o de sinal seja inclu´ na formata¸˜o.
u
e
ca
ıdo
ca
Edi¸˜o SP
ca
O descritor SP for¸a o processador a produzir um sinal de mais em qualquer posi¸˜o subseq¨ente onde
c
ca
u
ele seria opcional. O descritor toma a forma simples
SP
Edi¸˜o SS
ca
O descritor SS for¸a o processador a suprimir um sinal de mais em qualquer posi¸˜o subseq¨ente onde
c
ca
u
ele seria opcional. O descritor toma a forma simples
SS
Edi¸˜o S
ca
O descritor S retorna o status do sinal de mais como opcional para todos os campos num´ricos sube
seq¨entes. O descritor toma a forma simples
u
S
Interpreta¸˜o de brancos
ca
Os descritores BN e BZ controlam a interpreta¸˜o de brancos posteriores embebidos dentro de campos de
ca
entrada num´ricos. Estes descritores n˜o tˆm efeito durante a execu¸˜o de comandos de sa´ de dados.
e
a e
ca
ıda
Dentro de uma especifica¸˜o de formato, um descritor de edi¸˜o de brancos afeta todos os descritores de
ca
ca
dados subseq¨entes I, B, O, Z, F, E, EN, ES, D e G at´ que outro descritor de edi¸˜o de brancos seja inclu´
u
e
ca
ıdo
na formata¸˜o.
ca
Os descritores de edi¸˜o de brancos sobrep˜e-se ao efeito do especificador BLANK durante a execu¸˜o de
ca
o
ca
um comando de entrada de dados.
Edi¸˜o BN
ca
O descritor BN for¸a o processador a ignorar todos os brancos posteriores embebidos em campos de
c
entrada num´ricos. O descritor toma a forma simples:
e
BN
O campo de entrada ´ tratado como se todos os brancos tivessem sido removidos e o restante do campo ´
e
e
escrito na posi¸ao mais ` direita. Um campo todo composto de brancos ´ tratado como zero.
c˜
a
e
Edi¸˜o BZ
ca
O descritor BZ for¸a o processador a interpretar todos os brancos posteriores embebidos em campos de
c
entrada num´ricos como zeros. O descritor toma a forma simples:
e
BN
Edi¸˜o de fator de escala P
ca
O descritor P especifica um fator de escala, o qual move a posi¸˜o do ponto decimal em valores reais e
ca
das duas partes de valores complexos. O descritor toma a forma
<k>P
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

143

onde <k> ´ uma constante inteira com sinal (o sinal ´ opcional, se positiva) especificando o n´mero de
e
e
u
posi¸˜es, para a esquerda ou para a direita, que o ponto decimal deve se mover (o fator de escala). O
co
intervalo de valores de <k> ´ de -128 a 127.
e
No in´ de um comando de E/S formatado, o valor do fator de escala ´ zero. Se um descritor de escala ´
ıcio
e
e
especificado, o fator de escala ´ fixado, o qual afeta todos os descritores de edi¸˜o de dados reais subseq¨entes
e
ca
u
at´ que outro descritor de escala ocorra. Para redefinir a escala a zero, deve-se obrigatoriamente especificar
e
0P.
Na entrada, um fator de escala positivo move o ponto decimal para a esquerda e um fator negativo move
o ponto decimal para direita. Quando um campo de entrada, usando os descritores F, E, D, EN, ES ou G,
cont´m um expoente expl´
e
ıcito, o fator de escala n˜o tem efeito. Nos outros casos, o valor interno do dado
a
lido na lista de E/S ´ igual ao campo externo multiplicado por 10−<k> . Por exemplo, um fator de escala 2P
e
multiplica um valor de entrada por 0.01, movendo o ponto decimal duas posi¸˜es ` esquerda. Um fator de
co a
escala -2P multiplica o valor de entrada por 100, movendo o ponto decimal duas posi¸˜es ` direita.
co a
A seguinte tabela apresenta alguns exemplos do uso do especificador <k>P na entrada de dados:
Formato
3PE10.5
3PE10.5
-3PE10.5

Campo de entrada
37.614
37.614E2
37.614

Valor interno
.037614
3761.4
37614.0

O fator de escala deve preceder o primeiro descritor de edi¸˜o real associado com ele, mas n˜o necesca
a
sariamente deve preceder o descritor propriamente dito. Por exemplo, todos os seguintes formatos tˆm o
e
mesmo efeito:
(3P,I6,F6.3,E8.1)
(I6,3P,F6.3,E8.1)
(I6,3PF6.3,E8.1)
Note que se o fator de escala precede imediatamente o descritor real associado, a v´
ırgula ´ opcional.
e
Na sa´
ıda, um fator de escala positivo move o ponto decimal para a direita e um fator de escala negativo
move o ponto decimal para a esquerda. Neste caso, o efeito do fator de escala depende em que tipo de edi¸˜o
ca
real est´ associada com o mesmo, como segue:
a
ˆ Para edi¸˜o F, o valor externo iguala o valor interno da lista de E/S multiplicado por 10<k> , alterando
ca
a magnitude do dado.
ˆ Para edi¸˜es E e D, o campo decimal externo da lista de E/S ´ multiplicado por 10<k> e <k> ´ subtra´
co
e
e
ıdo
do expoente, alterando a magnitude do dado. Um fator de escala positivo diminui o expoente; um
fator de escala negativo aumenta o expoente. Para fator de escala positivo, <k> deve ser menor que
<d>+2 sen˜o ocorrer´ um erro no processo de convers˜o de sa´
a
a
a
ıda.
ˆ Para edi¸˜o G, o fator de escala n˜o tem efeito se a magnitude do dado a ser impresso est´ dentro do
ca
a
a
intervalo efetivo do descritor. Se a magnitude estiver fora do intervalo efetivo do descritor, edi¸˜o E ´
ca
e
usada e o fator de escala tem o mesmo efeito como neste caso.
ˆ Para edi¸˜es EN e ES, o fator de escala n˜o tem efeito.
co
a

A seguir, alguns exemplos de sa´ de dados usando o descritor P:
ıda
Formato
1PE12.3
1PE12.2
-1PE12.2

Campo de entrada
-270.139
-270.139
-270.139

Valor interno
-2.701E+02
-2.70E+02
-0.03E+04

O exemplo a seguir tamb´m usa edi¸˜o P:
e
ca
REAL, DIMENSION(6) :: A= 25.0
WRITE(6,10) A
10 FORMAT(’ ’, F8.2,2PF8.2,F8.2)
resultando os seguintes valores gravados na unidade 6:
25.00
2500.00

2500.00
2500.00

2500.00
2500.00

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
144

9.8. Descritores de edi¸˜o
ca

Edi¸˜o com barra (/)
ca
O descritor / termina a transferˆncia de dados para o registro corrente e inicia a transferˆncia de dados
e
e
para um registro novo. Em um arquivo ou na tela, o descritor tem a a¸˜o de iniciar uma nova linha.
ca
A forma que o descritor toma ´:
e
[<r>]/
onde <r> ´ um contador de repeti¸˜o. O intervalo de <r> inicia em 1 at´ um valor que depende do sistema.
e
ca
e
Em processadores intel de 32 bits, o valor m´ximo ´ <r>= 2**15-1.
a
e
M´ltiplas barras for¸am o sistema a pular registros de entrada ou a gerar registros brancos na sa´
u
c
ıda,
como segue:
ˆ Quando n barras consecutivas aparecem entre dois descritores de edi¸˜o, n - 1 registros s˜o pulados na
ca
a
entrada ou n - 1 registros brancos s˜o gerados na sa´
a
ıda. A primeira barra termina o registro corrente.
A segunda barra termina o primeiro pulo ou registro em branco e assim por diante.
ˆ Quando n barras consecutivas aparecem no in´ ou final de uma especifica¸˜o de formato, n registros
ıcio
ca
s˜o pulados ou n registros em branco s˜o gerados na sa´
a
a
ıda, porque o parˆnteses inicial e final da
e
especifica¸˜o de formato s˜o, por si mesmos, iniciadores ou finalizadores de registros, respectivamente
ca
a

Por exemplo, dado a seguinte formata¸˜o de sa´
ca
ıda:
WRITE(6,99)
99 FORMAT(’1’,T51,’Linha Cabe¸alho’//T51,’Sublinha Cabe¸alho’//)
c
c
ir´ gerar os seguintes registros no arquivo:
a
00000000011111111112222222222333333333344444444445555555555666666666677777777778
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
Linha Cabe¸alho
c
<linha em branco>
Sublinha Cabe¸alho
c
<linha em branco>
<linha em branco>
Edi¸˜o com dois pontos (:)
ca
O descritor : termina o controle de formato se n˜o houver mais ´
a
ıtens na lista de E/S. Por exemplo,
supondo os seguintes comandos:
PRINT 1, 3
PRINT 2, 13
1 FORMAT(’ I=’,I2,’ J=’,I2)
2 FORMAT(’ K=’,I2,:,’ L=’,I2)
as seguintes linhas aparecem na sa´
ıda:
I= 3 J=
K=13
Se houver ´
ıtens de E/S restantes, o descritor : n˜o tem efeito.
a

9.8.4

Descritores de edi¸˜o de strings
ca

Descritores de edi¸˜o de strings controlam a sa´ das constantes de string. Estes descritores s˜o:
ca
ıda
a
ˆ Constantes de caracteres
ˆ Descritor de edi¸˜o H (eliminado no Fortran 95).
ca

Um descritor de edi¸˜o de strings n˜o pode ser precedido por um contador de repeti¸˜o; contudo, eles
ca
a
ca
podem fazer parte de um grupo contido entre parˆnteses, o qual, por sua vez, ´ precedido por um contador
e
e
de repeti¸˜o.
ca
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

145

Edi¸˜o de constantes de caracteres
ca
O descritor de constante de caracteres provoca a sa´ de uma constante de string em um registro externo.
ıda
Ele vem em duas formas:
ˆ ’<string>’
ˆ “<string>”

onde <string> ´ uma constante de caracteres, sem especifica¸˜o de esp´cie. O seu comprimento ´ o n´mero
e
ca
e
e
u
de caracteres entre os delimitadores; dois delimitadores consecutivos s˜o contados como um caractere.
a
Para incluir um ap´strofe (’) em uma constante de caractere que ´ delimitada por ap´strofes, deve-se
o
e
o
colocar duas ap´strofes consecutivas (”) na formata¸˜o. Por exemplo,
o
ca
50 FORMAT(’Today”s date is:

’,i2,’/’,i2,’/’,i2)

Da mesma forma, para incluir aspas (“) em uma constante de caractere que ´ delimitada por aspas,
e
deve-se colocar duas aspas consecutivas na formata¸˜o.
ca
Como exemplo do uso dos comandos de E/S apresentados nas se¸˜es 9.4 – 9.8, o programa a seguir abre
co
o arquivo pessoal.dat, o qual cont´m registros dos nomes de pessoas (at´ 15 caracteres), idade (inteiro de
e
e
3 d´
ıgitos), altura (em metros e cent´
ımetros) e n´mero de telefone (inteiro de 8 d´
u
ıgitos). O programa lˆ estes
e
dados contidos em pessoal.dat e os imprime no monitor no formato:
Altura
Nome
Idade (metros) Tel. No.
-------------------P. A. Silva
45
1,80
33233454
J. C. Pedra
47
1,75
34931458
etc.
P O R M Pessoais dados
RGA
IMPLICIT N N
O E
C A A T R(LEN=15) : : name
H R CE
INTEGER : : age , t e l n o , stat
REAL : : h e i g h t
OPEN(UNIT=8, FILE=’ p e s s o a l . dat ’ )
WRITE( * , 1 0 0 )
100 F R A T24 , ’ Altura ’ )
O M T(
WRITE( * , 2 0 0 )
200 F R A T4 , ’ Nome ’ , T17 , ’ Idade ’ , T23 , ’ ( metros ) ’ , T32 , ’ Tel . No . ’ )
O M T(
WRITE( * , 3 0 0 )
300 F R A T4,’−−−−’,T17,’−−−−−’,T23 , ’ −−−−−− ’ , T32,’−−−−−−−−’)
O M T(
DO
READ( 8 , F T= ’( a15 , 1 x , i 3 , 1 x , f 4 . 2 , 1 x , i 8 ) ’ , IOSTAT stat ) name, &
M
=
age , h e i g h t , t e l n o
IF ( stat <0) EXIT
! Testa f i n a l de a r q u i v o
WRITE( * , 4 0 0 ) name, age , h e i g h t , t e l n o
400 F R A
O M T(A, T18 , I3 , T25 , F4 . 2 , T32 , I 8 )
END DO
END P O R M P e s s o a i s d a d o s
RGA
sendo que o arquivo pessoal.dat possui a seguinte formata¸˜o:
ca
P . A. S i l v a
J . C . Pedra

045 1 . 8 0 33233454
047 1 . 7 5 34931458

Cabe ressaltar tamb´m que os comandos FORMAT utilizados nos r´tulos 100, 200, 300 e 400 poderiam ser
e
o
igualmente substitu´
ıdos pelo especificador FMT=. Por exemplo, as linhas
WRITE(*,200)
200 FORMAT(T4,’Nome’,T17,’Idade’,T23,’(metros)’,T32,’Tel. No.’)
s˜o equivalentes a
a
WRITE(*, FMT=’(T4,”Nome”,T17,”Idade”,T23,”(metros)”,T32,”Tel.
Autor: Rudi Gaelzer – IFM/UFPel

No.”)’)

Impresso: 13 de abril de 2010
146

9.9. Comando CLOSE

9.9

Comando CLOSE

O prop´sito do comando CLOSE ´ desconectar um arquivo de uma unidade. Sua forma ´:
o
e
e
CLOSE([UNIT=]<u>[, IOSTAT=<ios>][, ERR= <err-label>][, STATUS=<status>])
onde <u>, <ios> e <err-label> tˆm os mesmos significados descritos para o comando OPEN (se¸˜o 9.4).
e
ca
Novamente, especificadores em palavras-chaves podem aparecer em qualquer ordem, mas o especificador de
unidade deve ser o primeiro ser for usada a forma posicional.
A fun¸˜o do especificador STATUS= ´ de determinar o que acontecer´ com o arquivo uma vez desconectado.
ca
e
a
O valor de <status>, a qual ´ uma express˜o escalar de caracteres da esp´cie padr˜o, pode ser um dos valores
e
a
e
a
’KEEP’ ou ’DELETE’, ignorando qualquer branco posterior. Se o valor ´ ’KEEP’, um arquivo que existe
e
continuar´ existindo ap´s a execu¸˜o do comando CLOSE, e pode ser posteriormente conectado novamente
a
o
ca
a uma unidade. Se o valor ´ ’DELETE’, o arquivo n˜o mais existir´ ap´s a execu¸˜o do comando. Se o
e
a
a o
ca
especificador for omitido, o valor padr˜o ´ ’KEEP’, exceto se o arquivo tem o status ’SCRATCH’, em cujo
a e
caso o valor padr˜o ´ ’DELETE’.
a e
Em qualquer caso, a unidade fica livre para ser conectada novamente a um arquivo. O comando CLOSE
pode aparecer em qualquer ponto no programa e se ´ executado para uma unidade n˜o existente ou descoe
a
nectada, nada acontece.
No final da execu¸˜o de um programa, todas as unidades conectadas s˜o fechadas, como se um comando
ca
a
CLOSE sem o especificador STATUS= fosse aplicado a cada unidade conectada.
Como exemplo:
CLOSE(2, IOSTAT=IOS, ERR=99, STATUS=’DELETE’)

9.10

Comando INQUIRE

O status de um arquivo pode ser definido pelo sistema operacional antes da execu¸˜o do programa ou
ca
pelo programa durante a sua execu¸˜o, seja por um comando OPEN ou seja por alguma a¸˜o sobre um arquivo
ca
ca
pr´-conectado que o faz existir. Em qualquer momento, durante a execu¸˜o do programa, ´ poss´ inquirir
e
ca
e
ıvel
a respeito do status e atributos de um arquivo usando o comando INQUIRE.
Usando uma variante deste comando, ´ poss´ determinar-se o status de uma unidade; por exemplo,
e
ıvel
se o n´mero de unidade existe para o sistema em quest˜o, se o n´mero est´ conectado a um arquivo e, em
u
a
u
a
caso afirmativo, quais os atributos do arquivo. Outra variante do comando permite inquirir-se a respeito do
tamanho de uma lista de sa´ quando usada para escrever um registro n˜o formatado.
ıda
a
Alguns atributos que podem ser determinados pelo uso do comando INQUIRE s˜o dependentes de outros.
a
Por exemplo, se um arquivo n˜o est´ conectado a uma unidade, n˜o faz sentido inquirir-se a respeito da
a
a
a
forma de acesso que est´ sendo usada para este arquivo. Se esta inquiri¸˜o ´ feita, de qualquer forma, o
a
ca e
especificador relevante fica indefinido.
As trˆs variantes do comando s˜o conhecidas como INQUIRE por arquivo, INQUIRE por unidade e INQUIRE
e
a
por lista de sa´
ıda. Na descri¸˜o feita a seguir, as primeiras duas variantes s˜o descritas juntas. Suas formas
ca
a
s˜o:
a
INQUIRE({[UNIT=]<u>|FILE=<arq>}[, IOSTAT=<ios>][, ERR=<err-label>]
[, EXIST=<ex>][, OPENED=<open>][, NUMBER=<num>][, NAMED=<nmd>]
[, NAME=<nam>][, ACCESS=<acc>][, SEQUENTIAL=<seq>][, DIRECT=<dir>]
[, FORM=<frm>][, FORMATTED=<fmt>][, UNFORMATTED=<unf>][, RECL=<rec>]
[, NEXTREC=<nr>][, BLANK=<bl>][, POSITION=<pos>][, ACTION=<act>]
[, READ=<rd>][, WRITE=<wr>][, READWRITE=<rw>][, DELIM=<del>][, PAD=<pad>])

&
&
&
&
&

onde os especificadores entre chaves ({}) s˜o excludentes; o primeiro deve ser usado no caso de INQUIRE
a
por unidade e o segundo no caso de INQUIRE por arquivo. Neste ultimo caso, <arq> ´ uma express˜o escalar
´
e
a
de caracteres cujo valor, ignorando quaisquer brancos posteriores, fornece o nome do arquivo envolvido,
incluindo o caminho. A interpreta¸˜o de <arq> depende do sistema. Em um sistema Unix/Linux, o nome
ca
depende do caso.
Um especificador n˜o pode aparecer mais de uma vez na lista de especificadores opcionais. Todas as
a
atribui¸˜es de valores aos especificadores seguem as regras usuais e todos os valores do tipo de caracteres,
co
exceto no caso de NAME= s˜o mai´sculos. Os especificadores, cujos valores s˜o todos escalares e da esp´cie
a
u
a
e
padr˜o s˜o:
a a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

147

IOSTAT= <ios>, tem o mesmo significado descrito no comando OPEN (se¸˜o 9.4). A vari´vel <ios> ´ a unica
ca
a
e ´
definida se uma condi¸˜o de erro ocorre durante a execu¸˜o do INQUIRE.
ca
ca
ERR= <err-label>, tem o mesmo significado descrito no comando OPEN (se¸˜o 9.4).
ca
EXIST= <ex>, onde <ex> ´ uma vari´vel l´gica. O valor .TRUE. ´ atribu´ se o arquivo (ou unidade)
e
a
o
e
ıdo
existir e .FALSE. em caso contr´rio.
a
OPENED= <open>, onde <open> ´ uma vari´vel l´gica. O valor .TRUE. ´ atribu´ se o arquivo (ou unidade)
e
a
o
e
ıdo
estiver conectado a uma unidade (ou arquivo) e .FALSE. em caso contr´rio.
a
NUMBER= <num>, onde <num> ´ uma vari´vel inteira ` qual ´ atribu´ o n´mero da unidade conectada ao
e
a
a
e
ıdo
u
arquivo, ou -1 se nenhuma unidade estiver conectada ao arquivo.
NAMED= <nmd>,
NAME= <nam>, onde <nmd> ´ uma vari´vel l´gica ` qual o valor .TRUE. ´ atribu´ se o arquivo tem um
e
a
o
a
e
ıdo
nome ou .FALSE. em caso contr´rio. Se o arquivo tem um nome, este ser´ atribu´ ` vari´vel de
a
a
ıdo a
a
caracteres <nam>. Este valor n˜o ´ necessariamente o mesmo que ´ dado no especificador FILE=, se
a e
e
usado, mas pode ser qualificado de alguma forma. Contudo, em qualquer situa¸˜o ´ um nome v´lido
ca e
a
para uso em um comando OPEN subseq¨ente. Assim, o INQUIRE pode ser usado para determinar o
u
valor real de um arquivo antes deste ser conectado. Dependendo do sistema, o nome depende do caso.
ACCESS= <acc>, onde <acc> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos um dos valores ’SEQUENTIAL’ ou ’DIRECT’ dependendo do m´todo de acesso para um arquivo que est´ conectado e ’UNDEe
a
FINED’ se n˜o houver conex˜o.
a
a
SEQUENTIAL= <seq>,
DIRECT= <dir>, onde <seq> e <dir> s˜o vari´veis de caracteres `s quais s˜o atribu´
a
a
a
a
ıdos os valores ’YES’,
’NO’ ou ’UNKNOWN’, dependendo se o arquivo puder ser aberto para acesso direto ou seq¨encial,
u
respectivamente, ou se isto n˜o pode ser determinado.
a
FORM= <frm>, onde <frm> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos um dos valores ’FORMATTED’ ou
’UNFORMATTED’, dependendo na forma para a qual o arquivo ´ realmente conectado, ou ’UNDEFINED’
e
se n˜o houver conex˜o.
a
a
FORMATTED= <fmt>,
UNFORMATTED= <unf>, onde <fmt> e <unf> s˜o vari´veis de caracteres `s quais s˜o atribu´
a
a
a
a
ıdos os valores
’YES’, ’NO’ ou ’UNKNOWN’, dependendo se o arquivo puder ser aberto para acesso formatado ou n˜o
a
formatado, respectivamente, ou se isto n˜o pode ser determinado.
a
RECL= <rec>, onde <rec> ´ uma vari´vel inteira ` qual ´ atribu´ o valor do tamanho do registro de um
e
a
a
e
ıdo
arquivo conectado para acesso direto, ou o tamanho m´ximo do registro permitido para um arquivo
a
conectado para acesso seq¨encial. O comprimento ´ o n´mero de caracteres para registros formatados
u
e
u
contendo somente caracteres do tipo padr˜o e dependente do sistema em caso contr´rio. Se n˜o houver
a
a
a
conex˜o, <rec> resulta indefinido.
a
NEXTREC= <nr>, onde <nr> ´ uma vari´vel inteira ` qual ´ atribu´ o valor do n´mero do ultimo registro
e
a
a
e
ıdo
u
´
lido ou escrito, mais um. Se nenhum registro foi ainda lido ou escrito, <nr>= 1. Se o arquivo n˜o
a
estiver conectado para acesso direto ou se a posi¸˜o ´ indeterminada devido a um erro anterior, <nr>
ca e
resulta indefinido.
BLANK= <bl>, onde <bl> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos os valores ’NULL’ ou ’ZERO’,
dependendo se os brancos em campos num´ricos devem ser por padr˜o interpretados como campos de
e
a
nulos ou de zeros, respectivamente, ou ’UNDEFINED’ se ou n˜o houver conex˜o ou se a conex˜o n˜o
a
a
a a
for para E/S formatada.
POSITION= <pos>, onde <pos> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos os valores ’REWIND’,
’APPEND’ ou ’ASIS’, conforme especificado no correspondente comando OPEN, se o arquivo n˜o foi
a
reposicionado desde que foi aberto. Se n˜o houver conex˜o ou se o arquivo est´ conectado para acesso
a
a
a
direto, o valor ´ ’UNDEFINED’. Se o arquivo foi reposicionado desde que a conex˜o foi estabelecida, o
e
a
valor depende do processador (mas n˜o deve ser ’REWIND’ ou ’APPEND’ exceto se estes corresponderem
a
a
` verdadeira posi¸˜o).
ca
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
148

9.11. Outros comandos de posicionamento

ACTION= <act>, onde <act> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos os valores ’READ’, ’WRITE’
ou ’READWRITE’, conforme a conex˜o. Se n˜o houver conex˜o, o valor ´ ’UNDEFINED’.
a
a
a
e
READ= <rd>, onde <rd> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos os valores ’YES’, ’NO’ ou
’UNKNOWN’, dependendo se leitura ´ permitida, n˜o permitida ou indeterminada para o arquivo.
e
a
WRITE= <wr>, onde <wr> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos os valores ’YES’, ’NO’ ou
’UNKNOWN’, dependendo se escrita ´ permitida, n˜o permitida ou indeterminada para o arquivo.
e
a
READWRITE= <rw>, onde <rw> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos os valores ’YES’, ’NO’ ou
’UNKNOWN’, dependendo se leitura e escrita s˜o permitidas, n˜o permitidas ou indeterminadas para o
a
a
arquivo.
DELIM= <del>, onde <del> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos os valores ’QUOTE’, ’APOSTROPHE’ ou ’NONE’, conforme especificado pelo correspondente comando OPEN (ou pelo valor padr˜o).
a
Se n˜o houver conex˜o, ou se o arquivo n˜o estiver conectado para E/S formatada, o valor ´ ’UNDEa
a
a
e
FINED’.
PAD= <pad>, onde <pad> ´ uma vari´vel de caracteres ` qual s˜o atribu´
e
a
a
a
ıdos os valores ’YES’, caso assim
especificado pelo correspondente comando OPEN (ou pelo valor padr˜o); em caso contr´rio, o valor ´
a
a
e
’NO’.
Uma vari´vel que ´ a especifica¸˜o em um comando INQUIRE, ou est´ associada com um, n˜o deve aparecer
a
e
ca
a
a
em outra especificador no mesmo comando.
A terceira variante do comando INQUIRE, INQUIRE por lista de E/S, tem a forma:
INQUIRE(IOLENGTH=<comp>) <lista-sa´da>
ı
onde <comp> ´ uma vari´vel inteira escalar padr˜o que ´ usada para determinar o comprimento de uma
e
a
a
e
<lista-sa´da> n˜o formatada em unidades que dependem do processador. Esta vari´vel pode ser usada
ı
a
a
para estabelecer se, por exemplo, uma lista de sa´ ´ muito grande para o tamanho do registro dado pelo
ıda e
especificador RECL= de um comando OPEN, ou ser usado como o valor do comprimento a ser determinado ao
especificador RECL=.
Um exemplo de uso do comando INQUIRE ´ dado abaixo:
e
LOGICAL
:: EX, OP
CHARACTER(LEN= 11) :: NAM, ACC, SEQ, FRM
INTEGER
:: IREC, NR
...
OPEN(2, IOSTAT= IOS, ERR= 99, FILE= ’Cidades’, STATUS= ’NEW’, &
ACCESS= ’DIRECT’, RECL= 100)
INQUIRE(2, ERR= 99, EXIST= EX, OPENED= OP, NAME= NAM, ACCESS= ACC, &
SEQUENTIAL= SEQ, FORM= FRM, RECL= IREC, NEXTREC= NR)
Ap´s execu¸˜o bem sucedida dos comandos OPEN e INQUIRE, as vari´veis ter˜o os seguintes valores:
o
ca
a
a
EX= .TRUE.
OP= .TRUE.
NAM= ’Cidades
’
ACC= ’DIRECT
’
SEQ= ’NO
’
FRM= ’UNFORMATTED’
IREC= 100
NR= 1

9.11

Outros comandos de posicionamento

Outros comandos que exercem fun¸˜es de controle no arquivo, em adi¸˜o ` entrada e sa´ de dados,
co
ca a
ıda
s˜o fornecidos abaixo.
a
Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
Cap´
ıtulo 9. Comandos de Entrada/Sa´ de Dados
ıda

9.11.1

149

Comando BACKSPACE

Pode acontecer em um programa que uma s´rie de registros sejam escritos e que, por alguma raz˜o, o
e
a
ultimo registro escrito deve ser substitu´ por um novo; isto ´, o ultimo registro deve ser sobrescrito. De
´
ıdo
e
´
forma similar, durante a leitura dos registros, pode ser necess´rio reler o ultimo registro, ou verificar por
a
´
leitura o ultimo registro escrito. Para estes prop´sitos, Fortran fornece o comando BACKSPACE, o qual tem
´
o
a sintaxe
BACKSPACE([UNIT=]<u>[, IOSTAT=<ios>][, ERR=<err-label>])
onde <u> ´ uma express˜o inteira escalar padr˜o que designa o n´mero da unidade e os outros especificadores
e
a
a
u
opcionais tˆm o mesmo significado que no comando READ (se¸˜o 9.5).
e
ca
A a¸˜o deste comando ´ posicionar o arquivo antes do registro corrente, se houver. Se o comando for
ca
e
tentado quando o registro estiver no in´ do arquivo, nada ocorre. Se o arquivo estiver posicionado ap´s
ıcio
o
um registro de final de arquivo, este resulta posicionado antes deste registro.
N˜o ´ poss´ solicitar BACKSPACE em um arquivo que n˜o exista, nem sobre um registro escrito por um
a e
ıvel
a
comando NAMELIST. Uma serie de comandos BACKSPACE resultar´ no retrocesso no n´mero correspondente
a
u
de registros.

9.11.2

Comando REWIND

De forma semelhante a uma releitura, re-escritura ou verifica¸˜o por leitura de um registro, uma opera¸˜o
ca
ca
similar pode ser realizada sobre um arquivo completo. Com este prop´sito, o comando REWIND:
o
REWIND([UNIT=]<u>[, IOSTAT=<ios>][ERR=<err-label>])
pode ser usado para reposicionar um arquivo, cujo n´mero de unidade ´ especificado pela express˜o escalar
u
e
a
inteira <u>. Novamente, os demais especificadores opcionais tˆm o mesmo significado que no comando READ.
e
Se o arquivo j´ estiver no seu in´
a
ıcio, nada ocorre. O mesmo ocorre caso o arquivo n˜o exista.
a

9.11.3

Comando ENDFILE

O final de um arquivo conectado para acesso seq¨encial ´ normalmente marcado por um registro especial,
u
e
denominado registro de final de arquivo, o qual ´ assim identificado pelo computador.
e
Quando necess´rio, ´ poss´
a
e
ıvel escrever-se um registro de final de arquivo explicitamente, usando o comando ENDFILE:
ENDFILE([UNIT=]<u>[, IOSTAT=<ios>][, ERR=<err-label>])
onde todos os argumentos tˆm o mesmo significado que nos comandos anteriores.
e
O arquivo ´ ent˜o posicionado ap´s o registro de final de arquivo. Este registro, se lido subseq¨entemente
e
a
o
u
por um programa, deve ser manipulado usado a especifica¸˜o END=<end-label> do comando READ sen˜o a
ca
a
execu¸˜o do programa ir´ normalmente terminar.
ca
a
Antes da transferˆncia de dados, um arquivo n˜o pode estar posicionado ap´s o registro de final de
e
a
o
arquivo, mas ´ poss´ retroceder com os comandos BACKSPACE ou REWIND, o que permite a ocorrˆncia de
e
ıvel
e
outras transferˆncias de dados.
e
Um registro de final de arquivo ´ automaticamente escrito sempre quando ou uma opera¸˜o de retrocesso
e
ca
parcial ou completo segue um opera¸˜o de escrita como a opera¸˜o seguinte na unidade; quando o arquivo
ca
ca
´ fechado por um comando CLOSE, por um novo comando OPEN na mesma unidade ou por encerramento
e
normal do programa.
Se o arquivo tamb´m pode ser conectado para acesso direto, somente os registros al´m do registro de
e
e
final de arquivo s˜o considerados como escritos e somente estes podem ser lidos em uma conex˜o de acesso
a
a
direto subseq¨ente.
u

Autor: Rudi Gaelzer – IFM/UFPel

Impresso: 13 de abril de 2010
´
Indice Remissivo
ˆ
Ambito
Nomes, 118
R´tulos, 118
o

Intr´
ınsecas
SINH, 68
Puras, 104
Recursivas, 101
Rotinas de m´dulos, 111
o
Valor matricial, 98

COUNT, rotina intr´
ınseca, 74
EXTERNAL, atributo e declara¸˜o, 98
ca

SAVE, atributo e declara¸˜o, 103
ca
FORALL, comando e construto, 62
WHERE, comando e construto, 57
INTENT, atributo e declara¸˜o, 84
ca
Interfaces, 86
Gen´ricas, 114, 117
e
INTRINSIC, atributo e declara¸˜o, 65
ca
M´dulos, 107
o
Dados globais, 108
Rotinas de, 111
Rotinas gen´ricas, 114, 117
e
Matrizes
Ajust´veis, 93
a
Aloc´veis, 59
a
Autom´ticas, 95
a
Construtores de, 55
Express˜es e atribui¸˜es, 49
o
co
Format assumida, 94
Se¸˜es de, 51
co
Tamanho assumido, 93
Terminologia, 45
Tipos derivados, 47
ONLY, op¸˜o, 107, 110
ca
PRIVATE, atributo e declara¸˜o, 113
ca
PUBLIC, atributo e declara¸˜o, 113
ca
ınseca, 78
RANDOM NUMBER, rotina intr´
RANDOM SEED, rotina intr´
ınseca, 78
RESHAPE, rotina intr´
ınseca, 56, 76
RETURN, comando, 84
Rotinas, 81
Argumentos, 83
Matrizes, 92
Opcionais, 91
Palavras-Chave, 88
Subprogramas como argumentos, 97
Tipos derivados, 92
Elementais, 106
Externas, 86
Gen´ricas, 114
e
Internas, 83
150

Apostila de fortran

  • 1.
    Introdu¸˜o ao Fortran90/95 ca Apostila preparada para a disciplina de Modelos Computacionais da F´ ısica I, ministrada para o Curso de Licenciatura em F´ ısica do Departamento de F´ ısica, Instituto de F´ ısica e Matem´tica, Funda¸˜o Universidade a ca Federal de Pelotas, Pelotas - RS. In´ ıcio: Janeiro de 2005. Vers˜o: 12 de abril de 2010 a
  • 3.
    Sum´rio a Referˆncias Bibliogr´ficas e a v 1 Introdu¸˜o ca 1.1As origens da Linguagem Fortran . . . . . . . . . . 1.2 O padr˜o Fortran 90 . . . . . . . . . . . . . . . . . a 1.2.1 Recursos novos do Fortran 90 . . . . . . . . 1.2.2 Recursos em obsolescˆncia do Fortran 90 . e 1.2.3 Recursos removidos do Fortran 90 . . . . . 1.3 Uma revis˜o menor: Fortran 95 . . . . . . . . . . . a 1.3.1 Recursos novos do Fortran 95 . . . . . . . . 1.3.2 Recursos em obsolescˆncia do Fortran 95 . e 1.3.3 Recursos removidos do Fortran 95 . . . . . 1.4 O Fortran no S´culo XXI: Fortran 2003 . . . . . . e 1.4.1 Recursos novos do Fortran 2003 . . . . . . . 1.4.2 Recursos em obsolescˆncia do Fortran 2003 e 1.4.3 Recursos removidos do Fortran 2003 . . . . 1.5 O novo padr˜o: Fortran 2008 . . . . . . . . . . . . a 1.5.1 Recursos novos do Fortran 2008 . . . . . . . 1.6 Coment´rios sobre a bibliografia . . . . . . . . . . a 1.7 Observa¸˜es sobre a apostila e agradecimentos . . co . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 2 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 2 Formato do C´digo-Fonte o 2.1 Formato do programa-fonte . . 2.2 Nomes em Fortran 90/95 . . . 2.3 Entrada e sa´ padr˜es . . . . ıda o 2.4 Conjunto de caracteres aceitos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 . 9 . 11 . 11 . 12 3 Tipos de Vari´veis a 3.1 Declara¸˜o de tipo de vari´vel . . . . . . . . . . ca a 3.2 Vari´veis do tipo INTEGER . . . . . . . . . . . . a 3.3 Vari´veis do tipo REAL . . . . . . . . . . . . . . a 3.4 Vari´veis do tipo COMPLEX . . . . . . . . . . . . a 3.5 Vari´veis do tipo CHARACTER . . . . . . . . . . . a 3.6 Vari´veis do tipo LOGICAL . . . . . . . . . . . . a 3.7 O conceito de esp´cie (kind) . . . . . . . . . . . e 3.7.1 Fortran 77 . . . . . . . . . . . . . . . . . 3.7.2 Fortran 90/95 . . . . . . . . . . . . . . . 3.7.2.1 Compilador Intel® Fortran 3.7.2.2 Compilador gfortran . . . . . 3.7.2.3 Compilador F . . . . . . . . . . 3.7.2.4 Literais de diferentes esp´cies . e 3.7.3 Fun¸˜es intr´ co ınsecas associadas ` esp´cie a e 3.7.3.1 KIND(X) . . . . . . . . . . . . 3.7.3.2 SELECTED_REAL_KIND(P,R) . . 3.7.3.3 SELECTED_INT_KIND(R) . . . . 3.8 Tipos derivados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i 13 13 14 14 15 15 16 17 17 17 17 19 19 21 22 22 22 23 23
  • 4.
    ii ´ SUMARIO 4 Express˜es eAtribui¸˜es Escalares o co 4.1 Regras b´sicas . . . . . . . . . . . . . . . . . . a 4.2 Express˜es num´ricas escalares . . . . . . . . . o e 4.3 Atribui¸˜es num´ricas escalares . . . . . . . . . co e 4.4 Operadores relacionais . . . . . . . . . . . . . . 4.5 Express˜es e atribui¸˜es l´gicas escalares . . . . o co o 4.6 Express˜es e atribui¸˜es de caracteres escalares o co . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 27 28 29 30 30 32 5 Comandos e Construtos de Controle de Fluxo 5.1 Comandos obsoletos do Fortran 77 . . . . . . . 5.1.1 R´tulos (statement labels) . . . . . . . . o 5.1.2 Comando GO TO incondicional . . . . . . 5.1.3 Comando GO TO computado . . . . . . . 5.1.4 Comando IF aritm´tico . . . . . . . . . e 5.1.5 Comandos ASSIGN e GO TO atribu´ . . ıdo 5.1.6 La¸os DO rotulados . . . . . . . . . . . . c 5.2 Comando e construto IF . . . . . . . . . . . . . 5.2.1 Comando IF . . . . . . . . . . . . . . . 5.2.2 Construto IF . . . . . . . . . . . . . . . 5.3 Construto DO . . . . . . . . . . . . . . . . . . . 5.3.1 Construto DO ilimitado . . . . . . . . . . 5.3.2 Instru¸˜o EXIT . . . . . . . . . . . . . . ca 5.3.3 Instru¸˜o CYCLE . . . . . . . . . . . . . ca 5.4 Construto CASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 35 35 36 36 36 36 37 37 38 38 39 41 41 42 42 6 Processamento de Matrizes 6.1 Terminologia e especifica¸˜es de matrizes . . . . . co 6.2 Express˜es e atribui¸˜es envolvendo matrizes . . . o co 6.3 Se¸˜es de matrizes . . . . . . . . . . . . . . . . . . co 6.3.1 Subscritos simples . . . . . . . . . . . . . . 6.3.2 Tripleto de subscritos . . . . . . . . . . . . 6.3.3 Vetores de subscritos . . . . . . . . . . . . . 6.4 Atribui¸˜es de matrizes e sub-matrizes . . . . . . . co 6.5 Matrizes de tamanho zero . . . . . . . . . . . . . . 6.6 Construtores de matrizes . . . . . . . . . . . . . . . 6.6.1 A fun¸˜o intr´ ca ınseca RESHAPE. . . . . . . . . 6.6.2 A ordem dos elementos de matrizes . . . . . 6.7 Rotinas intr´ ınsecas elementais aplic´veis a matrizes a 6.8 Comando e construto WHERE . . . . . . . . . . . . . 6.8.1 Comando WHERE . . . . . . . . . . . . . . . 6.8.2 Construto WHERE . . . . . . . . . . . . . . . 6.9 Matrizes aloc´veis . . . . . . . . . . . . . . . . . . a 6.10 Comando e construto FORALL . . . . . . . . . . . . 6.10.1 Comando FORALL . . . . . . . . . . . . . . . 6.10.2 Construto FORALL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 45 49 51 52 52 52 53 53 55 56 56 57 57 57 58 59 62 62 62 7 Rotinas Intr´ ınsecas 7.1 Categorias de rotinas intr´ ınsecas . . . . . . . . . . . . . 7.2 Declara¸˜o e atributo INTRINSIC . . . . . . . . . . . . . ca 7.3 Fun¸˜es inquisidoras de qualquer tipo . . . . . . . . . . co 7.4 Fun¸˜es elementais num´ricas . . . . . . . . . . . . . . . co e 7.4.1 Fun¸˜es elementais que podem converter . . . . . co 7.4.2 Fun¸˜es elementais que n˜o convertem . . . . . . co a 7.5 Fun¸˜es elementais matem´ticas . . . . . . . . . . . . . co a 7.6 Fun¸˜es elementais l´gicas e de caracteres . . . . . . . . co o 7.6.1 Convers˜es caractere-inteiro . . . . . . . . . . . . o 7.6.2 Fun¸˜es de compara¸˜o l´xica . . . . . . . . . . . co ca e 7.6.3 Fun¸˜es elementais para manipula¸˜es de strings co co 7.6.4 Convers˜o l´gica . . . . . . . . . . . . . . . . . . a o 7.7 Fun¸˜es n˜o-elementais para manipula¸˜o de strings . . co a ca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 65 65 66 66 66 67 67 68 68 69 69 69 69 Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 5.
    ´ SUMARIO 7.8 7.9 7.10 7.11 7.12 7.13 7.14 7.15 7.16 7.17 iii 7.7.1 Fun¸˜o inquisidorapara manipula¸˜o de strings . . . . . ca ca 7.7.2 Fun¸˜es transformacionais para manipula¸˜o de strings co ca Fun¸˜es inquisidoras e de manipula¸˜es num´ricas . . . . . . . co co e 7.8.1 Modelos para dados inteiros e reais . . . . . . . . . . . . 7.8.2 Fun¸˜es num´ricas inquisidoras . . . . . . . . . . . . . . co e 7.8.3 Fun¸˜es elementais que manipulam quantidades reais . . co 7.8.4 Fun¸˜es transformacionais para valores de esp´cie (kind) co e Rotinas de manipula¸˜o de bits . . . . . . . . . . . . . . . . . . ca 7.9.1 Fun¸˜o inquisidora . . . . . . . . . . . . . . . . . . . . . ca 7.9.2 Fun¸˜es elementais . . . . . . . . . . . . . . . . . . . . . co 7.9.3 Subrotina elemental . . . . . . . . . . . . . . . . . . . . Fun¸˜o de transferˆncia . . . . . . . . . . . . . . . . . . . . . . ca e Fun¸˜es de multiplica¸˜o vetorial ou matricial . . . . . . . . . . co ca Fun¸˜es transformacionais que reduzem matrizes . . . . . . . . co 7.12.1 Caso de argumento unico . . . . . . . . . . . . . . . . . ´ 7.12.2 Argumento opcional DIM . . . . . . . . . . . . . . . . . . 7.12.3 Argumento opcional MASK . . . . . . . . . . . . . . . . . Fun¸˜es inquisidoras de matrizes . . . . . . . . . . . . . . . . . co 7.13.1 Status de aloca¸˜o . . . . . . . . . . . . . . . . . . . . . ca 7.13.2 Limites, forma e tamanho . . . . . . . . . . . . . . . . . Fun¸˜es de constru¸˜o e manipula¸˜o de matrizes . . . . . . . . co ca ca 7.14.1 Fun¸˜o elemental MERGE . . . . . . . . . . . . . . . . . . ca 7.14.2 Agrupando e desagrupando matrizes . . . . . . . . . . . 7.14.3 Alterando a forma de uma matriz . . . . . . . . . . . . 7.14.4 Fun¸˜o transformacional para duplica¸˜o . . . . . . . . ca ca 7.14.5 Fun¸˜es de deslocamento matricial . . . . . . . . . . . . co 7.14.6 Transposta de uma matriz . . . . . . . . . . . . . . . . . Fun¸˜es transformacionais para localiza¸˜o geom´trica . . . . . co ca e Fun¸˜o transformacional para dissocia¸˜o de ponteiro . . . . . ca ca Subrotinas intr´ ınsecas n˜o-elementais . . . . . . . . . . . . . . . a 7.17.1 Rel´gio de tempo real . . . . . . . . . . . . . . . . . . . o 7.17.2 Tempo da CPU . . . . . . . . . . . . . . . . . . . . . . . 7.17.3 N´meros aleat´rios . . . . . . . . . . . . . . . . . . . . . u o 8 Sub-Programas e M´dulos o 8.1 Unidades de programa . . . . . . . . . . . . . . . . . . . . . . 8.1.1 Programa principal . . . . . . . . . . . . . . . . . . . . 8.1.2 Rotinas externas . . . . . . . . . . . . . . . . . . . . . 8.1.3 M´dulos . . . . . . . . . . . . . . . . . . . . . . . . . . o 8.2 Sub-programas . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.1 Fun¸˜es e subrotinas . . . . . . . . . . . . . . . . . . . co 8.2.2 Rotinas internas . . . . . . . . . . . . . . . . . . . . . 8.2.3 Argumentos de sub-programas . . . . . . . . . . . . . 8.2.4 Comando RETURN . . . . . . . . . . . . . . . . . . . . . 8.2.5 Atributo e declara¸˜o INTENT . . . . . . . . . . . . . . ca 8.2.6 Rotinas externas e bibliotecas . . . . . . . . . . . . . . 8.2.7 Interfaces impl´ ıcitas e expl´ ıcitas . . . . . . . . . . . . . 8.2.8 Argumentos com palavras-chave . . . . . . . . . . . . 8.2.9 Argumentos opcionais . . . . . . . . . . . . . . . . . . 8.2.10 Tipos derivados como argumentos de rotinas . . . . . 8.2.11 Matrizes como argumentos de rotinas . . . . . . . . . 8.2.11.1 Matrizes como argumentos em Fortran 77 . . 8.2.11.2 Matrizes como argumentos em Fortran 90/95 8.2.12 sub-programas como argumentos de rotinas . . . . . . 8.2.13 Fun¸˜es de valor matricial . . . . . . . . . . . . . . . . co 8.2.14 Recursividade e rotinas recursivas . . . . . . . . . . . 8.2.15 Atributo e declara¸˜o SAVE . . . . . . . . . . . . . . . ca 8.2.16 Fun¸˜es de efeito lateral e rotinas puras . . . . . . . . co 8.2.17 Rotinas elementais . . . . . . . . . . . . . . . . . . . . Autor: Rudi Gaelzer – IFM/UFPel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 70 70 70 70 71 71 72 72 72 73 73 73 74 74 74 74 75 75 75 75 75 75 76 76 76 76 76 77 77 77 78 78 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 79 79 81 81 81 81 83 83 84 84 86 86 88 91 92 92 92 94 97 98 101 103 104 106 Impresso: 12 de abril de 2010
  • 6.
    ´ SUMARIO iv 8.3 8.4 M´dulos . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o 8.3.1 Dados globais . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3.2 Rotinas de m´dulos . . . . . . . . . . . . . . . . . . . . . . . . o 8.3.3 Atributos e declara¸˜es PUBLIC e PRIVATE . . . . . . . . . . . . co 8.3.4 Interfaces e rotinas gen´ricas . . . . . . . . . . . . . . . . . . . e 8.3.5 Estendendo rotinas intr´ ınsecas via blocos de interface gen´ricos e ˆ Ambito (Scope) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ˆ 8.4.1 Ambito dos r´tulos . . . . . . . . . . . . . . . . . . . . . . . . . o ˆ 8.4.2 Ambito dos nomes . . . . . . . . . . . . . . . . . . . . . . . . . 9 Comandos de Entrada/Sa´ de Dados ıda 9.1 Comandos de Entrada/Sa´ ıda: introdu¸˜o r´pida ca a 9.2 Declara¸˜o NAMELIST . . . . . . . . . . . . . . . . ca 9.3 Unidades l´gicas . . . . . . . . . . . . . . . . . . o 9.4 Comando OPEN . . . . . . . . . . . . . . . . . . . 9.5 Comando READ . . . . . . . . . . . . . . . . . . . 9.6 Comandos PRINT e WRITE . . . . . . . . . . . . . 9.7 Comando FORMAT e especificador FMT= . . . . . . 9.8 Descritores de edi¸˜o . . . . . . . . . . . . . . . . ca 9.8.1 Contadores de repeti¸˜o . . . . . . . . . . ca 9.8.2 Descritores de edi¸˜o de dados . . . . . . ca 9.8.3 Descritores de controle de edi¸˜o . . . . . ca 9.8.4 Descritores de edi¸˜o de strings . . . . . . ca 9.9 Comando CLOSE . . . . . . . . . . . . . . . . . . 9.10 Comando INQUIRE . . . . . . . . . . . . . . . . . 9.11 Outros comandos de posicionamento . . . . . . . 9.11.1 Comando BACKSPACE . . . . . . . . . . . . 9.11.2 Comando REWIND . . . . . . . . . . . . . . 9.11.3 Comando ENDFILE . . . . . . . . . . . . . Autor: Rudi Gaelzer – IFM/UFPel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 108 111 113 114 117 118 118 118 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 121 125 129 129 132 133 134 135 135 136 139 144 146 146 148 149 149 149 Impresso: 12 de abril de 2010
  • 7.
    Referˆncias Bibliogr´ficas e a [1] Intel®Fortran Compiler for Linux. http://www.intel.com/software/products/compilers/flin/docs/manuals.htm. Acesso em: 01 jun. 2005. [2] CHAPMAN, STEPHEN J. Fortran 95/2003 for Scientists and Engineers. McGraw-Hill, 2007, xxvi + 976 pp., 3rd. Edi¸˜o. ca [3] MARSHALL, A. C. Fortran 90 Course Notes. http://www.liv.ac.uk/HPC/HTMLFrontPageF90.html, 1996. Acesso em: 01 jun. 2005. [4] METCALF, MICHAEL, REID, JOHN. Fortran 90/95 Explained. New York : Oxford University Press, 1996, 345 + xv pp. [5] PAGE, CLIVE G. Professional Programer’s Guide to Fortran77. prof77.pdf, Leicester, 2001. Acesso em: 01 jun. 2005. http://www.star.le.ac.uk/ cgp/- [6] RAMSDEN, S., LIN, F., PETTIPHER, M. A., NOLAND, OKE, J. M. Fortran 90. A Conversion Course for Fortran http://www.hpctec.mcc.ac.uk/hpctec/courses/Fortran90/F90course.html, 1995. jun. 2005. G. S., BRO77 Programmers. Acesso em: 01 [7] REID, JOHN. The New Features of Fortran 2003. Publicado http://www.fortranplus.co.uk/resources/john reid new 2003.pdf, 2004. Acesso em: 03 Jun. 2006. v em:
  • 8.
    vi Autor: Rudi Gaelzer– IFM/UFPel ˆ ´ REFERENCIAS BIBLIOGRAFICAS Impresso: 12 de abril de 2010
  • 9.
    Cap´ ıtulo 1 Introdu¸˜o ca ”I don’tknow what the technical characteristics of the standard language for scientific and engineering computation in the year 2000 will be... but I know it will be called Fortran.” John Backus Esta apostila destina-se ao aprendizado da Linguagem de Programa¸˜o Fortran 95. ca 1.1 As origens da Linguagem Fortran Programa¸˜o no per´ ca ıodo inicial do uso de computadores para a solu¸˜o de problemas em f´ ca ısica, qu´ ımica, engenharia, matem´tica e outras ´reas da ciˆncia era um processo complexo e tedioso ao extremo. a a e Programadores necessitavam de um conhecimento detalhado das instru¸˜es, registradores, endere¸os de meco c m´ria e outros constituintes da Unidade Central de Processamento (CPU1 ) do computador para o qual o eles escreviam o c´digo. O C´digo-Fonte era escrito em um nota¸˜o num´rica denominada c´digo octal. o o ca e o Com o tempo, c´digos mnemˆnicos foram introduzidos, uma forma de programa¸˜o conhecida como c´digo o o ca o num´rico ou c´digo Assembler. Estes c´digos eram traduzidos em instru¸˜es para a CPU por programas e o o co conhecidos como Assemblers. Durante os anos 50 ficou claro que esta forma de programa¸˜o era de todo ca inconveniente, no m´ ınimo, devido ao tempo necess´rio para se escrever e testar um programa, embora esta a forma de programa¸˜o possibilitasse um uso otimizado dos recursos da CPU. ca Estas dificuldades motivaram que um time de programadores da IBM, liderados por John Backus, desenvolvessem uma das primeiras chamadas linguagem de alto-n´ ıvel, denominada FORTRAN (significando FORmula TRANslation). Seu objetivo era produzir uma linguagem que fosse simples de ser entendida e usada, mas que gerasse um c´digo num´rico quase t˜o eficiente quanto a linguagem Assembler. Desde o o e a in´ ıcio, o Fortran era t˜o simples de ser usado que era poss´ programar f´rmulas matem´ticas quase como a ıvel o a se estas fossem escritas de forma simb´lica. Isto permitiu que programas fossem escritos mais rapidamente o que antes, com somente uma pequena perda de eficiˆncia no processamento, uma vez que todo cuidado era e dedicado na constru¸˜o do compilador, isto ´, no programa que se encarrega de traduzir o c´digo-fonte em ca e o Fortran para c´digo Assembler ou octal. o Mas o Fortran foi um passo revolucion´rio tamb´m porque o programadores foram aliviados da tarefa a e tediosa de usar Assembler, assim concentrando-se mais na solu¸˜o do problema em quest˜o. Mais imporca a tante ainda, computadores se tornaram acess´ ıveis a qualquer cientista ou engenheiro disposto a devotar um pequeno esfor¸o na aquisi¸˜o de um conhecimento b´sico em Fortran; a tarefa da programa¸˜o n˜o estava c ca a ca a mais restrita a um corpus pequeno de programadores especialistas. O Fortran disseminou-se rapidamente, principalmente nas ´reas da f´ a ısica, engenharia e matem´tica, a uma vez que satisfazia uma necessidade premente dos cientistas. Inevitavelmente, dialetos da linguagem foram desenvolvidos, os quais levaram a problemas quando havia necessidade de se trocar programas entre diferentes computadores. O dialeto de Fortran otimizado para processadores fabricados pela IBM, por exemplo, geralmente gerava erro quando se tentava rodar o mesmo programa em um processador Burroughs, ou em outro qualquer. Assim, em 1966, ap´s quatro anos de trabalho, a Associa¸˜o Americana de Padr˜es o ca o (American Standards Association), posteriormente Instituto Americano Nacional de Padr˜es (American o National Standards Institute, ou ANSI) originou o primeiro padr˜o para uma linguagem de programa¸˜o, a ca agora conhecido como Fortran 66. Essencialmente, era uma subconjunto comum de v´rios dialetos, de a tal forma que cada dialeto poderia ser reconhecido como uma extens˜o do padr˜o. Aqueles usu´rios que a a a desejavam escrever programas port´veis deveriam evitar as extens˜es e restringir-se ao padr˜o. a o a 1 Do inglˆs: Central Processing Unit. e 1
  • 10.
    2 1.2. O padr˜oFortran 90 a O Fortran trouxe consigo v´rios outros avan¸os, al´m de sua facilidade de aprendizagem combinada com a c e um enfoque em execu¸˜o eficiente de c´digo. Era, por exemplo, uma linguagem que permanecia pr´xima ca o o (e explorava) o hardware dispon´ ıvel, ao inv´s de ser um conjunto de conceitos abstratos. Ela tamb´m e e introduziu, atrav´s das declara¸˜es COMMON e EQUIVALENCE, a possibilidade dos programadores controlarem e co a aloca¸˜o da armazenagem de dados de uma forma simples, um recurso que era necess´rio nos prim´rdios da ca a o computa¸˜o, quando havia pouco espa¸o de mem´ria, mesmo que estas declara¸˜es sejam agora consideradas ca c o co potencialmente perigosas e o seu uso desencorajado. Finalmente, o c´digo fonte permitia espa¸os em branco o c na sua sintaxe, liberando o programador da tarefa de escrever c´digo em colunas rigidamente definidas e o permitindo que o corpo do programa fosse escrito da forma desejada e visualmente mais atrativa. A prolifera¸ao de dialetos permaneceu um problema mesmo ap´s a publica¸˜o do padr˜o Fortran 66. A c˜ o ca a primeira dificuldade foi que muitos compiladores n˜o aderiram ao padr˜o. A segunda foi a implementa¸˜o, a a ca em diversos compiladores, de recursos que eram essenciais para programas de grande escala, mas que eram ignorados pelo padr˜o. Diferentes compiladores implementavam estes recursos de formas distintas. a Esta situa¸˜o, combinada com a existˆncia de falhas evidentes na linguagem, tais como a falta de consca e tru¸˜es estruturadas de programa¸˜o, resultaram na introdu¸˜o de um grande n´mero de pr´-processadores. co ca ca u e Estes eram programas que eram capazes de ler o c´digo fonte de algum dialeto bem definido de Fortran e o gerar um segundo arquivo com o texto no padr˜o, o qual ent˜o era apresentado ao compilador nesta forma. a a Este recurso provia uma maneira de estender o Fortran, ao mesmo tempo retendo a sua portabilidade. O problema era que embora os programas gerados com o uso de um pr´-processador fossem port´veis, podendo e a ser compilados em diferentes computadores, o c´digo gerado era muitas vezes de uma dificuldade proibitiva o para a leitura direta. Estas dificuldades foram parcialmente removidas pela publica¸˜o de um novo padr˜o, em 1978, conhecido ca a como Fortran 77. Ele inclu´ diversos novos recursos que eram baseados em extens˜es comerciais ou pr´ıa o e processadores e era, portanto, n˜o um subconjunto comum de dialetos existentes, mas sim um novo dialeto a por si s´. O per´ o ıodo de transi¸˜o entre o Fortran 66 e o Fortran 77 foi muito mais longo que deveria, ca devido aos atrasos na elabora¸˜o de novas vers˜es dos compiladores e os dois padr˜es coexistiram durante ca o o um intervalo de tempo consider´vel, que se estendeu at´ meados da d´cada de 80. Eventualmente, os a e e fabricantes de compiladores passaram a liber´-los somente com o novo padr˜o, o que n˜o impediu o uso de a a a programas escritos em Fortran 66, uma vez que o Fortran 77 permitia este c´digo antigo por compatibilidade. o Contudo, diversas extens˜es n˜o foram mais permitidas, uma vez que o padr˜o n˜o as incluiu na sua sintaxe. o a a a 1.2 O padr˜o Fortran 90 a Ap´s trinta anos de existˆncia, Fortran n˜o mais era a unica linguagem de programa¸˜o dispon´ para o e a ´ ca ıvel os programadores. Ao longo do tempo, novas linguagens foram desenvolvidas e, onde elas se mostraram mais adequadas para um tipo particular de aplica¸˜o, foram adotadas em seu lugar. A superioridade do ca Fortran sempre esteve na ´rea de aplica¸˜es num´ricas, cient´ a co e ıficas, t´cnicas e de engenharia. A comunidade e de usu´rios do Fortran realizou um investimento gigantesco em c´digos, com muitos programas em uso a o freq¨ente, alguns com centenas de milhares ou milh˜es de linhas de c´digo. Isto n˜o significava, contudo, u o o a que a comunidade estivesse completamente satisfeita com a linguagem. V´rios programadores passaram a a migrar seus c´digos para linguagens tais como Pascal, C e C++. Para levar a cabo mais uma moderniza¸˜o o ca da linguagem, o comitˆ t´cnico X3J3, aprovado pela ANSI, trabalhando como o corpo de desenvolvimento e e do comitˆ da ISO (International Standards Organization, Organiza¸˜o Internacional de Padr˜es) ISO/IEC e ca o JTC1/SC22/WG5 (doravante conhecido como WG5), preparou um novo padr˜o, inicialmente conhecido a como Fortran 8x, e agora como Fortran 90. Quais eram as justificativas para continuar com o processo de revis˜o do padr˜o da linguagem Fortran? a a Al´m de padronizar extens˜es comerciais, havia a necessidade de moderniza¸˜o, em resposta aos desenvole o ca vimentos nos conceitos de linguagens de programa¸˜o que eram explorados em outras linguagens tais como ca APL, Algol, Pascal, Ada, C e C++. Com base nestas, o X3J3 podia usar os ´bvios benef´ o ıcios de conceitos tais como ocultamento de dados. Na mesma linha, havia a necessidade de fornecer uma alternativa ` peria gosa associa¸˜o de armazenagem de dados, de abolir a rigidez agora desnecess´ria do formato fixo de fonte, ca a bem como de aumentar a seguran¸a na programa¸˜o. Para proteger o investimento em Fortran 77, todo o c ca padr˜o anterior foi mantido como um subconjunto do Fortran 90. a Contudo, de forma distinta dos padr˜es pr´vios, os quais resultaram quase inteiramente de um esfor¸o o e c de padronizar pr´ticas existentes, o Fortran 90 ´ muito mais um desenvolvimento da linguagem, na qual s˜o a e a introduzidos recursos que s˜o novos em Fortran, mas baseados em experiˆncias em outras linguagens. Os a e recursos novos mais significativos s˜o a habilidade de manipular matrizes usando uma nota¸˜o concisa mais a ca poderosa e a habilidade de definir e manipular tipos de dados definidos pelo programador. O primeiro destes recursos leva a uma simplifica¸˜o na escrita de muitos problemas matem´ticos e tamb´m torna o Fortran ca a e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 11.
    Cap´ ıtulo 1. Introdu¸˜o ca 3 umalinguagem mais eficiente em supercomputadores. O segundo possibilita aos programadores a express˜o a de seus problemas em termos de tipos de dados que reproduzem exatamente os conceitos utilizados nas sua elabora¸˜es. co 1.2.1 Recursos novos do Fortran 90 Um resumo dos novos recursos ´ dado a seguir: e ˆ O Fortran 90 possui uma maneira para rotular alguns recursos antigos como em obsolescˆncia (isto ´, e e tornando-se obsoletos). ˆ Opera¸˜es de matrizes. co ˆ Ponteiros. ˆ Recursos avan¸ados para computa¸˜o num´rica usando um conjunto de fun¸˜es inquisidoras num´ricas. c ca e co e ˆ Parametriza¸˜o dos tipos intr´ ca ınsecos, permitindo o suporte a inteiros curtos, conjuntos de caracteres muito grandes, mais de duas precis˜es para vari´veis reais e complexas e vari´veis l´gicas agrupadas. o a a o ˆ Tipos de dados derivados, definidos pelo programador, compostos por estruturas de dados arbitr´rias a e de opera¸˜es sobre estas estruturas. co ˆ Facilidades na defini¸˜o de coletˆneas denominadas m´dulos, uteis para defini¸˜es globais de dados e ca a o ´ co para bibliotecas de subprogramas. ˆ Exigˆncia que o compilador detecte o uso de constru¸˜es que n˜o se conformam com a linguagem ou e co a que estejam em obsolescˆncia. e ˆ Um novo formato de fonte, adequado para usar em um terminal. ˆ Novas estruturas de controle, tais como SELECT CASE e uma nova forma para os la¸os DO. c ˆ A habilidade de escrever subprogramas internos e subprogramas recursivos e de chamar subprogramas com argumentos opcionais. ˆ Aloca¸ao dinˆmica de dados (matrizes autom´ticas, matrizes aloc´veis e ponteiros). c˜ a a a ˆ Melhoramentos nos recursos de entrada/sa´ de dados. ıda ˆ V´rios novos subprogramas intr´ a ınsecos. Todos juntos, estes novos recursos contidos em Fortran 90 ir˜o assegurar que o padr˜o continue a ser bem a a sucedido e usado por um longo tempo. O Fortran 77 continua sendo suportado como um subconjunto durante um per´ ıodo de adapta¸˜o. ca Os procedimentos de trabalho adotados pelo comitˆ X3J3 estabelecem um per´ e ıodo de aviso pr´vio antes e que qualquer recurso existente seja removido da linguagem. Isto implica, na pr´tica, um ciclo de revis˜o, que a a para o Fortran ´ de cerca de cinco anos. A necessidade de remo¸˜o de alguns recursos ´ evidente; se a unica e ca e ´ a¸˜o adotada pelo X3J3 fosse de adicionar novos recursos, a linguagem se tornaria grotescamente ampla, ca com muitos ´ ıtens redundantes e sobrepostos. A solu¸˜o finalmente adotada pelo comitˆ foi de publicar como ca e uma apˆndice ao padr˜o um conjunto de duas listas mostrando quais os ´ e a ıtens que foram removidos e quais s˜o os candidatos para uma eventual remo¸˜o. a ca A primeira lista cont´m os recursos removidos (deleted features). A segunda lista cont´m os recursos e e em obsolescˆncia (obsolescent features), os quais s˜o considerados obsoletos e redundantes, sendo assim e a candidatos ` remo¸˜o na pr´xima revis˜o da linguagem. a ca o a 1.2.2 Recursos em obsolescˆncia do Fortran 90 e Os recursos em obsolescˆncia do Fortran 90 s˜o: e a ˆ IF aritm´tico; e ˆ desvio para uma declara¸˜o END IF a partir de um ponto fora de seu bloco; ca ˆ vari´veis reais e de dupla precis˜o nas express˜es de controle de um comando DO; a a o Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 12.
    4 1.3. Uma revis˜omenor: Fortran 95 a ˆ finaliza¸˜o compartilhada de blocos DO, bem como finaliza¸˜o por uma declara¸˜o ou comando distintos ca ca ca de um CONTINUE ou de um END DO; ˆ declara¸˜o ASSIGN e comando GO TO atribu´ ca ıdo; ˆ RETURN alternativo; ˆ comando PAUSE; ˆ especificadores FORMAT atribu´ ıdos; ˆ descritor de edi¸˜o H. ca 1.2.3 Recursos removidos do Fortran 90 Uma vez que Fortran 90 cont´m o Fortran 77 como subconjunto, esta lista permaneceu vazia para o e Fortran 90. 1.3 Uma revis˜o menor: Fortran 95 a Seguindo a publica¸˜o do padr˜o Fortran 90 em 1991, dois significativos desenvolvimentos posteriores ca a referentes ` linguagem Fortran ocorreram. O primeiro foi a continuidade na opera¸˜o dos dois comitˆs de a ca e regulamenta¸˜o do padr˜o da linguagem: o X3J3 e o WG5; o segundo desenvolvimento foi a cria¸˜o do ca a ca F´rum Fortran de Alta Performance (High Performance Fortran Forum, ou HPFF). o Logo no inicio de suas delibera¸˜es, os comitˆs concordaram na estrat´gia de definir uma revis˜o menor co e e a no Fortran 90 para meados da d´cada de 90, seguida por uma revis˜o de maior escala para o in´ dos anos e a ıcio 2000. Esta revis˜o menor passou a ser denominada Fortran 95. a O HPFF teve como objetivo a defini¸˜o de um conjunto de extens˜es ao Fortran tais que permitissem a ca o constru¸˜o de c´digos port´veis quando se fizesse uso de computadores paralelos para a solu¸˜o de problemas ca o a ca envolvendo grandes conjuntos de dados que podem ser representados por matrizes regulares. Esta vers˜o a do Fortran ficou conhecida como o Fortran de Alta Performance (High Performance Fortran, ou HPF), tendo como linguagem de base o Fortran 90, n˜o o Fortran 77. A vers˜o final do HPF consiste em um a a conjunto de instru¸˜es que cont´m o Fortran 90 como subconjunto. As principais extens˜es est˜o na forma co e o a de diretivas, que s˜o vistas pelo Fortran 90 como coment´rios, mas que s˜o reconhecidas por um compilador a a a HPF. Contudo, tornou-se necess´ria tamb´m a inclus˜o de elementos adicionais na sintaxe, uma vez que a e a nem todos os recursos desejados puderam ser acomodados simplesmente na forma de diretivas. ` A medida que os comitˆs X3J3 e WG5 trabalhavam, este comunicavam-se regularmente com o HPFF. e Era evidente que, para evitar o surgimento de dialetos divergentes de Fortran, havia a necessidade de incorporar a sintaxe nova desenvolvida pelo HPFF no novo padr˜o da linguagem. De fato, os recursos do a HPF constituem as novidades mais importantes do Fortran 95. As outras mudan¸as consistem em corre¸˜es, c co clarifica¸˜es e interpreta¸˜es do novo padr˜o. Estas se tornaram prementes quando os novos compiladores co co a de Fortran 90 foram lan¸ados no mercado e utilizados; notou-se uma s´rie de erros e detalhes obscuros que c e demandavam repara¸˜es. Todas estas mudan¸as foram inclu´ co c ıdas no novo padr˜o Fortran 95, que teve a sua a vers˜o inicial lan¸ada no pr´prio ano de 1995.2 a c o O Fortran 95 ´ compat´ e ıvel com o Fortran 90, exceto por uma pequena altera¸˜o na fun¸˜o intr´ ca ca ınseca SIGN (se¸˜o 7.4.2) e a elimina¸˜o de recursos t´ ca ca ıpicos do Fortran 77, declarados em obsolescˆncia no Fortran e 90. Os detalhes do Fortran 95 foram finalizados em novembro de 1995 e o novo padr˜o ISO foi finalmente a publicado em outubro de 1996. 1.3.1 Recursos novos do Fortran 95 Os novos recursos do Fortran 95 est˜o discutidos ao longo desta apostila. Em rela¸˜o ao Fortran 90, a ca foram introduzidos os seguintes recursos: ˆ Concordˆncia aprimorada com o padr˜o de aritm´tica de ponto flutuante bin´ria da IEEE (IEEE 754 a a e a ou IEC 559-1989). ˆ Rotinas (procedures) puras (se¸˜o 8.2.16). ca ˆ Rotinas (procedures) elementais (se¸˜o 8.2.17). ca 2 Fortran 95, Commitee Draft, May 1995. ACM Fortran Forum, v. 12, n. 2, June 1995. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 13.
    Cap´ ıtulo 1. Introdu¸˜o ca 5 ˆDealoca¸˜o autom´tica de matrizes aloc´veis (p´gina 61). ca a a a ˆ Comando e construto FORALL (se¸˜o 6.10). ca ˆ Extens˜es do construto WHERE (p´gina 58). o a ˆ Fun¸˜es especificadoras. co ˆ Inicializa¸˜o de ponteiro e a fun¸˜o NULL (se¸˜o 7.16). ca ca ca ˆ Inicializa¸˜o de componentes de tipo derivado (p´gina 25). ca a ˆ Fun¸˜es elementares CEILING, FLOOR e SIGN (se¸˜es 7.4.1 e 7.4.2). co co ˆ Fun¸˜es transformacionais (7.15). co ˆ Subrotina intr´ ınseca CPU_TIME (se¸˜o 7.17.2). ca ˆ Coment´rio na entrada de uma lista NAMELIST (p´gina 128). a a ˆ Descritores de edi¸˜o com largura de campo m´ ca ınimo. ˆ Especifica¸˜o gen´rica na cl´usula END INTERFACE. ca e a 1.3.2 Recursos em obsolescˆncia do Fortran 95 e Os recursos abaixo entraram na lista em obsolescˆncia do Fortran 95 e, portanto, pouco ou nada foram e comentados ao longo desta Apostila. ˆ Formato fixo de fonte. ˆ Comando GO TO computado. ˆ Declara¸˜o de vari´vel de caractere na forma CHARACTER*. ca a ˆ Declara¸˜es DATA entre comandos execut´veis. co a ˆ Fun¸˜es definidas em uma linha (statement functions). co ˆ Extens˜o assumida de caracteres quando estas s˜o resultados de fun¸˜es. a a co 1.3.3 Recursos removidos do Fortran 95 Cinco recursos foram removidos do padr˜o da linguagem Fortran 95 e, portanto, n˜o ser˜o mais aceitos a a a por compiladores que respeitam o padr˜o Fortran 95. a ˆ ´ Indices de la¸os DO do tipo real (qualquer esp´cie). c e ˆ Declara¸˜o ASSIGN e comando GO TO atribu´ e uso de um inteiro atribu´ por ASSIGN em uma ca ıdo ıdo declara¸˜o FORMAT. ca ˆ Desvio para uma declara¸˜o END IF a partir de um ponto fora do bloco. ca ˆ Comando PAUSE. ˆ Descritor de edi¸˜o H. ca 1.4 O Fortran no S´culo XXI: Fortran 2003 e O Fortran 2003 ´ novamente uma revis˜o grande do padr˜o anterior: Fortran 95. A vers˜o curta (draft) do e a a a novo padr˜o foi divulgada em finais de 20033 e tornou-se desde ent˜o o novo padr˜o da linguagem, embora at´ a a a e o presente momento nenhum compilador apresenta suporte completo do novo padr˜o. As grandes novidades a introduzidas foram: um direcionamento ainda maior para programa¸˜o orientada a objeto, a qual oferece ca uma maneira efetiva de separar a programa¸˜o de um c´digo grande e complexo em tarefas independentes ca o e que permite a constru¸˜o de novo c´digo baseado em rotinas j´ existentes e uma capacidade expandida ca o a de interface com a linguagem C, necess´ria para que os programadores em Fortran possam acessar rotinas a escritas em C e para que programadores de C possam acessar rotinas escritas em Fortran. Esta Apostila n˜o ir´ abordar os novos recursos introduzidos pelo Fortran 2003, limitando-se a list´-los. a a a 3 Ver o draft em: http://www.dkuug.dk/jtc1/sc22/open/n3661.pdf. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 14.
    6 1.4. O Fortranno S´culo XXI: Fortran 2003 e 1.4.1 Recursos novos do Fortran 2003 Os principais recursos introduzidos pelo padr˜o s˜o: a a ˆ Aprimoramentos dos tipos derivados: tipos derivados parametrizados, controle melhorado de acessibilidade, construtores de estrutura aperfei¸oados e finalizadores. c ˆ Suporte para programa¸˜o orientada a objeto: extens˜o de tipo e heran¸a (inheritance), polimorfismo ca a c (polymorphism), aloca¸˜o dinˆmica de tipo e rotinas (procedures) ligadas a tipo. ca a ˆ Aperfei¸oamentos na manipula¸˜o de dados: componentes aloc´veis de estruturas, argumentos mudos c ca a aloc´veis, parˆmetros de tipo deferidos (deferred type parameters), atributo VOLATILE, especifica¸˜o a a ca expl´ ıcita de tipo em construtores de matrizes e declara¸˜es de aloca¸˜o, aperfei¸oamentos em ponteiros, co ca c express˜es de inicializa¸˜o estendidas e rotinas intr´ o ca ınsecas aperfei¸oadas. c ˆ Aperfei¸oamentos em opera¸˜es de Entrada/Sa´ (E/S) de dados: transferˆncia ass´ c co ıda e ıncrona, acesso de fluxo (stream access), opera¸˜es de transferˆncia especificadas pelo usu´rio para tipos derivados, co e a controle especificado pelo usu´rio para o arredondamento em declara¸˜es FORMAT, constantes nomeadas a co para unidades pr´-conectadas, o comando FLUSH, regulariza¸˜o de palavras-chave e acesso a mensagens e ca de erro. ˆ Ponteiros de rotinas (procedure pointers). ˆ Suporte para as exce¸˜es do padr˜o de aritm´tica bin´ria de ponto flutuante ISO/IEC 559, anteriorco a e a mente conhecido como padr˜o IEEE 754. a ˆ Interoperabilidade com a linguagem de programa¸˜o C. ca ˆ Suporte aperfei¸oado para internacionaliza¸˜o: acesso ao conjunto de caracteres de 4 bytes ISO 10646 c ca and escolha de v´ ırgula ou ponto como separador de parte inteira e parte decimal em opera¸˜es de E/S co num´ricas formatadas. e ˆ Integra¸˜o aperfei¸oada com o sistema operacional hospedeiro: acesso a argumentos de linha de coca c mando, vari´veis de ambiente e mensagens de erro do processador. a 1.4.2 Recursos em obsolescˆncia do Fortran 2003 e Nesta lista permanecem ´ ıtens que j´ estavam na lista de obsolescˆncia do Fortran 95. Os crit´rios para a e e inclus˜o nesta lista continuam sendo: recursos redundantes e para os quais m´todos melhores estavam a e dispon´ ıveis no Fortran 95. A lista dos ´ ıtens em obsolescˆncia do Fortran 2003 ´: e e ˆ IF aritm´tico. e ˆ END DO compartilhado por dois ou mais la¸os e t´rmino de um la¸o em uma cl´usula distinta de END c e c a DO ou CONTINUE. ˆ RETURN alternativo. ˆ Comando GO TO computado. ˆ Fun¸˜es definidas em uma linha (statement functions). co ˆ Declara¸˜es DATA entre comandos execut´veis. co a ˆ Fun¸˜es de caractere de extens˜o assumida. co a ˆ Formato fixo da fonte. ˆ Forma CHARACTER* da declara¸˜o CHARACTER. ca 1.4.3 Recursos removidos do Fortran 2003 Um recurso ´ removido do novo padr˜o se este for considerado redundante e praticamente sem uso pela e a comunidade, devido a novos recursos muito mais uteis na constru¸˜o do c´digo. ´ ca o A lista de recursos removidos no Fortran 2003, divulgada no draft, repete os recursos removidos do Fortran 95. Portanto, nenhum outro recurso foi removido. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 15.
    Cap´ ıtulo 1. Introdu¸˜o ca 1.5 7 Onovo padr˜o: Fortran 2008 a Embora ainda n˜o exista nenhum compilador que suporte completamente o padr˜o atual, Fortran 2003, a a j´ est´ em fase de conclus˜o as discuss˜es a respeito do padr˜o futuro: Fortran 2008. A vers˜o curta (draft) a a a o a a do novo padr˜o deve ser divulgada ao final do ano de 2008. a O Fortran 2008, embora pelo procedimento adotado pelos comitˆs X3J3/WG5 devesse ser uma revis˜o e a menor do Fortran 2003, pode vir a apresentar algumas novidades substanciais, tais como as co-matrizes (coarrays). Os detalhes completos dos novos recursos ainda n˜o foram plenamente divulgados para o p´blico a u em geral, mas alguns dos ´ ıtens que ir˜o compor o novo padr˜o, por consenso, est˜o listados a seguir. a a a 1.5.1 Recursos novos do Fortran 2008 Com base em material de divulga¸˜o obtido na World Wide Web, os seguintes recursos ser˜o inclu´ ca a ıdos: ˆ Co-matrizes (co-arrays). ˆ BITS, originalmente denominados objetos sem tipo (TYPELESS). ˆ Macros inteligentes (no lugar de m´dulos parametrizados). o ˆ Atributo CONTIGUOUS. ˆ La¸os DO concorrentes (DO CONCURRENT). c ˆ Interoperabilidade de ponteiros, objetos aloc´veis, matrizes de forma assumida e argumentos opcionais. a ˆ Execu¸ao de programas externos. c˜ ˆ Ponteiro aloc´vel em resolu¸˜o gen´rica a ca e ˆ Rotina interna como argumento real ˆ Inicializa¸˜o de ponteiros com alvos distintos de NULL(). ca ˆ Rotinas intr´ ınsecas estendidas. ˆ Opera¸˜o de E/S recursivas a distintas unidades. ca ˆ ... 1.6 Coment´rios sobre a bibliografia a Para escrever esta apostila, fiz uso de um n´mero restrito de publica¸˜es, algumas das quais s˜o de livre u co a acesso atrav´s da internet. e ˆ Para informa¸˜es a respeito do padr˜o existente na linguagem Fortran 77, a qual foi substitu´ pelo co a ıda Fortran 90/95, utilizei freq¨entemente o livro de Clive Page: Professional Programer’s Guide to Fortran u 77 [5]. ˆ A principal fonte de informa¸˜o sobre o padr˜o do Fortran 90/95 foi o amplo livro de Michael Metcalf ca a e John Reid: Fortran 90/95 Explained [4]. ˆ O curso virtual de Fortran 90 oferecido pela Universidade de Liverpool [3]. ˆ O curso virtual de Fortran 90 para programadores que j´ conhecem o Fortran 77, oferecido pela a Universidade de Manchester [6]. ˆ O manual de referˆncia ` Linguagem Fortran 90/95 que acompanha o compilador intel tamb´m foi e a e freq¨entemente consultado [1]. u ˆ Informa¸˜es divulgadas sobre o Fortran 2003 foram obtidas do livreto de John Reid [7] e do livro de co Stephen Chapman: Fortran 95/2003 for Scientists and Engineers [2]. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 16.
    8 1.7 1.7. Observa¸˜es sobrea apostila e agradecimentos co Observa¸˜es sobre a apostila e agradecimentos co Por se tratar de uma obra em constante revis˜o, esta apostila pode conter (e conter´, invariavelmente) a a uma s´rie de erros de ortografia, pontua¸˜o, acentua¸˜o, etc. Em particular, o texto n˜o foi ainda revisado e ca ca a para se conformar com o novo acordo ortogr´fico da Lingua Portuguesa. Certos pontos poderiam tamb´m a e ser melhor discutidos e podem conter at´ informa¸˜es n˜o completamente corretas. e co a Durante o desenvolvimento e divulga¸˜o desta apostila, algumas pessoas contribuiram com o seu aprica moramento ao apontar erros e inconsistˆncias e ao oferecer sugest˜es quanto a sua estrutura e conte´do. e o u Qualquer contribui¸˜o ´ bem vinda e pode ser enviada ao endere¸o eletrˆnico: rudi@ufpel.edu.br. ca e c o Gostaria de agradecer publicamente as contribui¸˜es das seguintes pessoas: Leandro Tezani. co Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 17.
    Cap´ ıtulo 2 Formato doC´digo-Fonte o Neste cap´ ıtulo estuda-se, inicialmente, um formato b´sico para o programa-fonte em Fortran 90/95 e os a tipos de vari´veis e suas caracter´ a ısticas b´sicas. a 2.1 Formato do programa-fonte Em Fortran h´ trˆs formatos b´sicos de arquivos que s˜o utilizados: a e a a Programa-Fonte. Trata-se do programa e/ou dos subprogramas escritos pelo programador, usando algum tipo de editor de texto, de acordo com as regras definidas pela linguagem de programa¸˜o de alto ca n´ ıvel. Programa-Objeto. Trata-se do programa-fonte compilado pelo compilador. Esta ´ a transcri¸˜o realizada e ca pelo compilador do programa-fonte fornecido pelo programador para uma linguagem de baixo n´ ıvel, como Assembler ou outro c´digo diretamente interpret´vel pela CPU. O programa-objeto n˜o pode o a a ainda ser executado; ´ necess´rio ainda passar-se pela fase do linking (tradu¸˜o livre: linkagem). e a ca Programa execut´vel. Ap´s a fase de compila¸˜o, onde os programas objetos s˜o criados, o agente de a o ca a compila¸˜o aciona o linker, o qual consiste em um programa especial que agrupa os programas objetos ca de forma a criar um arquivo final, o programa execut´vel, o qual pode ser ent˜o executado pelo a a programador. Nesta se¸˜o ser´ apresentada a estrutura b´sica de um programa-fonte em Fortran 90/95. ca a a O Fortran 90/95 suporta duas formas de c´digo-fonte: o formato antigo do Fortran 77, agora denominado o formato fixo e o novo formato livre. Fortran 77: O formato fixo foi utilizado pelo Fortran desde a primeira vers˜o at´ o Fortran 77. Este a e formato foi determinado pelas restri¸˜es impostas pelos cart˜es perfurados, que eram a unica op¸˜o para co o ´ ca entrar com o c´digo fonte. A estrutura do formato fixo ´ a seguinte: o e Colunas 1-5: r´tulos (labels) para desvio de processamento do programa. o Coluna 6: caractere de continua¸˜o de linha. ca Colunas 7-72: c´digo fonte. o H´, ainda, a possibilidade de incluir o caractere “C” ou “c” na coluna 1, o que instrui o compilador a ignorar a tudo que segue neste linha. Esta ´ a forma encontrada para se colocar coment´rios dentro do c´digo fonte. a a o Fortran 90/95: Nestas revis˜es, a linguagem passou a suportar o formato livre, com as seguintes caraco ter´ ısticas. ˆ No formato livre n˜o h´ uma coluna espec´ a a ıfica para iniciar o programa. Pode-se come¸ar a escrever c o c´digo a partir da coluna 1 e a linha de c´digo pode se estender at´ a coluna 132. Al´m disso, os o o e e caracteres em branco s˜o irrelevantes em qualquer lugar do c´digo, exceto quanto estiverem sendo a o utilizados entre ap´strofes. Neste caso, cada caractere em branco ser´ avaliado na composi¸˜o final do o a ca string. 9
  • 18.
    10 2.1. Formato doprograma-fonte ˆ Mais de uma instru¸˜o pode ser colocada na mesma linha. O separador de linhas padr˜o ´ o pontoca a e e-v´ ırgula “;”. M´ltiplos “;” em uma linha, com ou sem brancos, s˜o considerados como um separador u a simples. Desta forma, a seguinte linha de c´digo ´ interpretada como 3 linhas em seq¨ˆncia: o e ue A = 0; B = 0; C = 0 ˆ O caractere ampersand “&” ´ a marca de continua¸˜o, isto ´, ele indica que a linha com instru¸˜es e ca e co imediatamente posterior ´ continua¸˜o da linha onde o “&” foi digitado. Desta forma, s˜o permitidas e ca a at´ 39 linhas adicionais de c´digo. Como exemplo, a seguinte linha de c´digo: e o o X = (-Y + ROOT_OF_DISCRIMINANT)/(2.0*A) tamb´m pode ser escrita usando o “&”: e X = (-Y + ROOT_OF_DISCRIMINANT) /(2.0*A) & & ˆ Para entrar com coment´rios em qualquer ponto do c´digo-fonte, o usu´rio deve digitar o ponto de a o a exclama¸˜o “!” em qualquer coluna de uma linha. Todo o restante da linha ser´ desprezado pelo ca a compilador. Exemplo: X = Y/A - B ! Soluciona a equa¸~o linear. ca O programa “Alˆ Mam˜e”. o a Como primeiro exemplo de programa em Fortran 90/95, considere o seguinte c´digo-fonte: o program p r i m e i r o i m p l i c i t none print * , ”Alˆ Mam˜e” o a end program p r i m e i r o A forma mais simples de um programa em Fortran 90/95 ´ a seguinte: e PROGRAM <nome_do_programa> <declara¸~es de nomes de vari´veis> co a <comandos execut´veis> a END PROGRAM <nome_do_programa> Comparando com o exemplo do programa primeiro, a declara¸˜o ca PROGRAM primeiro ´ sempre a primeira instru¸˜o de um programa. Ela serve para identificar o c´digo ao compilador. e ca o Em seguida vˆm as declara¸~es de nomes de vari´veis. Neste ponto, s˜o definidos os nomes das e co a a vari´veis a ser usadas pelo programa. Caso n˜o seja necess´rio declarar vari´veis, como no programa a a a a primeiro, ´ recomend´vel incluir, pelo menos, a instru¸˜o implicit none. Esta instrui o compilador a e a ca exigir que todas as vari´veis usadas pelo programa tenham o seu tipo explicitamente definido.1 a Ap´s declaradas as vari´veis, vˆm os comandos execut´veis. No caso do programa primeiro, o unico o a e a ´ comando execut´vel empregado foi a print *, “Al^ Mam~e” o a o qual tem como conseq¨ˆncia a impress˜o do texto “Alˆ Mam˜e” na tela do monitor, o qual ´ a chamada ue a o a e sa´ padr˜o. ıda a Finalmente, o programa ´ encerrado com a instru¸˜o e ca end program primeiro Os recursos utilizados no programa primeiro ser˜o explicados com mais detalhes neste e nos pr´ximos a o cap´ ıtulos da apostila. 1 Os tipos de vari´veis suportados pelo Fortran 95 s˜o discutidos no cap´ a a ıtulo 3. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 19.
    Cap´ ıtulo 2. Formatodo C´digo-Fonte o 2.2 11 Nomes em Fortran 90/95 Um programa em Fortran 90/95 faz referˆncia a muitas entidades distintas, tais como programas, sube programas, m´dulos, vari´veis, etc. Os nomes destas entidades devem consistir em caracteres alfanum´ricos, o a e de 1 a 31 caracteres. Os caracteres alfanum´ricos v´lidos s˜o: e a a ˆ Letras (a - z; A - Z). ˆ Numerais (0 - 9). ˆ O caractere underscore “ ”. A unica restri¸˜o ´ que o primeiro caractere seja uma letra. Os seguintes exemplos s˜o v´lidos: ´ ca e a a A A_COISA X1 MASSA Q123 TEMPO_DE_VOO j´ estes exemplos n˜o s˜o v´lidos: a a a a 1A (come¸a com numeral) c A COISA (espa¸o em branco) c $SINAL (cont´m caractere n˜o alfanum´rico). e a e 2.3 Entrada e sa´ padr˜es ıda o O Fortran 90 possui trˆs comandos de entrada/sa´ de dados. A maneira mais direta de definir valores e ıda de vari´veis ou de exibir os valores destas ´ atrav´s dos dispositivos de entrada/sa´ padr˜es. a e e ıda o O dispositivo padr˜o de entrada de dados ´ o teclado. O comando de leitura para o programa ler os a e valores das vari´veis ´: a e READ *, <lista de nomes de vari´veis> a READ(*,*) <lista de nomes de vari´veis> a onde na lista de nomes de vari´veis est˜o listados os nomes das vari´veis que dever˜o receber seus a a a a valores via teclado. O usu´rio deve entrar com os valores das vari´veis separando-as por v´ a a ırgulas. O dispositivo padr˜o de sa´ de dados ´ a tela do monitor. H´ dois comandos de sa´ padr˜o de dados: a ıda e a ıda a PRINT *, [’<mensagem>’[,]][<lista de nomes de vari´veis>] a WRITE(*,*) [’<mensagem>’[,]][<lista de nomes de vari´veis>] a O programa a seguir instrui o computador a ler o valor de uma vari´vel real a partir do teclado e, ent˜o, a a imprimir o valor desta na tela do monitor: program l e v a l o r i m p l i c i t none real : : a print * , ”I n f o r m e o v a l o r de a : ” read * , a print * , ”Valor l i d o : ” , a end program l e v a l o r No programa acima, foi declarada a vari´vel real a, cujo valor ser´ lido pelo computador, a partir do teclado, a a ´ e ent˜o impresso na tela do monitor. E importante salientar que a instru¸˜o implicit none deve ser sempre a ca a segunda linha de um programa, sub-programa ou m´dulo, aparecendo antes do restante das declara¸˜es o co de vari´veis. a Esta se¸˜o apresentou somente um uso muito simples dos recursos de Entrada/Sa´ de dados. Uma ca ıda descri¸˜o mais completa destes recursos ser´ realizada no cap´ ca a ıtulo 9 na p´gina 121. a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 20.
    12 2.4. Conjunto decaracteres aceitos Tabela 2.1: Caracteres especiais do Fortran 90/95 Caractere = + * / ( ) , . $ : 2.4 Nome/Fun¸˜o ca Igual Soma Subtra¸˜o ca Multiplica¸˜o ca Divis˜o a Parˆnteses esquerdo e Parˆnteses direito e V´ ırgula Ponto decimal Cifr˜o a Dois pontos Caractere ! “ % & ; ? ** ’ < > Nome/Fun¸˜o ca Espa¸o em branco c Exclama¸˜o ca Aspas Porcentagem E comercial (ampersand) Ponto e v´ ırgula Ponto de interroga¸˜o ca Potˆncia e Ap´strofe o Menor que Maior que Conjunto de caracteres aceitos No Fortran 90/95, os elementos b´sicos, denominados de tokens, s˜o os caracteres alfanum´ricos, os 10 a a e d´ ıgitos ar´bicos, o underscore “ ” e o conjunto de caracteres especiais apresentados na tabela 2.1. Dentro da a sintaxe da linguagem, n˜o existem diferen¸as entre letras mai´sculas e min´sculas. a c u u Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 21.
    Cap´ ıtulo 3 Tipos deVari´veis a Em Fortran, h´ cinco tipos intr´ a ınsecos de vari´veis: trˆs tipos num´ricos, inteiros, reais e complexos (em a e e inglˆs INTEGER, REAL e COMPLEX) e dois tipos n˜o num´ricos, caracteres e l´gicos (em inglˆs CHARACTER e e a e o e LOGICAL). O primeiro grupo de vari´veis ´ utilizado em opera¸˜es matem´ticas e ´ o mais utilizado. O a e co a e segundo grupo ´ utilizado para opera¸˜es que envolvem manipula¸˜es de texto ou opera¸˜es l´gicas. e co co co o Em Fortran 90/95, cada um dos cinco tipos intr´ ınsecos possui um valor inteiro n˜o negativo denominado a parˆmetro de esp´cie do tipo (em inglˆs, kind type parameter ). A norma padr˜o da linguagem determina a e e a que qualquer processador deve suportar pelo menos duas esp´cies para os tipos REAL e COMPLEX e pelo menos e uma esp´cie para os tipos INTEGER, CHARACTER e LOGICAL. e Um outro avan¸o do Fortran 90 sobre o predecessor Fortran 77 consiste na habilidade em definir novos c tipos de vari´veis, baseados nos tipos intr´ a ınsecos. Estas s˜o os chamados tipos derivados ou estruturas, os a quais consistem em combina¸˜es de partes compostas por tipos intr´ co ınsecos e/ou por outros tipos derivados, permitindo gerar objetos de complexidade crescente. Neste cap´ ıtulo, vamos inicialmente definir o uso b´sicos dos tipos intr´ a ınsecos de vari´veis, seguindo pela a defini¸˜o das esp´cies de vari´veis mais comuns, terminando por definir os tipos derivados. ca e a 3.1 Declara¸˜o de tipo de vari´vel ca a Como j´ foi colocado anteriormente, ´ uma boa praxe de programa¸˜o iniciar o setor de declara¸˜es de a e ca co vari´veis com a declara¸˜o a ca IMPLICIT NONE a qual impede a possibilidade de haver nomes de vari´veis n˜o definidos, os quais possuem o seu tipo a a impl´ ıcito, uma pr´tica corriqueira em Fortran 77. a A forma geral de uma declara¸˜o de tipo de vari´veis ´: ca a e <tipo>[([KIND=]<par^metro de esp´cie>)][,<lista de atributos>] :: a e <lista de entidades> onde <tipo> especifica o tipo de vari´vel, <par^metro de esp´cie> especifica a esp´cie da vari´vel, <lista a a e e a de atributos> ´ um dos seguintes: e PARAMETER PUBLIC PRIVATE POINTER TARGET ALLOCATABLE DIMENSION(<lista de extens~es>) o INTENT(<inout>) OPTIONAL SAVE EXTERNAL INTRINSIC e cada entidade ´ e <nome do objeto> [(lista de extens~es)] [*char-len] [= express~o de inicializa¸~o] o a ca ou <nome da fun¸~o> [*char-len] ca onde <nome do objeto> ´ o nome da vari´vel, seguindo a regra de nomes v´lidos definida no cap´ e a a ıtulo 2. Os objetos restantes, em particular <par^metro de esp´cie> e <lista de atributos>, ser˜o estudados a e a ao longo do desenvolvimento desta apostila. 13
  • 22.
    14 3.2. Vari´veis dotipo INTEGER a 3.2 Vari´veis do tipo INTEGER a Este tipo de vari´vel armazena apenas a parte inteira de um n´mero, exemplos de n´meros inteiros a u u v´lidos, tamb´m denominados literais s˜o: a e a 123, 89312, 5. As declara¸˜es b´sicas de nomes de vari´veis de tipo inteiro s˜o: co a a a Fortran 77: INTEGER <lista de nomes de vari´veis> a Fortran 90/95: INTEGER :: <lista de nomes de vari´veis> a O tipo de dados inteiro possui valores que pertencem ao conjunto dos n´meros inteiros. u Programa exemplo: program i n t e i r o i m p l i c i t none integer : : x ! O v a l o r d i g i t a d o n˜ o pode c o n t e r ponto ( . ) Caso i s t o a ! aco nte¸ a , v a i g e r a r um e r r o de e x e c u ¸ ˜ o no programa , c ca ! a b o r t a n d o o mesmo . read * , x print * , ”Valor l i d o : ” , x end program i n t e i r o 3.3 Vari´veis do tipo REAL a O tipo de vari´vel real ´ composto de quatro partes, assim dispostas: a e 1. uma parte inteira, com ou sem sinal, 2. um ponto decimal, 3. uma parte fracion´ria e a 4. um expoente, tamb´m com ou sem sinal. e Um ou ambos os itens 1 e 3 devem estar presentes. O item 4 ou est´ ausente ou consiste na letra E seguida a por um inteiro com ou sem sinal. Um ou ambos os itens 2 e 4 devem estar presentes. Exemplos de literais reais s˜o: a -10.6E-11 (representando −10, 6 × 10−11 ) 1. -0.1 1E-1 (representando 10−1 ou 0,1) 3.141592653 Os literais reais s˜o representa¸˜es do conjunto dos n´meros reais e o padr˜o da linguagem n˜o especifica a co u a a o intervalo de valores aceitos para o tipo real e nem o n´mero de d´ u ıgitos significativos na parte fracion´ria a (item 3) que o processador suporta, uma vez que estes valores dependem do tipo de processador em uso. Valores comuns s˜o: intervalo de n´meros entre 10−38 a 10+38 , com uma precis˜o de cerca de 7 (sete) d´ a u a ıgitos decimais. As declara¸˜es b´sicas do tipo real s˜o: co a a Fortran 77: REAL <lista de nomes de vari´veis> a Fortran 90/95: REAL :: <lista de nomes de vari´veis> a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 23.
    Cap´ ıtulo 3. Tiposde Vari´veis a 15 Programa exemplo: program v a r r e a l i m p l i c i t none r e a l : : a , b= 1 0 . 5 e−2 ! V a r i ´ v e l b ´ i n i c i a l i z a d a a 1 0 . 5 e −2. a e print * , ’ Valor de a : ’ read * , a print * , ’ Valor de a : ’ , a print * , ’ Valor de b : ’ , b end program v a r r e a l 3.4 Vari´veis do tipo COMPLEX a O Fortran, como uma linguagem destinada para c´lculos cient´ a ıficos ou em engenharia, tem a vantagem de possuir um terceiro tipo intr´ ınseco: n´meros complexos. Este tipo ´ concebido como um par de literais, u e os quais s˜o ou inteiros ou reais, separados por v´ a ırgula “,” e contidos entre parˆnteses “(“ e “)”. Os literais e complexos representam n´meros contidos no conjunto dos n´meros complexos, isto ´, n´meros do tipo u u e u √ e e a u z = x + iy, onde i = −1, x ´ a parte real e y ´ a parte imagin´ria do n´mero complexo z. Assim, um literal complexo deve ser escrito: (<parte real>,<parte imagin´ria>) a Exemplos de literais complexos s˜o: a (1.,3.2) (representando 1 + 3, 2i) (1.,.99E-2) (representando 1 + 0, 99 × 10−2 i) (1.0,-3.7) Uma outra grande vantagem do Fortran ´ que toda a ´lgebra de n´meros complexos j´ est´ implementada e a u a a a n´ de compilador. Assim, se for realizado o produto de dois n´meros complexos (x1,y1) e (x2,y2), o ıvel u resultado ser´ o literal complexo dado por (x1*x2 - y1*y2,x1*y2 + x2*y1). O mesmo acontecendo com a as outras opera¸˜es alg´bricas. co e As declara¸˜es b´sicas do tipo complexo s˜o: co a a Fortran 77: COMPLEX <lista de nomes de vari´veis> a Fortran 90/95: COMPLEX :: <lista de nomes de vari´veis> a Programa exemplo: program va r c o m pl ex a i m p l i c i t none complex : : a= (5 , −5) , b , c ! V a r i ´ v e l a ´ i n i c i a l i z a d a a (5 , −5). a e print * , ”Valor de b : ” ! O v a l o r de b d e v e s e r e n t r a d o como um l i t e r a l complexo . ! Exemplo : ( − 1 . 5 , 2 . 5 ) read * , b c= a * b print * , ”O v a l o r de c : ” , c ! V e r i f i q u e o r e s u l t a d o no p a p e l . end program va r c o m pl ex a 3.5 Vari´veis do tipo CHARACTER a O tipo padr˜o consiste em um conjunto de caracteres contidos em um par de ap´strofes ou aspas. Os a o caracteres n˜o est˜o restritos ao conjunto de caracteres padr˜o definidos na se¸˜o 2.4. Qualquer caractere a a a ca que possa ser representado pelo processador ´ aceito, exceto os caracteres de controle tais como o return. e Os ap´strofes ou aspas servem como delimitadores dos literais de caractere e n˜o s˜o considerados parte o a a integrante do conjunto. Ao contr´rio das normas usuais, um espa¸o em branco ´ diferente de dois ou mais. a c e Exemplos de literais de caractere: Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 24.
    16 3.6. Vari´veis dotipo LOGICAL a ’bom Dia’ ’bomDia’ ’BRASIL’ “Fortran 90” As declara¸˜es mais utilizadas para o tipo caractere s˜o: co a Fortran 77: character*<comprimento> <lista de nomes de vari´veis> a ou character <nome 1>*<comp. 1>, [<nome 2>*<comp. 2>, ...] Fortran 90/95: character(len=<comprimento>) :: <lista de nomes de vari´veis> a onde <comprimento> indica a quantidade de caracteres contidos nas vari´veis. Todas as vari´veis definidas a a por esta declara¸˜o tˆm o mesmo n´mero de caracteres. Se for informado um literal maior que <comprica e u mento>, este ser´ truncado; se for informado um literal menor que o declarado, o processador ir´ preencher a a o espa¸o restante ` direita com espa¸os em branco. c a c Programa exemplo: program l e c a r a c t e r e i m p l i c i t none character ( len =10) : : s t r r e a d print * , ”Entre com t e x t o ” : read ’ ( a ) ’ , s t r r e a d print * , ”Texto l i d o : ” , s t r r e a d end program l e c a r a c t e r e ´ E importante mencionar aqui a regra particular para o formato de fonte dos literais de caractere que s˜o a escritos em mais de uma linha: 1. Cada linha deve ser encerrada com o caractere “&” e n˜o pode ser seguida por coment´rio. a a 2. Cada linha de continua¸˜o deve ser precedida tamb´m pelo caractere “&”. ca e 3. Este par “&&” n˜o faz parte do literal. a 4. Quaisquer brancos seguindo um & em final de linha ou precedendo o mesmo caractere em in´ ıcio de linha n˜o s˜o partes do literal. a a 5. Todo o restante, incluindo brancos, fazem parte do literal. Como exemplo temos: car_longo = ’O tempo que eu hei sonhado & Quantos anos foi de vida! & Ah, quanto do meu passado & Foi s´ a vida mentida o & De um futuro imaginado! & & Aqui ` beira do rio a & Sossego sem ter raz~o. a & Este seu correr vazio & Figura, an^nimo e frio, o & A vida, vivida em v~o.’ a 3.6 & & & & & & & & & & & Vari´veis do tipo LOGICAL a O tipo l´gico define vari´veis l´gicas. Uma vari´vel l´gica s´ pode assumir dois valores, verdadeiro e o a o a o o falso. A representa¸˜o dos dois estado poss´ ca ıveis de uma vari´vel l´gica s˜o: a o a ˆ .TRUE. ⇒ Verdadeiro Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 25.
    Cap´ ıtulo 3. Tiposde Vari´veis a 17 ˆ .FALSE. ⇒Falso. As declara¸˜es do tipo l´gico s˜o: co o a Fortran 77: logical <lista de nomes de vari´veis> a Fortran 90/95: logical :: <lista de nomes de vari´veis> a Programa exemplo: program l o g i c o i m p l i c i t none l o g i c a l : : a= . t r u e . i f ( a ) then print * , ”A v a r i ´ v e l ´ v e r d a d e i r a . ” a e end i f end program l o g i c o 3.7 O conceito de esp´cie (kind) e Em Fortran, al´m dos 5 tipos de vari´veis definidos nas se¸˜es 3.2 a 3.6, ´ poss´ definir extens˜es a e a co e ıvel o um determinado tipo, cujas declara¸˜es dependem da vers˜o do Fortran utilizada e do processador no qual co a o programa ser´ executado. a 3.7.1 Fortran 77 Em Fortran 77 as extens˜es mais comuns e as correspondentes declara¸˜es s˜o: o co a ˆ vari´veis reais de precis˜o dupla: real*8 <lista de nomes de vari´veis> ou double precision a a a <lista de nomes de vari´veis>. a ˆ vari´veis reais de precis˜o estendida (ou qu´drupla): real*16 <lista de nomes de vari´veis>. a a a a ˆ vari´veis complexas de precis˜o dupla: complex*16 <lista de nomes de vari´veis>. a a a As diferen¸as entre estas extens˜es e os correspondentes tipos originais ser˜o ilustradas a seguir. c o a 3.7.2 Fortran 90/95 Em Fortran 90/95, cada um dos cinco tipos intr´ ınsecos, INTEGER, REAL, COMPLEX, CHARACTER e LOGICAL possui associado um valor inteiro n˜o negativo denominado parˆmetro de esp´cie do tipo (kind type a a e parameter). Por exigˆncia do padr˜o, um processador deve suportar, no m´ e a ınimo, duas esp´cies para os tipos e REAL e COMPLEX e uma esp´cie para os tipos INTEGER, CHARACTER e LOGICAL. e Os valores da esp´cie s˜o dependentes do processador e/ou do compilador empregado. Contudo, h´ e a a fun¸˜es intr´ co ınsecas fornecidas pelo compilador que verificam as precis˜es suportadas pelo processador e que o podem ser usadas para definir o valor do parˆmetro KIND, possibilitando assim a portabilidade do c´digo, a o isto ´, a possibilidade deste rodar em diferentes arquiteturas usando uma precis˜o m´ e a ınima especificada pelo programador. Para demonstrar como diferentes compiladores implementam e usam o parˆmetro de esp´cie, ser˜o cona e a siderados os compiladores Intel® Fortran Compiler for linux (vers˜o 9.1), gfortran e o compilador a F, todos gratu´ ıtos. 3.7.2.1 Compilador Intel® Fortran O compilador Intel® Fortran oferece os seguintes tipos intr´ ınsecos, juntamente com as respectivas declara¸˜es de tipo e esp´cie: co e Tipo Inteiro. H´ 04 parˆmetros de esp´cie para o tipo inteiro. a a e Declara¸˜o: INTEGER([KIND=]<n>) [::] <lista de nomes de vari´veis> ca a Sendo <n> das esp´cies 1, 2, 4 ou 8. Se o parˆmetro de esp´cie ´ explicitado, as vari´veis na <lista de e a e e a nomes de vari´veis> ser˜o da esp´cie escolhida. Em caso contr´rio, a esp´cie ser´ o inteiro padr˜o: a a e a e a a INTEGER(KIND=4); ou seja, a declara¸˜o INTEGER :: <lista de nomes de vari´veis> equivale a ca a INTEGER(KIND=4) :: <lista de nomes de vari´veis>. a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 26.
    18 3.7. O conceitode esp´cie (kind) e ® Fortran. Tabela 3.1: Tabela de armazenamento de vari´veis para o compilador Intel a Tipo e Esp´cie e INTEGER(KIND=1) INTEGER(KIND=2) INTEGER(KIND=4) INTEGER(KIND=8) REAL(KIND=4) REAL(KIND=8) REAL(KIND=16) Armazenamento (bytes) 1=8 bits 2 4 8 4 8 16 Tipo e Esp´cie e LOGICAL(KIND=1) LOGICAL(KIND=2) LOGICAL(KIND=4) LOGICAL(KIND=8) COMPLEX(KIND=4) COMPLEX(KIND=8) COMPLEX(KIND=16) Armazenamento (bytes) 1 2 4 8 8 16 32 ® Fortran. Programa 3.1: Testa distintas esp´cies suportadas pelo compilador Intel e program t e s t a k i n d i n t e l i m p l i c i t none integer , parameter : : dp= 8 , qp= 16 real : : r s i m p l e s r e a l ( kind= dp ) : : r d u p l a r e a l ( kind= qp ) : : r quad ! ! C a l c u l a a r a i z quadrada de 2 em d i v e r s a s p r e c i s ˜ e s . o r s i m p l e s= s q r t ( 2 . 0 ) ! Precis˜o simples a r d u p l a= s q r t ( 2 . 0 dp ) ! P r e c i s ˜ o d u p l a a r quad= s q r t ( 2 . 0 qp ) ! P r e c i s ˜ o q u ´ d r u p l a ou e s t e n d i d a . a a ! ! Imprime r e s u l t a d o s na t e l a . print * , r s i m p l e s print * , r d u p l a print * , r quad ! end program t e s t a k i n d i n t e l Tipo Real. H´ 03 parˆmetros de esp´cie para o tipo real. a a e Declara¸˜o: REAL([KIND=]<n>) [::] <lista de nomes de vari´veis> ca a Sendo <n> igual a 4, 8 ou 16. Caso o parˆmetro de esp´cie n˜o seja especificado, a esp´cie ser´ o real a e a e a padr˜o: REAL(KIND= 4). a Tipo Complexo. H´ 03 parˆmetros de esp´cie para o tipo complexo. a a e Declara¸˜o: COMPLEX([KIND=]<n>) [::] <lista de nomes de vari´veis> ca a Sendo <n> igual a 4, 8 ou 16. Caso o parˆmetro de esp´cie n˜o seja explicitado, a esp´cie ser´ o a e a e a complexo padr˜o: COMPLEX(KIND= 4). a Tipo L´gico. H´ 04 parˆmetros de esp´cie para o tipo l´gico. o a a e o Declara¸˜o: LOGICAL([KIND=]<n>) [::] <lista de nomes de vari´veis> ca a Sendo <n> igual a 1, 2, 4 ou 8. Tipo Caractere. H´ somente uma esp´cie do tipo caractere. a e Declara¸˜o: CHARACTER([KIND=1],[LEN=]<comprimento>) [::] ca <lista de nomes de vari´veis> a Cada esp´cie distinta ocupa um determinado espa¸o de mem´ria na CPU. Para o compilador Intel® e c o Fortran, o espa¸o ocupado est´ descrito na tabela 3.1. c a O programa 3.1 a seguir ilustra do uso e as diferen¸as de algumas op¸˜es de esp´cies de tipos de vari´veis. c co e a O mesmo programa tamb´m indica o uso de alguns atributos na declara¸˜o de vari´veis, tais como na e ca a declara¸˜o ca INTEGER, PARAMETER :: DP= 2 O atributo PARAMETER indica que as vari´veis declaradas nesta senten¸a devem se comportar como constantes a c matem´ticas, isto ´, n˜o podem ser alteradas no programa por nenhuma atribui¸˜o de vari´veis (ver cap´ a e a ca a ıtulo 4). Na mesma declara¸˜o, j´ est´ sendo inicializado o valor do parˆmetro DP, sendo este igual a 2. ca a a a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 27.
    Cap´ ıtulo 3. Tiposde Vari´veis a 19 Tabela 3.2: Tabela de armazenamento de vari´veis para o compilador gfortran da funda¸ao GNU. a c˜ Tipo e Esp´cie e INTEGER(KIND=1) INTEGER(KIND=2) INTEGER(KIND=4) INTEGER(KIND=8) INTEGER(KIND=16)1 REAL(KIND=4) REAL(KIND=8) REAL(KIND=10) Armazenamento (bytes) 1=8 bits 2 4 8 16 4 8 10 Tipo e Esp´cie e LOGICAL(KIND=1) LOGICAL(KIND=2) LOGICAL(KIND=4) LOGICAL(KIND=8) LOGICAL(KIND=16) COMPLEX(KIND=4) COMPLEX(KIND=8) COMPLEX(KIND=10) Armazenamento (bytes) 1 2 4 8 16 8 16 20 O mesmo exemplo tamb´m ilustra o uso da fun¸˜o impl´ e ca ıcita SQRT(X): R_SIMPLES= SQRT(2.0) a qual calculou a raiz quadrada da constante 2.0 e atribuiu o resultado ` vari´vel R_SIMPLES. a a 3.7.2.2 Compilador gfortran Gfortran ´ o compilador Fortran 95 da GNU (Funda¸˜o Gnu is Not Unix.), inicialmente desenvolvido e ca como alternativa ao compilador f95 distribu´ pelas vers˜es comerciais do Unix. Atualmente, o gfortran ıdo o ´ parte integrante da plataforma de desenvolvimento de software GCC (GNU Compiler Collection), que e ´ composta por compiladores de diversas linguagens distintas, tais como Fortran 95, C/C++, Java, Ada, e entre outros. O comando gfortran consiste simplesmente em um script que invoca o programa f951, o qual traduz o c´digo-fonte para assembler, invocando em seguida o linkador e as bibliotecas comuns do pacote o GCC. No gfortran, os parˆmetros de esp´cie s˜o determinados de forma semelhante ao compilador Intel® a e a Fortran, discutido na se¸˜o 3.7.2.1, ou seja, o parˆmetro indica o n´mero de bytes necess´rios para armaca a u a zenar cada vari´vel da respectiva esp´cie de tipo. As esp´cies suportadas pelo gfortran s˜o descritas na a e e a tabela 3.2. O programa testa_kind_gfortran a seguir (programa 3.2) ilustra o uso e as diferen¸as entre as diversas c esp´cies de tipos de dados no compilador gfortran. e 3.7.2.3 Compilador F Como exemplo do uso do parˆmetro de esp´cie, a tabela 3.3 ilustra os valores suportados pelo compilador a e F, conforme fornecidos pelo guia do usu´rio2 . H´ duas possibilidades para os n´meros da esp´cie: a a u e 1. o modo padr˜o de opera¸˜o, tamb´m denominado seq¨encial, o qual pode, por´m, ser especificado a ca e u e explicitamente no momento da compila¸˜o com a chave -kind=sequential; ca 2. o esquema de numera¸˜o bytes, o qual deve ser especificado no momento da compila¸˜o com a chave ca ca -kind=byte: alunos|fulano>F -kind=byte <nome programa>.f90 -o <nome programa> O exemplo a seguir, programa testa_kind_F, ilustra do uso e as diferen¸as de algumas op¸˜es de esp´cies c co e de tipos de vari´veis. a program t e s t a k i n d F i m p l i c i t none integer , parameter : : dp= 2 real : : r s i m p l e s r e a l ( kind= dp ) : : r d u p l a complex : : c s i m p l e s complex ( kind= dp ) : : c d u p l a ! ! C a l c u l a a r a i z quadrada de 2 em d i v e r s a s p r e c i s ˜ e s . o r s i m p l e s= s q r t ( 2 . 0 ) ! Precis˜o simples a 1 Em 2 The plataformas de 64 bits, tais como a fam´ de processadores Intel® Core— 2. ılia F Compiler and Tools (http://www.fortran.com/imagine1/ftools.pdf). Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 28.
    20 3.7. O conceitode esp´cie (kind) e Programa 3.2: Testa distintas esp´cies suportadas pelo compilador gfortran . e program t e s t a k i n d g f o r t r a n i m p l i c i t none integer , parameter : : i 1= 1 , i 2= 2 , i 4= 4 , i 8= 8 , i 1 6= 16 integer , parameter : : dp= 8 , qp= 10 integer ( kind= i 1 ) : : v i 1 integer ( kind= i 2 ) : : v i 2 integer ( kind= i 4 ) : : v i 4 integer ( kind= i 8 ) : : v i 8 integer ( kind= i 1 6 ) : : v i 1 6 real : : r s i m p l e s r e a l ( kind= dp ) : : r d u p l a r e a l ( kind= qp ) : : r quad complex : : c s i m p l e s complex ( kind= dp ) : : c d u p l a complex ( kind= qp ) : : c quad ! ! Mostra maiores numeros r e p r e s e n t a v e i s do t i p o i n t e i r o . v i 1= huge ( 1 i 1 ) v i 2= huge ( 1 i 2 ) v i 4= huge ( 1 i 4 ) v i 8= huge ( 1 i 8 ) v i 1 6= huge ( 1 i 1 6 ) print * , ’ E s p e c i e s I n t e i r a s : ’ print * , vi1 , vi2 , v i 4 print * , v i 8 print * , v i 1 6 ! Mostra maiores numeros r e p r e s e n t a v e i s do t i p o r e a l . r s i m p l e s= huge ( 1 . 0 ) ! Precisao simples r d u p l a= huge ( 1 . 0 dp ) ! P r e c i s a o d u p l a r quad= huge ( 1 . 0 qp ) ! P r e c i s a o e s t e n d i d a ! ! C a l c u l a a r a i z quadrada de ( 2 , 2 ) em d i v e r s a s p r e c i s o e s . c s i m p l e s= s q r t ( ( 2 . 0 , 2 . 0 ) ) c d u p l a= s q r t ( ( 2 . 0 dp , 2 . 0 dp ) ) c quad= s q r t ( ( 2 . 0 qp , 2 . 0 qp ) ) ! print * , print * , ’ E s p e c i e s R e a i s e Complexas : ’ print * , r s i m p l e s print * , r d u p l a print * , r quad print * , c s i m p l e s print * , c d u p l a print * , c quad ! end program t e s t a k i n d g f o r t r a n Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 29.
    Cap´ ıtulo 3. Tiposde Vari´veis a 21 Tabela 3.3: Valores de esp´cies (kind) de tipos de vari´veis suportados pelo compilador F. e a Tipo Real Real Real3 Complex Complex Complex Logical Logical Logical Logical Integer Integer Integer Integer Character N´ mero do Kind u (Sequencial) ¨ 1 2 3 1 2 3 1 2 3 4 1 2 3 4 1 N´ mero do Kind u (Byte) 4 8 16 4 8 16 1 2 4 8 1 2 4 8 1 r d u p l a= s q r t ( 2 . 0 ) ! Precis˜o dupla a ! ! N´ meros c o m p l ex o s : p a r t e r e a l : r a i z de 2 . u c s i m p l e s= cmplx ( s q r t ( 2 . 0 ) , s q r t ( 3 . 0 ) ) c d u p l a= cmplx ( s q r t ( 2 . 0 ) , s q r t ( 3 . 0 ) ) ! ! Imprime r e s u l t a d o s na t e l a . print * , r s i m p l e s print * , r d u p l a print * , c s i m p l e s print * , c d u p l a ! end program t e s t a k i n d F 3.7.2.4 Descri¸˜o ca Real precis˜o simples (padr˜o) a a Real precis˜o dupla a Real precis˜o qu´drupla a a Complexo precis˜o simples (padr˜o) a a Complexo precis˜o dupla a Complexo precis˜o qu´drupla a a L´gico 1 byte o L´gico 2 bytes o L´gico 4 bytes (padr˜o) o a L´gico 8 bytes o Inteiro 1 byte Inteiro 2 bytes Inteiro 4 bytes (padr˜o) a Inteiro 8 bytes Caractere, 1 byte por caractere P ar te i m a g i n a r i a : r a i z de 3 . ´ Literais de diferentes esp´cies e Para disting¨ir as esp´cies dos literais (ou constantes) dentre diferentes n´meros fornecidos ao compilador, u e u utiliza-se o sufixo _<k>, sendo <k> o parˆmetro da esp´cie do tipo: a e Literais inteiros. Constante inteiras, incluindo a esp´cie, s˜o especificadas por: e a [<s>]<nnn...>[_<k>] onde: <s> ´ um sinal (+ ou −); obrigat´rio se negativo, opcional se positivo. <nnn...> ´ um conjunto e o e de d´ ıgitos (0 a 9); quaisquer zeros no in´ s˜o ignorados. _<k> ´ um dos parˆmetros de esp´cie do ıcio a e a e tipo: 1, 2, 4 ou 8; esta op¸˜o explicita a esp´cie do tipo ` qual o literal pertence. ca e a Literais reais. Constantes reais s˜o especificadas de diferentes maneiras, dependendo se possuem ou n˜o a a parte exponencial. A regra b´sica para a especifica¸˜o de um literal real j´ foi definida na se¸˜o 3.3. a ca a ca Para explicitar a esp´cie do tipo real ` qual o literal pertence, deve-se incluir o sufixo _<k>, onde <k> e a ´ um dos parˆmetros de esp´cie do tipo: 4, 8 ou 16. Por exemplo: e a e 2.0_8: para indicar tipo real, esp´cie 8. e Literais complexos. A regra b´sica para a especifica¸˜o de um literal complexo j´ foi definida na se¸˜o a ca a ca 3.4. Para explicitar a esp´cie do tipo ` qual o literal pertence, deve-se incluir o sufixo _<k>, onde <k> e a ´ um dos parˆmetros de esp´cie do tipo: 4, 8 ou 16, em cada uma das partes real e imagin´ria do e a e a literal complexo. Por exemplo: (1.0_8,3.5345_8): para indicar tipo complexo, esp´cie 8. e Literais l´gicos. Uma constante l´gica pode tomar uma das seguintes formas: o o .TRUE.[_<k>] 3 Vari´veis a reais e complexas de precis˜o qu´drupla n˜o s˜o suportadas por todas as vers˜es do compilador F. a a a a o Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 30.
    22 3.7. O conceitode esp´cie (kind) e .FALSE.[_<k>] onde <k> ´ um dos parˆmetros de esp´cie do tipo: 1, 2, 4 ou 8. e a e 3.7.3 Fun¸˜es intr´ co ınsecas associadas ` esp´cie a e Embora as declara¸˜es de esp´cie do tipo possam variar para diferentes compiladores, o padr˜o da co e a linguagem estabelece um conjunto de fun¸˜es intr´ co ınsecas que facilitam a determina¸˜o e a declara¸˜o destas ca ca esp´cies de uma forma totalmente port´vel, isto ´, independente de compilador e/ou arquitetura. e a e As fun¸˜es intr´ co ınsecas descritas nesta e nas subsequentes se¸˜es ser˜o novamente abordadas no cap´ co a ıtulo 7, onde ser˜o apresentadas todas as rotinas intr´ a ınsecas fornecidas pelo padr˜o da linguagem Fortran 95. a 3.7.3.1 KIND(X) A fun¸˜o intr´ ca ınseca KIND(X), a qual tem como argumento uma vari´vel ou constante de qualquer tipo a intr´ ınseco, retorna o valor inteiro que identifica a esp´cie da vari´vel X. Por exemplo, e a program t e s f u n k i n d i m p l i c i t none integer : : i , j integer , parameter : : dp= 2 real : : y r e a l ( kind= dp ) : : x ! i= kind ( x ) ! i= 2 j= kind ( y ) ! Depende do s i s t e m a ( j =1 para c o m p i l a d o r F ) . print * , i print * , j end program t e s f u n k i n d Outros exemplos: KIND(0) KIND(0.0) KIND(.FALSE.) KIND(’A’) KIND(0.0D0) 3.7.3.2 ! ! ! ! ! ! ! ! ! ! Retorna a esp´cie padr~o do tipo inteiro. e a (Dependente do processador). Retorna a esp´cie padr~o do tipo real. e a (Depende do processador). Retorna a esp´cie padr~o do tipo l´gico. e a o (Depende do processador). Fornece a esp´cie padr~o de caractere. e a (Sempre igual a 1). Usualmente retorna a esp´cie do tipo real de precis~o dupla. e a (Pode n~o ser aceito por todos compiladores). a SELECTED_REAL_KIND(P,R) A fun¸˜o intr´ ca ınseca SELECTED_REAL_KIND(P,R) tem dois argumentos opcionais: P e R. A vari´vel P a especifica a precis˜o (n´mero de d´ a u ıgitos decimais) m´ ınima requerida e R especifica o intervalo de varia¸˜o ca m´ ınimo da parte exponencial da vari´vel. a A fun¸˜o SELECTED_REAL_KIND(P,R) retorna o valor da esp´cie que satisfaz, ou excede minimamente, os ca e requerimentos especificados por P e R. Se mais de uma esp´cie satisfaz estes requerimentos, o valor retornado e ´ aquele com a menor precis˜o decimal. Se a precis˜o requerida n˜o for dispon´ e a a a ıvel, a fun¸˜o retorna o valor ca -1; se o intervalo da exponencial n˜o for dispon´ a ıvel, a fun¸˜o retorna -2 e se nenhum dos requerimentos for ca dispon´ ıvel, o valor -3 ´ retornado. e Esta fun¸˜o, usada em conjunto com a declara¸˜o de esp´cie, garante uma completa portabilidade ao ca ca e programa, desde que o processador tenha dispon´ ıveis os recursos solicitados. O exemplo a seguir ilustra o uso desta fun¸˜o intr´ ca ınseca e outros recursos. program t e s s e l e c t e d integer , parameter : : i 1 0= s e l e c t e d r e a l k i n d ( 1 0 , 2 0 0 ) integer , parameter : : dp= 8 r e a l ( kind= i 1 0 ) : : a , b , c r e a l ( kind= dp ) : : d Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 31.
    Cap´ ıtulo 3. Tiposde Vari´veis a 23 print * , i 1 0 a= 2 . 0 i 1 0 b= s q r t ( 5 . 0 i 1 0 ) c= 3 . 0 e 1 0 i 1 0 , d= 1 . 0 e201 dp print * , a print * , b print * , c print * , d end program t e s s e l e c t e d Pode-se ver que a precis˜o requerida na vari´vel I10 ´ dispon´ na esp´cie correspondente ` precis˜o dupla a a e ıvel e a a de uma vari´vel real para os compiladores mencionados (ver, por exemplo, tabela 3.2). Um outro recurso a dispon´ ´ a possibilidade de especificar constantes de uma determinada esp´cie, como na atribui¸˜o ıvel e e ca A= 2.0_I10 A constante A foi explicitamente especificada como pertencente ` esp´cie I10 seguindo-se o valor num´rico a e e com um underscore e com o parˆmetro de esp´cie do tipo (I10). Deve-se notar tamb´m que a defini¸˜o da a e e ca esp´cie I10, seguida da declara¸˜o das vari´veis A, B e C como sendo desta esp´cie, determina o intervalo e ca a e m´ ınimo de varia¸˜o da parte exponencial destas vari´veis. Se o parˆmetro da esp´cie associada ` constante ca a a e a I10 for distinto do parˆmetro DP, a vari´vel D n˜o poderia ter sido declarada tamb´m da esp´cie I10, pois a a a e e a atribui¸˜o ca D= 1.0E201_I10 iria gerar uma mensagem de erro no momento da compila¸˜o, uma vez que a parte exponencial excede ca o intervalo definido para a esp´cie I10 (200). Contudo, para alguns compiladores, como o gfortran, a e compila¸˜o ir´ resultar em I10 = DP, tornando desnecess´ria uma das declara¸˜es acima. Este exemplo ca a a co demonstra a flexibilidade e a portabilidade propiciada pelo uso da fun¸˜o intr´ ca ınseca SELECTED_REAL_KIND. 3.7.3.3 SELECTED_INT_KIND(R) A fun¸˜o intr´ ca ınseca SELECTED_INT_KIND(R) ´ usada de maneira similar ` fun¸˜o SELECTED_REAL_KIND. e a ca Agora, a fun¸˜o tem um unico argumento R, o qual especifica o intervalo de n´meros inteiros requerido. ca ´ u Assim, SELECTED_INT_KIND(r) retorna o valor da esp´cie que representa, no m´ e ınimo, valores inteiros no intervalo −10r a +10r . Se mais de uma esp´cie satisfaz o requerimento, o valor retornado ´ aquele com o e e menor intervalo no expoente r. Se o intervalo n˜o for dispon´ a ıvel, o valor -1 ´ retornado. e O exemplo a seguir mostra a declara¸ao de um inteiro de uma maneira independente do sistema: c˜ INTEGER, PARAMETER :: I8= SELECTED_INT_KIND(8) INTEGER(KIND= I8) :: IA, IB, IC As vari´veis inteiras IA, IB e IC podem ter valores entre −108 a +108 no m´ a ınimo, se dispon´ ıvel pelo processador. 3.8 Tipos derivados Uma das maiores vantagens do Fortran 90/95 sobre seus antecessores est´ na disponibilidade ao proa gramador de definir seus pr´prios tipos de vari´veis. Estas s˜o os chamados tipos derivados, tamb´m o a a e freq¨entemente denominados de estruturas. u A forma geral da declara¸˜o de um tipo derivado ´: ca e TYPE [[,<acesso> ] ::] <nome do tipo > [PRIVATE] <declara¸~es de componentes > co END TYPE [<nome do tipo >] onde cada <declara¸˜o de componentes> tem a forma ca <tipo >[[, <atributos >] ::] <lista de componentes > Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 32.
    24 3.8. Tipos derivados ondeaqui o <tipo> pode ser um tipo de vari´vel intr´ a ınseca ou outro tipo derivado. A declara¸˜o de uma ca lista de vari´veis do tipo derivado <nome do tipo> ´ feita atrav´s da linha: a e e TYPE (<nome do tipo >) [::] <lista de nomes> Para tentar-se entender o uso de uma vari´vel de tipo derivado, vamos definir um novo tipo: PONTO, o qual a ser´ constru´ a partir de trˆs valores reais, representando os valores das coordenadas x, y e z do ponto no a ıdo e espa¸o cartesiano: c program d e f t i p o d e r i m p l i c i t none type : : ponto real : : x , y , z end type ponto ! type ( ponto ) : : c e n t r o , a p i c e ! a p i c e%x= 0 . 0 a p i c e%y= 1 . 0 a p i c e%z= 0 . 0 c e n t r o = ponto ( 0 . 0 , 0 . 0 , 0 . 0 ) ! print * , a p i c e print * , c e n t r o ! end program d e f t i p o d e r No exemplo acima, definiu-se o tipo derivado PONTO, composto por trˆs componentes reais x, y e z. Em e seguida, declarou-se duas vari´veis como sendo do tipo PONTO: CENTRO e APICE. A seguir, atribuiu-se os a valores para estas vari´veis. Finalmente, mandou-se imprimir na tela o valor das vari´veis. a a Como foi mostrado na atribui¸˜o APICE%X= 0.0, cada componente da vari´vel de tipo derivado pode ser ca a referenciada individualmente por meio do caractere seletor de componente, “%”. J´ a vari´vel CENTRO teve a a os valores de suas componentes definidos pelo construtor de estrutura: CENTRO= PONTO(0.0,0.0,0.0) ou seja, CENTRO%X= 0.0, CENTRO%Y= 0.0 e CENTRO%Z= 0.0. Estruturas definidas desta forma podem ser interessantes quando o programador quer classificar determinados objetos caracterizados por parˆmetros e/ou qualificadores representados por vari´veis de diferentes a a ´ tipos. E poss´ ıvel construirem-se estruturas progressivamente mais complicadas definindo-se novos tipos derivados que englobam aqueles previamente definidos. Por exemplo, TYPE :: RETA TYPE (PONTO) :: P1,P2 END TYPE RETA TYPE (RETA) :: DIAGONAL_PRINCIPAL ! DIAGONAL_PRINCIPAL%P1%X= 0.0 DIAGONAL_PRINCIPAL%P1%Y= 0.0 DIAGONAL_PRINCIPAL%P1%Z= 0.0 ! DIAGONAL_PRINCIPAL%P2= PONTO(1.0,1.0,1.0) Aqui foi definido o tipo RETA no espa¸o cartesiano, a qual ´ totalmente caracterizada por dois pontos, P1 e P2, c e os quais, por sua vez s˜o ternas de n´meros do tipo (x, y, z). Definiu-se ent˜o a vari´vel DIAGONAL_PRINCIPAL a u a a como sendo do tipo RETA e definiu-se os valores dos dois pontos no espa¸o P1 e P2 que caracterizam a diagonal c principal. Note o uso de dois seletores de componente para definir o valor da coordenada x do ponto P1 da DIAGONAL_PRINCIPAL. Note, por outro lado, o uso do construtor de estrutura para definir a posi¸˜o do ca ponto P2, como componente da diagonal principal. O exemplo a seguir, define o tipo ALUNO, caracterizado por NOME, CODIGO de matr´ ıcula, notas parciais N1, N2 e N3 e m´dia final MF. O programa lˆ as notas e calcula e imprime a m´dia final do aluno. e e e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 33.
    Cap´ ıtulo 3. Tiposde Vari´veis a 25 ! Dados a c e r c a de a l u n o s usando t i p o d e r i v a d o . program a l u n o s i m p l i c i t none type : : a l u n o character ( len= 2 0 ) : : nome integer : : c o d i g o r e a l : : n1 , n2 , n3 , mf end type a l u n o type ( a l u n o ) : : d i s c e n t e ! print * , ’Nome : ’ read ’ ( a ) ’ , d i s c e n t e%nome print * , ’ c o d i g o : ’ read * , d i s c e n t e%c o d i g o print * , ’ Notas : N1 , N2 , N3 : ’ read * , d i s c e n t e%n1 , d i s c e n t e%n2 , d i s c e n t e%n3 d i s c e n t e%mf= ( d i s c e n t e%n1 + d i s c e n t e%n2 + d i s c e n t e%n3 ) / 3 . 0 print * , ’ ’ print *,’−−−−−−−−−−−> ’ , d i s c e n t e%nome , ’ ( ’ , d i s c e n t e%c o d i g o , ’ ) <−−−−−−−−−−−’ print * , ’ Media f i n a l : ’ , d i s c e n t e%mf end program a l u n o s Em Fortran 95, tornou-se poss´ ıvel inicializar os valores dos componentes dos tipos derivados. O valor deve ser especificado quando o componente ´ declarado como parte da defini¸˜o do tipo. Se o componente e ca n˜o for um ponteiro, a inicializa¸˜o ´ feita de forma usual, com um sinal de igual seguido da express˜o de a ca e a inicializa¸˜o. Se o componente for um ponteiro, a unica inicializa¸˜o admitida ´ o s´ ca ´ ca e ımbolo de atribui¸˜o de ca um ponteiro (=>), seguida pela fun¸˜o intr´ ca ınseca NULL() (se¸˜o 7.16). Em ambos os casos os caracteres :: ca s˜o exigidos. a Uma inicializa¸˜o n˜o deve necessariamente se aplicar a todos os componentes de um tipo derivado. Um ca a exemplo v´lido seria: a TYPE :: ENTRY REAL :: VALOR= 2.0 INTEGER INDEX TYPE(ENTRY), POINTER :: NEXT => NULL() END TYPE ENTRY Dada uma declara¸˜o de matriz tal como ca TYPE(ENTRY), DIMENSION(100) :: MATRIZ os sub-objetos tais como MATRIZ(3)%VALOR ter˜o automaticamente o valor 2.0 e a seguinte opera¸˜o, que a ca usa uma fun¸˜o intr´ ca ınseca ASSOCIATED(MATRIX(3)%NEXT) vai retornar o valor .FALSE. (ver se¸˜o 7.3). ca Se as declara¸˜es de tipos derivados estiverem aninhadas, as inicializa¸˜es associadas a componentes s˜o co co a reconhecidas em todos os n´ ıveis. Assim, TYPE :: NODO INTEGER CONTA TYPE(ENTRY) ELEMENTO END TYPE NODO TYPE(NODO) N ocasiona que o componente N%ELEMENTO%VALOR ter´ automaticamente o valor 2.0. a Os componentes do tipo derivado continuam podendo ser inicializados em declara¸˜es de vari´veis do co a tipo, tais como TYPE(ENTRY), DIMENSION(100) :: MATRIZ= ENTRY(HUGE(0.0), HUGE(0), NULL()) em cuja situa¸˜o a inicializa¸˜o inicial ´ ignorada. ca ca e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 34.
    26 Autor: Rudi Gaelzer– IFM/UFPel 3.8. Tipos derivados Impresso: 12 de abril de 2010
  • 35.
    Cap´ ıtulo 4 Express˜es eAtribui¸˜es Escalares o co Em uma express˜o, o programa descreve as opera¸˜es que devem ser executadas pelo computador. O a co resultado desta express˜o pode ent˜o ser atribu´ a uma vari´vel. H´ diferentes conjuntos de regras para a a ıdo a a express˜es e atribui¸˜es, dependendo se as vari´veis em quest˜o s˜o num´ricas, l´gicas, caracteres ou de tipo o co a a a e o derivado; e tamb´m se as express˜es s˜o escalares ou matriciais. e o a Cada um dos conjunto de regras para express˜es escalares ser´ agora discutido. o a 4.1 Regras b´sicas a Uma express˜o em Fortran 90/95 ´ formada de operandos e operadores, combinados de tal forma que a e estes seguem as regras de sintaxe. Os operandos podem ser constantes, vari´veis ou fun¸˜es e uma express˜o, a co a por si mesma, tamb´m pode ser usada como operando. e Uma express˜o simples envolvendo um operador unit´rio ou mon´dico tem a seguinte forma: a a a operador operando um exemplo sendo -Y J´ uma express˜o simples envolvendo um operador bin´rio (ou di´dico) tem a forma: a a a a operando operador operando um exemplo sendo X + Y Uma express˜o mais complicada seria a operando operador operando operador operando onde operandos consecutivos s˜o separados por um unico operador. Cada operando deve ter valor definido e a ´ o resultados da express˜o deve ser matematicamente definido; por exemplo, divis˜o por zero n˜o ´ permitido. a a a e A sintaxe do Fortran estabelece que as partes de express˜es sem parˆnteses sejam desenvolvidas da o e esquerda para a direita para operadores de igual precedˆncia, com a exce¸˜o do operador “**” (ver se¸˜o e ca ca 4.2). Caso seja necess´rio desenvolver parte de uma express˜o, ou sub-express˜o, antes de outra, parˆnteses a a a e podem ser usados para indicar qual sub-express˜o deve ser desenvolvida primeiramente. Na express˜o a a operando operador (operando operador operando) a sub-express˜o entre parˆnteses ser´ desenvolvida primeiro e o resultado usado como um operando para o a e a primeiro operador, quando ent˜o a express˜o completa ser´ desenvolvida usando a norma padr˜o, ou seja, a a a a da esquerda para a direita. Se uma express˜o ou sub-express˜o n˜o ´ contida entre parˆnteses, ´ permitido ao processador desenvolver a a a e e e uma express˜o equivalente, a qual ´ uma express˜o que resultar´ no mesmo valor, exceto por erros de a e a a arredondamento num´rico. As duas opera¸˜es a seguir s˜o, em princ´ e co a ıpio, equivalentes: 27
  • 36.
    28 4.2. Express˜es num´ricasescalares o e A/B/C ou A/(B*C) Poss´ ıveis diferen¸as nos resultados das opera¸˜es acima consistem em diferentes erros de arredondamento c co e/ou tempo de processamento, caso o processador consiga multiplicar mais rapidamente que dividir. Se dois operadores seguem-se imediatamente, como em operando operador operador operando a unica interpreta¸˜o poss´ ´ que o segundo operador ´ mon´dico. Portanto, a sintaxe pro´ que um ´ ca ıvel e e a ıbe operador bin´rio siga outro operador, somente um operador unit´rio. a a 4.2 Express˜es num´ricas escalares o e Uma express˜o num´rica ´ aquela cujos operandos s˜o um dos trˆs tipos num´ricos: inteiro, real e a e e a e e complexo. A tabela 4.1 apresenta os operadores, em ordem de precedˆncia, e o seu respectivo significado. e Estes operadores s˜o conhecidos como operadores num´ricos intr´ a e ınsecos. Na tabela 4.1, as linhas horizontais confinam os operadores de igual precedˆncia e a ordem de precedˆncia e e ´ dada de cima para baixo. O operador de potencia¸˜o “**” ´ o de maior precedˆncia; os operadores de e ca e e multiplica¸˜o “*” e divis˜o “/” tˆm a mesma precedˆncia entre si e possuem precedˆncia sobre os operadores ca a e e e de adi¸˜o “+” e subtra¸˜o “-”, os quais tˆm a mesma precedˆncia entre si. ca ca e e Na ausˆncia de parˆnteses, ou dentro destes, no caso de sub-express˜es, a opera¸˜o com a maior precee e o ca dˆncia ´ o c´lculo das fun¸˜es, seguidos das exponencia¸˜es que ser˜o realizadas antes de multiplica¸˜es ou e e a co co a co divis˜es e estas, por sua vez, antes de adi¸˜es ou subtra¸˜es. o co co Uma express˜o num´rica especifica uma computa¸˜o usando constantes, vari´veis ou fun¸˜es, seguindo a e ca a co o seguinte conjunto de regras: ˆ Os operadores de subtra¸˜o “-” e de adi¸˜o “+” podem ser usados como operadores unit´rios, como em ca ca a -VELOCIDADE ˆ Uma vez que n˜o ´ permitido na nota¸˜o matem´tica ordin´ria, uma subtra¸˜o ou adi¸˜o unit´ria a e ca a a ca ca a n˜o pode seguir imediatamente ap´s outro operador. Quando isto ´ necess´rio, deve-se fazer uso de a o e a parˆnteses. Por exemplo, as opera¸˜es matem´ticas a seguir: e co a x−y deve ser digitada: X**(-Y); x(−y) deve ser digitada : X*(-Y). Como j´ foi mencionado na se¸˜o 4.1, um operador bin´rio tamb´m n˜o pode seguir outro operador. a ca a e a ˆ Os parˆnteses devem indicar os agrupamentos, como se escreve em uma express˜o matem´tica. Os e a a parˆnteses indicam que as opera¸˜es dentro deles devem ser executadas prioritariamente: e co 3 (a + b) (x + y)2 + w2 deve ser digitada: (A+B)*((X+Y)**2 + W**2)**3 ou (A+B)*(((X+Y)**2 + W**2)**3) ˆ Os parˆnteses n˜o podem ser usados para indicar multiplica¸˜o, sendo sempre necess´rio o uso do e a ca a operador “*”. Qualquer express˜o pode ser envolvida por parˆnteses exteriores, que n˜o a afetam: a e a X + Y ´ equivalente a ((X) + Y) ou equivalente a ((X + Y)) e Contudo, o n´mero de parˆnteses ` esquerda deve sempre ser igual ao n´mero de parˆnteses ` direita. u e a u e a ˆ Nenhum operador pode ser deixado impl´ ıcito: 5*T ou T*5: correto 5T, 5(T) ou T5: incorreto. ˆ De acordo com a tabela 4.1, a qual fornece o ordenamento dos operadores, a opera¸˜o matem´tica ca a 2x2 + y pode ser expressa de, no m´ ınimo, duas maneiras equivalentes: 2*X**2 + Y ou 2*(X**2) + Y ou ainda (2*(x**2)) + Y. Tabela 4.1: Operadores num´ricos escalares e Operador ** * / + Autor: Rudi Gaelzer – IFM/UFPel Opera¸˜o ca Potencia¸˜o ca Multiplica¸˜o ca Divis˜o a Adi¸˜o ca Subtra¸˜o ca Impresso: 12 de abril de 2010
  • 37.
    Cap´ ıtulo 4. Express˜ese Atribui¸˜es Escalares o co Tabela 4.2: Tipos de resultados de A .op. Tipo de A Tipo de B I I I R R R C C C I R C I R C I R C Tipo de A Tipo de B I I I R R R C C C I R C I R C I R C Valor de A usado na .op. A REAL(A,KIND(B)) CMPLX(A,0,KIND(B)) A A CMPLX(A,0,KIND(B) A A A 29 B, onde .op. ´ +, -, * ou /. e Valor de B usado na .op. B B B REAL(B,KIND(A) B B CMPLX(B,0,KIND(A) CMPLX(B,0,KIND(A) B Tipo de resultado I R C R R C C C C Tabela 4.3: Tipos de resultados de A**B. Valor de A usado na .op. A REAL(A,KIND(B)) CMPLX(A,0,KIND(B)) A A CMPLX(A,0,KIND(B) A A A Valor de B usado na .op. B B B B B B B CMPLX(B,0,KIND(A) B Tipo de resultado I R C R R C C C C ˆ A exce¸˜o ` regra esquerda-para-direita para operadores de igual precedˆncia ocorre para a potencia¸˜o ca a e ca “**”. A express˜o a A**B**C ´ v´lida e ´ desenvolvida da direita para a esquerda como e a e A**(B**C). ˆ Para dados inteiros, o resultado de qualquer divis˜o ser´ truncado para zero, isto ´, para o valor inteiro a a e cuja magnitude ´ igual ou logo inferior ` magnitude do valor exato. Assim, o resultado de: e a 6/3 ´ 2 e 8/3 ´ 2 e -8/3 ´ -2. e Este fato deve sempre ser levado em conta quando divis˜es de inteiros est˜o sendo realizadas. Por isto, o a o valor de 2**3 ´ 8, enquanto que o valor de 2**(-3) ´ 0. e e ˆ A regra padr˜o do Fortran 90 tamb´m permite que uma express˜o num´rica contenha operandos a e a e num´ricos de diferentes tipos ou esp´cies. Esta ´ uma express˜o de modo misto. Exceto quando e e e a elevando um valor real ou complexo a uma potˆncia inteira, o objeto do tipo mais fraco (ou mais e simples) de vari´vel dos dois tipos envolvidos em uma express˜o ser´ convertido, ou coagido, para o a a a tipo mais forte. O resultado ser´ tamb´m do tipo mais forte. Por exemplo, se A ´ real e I ´ inteiro, a a e e e express˜o A*I tem, inicialmente, I sendo convertido a real, antes que a multiplica¸˜o seja efetuada e o a ca resultado da mesma ´ do tipo real. As tabelas 4.2 e 4.3 ilustram os resultados de diferentes opera¸˜es e co num´ricas escalares. e ˆ Com rela¸˜o ` ultima opera¸˜o mencionada na tabela 4.3, no case de um valor complexo ser eleca a ´ ca vado a uma potˆncia tamb´m complexa, o resultado corresponder´ ao valor principal, isto ´, ab = e e a e exp(b(log |a| + i arg a)), com −π < arg a < π. 4.3 Atribui¸oes num´ricas escalares c˜ e A forma geral de uma atribui¸˜o num´rica escalar ´ ca e e <nome vari´vel> = <express~o> a a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 38.
    30 4.4. Operadores relacionais onde<nome vari´vel> ´ o nome de uma vari´vel num´rica escalar e <express~o> ´ uma express˜o num´rica. a e a e a e a e Se <express~o> n˜o ´ do mesmo tipo ou esp´cie da <vari´vel>, a primeira ser´ convertida ao tipo e esp´cie a a e e a a e da ultima antes que a atribui¸˜o seja realizada, de acordo com as regras dadas na tabela 4.4. ´ ca Deve-se notar que se o tipo da vari´vel for inteiro mas a express˜o n˜o, ent˜o a atribui¸˜o ir´ resultar a a a a ca a em perda de precis˜o, exceto se o resultado for exatamente inteiro. Da mesma forma, atribuindo uma a express˜o real a uma vari´vel real de uma esp´cie com precis˜o menor tamb´m causar´ perda de precis˜o. a a e a e a a Similarmente, a atribui¸˜o de uma express˜o complexa a uma vari´vel n˜o complexa resultar´, no m´ ca a a a a ınimo, na perda da parte imagin´ria. Por exemplo, os valores de I e A ap´s as atribui¸˜es a o co I= 7.3 A= (4.01935, 2.12372) ! I do tipo inteiro. ! A do tipo real. s˜o, respectivamente, 7 e 4.01935. a 4.4 Operadores relacionais A tabela 4.5 apresenta os operadores relacionais escalares, utilizados em opera¸˜es que envolvem a co compara¸˜o entre duas vari´veis ou express˜es. Na coluna 1 da tabela, ´ apresentado o significado do ca a o e operador, na coluna 2 a sua forma escrita com caracteres alfanum´ricos e, na coluna 3, a sua forma escrita e com caracteres especiais. Fortran 77: somente a forma apresentada na coluna 2 ´ v´lida. e a Fortran 90/95: qualquer uma das duas formas ´ v´lida; por´m, a forma apresentada na coluna 3 ´ a mais e a e e moderna e recomend´vel, sendo a outra considerada obsoleta. a Se uma ou ambas as express˜es forem complexas, somente os operadores == e /= (ou .EQ. e .NE.) s˜o o a dispon´ ıveis. O resultado de uma compara¸˜o deste tipo tem como resultado um dos dois valores l´gicos poss´ ca o ıveis em uma ´lgebra booleana: .TRUE. e .FALSE. e este tipo de teste ´ de crucial importˆncia no controle do fluxo a e a do programa. Exemplos de express˜es relacionais s˜o dados abaixo, sendo I e J do tipo inteiro, A e B do o a tipo real e CHAR1 do tipo caractere padr˜o: a I .LT. 0 A < B A + B > I - J CHAR1 == ’Z’ ! ! ! ! express~o a express~o a express~o a express~o a relacional relacional relacional relacional inteira real de modo misto de caractere Os operadores num´ricos tˆm precedˆncia sobre os operadores relacionais. Assim, as express˜es num´ricas, e e e o e caso existam, s˜o desenvolvidas antes da compara¸˜o com os operadores relacionais. No terceiro exemplo a ca acima, como as express˜es envolvem dois tipos distintos, cada express˜o ´ desenvolvida separadamente e o a e ent˜o ambas s˜o convertidas ao tipo e esp´cie da soma dos resultados de cada express˜o, de acordo com a a a e a tabela 4.2, antes que a compara¸˜o seja feita. Portanto, no exemplo, o resultado de (I - J) ser´ convertido ca a a real. Para compara¸˜es de caracteres, as esp´cies devem ser as mesmas e as as letras (ou n´meros ou caracteres co e u especiais) s˜o comparados da esquerda para a direita at´ que uma diferen¸a seja encontrada ou ambos os a e c caracteres sejam idˆnticos. Se os comprimentos diferem, a vari´vel mais curta ´ suposta preenchida por e a e brancos ` direita. a 4.5 Express˜es e atribui¸oes l´gicas escalares o c˜ o Constantes, vari´veis e fun¸˜es l´gicas podem aparecer como operandos em express˜es l´gicas. Os a co o o o operadores l´gicos, em ordem decrescente de precedˆncia, s˜o: o e a Tabela 4.4: Convers˜o num´rica para o comando de atribui¸ao <nome vari´vel> = <express~o>. a e c˜ a a Tipo de <vari´vel> a I R C Autor: Rudi Gaelzer – IFM/UFPel Valor atribu´ ıdo INT(<express~o>,KIND(<nome vari´vel>) a a REAL(<express~o, KIND(<nome vari´vel>) a a CMPLX(<express~o>,KIND(<nome vari´vel>) a a Impresso: 12 de abril de 2010
  • 39.
    Cap´ ıtulo 4. Express˜ese Atribui¸˜es Escalares o co 31 Tabela 4.5: Operadores relacionais em Fortran 90/95 Significado Maior que Menor que Igual a Maior ou igual Menor ou igual Diferente de Forma obsoleta .GT. .LT. .EQ. .GE. .LE. .NE. Forma moderna > < == >= <= /= Operador unit´rio: a .NOT. (nega¸˜o l´gica) ca o Operadores bin´rios: a .AND. (intersec¸˜o l´gica, E l´gico) ca o o .OR. (uni˜o l´gica, OU l´gico) a o o .EQV. (equivalˆncia l´gica) e o .NEQV. (n˜o-equivalˆncia l´gica). a e o Dada ent˜o uma declara¸˜o de vari´veis l´gicas do tipo a ca a o LOGICAL :: I,J,K,L ent˜o as seguintes express˜es l´gicas s˜o v´lidas: a o o a a .NOT. J J .AND. K I .OR. L .AND. .NOT. J (.NOT. K .AND. J .NEQV. .NOT. L) .OR. I Na primeira express˜o o .NOT. ´ usado como operador unit´rio. Na terceira express˜o, as regras de precedˆna e a a e cia implicam em que a sub-express˜o L .AND. .NOT. J seja desenvolvida primeiro, e o resultado combinado a com I. Na ultima express˜o, as duas sub-express˜es .NOT. K .AND. J e .NOT. L ser˜o desenvolvidas e ´ a o a comparadas para testar n˜o-equivalˆncia; o resultado da compara¸˜o ser´ combinado com I. a e ca a O resultado de qualquer express˜o l´gica ´ .TRUE. ou .FALSE., e este valor pode ent˜o ser atribu´ a a o e a ıdo uma vari´vel l´gica, tal como no exemplo abaixo: a o FLAG= (.NOT. K .EQV. L) .OR. J O resultado de uma express˜o l´gica envolvendo duas vari´veis l´gicas A e B, por exemplo, pode ser inferido a o a o facilmente atrav´s da consulta `s Tabelas-Verdade 4.6 – 4.8. e a Uma vari´vel l´gica pode ter um valor pr´-determinado por uma atribui¸˜o no corpo de comandos do a o e ca programa: FLAG= .TRUE. ou no corpo de declara¸˜es de vari´veis: co a LOGICAL :: FLAG= .FALSE., BANNER= .TRUE., POLE Nos exemplos acima, todos os operando e resultados foram do tipo l´gico. Nenhum outro tipo de vari´vel o a pode participar de uma opera¸˜o l´gica intr´ ca o ınseca, ou atribui¸˜o. ca Os resultados de diversas express˜es relacionais podem ser combinados em uma express˜o l´gica, seguida o a o de atribui¸˜o, como no caso: ca Tabela 4.6: Tabela-Verdade .NOT. A T F .NOT. A F T Autor: Rudi Gaelzer – IFM/UFPel Tabela 4.7: Tabela-Verdade .AND. A T T F F B T F T F A .AND. B T F F F Tabela 4.8: Tabela-Verdade .OR. A T T F F B T F T F A .OR. B T T T F Impresso: 12 de abril de 2010
  • 40.
    32 4.6. Express˜es eatribui¸˜es de caracteres escalares o co REAL :: A, B, X, Y LOGICAL :: COND . . . COND= A > B .OR. X < 0.0 .AND. Y > 1.0 onde os operadores relacionais tˆm precedˆncia sobre os operadores l´gicos. Contudo, o uso mais freq¨ente de e e o u express˜es que envolvem operadores num´ricos, relacionais e l´gicos ocorre em testes destinados a determinar o e o o fluxo do programa, como no caso do comando IF, exemplificado abaixo e que ser´ discutido em mais a detalhes no cap´ ıtulo 5: REAL :: A= 0.0, B= 1.0, X= 2.5, Y= 5.0 . . . IF((A < B) .AND. (X - Y > 0.0))THEN . . . IF((B**2 < 10.0) .OR. (A > 0.0))THEN . . . No primeiro teste IF acima, o resultado, levando em conta a hierarquia das precedˆncias nas diferentes e opera¸˜es, ´ .FALSE. e os comandos contidos ap´s a cl´usula THEN n˜o ser˜o executados. J´ no segundo co e o a a a a exemplo, o resultado ´ .TRUE. e os comandos ap´s o THEN ser˜o executados. e o a 4.6 Express˜es e atribui¸oes de caracteres escalares o c˜ O unico operador intr´ ´ ınseco para express˜es de caracteres ´ o operador de concatena¸˜o “//”, o qual tem o e ca o efeito de combinar dois operandos de caracteres em um unico caractere resultante, de extens˜o igual ` ´ a a soma das extens˜es dos operandos originais. Por exemplo, o resultado da concatena¸˜o das constantes de o ca caractere ’AB’ e ’CD’, escrita como ’AB’//’CD’ ´ a constante ’ABCD’. e Uma outra opera¸˜o poss´ ca ıvel com vari´veis de caracteres ´ a extra¸˜o de “peda¸os” (substrings) das a e ca c vari´veis, os quais consistem em um determinado grupo de caracteres contidos na vari´vel. a a Substrings de caracteres. Consideremos a seguinte declara¸˜o da vari´vel de caractere HINO, a qual tem o comprimento igual a 236 ca a caracteres e cujo valor ´ atribu´ no momento da declara¸˜o: e ıdo ca CHARACTER(LEN=236):: HINO = & ’Qual aurora precursora, do farol da divindade, &Foi o 20 de setembro, o precursor da liberdade. &Mostremos valor, const^ncia, nesta ´mpia, injusta guerra. a ı &Sirvam nossas fa¸anhas, de modelo ` toda Terra (...) c a & & & ’ Pode-se isolar qualquer parte da vari´vel HINO usando-se a nota¸˜o de substring a ca HINO(I:J) onde I e J s˜o vari´veis inteiras, as quais localizam explicitamente os caracteres de I a J em HINO. Os dois a a pontos “:” s˜o usados para separar os dois ´ a ındices da substring e s˜o sempre obrigat´rios, mesmo que se a o queira isolar somente um caractere da vari´vel. Alguns exemplos de substrings da vari´vel HINO s˜o: a a a HINO(6:11) HINO(60:79) HINO(140:140) !Correspondente a ’aurora’ !Correspondente a ’Foi o 20 de setembro’ !Correspondente a ’^’ a As constantes de caracteres resultantes das substrings podem ser ent˜o atribu´ a ıdas a outras vari´veis de a caracteres. H´ valores padr˜o para os ´ a a ındices das substrings. Se o ´ ındice inferior ´ omitido, o valor 1 ´ e e assumido; se o valor superior ´ omitido, um valor correspondente ao comprimento da vari´vel ´ assumido. e a e Assim, Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 41.
    Cap´ ıtulo 4. Express˜ese Atribui¸˜es Escalares o co 33 HINO(:50) ´ equivalente a HINO(1:50) e HINO(100:) ´ equivalente a HINO(100:236). e Pode-se tamb´m fazer concatena¸˜es com substrings: e co HINO(6:11)//HINO(69:79) gera a constante ’aurora de setembro’ TROCADILHO= HINO(153:157)//’s’//HINO(191:199) atribui ` TROCADILHO o valor ’´mpias a ı fa¸anhas’. c Se o resultado da express˜o no lado direito for menor que o tamanho da vari´vel, o valor ´ atribu´ ` a a e ıdo a vari´vel come¸ando-se pela esquerda e o espa¸o restante ´ preenchido por brancos: a c c e CHARACTER(LEN= 10) :: PARTE1, PARTE2 PARTE1= HINO(178:183) ! Resulta em PARTE1= ’Sirvam ’ Ao passo que se o resultado da express˜o foi maior que o tamanho da vari´vel, esta ser´ preenchida coma a a pletamente e o restante do valor ser´ truncado: a PARTE2= HINO(:22) ! Resulta em PARTE2= ’Qual auror’ Finalmente, ´ poss´ substituir parte de uma vari´vel de caractere usando-se uma substring da mesma em e ıvel a uma atribui¸ao: c˜ HINO(50:113)= ’AAAAAAAAAAARRRRRRRRRRRRRGGGGGGGGGGGGGHHHHHHHHHHHH!!!!!$%#$%%&%#%$#’ de tal forma que resulta, HINO = ’Qual aurora precursora, do farol da divindade, AAAAAAAAAAA& &RRRRRRRRRRRRRGGGGGGGGGGGGGHHHHHHHHHHHH!!!!!$%#$%%&%#%$# & &Mostremos valor, const^ncia, nesta ´mpia, injusta guerra. & a ı &Sirvam nossas fa¸anhas, de modelo ` toda Terra (...) c a ’ Os lados esquerdo e direito de uma atribui¸˜o podem ser sobrepor. Neste caso, ser˜o sempre os valores ca a antigos os usados no lado direito da express˜o. Por exemplo, a PARTE2(3:5) = PARTE2(1:3) resulta em PARTE2= ’QuQuaauror’. Compara¸˜es e uso de operadores relacionais com vari´veis/constantes de caracteres s˜o poss´ co a a ıveis entre caracteres unicos, inclusive com os operadores > e <. Neste caso, n˜o se trata de testar qual caractere ´ maior ´ a e ou menor que outro. Em um sistema computacional, caracteres possuem uma propriedade denominada seq¨ˆncia de intercala¸ao,1 a qual ordena o armazenamento destes caracteres pelo sistema. ue c˜ O Fortran 90/95 determina que a seq¨ˆncia de intercala¸˜o para qualquer arquitetura deve satisfazer as ue ca seguintes condi¸˜es: co ˆ A precede (´ menor) que B, que precede C ... precede Y, que precede Z. e ˆ 0 precede 1, que precede 2 ... precede 8, que precede 9. ˆ Espa¸o em branco precede A e Z precede 0; ou branco precede 0 e 9 precede A. c Se letras min´sculas s˜o dispon´ u a ıveis, ent˜o a ˆ a precede b, que precede c, ... precede y, que precede z. ˆ Espa¸o em branco precede a e z precede 0; ou branco precede 0 e 9 precede a. c Assim, n˜o h´ regra que estabele¸a que os n´meros devem preceder ou n˜o as letras, nem tampouco h´ a a c u a a regra de precedˆncia para caracteres especiais. e De acordo com estas regras, as express˜es relacionais o ’A’ < ’B’ ’0’ < ’1’ 1 Collating sequence. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 42.
    34 4.6. Express˜es eatribui¸˜es de caracteres escalares o co Tabela 4.9: Tabela de c´digos ASCII de 7 bits. o Dec 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Hex 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F Char NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US (null) (start of heading) (start of text) (end of text) (end of transmission) (enquiry) (acknowledge) (bell) (backspace) (horizontal tab) (line feed, new line) (vertical tab) (form feed, new page) (carriage return) (shift out) (shift in) (data link escape) (device control 1) (device control 2) (device control 3) (device control 4) (negative acknowledge) (synchronous idle) (end of trans. block) (cancel) (end of medium) (substitute) (escape) (file separator) (group separator) (record separator) (unit separator) Dec 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 Hex 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F Char Space ! “ # $ % & ’ ( ) * + , . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? Dec 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 Hex 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F Char @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ˆ Dec 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 Hex 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F fornecem ambas o resultado T (true). Fortran 90/95 fornece acesso tamb´m ` seq¨ˆncia de intercala¸˜o original da tabela ASCII2 atrav´s de e a ue ca e fun¸˜es intr´ co ınsecas (se¸˜o 7.6.1). ASCII consiste em uma padroniza¸˜o para um encodeamento de caracteres3 ca ca de 7 bits (originalmente), baseado no alfabeto inglˆs. C´digos ASCII representam textos em computadores, e o equipamentos de comunica¸˜o e outros dispositivos eletrˆnicos que trabalham com texto. A tabela 4.9 mosca o tra os caracteres ASCII originais, juntamente com os seus identificadores nos sistemas num´ricos decimal, e hexadecimal e octal, bem como o c´digo html correspondente. Os primeiros 32 (0 – 31) caracteres mais o o caractere 127 s˜o caracteres de controle, destinados ` comunica¸˜o com perif´ricos; estes n˜o geram caraca a ca e a teres que podem ser impressos. J´ os caracteres restantes (32 – 126) comp˜e-se de caracteres alfanum´ricos a o e mais caracteres especiais. 2 American 3 Character Standard Code for Information Interchange (ASCII). encoding. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010 Char ‘ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ˜ DEL
  • 43.
    Cap´ ıtulo 5 Comandos eConstrutos de Controle de Fluxo Nos cap´ ıtulos anteriores foi descrito como comandos de atribui¸˜o devem ser escritos e como estes podem ca ser ordenados um ap´s o outro para formar uma seq¨ˆncia de c´digo, a qual ´ executada passo-a-passo. Na o ue o e maior parte das computa¸˜es, contudo, esta seq¨ˆncia simples de comandos ´, por si s´, inadequada para a co ue e o formula¸˜o do problema. Por exemplo, podemos desejar seguir um de dois poss´ ca ıveis caminhos em uma se¸˜o ca de c´digo, dependendo se um valor calculado ´ positivo ou negativo. Como outro exemplo, podemos querer o e somar 1000 elementos de uma matriz; escrever 1000 adi¸˜es e atribui¸˜es ´ uma tarefa claramente tediosa co co e e n˜o muito eficiente. Ao inv´s, a habilidade de realizar uma itera¸˜o sobre uma unica adi¸˜o ´ necess´ria. a e ca ´ ca e a Podemos querer passar o controle de uma parte do programa a outra ou ainda parar completamente o processamento. Para estes prop´sitos, recursos s˜o dispon´ o a ıveis em Fortran que possibilitam o controle do fluxo l´gico o atrav´s dos comandos no programa. Os recursos contidos em Fortran 90 correspondem aos que agora s˜o e a geralmente reconhecidos como os mais apropriados para uma linguagem de programa¸˜o moderna. Sua ca forma geral ´ a de um construto de bloco (do inglˆs block construct), o qual ´ um construto (uma constru¸˜o e e e ca ou estrutura) que come¸a com uma palavra-chave inicial, pode ter palavras-chave intermedi´rias e que c a termina com uma palavra-chave final que identifica a palavra inicial. Cada seq¨ˆncia de comandos entre as ue palavras-chave ´ chamada de um bloco. Um bloco pode ser vazio, embora tais casos sejam raros. e Construtos execut´veis podem ser aninhados (em inglˆs, nested ) ou encadeados, isto ´, um bloco pode a e e conter um outro construto execut´vel. Neste caso, o bloco deve conter o construto interno por inteiro. a Execu¸˜o de um bloco sempre inicia com o seu primeiro comando execut´vel. ca a Os primeiros comandos de controle de fluxo a ser mencionados ser˜o aqueles que foram definidos tanto a no Fortran 77 quanto no Fortran 90/95, seguidos daqueles que somente existem no Fortran 90/95. 5.1 Comandos obsoletos do Fortran 77 Os comandos descritos nesta se¸˜o fazem parte do padr˜o do Fortran 77 mas que s˜o considerados ca a a obsoletos no Fortran 90/95. O seu uso em um programa escrito nas ultimas vers˜es da linguagem ´ fortemente ´ o e desencorajado e, para alguns compiladores, proibido. A raz˜o para este status de obsoleto ´ porque estes a e comandos facilmente geram dificuldades e d˜o margem a confus˜o durante a leitura do programa. Algumas a a raz˜es para o status de obsoleto para estes comandos s˜o apresentadas abaixo. o a 5.1.1 R´tulos (statement labels) o Um r´tulo consiste em um n´mero inteiro, de 1 a 99999, inserido entre as colunas 1 e 5 de um programa o u ou sub-programa em Fortran 77 escrito, portanto, no formato fixo. Este r´tulo enfatiza o ponto do c´digo o o onde ele se encontra. H´ trˆs raz˜es para se usar um r´tulo: a e o o 1. O final de um la¸o DO ´ especificado por um r´tulo determinado no in´ do mesmo la¸o. c e o ıcio c 2. Todo comando FORMAT deve possuir um r´tulo, pois esta ´ a maneira como os comandos READ e WRITE o e fazem referˆncia ao mesmo. e 3. Qualquer comando execut´vel pode possuir um r´tulo afixado, de tal forma que o fluxo do c´digo pode a o o ser transferido ao mesmo. Isto ´ realizado, por exemplo, pelo comando GO TO. e 35
  • 44.
    36 5.1. Comandos obsoletosdo Fortran 77 Exemplo: c (F77) L^ n´meros de um arquivo de entrada at´ que ele termine, ent~o os soma. e u e a SUMA= 0.0 100 READ(UNIT= IN, FMT= 200, END= 9999) VALOR 200 FORMAT(F20.0) SOMA= SOMA + VALOR GO TO 100 9999 CONTINUE WRITE(UNIT= *, FMT=*)’SOMA dos valores ´:’, SOMA e O comando CONTINUE significa, literalmente, “continue”, isto ´, ele apenas instrui o programa a continuar a e partir daquele ponto. 5.1.2 Comando GO TO incondicional O comando GO TO incondicional simplesmente transfere o fluxo do c´digo para um comando rotulado em o algum outro ponto do programa. Sua forma geral ´: e GO TO <r´tulo> o Um exemplo de aplica¸˜o deste comando pode ser visto acima. A unica exce¸˜o para seu uso ´ a proibi¸˜o ca ´ ca e ca de transferir o fluxo para dentro de um bloco IF ou la¸o DO; entretanto, ´ permitido transferir o fluxo com c e o comando GO TO, ou outro, para fora de um bloco IF ou la¸o DO. c O uso do GO TO incondicional torna poss´ escrever-se programas com uma estrutura bastante indisıvel ciplinada. Tais programas s˜o usualmente dif´ a ıceis de ser compreendidos e corrigidos. Bons programadores usam este comando raras vezes ou nunca. Contudo, no Fortran 77 em algumas situa¸˜es n˜o era poss´ co a ıvel evit´-lo, devido a falta de alternativas de estruturas de controle. a 5.1.3 Comando GO TO computado O comando GO TO computado ´ uma alternativa para um bloco IF para as situa¸˜es em que um n´mero e co u grande de op¸˜es devem ser consideradas e elas podem ser selecionadas por uma express˜o de valores inteiros. co a A forma geral do comando ´: e GO TO (<r´tulo 1>, <r´tulo 2>, ..., <r´tulo N>)[,] <express~o inteira> o o o a A <express~o inteira> ´ desenvolvida; se o seu resultado ´ 1 (um), o controle ´ transferido ao comando a e e e afixado ao <r´tulo 1>; se o resultado ´ 2 (dois), o controle ´ transferido ao comando afixado ao <r´tulo o e e o 2> e assim por diante. Se o resultado da express˜o ´ menor que um ou maior que N (havendo N r´tulos na a e o lista), o comando n˜o tem efeito e o fluxo do programa continua com o pr´ximo comando em seq¨ˆncia. O a o ue mesmo r´tulo pode estar presente mais de uma vez na lista. o O GO TO computado sofre das mesmas desvantagens que o GO TO incondicional, uma vez que se suas ramifica¸˜es forem usadas sem cuidado, o programa se torna ileg´ de t˜o confuso. co ıvel a 5.1.4 Comando IF aritm´tico e A forma geral do comando IF aritm´tico ´: e e IF (<express~o aritm´tica>) <r´tulo 1>,<r´tulo 2>,<r´tulo 3> a e o o o Este comando geralmente fornece uma ramifica¸˜o com trˆs possibilidades, embora dois dos r´tulos possam ca e o ser iguais, o que o torna uma ramifica¸˜o de duas possibilidades. A <express~o aritm´tica> pode ser ca a e inteira, real ou real de precis˜o dupla. O controle do fluxo ´ transferido ao comando afixado ao <r´tulo 1> a e o se o valor for negativo, ao <r´tulo 2> se for zero e ao <r´tulo 3> se for positivo. o o 5.1.5 Comandos ASSIGN e GO TO atribu´ ıdo Estes dois comandos s˜o normalmente usados juntos. O comando ASSIGN atribui o valor de um r´tulo a a o uma vari´vel inteira. Quando isto ´ realizado, a vari´vel n˜o mais possui um valor aritm´tico, mas se torna a e a a e o pr´prio r´tulo. Se o r´tulo ´ afixado a um comando execut´vel, a vari´vel somente pode ser usada em um o o o e a a comando GO TO atribu´ ıdo; se ´ afixado a um comando FORMAT, a vari´vel somente pode ser usada em um e a comando READ ou WRITE. As formas gerais destes comandos s˜o: a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 45.
    Cap´ ıtulo 5. Comandose Construtos de Controle de Fluxo 37 ASSIGN <r´tulo> TO <vari´vel inteira> o a GO TO <vari´vel inteira> [,] [(<r´tulo>,<r´tulo>,...,<r´tulo>)] a o o o Um GO TO atribu´ pode ser usado para fornecer uma liga¸˜o para e a partir de uma se¸˜o de um programa ıdo ca ca ou sub-programa, atuando assim como um subrotina interna. 5.1.6 La¸os DO rotulados c O comando DO controla um bloco de comandos os quais s˜o executados repetidas vezes, uma vez para a cada valor de uma vari´vel denominada vari´vel de controle do la¸o (loop-control variable). O n´mero de a a c u itera¸˜es depende dos parˆmetros do comando DO no cabe¸alho do la¸o. co a c c A primeira vers˜o de um bloco ou la¸o DO cont´m um r´tulo que indica o ultimo comando do la¸o. A a c e o ´ c forma geral do cabe¸alho de um la¸o DO rotulado pode ter uma das duas formas seguintes: c c DO <r´tulo> [,] <vari´vel> = <in´cio>, <limite>, <passo> o a ı DO <r´tulo> [,] <vari´vel> = <in´cio>, <limite> o a ı Na segunda forma, o tamanho do passo ´ implicitamente igual a um. O <r´tulo> marca o ultimo comando e o ´ do la¸o. Ele deve estar afixado a um comando execut´vel em alguma linha posterior do programa ou subc a programa. A regra permite que este comando seja qualquer comando execut´vel, exceto outro comando de a controle (como o IF, por exemplo), mas ´ recomend´vel que se use o comando CONTINUE, cuja fun¸˜o foi e a ca exemplificada na se¸˜o 5.1.1. ca A <vari´vel> ´ a vari´vel de controle do la¸o ou ´ a e a c ındice do la¸o; ela deve ser uma vari´vel escalar (n˜o c a a um elemento de matriz) e pode ser dos tipos inteiro, real ou dupla precis˜o. a Os valores de <in´cio>, <limite> e <passo> podem ser express˜es tamb´m dos tipos inteiro, real ou ı o e precis˜o dupla. Se o valor do <passo> estiver presente, este n˜o pode ser zero; se for omitido, o seu valor ´ a a e assumido igual a um. O n´mero de itera¸˜es a ser realizadas ´ calculado antes do in´ da primeira itera¸˜o u co e ıcio ca e ´ dado pela f´rmula: e o itera¸~es = MAX(0,INT((limite - in´cio + passo)/passo)) co ı onde a fun¸˜o impl´ ca ıcita INT toma a parte inteira do argumento por truncagem e a fun¸˜o MAX toma o maior ca valor dos seus dois argumentos. Nota-se que se o valor de limite ´ menor que in´cio, o n´mero de itera¸˜es e ı u co ´ zero, exceto no case de passo ser negativo. Um n´mero nulo de itera¸˜es ´ permitido, mas isto significa e u co e que o conte´do do la¸o n˜o ser´ executado e o controle do fluxo ´ transferido ao primeiro comando ap´s u c a a e o o r´tulo. A vari´vel de controle do la¸o n˜o necessariamente assume o valor limite, especialmente se o o a c a tamanho do passo for maior que um e/ou do tipo real com valor fracion´rio. a Comandos dentro do la¸o podem alterar o valor das express˜es usadas para o in´cio, limite ou passo, c o ı mas o n´mero de itera¸˜es n˜o ´ alterado, uma vez que este ´ determinado antes do in´ u co a e e ıcio da primeira itera¸˜o. A vari´vel de controle do la¸o pode ser usada em express˜es mas um novo valor n˜o pode ser ca a c o a atribu´ a ela dentro do la¸o. ıdo c Dois exemplos de aplica¸˜es de la¸os DO rotulados: co c c Soma dos quadrados dos N primeiros elementos da matriz X. SOMA= 0.0 DO 15, I= 1,N SOMA= SOMA + X(I)**2 15 CONTINUE ------------------------------C Inicializa as componentes da matriz FIELD iguais a zero. c Exemplo de la¸os DO encadeados. c REAL FIELD(NX, NY) DO 50, IY= 1,NY DO 40, IX= 1,NX FIELD(IX, IY)= 0.0 40 CONTINUE 50 CONTINUE 5.2 Comando e construto IF O comando IF fornece um mecanismo para controle de desvio de fluxo, dependendo de uma condi¸˜o. ca H´ duas formas: o comando IF e o construto IF, sendo o ultimo uma forma geral do primeiro. a ´ Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 46.
    38 5.2. Comando econstruto IF 5.2.1 Comando IF No comando IF, o valor de uma express˜o l´gica escalar ´ testado e um unico comando ´ executado se a o e ´ e e somente se o seu valor for verdadeiro. A forma geral ´: e IF (<express~o relacional e/ou l´gica>) <comando execut´vel> a o a O <comando execut´vel> ´ qualquer, exceto aqueles que marcam o in´ a e ıcio ou o final de um bloco, como por exemplo IF, ELSE IF, ELSE, END IF, outro comando IF ou uma declara¸˜o END. Temos os seguintes ca exemplos: IF (FLAG) GO TO 6 IF(X-Y > 0.0) X= 0.0 IF(COND .OR. P < Q .AND. R <= 1.0) S(I,J)= T(J,I) 5.2.2 Construto IF Um construto IF permite que a execu¸ao de uma seq¨ˆncia de comandos (ou seja, um bloco) seja c˜ ue realizada, dependendo de uma condi¸˜o ou de um outro bloco, dependendo de outra condi¸˜o. H´ trˆs ca ca a e formas usuais para um construto IF. A forma mais simples tem a seguinte estrutura geral: [<nome>:] IF (<express~o relacional e/ou l´gica>) THEN a o <bloco> END IF [<nome>] onde <bloco> denota uma seq¨ˆncia de linhas de comandos execut´veis. O bloco ´ executado somente se o ue a e resultado da <express~o relacional e/ou l´gica> for verdadeiro. O construto IF pode ter um <nome>, a o o qual deve ser um nome v´lido em Fortran 90/95. O <nome> ´ opcional, mas se for definido no cabe¸alho a e c do construto, ele deve ser tamb´m empregado no final, denotado pela declara¸˜o END IF <nome>. Como e ca exemplo, temos: SWAP: IF (X < Y) THEN TEMP= X X= Y Y= TEMP END IF SWAP As trˆs linhas de texto entre “SWAP: IF ...” e “END IF SWAP” ser˜o executadas somente se X < Y. Pode-se e a incluir outro construto IF ou outra estrutura de controle de fluxo no bloco de um construto IF. A segunda forma usada para o construto IF ´ a seguinte: e [<nome>:] IF (<express~o relacional e/ou l´gica>) THEN a o <bloco 1> ELSE [<nome>] <bloco 2> END IF [<nome>] Na qual o <bloco 1> ´ executado se o resultado da <express~o relacional e/ou l´gica> for verdadeira; e a o caso contr´rio, o <bloco 2> ser´ executado. Este construto permite que dois conjuntos distintos de instrua a ¸˜es sejam executados, dependendo de um teste l´gico. Um exemplo de aplica¸˜o desta forma intermedi´ria co o ca a seria: IF (X < Y) THEN X= -Y ELSE Y= -Y END IF Neste exemplo, se o resultado de X < Y for verdadeiro, ent˜o X= -Y, sen˜o (ou seja, X >= Y) a a¸˜o ser´ Y= a a ca a -Y. A terceira e final vers˜o usa a instru¸˜o ELSE IF para realizar uma s´rie de testes independentes, cada a ca e um dos quais possui um bloco de comandos associado. Os testes s˜o realizados um ap´s o outro at´ que um a o e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 47.
    Cap´ ıtulo 5. Comandose Construtos de Controle de Fluxo 39 deles seja satisfeito, em cujo caso o bloco associado ´ executado, enquanto que os outros s˜o solenemente e a ignorados. Ap´s, o controle do fluxo ´ transferido para a instru¸˜o END IF. Caso nenhuma condi¸˜o seja o e ca ca satisfeita, nenhum bloco ´ executado, exceto se houver uma instru¸˜o ELSE final, que abarca quaisquer e ca possibilidades n˜o satisfeitas nos testes realizados no construto. A forma geral ´: a e [<nome>:] IF (<express~o relacional e/ou l´gica>) THEN a o <bloco> [ELSE IF (<express~o relacional e/ou l´gica>) THEN [<nome>] a o <bloco>] ... [ELSE [<nome>] <bloco>] END IF [<nome>] Pode haver qualquer n´mero (inclusive zero) de instru¸˜es ELSE IF e, no m´ximo, uma instru¸˜o ELSE. u co a ca Novamente, o <nome> ´ opcional, mas se for adotado no cabe¸alho do construto, ent˜o deve ser mencionado e c a em todas as circunstˆncias ilustradas acima. O exemplo a seguir ilustra o encadeamento de construtos a IF. Estruturas ainda mais complicadas s˜o poss´ a ıveis, mas neste caso ´ recomend´vel adotar nomes para os e a construtos, como forma de facilitar a leitura e compreens˜o do programa. a IF (I < 0) THEN IF (J < 0) THEN X= 0.0 Y= 0.0 ELSE Z= 0.0 END IF ELSE IF (K < 0) THEN Z= 1.0 ELSE X= 1.0 Y= 1.0 END IF O programa-exemplo a seguir (programa 5.1) faz uso de construtos IF para implementar o c´lculo do fatorial a de um n´mero natural, j´ utilizando o construto DO, abordado na se¸˜o 5.3. u a ca 5.3 Construto DO Um la¸o DO ´ usado quando for necess´rio calcular uma s´rie de opera¸˜es semelhantes, dependendo ou c e a e co n˜o de algum parˆmetro que ´ atualizado em cada in´ da s´rie. Por exemplo, para somar o valor de um a a e ıcio e polinˆmio de grau N em um dado ponto x: o N P (x) = a0 + a1 x + a2 x2 + · · · + aN xN = ai xi . i=0 Outro tipo de opera¸˜es freq¨entemente necess´rias s˜o aquelas que envolvem opera¸˜es matriciais, como o co u a a co produto de matrizes, triangulariza¸˜o, etc. Para este tipo de opera¸˜es repetidas, ´ conveniente usar-se um ca co e la¸o DO para implement´-las, ao inv´s de escrever o mesmo bloco de opera¸˜es N vezes, como aconteceria c a e co se fosse tentado implementar a soma do polinˆmio atrav´s das seguintes express˜es: o e o REAL POL= POL= POL= ... POL= :: POL,A0,A1,A2,...,AN A0 POL + A1*X POL + A2*X**2 POL + AN*X**N Esta forma do la¸o DO n˜o usa r´tulos, como a forma definida na se¸˜o 5.1.6. A forma geral de um construto c a o ca DO ´ a seguinte: e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 48.
    40 5.3. Construto DO Programa5.1: Programa que utiliza os construtos IF e DO. program i f f a t ! C a l c u l a o f a t o r i a l de um n´ mero n a t u r a l . u i m p l i c i t none integer : : i , f a t , j ! print * , ”Entre com v a l o r : ” read * , i i f ( i < 0 ) then print * , ”N˜o ´ p o s s´ v e l c a l c u l a r o f a t o r i a l . ” a e ı e l s e i f ( i == 0 ) then print * , ” f a t ( ” , i , ”)= ” , 1 else f a t= 1 do j= 1 , i f a t= f a t * j end do print * , ” f a t ( ” , i , ”)= ” , f a t end i f end program i f f a t [<nome>:] DO [<vari´vel> = <express~o 1>, <express~o 2> [, <express~o 3>]] a a a a <bloco> END DO [<nome>] onde <vari´vel> ´ uma vari´vel inteira e as trˆs express˜es contidas no cabe¸alho do construto devem ser a e a e o c do mesmo tipo. No cabe¸alho acima, cada uma das express˜es indica: c o <express~o 1>: o valor inicial da <vari´vel>; a a <express~o 2>: o valor m´ximo, ou limite, da <vari´vel> (n˜o necessariamente deve ser o ultimo valor a a a a ´ assumido pela vari´vel); a <express~o 3>: o passo, ou incremento, da vari´vel em cada nova itera¸˜o. a a ca Este construto tamb´m ´ aceito no Fortran 77, exceto pela possibilidade de se definir um <nome>. Como no e e caso de um la¸o DO rotulado, o n´mero de itera¸˜es ´ definido antes de se executar o primeiro comando do c u co e <bloco> e ´ dado pelo resultado da conta e MAX((<express~o 2> - <express~o 1> + <express~o 3>)/<express~o 3>,0). a a a a Novamente, se o resultado do primeiro argumento da fun¸˜o MAX acima for negativo, o la¸o n˜o ser´ execa c a a cutado. Isto pode acontecer, por exemplo, se <express~o 2> for menor que <express~o 1> e o passo a a <express~o 3> for positivo. Novamente, se o passo <express~o 3> for omitido, este ser´ igual a 1. O a a a exemplo abaixo ilustra o uso de express˜es no cabe¸alho do construto: o c DO I= J + 4, M, -K**2 ... END DO Como se pode ver, o incremento pode ser negativo, o que significa, na pr´tica, que os comandos do bloco a somente ser˜o executados se M <= J + 4. O exemplo a seguir ilustra um bloco DO onde a vari´vel I somente a a assume valores ´ ımpares: DO I= 1, 11, 2 ... END DO Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 49.
    Cap´ ıtulo 5. Comandose Construtos de Controle de Fluxo 41 Programa 5.2: Exemplo de uso do construto DO. ! M o d i f i c a o p a s s o de um l a ¸ o DO d e n t r o do b l o c o . c program mod passo i m p l i c i t none integer : : i , j ! Bloco sem m o d i f i c a ¸ ˜ o de p a s s o . ca do i= 1 , 10 print * , i end do ! Bloco com m o d i f i c a ¸ ˜ o do p a s s o . ca j= 1 do i= 1 , 1 0 , j i f ( i > 5 ) j= 3 print * , i , j end do end program mod passo Como no caso do DO rotulado, caso alguma das express˜es envolvam o uso de vari´veis, estas podem ser o a modificadas no bloco do la¸o, inclusive o passo das itera¸˜es. Entretanto, o n´mero de itera¸˜es e o passo c co u co a ser realmente tomado n˜o s˜o modificados, uma vez que foram pr´-determinados antes do in´ a a e ıcio das itera¸˜es. O programa abaixo (programa 5.2) exemplifica este fato: co Abaixo, temos um outro exemplo que ilustra o funcionamento do la¸o DO: c FAT= 1 DO I= 2, N FAT= FAT*I END DO Neste exemplo, o n´mero de itera¸˜es ser´ u co a MAX(N-2+1,0) = MAX(N-1,0). Caso N < 2, o la¸o n˜o ser´ executado, e o resultado ser´ FAT= 1. Caso N >= 2, o valor inicial da vari´vel c a a a a inteira I ´ 2, esta ´ usada para calcular um novo valor para a vari´vel FAT, em seguida a vari´vel I ser´ e e a a a incrementada por 1 e o novo valor I= 3 ser´ usado novamente para calcular o novo valor da vari´vel FAT. a a Desta forma, a vari´vel I ser´ incrementada e o bloco executado at´ que I= N + 1, sendo este o ultimo valor a a e ´ de I e o controle ´ transferido para o pr´ximo comando ap´s a declara¸˜o END DO. O exemplo ilustrado e o o ca acima retornar´, na vari´vel FAT, o valor do fatorial de N. a a Temos os seguintes casos particulares e instru¸˜es poss´ co ıveis para um construto DO. 5.3.1 Construto DO ilimitado Como caso particular de um construto DO, a seguinte instru¸˜o ´ poss´ ca e ıvel: [<nome>:] DO <bloco> END DO [<nome>] Neste caso, o conjunto de comandos contidos no <bloco> ser˜o realizados sem limite de n´mero de itera¸˜es, a u co exceto se algum teste ´ inclu´ dentro do bloco, o que possibilita um desvio de fluxo para a primeira instru¸˜o e ıdo ca ap´s o END DO. Uma instru¸˜o que realiza este tipo de desvio ´ a instru¸˜o EXIT, descrita a seguir. o ca e ca 5.3.2 Instru¸˜o EXIT ca Esta instru¸˜o permite a sa´ ca ıda, por exemplo, de um la¸o sem limite, mas o seu uso n˜o est´ restrito a c a a este caso particular, podendo ser usada em um construto DO geral. A forma geral desta instru¸˜o ´: ca e EXIT [<nome>] Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 50.
    42 5.4. Construto CASE ondeo <nome> ´ opcional, mas deve ser usado caso ele exista e, neste caso, ele serve para denotar de qual e construto a sa´ deve ser feita. Isto ocorre, por exemplo, no caso de construtos encadeados. Execu¸˜o de ıda ca um EXIT transfere controle ao primeiro comando execut´vel ap´s o END DO [<nome>] correspondente. a o Como exemplo, temos: DO ... I= I + 1 IF(I == J) EXIT ... END DO 5.3.3 Instru¸˜o CYCLE ca A forma geral desta instru¸˜o ´: ca e CYCLE [<nome>] a qual transfere controle ` declara¸˜o END DO do construto correspondente sem ocorrer a execu¸˜o dos comana ca ca dos posteriores a instru¸˜o. Assim, se outras itera¸˜es devem ser realizadas, estas s˜o feitas, incrementando` ca co a se o valor de <vari´vel> (caso exista) pelo passo dado pela <express~o 3>. O programa a seguir ilustra a a o uso desta instru¸˜o. ca program d o c y c l e i m p l i c i t none integer : : i n d e x= 1 do i n d e x= i n d e x + 1 i f ( i n d e x == 2 0 ) cycle i f ( i n d e x == 3 0 ) e xi t print * , ”Valor do ´ n d i c e : ” , i n d e x ı end do end program d o c y c l e 5.4 Construto CASE Fortran 90/95 fornece uma outra alternativa para selecionar uma de diversas op¸˜es: trata-se do construto co CASE. A principal diferen¸a entre este construto e um bloco IF est´ no fato de somente uma express˜o ser c a a calculada para decidir o fluxo e esta pode ter uma s´rie de resultados pr´-definidos. A forma geral do e e construto CASE ´: e [<nome>:] SELECT CASE (<express~o>) a [CASE (<seletor>) [<nome>] <bloco>] ... [CASE DEFAULT <bloco>] END SELECT [<nome>] A <express~o> deve ser escalar e pode ser dos tipos inteiro, l´gico ou de caractere e o valor especificado a o por cada <seletor> deve ser do mesmo tipo. No caso de vari´veis de caracteres, os comprimentos podem a diferir, mas n˜o a esp´cie. Nos casos de vari´veis inteiras ou l´gicas, a esp´cie pode diferir. A forma mais a e a o e simples do <seletor> ´ uma constante entre parˆnteses, como na declara¸˜o e e ca CASE (1) Para express˜es inteiras ou de caracteres, um intervalo pode ser especificado separando os limites inferior e o superior por dois pontos “: “ CASE (<inf> : <sup>) Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 51.
    Cap´ ıtulo 5. Comandose Construtos de Controle de Fluxo 43 Um dos limites pode estar ausente, mas n˜o ambos. Caso um deles esteja ausente, significa que o bloco de a comandos pertencente a esta declara¸˜o CASE ´ selecionado cada vez que a <express~o> calcula um valor ca e a que ´ menor ou igual a <sup>, ou maior ou igual a <inf>, respectivamente. Um exemplo ´ mostrado abaixo: e e SELECT CASE CASE (:-1) N_SINAL= CASE (0) N_SINAL= CASE (1:) N_SINAL= END SELECT (NUMERO) ! NUMERO ´ do tipo inteiro. e ! Todos os valores de NUMERO menores que 0. -1 ! Somente NUMERO= 0. 0 ! Todos os valores de NUMERO > 0. 1 A forma geral do <seletor> ´ uma lista de valores e de intervalos n˜o sobrepostos, todos do mesmo tipo e a que <express~o>, entre parˆnteses, tal como a e CASE (1, 2, 7, 10:17, 23) Caso o valor calculado pela <express~o> n˜o pertencer a nenhuma lista dos seletores, nenhum dos blocos ´ a a e executado e o controle do fluxo passa ao primeiro comando ap´s a declara¸˜o END SELECT. J´ a declara¸˜o o ca a ca CASE DEFAULT ´ equivalente a uma lista de todos os valores poss´ e ıveis de <express~o> que n˜o foram inclu´ a a ıdos nos outros seletores do construto. Portanto, somente pode haver um CASE DEFAULT em um dado construto CASE. O exemplo a seguir ilustra o uso desta declara¸˜o: ca SELECT CASE (CH) ! CH ´ do tipo de caractere. e CASE (’C’, ’D’, ’R’:) CH_TYPE= .TRUE. CASE (’I’:’N’) INT_TYPE= .TRUE. CASE DEFAULT REAL_TYPE= .TRUE. END SELECT No exemplo acima, os caracteres ’C’, ’D’, ’R’ e todos os caracteres ap´s o ultimo indicam nomes de o ´ vari´veis do tipo de caractere. Os caracteres ’I’ e ’N’ indicam vari´veis do tipo inteiro, e todos os outros a a caracteres alfab´ticos indicam vari´veis reais. e a O programa-exemplo abaixo mostra o uso deste construto. Note que os seletores de caso somente testam o primeiro caractere da vari´vel NOME, embora esta tenha um comprimento igual a 5. a program c a s e s t r i n g i m p l i c i t none character ( len= 5 ) : : nome print * , ”Entre com o nome ( 5 c a r a c t e r e s ) : ” read ”( a5 ) ” , nome s e l e c t case ( nome ) case ( ”a ” : ”z ”) ! S e l e c i o n a nome que come¸ a com l e t r a s m i n u s c u l a s . c ´ print * , ”P a l a v r a i n i c i a com L e t r a m i n u s c u l a . ” ´ case ( ”A” : ”Z ”) ! S e l e c i o n a nome que come¸ a com l e t r a s m a i u s c u l a s . c ´ print * , ”P a l a v r a i n i c i a com l e t r a s m a i u s c u l a . ” ´ case ( ”0 ” : ”9 ”) ! S e l e c i o n a n´ meros . u print * , ”P a l a v r a i n i c i a com n´ meros ! ! ! ” u case default ! Outros t i p o s de c a r a c t e r e s . print * , ”P a l a v r a i n i c i a com C a r a c t e r e s e s p e c i a i s ! ! ! ” end s e l e c t end program c a s e s t r i n g J´ o programa abaixo, testa o sinal de n´meros inteiros: a u Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 52.
    44 5.4. Construto CASE programt e s t a c a s e i m p l i c i t none integer : : a print * , ”Entre com a ( i n t e i r o ) : ” read * , a s e l e c t case ( a ) case (: −1) print * , ”Menor que z e r o . ” case ( 0 ) print * , ” I g u a l a z e r o . ” case ( 1 : ) print * , ”Maior que z e r o . ” end s e l e c t end program t e s t a c a s e O programa abaixo ilustra o uso de alguns dos construtos discutidos neste cap´ ıtulo. ! Imprime uma t a b e l a de c o n v e r s ˜ o das e s c a l a s C e l s i u s e F a h r e n h e i t a ! e n t r e l i m i t e s de t e m p e r a t u r a e s p e c i f i c a d o s . program conv temp i m p l i c i t none character ( len= 1 ) : : s c a l e integer : : low temp , high temp , temp real : : c e l s i u s , f a r e n h e i t ! r e a d l o o p : do ! Lˆ e s c a l a e l i m i t e s . e print * , ” E s c a l a de t e m p e r a t u r a s (C/F ) : ” read ”( a ) ” , s c a l e ! Confere v a l i d a d e dos dados . i f ( s c a l e /= ”C” . and . s c a l e /= ”F”) then print * , ” E s c a l a n˜ o v ´ l i d a ! ” a a e xi t r e a d l o o p end i f print * , ” L i m i t e s ( temp . i n f e r i o r , temp . s u p e r i o r ) : ” read * , low temp , high temp ! ! La¸ o s o b r e os l i m i t e s de t e m p e r a t u r a . c do temp= low temp , high temp ! E s c o l h e f ´ r m u l a de c o n v e r s ˜ o o a s e l e c t case ( s c a l e ) case ( ”C”) c e l s i u s= temp f a r e n h e i t= 9 * c e l s i u s / 5 . 0 + 3 2 . 0 case ( ”F”) f a r e n h e i t= temp c e l s i u s= 5 * ( f a r e n h e i t − 3 2 ) / 9 . 0 end s e l e c t ! Imprime t a b e l a print * , c e l s i u s , ”g r a u s C correspondem a ” , f a r e n h e i t , ”g r a u s F . ” end do end do r e a d l o o p ! ! Finaliza¸˜o . ca print * , ” F i n a l dos dados v ´ l i d o s . ” a end program conv temp Autor: Rudi Gaelzer – IFM/UFPel Impresso: 12 de abril de 2010
  • 53.
    Cap´ ıtulo 6 Processamento deMatrizes A defini¸ao e o processamento de matrizes e vetores sempre foi um recurso presente em todas as linguagens c˜ de programa¸˜o, inclusive no Fortran 77. Uma novidade importante introduzida no Fortran 90/95 ´ a ca e capacidade estendida de processamento das mesmas. Agora ´ poss´ trabalhar diretamente com a matriz e ıvel completa, ou com se¸˜es da mesma, sem ser necess´rio o uso de la¸os DO. Novas fun¸˜es intr´ co a c co ınsecas agora atuam de forma elemental (em todos os elementos) em matrizes e fun¸˜es podem retornar valores na forma co de matrizes. Tamb´m est˜o dispon´ e a ıveis as possibilidades de matrizes aloc´veis, matrizes de forma assumida a e matrizes dinˆmicas. a Estes e outros recursos ser˜o abordados neste e nos pr´ximos cap´ a o ıtulos. 6.1 Terminologia e especifica¸oes de matrizes c˜ Uma matriz ou vetor 1 ´ um outro tipo de objeto composto suportado pelo Fortran 77/90/95. Uma e matriz consiste de um conjunto retangular de elementos, todos do mesmo tipo e esp´cie do tipo. Uma outra e defini¸˜o equivalente seria: uma matriz ´ um grupo de posi¸˜es na mem´ria do computador as quais s˜o ca e co o a acessadas por interm´dio de um unico nome, fazendo-se uso dos subscritos da matriz. Este tipo de objeto e ´ ´ util quando for necess´rio se fazer referˆncia a um n´mero grande, por´m a princ´ e ´ a e u e ıpio desconhecido, de vari´veis do tipo intr´ a ınseco ou outras estruturas, sem que seja necess´rio definir um nome para cada vari´vel. a a O Fortran 77/90/95 permite que uma matriz tenha at´ sete subscritos, cada um relacionado com uma e dimens˜o da matriz. As dimens˜es de uma matriz podem ser especificadas usando-se tanto o atributo a o DIMENSION quanto a declara¸˜o DIMENSION. ca Os ´ ındices de cada subscrito da matriz s˜o constantes ou vari´veis inteiras e, por conven¸˜o, eles come¸am a a ca c em 1, exceto quando um intervalo distinto de valores ´ especificado, atrav´s do fornecimento de um limite e e inferior e um limite superior. A declara¸˜o de matrizes difere ligeiramente entre o Fortran 77 e o Fortran 90/95. ca Fortran 77. Uma matriz pode ser definida tanto na declara¸˜o de tipo intr´ ca ınseco quanto com o uso da declara¸˜o DIMENSION: ca INTEGER NMAX INTEGER POINTS(NMAX),MAT_I(50) REAL R_POINTS(0:50),A DIMENSION A(NMAX,50) CHARACTER COLUMN(5)*25, ROW(10)*30 No ultimo exemplo acima, o vetor COLUMN possui 5 componentes, COLUMN(1), COLUMN(2), ..., COLUMN(5), ´ cada um destes sendo uma vari´vel de caractere de comprimento 25. J´ o vetor ROW possui 10 componentes, a a cada um sendo uma vari´vel de caractere de comprimento 30. A matriz real A possui 2 dimens˜es, sendo a o NMAX linhas e 50 colunas. Todas as matrizes neste exemplo tˆm seus ´ e ındices iniciando em 1, exceto pela matriz R_POINTS, a qual inicia em 0: R_POINTS(0), R_POINTS(1), ..., R_POINTS(50). Ou seja, este vetor possui 51 componentes. 1 Nome usualmente para uma matriz de uma dimens˜o. a 45
  • 54.
    46 6.1. Terminologia eespecifica¸˜es de matrizes co Fortran 90/95. As formas de declara¸˜es de matrizes em Fortran 77 s˜o aceitas no Fortran 90/95. Por´m, co a e ´ recomend´vel que estas sejam declaradas na forma de atributos de tipos de vari´veis. Por exemplo, e a a REAL, DIMENSION(50) :: W REAL, DIMENSION(5:54) :: X CHARACTER(LEN= 25), DIMENSION(5) :: COLUMN CHARACTER(LEN= 30), DIMENSION(10) :: ROW Antes de prosseguir, ser´ introduzida a terminologia usada com rela¸˜o a matrizes. a ca Posto. O posto (rank ) de uma matriz ´ o n´mero de dimens˜es da mesma. Assim, um escalar tem posto e u o 0, um vetor tem posto 1 e uma matriz tem posto maior ou igual a 2. Extens˜o. A extens˜o (extent) de uma matriz se refere a uma dimens˜o em particular e ´ o n´mero de a a a e u componentes naquela dimens˜o. a Forma. A forma (shape) de uma matriz ´ um vetor cujos componentes s˜o a extens˜o de cada dimens˜o e a a a da matriz. Tamanho. O tamanho (size) de um matriz ´ o n´mero total de elementos que comp˜e a mesma. Este e u o n´mero pode ser zero, em cujo caso esta se denomina matriz nula. u Duas matrizes s˜o ditas serem conform´veis se elas tˆm a mesma forma. Todas as matrizes s˜o conform´veis a a e a a com um escalar, uma vez que o escalar ´ expandido em uma matriz com a mesma forma (ver se¸˜o 6.2). e ca Por exemplo, as seguintes matrizes: REAL, DIMENSION(-3:4,7) :: A REAL, DIMENSION(8,2:8) :: B REAL, DIMENSION(8,0:8) :: D INTEGER :: C A matriz A possui: ˆ posto 2; ˆ extens˜es 8 e 7; o ˆ forma (/8,7/), onde os s´ ımbolos “(/” e “/)” s˜o os construtores de matrizes, isto ´, eles definem ou a e inicializam os valores de um vetor ou matriz. Estes construtores de matrizes ser˜o descritos com mais a detalhes na se¸˜o 6.6. ca ˆ Tamanho 56. Al´m disso, A ´ conform´vel com B e C, uma vez que a forma de B tamb´m ´ (/8,7/) e C ´ um escalar. e e a e e e Contudo, A n˜o ´ conform´vel com D, uma vez que esta ultima tem forma (/8,9/). a e a ´ A forma geral da declara¸˜o de uma ou mais matrizes ´ como se segue: ca e <tipo>[[, DIMENSION(<lista de extens~es>)] [, < outros atributos>] ::] o <lista de nomes> Entretanto, a forma recomend´vel da declara¸˜o ´ a seguinte: a ca e <tipo>, DIMENSION(<lista de extens~es>) [, <outros atributos>] :: <lista de noo mes> Onde <tipo> pode ser um tipo intr´ ınseco de vari´vel ou de tipo derivado (desde que a defini¸˜o do tipo a ca derivado esteja acess´ ıvel). A <lista de extens~es> fornece as dimens˜es da matriz atrav´s de: o o e ˆ constantes inteiras; ˆ express˜es inteiras usando vari´veis mudas (dummy) ou constantes; o a ˆ somente o caractere “:” para indicar que a matriz ´ aloc´vel ou de forma assumida. e a Os <outros atributos> podem ser quaisquer da seguinte lista: Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 55.
    Cap´ ıtulo 6. Processamentode Matrizes 47 PARAMETER ALLOCATABLE INTENT(INOUT) OPTIONAL SAVE EXTERNAL INTRINSIC PUBLIC PRIVATE POINTER TARGET Os atributos contidos na lista acima ser˜o abordados ao longo deste e dos pr´ximos cap´ a o ıtulos. Os atributos em vermelho: POINTER e TARGET consistem em recursos avan¸ados do Fortran 90/95 que ser˜o discutidos c a em separado. Finalmente, segue a <lista de nomes> v´lidos no Fortran, onde os mesmos s˜o atribu´ a a ıdos `s matrizes. a Os seguintes exemplos mostram a forma da declara¸˜o de diversos tipos diferentes de matrizes, alguns dos ca quais s˜o novos no Fortran 90/95 e ser˜o abordados adiante. a a 1. Inicializa¸˜o de vetores contendo 3 elementos: ca INTEGER :: I INTEGER, DIMENSION(3) :: IA= (/1,2,3/), IB= (/(I, I=1,3)/) 2. Declara¸˜o da matriz autom´tica LOGB. Aqui, LOGA ´ uma matriz qualquer (“muda” ou “dummy”) e SIZE ca a e ´ uma fun¸˜o intr´ e ca ınseca que retorna um escalar inteiro correspondente ao tamanho do seu argumento: LOGICAL, DIMENSION(SIZE(LOGA)) :: LOGB 3. Declara¸ao das matrizes dinˆmicas, ou aloc´veis, de duas dimens˜es A e B. A forma das matrizes ser´ c˜ a a o a definida a posteriori por um comando ALLOCATE: REAL, DIMENSION(:,:), ALLOCATABLE :: A,B 4. Declara¸ao das matrizes de forma assumida de trˆs dimens˜es A e B. A forma das matrizes ser´ assumida c˜ e o a a partir das informa¸˜es transferidas pela rotina que aciona o sub-programa onde esta declara¸˜o ´ co ca e feita. REAL, DIMENSION(:,:,:) :: A,B Matrizes de tipos derivados. A capacidade de se misturar matrizes com defini¸˜es de tipos derivados co possibilita a constru¸˜o de objetos de complexidade crescente. Alguns exemplos ilustram estas possibilidades. ca Um tipo derivado pode conter um ou mais componentes que s˜o matrizes: a TYPE :: TRIPLETO REAL :: U REAL, DIMENSION(3) :: DU REAL, DIMENSION(3,3) :: D2U END TYPE TRIPLETO TYPE(TRIPLETO) :: T Este exemplo serve para declarar, em uma unica estrutura, um tipo de vari´vel denominado TRIPLETO, cujos ´ a componentes correspondem ao valor de uma fun¸˜o de 3 vari´veis, suas 3 derivadas parciais de primeira ca a ordem e suas 9 derivadas parciais de segunda ordem. Se a vari´vel T ´ do tipo TRIPLETO, T%U ´ um escalar a e e real, mas T%DU e T%D2U s˜o matrizes do tipo real. a ´ E poss´ agora realizar-se combina¸˜es entre matrizes e o tipo derivado TRIPLETO para se obter objetos ıvel co mais complexos. No exemplo abaixo, declara-se um vetor cujos elementos s˜o TRIPLETOs de diversas fun¸˜es a co distintas: TYPE(TRIPLETO), DIMENSION(10) :: V Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 56.
    48 6.1. Terminologia eespecifica¸˜es de matrizes co Assim, a referˆncia ao objeto V(2)%U fornece o valor da fun¸˜o correspondente ao segundo elemento do e ca vetor V; j´ a referˆncia V(5)%D2U(1,1) fornece o valor da derivada segunda em rela¸˜o ` primeira vari´vel a e ca a a da fun¸˜o correspondente ao elemento 5 do vetor V, e assim por diante. ca O primeiro programa a seguir exemplifica um uso simples de matrizes: ! D e c l a r a um v e t o r , d e f i n e v a l o r e s aos e l e m e n t o s do mesmo e imprime ! e s t e s v a l o r e s na t e l a . program e x 1 a r r a y i m p l i c i t none integer , parameter : : dp= s e l e c t e d r e a l k i n d ( 1 0 , 2 0 0 ) integer : : i real , dimension ( 1 0 ) : : vr r e a l ( kind= dp ) , dimension ( 1 0 ) : : vd ! do i= 1 , 1 0 vr ( i )= s q r t ( r e a l ( i ) ) vd ( i )= s q r t ( r e a l ( i ) ) end do print * , ”Raiz quadrada dos 10 p r i m e i r o s i n t e i r o s , em p r e c i s a o s i m p l e s : ” print * , vr ! Imprime t o d o s os componentes do v e t o r . print * , ” ” print * , ”Raiz quadrada dos 10 p r i m e i r o s i n t e i r o s , em p r e c i s a o dupla : ” print * , vd end program e x 1 a r r a y O segundo programa-exemplo, a seguir, est´ baseado no programa alunos, descrito na se¸˜o 3.8. Agora, a ca ser´ criado um vetor para armazenar os dados de um n´mero fixo de alunos e os resultados somente ser˜o a u a impressos ap´s a aquisi¸˜o de todos os dados. o ca ! Dados a c e r c a de a l u n o s usando t i p o d e r i v a d o . program a l u n o s v e t i m p l i c i t none integer : : i , n d i s c= 5 ! Mude e s t e v a l o r , c a s o s e j a maior . type : : a l u n o character ( len= 2 0 ) : : nome integer : : c o d i g o r e a l : : n1 , n2 , n3 , mf end type a l u n o type ( a l u n o ) , dimension ( 5 ) : : d i s c ! do i= 1 , n d i s c print * , ”Nome : ” read ”( a ) ” , d i s c ( i )%nome print * , ” c ´ d i g o : ” o read * , d i s c ( i )% c o d i g o print * , ”Notas : N1 , N2 , N3 : ” read * , d i s c ( i )%n1 , d i s c ( i )%n2 , d i s c ( i )%n3 d i s c ( i )%mf= ( d i s c ( i )%n1 + d i s c ( i )%n2 + d i s c ( i )%n3 ) / 3 . 0 end do do i= 1 , n d i s c print * , ” ” print * , ”−−−−−−−−−−−> ” , d i s c ( i )%nome , ” ( ” , d i s c ( i )%c o d i g o , ”) <−−−−−−−−−−−” print * , ” M´dia f i n a l : ” , d i s c ( i )%mf e end do end program a l u n o s v e t Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 57.
    Cap´ ıtulo 6. Processamentode Matrizes 6.2 49 Express˜es e atribui¸oes envolvendo matrizes o c˜ Com o Fortran 77 n˜o era poss´ desenvolver express˜es envolvendo o conjunto de todos os elemento de a ıvel o uma matriz simultaneamente. Ao inv´s disso, cada elemento da matriz deveria ser envolvido na express˜o e a separadamente, em um processo que com frequˆncia demandava o uso de diversos la¸os DO encadeados. e c Quando a opera¸˜o envolvia matrizes grandes, com 100 × 100 elementos ou mais, tais processos podiam ser ca extremamente dispendiosos do ponto de vista do tempo necess´rio para a realiza¸˜o de todas as opera¸˜es a ca co desejadas, pois os elementos da(s) matriz(es) deveriam ser manipulado de forma seq¨encial. Al´m disso, u e o c´digo tornava-se gradualmente mais complexo para ser lido e interpretado, ` medida que o n´mero de o a u opera¸˜es envolvidas aumentava. co Um desenvolvimento novo, introduzido no Fortran 90, ´ a sua habilidade de realizar opera¸˜es envolvendo e co a matriz na sua totalidade, possibilitando o tratamento de uma matriz como um objeto unico, o que, no ´ m´ ınimo, facilita enormemente a constru¸˜o, leitura e interpreta¸˜o do c´digo. Uma outra vantagem, ainda ca ca o mais importante, resulta deste novo modo de encarar matrizes. Com o desenvolvimento dos processadores e das arquiteturas de computadores, entraram em linha, recentemente, sistemas compostos por mais de um processador, os quais fazem uso da id´ia de processamento distribu´ ou, em outras palavras, processamento e ıdo paralelo. As normas definidas pelo comitˆ X3J3 para o padr˜o da linguagem Fortran 90/95 sup˜e que come a o piladores usados em sistemas distribu´ ıdos devem se encarregar de distribuir automaticamente os processos num´ricos envolvidos nas express˜es com matrizes de forma equilibrada entre os diversos processadores que e o comp˜e a arquitetura. A evidente vantagem nesta estrat´gia consiste no fato de que as mesmas opera¸˜es o e co num´ricas s˜o realizadas de forma simultˆnea em diversos componentes distintos das matrizes, acelerando e a a substancialmente a eficiˆncia do processamento. Com a filosofia das opera¸˜es sobre matrizes inteiras, a e co tarefa de implantar a paraleliza¸˜o do c´digo num´rico fica, essencialmente, a cargo do compilador e n˜o ca o e a do programador. Uma outra vantagem deste enfoque consiste na manuten¸˜o da portabilidade dos c´digos ca o num´ricos. e Para que as opera¸˜es envolvendo matrizes inteiras sejam poss´ co ıveis, ´ necess´rio que as matrizes consie a deradas sejam conform´veis, ou seja, elas devem todas ter a mesma forma. Opera¸˜es entre duas matrizes a co conform´veis s˜o realizadas na maneira elemental (distribuindo as opera¸˜es entre os diversos processadores, a a co se existirem) e todos os operadores num´ricos definidos para opera¸˜es entre escalares tamb´m s˜o definidos e co e a para opera¸oes entre matrizes. c˜ Por exemplo, sejam A e B duas matrizes 2 × 3: A= 348 566 521 331 , B= , o resultado da adi¸˜o de A por B ´: ca e A+B= 869 897 A*B = 15 8 8 15 18 6 A/B = 3/5 2 8 5/3 2 6 , o resultado da multiplica¸˜o ´: ca e e o resultado da divis˜o ´: a e . Se um dos operandos ´ um escalar, ent˜o este ´ distribu´ em uma matriz conform´vel com o outro e a e ıdo a operando. Assim, o resultado de adicionar 5 a A ´: e A+5= 348 566 + 555 555 = 8 9 13 10 11 11 . Esta distribui¸˜o de um escalar em uma matriz conform´vel ´ util no momento da inicializa¸˜o dos elementos ca a e´ ca de uma matriz. Da mesma forma como acontece com express˜es e atribui¸˜es escalares, em uma linha de programa¸˜o o co ca como a seguir, A= A + B sendo A e B matrizes, a express˜o do lado direito ´ desenvolvida antes da atribui¸˜o do resultado da expresa e ca s˜o ` matriz A. Este ordenamento ´ importante quando uma matriz aparece em ambos os lados de uma a a e atribui¸˜o, como no caso do exemplo acima. ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 58.
    50 6.2. Express˜es eatribui¸˜es envolvendo matrizes o co As vantagens do processamento de matrizes inteiras, presente no Fortran 90/95 mas ausente no Fortran 77, podem ser contempladas atrav´s da compara¸˜o de alguns exemplos de c´digos desenvolvidos em ambas e ca o as revis˜es da linguagem. Nestes c´digos ser˜o tamb´m apresentadas algumas fun¸˜es intr´ o o a e co ınsecas do Fortran 90/95 que operam em matrizes, elemento a elemento. Uma descri¸˜o completa das rotinas intr´ ca ınsecas ´ e apresentada no cap´ ıtulo 7. 1. Considere trˆs vetores, A, B e C, todos do mesmo comprimento. Inicialize todos os elementos de A a e zero e realize as atribui¸˜es A(I)= A(I)/3.1 + B(I)*SQRT(C(I)) para todos os valores de I co Solu¸˜o Fortran 77. ca REAL A(20), B(20), C(20) ... 10 ... 20 DO 10 I= 1, 20 A(I)= 0.0 CONTINUE DO 20 I= 1, 20 A(I)= A(I)/3.1 + B(I)*SQRT(C(I)) CONTINUE Solu¸˜o Fortran 90/95. ca REAL, DIMENSION(20) :: A= 0.0, B, C ... A= A/3.1 + B*SQRT(C) Note como o c´digo ficou mais reduzido e f´cil de ser lido. Al´m disso, a fun¸˜o intr´ o a e ca ınseca SQRT opera sobre cada elemento do vetor C. 2. Considere trˆs matrizes bi-dimensionais com a mesma forma. Multiplique duas matrizes entre si, e elemento a elemento, e atribua o resultado a uma terceira matriz. Solu¸˜o Fortran 77. ca REAL A(5,5), B(5,5), C(5,5) ... 10 20 DO 20 I= 1, 5 DO 10 J= 1, 5 C(J,I)= A(J,I) + B(J,I) CONTINUE CONTINUE Solu¸˜o Fortran 90/95. ca REAL, DIMENSION(5,5) :: A, B, C ... C= A + B 3. Considere uma matriz tri-dimensional. Encontre o maior valor menor que 1000 nesta matriz. Solu¸˜o Fortran 77. ca REAL A(5,5,5) REAL VAL_MAX ... VAL_MAX= DO 30 K= DO 20 DO 10 20 30 0.0 1, 5 J= 1, 5 10 I= 1, 5 IF((A(I,J,K) .GT. VAL_MAX) .AND. & (A(I,J,K) .LT. 1000.0))VAL_MAX= A(I,J,K) CONTINUE CONTINUE CONTINUE Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 59.
    Cap´ ıtulo 6. Processamentode Matrizes 51 Solu¸˜o Fortran 90/95. ca REAL, DIMENSION(5,5,5) :: A REAL :: VAL_MAX ... VAL_MAX= MAXVAL(A, MASK=(A<1000.0)) Note que no Fortran 95 conseguiu-se fazer em uma linha o que necessitou de 8 linhas no Fortran 77. A fun¸˜o intr´ ca ınseca MAXVAL devolve o valor m´ximo entre os elementos de uma matriz. O argumento a opcional MASK=(...) estabelece uma m´scara, isto ´, uma express˜o l´gica envolvendo a(s) matriz(es). a e a o Em MASK=(A<1000.0), somente aqueles elementos de A que satisfazem a condi¸˜o de ser menores que ca 1000 s˜o levados em considera¸˜o. a ca 4. Encontre o valor m´dio dos elementos maiores que 3000 na matriz A do exemplo anterior. e Solu¸˜o Fortran 77. ca REAL A(5,5,5) REAL MEDIA,ACUM INTEGER CONTA ... ACUM= 0.0 CONTA= 0 DO 30 K= 1, 5 DO 20 J= 1, 5 DO 10 I= 1, 5 IF(A(I,J,K) .GT. 3000.0)THEN ACUM= ACUM + A(I,J,K) CONTA= CONTA + 1 END IF 10 CONTINUE 20 CONTINUE 30 CONTINUE MEDIA= ACUM/REAL(CONTA) Solu¸˜o Fortran 90/95. ca REAL, DIMENSION(5,5,5) :: A REAL :: MEDIA ... MEDIA= SUM(A,MASK=(A>3000.0))/COUNT(MASK=(A>3000.0)) Agora, conseguiu-se realizar em uma linha de c´digo em Fortran 90 o que necessitou de 13 linhas em o Fortran 77. Os ultimos dois exemplos fizeram uso das seguintes fun¸˜es intr´ ´ co ınsecas (ver se¸˜o 7.12): ca MAXVAL - retorna o valor m´ximo de uma matriz. a SUM - retorna a soma de todos os elementos de uma matriz. COUNT - retorna o n´mero de elementos da matriz que satisfazem a m´scara. u a 6.3 Se¸˜es de matrizes co Uma sub-matriz, tamb´m chamada se¸˜o de matriz, pode ser acessada atrav´s da especifica¸˜o de um e ca e ca intervalo de valores de subscritos da matriz. Uma se¸˜o de matriz pode ser acessada e operada da mesma ca forma que a matriz completa, mas n˜o ´ poss´ a e ıvel fazer-se referˆncia direta a elementos individuais ou a e subse¸˜es da se¸˜o. co ca Se¸˜es de matrizes podem ser extra´ co ıdas usando-se um dos seguintes artif´ ıcios: ˆ Um subscrito simples. ˆ Um tripleto de subscritos. ˆ Um vetor de subscritos. Estes recursos ser˜o descritos a seguir. a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 60.
    52 6.3. Se¸˜es dematrizes co 6.3.1 Subscritos simples Um subscrito simples seleciona um unico elemento da matriz. Considere a seguinte matriz 5 × 5, deno´ minada RA. Ent˜o o elemento X pode ser selecionado atrav´s de RA(2,2): a e   00000 0 X 0 0 0   RA =  0 0 0 0 0  =⇒ RA(2, 2) = X.   0 0 0 0 0 00000 6.3.2 Tripleto de subscritos A forma de um tripleto de subscritos ´ a seguinte, sendo esta forma geral v´lida para todas as dimens˜es e a o definidas para a matriz: [<limite inferior>] : [<limite superior>] : [<passo>] Se um dos limites, inferior ou superior (ou ambos) for omitido, ent˜o o limite ausente ´ assumido como o a e limite inferior ou superior da correspondente dimens˜o da matriz da qual a se¸˜o est´ sendo extra´ a ca a ıda; se o <passo> for omitido, ent˜o assume-se <passo>=1. a Os exemplos a seguir ilustram v´rias se¸˜es de matrizes usando-se tripletos. Os elementos das matrizes a co marcados por X denotam a se¸˜o a ser extra´ ca ıda. Novamente, no exemplo ser´ utilizada a matriz 5 × 5 a denominada RA.   00000   0 X 0 0 0   RA =  0 0 0 0 0  =⇒RA(2:2,2:2) = X; Elemento simples, escalar, forma: (/1/).     0 0 0 0 0 00000   00000   0 0 0 0 0   RA =  0 0 X X X  =⇒RA(3,3:5); se¸˜o de linha da matriz, forma: (/3/). ca     0 0 0 0 0 00000   00X00   0 0 X 0 0   RA =  0 0 X 0 0  =⇒RA(:,3); coluna inteira, forma: (/5/).     0 0 X 0 0 00X00   0XXX0 0 0 0 0 0   RA =  0 X X X 0  =⇒RA(1::2,2:4); se¸˜es de linhas com passo 2, forma: (/3,3/). co   0 0 0 0 0 0XXX0 6.3.3 Vetores de subscritos Um vetor de subscritos ´ uma express˜o inteira de posto 1, isto ´, um vetor. Cada elemento desta e a e express˜o deve ser definido com valores que se encontrem dentro dos limites dos subscritos da matriz-m˜e. a a Os elementos de um vetor de subscritos podem estar em qualquer ordem. Um exemplo ilustrando o uso de um vetor de subscritos, denominado IV, ´ dado a seguir: e REAL, DIMENSION(6) :: REAL, DIMENSION(3) :: INTEGER, DIMENSION(3) RB= RA(IV) ! IV ´ o e RA= (/ 1.2, 3.4, 3.0, 11.2, 1.0, 3.7 /) RB :: IV= (/ 1, 3, 5 /) ! Express~o inteira de posto 1. a vetor de subscritos. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 61.
    Cap´ ıtulo 6. Processamentode Matrizes 53 ! Resulta: !RB= (/ RA(1), RA(3), RA(5) /), ou !RB= (/ 1.2, 3.0, 1.0 /). Um vetor de subscritos pode tamb´m estar do lado esquerdo de uma atribui¸˜o: e ca IV= (/ 1, 3, 5 /) RA(IV)= (/ 1.2, 3.4, 5.6 /) !Atribui¸~es dos elementos 1, 3 e 5 de RA. co ! Resulta: ! RA(1)= 1.2; RA(3)= 3.4; RA(5)= 5.6 ! Os elementos 2, 4 e 6 de RA n~o foram definidos. a 6.4 Atribui¸oes de matrizes e sub-matrizes c˜ Tanto matrizes inteiras quanto se¸˜es de matrizes podem ser usadas como operandos (isto ´, podem co e estar tanto no lado esquerdo quanto do lado direito de uma atribui¸˜o) desde que todos os operandos sejam ca conform´veis (p´gina 46). Por exemplo, a a REAL, DIMENSION(5,5) :: RA, RB, RC INTEGER :: ID ... RA= RB + RC*ID !Forma (/5,5/). ... RA(3:5,3:4)= RB(1::2,3:5:2) + RC(1:3,1:2) !Forma (/3,2/): !RA(3,3)= RB(1,3) + RC(1,1) !RA(4,3)= RB(3,3) + RC(2,1) !RA(5,3)= RB(5,3) + RC(3,1) !RA(3,4)= RB(1,5) + RC(1,2) !etc. ... RA(:,1)= RB(:,1) + RB(:,2) + RC(:3) !Forma (/5/). Um outro exemplo, acompanhado de figura, torna a opera¸˜o com sub-matrizes conform´veis mais clara. ca a REAL, DIMENSION(10,20) :: A,B REAL, DIMENSION(8,6) :: C ... C= A(2:9,5:10) + B(1:8,15:20) !Forma (/8,6/). ... A figura 6.1 ilustra como as duas sub-matrizes s˜o conform´veis neste caso e o resultado da soma das duas a a se¸˜es ser´ atribu´ ` matriz C, a qual possui a mesma forma. co a ıdo a O programa-exemplo 6.1 mostra algumas opera¸˜es e atribui¸˜es b´sicas de matrizes: co co a 6.5 Matrizes de tamanho zero Matrizes de tamanho zero, ou matrizes nulas tamb´m s˜o permitidas em Fortran 90/95. A no¸˜o de e a ca uma matriz nula ´ util quando se quer contar com a possibilidade de existˆncia de uma matriz sem nenhum e´ e elemento, o que pode simplificar a programa¸˜o do c´digo em certas situa¸˜es. Uma matriz ´ nula quando ca o co e o limite inferior de uma ou mais de suas dimens˜es ´ maior que o limite superior. o e Por exemplo, o c´digo abaixo resolve um sistema linear de equa¸˜es que j´ est˜o na forma triangular: o co a a 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) END DO Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 62.
    54 6.5. Matrizes detamanho zero A(1,20) A(1,1) A(2,5) A(2,10) A(9,5) A(9,10) Resultado A(10,1) A(20,20) + B(1,1) B(1,15) = 8x6 B(1,20) B(8,15) B(10,1) B(20,20) Figura 6.1: A soma de duas se¸oes de matrizes conform´veis. c˜ a Quando I assume o valor N, as sub-matrizes B(N+1:N) e A(N+1:N,N) se tornam nulas. Se esta possibilidade n˜o existisse, seria necess´ria a inclus˜o de linhas adicionais de programa¸˜o. a a a ca As matrizes nulas seguem as mesmas regras de opera¸˜o e atribui¸˜o que as matrizes usuais, por´m elas ca ca e ainda devem ser conform´veis com as matrizes restantes. Por exemplo, duas matrizes nulas podem ter o a mesmo posto mas formas distintas; as formas podem ser (/2,0/) e (/0,2/). Neste caso, estas matrizes n˜o a s˜o conform´veis. Contudo, uma matriz ´ sempre conform´vel com um escalar, assim a atribui¸˜o a a e a ca Programa 6.1: Express˜es e atribui¸oes envolvendo matrizes. o c˜ program t e s t a a t r m a t r i m p l i c i t none real , dimension ( 3 , 3 ) : : a real , dimension ( 2 , 2 ) : : b integer : : i , j ! do i= 1 , 3 do j= 1 , 3 a ( i , j )= s i n ( r e a l ( i ) ) + c o s ( r e a l ( j ) ) end do end do b= a ( 1 : 2 , 1 : 3 : 2 ) print * , ”Matriz A: ” print ” ( 3 ( f 1 2 . 5 ) ) ” , ( ( a ( i , j ) , j= 1 , 3 ) , i= 1 , 3 ) Print * , ”Matriz B : ” print ” ( 2 ( f 1 2 . 5 ) ) ” , ( ( b ( i , j ) , j= 1 , 2 ) , i= 1 , 2 ) end program t e s t a a t r m a t r Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 63.
    Cap´ ıtulo 6. Processamentode Matrizes 55 <matriz nula>= <escalar> ´ sempre v´lida. e a 6.6 Construtores de matrizes Um construtor de matrizes cria um vetor (matriz de posto 1) contendo valores constantes. Estes construtores servem, por exemplo, para inicializar os elementos de um vetor, como foi exemplificado na p´gina a 47. Outro exemplo de uso dos construtores de matrizes est´ na defini¸˜o de um vetor de subscritos, como a ca foi abordado na se¸˜o 6.3.3. ca A forma geral de um construtor de matrizes ´ a seguinte: e (/ <lista de valores do construtor> /) onde <lista de valores do construtor> pode ser tanto uma lista de constantes, como no exemplo IV= (/ 1, 3, 5 /) como pode ser um conjunto de express˜es num´ricas: o e A= (/ I+J, 2*I, 2*J, I**2, J**2, SIN(REAL(I)), COS(REAL(J)) /) ou ainda um comando DO impl´ ıcito no construtor, cuja forma geral ´ a seguinte: e (<lista de valores do construtor>, <vari´vel>= <exp1>, <exp2>, [<exp3>]) a onde <vari´vel> ´ uma vari´vel escalar inteira e <exp1>, <exp2> e <exp3> s˜o express˜es escalares inteiras. a e a a o A interpreta¸˜o dada a este DO impl´ ca ıcito ´ que a <lista de valores dos construtor> ´ escrita um n´mero e e u de vezes igual a MAX((<exp2> - <exp1> + <exp3>)/<exp3>, 0) sendo a <vari´vel> substitu´ por <exp1>, <exp1> + <exp3>, ..., <exp2>, como acontece no construto DO a ıda (se¸˜o 5.3). Tamb´m ´ poss´ encadear-se DO’s impl´ ca e e ıvel ıcitos. A seguir, alguns exemplos s˜o apresentados: a (/ (i, i= 1,6) /) ! Resulta: (/ 1, 2, 3, 4, 5, 6 /) (/ 7, (i, i= 1,4), 9 /) ! Resulta: (/ 7, 1, 2, 3, 4, 9 /) (/ (1.0/REAL(I), I= 1,6) /) ! Resulta: (/ 1.0/1.0, 1.0/2.0, 1.0/3.0, 1.0/4.0, 1.0/5.0, 1.0/6.0 /) ! DO’s impl´citos encadeados: ı (/ ((I, I= 1,3), J= 1,3) /) ! Resulta: (/ 1, 2, 3, 1, 2, 3, 1, 2, 3 /) (/ ((I+J, I= 1,3), J= 1,2) /) ! = (/ ((1+J, 2+J, 3+J), J= 1,2) /) ! Resulta: (/ 2, 3, 4, 3, 4, 5 /) Um construtor de matrizes pode tamb´m ser criado usando-se tripletos de subscritos: e (/ A(I,2:4), A(1:5:2,I+3) /) ! Resulta: (/ A(I,2), A(I,3), A(I,4), A(1,I+3), A(3,I+3), A(5,I+3) /) Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 64.
    56 6.6. Construtores dematrizes B(1,1) B(1,1) B(1,3) B(1,4) B(2,1) B(2,2) B(2,3) B(2,4) B(3,1) B(3,2) B(3,3) B(3,4) B(4,1) B(4,2) B(4,3) B(4,4) B(5,1) B(5,2) B(5,3) B(5,4) Figura 6.2: O ordenamento dos elementos da matriz B(5,4). 6.6.1 A fun¸˜o intr´ ca ınseca RESHAPE. Uma matriz de posto maior que um pode ser constru´ a partir de um construtor de matrizes atrav´s ıda e do uso da fun¸˜o intr´ ca ınseca RESHAPE. Por exemplo, RESHAPE( SOURCE= (/ 1, 2, 3, 4, 5, 6 /), SHAPE= (/ 2, 3 /) ) gera a matriz de posto 2: 135 246 a qual ´ uma matriz de forma (/ 2, 3 /), isto ´, 2 linhas e 3 colunas. Um outro exemplo seria: e e REAL, DIMENSION(3,2) :: RA RA= RESHAPE( SOURCE= (/ ((I+J, I= 1,3), J= 1,2) /), SHAPE= (/ 3,2 /) ) de onde resulta   23 RA =  3 4  45 Usando a fun¸˜o RESHAPE, o programa-exemplo da p´gina 53 apresenta uma forma mais concisa: ca a program t e s t a a t r m a t r i m p l i c i t none real , dimension ( 3 , 3 ) : : a real , dimension ( 2 , 2 ) : : b integer : : i , j ! a= r e s h a p e ( s o u r c e= ( / ( ( s i n ( r e a l ( i ))+ c o s ( r e a l ( j ) ) , i= 1 , 3 ) , j= 1 , 3 ) / ) , & shape= ( / 3 , 3 / ) ) b= a ( 1 : 2 , 1 : 3 : 2 ) print * , ”Matriz A: ” print ” ( 3 ( f 1 2 . 5 ) ) ” , ( ( a ( i , j ) , j= 1 , 3 ) , i= 1 , 3 ) Print * , ”Matriz B : ” print ” ( 2 ( f 1 2 . 5 ) ) ” , ( ( b ( i , j ) , j= 1 , 2 ) , i= 1 , 2 ) end program t e s t a a t r m a t r 6.6.2 A ordem dos elementos de matrizes A maneira como a fun¸˜o RESHAPE organizou os elementos das matrizes na se¸˜o 6.6.1 seguiu a denoca ca minada ordem dos elementos de matriz, a qual ´ a maneira como a maioria dos compiladores de Fortran e armazena os elementos de matrizes em espa¸os cont´ c ıguos de mem´ria. Este ordenamento ´ obtido variandoo e se inicialmente o ´ ındice da primeira dimens˜o da matriz, depois variando-se o ´ a ındice da segunda dimens˜o e a assim por diante. Em uma matriz com 2 dimens˜es isto ´ obtido variando-se inicialmente as linhas e depois o e as colunas. A figura 6.2 ilustra este procedimento com a matriz B(5,4). Em uma matriz com mais de 2 dimens˜es, o ordenamento ´ realizado da mesma maneira. Assim, dada o e a matriz Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 65.
    Cap´ ıtulo 6. Processamentode Matrizes 57 REAL, DIMENSION(-10:5, -20:1, 0:1, -1:0, 2, 2, 2) :: G o ordenamento segue a ordem: G(-10,-20,0,-1,1,1,1) → G(-9,-20,0,-1,1,1,1) → G(-8,-20,0,-1,1,1,1) →...→ G(5,-20,0,-1,1,1,1) → G(-10,-19,0,-1,1,1,1) → G(-9,-19,0,-1,1,1,1) → G(-8,-19,0,-1,1,1,1) →...→ G(5,-19,0,-1,1,1,1) → G(-10,-18,0,-1,1,1,1) → → G(-8,-15,0,-1,1,1,1) →...→ G(5,1,1,0,2,2,1) → G(-10,1,1,0,2,2,2) → G(-9,1,1,0,2,2,2) → →...→ G(5,1,1,0,2,2,2) ... ... Em muitas situa¸˜es, ´ mais r´pido escrever-se um c´digo que processa matrizes seguindo o ordenamento co e a o dos elementos. As fun¸˜es intr´ co ınsecas do Fortran 90/95 que manipulam matrizes inteiras foram concebidas de forma a levar em conta este fato. 6.7 Rotinas intr´ ınsecas elementais aplic´veis a matrizes a O Fortran 90/95 permite a existˆncia de rotinas (fun¸˜es ou subrotinas) intr´ e co ınsecas elementais, isto ´, e rotinas que se aplicam a cada elemento de uma matriz. Matrizes podem, ent˜o, ser usadas como argumentos a de rotinas intr´ ınsecas, da mesma forma que escalares. Este tipo de recurso n˜o existem no Fortran 77. a As opera¸˜es definidas na rotina intr´ co ınseca ser˜o aplicadas a cada elemento da matriz separadamente. a Novamente, caso mais de uma matriz apare¸a no argumento da rotina, estas devem ser conform´veis. c a A seguir, alguns exemplos de rotinas intr´ ınsecas elementais. A lista completa destas rotinas pode ser obtida no cap´ ıtulo 7. 1. Calcule as ra´ quadradas de todos os elementos da matriz A. O resultado ser´ atribu´ ` matriz B, ızes a ıdo a a qual ´ conform´vel com A. e a REAL, DIMENSION(10,10) :: A, B ... B= SQRT(A) 2. Calcule a exponencial de todos os argumentos da matriz A. Novamente, o resultado ser´ atribu´ a a ıdo B. COMPLEX, DIMENSION(5,-5:15, 25:125) :: A, B ... B= EXP(A) 3. Encontre o comprimento da string (vari´vel de caractere) excluindo brancos no final da vari´vel para a a todos os elementos da matriz CH. CHARACTER(LEN= 80), DIMENSION(10) :: CH INTEGER :: COMP ... COMP= LEN_TRIM(CH) 6.8 Comando e construto WHERE Em muitas situa¸˜es, ´ desej´vel realizar-se opera¸˜es somente para alguns elementos de uma matriz; co e a co por exemplo, somente para aqueles elementos que s˜o positivos. a 6.8.1 Comando WHERE O comando WHERE fornece esta possibilidade. Um exemplo simples ´: e REAL, DIMENSION(10,10) :: A ... WHERE (A > 0.0) A= 1.0/A o qual fornece a rec´ ıproca (inversa) de todos os elementos positivos de A, deixando os demais inalterados. A forma geral do comando ´ e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 66.
    58 6.8. Comando econstruto WHERE WHERE (<express~o l´gica matriz>) <vari´vel matriz>= <express~o matriz> a o a a A <express~o l´gica matriz> deve ter a mesma forma que a <vari´vel matriz>. A express˜o l´gica ´ a o a a o e desenvolvida inicialmente e ent˜o somente aqueles elementos da <vari´vel matriz> que satisfazem o teste a a l´gico s˜o operados pela <express~o matriz>. Os restantes permanecem inalterados. o a a 6.8.2 Construto WHERE Uma unica express˜o l´gica de matriz pode ser usada para determinar uma seq¨ˆncia de opera¸˜es e ´ a o ue co atribui¸˜es em matrizes, todas com a mesma forma. A sintaxe deste construto ´: co e WHERE (<express~o l´gica matriz>) a o <opera¸~es atribui¸~es matrizes> co co END WHERE Inicialmente, a <express~o l´gica matriz> ´ desenvolvida em cada elemento da matriz, resultando em a o e uma matriz l´gica tempor´ria, cujos elementos s˜o os resultados da <express~o l´gica matriz>. Ent˜o, o a a a o a cada opera¸˜o e atribui¸˜o de matriz no bloco do construto ´ executada sob o controle da m´scara deterca ca e a minada pela matriz l´gica tempor´ria; isto ´, as <opera¸~es atribui¸~es matrizes> ser˜o realizadas em o a e co co a cada elemento das matrizes do bloco que corresponda ao valor .TRUE. da matriz l´gica tempor´ria. o a Existe tamb´m uma forma mais geral do construto WHERE que permite a execu¸˜o de atribui¸˜es a e ca co elementos de matrizes que n˜o satisfazem o teste l´gico no cabe¸alho: a o c WHERE (<express~o l´gica matriz>) a o <opera¸~es atribui¸~es matrizes 1> co co ELSEWHERE <opera¸~es atribui¸~es matrizes 2> co co END WHERE O bloco <opera¸~es atribui¸~es matrizes 1> ´ executado novamente sob o controle da m´scara defico co e a nida na <express~o l´gica matriz> e somente elementos que satisfazem esta m´scara s˜o afetados. Em a o a a seguida, as <opera¸~es atribui¸~es matrizes 2> s˜o executadas sob o controle da m´scara definida por co co a a .NOT. <express~o l´gica matriz>, isto ´, novas atribui¸˜es s˜o realizadas sobre elementos que n˜o satisa o e co a a fazem o teste l´gico definido no cabe¸alho. o c Um exemplo simples do construto WHERE ´: e WHERE (PRESSURE <= 1.0) PRESSURE= PRESSURE + INC_PRESSURE TEMP= TEMP + 5.0 ELSEWHERE RAINING= .TRUE. END WHERE Neste exemplo, PRESSURE, INC_PRESSURE, TEMP e RAINING s˜o todas matrizes com a mesma forma, embora a n˜o do mesmo tipo. a O programa-exemplo 6.2 mostra outra aplica¸˜o do construto WHERE. ca Um recurso ausente no Fortran 90 mas incorporado no Fortran 95 ´ o mascaramento na instru¸˜o e ca ELSEWHERE, juntamente com a possibilidade de conter qualquer n´mero de instru¸˜es ELSEWHERE mascaradas u co mas, no m´ximo, uma instru¸˜o ELSEWHERE sem m´scara, a qual deve ser a ultima. Todas as express˜es a ca a ´ o l´gicas que definem as m´scaras devem ter a mesma forma. Adicionalmente, os construtos WHERE podem ser o a encadeados e nomeados; neste caso, as condi¸˜es l´gicas de todas as m´scaras devem ter a mesma forma. O co o a seguinte exemplo ilustra este recurso: ATRIB1: WHERE (<cond 1>) <corpo 1> !Mascarado por <cond 1> ELSEWHERE (<cond 2>) ATRIB1 <corpo 2> !Masc. por <cond 2> .AND. .NOT. <cond 1> ATRIB2: WHERE (<cond 4>) <corpo 4> !Masc. por <cond 2> .AND. .NOT. <cond 1> .AND. <cond 4> ELSEWHERE ATRIB2 Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 67.
    Cap´ ıtulo 6. Processamentode Matrizes 59 Programa 6.2: Exemplo do construto WHERE. program t e s t a w h e r e i m p l i c i t none real , dimension ( 3 , 3 ) : : a integer : : i , j ! a= r e s h a p e ( s o u r c e= ( / ( ( s i n ( r e a l ( i+j ) ) , i= 1 , 3 ) , j= 1 , 3 ) / ) , shape= ( / 3 , 3 / ) ) print * , ”Matriz A o r i g i n a l : ” print * , a ( 1 , : ) print * , a ( 2 , : ) print * , a ( 3 , : ) ! where ( a >= 0 . 0 ) a= s q r t ( a ) elsewhere a= a ** 2 end where print * , ”Matriz A m o d i f i c a d a : ” print * , a ( 1 , : ) print * , a ( 2 , : ) print * , a ( 3 , : ) end program t e s t a w h e r e <corpo 5> !Masc. por ... ! .AND. END WHERE ATRIB2 ... ELSEWHERE (<cond 3>) ATRIB1 <corpo 3> !Masc. por ... ! .AND. ELSEWHERE ATRIB1 <corpo 6> !Masc. por ... ! .AND. END WHERE ATRIB1 6.9 <cond 2> .AND. .NOT. <cond 1> .NOT. <cond 4> <cond 3> .AND. .NOT. <cond 1> .NOT. <cond 2> .NOT. <cond 1> .AND. .NOT. <cond 2> .NOT. <cond 3> Matrizes aloc´veis a Uma novidade importante introduzida no Fortran 90/95 ´ a habilidade de se declarar vari´veis dinˆmicas; e a a em particular, matrizes dinˆmicas. Fortran 90 fornece tanto matrizes aloc´veis quanto matrizes autom´ticas, a a a ambos os tipos sendo matrizes dinˆmicas. Usando matrizes aloc´veis, ´ poss´ alocar e de-alocar espa¸o de a a e ıvel c mem´ria conforme necess´rio. O recurso de matrizes autom´ticas permite que matrizes locais em uma fun¸˜o o a a ca ou subrotina tenham forma e tamanho diferentes cada vez que a rotina ´ invocada. Matrizes autom´ticas e a s˜o discutidas no cap´ a ıtulo 8. Matrizes aloc´veis permitem que grandes fra¸˜es da mem´ria do computador sejam usadas somente a co o quando requerido e, posteriormente, liberadas, quando n˜o mais necess´rias. Este recurso oferece um uso de a a mem´ria muito mais eficiente que o Fortran 77, o qual oferecia somente aloca¸˜o est´tica (fixa) de mem´ria. o ca a o Al´m disso, o c´digo torna-se muito mais robusto, pois a forma e o tamanho das matrizes podem ser decididos e o durante o processamento do c´digo. o Uma matriz aloc´vel ´ declarada na linha de declara¸˜o de tipo de vari´vel com o atributo ALLOCATABLE. a e ca a O posto da matriz deve tamb´m ser declarado com a inclus˜o dos s´ e a ımbolos de dois pontos “:”, um para cada dimens˜o da matriz. Por exemplo, a matriz de duas dimens˜es A ´ declarada como aloc´vel atrav´s da a o e a e declara¸˜o: ca REAL, DIMENSION(:,:), ALLOCATABLE :: A Esta forma de declara¸˜o n˜o aloca espa¸o de mem´ria imediatamente ` matriz, como acontece com as ca a c o a declara¸˜es usuais de matrizes. O status da matriz nesta situa¸˜o ´ not currently allocated, isto ´, correnco ca e e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 68.
    60 6.9. Matrizes aloc´veis a tementen˜o alocada. Espa¸o de mem´ria ´ dinamicamente alocado durante a execu¸˜o do programa, logo a c o e ca antes da matriz ser utilizada, usando-se o comando ALLOCATE. Este comando especifica os limites da matriz, seguindo as mesmas regras definidas na se¸˜o 6.1. A seguir s˜o dados dois exemplos de uso deste comando: ca a ALLOCATE (A(0:N,M)) ou usando express˜es inteiras: o ALLOCATE (A(0:N+1,M)) Como se pode ver, esta estrat´gia confere uma flexibilidade grande na defini¸˜o de matrizes ao programador. e ca O espa¸o alocado ` matriz com o comando ALLOCATE pode, mais tarde, ser liberado com o comando c a DEALLOCATE. Este comando requer somente nome da matriz previamente alocada. Por exemplo, para liberar o espa¸o na mem´ria reservado para a matriz A, o comando fica c o DEALLOCATE (A) Tanto os comandos ALLOCATE e DEALLOCATE possuem o especificador opcional STAT, o qual retorna o status do comando de aloca¸˜o ou de-aloca¸˜o. Neste caso, a forma geral do comando ´: ca ca e ALLOCATE (<lista de objetos alocados> [, STAT= <status>]) DEALLOCATE (<lista de objetos alocados> [, STAT= <status>]) onde <status> ´ uma vari´vel inteira escalar. Se STAT= est´ presente no comando, <status> recebe o valor e a a zero se o procedimento do comando ALLOCATE/DEALLOCATE foi bem sucedido ou um valor positivo se houve um erro no processo. Se o especificador STAT= n˜o estiver presente e ocorra um erro no processo, o programa a ´ abortado. Finalmente, ´ poss´ e e ıvel alocar-se ou de-alocar-se mais de uma matriz simultaneamente, como indica a <lista de objetos alocados>. Um breve exemplo do uso destes comandos seria: REAL, DIMENSION(:), ALLOCATABLE :: A, B REAL, DIMENSION(:,:), ALLOCATABLE :: C INTEGER :: N ... ALLOCATE (A(N), B(2*N), C(N,2*N)) B(:N)= A B(N+1:)= SQRT(A) DO I= 1,N C(I,:)= B END DO DEALLOCATE (A, B, C) Matrizes aloc´veis tornam poss´ a ıvel o requerimento freq¨ente de declarar uma matriz tendo um n´mero u u vari´vel de elementos. Por exemplo, pode ser necess´rio ler vari´veis, digamos tam1 e tam2 e ent˜o declarar a a a a uma matriz com tam1 × tam2 elementos: INTEGER :: TAM1, TAM2 REAL, DIMENSION (:,:), ALLOCATABLE :: A INTEGER :: STATUS ... READ*, TAM1, TAM2 ALLOCATE (A(TAM1,TAM2), STAT= STATUS) IF (STATUS > 0)THEN ... ! Comandos de processamento de erro. END IF ... ! Uso da matriz A. DEALLOCATE (A) ... No exemplo acima, o uso do especificador STAT= permite que se tome providˆncias caso n˜o seja poss´ e a ıvel alocar a matriz, por alguma raz˜o. a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 69.
    Cap´ ıtulo 6. Processamentode Matrizes 61 Como foi mencionado anteriormente, uma matriz aloc´vel possui um status de aloca¸˜o. Quando a matriz a ca ´ declarada, mas ainda n˜o alocada, o seu status ´ unallocated ou not currently allocated. Quando a matriz e a e aparece no comando ALLOCATE, o seu status passa a allocated ; uma vez que ela ´ de-alocada, o seu status e retorna a not currently allocated. Assim, o comando ALLOCATE somente pode ser usado em matrizes n˜o a correntemente alocadas, ao passo que o comando DEALLOCATE somente pode ser usado em matrizes alocadas; caso contr´rio, ocorre um erro. a ´ E poss´ ıvel verificar se uma matriz est´ ou n˜o correntemente alocada usando-se a fun¸˜o intr´ a a ca ınseca ALLOCATED. Esta ´ uma fun¸˜o l´gica com um argumento, o qual deve ser o nome de uma matriz aloc´vel. e ca o a Usando-se esta fun¸˜o, comandos como os seguintes s˜o poss´ ca a ıveis: IF (ALLOCATED(A)) DEALLOCATE (A) ou IF (.NOT. ALLOCATED(A)) ALLOCATE (A(5,20)) Um terceiro status de aloca¸˜o, poss´ no Fortran 90 mas n˜o no Fortran 95, ´ o undefined, o qual ocorria ca ıvel a e quando uma matriz era alocada dentro de uma rotina e n˜o era de-alocada antes de retornar ao programa a que chamou a rotina. O que ocorria era que em subseq¨entes chamadas desta rotina a matriz com o status u undefined n˜o mais podia ser utilizada. No Fortran 95, todas as matrizes aloc´veis definidas em rotinas s˜o a a a automaticamente colocadas no status unallocated quando da sa´ da rotina. Contudo, um boa pr´tica de ıda a programa¸˜o consiste em sempre de-alocar todas as matrizes alocadas dentro de uma rotina. ca Finalmente, h´ trˆs restri¸˜es no uso de matrizes aloc´veis: a e co a 1. Matrizes aloc´veis n˜o podem ser argumentos mudos de uma rotina e devem, portanto, ser alocadas e a a de-alocadas dentro da mesma unidade de programa (ver cap´ ıtulo 8). 2. O resultado de uma fun¸˜o n˜o pode ser uma matriz aloc´vel (embora possa ser uma matriz). ca a a 3. Matrizes aloc´veis n˜o podem ser usadas na defini¸˜o de um tipo derivado (esta restri¸˜o foi retirada a a ca ca no Fortran 2003. O programa-exemplo a seguir ilustra o uso de matrizes aloc´veis. a program t e s t a a l o c i m p l i c i t none integer , dimension ( : , : ) , a l l o c a t a b l e : : b integer : : i , j , n= 2 ! print * , ”Valor i n i c i a l de n : ” , n allocate (b(n , n )) b= n print * , ”Valor i n i c i a l de B : ” print ” ( 2 ( i 2 ) ) ” , ( ( b ( i , j ) , j= 1 , n ) , i= 1 , n ) deallocate ( b ) n= n + 1 print * , ”Segundo v a l o r de n : ” , n allocate (b(n , n )) b= n print * , ”Segundo v a l o r de B : ” print ” ( 3 ( i 2 ) ) ” , ( ( b ( i , j ) , j= 1 , n ) , i= 1 , n ) deallocate ( b ) n= n + 1 print * , ” T e r c e i r o v a l o r de n : ” , n a l l o c a t e ( b ( n+1,n+1)) b= n + 1 print * , ” T e r c e i r o v a l o r de B : ” print ” ( 5 ( i 2 ) ) ” , ( ( b ( i , j ) , j= 1 , n+1) , i= 1 , n+1) end program t e s t a a l o c Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 70.
    62 6.10. Comando econstruto FORALL 6.10 Comando e construto FORALL Quando um construto DO como o seguinte: DO I= 1, N A(I,I)= X(I) END DO !A tem posto 2 e X tem posto 1. ´ executado, o processador deve realizar cada itera¸˜o sucessiva em ordem, com uma atribui¸˜o ap´s a e ca ca o outra. Isto representa um impedimento severo na otimiza¸˜o do c´digo em uma plataforma paralelizada. ca o Este problema foi enfocado com a constru¸ao do HPF (High Performance Fortran), o qual consiste em c˜ uma vers˜o do Fortran 90 destinada a sistemas de computa¸˜o paralela. Posteriormente, alguns avan¸os a ca c realizados pelo HPF, em rela¸˜o ao Fortran 90, foram incorporados do padr˜o do Fortran 95; entre eles, ca a a instru¸˜o FORALL. A id´ia ´ oferecer ao programador uma estrutura que possibilite os mesmos recursos ca e e obtidos com la¸os DO, por´m que sejam automaticamente paraleliz´veis, quando o programa estiver rodando c e a em uma plataforma paralela. 6.10.1 Comando FORALL As instru¸˜es do exemplo acima s˜o implementadas atrav´s de um comando FORALL da seguinte maneira: co a e FORALL (I= 1:N) A(I,I)= X(I) a qual especifica que as atribui¸˜es individuais sejam realizadas em qualquer ordem, inclusive simultaneaco mente, caso o programa rode em uma plataforma paralela. O comando FORALL pode ser visto como uma atribui¸˜o de matrizes expressa com a ajuda de ´ ca ındices. Neste exemplo em particular, deve-se notar que as atribui¸˜es n˜o poderiam ser representadas de maneira simples atrav´s de uma atribui¸˜o de matrizes co a e ca inteiras, tal como A= X, porque as matrizes A e X n˜o tˆm a mesma forma. Outros exemplos do comando a e s˜o: a FORALL (I= 1:N, J= 1:M) A(I,J)= I + J FORALL (I= 1:N, J= 1:N, Y(I,J) /= 0.0) X(J,I)= 1.0/Y(I,J) O primeiro exemplo poderia ser implementado com o uso da fun¸˜o intr´ ca ınseca RESHAPE, mas o uso do FORALL possibilita a paraleliza¸˜o do programa execut´vel. J´ o segundo exemplo n˜o poderia ser implementado ca a a a com opera¸˜o de matriz inteira (tal como X= 1.0/Y) porque, em primeiro lugar, a matriz X tˆm elementos ca e transpostos em rela¸˜o ` matriz Y. Em segundo lugar, a m´scara Y(I,J) /= 0.0 n˜o est´ presente na ca a a a a opera¸˜o de matriz inteira; somente ´ poss´ introduzir esta m´scara com o uso do FORALL. ca e ıvel a A forma geral do comando FORALL ´ a seguinte: e FORALL (<´ndice>= <menor>:<maior>[:<passo>] [,<´ndice>= <meı ı nor>:<maior>[:<passo>]] & [...] [, <express~o escalar l´gica>]) <opera¸~es atribui¸~es matrizes> a o co co as condi¸˜es impostas a <´ndice>, <menor>, <maior>, <passo> e <express~o escalar l´gica> s˜o as co ı a o a mesmas impostas ao construto FORALL e ser˜o explicadas na descri¸˜o da forma geral do mesmo. a ca 6.10.2 Construto FORALL O construto FORALL tamb´m existe. Ele permite que diversas atribui¸˜es sejam executadas em ordem. e co Por exemplo, dadas as seguintes opera¸˜es com sub-matrizes: co A(2:N-1, 2:N-1)= A(2:N-1, 1:N-2) + A(2:N-1, 3:N) & + A(1:N-2, 2:N-1) + A(3:N, 2:N-1) B(2:N-1, 2:N-1)= A(2:N-1, 2:N-1) tamb´m podem ser implementadas com o uso do construto FORALL: e FORALL (I= 2:N-1, J= 2:N-1) A(I,J)= A(I,J-1) + A(I, J+1) + A(I-1, J) + A(I+1, J) B(I,J)= A(I,J) END FORALL Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 71.
    Cap´ ıtulo 6. Processamentode Matrizes 63 Neste exemplo, cada elemento de A ´ igualado ` soma dos quatro vizinhos mais pr´ximos e ´ feita ent˜o e a o e a uma c´pia em B. A vers˜o com o FORALL ´ melhor leg´ o a e ıvel e pode ser executado em qualquer ordem, inclusive simultaneamente. Devido a isto, quando o corpo do construto possui mais de uma instru¸˜o, o ca processador executa todas express˜es e atribui¸˜es da primeira linha antes de passar a executar a instru¸˜o o co ca da linha seguinte. N˜o ocorre erro na atribui¸˜o, porque inicialmente as express˜es s˜o desenvolvidas, em a ca o a qualquer ordem, seus resultados guardados em local de armazenagem tempor´ria na mem´ria e s´ no final a o o as atribui¸˜es s˜o feitas, tamb´m em qualquer ordem. co a e Construtos FORALL podem ser encadeados. A seq¨ˆncia ue FORALL (I= 1:N-1) FORALL (J= I+1:N) A(I,J)= A(J,I) END FORALL END FORALL atribui a transposta do triˆngulo inferior de A ao triˆngulo superior de A. a a Um construto FORALL pode conter um comando ou construto WHERE. Cada comando no corpo de um construto WHERE ´ executado em seq¨ˆncia. Por exemplo, e ue FORALL (I= 1:N) WHERE (A(I,:) == 0) A(I,:)= I B(I,:)= I/A(I,:) END FORALL Aqui, cada elemento nulo de A ´ substitu´ pelo valor do ´ e ıdo ındice das linhas e, seguindo a opera¸˜o completa, os ca elementos das linhas de B s˜o definidos como as rec´ a ıprocas dos correspondentes elementos de A multiplicados pelo respectivo ´ ındice. A sintaxe mais geral do construto FORALL ´: e [<nome>:] FORALL (<´ndice>= <menor>:<maior>[:<passo>], & ı [, <´ndice>= <menor>:<maior>[:<passo>]] [...] & ı [, <express~o l´gica escalar>]) a o <corpo> END FORALL [<nome>] onde <´ndice> ´ uma vari´vel inteira escalar, a qual permanece v´lida somente dentro do <corpo> do ı e a a construto, ou seja, outras vari´veis podem ter o mesmo nome do <´ndice> mas est˜o separadas e n˜o s˜o a ı a a a acess´ ıveis de dentro do FORALL.2 O <´ndice> n˜o pode ser redefinido dentro do construto. As express˜es ı a o <menor>, <maior> e <passo> devem ser express˜es escalares inteiras e formar uma seq¨ˆncia de valores como o ue para uma se¸˜o de matriz (se¸˜o 6.3); eles n˜o podem fazer referˆncia a um ´ ca ca a e ındice no mesmo cabe¸alho, c mas podem fazer referˆncia a um ´ e ındice de um FORALL mais externo. Uma vez tendo as express˜es inteiras o sido desenvolvidas, a <express~o l´gica escalar>, se presente, ´ desenvolvida para cada combina¸˜o dos a o e ca valores dos ´ ındices. Aqueles para os quais o resultado ´ .TRUE. s˜o ativados em cada comando no <corpo> e a do construto. O <corpo> consiste em um ou mais dos seguintes: express˜es e atribui¸˜es de elementos de matrizes, o co comandos ou construtos WHERE e outros comandos ou construtos FORALL. Usualmente, o sub-objeto (submatriz, por exemplo) no lado esquerdo de uma atribui¸˜o no <corpo> far´ referˆncia a cada <´ndice> dos ca a e ı construtos nos quais ele est´ imerso, como parte da identifica¸˜o do sub-objeto. Nenhum dos comandos no a ca <corpo> pode conter uma ramifica¸˜o ou ser acess´ ca ıvel atrav´s de algum comando de desvio de fluxo, tal e como o GO TO. Rotinas externas podem ser acessadas de dentro do <corpo> ou de dentro do cabe¸alho do c construto (na m´scara, por exemplo). Todas as rotinas invocadas dentro desta estrutura devem ser puras a (se¸˜o 8.2.16). ca O programa-exemplo 6.3 (programa tesforall) ilustra uma aplica¸˜o simples do construto FORALL, ca enquanto que o programa 6.4 (programa tesforall2) calcula a transposta de uma matriz. Pode-se notar aqui que o comando FORALL n˜o acarreta em erro, uma vez que as atribui¸˜es s˜o inicialmente armazenadas a co a em espa¸o tempor´rio e somente no final s˜o transferidas aos componentes da matriz A. c a a 2O que ´ denominado de ambito (scope). e ˆ Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 72.
    64 6.10. Comando econstruto FORALL Programa 6.3: Exemplo simples do construto FORALL. program t e s f o r a l l i m p l i c i t none integer , dimension ( 3 0 ) : : a , b integer : : n ! f o r a l l ( n =1:30) a ( n)= n b ( n)= a(30−n+1) end f o r a l l print * , ’ Vetor a : ’ print * , a print * , ’ ’ print * , ’ Vetor b : ’ print * , b end program t e s f o r a l l Programa 6.4: Calcula a transposta de uma matriz utilizando o comando FORALL. program t e s f o r a l l 2 i m p l i c i t none integer , dimension ( 3 , 3 ) : : a integer : : i , j a= r e s h a p e ( s o u r c e= ( / ( i , i= 1 , 9 ) / ) , shape= ( / 3 , 3 / ) ) print * , ”Matriz A: ” print * , a ( 1 , : ) print * , a ( 2 , : ) print * , a ( 3 , : ) f o r a l l ( i= 1 : 3 , j= 1 : 3 ) a ( i , j )= a ( j , i ) print * , ”T ra ns po s ta de A: ” print * , a ( 1 , : ) print * , a ( 2 , : ) print * , a ( 3 , : ) end program t e s f o r a l l 2 Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 73.
    Cap´ ıtulo 7 Rotinas Intr´ ınsecas Emuma linguagem de programa¸˜o destinada a aplica¸˜es cient´ ca co ıficas h´ uma exigˆncia ´bvia para que as a e o fun¸˜es matem´ticas mais requisitadas sejam oferecidas como parte da pr´pria linguagem, ao inv´s de terem co a o e de ser todas implementadas pelo programador. Al´m disso, ao serem fornecidas como parte do compilador, e espera-se que estas fun¸˜es tenham sido altamente otimizadas e testadas. co A eficiˆncia das rotinas intr´ e ınsecas quando estas manipulam matrizes em computadores vetoriais ou paralelos deve ser particularmente marcante, porque uma unica chamada ` rotina deve causar um n´mero ´ a u grande de opera¸˜es individuais sendo feitas simultaneamente, sendo o c´digo que as implementa otimizado co o para levar em conta todos os recursos de hardware dispon´ ıveis. No padr˜o do Fortran 90/95 h´ mais de cem rotinas intr´ a a ınsecas ao todo. Elas se dividem em grupos distintos, os quais ser˜o descritos em certo detalhe. Certos compiladores em particular poder˜o oferecer a a ainda mais rotinas, al´m das oferecidas pelo padr˜o da linguagem; contudo, o pre¸o a pagar ´ a falta de e a c e portabilidade de programas que usam rotinas fora do grupo-padr˜o. Al´m disso, rotinas extras somente a e poder˜o ser oferecidas ao usu´rio atrav´s de m´dulos (cap´ a a e o ıtulo 8). Ao longo deste cap´ ıtulo, as rotinas intr´ ınsecas ser˜o naturalmente divididas em fun¸˜es e subrotinas. A a co distin¸˜o entre estas duas classes de rotinas ser´ discutida com mais detalhes no cap´ ca a ıtulo 8. 7.1 Categorias de rotinas intr´ ınsecas H´ quatro categorias de rotinas intr´ a ınsecas: Rotinas elementais. S˜o especificadas para argumentos escalares, mas podem tamb´m ser aplicadas a a e matrizes conform´veis. No caso de uma fun¸˜o elemental, cada elemento da matriz resultante, caso a ca exista, ser´ obtido como se a fun¸˜o tivesse sido aplicada a cada elemento individual da matriz que a ca foi usada como argumento desta fun¸˜o. No caso de uma subrotina elemental com um argumento ca matricial, cada argumento com intento IN ou INOUT deve ser uma matriz e cada elemento resultante ser´ obtido como se a subrotina tivesse sido aplicada a cada elemento da matriz que ´ passada como a e argumento ` subrotina. a Fun¸˜es inquisidoras. Retornam propriedades dos seus argumentos principais que n˜o dependem dos seus co a valores, somente do seu tipo e/ou esp´cie. e Fun¸˜es transformacionais. S˜o fun¸˜es que n˜o s˜o nem elementais nem inquisidoras. Elas usualmente co a co a a tˆm argumentos matriciais e o resultado tamb´m ´ uma matriz cujos elementos dependem dos elemene e e tos dos argumentos. Rotinas n˜o-elementais. Rotinas que n˜o se enquadram em nenhum dos tipos acima. a a As rotinas intr´ ınsecas ser˜o descritas posteriormente com base nesta categoriza¸˜o. a ca 7.2 Declara¸˜o e atributo INTRINSIC ca Um nome pode ser especificado como o nome de uma rotina intr´ ınseca com a declara¸˜o INTRINSIC, o ca qual possui a forma geral: INTRINSIC <lista de nomes intr´nsecos> ı 65
  • 74.
    66 7.3. Fun¸˜es inquisidorasde qualquer tipo co onde <lista de nomes intr´nsecos> ´ uma lista de nomes de rotinas intr´ ı e ınsecas. O uso desta declara¸˜o ca ´ recomendado quando se quer enfatizar ao compilador que certos nomes s˜o destinados a rotinas intr´ e a ınsecas. Isto pode ser util quando o programador est´ estendendo a defini¸˜o de uma rotina intr´ ´ a ca ınseca, em um procedimento denominado sobrecarga de operador (operator overloading), o qual faz uso de interfaces gen´ricas (generic interfaces). Para mais detalhes nestes recursos avan¸ados, ver Metcalf & Reid (1996) e c [4]. Alternativamente, uma ou mais fun¸˜es intr´ co ınsecas podem ser declaradas com o atributo INTRINSIC, no lugar da declara¸˜o. ca O atributo ou declara¸˜o INTRINSIC s˜o excludentes em rela¸˜o ao atributo ou declara¸˜o EXTERNAL ca a ca ca (se¸˜o 8.2.12). ca 7.3 Fun¸˜es inquisidoras de qualquer tipo co As seguintes s˜o fun¸˜es inquisidoras, com argumentos que podem ser de qualquer tipo: a co ASSOCIATED(POINTER[,TARGET]). Quanto TARGET est´ ausente, a fun¸˜o retorna o valor .TRUE. se o pona ca teiro (pointer) est´ associado com um alvo (target) e retorna o valor .FALSE. em caso contr´rio. O a a status de associa¸˜o de ponteiro de POINTER n˜o deve ser indefinido. Se TARGET estiver presente, este ca a deve ter o mesmo tipo, esp´cie e posto de POINTER. O valor da fun¸˜o ´ .TRUE. se POINTER estiver e ca e associado a TARGET ou .FALSE. em caso contr´rio. No caso de matrizes, .TRUE. ´ obtido somente se as a e formas s˜o idˆnticas e elementos de matriz correspondentes, na ordem de elementos de matriz, est˜o a e a associadas umas com as outras. Se o comprimento do caractere ou tamanho da matriz s˜o iguais a a zero, .FALSO. ´ obtido. Um limite diferente, como no caso de ASSOCIATED(P,A) seguindo a atribuie ¸˜o de ponteiro P => A(:) quando LBOUND(A)= 0, ´ insuficiente para causar um resultado .FALSE.. ca e TARGET pode ser tamb´m um ponteiro, em cujo caso seu alvo ´ comparado com o alvo de POINTER; o e e status de associa¸˜o de ponteiro de TARGET n˜o deve ser indefinido e se ou POINTER ou TARGET est˜o ca a a dissociados, o resultado ´ .FALSE. e PRESENT(A). Pode ser chamada em um sub-programa que possui um argumento mudo opcional A (ver se¸˜o 8.2.9) ou acesse este argumento mudo a partir de seu hospedeiro. A fun¸˜o retorna o valor ca ca .TRUE. se o argumento est´ presente na chamada do sub-programa ou .FALSE. em caso contr´rio. Se a a um argumento mudo opcional ´ usado como um argumento real na chamada de outra rotina, ele ´ e e considerado tamb´m ausente pela rotina chamada. e KIND(X). Tem o argumento X de qualquer tipo e esp´cie e o seu resultado tem o tipo inteiro padr˜o e de e a valor igual ao valor do parˆmetro de esp´cie de X. a e 7.4 Fun¸˜es elementais num´ricas co e H´ 17 fun¸oes elementais destinadas ` realiza¸˜o de opera¸˜es num´ricas simples, muitas das quais a c˜ a ca co e realizam convers˜o de tipo de vari´veis para alguns ou todos os argumentos. a a 7.4.1 Fun¸˜es elementais que podem converter co Se o especificador KIND estiver presente nas fun¸˜es elementais seguintes, este deve ser uma express˜o co a inteira e fornecer um parˆmetro de esp´cie de tipo que seja suportado pelo processador. a e ABS(A). Retorna o valor absoluto de um argumento dos tipos inteiro, real ou complexo. O resultado ´ do e tipo inteiro se A for inteiro e ´ real nos demais casos. O resultado ´ da mesma esp´cie que A. e e e AIMAG(Z). Retorna a parte imagin´ria do valor complexo Z. O tipo do resultado ´ real e a esp´cie ´ a mesma a e e e que Z. AINT(A[,KIND]). Trunca um valor real A em sentido ao zero para produzir um valor real cujos valores decimais s˜o iguais a zero. Se o argumento KIND estiver presente, o resultado ´ da esp´cie dada por a e e este; caso contr´rio, retorna o resultado na esp´cie padr˜o do tipo real. a e a ANINT(A[,KIND]). Retorna um real cujo valor ´ o n´mero completo (sem parte fracion´ria) mais pr´ximo e u a o de A. Se KIND estiver presente, o resultado ´ do tipo real da esp´cie definida; caso contr´rio, o resultado e e a ser´ real da esp´cie padr˜o. a e a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 75.
    Cap´ ıtulo 7. RotinasIntr´ ınsecas 67 CEILING(A). Retorna o menor inteiro maior ou igual ao seu argumento real. Se KIND estiver presente, o resultado ser´ do tipo inteiro com a esp´cie definida pelo parˆmetro; caso contr´rio, o resultado ser´ a e a a a inteiro da esp´cie padr˜o. e a CMPLX(X[,Y][,KIND]). Converte X ou (X,Y) ao tipo complexo com a esp´cie definida pelo argumento KIND, e caso presente, ou na esp´cie padr˜o do tipo complexo em caso contr´rio. Se Y for ausente, X pode ser e a a dos tipos inteiro, real ou complexo. Se Y estiver presente, tanto X quanto Y devem ser dos tipos inteiro ou real. FLOOR(A[,KIND]). Retorna o maior inteiro menor ou igual a seu argumento real A. Se KIND estiver presente, o resultado ´ do tipo inteiro da esp´cie definida; caso contr´rio, o resultado ´ inteiro da esp´cie padr˜o. e e a e e a INT(A[,KIND]). Converte ao tipo inteiro da esp´cie padr˜o ou dada pelo argumento KIND. O argumento A e a pode ser: ˆ inteiro, em cujo caso INT(A)= A; ˆ real, em cujo caso o valor ´ truncado em sentido ao zero, ou e ˆ complexo, em cujo caso somente a parte real ´ considerada e esta ´ truncada em sentido ao zero. e e NINT(A[,KIND]). Retorna o valor inteiro mais pr´ximo do real A. Se KIND estiver presente, o resultado ´ o e do tipo inteiro da esp´cie definida; caso contr´rio, o resultado ser´ inteiro da esp´cie padr˜o. e a a e a REAL(A[,KIND]). Converte ao tipo real da esp´cie dada pelo argumento KIND. O argumento A pode ser dos e tipos inteiro, real ou complexo. Se A for complexo, a parte imagin´ria ´ ignorada. Se o argumento a e KIND estiver ausente, o resultado ser´ da esp´cie padr˜o do tipo real se A for inteiro ou real e da mesma a e a esp´cie de A se este for complexo. e 7.4.2 Fun¸˜es elementais que n˜o convertem co a As seguintes s˜o fun¸˜es elementais cujos resultados s˜o do tipo e da esp´cie iguais aos do primeiro ou a co a e unico argumento. Para aquelas que possuem mais de um argumento, todos devem ser do mesmo tipo e ´ esp´cie. e CONJG(Z). Retorna o conjugado do valor complexo Z. DIM(X,Y). Retorna MAX(X-Y,0) para argumentos que s˜o ambos inteiros ou ambos reais. a MAX(A1,A2[,A3,...]). Retorna o m´ximo (maior valor) entre dois ou mais valores inteiros ou reais. a MIN(A1,A2[,A3,...]). Retorna o m´ ınimo (menor valor) entre dois ou mais valores inteiros ou reais. MOD(A,P). Retorna o restante de A m´dulo P, ou seja, A-INT(A/P)*P. Se P=0, o resultado depende do o processador. A e P devem ambos ser inteiros ou ambos reais. MODULO(A,P). Retorna A m´dulo P quando A e P s˜o ambos inteiros ou ambos reais; isto ´, A-FLOOR(A/P)*P o a e no caso real ou A-FLOOR(A÷P)*P no caso inteiro, onde ÷ representa divis˜o matem´tica ordin´ria. Se a a a P=0, o resultado depende do processador. SIGN(A,B). Retorna o valor absoluto de A vezes o sinal de B. A e B devem ser ambos inteiros ou ambos reais. Se B= 0 e ´ inteiro, seu sinal ´ assumido positivo. Se o processador n˜o tem a capacidade de e e a disting¨ir entre zeros reais positivos ou negativos ent˜o, para B= 0.0 o sinal ´ assumido positivo. u a e 7.5 Fun¸˜es elementais matem´ticas co a As seguintes s˜o fun¸˜es elementais que calculam o conjunto imagem de fun¸˜es matem´ticas elementares. a co co a O tipo e esp´cie do resultado s˜o iguais aos do primeiro argumento, o qual, usualmente, ´ o unico. e a e ´ ACOS(X). Retorna a fun¸˜o arco cosseno (ou cos−1 ) para valores reais do argumento X (|X| ≤ 1). O resultado ca ´ obtido em radianos no intervalo 0 ≤ ACOS(X) ≤ π. e ASIN(X). Retorna a fun¸˜o arco seno (ou sin−1 ) para valores reais do argumento X (|X| ≤ 1). O resultado ´ ca e obtido em radianos no intervalo −π/2 ≤ ASIN(X) ≤ π/2. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 76.
    68 7.6. Fun¸˜es elementaisl´gicas e de caracteres co o ATAN(X). Retorna a fun¸˜o arco tangente (ou tan−1 ) para valores reais do argumento X (−∞ < X < ∞). O ca resultado ´ obtido em radianos no intervalo −π/2 ≤ ATAN(X) ≤ π/2. e ATAN2(Y,X). Retorna a fun¸˜o arco tangente (ou tan−1 ) para pares de argumentos reais, X e Y, ambos do ca mesmo tipo e esp´cie. O resultado ´ o valor principal do argumento do n´mero complexo (X,Y), e e u expresso em radianos no intervalo −π < ATAN2(Y, X) ≤ π. Os valores de X e Y n˜o devem ser simultaa neamente nulos. COS(X). Retorna o valor da fun¸˜o cosseno para um argumento dos tipos real ou complexo. A unidade do ca argumento X ´ suposta ser radianos. e COSH(X). Retorna o valor da fun¸˜o cosseno hiperb´lico para um argumento X real. ca o EXP(X). Retorna o valor da fun¸˜o exponencial para um argumento X real ou complexo. ca LOG(X). Retorna o valor da fun¸˜o logaritmo natural para um argumento X real ou complexo. No caso real, ca X deve ser positivo. No caso complexo, X n˜o pode ser nulo e a parte imagin´ria do resultado (Zi ) est´ a a a no intervalo −π < Zi ≤ π. LOG10(X). Retorna o valor da fun¸˜o logaritmo de base 10 para um argumento X real e positivo. ca SIN(X). Retorna o valor da fun¸˜o seno para um argumento dos tipos real ou complexo. A unidade do ca argumento X ´ suposta ser radianos. e SINH(X). Retorna o valor da fun¸˜o seno hiperb´lico para um argumento X real. ca o SQRT(X). Retorna o valor da fun¸˜o raiz quadrada para um argumento X real ou complexo. No caso real, ca X n˜o pode ser negativo. No caso complexo, o resultado consiste na raiz principal, ou seja, a parte a real do resultado ´ positiva ou nula. Quando a parte real do resultado for nula, a parte imagin´ria ´ e a e positiva ou nula. TAN(X). Retorna o valor da fun¸˜o tangente para um argumento X real. A unidade do argumento ´ suposta ca e ser radianos. TANH(X). Retorna o valor da fun¸˜o tangente hiperb´lica para um argumento X real. ca o 7.6 7.6.1 Fun¸˜es elementais l´gicas e de caracteres co o Convers˜es caractere-inteiro o As seguintes s˜o fun¸˜es elementais para converter um unico caractere em um inteiro e vice-versa. a co ´ ACHAR(I). O resultado ´ do tipo de caractere padr˜o de comprimento um e retorna o caractere que est´ na e a a posi¸˜o especificada pelo valor inteiro I na tabela ASCII de caracteres (tabela 4.9). I deve estar no ca intervalo 0 ≤ I ≤ 127; caso contr´rio, o resultado depende do processador. a CHAR(I[,KIND]). O resultado ´ do tipo caractere de comprimento um. A esp´cie ´ dada pelo argumento e e e opcional KIND, se presente ou, em caso contr´rio, ser´ a esp´cie padr˜o. A fun¸˜o retorna o caractere na a a e a ca posi¸˜o I (tipo inteiro) da seq¨ˆncia de caracteres interna do processador associada com o parˆmetro ca ue a de esp´cie relevante. I deve estar no intervalo 0 ≤ I ≤ n − 1, onde n ´ o n´mero de caracteres na e e u seq¨ˆncia interna do processador. ue IACHAR(C). O resultado ´ do tipo inteiro padr˜o e retorna a posi¸˜o do caractere C na tabela ASCII. Se C e a ca n˜o est´ na tabela, o resultado depende do processador. a a ICHAR(C). O resultado ´ do tipo inteiro padr˜o e retorna a posi¸˜o do caractere C na seq¨ˆncia interna do e a ca ue processador associada com a esp´cie de C. e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 77.
    Cap´ ıtulo 7. RotinasIntr´ ınsecas 7.6.2 69 Fun¸˜es de compara¸˜o l´xica co ca e As seguintes fun¸˜es elementais aceitam strings de caracteres da esp´cie padr˜o, realizam uma comparaco e a ¸˜o l´xica baseada na tabela ASCII e retornam um resultado l´gico da esp´cie padr˜o. Se as strings tiverem ca e o e a comprimentos distintos, a mais curta ´ complementada com espa¸os em branco. e c LGE(STRING_A,STRING_B). Retorna o valor .TRUE. se STRING_A segue STRING_B na seq¨ˆncia estabelecida ue pela tabela ASCII, ou a iguala. O resultado ´ .FALSE. em caso contr´rio. e a LGT(STRING_A,STRING_B). Retorna o valor .TRUE. se STRING_A segue STRING_B na seq¨ˆncia estabelecida ue pela tabela ASCII. O resultado ´ .FALSE. em caso contr´rio. e a LLE(STRING_A,STRING_B). Retorna o valor .TRUE. se STRING_A precede STRING_B na seq¨ˆncia estabeleue cida pela tabela ASCII, ou a iguala. O resultado ´ .FALSE. em caso contr´rio. e a LLT(STRING_A,STRING_B). Retorna o valor .TRUE. se STRING_A precede STRING_B na seq¨ˆncia estabeleue cida pela tabela ASCII. O resultado ´ .FALSE. em caso contr´rio. e a 7.6.3 Fun¸˜es elementais para manipula¸oes de strings co c˜ As seguintes s˜o fun¸˜es elementais que manipulam strings. Os argumentos STRING, SUBSTRING e SET a co s˜o sempre do tipo de caractere e, quando dois est˜o presentes, ambos devem ser da mesma esp´cie. O a a e resultado ´ da mesma esp´cie de STRING. e e ADJUSTL(STRING). Ajusta uma string ` esquerda. Ou seja, remove os espa¸os em branco no in´ da string a c ıcio e coloca o mesmo n´mero de brancos no final da string. u ADJUSTR(STRING). Ajusta uma string ` direita. Ou seja, remove os espa¸os em branco no final da string e a c coloca o mesmo n´mero de brancos no in´ da string. u ıcio INDEX(STRING,SUBSTRING[,BACK]). Retorna um valor do tipo inteiro padr˜o, o qual consiste na posi¸˜o a ca inicial de SUBSTRING como uma substring de STRING, ou zero se tal substring n˜o existe. Se BACK a (vari´vel l´gica) est´ ausente, ou se est´ presente com o valor .FALSE., a posi¸˜o inicial da primeira das a o a a ca substrings ´ retornada; o valor 1 ´ retornado se SUBSTRING tem comprimento zero. Se BACK est´ pree e a sente com valor .TRUE., a posi¸˜o inicial da ultima das substrings ´ retornada; o valor LEN(STRING)+1 ca ´ e ´ retornado se SUBSTRING tem comprimento zero. e LEN_TRIM(STRING). Retorna um valor inteiro padr˜o correspondente ao comprimento de STRING, ignorando a espa¸os em branco no final do argumento. c SCAN(STRING,SET[,BACK]). Retorna um valor inteiro padr˜o correspondente ` posi¸˜o de um caractere de a a ca STRING que esteja em SET, ou zero se n˜o houver tal caractere. Se a vari´vel l´gica BACK est´ ausente, a a o a ou presente com valor .FALSE., a posi¸˜o mais ` esquerda deste caractere ´ retornada. Se BACK est´ ca a e a presente com valor .TRUE., a posi¸˜o mais ` direita deste caractere ´ retornada. ca a e VERIFY(STRING,SET[,BACK]). Retorna o valor inteiro padr˜o 0 se cada caractere em STRING aparece em a SET, ou a posi¸˜o de um caractere de STRING que n˜o esteja em SET. Se a vari´vel l´gica BACK est´ ca a a o a ausente, ou presente com valor .FALSE., a posi¸˜o mais ` esquerda de tal caractere ´ retornada. Se ca a e BACK est´ presente com valor .TRUE., a posi¸˜o mais ` direita de tal caractere ´ retornada. a ca a e 7.6.4 Convers˜o l´gica a o A fun¸˜o elemental a seguir converte de uma esp´cie do tipo l´gico em outra. ca e o LOGICAL(L[,KIND]). Retorna o valor l´gico idˆntico ao valor de L. A esp´cie do resultado ´ definida pelo o e e e argumento opcional KIND, caso esteja presente, ou ´ da esp´cie padr˜o em caso contr´rio. e e a a 7.7 7.7.1 Fun¸˜es n˜o-elementais para manipula¸˜o de strings co a ca Fun¸˜o inquisidora para manipula¸˜o de strings ca ca LEN(STRING). Trata-se de uma fun¸˜o inquisidora que retorna um valor inteiro padr˜o escalar que corresca a ponde ao n´mero de caracteres em STRING se esta ´ escalar ou de um elemento de STRING se a mesma u e ´ uma matriz. O valor de STRING n˜o precisa estar definido. e a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 78.
    70 7.8. Fun¸˜es inquisidorase de manipula¸˜es num´ricas co co e 7.7.2 Fun¸˜es transformacionais para manipula¸˜o de strings co ca Existem duas fun¸˜es que n˜o s˜o elementais porque o comprimento do resultado depende do valor de co a a um argumento. REPEAT(STRING,NCOPIES). Forma a string que consiste na concatena¸˜o de NCOPIES c´pias de STRING, ca o onde NCOPIES ´ do tipo inteiro e seu valor n˜o deve ser negativo. Ambos argumentos devem ser e a escalares. TRIM(STRING). Retorna STRING com todos os espa¸os em branco no final da vari´vel removidos. STRING c a deve ser escalar. 7.8 Fun¸˜es inquisidoras e de manipula¸˜es num´ricas co co e 7.8.1 Modelos para dados inteiros e reais As fun¸˜es inquisidoras e de manipula¸˜es num´ricas s˜o definidas em termos de modelos de representa¸˜o co co e a ca de n´meros inteiro e reais para cada esp´cie suportada pelo processador. u e Para cada esp´cie do tipo inteiro, o modelo ´: e e q wk × rk−1 , i=s× (7.1) k=1 onde s = ±1, q ´ um inteiro positivo, r ´ um inteiro maior que um (usualmente 2) e cada valor de wk ´ um e e e inteiro no intervalo 0 ≤ wk < r. Para cada esp´cie do tipo real, o modelo ´: e e x=0 e p fk × b−k , e x=s×b × (7.2) k=1 onde s = ±1, p e b s˜o inteiros maiores que um, e ´ um inteiro no intervalo emin ≤ e ≤ emax e cada fk ´ um a e e inteiro no intervalo 0 ≤ fk < b, exceto f1 , que ´ n˜o nulo. e a Os valores de todos os parˆmetros nestes modelos s˜o escolhidos para o processador de tal forma que o a a modelo melhor se ajuste ao hardware, desde que todos os n´meros sejam represent´veis. u a 7.8.2 Fun¸˜es num´ricas inquisidoras co e H´ nove fun¸˜es inquisidoras que retornam valores para os modelos de dados associados com seus argua co mentos. Cada fun¸˜o tem um unico argumento que pode ser escalar ou matricial e todas retornam um valor ca ´ escalar. O valor per se do argumento n˜o precisa ser definido, somente o seu tipo e esp´cie. a e DIGITS(X). Para X real ou inteiro, retorna o inteiro padr˜o cujo valor ´ o n´mero de d´ a e u ıgitos significantes no modelo que inclui X; isto ´, retorna p para X real ou q para X inteiro. e EPSILON(X). Para X real, retorna um resultado real com o mesmo tipo de X e que ´ quase indisting¨´ do e uıvel valor 1.0 no modelo que inclui X. Ou seja, a fun¸˜o calcula b1−p . ca HUGE(X). Para X real ou inteiro, retorna o maior valor represent´vel no modelo que inclui X. O resultado a possui o mesmo tipo e esp´cie de X. O valor ´ e e 1 − b−p bemax para X real ou rq − 1 para X inteiro. MAXEXPONENT(X). Para X real, retorna o inteiro padr˜o emax , ou seja, o expoente m´ximo no modelo que a a inclui X. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 79.
    Cap´ ıtulo 7. RotinasIntr´ ınsecas 71 MINEXPONENT(X). Para X real, retorna o inteiro padr˜o emin , ou seja, o expoente m´ a ınimo no modelo que inclui X. PRECISION(X). Para X real ou complexo, retorna um inteiro padr˜o que cont´m a precis˜o decimal equia e a valente no modelo que representa n´meros reais da mesma esp´cie de X. O valor da fun¸˜o ´ u e ca e INT((p − 1)) ∗ LOG10(b))+k, onde k ´ 1 se b ´ uma potˆncia inteira de 10 ou 0 em outro caso. e e e RADIX(X). Para X real ou inteiro, retorna o inteiro padr˜o que ´ a base no modelo que inclui X. Isto ´, a e e retorna b para X real ou r para X inteiro. RANGE(X). Para X inteiro, real ou complexo, retorna o inteiro padr˜o que cont´m o intervalo de expoentes a e decimais nos modelos representando n´meros reais ou inteiro da mesma esp´cie de X. O valor da u e fun¸˜o ´ INT(LOG10(huge)) para X inteiro e ca e INT(MIN(LOG10(huge), −LOG10(tiny))) para X real, onde huge e tiny s˜o, respectivamente, o maior e o menor n´meros positivos nos modelos. a u TINY(X). Para X real, retorna o menor n´mero positivo, u bemin −1 no modelo que inclui X. O resultado ´ do mesmo tipo e esp´cie de X. e e 7.8.3 Fun¸˜es elementais que manipulam quantidades reais co H´ sete fun¸˜es elementais cujo primeiro ou unico argumento ´ do tipo real e que retorna valores relacia co ´ e onados aos componentes dos modelos de valores associados ao valor do argumento. EXPONENT(X). Retorna o inteiro padr˜o cujo valor ´ a parte de expoente e de X quando representado como a e um n´mero de modelo. Se X=0, o resultado tamb´m ´ nulo. u e e FRACTION(X). Retorna uma quantidade real da mesma esp´cie que X e cujo valor ´ a parte fracion´ria de X e e a quando representado como um n´mero de modelo; isto ´, a fun¸˜o retorna Xb−e . u e ca NEAREST(X,S). Retorna uma quantidade real da mesma esp´cie que X e cujo valor ´ o n´mero distinto mais e e u pr´ximo de X no sentido dado pelo sinal da quantidade real S. O valor de S n˜o pode ser nulo. o a RRSPACING(X). Retorna uma quantidade real da mesma esp´cie que X cujo valor ´ a rec´ e e ıproca do espa¸ac mento relativo dos n´meros de modelo pr´ximos a X; isto ´, a fun¸˜o retorna |Xb−e | bp . u o e ca SCALE(X,I). Retorna uma quantidade real da mesma esp´cie que X cujo valor ´ XbI , onde b ´ a base do e e e modelo para X e I ´ do tipo inteiro. e SET_EXPONENT(X,I). Retorna uma quantidade real da mesma esp´cie que X cuja parte fracion´ria ´ a parte e a e fracion´ria da representa¸˜o de X e cuja parte exponencial ´ I; isto ´, a fun¸˜o retorna Xb1−e . a ca e e ca SPACING(X). Retorna uma quantidade real da mesma esp´cie que X cujo valor ´ o espa¸amento absoluto do e e c modelo de n´meros pr´ximos a X. O resultado ´ be−p se X ´ n˜o nulo e este resultado est´ dentro do u o e e a a intervalo de n´meros represent´veis. Caso contr´rio, a fun¸˜o retorna TINY(X). u a a ca 7.8.4 Fun¸˜es transformacionais para valores de esp´cie (kind) co e H´ duas fun¸˜es que retornam o menor valor do parˆmetro de esp´cie que ir´ satisfazer um dado rea co a e a querimento num´rico. As fun¸˜es tˆm argumentos e resultados escalares; por´m s˜o classificadas como e co e e a transformacionais. Estas fun¸˜es j´ foram discutidas na se¸˜o 3.7.3. co a ca SELECTED_INT_KIND(R). Retorna o inteiro escalar padr˜o que ´ o valor do parˆmetro da esp´cie para um a e a e dado do tipo inteiro capaz de representar todos os valor inteiros n no intervalo −10R < n < 10R , onde R ´ um inteiro escalar. Se mais de uma esp´cie for dispon´ e e ıvel, a esp´cie com menor intervalo exponencial e ´ escolhida. Se nenhuma esp´cie ´ dispon´ e e e ıvel, o resultado ´ -1. e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 80.
    72 7.9. Rotinas demanipula¸˜o de bits ca SELECTED_REAL_KIND([P][,R]). Retorna o inteiro escalar padr˜o que ´ o valor do parˆmetro da esp´cie a e a e para um dado do tipo real com precis˜o decimal (conforme retornada pela fun¸˜o PRECISION) no a ca m´ ınimo igual a P e intervalo de expoente decimal (conforme retornado pela fun¸˜o RANGE) no m´ ca ınimo igual a R. Se mais de uma esp´cie for dispon´ e ıvel, a esp´cie com a menor precis˜o decimal ´ escolhida. e a e Tanto P quanto R s˜o inteiros escalares; pelo menos um destes deve estar presente. Se n˜o houver a a esp´cie dispon´ e ıvel, o resultado ´: e -1: se a precis˜o requerida n˜o for dispon´ a a ıvel; -2: se um intervalo de expoente grande o suficiente n˜o for dispon´ a ıvel; -3: se ambos n˜o forem dispon´ a ıveis. 7.9 Rotinas de manipula¸˜o de bits ca H´ onze rotinas para manipular bits contidos em quantidades inteiras. Estas rotinas s˜o elementais, a a quando apropriado. As rotinas s˜o baseadas em um modelo no qual um valor inteiro ´ representado por s a e bits wk , com k = 0, 1, . . . , s − 1, em uma seq¨ˆncia da direita para a esquerda, baseada no valor n˜o-negativo ue a s−1 wk × 2k . k=0 Este modelo ´ v´lido somente no contexto destas rotinas intr´ e a ınsecas e ´ idˆntico ao modelo de n´meros e e u inteiros (7.1) quando r ´ uma potˆncia inteira de 2 e ws−1 = 0; mas quando ws−1 = 1 os modelos diferem. e e 7.9.1 Fun¸˜o inquisidora ca BIT_SIZE(I). Retorna o n´mero de bits no modelo para bits dentro de um inteiro da mesma esp´cie que u e I. O resultado ´ um inteiro escalar da mesma esp´cie que I. e e 7.9.2 Fun¸˜es elementais co BTEST(I,POS). Retorna o valor l´gico da esp´cie padr˜o .TRUE. se o bit POS do inteiro I tem valor 1 e retorna o e a .FALSE. em outra situa¸˜o. POS deve ser um inteiro com valor no intervalo 0 ≤ POS < BIT SIZE(I). ca IAND(I,J). Retorna o l´gico AND de todos os bits em I e bits correspondentes em J, de acordo com a o tabela-verdade I 1100 J 1010 I AND(I, J) 1 0 0 0 I e J devem ser do mesmo tipo; o resultado tamb´m ser´ do mesmo tipo. e a IBCLR(I,POS). Retorna um inteiro do mesmo tipo que I e valor igual ao de I exceto que o bit POS ´ levado e a 0. POS deve ser um inteiro com valor no intervalo 0 ≤ POS < BIT SIZE(I). IBITS(I,POS,LEN). Retorna um inteiro do mesmo tipo que I e valor igual aos LEN bits de I iniciando no bit POS ajustado ` direita e com todos os outros bits iguais a 0. POS e LEN devem ser inteiros positivos a tais que POS + LEN ≤ BIT SIZE(I). IBSET(I,POS). Retorna um inteiro do mesmo tipo que I e valor igual ao de I exceto que o bit POS ´ levado e a 1. POS deve ser um inteiro com valor no intervalo 0 ≤ POS < BIT SIZE(I). IEOR(I,J). Retorna o OU l´gico exclusivo de todos os bits de I e correspondentes bits em J, de acordo com o a tabela-verdade I 1100 J 1010 I EOR(I, J) 0 1 1 0 I e J devem ser do mesmo tipo; o resultado tamb´m ser´ do mesmo tipo. e a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 81.
    Cap´ ıtulo 7. RotinasIntr´ ınsecas 73 IOR(I,J). Retorna o OU l´gico inclusivo de todos os bits de I e correspondentes bits em J, de acordo com o a tabela-verdade I 1100 J 1010 I IOR(I, J) 1 1 1 0 I e J devem ser do mesmo tipo; o resultado tamb´m ser´ do mesmo tipo. e a ISHFT(I,SHIFT). Retorna um inteiro do mesmo tipo que I e valor igual ao de I exceto que os bits s˜o a deslocados SHIFT posi¸˜es para a esquerda (-ISHIFT desloca para a direita se SHIFT for positivo). co Zeros s˜o inseridos a partir da extremidade oposta. SHIFT deve ser um inteiro com valor que satisfaz a a inegualdade |SHIFT| ≤ BIT SIZE(I). ISHFTC(I,SHIFT[,SIZE]). Retorna um inteiro do mesmo tipo que I e valor igual ao de I exceto que os SIZE bits mais ` direita (ou todos os bits se SIZE for ausente) s˜o deslocados de forma circular SHIFT a a posi¸˜es para a esquerda (-ISHIFT desloca para a direita se SHIFT for positivo). Zeros s˜o inseridos co a a partir da extremidade oposta. SHIFT deve ser um inteiro com valor que n˜o excede o valor de SIZE a ou BIT_SIZE(I), se SIZE estiver ausente. NOT(I). Retorna o complemento l´gico de todos os bits em I, de acordo com a tabela-verdade o I 01 NOT(I) 1 0 7.9.3 Subrotina elemental MVBITS(FROM,FROMPOS,LEN,TO,TOPOS). Copia a seq¨ˆncia de bits em FROM que inicia na posi¸˜o FROMPOS ue ca e tem comprimento LEN para TO, iniciando na posi¸˜o TOPOS. Os outros bits de TO permanecem ca inalterados. FROM, FROMPOS, LEN e TOPOS s˜o todos inteiros com intent IN e devem ter valores que a satisfazem as inegualdades: LEN ≥ 0, FROMPOS+LEN ≤ BIT_SIZE(FROM), FROMPOS ≥ 0, TOPOS ≥ 0 e TOPOS+LEN ≤ BIT_SIZE(TO). TO ´ um inteiro com intent INOUT; ele deve ser da mesma esp´cie que e e FROM. A mesma vari´vel pode ser especificada para FROM e TO. a 7.10 Fun¸˜o de transferˆncia ca e A fun¸˜o de transferˆncia permite que dados de um tipo sejam transferidos a outro tipo sem que a ca e representa¸˜o f´ ca ısica dos mesmos seja alterada. Esta fun¸˜o pode ser util, por exemplo, ao se escrever um ca ´ sistema de armazenamento e recupera¸˜o de dados; o sistema pode ser escrito para uma dado tipo, por ca exemplo, inteiro, e os outros tipos s˜o obtidos atrav´s de transferˆncias de e para este tipo. a e e TRANSFER(SOURCE,MOLD[,SIZE]). Retorna um valor do tipo e esp´cie de MOLD. Quando SIZE estiver aue sente, o resultado ´ escalar se MOLD for escalar e ´ de posto 1 e tamanho suficiente para armazenar toda e e a SOURCE se MOLD for uma matriz. Quando SIZE estiver presente, o resultado ´ de posto 1 e tamanho e SIZE. Se a representa¸˜o f´ ca ısica do resultado ´ t˜o ou mais longa que o tamanho de SOURCE, o resultado e a cont´m SOURCE como sua parte inicial e o resto ´ indefinido; em outros casos, o resultado ´ a parte e e e inicial de SOURCE. Como o posto do resultado depende se SIZE ´ ou n˜o especificado, o argumento em e a si n˜o pode ser um argumento opcional. a 7.11 Fun¸oes de multiplica¸˜o vetorial ou matricial c˜ ca H´ duas fun¸˜es transformacionais que realizam multiplica¸˜es vetorial ou matricial. Elas possuem dois a co co argumentos que s˜o ambos de um tipo num´rico (inteiro, real ou complexo) ou ambas do tipo l´gico. O a e o resultado ´ do mesmo tipo e esp´cie como seria resultante das opera¸˜es de multiplica¸˜o ou .AND. entre e e co ca dois escalares. As fun¸˜es SUM e ANY, usadas nas defini¸˜es abaixo, s˜o definidas na se¸˜o 7.12.1 abaixo. co co a ca DOT_PRODUCT(VETOR_A,VETOR_B). Requer dois argumentos, ambos de posto 1 e do mesmo tamanho. Se VETOR_A ´ dos tipos inteiro ou real, a fun¸˜o retorna SUM(VETOR_A*VETOR_B); se VETOR_A ´ do tipo e ca e complexo, a fun¸˜o retorna SUM(CONJG(VETOR_A)*VETOR_B); e se VETOR_A ´ do tipo l´gico, a fun¸˜o ca e o ca retorna ANY(VETOR_A .AND. VETOR_B). MATMUL(MATRIZ_A,MATRIZ_B). Realiza a multiplica¸˜o escalar. Para argumentos num´ricos, trˆs casos s˜o ca e e a poss´ ıveis: Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 82.
    74 7.12. Fun¸˜es transformacionaisque reduzem matrizes co 1. MATRIZ_A tem forma (/n,m/) e MATRIZ_B tem forma (/m,k/). O resultado tem forma (/n,k/) e o elemento (i, j) tem o valor dado por SUM(MATRIZ_A(I,:)*MATRIZ_B(:,J)). 2. MATRIZ_A tem forma (/m/) e MATRIZ_B tem forma (/m,k/). O resultado tem forma (/k/) e o elemento j tem o valor dado por SUM(MATRI_A*MATRIZ_B(:,J)). 3. MATRIZ_A tem forma (/n,m/) e MATRIZ_B tem forma (/m/). O resultado tem forma (/n/) e o elemento i tem o valor dado por SUM(MATRIZ_A(I,:)*MATRIZ_B). Para argumentos l´gicos, as formas s˜o as mesmas que para argumentos num´ricos e os valores s˜o o a e a determinados pela substitui¸˜o da fun¸˜o SUM e do operador “*” pela fun¸˜o ANY e pelo operador .AND.. ca ca ca 7.12 Fun¸oes transformacionais que reduzem matrizes c˜ H´ sete fun¸˜es transformacionais que executam opera¸˜es em matrizes, tais como somar seus elementos. a co co 7.12.1 Caso de argumento unico ´ Nas suas formas mais simples, estas fun¸˜es tˆm um unico argumento matricial e o resultado ´ um valor co e ´ e escalar. Todas, exceto COUNT tem o resultado do mesmo tipo e esp´cie que o argumento. e ALL(MASK). Retorna o valor .TRUE. se todos os elementos da matriz l´gica MASK forem verdadeiros ou se o MASK for nula; caso contr´rio, retorna o valor .FALSE. a ANY(MASK). Retorna o valor .TRUE. se algum dos elementos da matriz l´gica MASK for verdadeiro e o valor o .FALSE. se todos os elementos forem falsos ou se a matriz for nula. COUNT(MASK). Retorna o valor inteiro padr˜o igual ao n´mero de elementos da matriz MASK que tˆm o valor a u e .TRUE. MAXVAL(ARRAY). Retorna o valor m´ximo dentre os elementos da matriz ARRAY, a qual pode ser inteira a ou real. Se ARRAY for nula, a fun¸˜o retorna o valor negativo de maior magnitude suportado pelo ca processador. MINVAL(ARRAY). Retorna o valor m´ ınimo dentre os elementos da matriz ARRAY, a qual pode ser inteira ou real. Se ARRAY for nula, a fun¸˜o retorna o valor positivo de maior magnitude suportado pelo ca processador. PRODUCT(ARRAY). Retorna o produto de todos os elementos de uma matriz inteira, real ou complexa. A fun¸˜o retorna o valor 1 se ARRAY for nula. ca SUM(ARRAY). Retorna a soma de todos os elementos de uma matriz inteira, real ou complexa. A fun¸˜o ca retorna o valor 0 se ARRAY for nula. 7.12.2 Argumento opcional DIM Todas as fun¸˜es acima tˆm um segundo argumento opcional DIM, o qual ´ um inteiro escalar. Se co e e este argumento est´ presente, a opera¸˜o ´ aplicada a todas as se¸˜es de posto 1 que varrem atrav´s da a ca e co e dimens˜o DIM para produzir uma matriz de posto reduzido por um e extens˜es iguais `s extens˜es nas outras a o a o dimens˜es. Por exemplo, se A ´ uma matriz real de forma (/4,5,6/), SUM(A,DIM=2) ´ uma matriz real de o e e forma (/4,6/) e o seu elemento (i, j) tem o valor dado por SUM(A(I,:,J)). 7.12.3 Argumento opcional MASK As fun¸˜es MAXVAL, MINVAL, PRODUCT e SUM tˆm um terceiro argumento opcional; uma matriz l´gica co e o MASK. Se esta matriz estiver presente, ela deve ter a mesma forma que o primeiro argumento e a opera¸˜o ca ´ aplicada aos elementos do primeiro argumento correspondentes aos elementos verdadeiros de MASK. Por e exemplo, SUM(A, MASK= A>0) soma todos os elementos positivos da matriz A. O argumento MASK afeta somente o valor da fun¸˜o e n˜o afeta o desenvolvimento de argumentos que s˜o express˜es matriciais. ca a a o Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 83.
    Cap´ ıtulo 7. RotinasIntr´ ınsecas 7.13 75 Fun¸oes inquisidoras de matrizes c˜ H´ cinco fun¸˜es que inquirem sobre os limites, forma, tamanho e status de aloca¸˜o de uma matriz de a co ca qualquer tipo. Uma vez que o resultado depende somente nas propriedades da matriz, o valor desta n˜o a necessita ser definido. 7.13.1 Status de aloca¸˜o ca ALLOCATED(ARRAY). Retorna, quando a matriz aloc´vel ARRAY est´ correntemente alocada, o valor .TRUE.; a a na outra situa¸˜o, o valor .FALSE. ´ retornado. Se os status da aloca¸˜o ´ indefinido, o resultado ca e ca e tamb´m ´ indefinido. e e 7.13.2 Limites, forma e tamanho As fun¸˜es a seguir inquirem sobre as propriedades de uma matriz. No caso de uma matriz aloc´vel, co a esta deve estar alocada. No caso de um ponteiro (pointer), ele deve estar associado a um alvo (target). Uma se¸˜o de matriz ou uma express˜o matricial ´ assumida ter limite inferior 1 e limite superior igual `s ca a e a extens˜es. o LBOUND(ARRAY[,DIM]). Quando DIM ´ ausente, retorna uma matriz inteira padr˜o de posto um, a qual e a cont´m os limites inferiores. Quando DIM ´ presente, este deve ser um inteiro escalar e o resultado ´ e e e um escalar inteiro padr˜o com o valor do limite inferior na dimens˜o DIM. Como o posto do resultado a a depende da presen¸a de DIM, o argumento da fun¸˜o n˜o pode ser, por sua vez, um argumento mudo c ca a opcional. SHAPE(SOURCE). Retorna um vetor inteiro padr˜o contendo a forma da matriz ou escalar SOURCE. No caso a de um escalar, o resultado tem tamanho zero. SIZE(ARRAY[,DIM]). Retorna um escalar inteiro padr˜o igual ao tamanho da matriz ARRAY ou a extens˜o a a ao longo da dimens˜o DIM, caso este argumento esteja presente. a UBOUND(ARRAY[,DIM]). Similar a LBOUND exceto que retorna limites superiores. 7.14 Fun¸oes de constru¸˜o e manipula¸˜o de matrizes c˜ ca ca H´ oito fun¸˜es que constroem ou manipulam matrizes de qualquer tipo. a co 7.14.1 Fun¸˜o elemental MERGE ca MERGE(TSOURCE,FSOURCE,MASK). Trata-se de uma fun¸˜o elemental. TSOURCE pode ter qualquer tipo e ca FSOURCE deve ser do mesmo tipo e esp´cie. MASK deve ser do tipo l´gico. O resultado ´ TSOURCE se e o e MASK ´ verdadeiro ou FSOURCE no contr´rio. e a 7.14.2 Agrupando e desagrupando matrizes A fun¸˜o transformacional PACK agrupa dentro de um vetor aqueles elemento de uma matriz que s˜o ca a selecionados por uma matriz l´gica conforme e a fun¸˜o transformacional UNPACK executa a opera¸˜o reversa. o ca ca Os elementos s˜o tomados na ordem dos elementos das matrizes. a PACK(ARRAY,MASK[,VECTOR]). Quando VECTOR ´ ausente, retorna um vetor contendo os elementos de ARRAY e correspondentes aos valores verdadeiros de MASK na ordem dos elementos das matrizes. MASK pode ser um escalar de valor .TRUE.; em cujo caso, todos os elementos s˜o selecionados. Se VECTOR ´ presente, a e este deve ser um vetor do mesmo tipo e esp´cie de ARRAY e tamanho no m´ e ınimo igual ao n´mero t de u elementos selecionados. O resultado, neste caso, tem tamanho igual ao tamanho n do VECTOR; se t < n, elementos i do resultado para i > t s˜o os elementos correspondentes de VECTOR. a UNPACK(VECTOR,MASK,FIELD). Retorna uma matriz do tipo e esp´cie de VECTOR e da forma de MASK. MASK e deve ser uma matriz l´gica e VECTOR deve ser um vetor de tamanho no m´ o ınimo igual ao n´mero de u elementos verdadeiros de MASK. FIELD deve ser do mesmo tipo e esp´cie de VECTOR e deve ou ser e escalar ou ter a mesma forma que MASK. O elemento do resultado correspondendo ao i -´simo elemento e verdadeiro de MASK, na ordem dos elementos da matriz, ´ o i -´simo elemento de VECTOR; todos os e e outros s˜o iguais aos correspondentes elementos de FIELD se este for uma matriz ou igual a FIELD se a este for um escalar. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 84.
    76 7.15. Fun¸˜es transformacionaispara localiza¸˜o geom´trica co ca e 7.14.3 Alterando a forma de uma matriz A fun¸˜o transformacional RESHAPE permite que a forma de uma matriz seja alterada, com a poss´ ca ıvel permuta¸˜o dos ´ ca ındices. RESHAPE(SOURCE,SHAPE[,PAD][,ORDER]). Retorna uma matriz com forma dada pelo vetor inteiro SHAPE e tipo e esp´cie iguais aos da matriz SOURCE. O tamanho de SHAPE deve ser constante e seus elementos e n˜o podem ser negativos. Se PAD est´ presente, esta deve ser uma matriz do mesmo tipo e esp´cie a a e de SOURCE. Se PAD estiver ausente ou for uma matriz de tamanho zero, o tamanho do resultado n˜o a deve exceder o tamanho de SOURCE. Se ORDER estiver ausente, os elementos da matriz resultante, arranjados na ordem de elementos de matrizes (se¸˜o 6.6.2), s˜o os elementos de SOURCE, seguidos ca a por c´pias de PAD, tamb´m na ordem de elementos de matrizes. Se ORDER estiver presente, este deve o e ser um vetor inteiro com um valor que ´ uma permuta¸˜o de (1, 2, ..., n); os elementos R(s1 , . . . , sn ) e ca do resultado, tomados na ordem dos ´ ındices para a matriz tendo elementos R(sordem(1) , . . . , sordem(n) ), s˜o aqueles de SOURCE na ordem de elementos de matriz seguidos por c´pias de PAD, tamb´m na a o e ordem de elementos de matriz. Por exemplo, se ORDER tem o valor (/3,1,2/), os elementos R(1,1,1), R(1,1,2), ..., R(1,1,k ), R(2,1,1), R(2,1,2), ... correspondem aos elementos de SOURCE e PAD na ordem de elementos de matriz. 7.14.4 Fun¸˜o transformacional para duplica¸˜o ca ca SPREAD(SOURCE,DIM,NCOPIES). Retorna uma matriz do tipo e esp´cie de SOURCE e de posto acrescido por e um. SOURCE pode ser escalar ou matriz. DIM e NCOPIES s˜o inteiros escalares. O resultado cont´m a e MAX(NCOPIES,0) c´pias de SOURCE e o elemento (r1 , . . . , rn+1 ) do resultado ´ SOURCE(s1 , . . . , sn ), onde o e (s1 , . . . , sn ) ´ (r1 , . . . , rn+1 ) com subscrito DIM omitido (ou a pr´pria SOURCE se esta for um escalar). e o 7.14.5 Fun¸oes de deslocamento matricial c˜ CSHIFT(ARRAY,SHIFT[,DIM]). Retorna uma matriz do mesmo tipo, esp´cie e forma de ARRAY. DIM ´ um e e escalar inteiro. Se DIM for omitido, o seu valor ser´ assumido igual a 1. SHIFT ´ do tipo inteiro e deve a e ser um escalar se ARRAY tiver posto um. Se SHIFT ´ escalar, o resultado ´ obtido deslocando-se toda e e se¸˜o vetorial que se estende ao longo da dimens˜o DIM de forma circular SHIFT vezes. O sentido do ca a deslocamento depende do sinal de SHIFT e pode ser determinado a partir do caso com SHIFT= 1 e ARRAY de posto um e tamanho m, quando o elemento i do resultado ´ ARRAY(i + 1), i= 1, 2, ..., m-1 e e o elemento m ´ ARRAY(1). Se SHIFT for uma matriz, esta deve ter a forma de ARRAY com a dimens˜o e a DIM omitida; desta forma, SHIFT oferece um valor distinto para cada deslocamento. ´ e EOSHIFT(ARRAY,SHIFT[,BOUNDARY][,DIM]). E idˆntica a CSHIFT, exceto que um deslocamento final ´ exee cutado e valores de borda s˜o inseridos nas lacunas assim criadas. BOUNDARY pode ser omitida quando a ARRAY tiver tipo intr´ ınsecos, em cujo caso o valor zero ´ inserido para os casos inteiro, real e complexo; e .FALSE. no caso l´gico e brancos no caso de caracteres. Se BOUNDARY estiver presente, deve ser do o mesmo tipo e esp´cie de ARRAY; ele pode ser um escalar e prover todos os valores necess´rios ou pode e a ser uma matriz cuja forma ´ a de ARRAY com dimens˜o DIM omitida e prover um valor separado para e a cada deslocamento. 7.14.6 Transposta de uma matriz A fun¸˜o TRANSPOSE executa a transposi¸ao matricial para qualquer matriz de posto dois. ca c˜ TRANSPOSE(MATRIX). Retorna uma matriz do mesmo tipo e esp´cie da matriz de posto dois MATRIX. Elee mento (i,j ) do resultado ´ igual a MATRIX(i,j ). e 7.15 Fun¸oes transformacionais para localiza¸˜o geom´trica c˜ ca e H´ duas fun¸˜es transformacionais que localizam as posi¸˜es dos valores m´ximos e m´ a co co a ınimos de uma matriz inteira ou real. MAXLOC(ARRAY,DIM[,MASK]) ou MAXLOC(ARRAY[,MASK]). Retorna um vetor inteiro padr˜o de tamanho a igual ao posto de ARRAY. Seu valor ´ a seq¨ˆncia de subscritos de um elemento de valor m´ximo (dentre e ue a aqueles correspondentes aos elementos de valor .TRUE. da matriz l´gica MASK, caso esta exista), como o se todos os limites inferiores de ARRAY fossem iguais a 1. Se houver mais de um elemento com o mesmo Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 85.
    Cap´ ıtulo 7. RotinasIntr´ ınsecas 77 valor m´ximo, o primeiro na ordem de elementos de matriz ´ assumido. Caso o argumento DIM esteja a e presente, este ´ um escalar inteiro padr˜o que indica a dimens˜o ao longo da qual o valor m´ximo deve e a a a ser procurado. O compilador pode disting¨ir sem aux´ caso o segundo argumento seja DIM ou MASK u ılio pelo fato de que o tipo de vari´vel ´ distinto. a e MINLOC(ARRAY,DIM[,MASK]) ou MAXLOC(ARRAY[,MASK]). Retorna um vetor inteiro padr˜o de tamanho a igual ao posto de ARRAY. Seu valor ´ a seq¨ˆncia de subscritos de um elemento de valor m´ e ue ınimo (dentre aqueles correspondentes aos elementos de valor .TRUE. da matriz l´gica MASK, caso esta exista), como o se todos os limites inferiores de ARRAY fossem iguais a 1. Se houver mais de um elemento com o mesmo valor m´ ınimo, o primeiro na ordem de elementos de matriz ´ assumido. e 7.16 Fun¸˜o transformacional para dissocia¸˜o de ponteiro ca ca Em Fortran 95, a fun¸˜o NULL est´ dispon´ para fornecer status de dissociado a ponteiros. ca a ıvel NULL([MOLDE]). Retorna um pointer dissociado. O argumento MOLDE ´ um ponteiro de qualquer tipo e que e pode ter qualquer status, inclusive de indefinido. O tipo, esp´cie e posto do resultado s˜o aqueles e a de MOLDE se ele est´ presente; em caso contr´rio, s˜o aqueles do objeto com o qual o ponteiro est´ a a a a associado. 7.17 Subrotinas intr´ ınsecas n˜o-elementais a H´ cinco subrotinas intr´ a ınsecas n˜o elementais, as quais foram escolhidas ser subrotinas no lugar de a fun¸˜es devido ` necessidade destas retornarem diversas informa¸˜es atrav´s de seus argumentos. co a co e 7.17.1 Rel´gio de tempo real o H´ duas subrotinas que retornam informa¸˜o acerca do rel´gio de tempo real; a primeiro ´ baseada no a ca o e padr˜o ISO 8601 (Representa¸˜o de datas e tempos). Assume-se que exista um rel´gio b´sico no sistema a ca o a que ´ incrementado por um para cada contagem de tempo at´ que um valor m´ximo COUNT_MAX ´ alcan¸ado e e a e c e da´ na pr´xima contagem de tempo, este ´ zerado. Valores padronizados s˜o retornados em sistemas sem ı, o e a rel´gio. Todos os argumentos tˆm inten¸˜o OUT (se¸˜o 8.2.5). Adicionalmente, h´ uma subrotina que acessa o e ca ca a o rel´gio interno do processador. o Acesso a qualquer argumento opcional pode ser realizado atrav´s do uso das palavras-chave (se¸˜es 8.2.8 e co e 8.2.9). CALL DATE_AND_TIME([DATE][,TIME][,ZONE][,VALUES]). Retorna os seguintes valores (com valores-padr˜o a nulos ou -HUGE(0), conforme apropriado, caso n˜o haja rel´gio): a o DATE ´ uma vari´vel escalar de caractere da esp´cie padr˜o que cont´m a data na forma ccyymmdd, e a e a e correspondendo ao s´culo, ano, mˆs e dia, respectivamente. e e TIME ´ uma vari´vel escalar de caractere padr˜o que cont´m o tempo na forma hhmmss.sss, correse a a e pondendo a horas, minutos, segundos e milisegundos, respectivamente. ZONE ´ uma vari´vel escalar de caractere padr˜o que ´ fixada como a diferen¸a entre o tempo local e e a a e c o Tempo Coordenado Universal (UTC, de Coordinated Universal Time, tamb´m conhecido como e Tempo M´dio de Greenwich, ou Greenwich Mean Time) na forma Shhmm, correspondendo ao e sinal, horas e minutos, respectivamente. Por exemplo, a hora local de Bras´ corresponde a UTC= ılia -0300. VALUES ´ um vetor inteiro padr˜o que cont´m a seguinte seq¨ˆncia de valores: o ano, o mˆs do ano, e a e ue e o dia do mˆs, a diferen¸a temporal em minutos com rela¸˜o ao UTC, a hora do dia, os minutos e c ca da hora, os segundos do minuto e os milisegundos do segundo. CALL SYSTEM_CLOCK([COUNT][,COUNT_RATE][,COUNT_MAX]). Retorna o seguinte: COUNT ´ uma vari´vel escalar inteira padr˜o que cont´m o valor, dependente do processador, que e a a e correspondem ao valor corrente do rel´gio do processador, ou -HUGE(0) caso n˜o haja rel´gio. o a o Na primeira chamada da subrotina, o processador pode fixar um valor inicial igual a zero. COUNT_RATE ´ uma vari´vel escalar inteira padr˜o que cont´m o n´mero de contagens por segundo do e a a e u rel´gio, ou zero caso n˜o haja rel´gio. o a o COUNT_MAX ´ uma vari´vel escalar inteira padr˜o que cont´m o valor m´ximo que COUNT pode assumir, e a a e a ou zero caso n˜o haja rel´gio. a o Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 86.
    78 7.17. Subrotinas intr´ ınsecasn˜o-elementais a 7.17.2 Tempo da CPU Em Fortran 95, h´ uma subrotina intr´ a ınseca n˜o-elemental que retorna o tempo do processador. a CALL CPU_TIME(TIME). Retorna o seguinte: TIME ´ uma vari´vel real escalar padr˜o ` qual ´ atribu´ uma aproxima¸˜o (dependente de procese a a a e ıda ca sador) do tempo do processador em segundos, ou um valor negativo (dependente de processador) caso n˜o haja rel´gio. a o 7.17.3 N´ meros aleat´rios u o Uma seq¨ˆncia de n´meros pseudo-aleat´rios ´ gerada a partir de uma semente que ´ fornecida como um ue u o e e vetor de n´meros inteiros. A subrotina RANDOM_NUMBER retorna os n´meros pseudo-aleat´rios e a subrotina u u o RANDOM_SEED permite que uma inquiri¸˜o seja feita a respeito do tamanho ou valor do vetor-semente e, ent˜o, ca a redefinir o mesmo. As subrotinas fornecem uma interface a uma seq¨ˆncia que depende do processador. ue CALL RANDOM_NUMBER(COLHE) Retorna um n´mero pseudo-aleat´rio a partir da distribui¸˜o uniforme de u o ca n´meros no intervalo 0 ≤ x < 1 ou um vetor destes n´meros. COLHE tem inten¸˜o OUT, pode ser um u u ca escalar ou vetor e deve ser do tipo real. CALL RANDOM_SEED([SIZE][,PUT][,GET]). Tem os argumentos abaixo. N˜o mais de um argumento pode a ser especificado; caso nenhum argumento seja fornecido, a semente ´ fixada a um valor dependente do e processador. SIZE tem inten¸˜o OUT e ´ um inteiro escalar padr˜o que o processador fixa com o tamanho n do ca e a vetor-semente. PUT tem inten¸˜o IN e ´ um vetor inteiro padr˜o de tamanho n que ´ usado pelo processador para ca e a e fixar uma nova semente. Um processador pode fixar o mesmo valor de semente para mais de um valor de PUT. GET tem inten¸˜o OUT e ´ um vetor inteiro padr˜o de tamanho n que o processador fixa como o valor ca e a atual da semente. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 87.
    Cap´ ıtulo 8 Sub-Programas eM´dulos o Como foi visto nos cap´ ıtulos anteriores, ´ poss´ escrever um programa completo em Fortran em um e ıvel unico arquivo, ou como uma unidade simples. Contudo, se o c´digo ´ suficientemente complexo, pode ser ´ o e necess´rio que um determinado conjunto de instru¸˜es seja realizado repetidas vezes, em pontos distintos a co do programa. Um exemplo desta situa¸˜o seria a defini¸˜o de uma fun¸˜o extr´ ca ca ca ınseca, ou seja, n˜o contida a no conjunto de fun¸˜es intr´ co ınsecas discutidas no cap´ ıtulo 7. Neste caso, ´ melhor quebrar o programa em e unidades distintas. Cada uma das unidades de programa corresponde a um conjunto completo e consistente de tarefas que podem ser, idealmente, escritas, compiladas e testadas individualmente, sendo posteriormente inclu´ ıdas no programa principal para gerar um arquivo execut´vel. Em Fortran h´ dois tipos de estruturas que se a a encaixam nesta categoria: subrotinas e fun¸˜es (externas ou extr´ co ınsecas). Em Fortran 77, havia somente dois tipos de unidades de programas distintas: ˆ Programa principal. ˆ Rotinas externas. Em Fortran 90/95, existem, ao todo, trˆs unidades distintas de programa: e ˆ Programa principal. ˆ Rotinas externas. ˆ M´dulos. o Cada uma destas unidades de programas ser˜o discutidas nas se¸˜es seguintes. a co Neste cap´ ıtulo (e nos posteriores), os termos rotina (procedure) e sub-programa ser˜o usados alternadaa mente para indicar de forma gen´rica tanto subrotinas quanto fun¸˜es. Outros textos podem vir a tratar e co estes dois termos como representando entidades ligeiramente distintas. 8.1 Unidades de programa Tanto em Fortran 77 quanto em Fortran 90/95, um c´digo execut´vel ´ criado a partir de um e somente o a e um programa principal, o qual pode invocar rotinas externas e, no caso do Fortran 90/95, pode usar tamb´m e m´dulos. A unica unidade de programa que deve necessariamente existir sempre ´ o programa principal. o ´ e Com a introdu¸˜o do Fortran 90/95, quaisquer uma destas trˆs unidades de programas podem tamb´m ca e e invocar rotinas internas, as quais tˆm estrutura semelhante `s rotinas externas, por´m n˜o podem ser e a e a testadas isoladamente. Um diagrama ilustrativo das trˆs unidades de programas existentes no Fortran e 90/95 pode ser visto na figura 8.1. Uma descri¸˜o mais completa das unidades de programas ´ dada a seguir. ca e 8.1.1 Programa principal Todo c´digo execut´vel deve ser composto a partir de um, e somente um, programa principal. Opcioo a nalmente, este pode invocar sub-programas. Um programa principal possui a seguinte forma: 79
  • 88.
    80 8.1. Unidades deprograma Programa Principal Modulo Rotina Externa Rotina de Modulo Rotina Interna Figura 8.1: As trˆs unidades de programa, as quais podem possuir tamb´m rotinas internas. e e [PROGRAM <nome do programa> [<declara¸~es de vari´veis>] co a [<comandos execut´veis>] a [CONTAINS <sub-programas internos> END [PROGRAM [<nome do programa>]] A declara¸˜o PROGRAM ´ opcional, por´m o seu uso ´ recomendado.1 O unico campo n˜o opcional na estrutura ca e e e ´ a de um programa, na defini¸˜o do padr˜o da linguagem, ´ a instru¸˜o END, a qual possui dois prop´sitos: ca a e ca o indicar ao compilador que o programa chegou ao fim e, quando da execu¸˜o do c´digo, provoca a parada do ca o mesmo. Nos cap´ ıtulos anteriores, j´ foram dados v´rios exemplos da estrutura do programa principal e, portanto, a a maiores detalhes n˜o s˜o necess´rios aqui. a a a A declara¸˜o CONTAINS indica a presen¸a de um ou mais sub-programas internos. Estes ser˜o descritos ca c a em mais detalhes na se¸˜o 8.2.2. Se a execu¸˜o do ultimo comando anterior a CONTAINS n˜o provoca um ca ca ´ a desvio de percurso na execu¸˜o do programa, atrav´s de uma instru¸˜o GO TO, por exemplo, o controle passa ca e ca por sobre os sub-programas internos ao comando END e o programa p´ra. a O comando END pode ser rotulado e ser ent˜o atingido por um desvio de execu¸˜o, como no exemplo a ca ... GO TO 100 ... 100 END PROGRAM em cuja situa¸˜o o programa tamb´m termina. Contudo, este estilo de programa¸˜o ´ t´ ca e ca e ıpico do Fortran 77, mas n˜o ´ recomendado pelo padr˜o do Fortran 90/95. a e a O comando STOP. Outra forma de interromper a execu¸˜o do programa ´ atrav´s do comando STOP, o ca e e qual pode ser rotulado, pode ser parte de um comando ou construto IF e ´ um comando que pode aparecer e no programa principal ou em um sub-programa. 1 No caso do compilador F, ´ obrigat´rio. e o Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 89.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 81 Caso haja v´rios comandos STOP em uma mesma unidade, estes podem ser disting¨idos por um c´digo a u o de acesso, que se trata de uma constante de caractere ou uma string de at´ 5 d´ e ıgitos. Isto originar´ uma a mensagem na sa´ padr˜o indicando o ponto onde a execu¸˜o foi terminada. A seguir, dois exemplos deste ıda a ca caso: STOP ’Dados incompletos. STOP 12345 8.1.2 Programa interrompido.’ Rotinas externas Rotinas externas s˜o chamadas de dentro de um programa principal ou de outra unidade, usualmente a com o intuito de executar uma tarefa bem definida dentro dos objetivos cumpridos pelo programa completo. Rotinas externas s˜o escritas em arquivos distintos, separados do arquivo do programa principal. a Durante o processo de cria¸˜o do programa execut´vel, estas rotinas podem ser compiladas conjuntaca a mente com o programa principal ou em separado. Nesta ultima situa¸˜o, os programas objetos criados ´ ca durante compila¸˜es pr´vias das rotinas externas s˜o linkados junto com o programa objeto do programa co e a principal. Embora seja poss´ colocar-se mais de uma rotina externa no mesmo arquivo, esta pr´tica n˜o ıvel a a ´ recomendada. e 8.1.3 M´dulos o O terceiro tipo de unidade de programa, exclusivo no Fortran 90/95, ´ o m´dulo. Trata-se de uma e o maneira de se agrupar dados globais, tipos derivados e suas opera¸˜es associadas, blocos de interface, grupos co NAMELIST (se¸˜o 9.2) e rotinas internas. Tudo associado com uma determinada tarefa pode ser coletado ca dentro de um m´dulo e acessado quando necess´rio. Aquelas partes que s˜o restritas ao funcionamento o a a interno da tarefa e n˜o s˜o do interesse direto do programador podem ser feitas “invis´ a a ıveis” a este, o que permite que o funcionamento interno do m´dulo possa ser alterado sem a necessidade de alterar o programa o que o usa, prevenindo-se assim altera¸˜o acidental dos dados. ca Um m´dulo tem a seguinte forma: o MODULE <nome m´dulo> o <declara¸~es de vari´veis> co a [CONTAINS <rotinas de m´dulo> o END [MODULE [<nome m´dulo>]] o Assim como para END PROGRAM, ´ recomendado o uso da forma completa do comando END. e Uma discuss˜o mais extensa acerca dos m´dulos em Fortran 90/95 ser´ feita na se¸˜o 8.3. a o a ca 8.2 Sub-programas sub-programas podem ser subrotinas ou fun¸˜es. Como j´ foi mencionado, tarefas que podem ser delico a mitadas por um n´mero finito de opera¸˜es e que devem ser realizadas repetidas vezes durante a execu¸˜o u co ca de um programa devem ser escritas como sub-programas. Uma fun¸˜o retorna um unico valor, o qual pode ser um escalar ou uma matriz, e esta usualmente n˜o ca ´ a altera os valores de seus argumentos2 . Neste sentido, uma fun¸˜o em Fortran age como uma fun¸˜o em ca ca an´lise matem´tica. J´ uma subrotina pode executar uma tarefa mais complexa e retornar diversos valores a a a atrav´s de seus argumentos, os quais podem ser modificados ao longo da computa¸˜o da subrotina. e ca 8.2.1 Fun¸˜es e subrotinas co Exceto pela declara¸˜o inicial, os sub-programas apresentam uma forma semelhante a de um programa ca principal. Um sub-programa pode ser uma subrotina: [PURE] [ELEMENTAL] [RECURSIVE] SUBROUTINE <nome subrotina> [(<lista argumentos mudos>)] [<declara¸~es de vari´veis>] co a 2 Situa¸˜es co onde este requisito pode ser relaxado e como estabelecer salvaguardas s˜o discutidas na se¸˜o 8.2.16. a ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 90.
    82 8.2. Sub-programas [<comandos execut´veis>] a [CONTAINS <sub-programasinternos>] END [SUBROUTINE [<nome subrotina>]] ou pode ser uma fun¸˜o: ca [PURE] [ELEMENTAL] [<tipo>] [RECURSIVE] FUNCTION <nome fun¸~o> & ca (<lista argumentos mudos>)[RESULT (<nome resultado>)] [<declara¸~es de vari´veis>] co a [<comandos execut´veis>] a [CONTAINS <sub-programas internos>] END [FUNCTION [<nome fun¸~o>]] ca Os diversos constituintes das formas gerais apresentadas acima ser˜o discutidos em detalhes nas se¸˜es a co seguintes. Por enquanto, ser˜o apresentados alguns dos atributos usualmente empregados no campo de a <declara¸~es de vari´veis> de um sub-programa. Al´m dos atributos j´ vistos, relacionados com as co a e a declara¸˜es de tipo e esp´cie de vari´veis, dos atributos DIMENSION e ALLOCATABLE, os seguintes atributos co e a podem ser usados: INTENT([IN][OUT][INOUT]) OPTIONAL SAVE EXTERNAL INTRINSIC POINTER TARGET A declara¸˜o CONTAINS cumpre exatamente o mesmo papel cumprido dentro do programa principal. O efeito ca do comando END em um sub-programa consiste em retornar o controle ` unidade que o chamou, ao inv´s a e de interromper a execu¸˜o do programa. Aqui tamb´m recomenda-se o uso da forma completa do comando ca e para deixar claro ao compilador e ao programador qual parte do programa est´ sendo terminada. a Uma fun¸˜o ´ ativada ou chamada de forma semelhante como se usa uma fun¸˜o em an´lise matem´tica. ca e ca a a Por exemplo, dada a fun¸˜o BESSELJ(n,x), a qual calcula Jn (x), o valor da fun¸˜o de Bessel do primeiro ca ca tipo de ordem n no ponto x. Esta fun¸˜o pode ser chamada para atribuir seu valor a uma vari´vel escalar ca a ou a um elemento de matriz: y= BESSELJ(n,x) sendo que o tipo e esp´cie de y devem, em princ´ e ıpio, concordar com o tipo e esp´cie do resultado de e BESSELJ(n,x). Contudo, caso isto n˜o ocorra, valem as regras de convers˜o definidas no cap´ a a ıtulo 4. Uma fun¸˜o pode tamb´m fazer o papel de um operando em uma express˜o: ca e a y= BESSELJ(n,x) + 2*BESSELJ(n,x**2) ou ainda servir de argumento para uma outra rotina. Uma subrotina, devido ao fato de esta retornar, em geral, mais de um valor em cada chamada, n˜o pode a ser operada como uma fun¸˜o em an´lise matem´tica mas deve, isto sim, ser chamada atrav´s da instru¸˜o ca a a e ca CALL. Supondo que exista a subrotina BASCARA, a qual calcula as ra´ ızes de um polinˆmio de segundo grau, o x1 e x2, estas ser˜o obtidas atrav´s da chamada: a e CALL BASCARA(A0,A1,A2,X1,X2) onde os argumentos da subrotina ser˜o discutidos na se¸˜o 8.2.3 e posteriores. Por exemplo, ´ poss´ a ca e ıvel usar-se uma fun¸˜o como argumento da subrotina: ca CALL BASCARA(A0,A1,BESSELJ(n,x),x1,x2) Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 91.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 8.2.2 83 Rotinas internas J´ foi observado nas se¸˜es anteriores que rotinas internas podem ser definidas dentro de quaisquer a co unidades de programa. Uma rotina interna possui a seguinte estrutura: [RECURSIVE] SUBROUTINE <nome subrotina> [(<lista argumentos mudos>)] [<declara¸~es de vari´veis>] co a [<comandos execut´veis>] a END SUBROUTINE [<nome subrotina>]] ou [<tipo>] [RECURSIVE] FUNCTION <nome fun¸~o> (<lista argumentos mudos>) & ca [RESULT (<nome resultado>)] [<declara¸~es de vari´veis>] co a [<comandos execut´veis>] a END FUNCTION [<nome fun¸~o>]] ca Nota-se agora que as declara¸˜es FUNCTION e SUBROUTINE agora s˜o obrigat´rias no comando END. Uma co a o determinada unidade de programa pode conter qualquer n´mero de rotinas internas, por´m estas, por sua u e vez, n˜o podem conter outras rotinas internas. a Cabe aqui uma men¸˜o a respeito da diferen¸a entre uma rotina interna e uma rotina de m´dulo. Esta ca c o ultima tamb´m ´ inclu´ depois da palavra-chave CONTAINS, em um m´dulo, mas pode conter rotinas ´ e e ıda o internas a ela. Uma rotina interna automaticamente tem acesso a todas as entidades do hospedeiro, tais como vari´veis, a e possuem tamb´m a habilidade de chamar as outras rotinas deste. Contudo, uma determinada rotina e interna n˜o possui acesso `s entidades de outra rotina interna. a a Um exemplo simples do uso de uma fun¸˜o interna ´ apresentado a seguir. Note que a vari´vel a ´ ca e a e declarada no programa principal, tornando-se assim uma vari´vel declarada tamb´m dentro do ˆmbito da a e a fun¸˜o calc_a_raiz: ca program r o t i n t i m p l i c i t none real : : x , a ! print * , ”Entre com o v a l o r de x : ” read * , x print * , ”Entre com o v a l o r de a : ” read * , a print * , ”O r e s u l t a d o de a + s q r t ( x ) ´ : ” e print * , c a l c a r a i z ( x ) print * , ”O r e s u l t a d o de a + s q r t (1+ x * * 2 ) ´ : ” e print * , c a l c a r a i z ( 1 . 0 + x * * 2 ) CONTAINS function c a l c a r a i z ( y ) real :: calc a raiz real , intent ( in ) : : y c a l c a r a i z= a + s q r t ( y ) return end function c a l c a r a i z end program r o t i n t No restante deste cap´ ıtulo, ser˜o descritas v´rias propriedades que se aplicam a sub-programas internos, a a externos e a rotinas de m´dulos. o 8.2.3 Argumentos de sub-programas Argumentos de sub-programas fornecem um meio alternativo para que duas unidades de programa compartilhem os mesmos dados. Estes consistem em uma lista de vari´veis escalares ou matriciais, constantes, a express˜es escalares ou matriciais e at´ mesmo os nomes de outras rotinas. Os argumentos de um subo e programa s˜o muitas vezes denominados vari´veis mudas (dummy variables). Estes devem coincidir com a a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 92.
    84 8.2. Sub-programas os argumentostransferidos a partir da unidade que chama a rotina em tipo, esp´cie e forma. Contudo, os e nomes n˜o necessitam ser os mesmos, como se pode ver no exemplo acima. Com base no mesmo exemplo, a poder-se-ia realizar duas chamadas da fun¸˜o calc_a_raiz: ca ... read*, a,x print*, calc_a_raiz(x) print*, calc_a_raiz(a + x**2) ... Sempre que poss´ ıvel, ´ recomendado que o nome do argumento transferido ao sub-programa seja igual ao e nome da vari´vel muda. O ponto importante ´ que sub-programas podem ser escritos de forma independente a e uns dos outros. A associa¸˜o das vari´veis mudas com os argumentos verdadeiros ocorrem somente quando ca a a rotina ´ chamada. Desta forma, bibliotecas de sub-programas podem ser constru´ e ıdos, possibilitando que estes sejam usados em diferentes programas (ver se¸˜o 8.2.6). ca O programa-exemplo bascara1, apresentado na p´gina 85, implementa, de forma ingˆnua, o c´lculo das a e a ra´ ızes de um polinˆmio de segundo grau atrav´s da F´rmula de B´scara usando uma subrotina interna. o e o a Exemplos semelhantes a este ser˜o usados para ilustrar o uso de rotinas em outras unidades de programa. a 8.2.4 Comando RETURN No padr˜o da linguagem, um sub-programa pode ser encerrado pelo comando END, sendo o controle do a fluxo retornado ` unidade que chamou este sub-programa. Contudo, o meio recomendado de se retornar a controle a partir de um sub-programa consiste na utiliza¸˜o do comando RETURN, o qual pode surgir em ca mais de um ponto da rotina, ao contr´rio do END. a Como no caso dos comandos STOP e END, o RETURN pode ser rotulado, pode fazer parte de um construto como o IF e ´ um comando execut´vel. O RETURN n˜o pode aparecer entre os comandos execut´veis do e a a a programa principal. 8.2.5 Atributo e declara¸˜o INTENT ca No programa bascara1, (programa 8.1) as vari´veis mudas a0, a1 e a2 foram utilizadas para transferir ` a a subrotina informa¸˜o acerca dos coeficientes do polinˆmio de 2º grau. Por isto, estes nomes foram declarados ca o ter a inten¸˜o INTENT(IN). Por outro lado, a subrotina devolveu ao programa os valores das ra´ ca ızes reais (caso existam) atrav´s das vari´veis mudas r1 e r2, as quais foram declaradas ter a inten¸˜o INTENT(OUT). e a ca Uma terceira possibilidade seria a existˆncia de uma vari´vel cujo valor ´ inicialmente transferido para e a e dentro da subrotina, modificado por esta e, ent˜o transferido para fora da subrotina. Neste caso, esta a vari´vel deveria ser declarada com a inten¸˜o INTENT(INOUT). a ca Se uma vari´vel muda ´ especificada com atributo INTENT(IN), o seu valor n˜o pode ser alterado pela a e a rotina, seja atrav´s de atribui¸˜o de valor a partir de uma express˜o, ou atrav´s de sua transferˆncia para e ca a e e uma outra rotina que, por sua vez, alteraria este valor. Se a vari´vel ´ especificada com INTENT(OUT), o seu valor ´ indefinido na chamada da rotina, sendo este a e e ent˜o definido durante a execu¸˜o da mesma e finalmente transferido ` unidade que chamou a rotina. a ca a Se a vari´vel ´ especificada com INTENT(INOUT), esta tem o seu valor inicial transferido na chamada da a e rotina, o valor pode ser alterado e, ent˜o, o novo valor pode ser devolvido ` unidade que chamou a rotina. a a ´ E recomendado que a inten¸˜o de todas as vari´veis mudas seja declarada. Em fun¸˜es, vari´veis mudas ca a co a somente podem ser declaradas com INTENT(IN). Como alternativa ao uso do atributo INTENT(INOUT), pode-se declarar a inten¸˜o de nomes de argumentos ca mudos de rotinas, que n˜o sejam sub-programas mudos, atrav´s da declara¸˜o INTENT(INOUT), a qual tem a e ca a forma geral: INTENT(<inout>) [::] <lista nomes argumentos mudos> Por exemplo, SUBROUTINE SOLVE(A, B, C, X, Y, Z) REAL :: A, B, C, X, Y, Z INTENT(IN) :: A, B, C INTENT(OUT) :: X, Y, Z ... Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 93.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 85 Programa 8.1: Exemplo de emprego de rotinas internas. program b a s c a r a 1 i m p l i c i t none logical : : controle real : : a , b , c r e a l : : x1 , x2 ! R a i z e s r e a i s . ! do print * , ”Entre com o s v a l o r e s dos c o e f i c i e n t e s ( a , b , c ) , ” print * , ”onde a * x ** 2 + b * x + c . ” read * , a , b , c c a l l b a s c a r a ( a , b , c , c o n t r o l e , x1 , x2 ) i f ( c o n t r o l e ) then print * , ”As r a i z e s ( r e a i s ) s a o : ” print * , ”x1=” , x1 print * , ”x2=” , x2 e xi t else print * , ”As r a i z e s s a o complexas . Tente novamente . ” end i f end do CONTAINS subroutine b a s c a r a ( a2 , a1 , a0 , r a i z e s r e a i s , r1 , r 2 ) ! V a r i a v e i s mudas : real , intent ( in ) : : a0 , a1 , a2 l o g i c a l , intent ( out ) : : r a i z e s r e a i s real , intent ( out ) : : r1 , r 2 ! Variaveis l o ca is : real : : d i s c ! r a i z e s r e a i s= t e s t a d i s c ( a2 , a1 , a0 ) i f ( . not . r a i z e s r e a i s ) return d i s c= a1 * a1 − 4 * a0 * a2 r 1= 0.5 * ( − a1 − s q r t ( d i s c ) ) / a2 r 2= 0.5 * ( − a1 + s q r t ( d i s c ) ) / a2 return end subroutine b a s c a r a ! function t e s t a d i s c ( c2 , c1 , c0 ) logical : : testa disc ! V a r i a v e i s mudas : real , intent ( in ) : : c0 , c1 , c2 i f ( c1 * c1 − 4 * c0 * c2 >= 0 . 0 ) then t e s t a d i s c= . t r u e . else t e s t a d i s c= . f a l s e . end i f return end function t e s t a d i s c end program b a s c a r a 1 Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 94.
    86 8.2. Sub-programas 8.2.6 Rotinas externase bibliotecas Em muitas situa¸˜es, uma determinada rotina ´ escrita com o intuito de ser utilizada em diversas co e aplica¸˜es distintas. Um exemplo seria uma rotina gen´rica que calcula a integral de uma fun¸˜o qualquer co e ca entre dois pontos reais. Nesta situa¸˜o, ´ mais interessante manter a rotina como uma entidade distinta do ca e programa principal, para que esta possa ser utilizada por outras unidades de programas. Por isto, uma ou mais rotinas podem ser escritas em um arquivo em separado, constituindo uma unidade de programa pr´pria, j´ mencionada na se¸˜o 8.1.2. Esta unidade pode ent˜o ser compilada em separado, o a ca a quando ser´ ent˜o gerado o programa-objeto correspondente a esta parte do c´digo. Este programa-objeto a a o ´ ent˜o acessado pelo programa linkador para gerar o programa execut´vel, ligando a(s) rotina(s) contida(s) e a a nesta unidade com as outras unidades que fazem referˆncia `(s) mesma(s). O procedimento para realizar e a esta linkagem ´ realizado, usualmente, de duas maneiras distintas: e 1. O(s) programa-objeto(s) ´(s˜o) linkado(s) diretamente com as demais unidades de programa. Neste e a caso, o compilador e o linkador identificam a existˆncia do programa-objeto pela sua extens˜o, fornecida e a na linha de comando que demanda a cria¸˜o do c´digo execut´vel. A extens˜o de um programa-objeto ca o a a ´ usualmente *.o em sistemas operacionais Linux/Unix ou *.obj em sistemas DOS/Windows. e 2. O programa-objeto rec´m criado ´ armazenado, inicialmente, em uma biblioteca de programas-objeto e e criados anteriormente. Ent˜o, no momento de se gerar o c´digo execut´vel a partir de um programaa o a fonte, o linkador ´ instru´ com o nome e o endere¸o da biblioteca que cont´m o(s) programa-objeto(s) e ıdo c e da(s) rotina(s) chamadas pelo programa principal e/ou por outras unidades de programas. O linkador procura nesta biblioteca pelos nomes das rotinas invocadas e incorpora o c´digo destas (e somente o destas) ao programa execut´vel. a Com base nesta filosofia, o programa bascara1, apresentado na p´gina 8.1, pode ser ent˜o desmembrado a a em trˆs arquivos distintos, dois contendo a subrotina bascara e a fun¸˜o testa_disc e um contendo o e ca programa principal bascara2, apresentados na p´gina 87. Note o uso do atributo EXTERNAL para indicar a que o nome TESTA_DISC consiste em uma fun¸˜o externa do tipo l´gico. ca o 8.2.7 Interfaces impl´ ıcitas e expl´ ıcitas No exemplo apresentado na p´gina 87, o nome testa_disc ´ identificado como pertencente a uma fun¸˜o a e ca l´gica pelo atributo EXTERNAL: o ... LOGICAL, EXTERNAL :: TESTA_DISC ... Caso esta declara¸˜o n˜o fosse realizada, o compilador iria gerar uma mensagem de erro indicando que este ca a nome n˜o foi declarado. a Uma outra maneira de declarar um nome como pertencente a uma fun¸˜o externa ´ usando a declara¸˜o ca e ca EXTERNAL, em vez do atributo. Esta ´ a forma utilizada no Fortran 77. Desta maneira, o mesmo resultado e seria obtido atrav´s das seguintes linhas: e ... LOGICAL :: TESTA_DISC EXTERNAL :: TESTA_DISC ... A unica diferen¸a entre o exemplo acima e o mesmo tipo de declara¸˜o em um programa Fortran 77 consiste ´ c ca na ausˆncia dos (::) no ultimo caso. e ´ Em ambas as op¸˜es anteriores, somente ´ fornecido ao compilador o nome da fun¸˜o. Nenhum controle co e ca existe sobre os argumentos da fun¸˜o testa_disc e da subrotina bascara. Por isto, seria poss´ o programa ca ıvel bascara2 chamar a subrotina bascara tentando transferir vari´veis complexas, por exemplo, quando os a argumentos mudos da subrotina esperam vari´veis reais. Esta falta de controle, n˜o somente quanto ao a a tipo e esp´cie das vari´veis transferidas a rotinas externas, mas tamb´m quanto ao n´mero e a ordem dos e a e u argumentos, ´ inerente ao Fortran 77; nenhum mecanismo de controle existe para auxiliar o compilador e o e linkador na tarefa de determinar a coerˆncia entre as diferentes unidades de programas. e Para gerar chamadas a sub-programas de forma correta, o compilador necessita conhecer certos detalhes destes sub-programas, como os seus nomes e o n´mero, tipo e esp´cie dos argumentos. Em Fortran 90/95, u e esta tarefa ´ desempenhada pelos blocos de interface. e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 95.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 87 ! Chamada p e l a s u b r o t i n a b a s c a r a para t e s t a r s e r a´ z e s s˜ o r e a i s . ı a ! function t e s t a d i s c ( c2 , c1 , c0 ) i m p l i c i t none logical : : testa disc ! V a r i a v e i s mudas : ´ real , intent ( in ) : : c0 , c1 , c2 i f ( c1 * c1 − 4 * c0 * c2 >= 0 . 0 ) then t e s t a d i s c= . t r u e . else t e s t a d i s c= . f a l s e . end i f return end function t e s t a d i s c ! C a l c u l a as r a´ z e s r e a i s , c a s o ex is t a m , de um p o l i n ˆ n i o de grau 2 . ı o ! Usa f u n c ˜ o t e s t a d i s c . ¸a ! subroutine b a s c a r a ( a2 , a1 , a0 , r a i z e s r e a i s , r1 , r 2 ) i m p l i c i t none ! V a r i a v e i s mudas : ´ real , intent ( in ) : : a0 , a1 , a2 l o g i c a l , intent ( out ) : : r a i z e s r e a i s real , intent ( out ) : : r1 , r 2 ! Fun¸ ˜ o e x t e r n a : ca l o g i c a l , external : : t e s t a d i s c ! Variaveis l o ca i s : ´ real : : d i s c ! r a i z e s r e a i s= t e s t a d i s c ( a2 , a1 , a0 ) i f ( . not . r a i z e s r e a i s ) return d i s c= a1 * a1 − 4 * a0 * a2 r 1= 0.5 * ( − a1 − s q r t ( d i s c ) ) / a2 r 2= 0.5 * ( − a1 + s q r t ( d i s c ) ) / a2 return end subroutine b a s c a r a ! C a l c u l a as r a´ z e s r e a i s de um p o l i n ˆ m i o de grau 2 . ı o program b a s c a r a 2 i m p l i c i t none logical : : controle real : : a , b , c r e a l : : x1 , x2 ! R a´z e s r e a i s . ı ! do print * , ”Entre com o s v a l o r e s dos c o e f i c i e n t e s ( a , b , c ) , ” print * , ”onde a * x ** 2 + b * x + c . ” read * , a , b , c c a l l b a s c a r a ( a , b , c , c o n t r o l e , x1 , x2 ) i f ( c o n t r o l e ) then print * , ”As r a´ z e s ( r e a i s ) s ˜ o : ” ı a print * , ”x1=” , x1 print * , ”x2=” , x2 e xi t else print * , ”As r a´ z e s s ˜ o complexas . Tente novamente . ” ı a end i f end do end program b a s c a r a 2 Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 96.
    88 8.2. Sub-programas No casode rotinas intr´ ınsecas, sub-programas internos e m´dulos, esta informa¸˜o ´ sempre conhecida o ca e pelo compilador; por isso, diz-se que as interfaces s˜o expl´ a ıcitas. Contudo, quando o compilador chama uma rotina externa, esta informa¸˜o n˜o ´ conhecida de antem˜o e da´ a interface ´ dita impl´ ca a e a ı e ıcita. Um bloco de interface, ent˜o, fornece a informa¸˜o necess´ria ao compilador. A forma geral de um bloco de interface ´: a ca a e INTERFACE <corpo interface> END INTERFACE Nesta forma, este bloco de interface n˜o pode ser nomeado. Assim, a interface deixa de ser impl´ a ıcita e se torna expl´ ıcita. O <corpo interface> consiste das declara¸˜es FUNCTION ou SUBROUTINE, declara¸˜es dos tipos e esco co p´cies dos argumentos dos sub-programas e do comando END FUNCTION ou END SUBROUTINE. Em outras e palavras, consiste, normalmente, em uma c´pia exata do sub-programa sem seus comandos execut´veis ou o a rotinas internas, cujas interfaces sempre s˜o expl´ a ıcitas. Por exemplo, INTERFACE FUNCTION FUNC(X) REAL :: FUNC REAL, INTENT(IN) :: X END FUNCTION FUNC END INTERFACE Neste exemplo, o bloco fornece ao compilador a interface da fun¸˜o FUNC. ca Existe uma certa flexibilidade na defini¸ao de um bloco de interfaces. Os nomes (mas n˜o os tipos e c˜ a esp´cies) das vari´veis podem ser distintos dos nomes mudos definidos na rotina ou usados na chamada da e a mesma e outras especifica¸˜es podem ser inclu´ co ıdas, como por exemplo para uma vari´vel local ` rotina. a a Contudo, rotinas internas e comandos DATA ou FORMAT n˜o podem ser inclu´ a ıdos. Um bloco de interfaces pode conter as interfaces de mais de um sub-programa externo e este bloco pode ser colocado na unidade de programa que chama as rotinas externas ou atrav´s do uso de m´dulos, como e o ser´ discutido na se¸˜o 8.3. Em qualquer unidade de programa, o bloco de interfaces ´ sempre colocado a ca e ap´s as declara¸˜es de vari´veis mudas ou de vari´veis locais. o co a a Em certas situa¸˜es, ´ necess´rio fornecer a uma rotina externa o nome de outra rotina externa como co e a um de seus argumentos. Isto pode ser realizado de duas maneiras: 1. Usando o atributo ou declara¸˜o EXTERNAL, como foi realizado na subrotina bascara, na p´gina 8.2.6. ca a 2. Com o uso de um bloco de interface. Neste caso, a interface indicar´ ao compilador que um determinado a nome consiste, na verdade, no nome de um outro sub-programa. As situa¸˜es onde isto pode ocorrer s˜o discutidas na se¸˜o 8.2.12 co a ca Como exemplo do uso de interfaces expl´ ıcitas ser´ apresentado o programa bascara3, o qual chama a novamente as rotinas bascara e testa_disc. Este programa est´ listado nas p´ginas 89 e 90. a a 8.2.8 Argumentos com palavras-chave Argumentos com palavras-chave (keyword arguments) s˜o um recurso j´ utilizado em comandos de Ena a trada/Sa´ (E/S) no Fortran 77: ıda READ(UNIT= 5, FMT= 101, END= 9000) X,Y,Z onde UNIT, FMT e END s˜o as palavras-chave. Elas indicam, respectivamente, o n´mero da unidade de acesso a u para leitura, o r´tulo do comando de formato e o r´tulo para onde o controle de fluxo deve ser desviado o o quando se atingir o ponto final de entrada dos dados. Em Fortran 90/95, argumentos com palavras-chave podem ser utilizados n˜o somente em comandos a de E/S, mas tamb´m em rotinas. Quando uma rotina tem diversos argumentos, palavras-chave s˜o um e a excelente recurso para evitar confus˜o entre os mesmos. A grande vantagem no uso de palavras-chave est´ a a em que n˜o ´ necess´rio lembrar a ordem dos argumentos. Contudo, ´ necess´rio conhecer os nomes dos a e a e a argumentos mudos definidos no campo de declara¸˜es da rotina. co Por exemplo, dada a seguinte fun¸˜o interna: ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 97.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 89 ! Chamada p e l a s u b r o t i n a b a s c a r a para t e s t a r s e r a´ z e s s˜ o r e a i s . ı a ! function t e s t a d i s c ( c2 , c1 , c0 ) i m p l i c i t none logical : : testa disc ! V a r i a v e i s mudas : ´ real , intent ( in ) : : c0 , c1 , c2 i f ( c1 * c1 − 4 * c0 * c2 >= 0 . 0 ) then t e s t a d i s c= . t r u e . else t e s t a d i s c= . f a l s e . end i f return end function t e s t a d i s c ! C a l c u l a as r a´ z e s r e a i s , c a s o ex is t a m , de um p o l i n ˆ n i o de grau 2 . ı o ! Usa f u n c ˜ o t e s t a d i s c . ¸a ! subroutine b a s c a r a ( a2 , a1 , a0 , r a i z e s r e a i s , r1 , r 2 ) i m p l i c i t none ! V a r i a v e i s mudas : ´ real , intent ( in ) : : a0 , a1 , a2 l o g i c a l , intent ( out ) : : r a i z e s r e a i s real , intent ( out ) : : r1 , r 2 ! Variaveis l o ca i s : ´ real : : d i s c INTERFACE function t e s t a d i s c ( c2 , c1 , c0 ) logical : : testa disc real , intent ( in ) : : c0 , c1 , c2 end function t e s t a d i s c END INTERFACE ! r a i z e s r e a i s= t e s t a d i s c ( a2 , a1 , a0 ) i f ( . not . r a i z e s r e a i s ) return d i s c= a1 * a1 − 4 * a0 * a2 r 1= 0.5 * ( − a1 − s q r t ( d i s c ) ) / a2 r 2= 0.5 * ( − a1 + s q r t ( d i s c ) ) / a2 return end subroutine b a s c a r a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 98.
    90 8.2. Sub-programas ! Ca l c u l a as r a´ z e s r e a i s de um p o l i n ˆ m i o de grau 2 . ı o program b a s c a r a 3 i m p l i c i t none logical : : controle real : : a , b , c r e a l : : x1 , x2 ! R a´z e s r e a i s . ı INTERFACE subroutine b a s c a r a ( a2 , a1 , a0 , r a i z e s r e a i s , r1 , r 2 ) real , intent ( in ) : : a0 , a1 , a2 l o g i c a l , intent ( out ) : : r a i z e s r e a i s real , intent ( out ) : : r1 , r 2 end subroutine b a s c a r a END INTERFACE ! do print * , ”Entre com o s v a l o r e s dos c o e f i c i e n t e s ( a , b , c ) , ” print * , ”onde a * x ** 2 + b * x + c . ” read * , a , b , c c a l l b a s c a r a ( a , b , c , c o n t r o l e , x1 , x2 ) i f ( c o n t r o l e ) then print * , ”As r a´ z e s ( r e a i s ) s ˜ o : ” ı a print * , ”x1=” , x1 print * , ”x2=” , x2 e xi t else print * , ”As r a´ z e s s ˜ o complexas . Tente novamente . ” ı a end i f end do end program b a s c a r a 3 ... CONTAINS FUNCTION AREA(INICIO, FINAL, TOL) REAL :: AREA REAL, INTENT(IN) :: INICIO, FINAL, TOL ... END FUNCTION AREA esta pode ser chamada por quaisquer uma das trˆs seguintes atribui¸˜es: e co A= AREA(0.0, 100.0, 1.0E-5) B= AREA(INICIO= 0.0, TOL= 1.0E-5, FINAL= 100.0) C= AREA(0.0, TOL= 1.0E-5, FINAL= 100.0) VALOR= 100.0 ERRO= 1.0E-5 D= AREA(0.0, TOL= ERRO, FINAL= VALOR) onde A, B, C e D s˜o vari´veis declaradas previamente como reais. Todos os argumentos antes da primeira a a palavra-chave devem estar ordenados na ordem definida pela fun¸˜o. Contudo, se uma palavra-chave ´ ca e utilizada, esta n˜o necessita estar na ordem da defini¸˜o. Al´m disso, o valor atribu´ ao argumento mudo a ca e ıdo pode ser uma constante, uma vari´vel ou uma express˜o, desde que a interface seja obedecida. Depois a a que uma palavra-chave ´ utilizada pela primeira vez, todos os argumentos restantes tamb´m devem ser e e transferidos atrav´s de palavras-chave. Conseq¨entemente, a seguinte chamada n˜o ´ v´lida: e u a e a C= AREA(0.0, TOL= 1.0E-5, 100.0) ! N~o ´ v´lido. a e a O exemplo acima n˜o ´ v´lido porque tentou-se transferir o valor 100.0 sem haver a informa¸˜o da palavraa e a ca chave. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 99.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 91 Uma vez que o compilador n˜o ser´ capaz de realizar as associa¸˜es apropriadas exceto se este conhecer as a a co palavras-chave (nomes dos argumentos mudos), a interface do sub-programa deve ser expl´ ıcita caso palavraschave sejam utilizadas. No caso de rotinas internas ou rotinas de m´dulo, a interface j´ ´ expl´ o ae ıcita. No caso de rotinas externas, faz-se necess´rio o uso de um bloco de interfaces. a 8.2.9 Argumentos opcionais Em algumas situa¸˜es, nem todos os argumentos de um sub-programa necessitam ser transferidos durante co uma chamada do mesmo. Um argumento que n˜o necessita ser transferido em todas as chamadas poss´ a ıveis de um sub-programa ´ denominado opcional. Estes argumentos opcionais podem ser declarados pelo atributo e OPTIONAL na declara¸˜o do tipo de vari´veis. ca a Mantendo o exemplo da fun¸˜o AREA acima, a seguinte defini¸˜o pode ser feita: ca ca ... CONTAINS FUNCTION AREA(INICIO, FINAL, TOL) REAL :: AREA REAL, INTENT(IN), OPTIONAL :: INICIO, FINAL, TOL ... END FUNCTION AREA a qual agora tem as seguintes chamadas v´lidas, entre outras: a A= B= C= D= AREA(0.0, 100.0, 1.0E-2) AREA(INICIO= 0.0, FINAL= 100.0, TOL= 1.0E-2) AREA(0.0) AREA(0.0, TOL= 1.0E-2) onde se fez uso tanto da associa¸˜o posicional para os valores dos argumentos, quanto da associa¸˜o via o ca ca uso de palavras-chave. Um argumento obrigat´rio (que n˜o ´ declarado opcional) deve aparecer exatamente uma vez na lista o a e de argumentos da chamada de uma rotina, ou na ordem posicional ou na lista de palavras-chave. J´ um a argumento opcional pode aparecer, no m´ximo uma vez, ou na lista posicional de argumentos ou na lista a de palavras-chave. Da mesma forma como na se¸˜o 8.2.8, a lista de palavras-chave pode aparecer em qualquer ordem; por´m, ca e depois que o primeiro argumento ´ transferido via uma palavra-chave, todos os restantes, obrigat´rios ou e o opcionais, devem ser transferidos da mesma forma. A rotina necessita de algum mecanismo para detectar se um argumento opcional foi transferido na sua chamada, para que esta possa tomar a medida adequada no caso de presen¸a ou de ausˆncia. Este c e mecanismo ´ fornecido pela fun¸˜o intr´ e ca ınseca PRESENT (se¸˜o 7.3). Por exemplo, na fun¸˜o AREA acima, ca ca pode ser necess´rio verificar a existˆncia da vari´vel TOL para definir a tolerˆncia do c´lculo ou usar um a e a a a valor padr˜o caso ela n˜o tenha sido transferida: a a ... REAL :: TTOL ... IF(PRESENT(TOL))THEN TTOL= TOL ELSE TTOL= 1.0E-3 END IF ... A vari´vel TTOL ´ utilizada aqui porque ela pode ser redefinida, ao passo que a vari´vel TOL n˜o, uma vez a e a a que ela foi declarada com INTENT(IN). Como no caso dos argumento com palavras-chave, se a rotina ´ externa e possui algum argumento e opcional, um bloco de interface deve ser fornecido em algum momento. Este n˜o ´ o caso da fun¸˜o AREA, a e ca uma vez que ela ´ interna. Contudo se externa ela o fosse, dever-se-ia declarar o seguinte bloco de interface: e INTERFACE FUNCTION AREA(INICIO, FINAL, TOL) Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 100.
    92 8.2. Sub-programas REAL :: AREA REAL,INTENT(IN), OPTIONAL :: INICIO, FINAL, TOL END FUNCTION AREA END INTERFACE 8.2.10 Tipos derivados como argumentos de rotinas Argumentos de rotinas podem ser do tipo derivado se este est´ definido em somente uma unica unidade a ´ de programa. Isto pode ser obtido de duas maneiras: 1. A rotina ´ interna ` unidade de programa na qual o tipo derivado ´ definido. e a e 2. O tipo derivado ´ definido em um m´dulo o qual ´ acessado pela rotina. e o e 8.2.11 Matrizes como argumentos de rotinas Um outro recurso importante em Fortran ´ a capacidade de usar matrizes como argumentos mudos de e sub-programas. Se um argumento mudo de uma rotina ´ uma matriz, ent˜o o argumento real pode ser: e a ˆ o nome da matriz (sem subscritos); ˆ um elemento de matriz. A primeira forma transfere a matriz inteira; a segunda forma, a qual transfere somente uma se¸˜o que inicia ca no elemento especificado, ´ descrita em mais detalhes a seguir. e 8.2.11.1 Matrizes como argumentos em Fortran 77 O Fortran 77 j´ possu´ diversos recursos para realizar a transferˆncia de matrizes entre sub-programas. a ıa e Estes recursos foram posteriormente estendidos com a defini¸˜o do novo padr˜o com o Fortran 90/95. ca a O uso mais simples e comum de argumentos mudos matriciais consiste em tornar dispon´ o conte´do ıvel u completo de uma matriz em uma rotina. Se as matrizes usadas como argumentos reais ser˜o todas do mesmo a tamanho, ent˜o as matrizes mudas na rotina podem usar limites fixos (aloca¸˜o est´tica). Por exemplo: a ca a SUBROUTINE PROD(X, Y, Z) C Calcula o produto dos vetores X e Y, com 100 elementos cada, C resultando no vetor Z do mesmo tamanho. REAL X(100), Y(100), Z(100) DO 10, I= 1,100 Z(I)= X(I)*Y(I) 15 CONTINUE END Esta subrotina pode ser chamada por um programa semelhante a este: PROGRAM CHAMA_PROD REAL A(100), B(100), C(100) READ(UNIT=*, FMT=*) A,B CALL PROD(A, B, C) WRITE(UNIT=*, FMT=*)C END Este uso de matrizes como argumentos mudos de sub-programas ´ perfeitamente leg´ e ıtimo, por´m inflex´ e ıvel, porque n˜o permite o uso de matrizes de qualquer outro tamanho. Para possibilitar uma flexibilidade a maior, o Fortran 77 introduziu dois mecanismos que possibilitaram uma aloca¸˜o dinˆmica no tamanho de ca a matrizes usadas como argumentos mudos de sub-programas. Estes mecanismos s˜o as matrizes ajust´veis a a e as matrizes de tamanho assumido. A aloca¸˜o dinˆmica, entretanto, ´ parcial, porque as matrizes reais ca a e transferidas aos sub-programas deveriam ter seu tamanho definido por aloca¸˜o est´tica em algum ponto ca a dentro das unidades de programas que chamavam as rotinas. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 101.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 93 Matrizes ajust´veis a Consiste na generaliza¸˜o dos argumentos matriciais de uma rotina para permitir o uso de matrizes de ca qualquer tamanho. Neste caso, as express˜es inteiras que definem os limites em cada dimens˜o das matrizes o a mudas s˜o inclu´ a ıdas nas declara¸˜es destas dentro da rotina, usando vari´veis inteiras que s˜o transferidas co a a junto com as matrizes nos argumentos da rotina ou atrav´s do uso de um bloco COMMON (ver se¸˜o 8.3.1). O e ca exemplo a seguir mostra como isto ´ realizado: e SUBROUTINE PROD(NPTS, X, Y, Z) REAL X(NPTS), Y(NPTS), Z(NPTS) DO 15, I= 1, NPTS ... END Esta subrotina pode ser invocada pela seguinte linha no programa principal ou em outra unidade de programa: CALL PROD(100, A, B, C) as matrizes A, B e C devem ter o seu tamanho alocado de forma est´tica nesta ou em alguma outra unidade a de programa anterior, conforme j´ foi mencionado. a O recurso das matrizes ajust´veis pode ser estendido de forma trivial para cobrir o caso de matrizes a multi-dimensionais, com limites inferior e superior distintos. Por exemplo, SUBROUTINE MULTI(MAP, K1, L1, K2, L2, TRACO) DOUBLE PRECISION MAP(K1:L1, K2:L2) REAL TRACO(L1-K1+1) Como o exemplo mostra, os limites das dimens˜es das matrizes mudas pode ser express˜es inteiras envolvendo o o n˜o somente constantes mas tamb´m vari´veis inteiras transferidas ` rotina ou na lista de argumentos ou a e a a atrav´s de um bloco COMMON. e O mecanismo de matrizes ajust´veis pode ser usado para matrizes de qualquer tipo. Uma matriz ajust´vel a a tamb´m pode ser transferida a uma outra rotina como um argumento real com, se necess´rio, os limites das e a dimens˜es sendo passados de forma concomitante. o Matrizes de tamanho assumido Podem haver circunstˆncias onde seja impratic´vel o uso tanto de matrizes fixas quanto de matrizes a a ajust´veis como argumentos mudos de um sub-programa. A circunstˆncia mais freq¨ente ocorre quando o a a u tamanho real da matriz ´ desconhecido quando a rotina ´ inicialmente chamada. Neste caso, uma matriz e e de tamanho assumido ´ a alternativa existente em Fortran 77. e Estas matrizes tamb´m somente s˜o permitidas como argumentos mudos de sub-programas, mas neste e a caso a matriz ´, efetivamente, declarada como tendo tamanho desconhecido. Por exemplo: e REAL FUNCTION SOMADOIS(TABELA, ANGULO) REAL TABELA(*) N= MAX(1, NINT(SIN(ANGULO)*500.0)) SOMADOIS= TABELA(N) + TABELA(N+1) END Neste caso, a fun¸˜o somente sabe que a matriz TABELA ´ unidimensional, com um limite inferior igual ca e a um. Isto ´ tudo que a fun¸˜o necessita saber para acessar os elementos apropriados N e N + 1. Ao e ca executar a fun¸˜o, ´ responsabilidade do programador assegurar que o valor do ANGULO nunca ir´ resultar ca e a em um subscrito fora do intervalo correto. Este ´ sempre um problema quando se usa matrizes de tamanho e assumido, porque o compilador n˜o tem nenhuma informa¸˜o a respeito do limite superior da matriz. a ca Uma matriz de tamanho assumido somente pode ter o limite superior de sua ultima dimens˜o especificado ´ a por um asterisco; todas as outras dimens˜es devem ter seus limites definidos pelas regras usuais ou serem o definidos na forma de matrizes ajust´veis. a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 102.
    94 8.2. Sub-programas Se¸˜es dematrizes co As regras do Fortran requerem que as extens˜es de uma matriz, usada como argumento real de uma o rotina, sejam, no m´ ınimo, iguais `s respectivas extens˜es da matriz muda declarada na rotina. Entretanto, a o a matriz real pode ter extens˜es maiores e as regras permitem tamb´m uma discordˆncia entre os limites o e a inferior e superior das matrizes real e muda. Por exemplo: PROGRAM CONFUS REAL X(-1:50), Y(10:1000) READ(UNIT=*, FMT=*)X, Y CALL SAIDA(X) CALL SAIDA(Y) END C SUBROUTINE SAIDA(MATRIZ) REAL MATRIZ(50) WRITE(UNIT=*,FMT=*)MATRIZ END O resultado deste programa ser´ escrever na sa´ padr˜o inicialmente os elementos X(-1) a X(48), uma vez a ıda a que este ultimo coresponde ` posi¸˜o na mem´ria de MATRIZ(50). Em seguida, o programa escreve Y(10) ´ a ca o a Y(59). Esta subrotina ir´ funcionar de forma semelhante na se¸˜o de uma matriz bi-dimensional: a ca PROGRAM DOIS_D REAL D(100,20) ... NFATIA= 15 CALL SAIDA(D(1,NFATIA)) ... Neste exemplo, a se¸˜o da matriz dos elementos D(1,15) a D(50,15)ser escrita na sa´ padr˜o. Isto ocorre ca ıda a atrav´s da varia¸˜o dos ´ e ca ındices das linhas, porque esta ´ a ordem dos elementos de matrizes em Fortran (ver e se¸˜o 6.6.2). ca O uso de um elemento de matriz como argumento real, quando o argumento mudo da rotina ´ uma e matriz completa consiste uma pr´tica que facilmente incorre em erro e, portanto, deve ser evitada. a 8.2.11.2 Matrizes como argumentos em Fortran 90/95 Com a defini¸˜o do novo padr˜o Fortran 90/95, os recursos para uso de matrizes como argumentos mudos ca a de sub-programas foi ampliado em rela¸˜o aos mecanismos j´ existentes no Fortran 77. ca a No Fortran 90/95, como j´ foi visto na se¸˜o 6.9, a aloca¸˜o do tamanho das matrizes pode ser reaa ca ca lizada de maneira inteiramente dinˆmica, sendo o espa¸o na mem´ria da CPU alocado em tempo real de a c o processamento. Para fazer uso deste novo recurso, o Fortran 90/95 definiu dois novos mecanismos para a defini¸˜o de matrizes mudas vari´veis como argumentos de sub-programas: as matrizes de forma assumida, ca a as quais generalizam as matrizes de tamanho assumido do Fortran 77 e os objetos autom´ticos, os quais n˜o a a s˜o argumentos da rotina, mas tem suas extens˜es definidas pelas matrizes mudas desta. a o Matrizes de forma assumida Novamente como no caso de matrizes ajust´veis ou de tamanho assumido, as formas dos argumentos a reais e mudos ainda devem concordar. Contudo, agora uma matriz muda pode assumir a forma (n˜o somente a o tamanho) da matriz real usada no argumento da rotina. Tal matriz muda ´ denominada matriz de forma e assumida. Quando a forma ´ declarada com a especifica¸˜o DIMENSION, cada dimens˜o tem a sintaxe: e ca a [<lim inferior>]: isto ´, pode-se definir o limite inferior da dimens˜o onde <lim inferior>, no caso mais geral, ´ uma e a e express˜o inteira que pode depender dos outros argumentos da rotina ou de vari´veis globais definidas em a a m´dulos (ou em blocos COMMON, mas o seu uso ´ desaconselhado no Fortran 90/95). Se <lim inferior> ´ o e e omitido, o valor padr˜o ´ 1. Deve-se notar que ´ a forma da matriz que ´ transferida, n˜o os seus limites. a e e e a Por exemplo: Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 103.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 95 PROGRAM TESTA_MATRIZ IMPLICIT NONE REAL, DIMENSION(0:10, 0:20) :: A ... CALL SUB_MATRIZ(A) ... CONTAINS SUBROUTINE SUB_MATRIZ(DA) REAL, DIMENSION(:,:), INTENT(INOUT) :: DA ... END SUBROUTINE SUB_MATRIZ END PROGRAM TESTA_MATRIZ A subrotina SUB_MATRIZ declara a matriz de forma assumida DA. A correspondˆncia entre os elementos da e matriz real A e a matriz muda DA ´: A(0,0)↔DA(1,1) . . . A(I,J)↔DA(I+1,J+1) . . . A(10,20)↔DA(11,21). e Para que houvesse a mesma correspondˆncia entre os elemento de A e DA, seria necess´rio declarar esta ultima e a ´ como: REAL, DIMENSION(0:,0:), INTENT(INOUT) :: DA Neste caso, a correspondˆncia seria a desejada: A(0,0)↔DA(0,0) . . . A(I,J)↔DA(I,J) . . . A(10,20)↔DA(10,20). e Para se definir matrizes de forma assumida, ´ necess´rio que a interface seja expl´ e a ıcita na unidade que chama a rotina. A matriz real pode ter sido declarada, na unidade que chama a rotina ou em outra unidade anterior, como uma matriz aloc´vel. Como exemplo, considere a seguinte rotina externa, seguida a do programa que a chama, programa 8.2, listado na p´gina 96: a subroutine sub ( ra , rb , rc , max a ) i m p l i c i t none real , dimension ( : , : ) , intent ( in ) real , dimension ( : , : ) , intent ( out ) real , intent ( out ) ! max a= maxval ( r a ) r c= 0 . 5 * rb return end subroutine sub : : ra , rb : : rc : : max a Objetos autom´ticos a Uma rotina com argumentos mudos que s˜o matrizes cujos tamanhos variam de uma chamada a outra a pode tamb´m precisar de matrizes locais (n˜o mudas) cujos tamanhos variem ao sabor dos tamanhos das e a matrizes mudas. Um exemplo simples ´ a matriz TEMP na subrotina abaixo, destinada a trocar os elementos e entre duas matrizes: SUBROUTINE TROCA(A,B) IMPLICIT NONE REAL, DIMENSION(:), INTENT(INOUT) :: A, B REAL, DIMENSION(SIZE(A)) :: TEMP !A fun¸~o SIZE fornece o tamanho de TEMP. ca TEMP= A A= B B= TEMP RETURN END SUBROUTINE TROCA Matrizes como a TEMP, cujas extens˜es variam da maneira apresentada s˜o chamadas matrizes autom´ticas o a a e s˜o exemplos de objetos autom´ticos de dados. Estes s˜o objetos de dados cujas declara¸˜es dependem do a a a co valor de express˜es n˜o-constantes e que n˜o s˜o argumentos mudos de rotinas. o a a a Um outro objeto autom´tico, relacionado com vari´veis de caracteres, surge atrav´s do comprimento a a e vari´vel de um caractere: a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 104.
    96 8.2. Sub-programas Programa 8.2:Exemplifica o uso de matrizes de forma assumida. program p r o g s u b i m p l i c i t none real , dimension ( 0 : 9 , 1 0 ) : : a real , dimension ( 5 , 5 ) :: c real : : valor max integer : : i INTERFACE subroutine sub ( ra , rb , rc , max a ) real , dimension ( : , : ) , intent ( in ) : : ra , rb real , dimension ( : , : ) , intent ( out ) : : r c real , intent ( out ) : : max a end subroutine sub END INTERFACE ! a= r e s h a p e ( s o u r c e =(/( c o s ( r e a l ( i ) ) , i= 1 , 1 0 0 ) / ) , shape= ( / 1 0 , 1 0 / ) ) c a l l sub ( a , a ( 0 : 4 , : 5 ) , c , valor max ) print * , ”A m a t r i z a : ” do i= 0 , 9 print * , a ( i , : ) end do print * , ” ” print * , ”O maior v a l o r em a : ” , valor max print * , ” ” print * , ”A m a t r i z c : ” do i= 1 , 5 print * , c ( i , : ) end do end program p r o g s u b SUBROUTINE EXEMPLO(PALAVRA1) IMPLICIT NONE CHARACTER(LEN= *) :: PALAVRA1 CHARACTER(LEN= LEN(PALAVRA1)) :: PALAVRA2 ... como um exemplo. Se este objeto consiste em uma fun¸˜o de caractere de tamanho vari´vel, a interface ca a deve ser expl´ ıcita, como no programa-exemplo loren abaixo. A defini¸˜o dos limites das dimens˜es de um objeto autom´tico pode ser realizada tamb´m de argumentos ca o a e mudos ou de vari´veis definidas por associa¸˜o por uso ou por associa¸˜o ao hospedeiro. Associa¸˜o por uso a ca ca ca ocorre quando vari´veis globais p´blicas declaradas no corpo de um m´dulo s˜o disponibilizadas ` rotina a u o a a program l o r e n i m p l i c i t none character ( len= * ) , parameter : : a= ”S´ um pequeno exemplo . ” o print * , dobro ( a ) CONTAINS function dobro ( a ) character ( len= * ) , intent ( in ) : : a character ( len= 2 * len ( a )+2) : : dobro dobro= a // ” ” // a return end function dobro end program l o r e n Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 105.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 97 atrav´s da instru¸˜o USE; enquanto que associa¸˜o ao hospedeiro ocorre quando vari´veis declaradas em e ca ca a uma unidade de programa s˜o disponibilizadas `s suas rotinas internas. a a Matrizes autom´ticas s˜o automaticamente criadas (alocadas) na entrada da rotina e automaticamente a a dealocadas na sa´ ıda. Assim, o tamanho das matrizes autom´ticas pode variar em diferentes chamadas da a rotina. Note que n˜o h´ mecanismo para verificar a disponibilidade de mem´ria para a cria¸˜o de matrizes a a o ca autom´ticas. Caso n˜o haja mem´ria suficiente, o programa ´ interrompido. Al´m disso, uma matriz a a o e e autom´tica n˜o pode aparecer em uma declara¸˜o SAVE (se¸˜o 8.2.15) ou NAMELIST, ou possuir o atributo a a ca ca SAVE na sua declara¸˜o. Al´m disso, a matriz n˜o pode ser inicializada na sua declara¸˜o. ca e a ca O seguinte programa-exemplo usa matrizes aloc´veis, de forma assumida e autom´ticas: a a subroutine sub mat ( a , r e s ) i m p l i c i t none real , dimension ( : , : ) , intent ( in ) : : a ! M a t r i z de forma assumida real , intent ( out ) : : r e s real , dimension ( s i z e ( a , 1 ) , s i z e ( a , 2 ) ) : : temp ! M a t r i z a u t o m a t i c a ´ ! temp= s i n ( a ) r e s= minval ( a+temp ) return end subroutine sub mat program m a t r i z a u t i m p l i c i t none real , dimension ( : , : ) , a l l o c a t a b l e : : a real : : res integer : : n , m, i INTERFACE subroutine sub mat ( a , r e s ) real , dimension ( : , : ) , intent ( in ) : : a real , intent ( out ) : : r e s real , dimension ( s i z e ( a , 1 ) , s i z e ( a , 2 ) ) : : temp end subroutine sub mat END INTERFACE print * , ”Entre com di m e n s ˜ e s da m a t r i z : ” o read * , n ,m a l l o c a t e ( a ( n ,m) ) a= r e s h a p e ( s o u r c e =(/( tan ( r e a l ( i ) ) , i= 1 , n *m) / ) , shape= ( / n ,m/ ) ) print * , ”Matriz a : ” do i= 1 , n print * , a ( i , : ) end do c a l l sub mat ( a , r e s ) print * , ” ” print * , ”O menor v a l o r de a + s i n ( a ) ´ : ” , r e s e end program m a t r i z a u t 8.2.12 sub-programas como argumentos de rotinas At´ este ponto, os argumentos de uma rotina forma supostos ser vari´veis ou express˜es. Contudo, uma e a o outra possibilidade ´ um ou mais argumentos sendo nomes de outras rotinas que ser˜o invocadas. Um e a exemplo de situa¸˜o onde ´ necess´rio mencionar o nome de uma rotina como argumento de outra ´ quando ca e a e a segunda executa a integra¸˜o num´rica da primeira. Desta forma, ´ poss´ ca e e ıvel escrever-se um integrador num´rico gen´rico, que integra qualquer fun¸˜o que satisfa¸a a interface imposta a ela. e e ca c Um exemplo de uso do nome de uma rotina como argumento ocorre abaixo. a fun¸˜o MINIMO calcula o ca m´ ınimo (menor valor) da fun¸˜o FUNC em um intervalo: ca FUNCTION MINIMO(A, B, FUNC) ! Calcula o m´nimo de FUNC no intervalo [A,B]. ı REAL :: MINIMO Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 106.
    98 8.2. Sub-programas REAL, INTENT(IN):: A, B INTERFACE FUNCTION FUNC(X) REAL :: FUNC REAL, INTENT(IN) :: X END FUNCTION FUNC END INTERFACE REAL :: F,X ... F= FUNC(X) !Invoca¸~o da fun¸~o. ca ca ... END FUNCTION MINIMO Note o uso de um bloco de interface para indicar ao compilador que o nome FUNC corresponde a uma fun¸˜o ca definida pelo usu´rio. a Em Fortran 77, como n˜o havia o recurso de blocos de interface, a indica¸˜o que o nome FUNC corresponde a ca a uma fun¸˜o externa ´ realizada atrav´s da declara¸˜o EXTERNAL. Assim, no exemplo acima, no lugar da ca e e ca interface apareceria: ... REAL FUNC EXTERNAL FUNC ... para indicar a fun¸˜o externa. A mesma alternativa continua v´lida em Fortran 90/95, onde, al´m da ca a e declara¸˜o, pode-se usar tamb´m a palavra-chave EXTERNAL como atributo de um nome. Contudo, como j´ ca e a foi mencionado na se¸˜o 8.2.7, o simples uso da declara¸˜o ou atributo EXTERNAL n˜o possibilita o controle ca ca a nos argumentos desta fun¸˜o, ao contr´rio do que ocorre quando a interface ´ expl´ ca a e ıcita. Um exemplo de programa que chama a fun¸˜o MINIMO seria o seguinte: ca PROGRAM MIN IMPLICIT NONE REAL :: MENOR INTERFACE FUNCTION FUN(X) REAL :: FUN REAL, INTENT(IN) :: X END FUNCTION FUN END INTERFACE ... MENOR= MINIMO(1.0, 2.0, FUN) ... END PROGRAM MIN O uso de um bloco de interface n˜o ´ necess´rio se a interface de FUN for expl´ a e a ıcita, como no caso de uma rotina de m´dulo. o No exemplo acima, a fun¸˜o FUN n˜o pode ser interna, porque estas n˜o s˜o admitidas quando os seus ca a a a nomes s˜o usados como argumentos de outras rotinas. Ou seja, somente rotinas externas ou de m´dulos s˜o a o a aceitas quando os seus nomes s˜o transferidos a outras rotinas como argumentos. a O programa-exemplo das p´ginas 99 e 100 descreve uma subrotina que gera uma matriz de pontos a a partir de uma fun¸˜o fornecida pelo programador. ca 8.2.13 Fun¸oes de valor matricial c˜ Fun¸˜es, al´m de fornecer os resultados usuais na forma de valores dos tipos intr´ co e ınsecos inteiro, real, complexo, l´gico e de caractere, podem tamb´m fornecer como resultado valores de tipo derivado, matrizes o e e ponteiros. No caso de fun¸˜es de valor matricial, o tamanho do resultado pode ser determinado de forma co semelhante ` maneira como matrizes autom´ticas s˜o declaradas. a a a Considere o seguinte exemplo de uma fun¸˜o de valor matricial: ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 107.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 99 ! Usa s u b r o t i n a p l o t a e chama a f u n ¸ ˜ o e x t e r n a Meu F . ca ! program t e s p l o t a i m p l i c i t none integer : : pts , j real : : yi , y f real , dimension ( : , : ) , a l l o c a t a b l e : : xy INTERFACE subroutine p l o t a ( f , xi , xf , npt , p l o t ) integer , intent ( in ) : : npt real , intent ( in ) : : xi , x f real , dimension ( 2 , npt ) , intent ( out ) : : p l o t INTERFACE function f ( x ) real : : f real , intent ( in ) : : x end function f END INTERFACE end subroutine p l o t a ! function Meu F ( y ) r e a l : : Meu F real , intent ( in ) : : y end function Meu F END INTERFACE ! print * , ”Entre com o n´ mero de p o n t o s : ” u read * , p t s print * , ”Entre com o s l i m i t e s i n f e r i o r e s u p e r i o r : ” read * , yi , y f a l l o c a t e ( xy ( 2 , p t s ) ) ! c a l l p l o t a ( Meu F , yi , yf , pts , xy ) ! do j= 1 , p t s print * , xy ( : , j ) end do end program t e s p l o t a ! Fun¸ ˜ o sen ( exp ( x ) ) . ca function Meu F ( x ) r e a l : : Meu F real , intent ( in ) : : x ! Meu F= s i n ( exp ( x ) ) return end function Meu F Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 108.
    100 8.2. Sub-programas ! Gerauma m a t r i z de p o n t o s de uma f u n ¸ ˜ o q u a l q u e r d e s t i n a d a ` p l o t a g e m ca a ! do g r a f i c o d e s t a f u n ¸ ˜ o . ´ ca ! Parˆ metros : a ! f : Fun¸ ˜ o e x t e r n a a s e r p l o t a d a . ca ! x i : Ponto i n i c i a l ( e n t r a d a ) . ! x f : Ponto f i n a l ( e n t r a d a ) . ! npt : N´mero de p o n t o s a s e r g e r a d o s ( e n t r a d a ) u ! p l o t : m a t r i z de forma (/ npt , 2 /) contendo as a b c i s s a s e ordena da s dos ! p o n t o s ( s a´d a ) . ı ! subroutine p l o t a ( f , xi , xf , npt , p l o t ) i m p l i c i t none integer , intent ( in ) : : npt real , intent ( in ) : : xi , x f real , dimension ( 2 , npt ) , intent ( out ) : : p l o t INTERFACE function f ( x ) real : : f real , intent ( in ) : : x end function f END INTERFACE ! Variaveis l o ca i s : ´ integer : : i real : : passo , x ! p a s s o= ( x f − x i ) / r e a l ( npt − 1 ) x= x i do i= 1 , npt p l o t ( 1 , i )= x p l o t ( 2 , i )= f ( x ) x= x + p a s s o end do return end subroutine p l o t a PROGRAM TES_VAL_MAT IMPLICIT NONE INTEGER, PARAMETER :: M= 6 INTEGER, DIMENSION(M,M) :: IM1, IM2 ... IM2= FUN_VAL_MAT(IM1,1) !Chama fun¸~o matricial. ca ... CONTAINS FUNCTION FUN_VAL_MAT(IMA, SCAL) INTEGER, DIMENSION(:,:), INTENT(IN) :: IMA INTEGER, INTENT(IN) :: SCAL INTEGER, DIMENSION(SIZE(IMA,1),SIZE(IMA,2)) :: FUN_VAL_MAT FUN_VAL_MAT= IMA*SCAL END FUNCTION FUN_VAL_MAT END PROGRAM TES_VAL_MAT Neste exemplo, o limites das dimens˜es de FUN_VAL_MAT s˜o herdadas do argumento verdadeiro transferido o a a ` fun¸˜o e usadas para determinar o tamanho da matriz resultante. ca Para que o compilador conhe¸a a forma da matriz resultante, a interface de uma fun¸˜o de valor matricial c ca deve ser expl´ ıcita em todas as unidades onde esta fun¸˜o ´ invocada. ca e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 109.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 8.2.14 101 Recursividade e rotinas recursivas Recursividade ocorre quando rotinas chamam a si mesma, seja de forma direta ou indireta. Por exemplo, sejam as rotinas A e B. Recursividade pode ocorrer de duas formas: Recursividade direta: A invoca A diretamente. Recursividade indireta: A invoca B, a qual invoca A. Qualquer cadeia de invoca¸˜es de rotinas com um componente circular (isto ´, invoca¸˜o direta ou indireta) co e ca exibe recursividade. Embora recursividade seja uma t´cnica bonita e sucinta para implementar uma grande e variedade de problemas, o uso incorreto da mesma pode provocar uma perda na eficiˆncia da computa¸˜o e ca do c´digo. o Fortran 77 Em Fortran 77, recursividade direta n˜o ´ permitida. Qualquer tentativa de for¸ar uma rotina a chamar a e c a si pr´pria resultar´ em erro de compila¸˜o. Em grande parte dos textos, afirma-se que recursividade o a ca indireta tamb´m n˜o ´ poss´ 3 . Contudo, recursividade pode ser simulada em Fortran 77 quando uma e a e ıvel rotina chama a si pr´pria usando n˜o o seu nome real mas atrav´s de um argumento mudo, como no exemplo o a e abaixo:4 PROGRAM MAIN INTEGER N, X EXTERNAL SUB1 COMMON /GLOBALS/ N X= 0 PRINT*, ’Entre n´mero de repeti¸~es:’ u co READ(*,*) N CALL SUB1(X, SUB1) END PROGRAM MAIN ------------------------------------------SUBROUTINE SUB1(X, SUBMUDO) INTEGER N, X EXTERNAL SUBMUDO COMMON /GLOBALS/ N IF(X .LT. N)THEN X= X + 1 PRINT*, ’X=’, X CALL SUBMUDO(X, SUBMUDO) END IF RETURN END SUBROUTINE SUB1 Como a subrotina SUB1 n˜o sabe que ao invocar o argumento mudo SUBMUDO, o qual ´ o nome de uma a e rotina externa, vai estar na verdade invocando a si pr´pria, o compilador n˜o ir´ gerar mensagem de erro e o a a o c´digo ir´ funcionar em grande parte das plataformas. Por exemplo, se o valor de N for definido igual a 5, o a o resultado ser´ a X = 1 X = 2 ... X = 5 o que demonstra que ´ poss´ simular-se recursividade mesmo em Fortran 77. e ıvel Fortran 90/95 Em Fortran 90/95, por outro lado, recursividade ´ suportada como um recurso expl´ e ıcito da linguagem. 3 Ver, por exemplo, o texto de Clive Page [5, se¸ao 4.3]. c˜ Fortran Examples http://www.esm.psu.edu/~ajm138/fortranexamples.html, consultada em 07/06/2005. 4 Referˆncia: e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 110.
    102 8.2. Sub-programas Recursividade direta.Para fins de eficiˆncia na execu¸˜o do c´digo, rotinas recursivas devem ser explie ca o citamente declaradas usando-se a palavra-chave RECURSIVE SUBROUTINE ... ou RECURSIVE FUNCTION ... A declara¸˜o de uma fun¸˜o recursiva ´ realizada com uma sintaxe um pouco distinta da at´ ent˜o abordada: ca ca e e a uma fun¸˜o explicitamente declarada recursiva deve conter tamb´m a palavra-chave RESULT, a qual especifica ca e o nome de uma vari´vel ` qual o valor do resultado do desenvolvimento da fun¸˜o deve ser atribu´ a a ca ıdo, em lugar do nome da fun¸˜o propriamente dito. ca A palavra-chave RESULT ´ necess´ria, uma vez que n˜o ´ poss´ usar-se o nome da fun¸˜o para retornar e a a e ıvel ca o resultado, pois isso implicaria em perda de eficiˆncia no c´digo. De fato, o nome da palavra-chave deve ser e o usado tanto na declara¸˜o do tipo e esp´cie do resultado da fun¸˜o quanto para atribui¸˜o de resultados e em ca e ca ca express˜es escalares ou matriciais. Esta palavra-chave pode tamb´m ser usada para fun¸˜es n˜o recursivas. o e co a Cada vez que uma rotina recursiva ´ invocada, um conjunto novo de objetos de dados locais ´ criado, e e o qual ´ eliminado na sa´ da rotina. Este conjunto consiste de todos os objetos definidos no campo de e ıda declara¸˜es da rotina ou declarados implicitamente, exceto aqueles com atributos DATA ou SAVE (ver se¸˜o co ca 8.2.15). Fun¸˜es de valor matricial recursivas s˜o permitidas e, em algumas situa¸˜es, a chamada de uma co a co fun¸˜o recursiva deste tipo ´ indisting¨´ de uma referˆncia a matrizes. ca e uıvel e O exemplo tradicional do uso de rotinas recursivas consiste na implementa¸˜o do c´lculo do fatorial de ca a um inteiro positivo. A implementa¸˜o ´ realizada a partir das seguintes propriedades do fatorial: ca e 0! = 1; N ! = N (N − 1)! A seguir, o c´lculo do fatorial ´ implementado tanto na forma de uma fun¸˜o quanto na forma de uma a e ca subrotina recursivas: RECURSIVE FUNCTION FAT(N) RESULT (N_FAT) IMPLICIT NONE INTEGER :: N_FAT !Define tamb´m o tipo de FAT. e INTEGER, INTENT(IN) :: N IF(N == 0)THEN N_FAT= 1 ELSE N_FAT= N*FAT(N-1) END IF RETURN END FUNCTION FAT ---------------------------------------------RECURSIVE SUBROUTINE FAT(N, N_FAT) IMPLICIT NONE INTEGER, INTENT(IN) :: N INTEGER, INTENT(INOUT) :: N_FAT IF(N == 0)THEN N_FAT= 1 ELSE CALL FAT(N - 1, N_FAT) N_FAT= N*N_FAT END IF RETURN END SUBROUTINE FAT Recursividade indireta. Uma rotina tamb´m pode ser invocada por recursividade indireta, isto ´, uma e e rotina chama outra a qual, por sua vez, invoca a primeira. Para ilustrar a utilidade deste recurso, sup˜e-se o que se queira realizar uma integra¸˜o num´rica bi-dimensional quando se disp˜e somente de um c´digo que ca e o o executa integra¸˜o unidimensional. Um exemplo de fun¸˜o que implementaria integra¸˜o unidimensional ´ ca ca ca e dado a seguir. O exemplo usa um m´dulo, o qual ´ uma unidade de programa que ser´ discutido na se¸˜o o e a ca 8.3: Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 111.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 103 FUNCTION INTEGRA(F, LIMITES) ! Integra F(x) de LIMITES(1) a LIMITES(2). implicit none REAL, DIMENSION(2), INTENT(IN) :: LIMITES INTERFACE FUNCTION F(X) REAL :: F REAL, INTENT(IN) :: X END FUNCTION F END INTERFACE ... INTEGRA= <implementa¸~o integra¸~o num´rica> ca ca e RETURN END FUNCTION INTEGRA -------------------------------------------MODULE FUNC IMPLICIT NONE REAL :: YVAL REAL, DIMENSION(2) :: LIMX, LIMY CONTAINS FUNCTION F(XVAL) REAL :: F REAL, INTENT(IN) :: XVAL F= <express~o envolvendo XVAL e YVAL> a RETURN END FUNCTION F END MODULE FUNC -----------------------------------------FUNCTION FY(Y) ! Integra em X, para um valor fixo de Y. USE FUNC REAL :: FY REAL, INTENT(IN) :: Y YVAL= Y FY= INTEGRA(F, LIMX) RETURN END FUNCTION FY Com base nestas trˆs unidades de programa, um programa pode calcular a integral sobre o retˆngulo no e a plano (x, y) atrav´s da chamada: e AREA= INTEGRA(FY, LIMY) 8.2.15 Atributo e declara¸˜o SAVE ca A declara¸˜o ou o atributo SAVE s˜o utilizados quando se deseja manter o valor de uma vari´vel local ca a a em um sub-programa ap´s a sa´ o ıda. Desta forma, o valor anterior desta vari´vel est´ acess´ a a ıvel quando o sub-programa ´ invocado novamente. e Como exemplo, a subrotina abaixo cont´m as vari´veis locais CONTA, a qual conta o n´mero de chamadas e a u da subrotina e ´ inicializada a zero e a vari´vel A, que ´ somada ao valor do argumento. e a e SUBROUTINE CONTA_SOMA(X) IMPICIT NONE REAL, INTENT(IN) :: X REAL, SAVE :: A INTEGER :: CONTA= 0 !Inicializa o contador. ... CONTA= CONTA + 1 IF(CONTA == 1)THEN A= 0.0 Autor: Rudi Gaelzer – IFM/UFPel Mant´m o valor da vari´vel. e a Impresso: 13 de abril de 2010
  • 112.
    104 8.2. Sub-programas ELSE A= A+ X END IF ... RETURN END SUBROUTINE CONTA_SOMA Neste exemplo, tanto a vari´vel A quanto CONTA tˆm o seu valor mantido quando a subrotina ´ abandonada. a e e Isto ´ garantido porque a vari´vel A ´ declarada com o atributo SAVE. J´ a vari´vel CONTA n˜o precisa ser e a e a a a declarada com o mesmo atributo porque ela tem o seu valor inicializado na declara¸˜o. De acordo com o paca dr˜o da linguagem, as vari´veis que tˆm o seu valor inicializado no momento da declara¸˜o automaticamente a a e ca adquirem o atributo SAVE. Alternativamente ao uso do atributo, pode-se declarar uma lista de nomes de vari´veis com a mesma a propriedade atrav´s da declara¸˜o SAVE. Desta forma, a vari´vel A, no exemplo acima, podia ser declarada e ca a atrav´s das linhas: e ... REAL :: A SAVE :: A ... A forma geral desta declara¸˜o ´: ca e SAVE [[::] <lista nomes vari´veis>] a onde uma declara¸˜o SAVE sem a subseq¨ente <lista nomes vari´veis> equivale ` mesma declara¸˜o ca u a a ca aplicada a todos os nomes da rotina, em cujo caso nenhuma outra vari´vel pode ser declarada com o a atributo SAVE. O atributo SAVE n˜o pode ser especificado para um argumento mudo, um resultado de fun¸˜o ou um a ca objeto autom´tico. O atributo pode ser especificado para um ponteiro, em cuja situa¸˜o seu status de a ca associa¸˜o ´ preservado. Pode ser aplicado tamb´m a uma matriz aloc´vel, em cuja situa¸˜o o status de ca e e a ca aloca¸˜o e valores s˜o preservados. Uma vari´vel preservada em um sub-programa recursivo ´ compartilhada ca a a e por todas as instˆncias da rotina. a O comando ou atributo SAVE podem aparecer no campo de declara¸˜es de um programa principal, mas co neste caso o seu efeito ´ nulo. O uso pr´tico deste recurso est´ restrito `s outras unidades de programa. e a a a 8.2.16 Fun¸oes de efeito lateral e rotinas puras c˜ Na se¸˜o 8.2, foi mencionado que fun¸˜es normalmente n˜o alteram o valor de seus argumentos. Enca co a tretanto, em certas situa¸˜es esta a¸˜o ´ permitida. Fun¸˜es que alteram o valor de seus argumentos s˜o co ca e co a denominadas fun¸˜es de efeito lateral (side-effect functions). co Para auxiliar na otimiza¸˜o do c´digo, o padr˜o da linguagem estabelece uma proibi¸˜o no uso de fun¸˜es ca o a ca co de efeito lateral quando o uso de tal fun¸˜o em uma express˜o altera o valor de um outro operando na mesma ca a express˜o, seja este operando uma vari´vel ou um argumento de uma outra fun¸˜o. Caso este tipo de fun¸˜o a a ca ca fosse poss´ neste caso, a atribui¸˜o ıvel ca RES= FUN1(A,B,C) + FUN2(A,B,C) onde ou FUN1 ou FUN2, ou ambas, alterassem o valor de um ou mais argumentos, a ordem de execu¸˜o desta ca express˜o seria importante; o valor de RES seria diferente caso FUN1 fosse calculada antes de FUN2 do que a seria caso a ordem de c´lculo fosse invertida. Exemplos de fun¸˜es de efeito lateral s˜o dados a seguir: a co a FUNCTION FUN1(A,B,C) INTEGER :: FUN1 REAL, INTENT(INOUT) :: A REAL, INTENT(IN) :: B,C A= A*A FUN1= A/B RETURN END FUNCTION FUN1 ----------------------------------Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 113.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 105 FUNCTION FUN2(A,B,C) INTEGER :: FUN2 REAL, INTENT(INOUT) :: A REAL, INTENT(IN) :: B,C A= 2*A FUN2= A/C RETURN END FUNCTION FUN2 Nota-se que ambas as fun¸˜es alteram o valor de A; portanto, o valor de RES ´ totalmente dependente na co e ordem de execu¸˜o da express˜o. ca a Como o padr˜o da linguagem n˜o estabelece uma ordem para a execu¸˜o das opera¸˜es e desenvolvia a ca co mentos em uma express˜o, este efeito lateral ´ proibido neste caso. Isto possibilita que os compiladores a e executem as opera¸˜es na ordem que otimiza a execu¸˜o do c´digo. co ca o O uso de fun¸˜es de efeito lateral em comandos ou construtos FORALL (se¸˜o 6.10), por exemplo, acarco ca retaria em um impedimento severo na otimiza¸˜o da execu¸˜o do comando em um processador paralelo, ca ca efetivamente anulando o efeito desejado pela defini¸˜o deste recurso. ca Para controlar esta situa¸˜o, o programador pode assegurar ao compilador que uma determinada rotina ca (n˜o somente fun¸˜es) n˜o possui efeitos laterais ao incluir a palavra-chave PURE ` declara¸˜o SUBROUTINE a co a a ca ou FUNCTION: PURE SUBROUTINE ... --------------------------PURE FUNCTION ... Em termos pr´ticos, esta palavra-chave assegura ao compilador que: a ˆ se a rotina ´ uma fun¸˜o, esta n˜o altera os seus argumentos mudos; e ca a ˆ a rotina n˜o altera nenhuma parte de uma vari´vel acessada por associa¸˜o ao hospedeiro (rotina a a ca interna) ou associa¸˜o por uso (m´dulos); ca o ˆ a rotina n˜o possui nenhuma vari´vel local com o atributo SAVE; a a ˆ a rotina n˜o executa opera¸˜es em um arquivo externo; a co ˆ a rotina n˜o cont´m um comando STOP. a e Para assegurar que estes requerimentos sejam cumpridos e que o compilador possa facilmente verificar o seu cumprimento, as seguintes regras adicionais s˜o impostas: a ˆ qualquer argumento mudo que seja o nome de uma rotina e qualquer rotina invocada devem tamb´m e ser puras e ter a interface expl´ ıcita; ˆ as inten¸˜es de um argumento mudo qualquer devem ser declaradas, exceto se este seja uma rotina ou co um ponteiro, e a inten¸˜o deve sempre ser IN no caso de uma fun¸˜o; ca ca ˆ qualquer rotina interna de uma rotina pura tamb´m deve ser pura; e ˆ uma vari´vel que ´ acessada por associa¸˜o ao hospedeiro ou por uso ou ´ um argumento mudo de a e ca e inten¸ao IN n˜o pode ser o alvo de uma atribui¸˜o de ponteiro; se a vari´vel ´ do tipo derivado com c˜ a ca a e uma componente de ponteiro, ela n˜o pode estar no lado direito de uma atribui¸˜o e ela n˜o pode a ca a estar associada como o argumento real de um argumento mudo que seja um ponteiro ou que tenha inten¸oes OUT ou INOUT. c˜ Esta ultima regra assegura que um ponteiro local n˜o pode causar um efeito lateral. ´ a A principal raz˜o para se permitir subrotinas puras est´ na possibilidade de seu uso em construtos a a FORALL. Por´m, ao contr´rio de fun¸˜es, uma subrotina pura pode ter argumentos mudos com inten¸˜es e a co co OUT ou INOUT ou atributo POINTER. A sua existˆncia tamb´m oferece a possibilidade de se fazer chamadas e e a subrotinas de dentro de fun¸˜es puras. co Uma rotina externa ou muda que seja usada como rotina pura deve possuir uma interface expl´ ıcita que a caracterize inequivocamente como tal. Contudo, a rotina pode ser usada em outros contextos sejam o uso de um bloco de interface ou com uma interface que n˜o a caracterize como pura. Isto permite que rotinas a em bibliotecas sejam escritas como puras sem que elas sejam obrigatoriamente usadas como tal. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 114.
    106 8.2. Sub-programas Todas asfun¸˜es intr´ co ınsecas (cap´ ıtulo 7) s˜o puras e, portanto, podem ser chamadas livremente de dentro a de qualquer rotina pura. Adicionalmente, a subrotina intr´ ınseca elemental MVBITS (se¸˜o 7.9.3) tamb´m ´ ca e e pura. O atributo PURE ´ dado automaticamente a qualquer rotina que seja definida com o atributo ELEMENTAL e (se¸˜o 8.2.17). ca 8.2.17 Rotinas elementais Na se¸˜o 6.7 j´ foi introduzida a no¸˜o de rotinas intr´ ca a ca ınsecas elementais, as quais s˜o rotinas com argua mentos mudos escalares que podem ser invocadas com argumentos reais matriciais, desde que os argumentos matriciais tenham todos a mesma forma (isto ´, que sejam conform´veis). Para uma fun¸˜o, a forma do e a ca resultado ´ a forma dos argumentos matriciais. e O Fortran 95 estende este conceito a rotinas n˜o-intr´ a ınsecas. Uma rotina elemental criada pelo programador deve ter um dos seguintes cabe¸alhos: c ELEMENTAL SUBROUTINE ... -------------------------ELEMENTAL FUNCTION ... Um exemplo ´ fornecido abaixo. Dado o tipo derivado INTERVALO: e TYPE :: INTERVALO REAL :: INF, SUP END TYPE INTERVALO pode-se definir a seguinte fun¸˜o elemental: ca ELEMENTAL FUNCTION SOMA_INTERVALOS(A,B) INTRINSIC NONE TYPE(INTERVALO) :: SOMA_INTERVALOS TYPE(INTERVALO), INTENT(IN) :: A, B SOMA_INTERVALOS%INF= A%INF + B%INF SOMA_INTERVALOS%SUP= A%SUP + B%SUP RETURN END FUNCTION SOMA_INTERVALOS a qual soma dois intervalos de valores, entre um limite inferior e um limite superior. Nota-se que os argumentos mudos s˜o escritos como escalares, mas a especifica¸˜o ELEMENTAL possibilita o uso de matrizes a ca conform´veis como argumentos reais. Neste caso, as opera¸˜es de soma dos intervalos s˜o realizadas coma co a ponente a componente das matrizes A e B da maneira mais eficiente poss´ ıvel. Uma rotina n˜o pode ser ao mesmo tempo elemental e recursiva. a Uma rotina elemental deve satisfazer todos os requisitos de uma rotina pura; de fato, ela j´ possui a automaticamente o atributo PURE. Adicionalmente, todos os argumentos mudos e resultados de fun¸˜o ca devem ser vari´veis escalares sem o atributo POINTER. Se o valor de um argumento mudo ´ usado em uma a e declara¸˜o, especificando o tamanho ou outra propriedade de alguma vari´vel, como no exemplo ca a ELEMENTAL FUNCTION BRANCO(N) IMPLICIT NONE INTEGER, INTENT(IN) :: N CHARACTER(LEN= N) :: BRANCO BRANCO= ’ ’ RETURN END FUNCTION BRANCO esta fun¸˜o deve ser chamada com argumento real escalar, uma vez que um argumento real matricial ca resultaria em uma matriz cujos elementos seriam caracteres de comprimentos vari´veis. a Uma rotina externa elemental deve possuir uma interface expl´ ıcita que sempre a caracterize de forma inequ´ ıvoca como elemental. Isto ´ exigido para que o compilador possa determinar o mecanismo de chamada e que acomode os elementos de matriz de forma mais eficiente. Isto contrasta com o caso de uma rotina pura, onde a interface nem sempre necessita caracterizar a rotina como pura. No caso de uma subrotina elemental, se algum argumento real ´ matriz, todos os argumentos com e inten¸˜es OUT ou INOUT devem ser matrizes. No exemplo abaixo, co Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 115.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 107 ELEMENTAL SUBROUTINE TROCA(A,B) IMPLICIT NONE REAL, INTENT(INOUT) :: A, B REAL :: TEMP TEMP= A A= B B= TEMP RETURN END SUBROUTINE TROCA chamar esta subrotina com um argumento escalar e um matricial est´ obviamente errado, uma vez que o a mecanismo de distribuir o valor da vari´vel escalar por uma matriz conform´vel com o outro argumento n˜o a a a pode ser aplicado aqui. Se a referˆncia a uma rotina gen´rica (se¸˜o 8.3.4) ´ consistente tanto com uma rotina elemental quanto e e ca e com uma n˜o-elemental, a segunda vers˜o ´ invocada, pois espera-se que a vers˜o elemental de uma rotina a a e a rode, em geral, mais lentamente. Finalmente, uma rotina elemental n˜o pode ser usada como um argumento real de outra rotina. a 8.3 M´dulos o Uma das novidades mais importantes introduzidas pelo Fortran 90 ´ um novo tipo de unidade de proe grama denominada m´dulo. Um m´dulo ´ um recurso muito poderoso para transferir dados entre subo o e programas e para organizar a arquitetura global de um programa grande e complexo. A funcionalidade de um m´dulo pode ser explorada por qualquer unidade de programa que deseja fazer o uso (atrav´s de uma instru¸˜o USE) dos recursos disponibilizados por este. Os recursos que podem ser e ca inclu´ ıdos em um m´dulo s˜o os seguintes: o a Declara¸˜o de objetos globais. M´dulos devem ser empregados no lugar das declara¸˜es COMMON e INca o co CLUDE, comuns no Fortran 77. Se dados globais s˜o necess´rios, por exemplo para transferir valores a a entre rotinas, ent˜o estes s˜o s˜o tornados vis´ a a a ıveis sempre que o m´dulo ´ usado. Objetos em um o e m´dulo podem ser inicializados com valores est´ticos, de tal forma que estes mantˆm seu valor em o a e diferentes unidades que usam o mesmo m´dulo. o Blocos de interfaces. Na maior parte das situa¸˜es ´ vantajoso congregar todos os blocos de interfaces co e em um ou poucos m´dulos e ent˜o usar o m´dulo sempre que uma interface expl´ o a o ıcita ´ necess´ria. Isto e a pode realizado em conjunto com a cl´usula ONLY. a Rotinas de m´dulos. Rotinas podem ser definidas internamente em um m´dulo, sendo estas tornadas o o acess´ ıveis a qualquer unidade de programa que USE o m´dulo. Esta estrat´gia ´ mais vantajosa que o e e usar uma rotina externa porque em um m´dulo a interface das rotinas internas ´ sempre expl´ o e ıcita. Acesso controlado a objetos. Vari´veis, rotinas e declara¸˜es de operadores podem ter a sua visibilidade a co controlada por declara¸˜es ou atributos de acesso dentro de um m´dulo. Desta forma, ´ poss´ co o e ıvel especificar que um determinado objeto seja vis´ ıvel somente no interior do m´dulo. Este recurso ´ o e freq¨entemente utilizado para impedir que um usu´rio possa alterar o valor de um objeto de ˆmbito u a a puramente interno ao m´dulo. o Interfaces gen´ricas. Um m´dulo pode ser usado para definir um nome gen´rico para um conjunto de e o e rotinas, com interfaces distintas, mas que executem todas a mesma fun¸˜o. Interfaces gen´ricas podem ca e ser usadas tamb´m para estender a funcionalidade de rotinas intr´ e ınsecas. Sobrecarga de operadores. Um m´dulo pode ser usado tamb´m para redefinir a opera¸˜o executada o e ca pelos operadores intr´ ınsecos da linguagem (= + - * / **) ou para definir novos tipos de operadores. Extens˜o semˆntica. Um m´dulo de extens˜o semˆntica ´ uma cole¸˜o de defini¸˜es de tipos derivaa a o a a e ca co dos, rotinas e operadores sobrecarregados tais que, quando agregados a uma unidade de programa, permitem que o usu´rio use esta funcionalidade estendida como se fizesse parte da linguagem padr˜o. a a A forma geral de um m´dulo ´: o e MODULE <nome m´dulo> o <declara¸~es vari´veis> co a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 116.
    108 8.3. M´dulos o <comandos execut´veis> a [CONTAINS <rotinasde m´dulo>] o END [MODULE [<nome m´dulo>]] o 8.3.1 Dados globais Em Fortran, vari´veis s˜o usualmente entidades locais. Contudo, em muitas situa¸˜es ´ necess´rio que a a co e a alguns objetos tenham o seu valor compartilhado entre diferentes unidades de programa. A maneira mais usual de se realizar este compartilhamento ´ atrav´s da lista de argumentos de uma rotina. Entretanto, e e facilmente surge uma situa¸˜o onde uma vari´vel n˜o pode ser compartilhada como argumento de um subca a a programa. Neste momento, ´ necess´ria uma outra estrat´gia para se definir dados globais. Esta necessidade e a e j´ era corriqueira no Fortran 77. a Fortran 77 A maneira mais usada no Fortran 77 para compartilhar dados globais ´ atrav´s de blocos common. e e Um bloco common ´ uma lista de vari´veis armazenadas em uma ´rea da mem´ria do computador que ´ e a a o e identificada atrav´s de um nome e que pode ser acessada diretamente em mais de uma unidade de programa. e A necessidade de se criar um bloco common surge, muitas vezes, com o uso de rotinas de bibliotecas de aplica¸˜o generalizada, as quais s˜o definidas com um conjunto restrito de argumentos. Muitas vezes, faz-se ca a necess´rio transferir informa¸˜o entre estas rotinas ou entre rotinas que usam as bibliotecas de maneira n˜o a ca a prevista na lista de argumentos. Por exemplo, seja a subrotina INTEG, a qual realiza a integra¸˜o num´rica unidimensional de uma fun¸˜o ca e ca F(x) qualquer, no intervalo (A,B): SUBROUTINE INTEG(F,A,B,RES) REAL*8 A, B, F, RES, TEMP EXTERNAL F ... TEMP= F(X) ... RES= <resultado> END SUBROUTINE INTEG Caso o programador queira integrar a fun¸˜o g(x) = cos(αx) no intervalo [0, 1], ele n˜o poder´ informar ca a a ao integrador o valor de α na lista de argumentos da subrotina INTEG. A solu¸˜o est´ no uso de um bloco ca a common: REAL*8 FUNCTION G(X) REAL*8 X, ALFA COMMON /VAR/ ALFA G= COS(ALFA*X) RETURN END FUNCTION G onde VAR ´ o nome que identifica o espa¸o de mem´ria onde o valor de ALFA ser´ armazenado. Assim, o e c o a programa pode realizar a integra¸˜o usando o mesmo bloco common: ca PROGRAM INTEGRA REAL*8 G, A, INT EXTERNAL G COMMON /VAR/ A ... PRINT*, ’Entre com o valor de alfa:’ READ(*,*) A C CALL INTEG(G,0.0D0,1.0D0,INT) C ... END PROGRAM INTEGRA Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 117.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 109 Note que o bloco VAR aparece tanto no programa quanto na fun¸˜o; por´m n˜o h´ necessidade de ele aparecer ca e a a na subrotina INTEG. A forma geral de um bloco common ´: e COMMON /<nome common>/ <lista vari´veis> a onde <nome common> ´ qualquer nome v´lido em Fortran e <lista vari´veis> ´ uma lista de vari´veis e a a e a que podem ser escalares, elementos de matrizes, se¸˜es de matrizes ou matrizes completas. Neste ultimo co ´ ´ caso, somente se utiliza o nome da matriz. E claro que a informa¸˜o acerca da natureza e tipo das vari´veis ca a listadas no bloco common deve ser fornecida por declara¸˜es adequadas de vari´veis. co a A grande desvantagem desta forma descentralizada de definir-se dados globais est´ no fato de que em a todas as unidades de programa que utilizam um dado bloco common, as vari´veis listadas nele devem cona cordar em n´mero, ordem, natureza e tipo. Caso o programador esteja desenvolvendo um c´digo complexo, u o composto por um n´mero grande de unidades que usam o mesmo bloco common, e ele sinta a necessidade u de alterar de alguma forma a lista de vari´veis em uma determinada unidade, ele dever´ buscar em todas a a unidades restantes que fazem referˆncia ao mesmo bloco e realizar a mesma altera¸˜o; caso contr´rio, mesmo e ca a que o programa compile e linke sem erro, ´ quase certo que as vari´veis ser˜o compartilhadas de forma incoe a a ´ a erente entre as diferentes unidade de programa e este acabe gerando resultados incorretos. E f´cil perceber que este controle torna-se sucessivamente mais dif´ ` medida que a complexidade do programa aumenta. ıcil a Os blocos common s˜o ainda aceitos em Fortran 90/95; por´m, o seu uso n˜o ´ recomendado, pela raz˜o a e a e a exposta acima. Fortran 90/95 O uso de um m´dulo fornece um mecanismo centralizado de defini¸˜o de objetos globais. Por exemplo, o ca suponha que se queira ter acesso `s vari´veis inteiras I, J e K e `s vari´veis reais A, B e C em diferentes a a a a unidades de programa. Um m´dulo que permitira o compartilhamento destas vari´veis ´ o seguinte: o a e MODULE GLOBAIS IMPLICIT NONE INTEGER :: I, J, K REAL :: A, B, C END MODULE GLOBAIS Estas vari´veis se tornam acess´ a ıveis a outras unidades de programa (inclusive outros m´dulos) atrav´s da o e instru¸˜o USE, isto ´: ca e USE GLOBAIS A instru¸˜o USE ´ n˜o execut´vel e deve ser inserida logo ap´s o cabe¸alho da unidade de programa (PROGRAM, ca e a a o c FUNCTION, SUBROUTINE ou MODULE) e antes de qualquer outra instru¸˜o n˜o execut´vel, tal como uma ca a a declara¸˜o de vari´veis. Uma unidade de programa pode invocar um n´mero arbitr´rio de m´dulos usando ca a u a o uma s´rie de instru¸˜es USE. Um m´dulo pode usar outros m´dulos, por´m um m´dulo n˜o pode usar a si e co o o e o a pr´prio, seja de forma direta ou indireta. o Assim, o m´dulo GLOBAIS pode ser usado da seguinte forma: o FUNCTION USA_MOD(X) USE GLOBAIS IMPLICIT NONE REAL :: USA_MOD REAL, INTENT(IN) :: X USA_MOD= I*A - J*B + K*C - X RETURN END FUNCTION USA_MOD O vantagem de um m´dulo sobre um bloco COMMON para compartilhar objetos globais ´ evidente. A defio e ni¸˜o dos nomes, tipos e esp´cies das vari´veis ´ realizada em uma unica unidade de programa, a qual ´ ca e a e ´ e simplesmente usada por outras, estabelecendo assim um controle centralizado sobre os objetos. O uso de vari´veis de um m´dulo pode causar problemas se o mesmo nome ´ usado para diferentes a o e vari´veis em partes diferentes de um programa. A declara¸˜o USE pode evitar este problema ao permitir a a ca especifica¸˜o de um nome local distinto daquele definido no m´dulo, por´m que ainda permita o acesso aos ca o e dados globais. Por exemplo, Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 118.
    110 8.3. M´dulos o ... USE GLOBAIS,R => A, S => B ... USA_MOD= I*R - J*S + K*C - X ... Aqui, os nomes R e S s˜o usado para acessar as vari´veis globais A e B, definidas no m´dulo, caso estes a a o nomes ultimos sejam usados para diferentes vari´veis na mesma unidade de programa. Os s´ ´ a ımbolos “=>“ promovem a liga¸˜o do nome local com o nome no m´dulo. Tudo se passa como se R fosse o apelido de A e S ca o o apelido de B nesta unidade de programa. Os ponteiros em Fortran 90/95 tamb´m atuam como apelidos, e por´m, neste caso, pode-se usar tanto o nome verdadeiro de uma vari´vel quanto o nome de um ponteiro e a que aponta a ela. Existe tamb´m uma forma da declara¸˜o USE que limita o acesso somente a certos objetos dentro de um e ca m´dulo. Este recurso n˜o ´ exatamente igual ao uso dos atributos PUBLIC ou PRIVATE (se¸˜o 8.3.3), uma o a e ca vez que ele atua somente na unidade que acessa o m´dulo, e n˜o sobre o m´dulo em geral. O recurso requer o a o o uso do qualificador ONLY, seguido de dois pontos “:” e uma <lista only>: USE <nome m´dulo>, ONLY: <lista only> o Por exemplo para tornar somente as vari´veis A e C do m´dulo GLOBAIS acess´ a o ıveis em uma dada unidade de programa, a declara¸˜o fica: ca ... USE GLOBAIS, ONLY: A, C ... Os dois ultimos recursos podem ser tamb´m combinados: ´ e ... USE GLOBAIS, ONLY: R => A ... para tornar somente a vari´vel A acess´ a ıvel, por´m com o nome R. Uma unidade de programa pode ter mais e de uma declara¸ao USE referindo-se ao mesmo m´dulo. Por conseguinte, deve-se notar que que um USE com c˜ o o qualificador ONLY n˜o cancela uma declara¸ao USE menos restritiva. a c˜ Um uso freq¨ente de m´dulos para armazenar dados globais consiste em defini¸˜es de parˆmetros de u o co a esp´cie de tipo, constantes universais matem´ticas e/ou f´ e a ısicas e outros objetos est´ticos, como no exemplo a abaixo: ! *** Module E s p c o n s t *** ! D e f i n e e s p ´ c i e s de t i p o p a d r o e s e c o n s t a n t e s u n i v e r s a i s . e ˜ ! M D L esp const O UE ! INTEGER, P R M T R : : I4B = SELECTED INT KIND ( 9 ) A A EE INTEGER, P R M T R : : I2B = SELECTED INT KIND ( 4 ) A A EE INTEGER, P R M T R : : I1B = SELECTED INT KIND ( 2 ) A A EE integer , parameter : : sp= kind ( 1 . 0 ) integer , parameter : : dp= s e l e c t e d r e a l k i n d ( 2 * precision ( 1 . 0 s p ) ) integer , parameter : : qp= s e l e c t e d r e a l k i n d ( 2 * precision ( 1 . 0 dp ) ) complex ( kind= dp ) , parameter : : z1= ( 1 . 0 dp , 0 . 0 dp ) , z i= ( 0 . 0 dp , 1 . 0 dp ) REAL(DP) , P R M T R : : PI= A A EE 3.14159265358979323846264338327950288419717 REAL(DP) , P R M T R : : PID2= A A EE 1.57079632679489661923132169163975144209858 REAL(DP) , P R M T R : : TWOPI= A A EE 6.28318530717958647692528676655900576839434 r e a l ( dp ) , parameter : : r t p i= 1.77245385090551602729816748334114518279755 REAL(DP) , P R M T R : : SQRT2= A A EE 1.41421356237309504880168872420969807856967 r e a l ( dp ) , parameter : : e u l e r e= 2 . 7 1 8 2 8 1 8 2 8 4 5 9 0 4 5 2 3 5 3 6 0 2 8 7 4 7 1 3 5 2 6 6 2 4 9 7 7 5 7 2 5 REAL(SP ) , P R M T R : : PI S= A A EE 3.14159265358979323846264338327950288419717 REAL(SP ) , P R M T R : : PID2 S= 1 . 5 7 0 7 9 6 3 2 6 7 9 4 8 9 6 6 1 9 2 3 1 3 2 1 6 9 1 6 3 9 7 5 1 4 4 2 0 9 8 5 8 A A EE REAL(SP ) , P R M T R : : TWOPI s= 6 . 2 8 3 1 8 5 3 0 7 1 7 9 5 8 6 4 7 6 9 2 5 2 8 6 7 6 6 5 5 9 0 0 5 7 6 8 3 9 4 3 4 A A EE r e a l ( sp ) , parameter : : r t p i s= 1 . 7 7 2 4 5 3 8 5 0 9 0 5 5 1 6 0 2 7 2 9 8 1 6 7 4 8 3 3 4 1 1 4 5 1 8 2 7 9 7 5 5 Autor: Rudi Gaelzer – IFM/UFPel dp dp dp dp dp dp sp sp sp sp Impresso: 13 de abril de 2010
  • 119.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 111 Programa 8.3: Ilustra uso de m´dulo para armazenar dados globais. o M D L modu1 O UE i m p l i c i t none real , parameter : : p i= 3 . 1 4 1 5 9 2 6 5 3 6 real , parameter : : e u l e r e= 2 . 7 1 8 2 8 1 8 2 8 END M D L modu1 O UE ! ***************************************** program mod1 use modu1 i m p l i c i t none real : : x do print * , ”Entre com o v a l o r de x : ” read * , x print * , ”s e n ( p i * x)= ” , s e n ( ) print * , ” l n ( e * x)= ” , l n ( ) end do CONTAINS function s e n ( ) real : : sen s e n= s i n ( p i * x ) return end function s e n ! function l n ( ) real : : ln l n= l o g ( e u l e r e * x ) return end function l n end program mod1 REAL(SP ) , P R M T R : : SQRT2 S= 1 . 4 1 4 2 1 3 5 6 2 3 7 3 0 9 5 0 4 8 8 0 1 6 8 8 7 2 4 2 0 9 6 9 8 0 7 8 5 6 9 6 7 s p A A EE ! ! Fundamental p h y s i c a l c o n s t a n t s , o b t a i n e d from NIST : ! h t t p : / / p h y s i c s . n i s t . gov / cuu / C o n s t a n t s / i n d e x . html r e a l ( dp ) , parameter : : rmemp= 5 . 4 4 6 1 7 0 2 1 7 3 e−4 dp ! E l e c t r o n −p r o t o n mass r a t i o . r e a l ( dp ) , parameter : : rmpme= 1 8 3 6 . 1 5 2 6 7 2 6 1 dp ! Protron−e l e c t r o n mass r a t i o . END M D L e s p c o n s t O UE O programa-exemplo mod1.f90 (programa 8.3), ilustra o uso de um m´dulo para armazenar dados o globais. 8.3.2 Rotinas de m´dulos o Rotinas podem ser definidas em m´dulos e estas s˜o denominadas rotinas de m´dulos. Estas podem ser o a o tanto subrotinas quanto fun¸˜es e ter a mesma forma de rotinas internas definidas dentro de outras unidades co de programa. O n´mero de rotinas de m´dulo ´ arbitr´rio. u o e a Rotinas de m´dulo podem ser chamadas usando o comando CALL usual ou fazendo referˆncia ao nome o e de uma fun¸˜o. Contudo, estas somente s˜o acess´ ca a ıveis a unidades de programa que fazem uso do m´dulo o atrav´s da instru¸˜o USE. e ca Uma rotina de m´dulo pode invocar outras rotinas de m´dulo contidas no mesmo m´dulo. As vari´veis o o o a declaradas no m´dulo antes da palavra-chave CONTAINS s˜o diretamente acess´ o a ıveis a todas as rotinas deste, por associa¸˜o ao hospedeiro. Contudo, vari´veis declaradas localmente em um determinado sub-programa ca a de m´dulo s˜o opacas aos outros sub-programas. Caso o m´dulo invoque outro m´dulo com uma instru¸˜o o a o o ca USE antes da palavra-chave CONTAINS, estes objetos tamb´m se tornam acess´ e ıveis a todas as rotinas de m´dulo. Por outro lado, uma determinada rotina de m´dulo pode usar localmente outro m´dulo (n˜o o o o o a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 120.
    112 8.3. M´dulos o hospedeiro), emcuja situa¸˜o os objetos somente s˜o acess´ ca a ıveis localmente. Em suma, uma rotina de m´dulo o possui todas as propriedades de rotinas internas em outras unidades de programa, exceto que uma rotina de m´dulo pode conter, por sua vez, rotinas internas a ela. Por exemplo, o seguinte m´dulo ´ v´lido: o o e a MODULE INTEG IMPLICIT NONE REAL :: ALFA ! Vari´vel global. a CONTAINS FUNCTION FF(X) REAL :: FF REAL, INTENT(IN) :: X FF= EXP(-ALFA*X*X) FF= FF*X2(X) RETURN CONTAINS FUNCTION X2(Y) REAL :: X2 REAL, INTENT(IN) :: Y X2= Y**2 RETURN END FUNCTION X2 END FUNCTION FF END MODULE INTEG A outra grande diferen¸a est´ no fato de que as interfaces das rotinas de m´dulo s˜o expl´ c a o a ıcitas no ˆmbito a deste. Todavia, quando uma outra unidade de programa usa o m´dulo, todas os objetos p´blicos nele cono u tidos se tornam acess´ ıveis a esta, resultando que as interfaces das rotinas de m´dulo s˜o automaticamente o a expl´ ıcitas tamb´m para a unidade de programa que o invoca. Portanto, um m´dulo ´ considerado a unie o e dade ideal para armazenar grupos de sub-programas criados para desempenhar uma determinada tarefa, juntamente com os objetos globais associados a estes sub-programas. Ao se compilar um arquivo contendo um m´dulo, os compiladores automaticamente geram um novo o tipo de arquivo, geralmente com a extens˜o *.mod, onde as informa¸˜es contidas no m´dulo, tais como a co o vari´veis globais e interfaces, s˜o armazenadas. Quando uma outra unidade de programa faz referˆncia a a a e este m´dulo, o compilador busca estas informa¸˜es no arquivo .mod . Desta forma, cria-se um mecanismo o co para verificar se as vari´veis e as interfaces est˜o sendo corretamente utilizadas pela unidade que chama o a a m´dulo. Quando o m´dulo n˜o define um rotina interna, n˜o ´ necess´rio guardar o arquivo objeto (*.o o o a a e a ou *.obj) associado, bastando guardar o arquivo *.mod. Por esta raz˜o, muitos compiladores oferecem a uma chave extra de compila¸˜o atrav´s da qual nenhum arquivo objeto ´ criado, mas somente o arquivo de ca e e m´dulo. o Rotinas de m´dulo pode ser uteis por diversas raz˜es. Por exemplo, um m´dulo que define a estrutura de o ´ o o um conjunto particular de dados pode tamb´m incluir rotinas especiais, necess´rias para operar com estes e a dados; ou um m´dulo pode ser usado para conter uma biblioteca de rotinas relacionadas entre si. o Como exemplo, um m´dulo pode ser usado para “adicionar” vari´veis de tipo derivado: o a MODULE MOD_PONTO IMPLICIT NONE TYPE :: PONTO REAL :: X, Y END TYPE PONTO CONTAINS FUNCTION ADPONTOS(P,Q) TYPE(POINT) :: ADPONTOS TYPE(POINT), INTENT(IN) :: P, Q ADPONTOS%X= P%X + Q%X ADPONTOS%Y= P%Y + Q%Y RETURN END FUNCTION ADPONTOS END MODULE MOD_PONTO Neste caso, o programa principal usa este m´dulo: o Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 121.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 113 Programa 8.4: Ilustra o uso de rotinas de m´dulo. o M D L modu2 O UE i m p l i c i t none real , parameter : : p i= 3 . 1 4 1 5 9 2 6 5 3 6 real , parameter : : e u l e r e= 2 . 7 1 8 2 8 1 8 2 8 real : : x CONTAINS function s e n ( ) real : : sen s e n= s i n ( p i * x ) return end function s e n ! function l n ( ) real : : ln l n= l o g ( e u l e r e * x ) return end function l n END M D L modu2 O UE ! ***************************************** program mod2 use modu2 i m p l i c i t none do print * , ”Entre com o v a l o r de x : ” read * , x print * , ”s e n ( p i * x)= ” , s e n ( ) print * , ” l n ( e * x)= ” , l n ( ) end do end program mod2 PROGRAM P_PONTO USE MOD_PONTO IMPLICIT NONE TYPE(POINT) :: PX, PY, PZ ... PZ= ADPONTO(PX,PY) ... END PROGRAM P_PONTO O recurso avan¸ado de sobrecarga de operador (operator overloading) permite redefinir a opera¸˜o de adi¸˜o c ca ca (+), por exemplo, dentro do ˆmbito do m´dulo M_PONTO, de tal forma que o processo de adi¸˜o de duas a o ca vari´veis do tipo PONTO automaticamente iria chamar a fun¸˜o ADPONTO. Desta forma, ao inv´s do programa a ca e chamar esta fun¸˜o, bastaria realizar a opera¸˜o: ca ca PZ= PX + PY Entretanto, este recurso n˜o ser´ discutido aqui. a a O programa-exemplo mod2.f90 (programa 8.4) ´ igual ao mod1.f90, por´m usando rotinas de m´dulo. e e o 8.3.3 Atributos e declara¸˜es PUBLIC e PRIVATE co Usualmente, todas as entidades em um m´dulo est˜o dispon´ o a ıveis para qualquer unidade de programa que chame este m´dulo com a instru¸˜o USE. Contudo, em certas situa¸˜es ´ recomend´vel proibir o uso o ca co e a de certas entidades (objetos globais e/ou rotinas) contidas no m´dulo para for¸ar o usu´rio a invocar as o c a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 122.
    114 8.3. M´dulos o rotinas dem´dulo que realmente deveriam ser acess´ o ıveis a este, ou para permitir flexibilidade no aperfei¸oc amento das entidades contidas no m´dulo sem haver a necessidade de informar o usu´rio a respeito destes o a aperfei¸oamentos. c Este controle ´ exercido atrav´s dos atributos ou declara¸˜es PUBLIC ou PRIVATE. Por exemplo, abaixo e e co temos a declara¸˜es de vari´veis com dois atributos distintos: co a REAL, PUBLIC :: X, Y, Z INTEGER, PRIVATE :: U, V, W Dentro deste conjunto de vari´veis, somente X, Y e Z s˜o acess´ a a ıveis ` unidade de programa que acessa este a m´dulo. o Outra maneira de se estabelecer o controle de acesso ´ atrav´s de declara¸˜es, as quais listam os nomes e e co dos objetos que s˜o p´blicos ou privados: a u PUBLIC :: X, Y, Z PRIVATE :: U, V, W A forma geral da declara¸˜o ´: ca e PUBLIC [[::] <lista acesso>] PRIVATE [[::] <lista acesso>] Caso nenhum controle ´ estabelecido em um m´dulo, seja atrav´s de um atributo ou de uma declara¸˜o, e o e ca todas as entidades tˆm o atributo PUBLIC. e Se uma declara¸˜o PUBLIC ou PRIVATE n˜o possui uma lista de entidades, esta confirma ou altera o ca a acesso padr˜o. Assim, a declara¸˜o a ca PUBLIC confirma o acesso padr˜o, ao passo que a declara¸˜o a ca PRIVATE altera o acesso padr˜o. Desta forma, uma seq¨ˆncia de declara¸˜es como as abaixo: a ue co ... PRIVATE PUBLIC <lista acesso> ... confere aos nomes na <lista acesso> o atributo PUBLIC enquanto que todas as entidades restantes no m´dulo s˜o privadas, podendo ser acessadas somente dentro do ˆmbito do m´dulo. o a a o 8.3.4 Interfaces e rotinas gen´ricas e Outro recurso poderoso introduzido pelo Fortran 90 ´ a habilidade do programador definir suas pr´e o prias rotinas gen´ricas, de tal forma que um unico nome ´ suficiente para invocar uma determinada rotina, e ´ e enquanto que a a¸˜o que realmente ´ executada quando este nome ´ usado depende do tipo de seus argumenca e e tos. Embora possam ser declaradas em quaisquer unidades de programa, rotinas gen´ricas s˜o usualmente e a definidas em m´dulos. o Uma rotina gen´rica ´ definido usando-se um bloco interfaces e um nome gen´rico ´ usado para todas as e e e e rotinas definidas dentro deste bloco de interfaces. Assim, a forma geral ´: e INTERFACE <nome gen´rico> e <bloco interface rotina espec´fica 1> ı <bloco interface rotina espec´fica 2> ı ... END INTERFACE <nome gen´rico> e onde <bloco interface rotina espec´fica 1>, etc, s˜o os blocos das interfaces das rotinas espec´ ı a ıficas, isto ´, que se referem a um dado conjunto de tipos de vari´veis, e que s˜o acessadas atrav´s do <nome e a a e gen´rico>. As rotinas per se podem se encontrar em outras unidades; por exemplo, elas podem ser rotinas e externas. O uso do <nome gen´rico> no final do bloco somente ´ permitido a partir do Fortran 95. e e Como um m´dulo ´ a unidade de programa ideal para armazenar todas estas rotinas espec´ o e ıficas relacionadas entre si e como as interfaces das rotinas de m´dulo s˜o sempre expl´ o a ıcitas, estas rotinas gen´ricas s˜o, e a em geral, definidas dentro de m´dulos. Neste caso, a declara¸˜o o ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 123.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 115 MODULE PROCEDURE <lista nomes rotinas> ´ inclu´ no bloco de interface para nomear as rotinas de m´dulo que s˜o referidas atrav´s do nome gen´rico. e ıda o a e e Assim, a declara¸˜o geral ´: ca e INTERFACE <nome gen´rico> e [<blocos interfaces>] [MODULE PROCEDURE <lista nomes rotinas>] ! Em Fortran 95 blocos de interfaces e declara¸~es MODULE PROCEDURE co ! podem aparecer em qualquer ordem. END INTERFACE [<nome gen´rico>] e ! Somente em Fortran 95 o nome gen´rico ´ aceito aqui. e e Deve-se notar que todos os nomes na <lista nomes rotinas> devem ser de rotinas de m´dulo acess´ o ıveis; portanto, elas n˜o necessariamente devem estar definidas no mesmo m´dulo onde a interface gen´rica ´ a o e e estabelecida, bastando que elas sejam acess´ ıveis por associa¸˜o de uso. ca Para demonstrar o poderio de uma interface gen´rica, ser´ utilizada novamente a subrotina TROCA, a qual e a foi definida primeiramente na p´gina 95 e depois, na forma de uma subrotina elemental, na se¸˜o 8.2.17. a ca O m´dulo gentroca na p´gina 116 define o nome gen´rico de uma s´rie de subrotinas elementais TROCA o a e e associadas a vari´veis dos tipos real, inteiro, l´gico e do tipo derivado ponto, o qual ´ definido no mesmo a o e m´dulo. o Este m´dulo ´ utilizado ent˜o em duas situa¸˜es distintas. Na primeira vez, o m´dulo ser´ utilizado para o e a co o a a trocar o valor de duas vari´veis escalares do tipo ponto, como no programa usa gentroca.f90 na p´gina a 117. Posteriormente, o mesmo m´dulo ser´ utilizado para trocar os elementos de duas matrizes inteiras, o a como no programa usa_gt_mat.f90, tamb´m listado na p´gina 117. e a Uma declara¸˜o MODULE PROCEDURE somente ´ permitida se um <nome gen´rico> ´ fornecido. Por´m, ca e e e e o nome gen´rico pode ser igual ao nome de uma das rotinas declaradas na <lista nomes rotinas>. Em e conjunto com esta propriedade, o nome gen´rico definido em um m´dulo pode ser o mesmo de outro nome e o gen´rico acess´ ao m´dulo, inclusive no caso onde o nome gen´rico corresponde ao de uma rotina intr´ e ıvel o e ınseca. Neste caso, o m´dulo estar´ estendendo o intervalo de aplica¸˜o de uma rotina intr´ o a ca ınseca. As rotinas `s quais s˜o dadas um certo nome gen´rico devem ser todas ou subrotinas ou fun¸˜es, incluindo a a e co as intr´ ınsecas quando uma rotina intr´ ınseca ´ estendida. Quaisquer duas rotinas n˜o-intr´ e a ınsecas associadas ao mesmo nome gen´rico devem ter argumentos que diferem de tal forma que qualquer invoca¸˜o ´ feita de e ca e forma inequ´ ıvoca. As regras s˜o que: a 1. uma delas tenha mais argumentos obrigat´rios mudos de um tipo, esp´cie e posto particulares que a o e outra ou 2. que ao menos uma delas tenha um argumento mudo obrigat´rio tal que o (a) corresponda por posi¸˜o na lista de argumentos a um argumento mudo que n˜o esteja presente ca a na outra, ou esteja presente com um tipo e/ou esp´cie distinta ou com posto distinto, e e (b) corresponda por nome a um argumento mudo que n˜o esteja presente na outra, ou presente com a tipo e/ou esp´cie diferente ou com posto diferente. e Para o caso (2), ambas as regras s˜o necess´rias para descartar a possibilidade de invoca¸˜o amb´ a a ca ıgua por uso de palavras-chave. Como exemplo onde haver´ ambig¨idade, o exemplo abaixo: a u !Exemplo de defini¸~o amb´gua de nome gen´rico ca ı e INTERFACE F MODULE PROCEDURE FXI, FIX END INTERFACE F CONTAINS FUNCTION FXI(X,I) REAL :: FXI REAL, INTENT(IN) :: X INTEGER, INTENT(IN) :: I ... Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 124.
    116 8.3. M´dulos o ! De f i n e nome g e n ´ r i c o para t r o c a de duas v a r i ´ v e i s q u a i s q u e r . e a M D L gentroca O UE i m p l i c i t none type : : ponto real : : x , y end type ponto ! INTERFACE t r o c a M D L PROCEDURE t r o c a p o n t o , t r o c a r e a l , t r o c a i n t , t r o c a l o g O UE END INTERFACE t r o c a ! CONTAINS e l e m e n t a l subroutine t r o c a p o n t o ( a , b ) type ( ponto ) , intent ( inout ) : : a , b type ( ponto ) : : temp temp= a a= b b= temp end subroutine t r o c a p o n t o ! e l e m e n t a l subroutine t r o c a r e a l ( a , b ) real , intent ( inout ) : : a , b r e a l : : temp temp= a a= b b= temp end subroutine t r o c a r e a l ! e l e m e n t a l subroutine t r o c a i n t ( a , b ) integer , intent ( inout ) : : a , b integer : : temp temp= a a= b b= temp end subroutine t r o c a i n t ! e l e m e n t a l subroutine t r o c a l o g ( a , b ) l o g i c a l , intent ( inout ) : : a , b l o g i c a l : : temp temp= a a= b b= temp end subroutine t r o c a l o g END M D L g e n t r o c a O UE Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 125.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 117 program u s a g e n t r o c a use g e n t r o c a type ( ponto ) : : b= ponto ( 1 . 0 , 0 . 0 ) , c= ponto ( 1 . 0 , 1 . 0 ) print * , ’ V a l o r e s o r i g i n a i s : ’ print * , b , c call troca (b , c ) print * , ’ Novos v a l o r e s : ’ print * , b , c end program u s a g e n t r o c a program u s a g t m a t use g e n t r o c a integer , dimension ( 2 , 2 ) : : b , b= r e s h a p e ( s o u r c e= ( / ( ( i+j , c= r e s h a p e ( s o u r c e= ( / ( ( i+j , print * , ’ V a l o r e s o r i g i n a i s : ’ do i= 1 , 2 print * , b ( i , : ) , ” ”,c(i end do call troca (b , c ) print * , ’ Novos v a l o r e s : ’ do i= 1 , 2 print * , b ( i , : ) , ” ”,c(i end do end program u s a g t m a t c i= 1 , 2 ) , j= 1 , 2 ) / ) , shape= ( / 2 , 2 / ) ) i= 3 , 4 ) , j= 3 , 4 ) / ) , shape= ( / 2 , 2 / ) ) ,:) ,:) END FUNCTION FXI ! FUNCTION FIX(I,X) REAL :: FIX REAL, INTEN(IN) :: X INTEGER, INTENT(IN) :: I ... END FUNCTION FIX Neste caso, a chamada ao nome gen´rico F ser´ n˜o-amb´ e a a ıgua no caso de argumentos posicionais: A= F(INT,VAR) por´m ser´ amb´ e a ıgua para chamada usando palavras-chave: A= F(I= INT, X= VAR) Se uma invoca¸˜o gen´rica ´ amb´ ca e e ıgua entre uma rotina intr´ ınseca e uma n˜o-intr´ a ınseca, esta ultima ´ sempre ´ e invocada. 8.3.5 Estendendo rotinas intr´ ınsecas via blocos de interface gen´ricos e Como j´ foi mencionado, uma rotina intr´ a ınseca pode ser estendida ou tamb´m redefinida. Uma rotina e intr´ ınseca estendida suplementa as rotinas intr´ ınsecas espec´ ıficas j´ existentes. Uma rotina intr´ a ınseca redefinida substitui uma rotina intr´ ınseca espec´ ıfica existente. Desta forma ´ poss´ ampliar um determinado e ıvel c´lculo de uma fun¸˜o, por exemplo, para interfaces n˜o previstas pelo padr˜o da linguagem (extens˜o) a ca a a a e/ou substituir o processo de c´lculo do valor da fun¸˜o por um c´digo distinto daquele implementado no a ca o compilador (substitui¸˜o). ca Quando um nome gen´rico ´ igual ao nome gen´rico de uma rotina intr´ e e e ınseca e o nome ´ declarado com e o atributo ou declara¸˜o INTRINSIC (ou aparece em um contexto intr´ ca ınseco), a interface gen´rica estende a e rotina gen´rica intr´ e ınseca. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 126.
    ˆ 8.4. Ambito (Scope) 118 Quandoum nome gen´rico ´ igual ao nome gen´rico de uma rotina intr´ e e e ınseca e este nome n˜o possui o a atributo INTRINSIC (nem possui este atributo pelo contexto), a rotina gen´rica redefine a rotina gen´rica e e intr´ ınseca. Como exemplo, o m´dulo EXT_SINH abaixo estende o c´lculo da fun¸˜o seno hiperb´lico para um arguo a ca o mento escalar complexo, enquanto que o padr˜o da linguagem somente considera argumentos reais (se¸˜o a ca 7.5): MODULE EXT_SINH IMPLICIT NONE INTRINSIC :: SINH ! INTERFACE SINH MODULE PROCEDURE SINH_C END INTERFACE SINH ! CONTAINS FUNCTION SINH_C(Z) COMPLEX :: SINH_C COMPLEX, INTENT(IN) :: Z REAL :: X,Y X= REAL(Z) Y= AIMAG(Z) SINH_C= CMPLX(SINH(X)*COS(Y),COSH(X)*SIN(Y)) RETURN END FUNCTION SINH_C END MODULE EXT_SINH 8.4 ˆ Ambito (Scope) J´ foi mencionado neste texto, em diversos lugares, o ˆmbito de um certo nome de vari´vel. O ˆmbito a a a a de um objeto nomeado ou de um r´tulo ´ o conjunto de unidades de ambito, que n˜o se sobrep˜e, onde o o e ˆ a o nome deste objeto pode ser usado sem ambig¨idade. u Uma unidade de ˆmbito ´ qualquer um dos seguintes: a e ˆ uma defini¸˜o de tipo derivado; ca ˆ o corpo de um bloco de interfaces de rotinas, excluindo quaisquer defini¸˜es de tipo derivado e blocos co de interfaces contidos dentro deste, ou ˆ uma unidade de programa ou sub-programa, excluindo defini¸˜es de tipo derivado, blocos de interfaces co e rotinas internas contidas dentro desta unidade. 8.4.1 ˆ Ambito dos r´tulos o Toda unidade de programa ou sub-programa, interno ou externo, tem seu conjunto independente de r´tulos. Portanto, o mesmo r´tulo pode ser usado em um programa principal e em seus sub-programas o o internos sem ambig¨idade. u Assim, o ˆmbito de um r´tulo ´ um programa principal ou sub-programa, excluindo quaisquer suba o e programas internos que eles contenham. O r´tulo pode ser usado sem ambig¨idade em qualquer ponto entre o u os comandos execut´veis de seu ˆmbito. a a 8.4.2 ˆ Ambito dos nomes O ˆmbito de um nome declarado em uma unidade de programa estende-se do cabe¸alho da unidade de a c programa ao seu comando END. O ˆmbito de um nome declarado em um programa principal ou rotina externa a estende-se a todos os sub-programas que eles contˆm, exceto quando o nome ´ redeclarado no sub-programa. e e O ˆmbito de um nome declarado em uma rotina interna ´ somente a pr´pria rotina, e n˜o os outros a e o a sub-programas internos. O ˆmbito do nome de um sub-programa interno e do n´mero e tipos dos seus a u argumentos estende-se por toda a unidade de programa que o cont´m, inclusive por todos os outros sube programas internos. Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 127.
    Cap´ ıtulo 8. Sub-Programase M´dulos o 119 O ˆmbito de um nome declarado em um m´dulo estende-se a todas as unidades de programa que usam a o este m´dulo, exceto no caso em que a entidade em quest˜o tenha o atributo PRIVATE, ou ´ renomeada na o a e unidade de programa que usa o m´dulo ou quando a instru¸˜o USE apresenta o qualificador ONLY e a entidade o ca em quest˜o n˜o esteja na <lista only>. O ˆmbito de um nome declarado em um m´dulo estende-se a todos a a a o os sub-programas internos, excluindo aqueles onde o nome ´ redeclarado. e Considerando a defini¸˜o de unidade de ˆmbito acima, ca a ˆ Entidades declaradas em diferentes unidades de ˆmbito s˜o sempre distintas, mesmo que elas tenham a a o mesmo nome e propriedades. ˆ Dentro de uma unidade de ˆmbito, cada entidade nomeada deve possuir um nome distinto, com a a exce¸˜o de nomes gen´ricos de rotinas. ca e ˆ Os nomes de unidades de programas s˜o globais; assim, cada nome deve ser distinto dos outros e a distinto de quaisquer entidades locais na unidade de programa. ˆ O ˆmbito do nome de uma rotina interna estende-se somente por toda a unidade de programa que a a cont´m. e ˆ O ˆmbito de um nome declarado em uma rotina interna ´ esta rotina interna. a e Este conjunto de regras resume a defini¸˜o de ˆmbito de um nome. ca a Nomes de entidades s˜o acess´ a ıveis por associa¸˜o ao hospedeiro ou associa¸˜o por uso quando: ca ca Associa¸˜o ao hospedeiro. O ˆmbito de um nome declarado em uma unidade de programa estende-se ca a do cabe¸alho da unidade de programa ao comando END. c Associa¸˜o por uso. O ˆmbito de um nome declarado em um m´dulo, o qual n˜o possui o atributo ca a o a PRIVATE, estende-se a qualquer unidade de programa que usa o m´dulo. o Nota-se que ambos os tipos de associa¸˜o n˜o se estende a quaisquer rotinas externas que possam ser ca a invocadas e n˜o incluem quaisquer rotinas internas onde o nome ´ redeclarado. a e Um exemplo contendo 5 unidades de ˆmbito ´ ilustrado a seguir: a e MODULE AMBITO1 ... CONTAINS SUBROUTINE AMBITO2 TYPE :: AMBITO3 ... END TYPE AMBITO3 INTERFACE ... END INTERFACE ... CONTAINS FUNCTION AMBITO5(...) ... END FUNCTION AMBITO5 END SUBROUTINE AMBITO2 END MODULO AMBITO1 Autor: Rudi Gaelzer – IFM/UFPel ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito Ambito 1 1 1 2 3 3 3 2 4 2 2 2 5 5 5 2 1 Impresso: 13 de abril de 2010
  • 128.
    120 Autor: Rudi Gaelzer– IFM/UFPel ˆ 8.4. Ambito (Scope) Impresso: 13 de abril de 2010
  • 129.
    Cap´ ıtulo 9 Comandos deEntrada/Sa´ de ıda Dados O Fortran 90/95 possui um conjunto rico de instru¸˜es de entrada/sa´ (E/S) de dados. Entretanto, co ıda este cap´ ıtulo ir´ apresentar apenas um conjunto de instru¸˜es que implementam um processo b´sico de E/S. a co a Muitos programas necessitam de dados iniciais para o seu processamento. Depois que os c´lculos estivea rem completos, os resultados naturalmente precisam ser impressos, mostrados graficamente ou salvos para uso posterior. Durante a execu¸˜o de um programa, algumas vezes h´ uma quantidade grande de dados ca a produzidos por uma parte do programa, os quais n˜o podem ser todos armazenados na mem´ria de acesso a o aleat´rio (RAM) do computador. Nesta situa¸˜o tamb´m se usam os comandos de E/S da linguagem. o ca e O Fortran 90/95 possui muitos comandos de E/S. Os mais utilizados s˜o: a ˆ OPEN ˆ READ ˆ WRITE ˆ PRINT ˆ CLOSE ˆ REWIND ˆ BACKSPACE estes comandos est˜o todos embutidos dentro da linguagem a qual possui, adicionalmente, recursos de a formata¸˜o que instruem a maneira como os dados s˜o lidos ou escritos. ca a At´ este ponto, todos os exemplos abordados executaram opera¸˜es de E/S de dados com teclado (ene co trada) e terminal (sa´ ıda). Adicionalmente, Fortran 90/95 permite que diversos outros objetos, como arquivos de dados, estejam conectados a um programa para leitura e/ou escrita. Neste cap´ ıtulo, ser˜o abordados os a processos de E/S em arquivos de dados, por ser este o uso mais freq¨ente deste recurso. Outros tipos de u usos incluem sa´ direta de dados em impressoras, plotters, programas gr´ficos, recursos de multimeios, ıda a etc. Devido ` variedade de usos dos comandos de E/S, ´ interessante que se fa¸a inicialmente uma introdu¸˜o a e c ca simples ao assunto, abordando os usos mais freq¨entes dos processos com arquivos externos, para posterioru mente entrar-se em maiores detalhes. Com este intuito, a se¸˜o 9.1 cont´m esta introdu¸˜o r´pida, ao passo ca e ca a que as se¸˜es posteriores (9.3 – 9.11) abordam o assunto de uma forma bem mais abrangente. co 9.1 Comandos de Entrada/Sa´ ıda: introdu¸˜o r´pida ca a Na se¸˜o 2.3 na p´gina 11 j´ foram apresentadas a entrada (teclado) e a sa´ (tela do monitor) padr˜es ca a a ıda o do Fortran. Usado desta forma, o recurso ´ demasiado limitado. O programador possui controle muito e restrito, por exemplo, sobre onde, na tela, o resultado deve ser apresentado e sobre o n´mero de casas u decimais que deve ser utilizado para representar o valor. Adicionalmente, o programador est´ limitado ao a teclado para o fornecimento de parˆmetros ao programa. a Um uso mais desej´vel dos recursos de E/S do Fortran consiste na habilidade de ler e gravar dados, por a exemplo, em arquivos residentes no disco r´ ıgido do computador ou em outra m´ ıdia ` qual o mesmo tem a 121
  • 130.
    122 9.1. Comandos deEntrada/Sa´ ıda: introdu¸˜o r´pida ca a acesso. Nesta se¸˜o, o acesso de E/S a arquivos ser´ brevemente discutido na forma de tarefas atribu´ ca a ıdas ao programador. Tarefa 1. Sa´ formatada na tela do monitor ıda Considera-se inicialmente o seguinte programa que realiza sa´ no formato livre na tela: ıda program F out i m p l i c i t none integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 ) r e a l ( dp ) : : a , b , c a= 1 . 0 dp / 7 . 0 dp b= s q r t ( 2 . 0 dp ) c= 4 * atan ( 1 . 0 dp ) print * , a , b , c end program F out Os resultados deste programa s˜o apresentados da seguinte maneira na tela do monitor: a 0.142857142857143 1.41421356237310 3.14159265358979 Observa-se que h´ um n´mero grande de espa¸os em branco antes e entre os valores dos resultados e todos a u c s˜o apresentados com o n´mero total de d´ a u ıgitos represent´veis para uma vari´vel real de dupla precis˜o. a a a O programa a seguir apresenta os mesmos resultados, por´m de maneiras mais organizadas: e program F o u t f o r m a t a d o i m p l i c i t none integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 ) r e a l ( dp ) : : a , b , c a= 1 . 0 dp / 7 . 0 dp b= s q r t ( 2 . 0 dp ) c= 4 * atan ( 1 . 0 dp ) print ”( f 7 . 5 , 1 x , f 9 . 7 , 1 x , f 1 1 . 9 ) ” , a , b , c print ”( f 7 . 7 , 1 x , f 9 . 9 , 1 x , e11 . 5 ) ” , a , b , c print ” ( ’ a= ’ , f 7 . 5 , 2 x , ’ b= ’ , f 9 . 7 , 3 x , ’ c= ’ , f 1 1 . 9 ) ” , a , b , c end program F o u t f o r m a t a d o Agora, os resultados s˜o: a 0.14286 1.4142136 3.141592654 ******* ********* 0.31416 E +01 a = 0.14286 b = 1.4142136 c = 3.141592654 Nos trˆs resultados, o segundo argumento dos comandos WRITE indica a formata¸˜o na sa´ e ca ıda, conforme determinada pelo especificador FMT=,1 o qual n˜o ´ obrigat´rio se o formato dos dados aparecer como a e o segundo elemento de um comando de E/S. A formata¸˜o dos dados de sa´ ´ determinada pela seq¨ˆncia ca ıda e ue de descritores de edi¸˜o (X, F e E), os quais tˆm os seguintes significados: ca e ˆ Os descritores 1X, 2X e 3X indicam quantos espa¸os em branco (respectivamente 1, 2 e 3) devem ser c deixados na sa´ dos dados. ıda ˆ Os descritores F e E s˜o descritores de edi¸˜o de dados e eles se aplicam ao dados na lista de vari´veis a ca a (A, B e C) na mesma ordem em que aparecem, ou seja, na sa´ 1, F7.5 determina a edi¸˜o da vari´vel ıda ca a A, F9.7 determina a adi¸˜o de B e F11.9 determina a edi¸˜o de C. ca ca ˆ O descritor F7.5 indica que a vari´vel deve ser impressa no formato de ponto flutuante, com um total a de 7 algarismos alfanum´ricos, contando o ponto decimal e o sinal (se houver), destinando 5 d´ e ıgitos para a parte fracion´ria da vari´vel A. Exemplos de n´meros de ponto flutuante v´lidos s˜o: a a u a a 5 d´ ıgitos F7.5: 0.14286 7 d´ ıgitos F9.7: -.1414214 7 caracteres 1 Discutido 9 caracteres 9 d´ ıgitos F12.9: -3.141592654 12 caracteres em detalhes na se¸˜o 9.7 na p´gina 134. ca a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 131.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 123 ˆ O descritor E11.5, que aparece na sa´ 2 determinando o formato de sa´ da vari´vel C, indica a ıda ıda a sa´ na forma de ponto flutuante com parte exponencial. O resultado impresso (0.31416E+01) possui ıda uma extens˜o total de 11 algarismos alfanum´ricos, contando o ponto decimal, o sinal (se houver), a e o s´ ımbolo da parte exponencial (E), o sinal da parte exponencial (+) e o seu valor, com duas casas decimais (01). Restam, ent˜o, somente 5 d´ a ıgitos para a parte fracion´ria. Caso a extens˜o total do a a descritor, descontado o n´mero de d´ u ıgitos na parte fracion´ria, n˜o for suficiente para imprimir a parte a a exponencial e mais o sinal, ocorre um estouro de campo, indicado pelos asteriscos nos resultados das vari´veis A e B. Exemplos v´lidos de n´meros no formato exponencial s˜o: a a u a 6 d´ ıgitos 5 d´ ıgitos E11.5: 0.31416 E+01 E13.6: -4. 430949 E-12 11 caracteres 13 caracteres ˆ Finalmente, as constantes de caractere ’A= ’, ’B= ’ e ’C= ’ que aparecem na formata¸˜o da sa´ ca ıda 3 s˜o impressas ipsis literis na sa´ padr˜o e na mesma ordem em que aparecem, relativamente a si a ıda a pr´prias e `s vari´veis. o a a Uma exposi¸ao completa de todos os descritores ´ realizada na se¸˜o 9.8 na p´gina 135. c˜ e ca a Tarefa 2. Entrada formatada a partir do teclado Entrada formatada a partir do teclado n˜o ´ uma tarefa muito pr´tica, pois uma instru¸˜o do tipo a e a ca READ(*,FMT=’(1X,F7.5,5X,F9.6,3X,F11.8)’)A, B, C iria requerer a digita¸˜o dos valores das vari´veis exatamente nas posi¸˜es assinaladas e com as extens˜es ca a co o e partes fracion´rias exatamente como determinadas pelos descritores. Por exemplo, se A= 2.6, B= -3.1 e a C= 10.8, seria necess´rio digitar a 2.60000 -3.100000 10.80000000 para preencher todos os d´ ıgitos e espa¸os determinados pelos descritores de formata¸˜o. c ca Tarefa 3. Sa´ de dados em um arquivo ıda Da mesma maneira que um programa-fonte ´ gravado em um arquivo situado no disco r´ e ıgido do computador, ´ poss´ gravar dados em arquivos a partir de um programa ou, de forma alternativa, ler dados e ıvel contidos em arquivos situados no disco. Para possibilitar acesso de E/S em um arquivo ´ necess´rio que o programador: e a ˆ Identifique o nome do arquivo, fornecendo o caminho completo, caso o arquivo resida em um diret´rio o (pasta) distinto do programa execut´vel. a ˆ Informe ao sistema sobre o tipo de acesso e uso que ser´ feito do arquivo. a ´ ˆ Associe instru¸˜es individuais de leitura ou grava¸˜o com o arquivo em uso. E poss´ existir mais de co ca ıvel um arquivo simultaneamente acess´ para E/S, al´m das interfaces j´ utilizadas (teclado e monitor). ıvel e a ˆ Quando as opera¸˜es de E/S estiverem conclu´ co ıdas, ´ necess´rio instruir ao sistema n˜o ´ mais necess´rio e a a e a acessar o(s) arquivo(s). O programa exemplo a seguir grava informa¸˜es formatadas ao arquivo EX1.DAT. A extens˜o .DAT simplesco a mente identifica o arquivo como sendo de dados. Se o arquivo n˜o existir, este ´ criado e tornado acess´ a e ıvel; se ele existe, ent˜o os dados previamente contidos nele podem ser substitu´ a ıdos por novos. program A rq Sa i i m p l i c i t none integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 ) r e a l ( dp ) : : a , b , c a= 1 . 0 dp / 7 . 0 dp b= s q r t ( 2 . 0 dp ) c= 4 * atan ( 1 . 0 dp ) open ( 1 0 , f i l e=”ex1 . dat ”) write ( 1 0 , fmt=”( f 7 . 5 , 1 x , f 9 . 7 , 1 x , f 1 1 . 9 ) ”) a , b , c close (10) end program A rq Sa i Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 132.
    124 9.1. Comandos deEntrada/Sa´ ıda: introdu¸˜o r´pida ca a Alterando os valores das vari´veis A, B e C, altera-se os valores gravados no arquivo EX1.DAT. a Os comandos-chave neste exemplo s˜o: a OPEN(10, FILE="EX1.DAT"). O comando OPEN habilita acesso ao arquivo EX1.DAT para o sistema. O arquivo est´ situado no mesmo diret´rio que o programa e este ser´ criado caso n˜o exista previamente, a o a a sendo poss´ ent˜o a grava¸˜o no mesmo, ou, caso ele j´ exista, ter´ acesso de leitura e/ou escrita. ıvel a ca a a O n´mero 11 indica a unidade l´gica que ser´ acessada. Doravante, o arquivo EX1.DAT ser´ sempre u o a a identificado pelo programa atrav´s deste n´mero. e u O modo como o acesso ao arquivo ´ feito pode ser alterado de diversas maneiras. A se¸˜o 9.4 descreve e ca todos os especificadores poss´ ıveis do comando OPEN. WRITE(10, FMT="(F7.5,1X,F9.7,1X,F11.9)") A, B, C. Este comando ´ aqui utilizado no lugar de PRINT e para realizar um processo de escrita formatada no arquivo associado ` unidade l´gica 10. A formata¸˜o a o ca ´ fornecida pela lista de descritores de formata¸˜o que seguem a palavra-chave FMT=. O papel destes e ca descritores j´ foi esclarecido. a O comando essencialmente grava os valores das vari´veis A, B e C de maneira formatada no arquivo a associado a unidade 10. ` CLOSE(10). Finalmente, este comando informa ao computador que n˜o ser´ mais necess´rio acessar o a a a arquivo associado ` unidade l´gica 10 e que tal associa¸˜o deve ser interrompida. a o ca Tarefa 4. Leitura/escrita de dados em arquivos. Vers˜o 1: n´ mero conhecido a u de linhas O programa a seguir lˆ os dados gravados no arquivo EX1.DAT, criado a partir do programa ARQ_SAI, e e usa estes dados para definir valores de outros, os quais ser˜o gravados no arquivo EX2.DAT. a program A r q S a i 2 i m p l i c i t none integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 ) r e a l ( dp ) : : a , b , c ! Dados de e n t r a d a . r e a l ( dp ) : : d , e , f ! Dados de s a i d a . open ( 1 0 , f i l e=”ex1 . dat ” , status=” o l d ”) open ( 1 1 , f i l e=”ex2 . dat ” , status=”new ”) read ( 1 0 , fmt=”( f 7 . 5 , 1 x , f 9 . 7 , 1 x , f 1 1 . 9 ) ”) a , b , c print * , ”Os v a l o r e s l i d o s foram : ” print * , ”a= ” , a print * , ”b= ” , b print * , ”c= ” , c d= a + b + c e= b ** 2 + c o s ( c ) f= s q r t ( a ** 2 + b ** 3 + c * * 5 ) write ( 1 1 , fmt=” ( 3 ( e11 . 5 , 1 x ) ) ”) d , e , f end program A r q S a i 2 No programa ARQ_SAI_2 aparecem as seguintes instru¸˜es que ainda n˜o foram discutidas: co a STATUS="OLD/NEW". Estas cl´usulas, que aparecem nos comandos OPEN, indicam o status exigido para o a arquivo a ser acessado. STATUS="OLD" indica que o arquivo deve existir no momento de acesso. Caso isto n˜o aconte¸a, ocorre uma mensagem de erro e o programa ´ interrompido. STATUS="NEW" indica a c e que o arquivo n˜o deve existir previamente e, ent˜o, deve ser criado. Novamente, se estas condi¸˜es a a co n˜o se cumprirem, o programa p´ra. a a READ(10, FMT="(F7.5,1X,F9.7,1X,F11.9)") A, B, C. Observa-se aqui o uso de uma entrada formatada com o comando READ. A formata¸˜o das vari´veis A, B e C j´ foi discutida. Deve-se enfatizar novamente ca a a que a formata¸˜o especificada pelo FMT= deve possibilitar a leitura correta dos dados no arquivo ca associado a unidade l´gica 10. ` o WRITE(11, FMT="(3(E11.5,1X))") D, E, F. O aspecto ainda n˜o abordado neste comando WRITE ´ o uso a e do contador de repeti¸˜o 3, o qual indica que as vari´veis D, E e F devem ser gravado no arquivo ca a associado a unidade 11 com a formata¸ao dada por "E11.5,1X" repetido 3 vezes consecutivas. ` c˜ Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 133.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 125 Finalmente, deve-se mencionar que os comandos CLOSE(10) e CLOSE(11) n˜o foram utilizados. Isto ´ a e permitido, uma vez que, neste caso, a associa¸˜o das unidades l´gicas aos arquivos ser´ interrompida com ca o a o final da execu¸˜o do programa. Contudo, em certas situa¸˜es ´ necess´rio associar uma unidade l´gica ca co e a o previamente empregada a um outro arquivo, o que neste caso obriga o programador a fazer uso do comando CLOSE. Modifica¸˜es posteriores no programa necessitar˜o tamb´m a elimina¸˜o do arquivo EX2.DAT, devido ` co a e ca a cl´usula STATUS="NEW". a Tarefa 5. Leitura/escrita de dados em arquivos. Vers˜o 2: n´ mero desconhecido a u de linhas Quando o n´mero de linhas no arquivo de entrada n˜o ´ previamente conhecido, ´ necess´rio um procediu a e e a mento diferente daquele adotado na Tarefa 4. O programa 9.1 ilustra dois poss´ ıveis m´todos a ser adotados, e os quais utilizam as op¸˜es IOSTAT ou END do comando READ (se¸˜o 9.5). Em ambos, aloca-se inicialmente co ca uma matriz tempor´ria com o posto adequado e com um n´mero tal de elementos que seja sempre maior a u ou igual ao n´mero m´ximo de linhas que podem estar contidas no arquivo de entrada. Ap´s a leitura u a o dos dados na matriz tempor´ria, o n´mero de linhas no arquivo tornou-se conhecido e aloca-se, ent˜o, uma a u a matriz definitiva com o n´mero correto de elementos. O segundo exemplo faz uso de um r´tulo (se¸˜o u o ca 5.1.1), que embora n˜o seja um procedimento recomendado em Fortran 90/95, ´ completamente equivalente a e ao primeiro exemplo. Existem maneiras mais inteligentes de realizar esta tarefa, sem que seja necess´rio definir-se uma matriz a tempor´ria. Por´m, estas maneiras envolvem o uso de ponteiros e listas encadeadas (linked lists) os quais a e constituem recursos mais avan¸ados e que n˜o foram ainda abordados nesta apostila. c a Os exemplos abordados nas Tarefas 1 — 5 constituem um conjunto pequeno, por´m freq¨ente, de usos e u dos comando de E/S. A descri¸˜o completa destes recursos pode ser obtida nas se¸˜es 9.3—9.11 posteriores. ca co 9.2 Declara¸˜o NAMELIST ca Em certas situa¸˜es, quando h´ por exemplo um n´mero grande de parˆmetros sendo transferidos em co a u a processos de E/S, pode ser util definir-se uma lista rotulada de valores destinados ` transferˆncia. O Fortran ´ a e 90 introduziu, com este fim, a declara¸˜o NAMELIST, que define um ou mais grupos de vari´veis referenciadas ca a com o mesmo nome. Esta declara¸˜o ´ empregada em conjunto com opera¸˜es de E/S executadas por ca e co comandos READ e WRITE. A forma geral da declara¸˜o, que pode aparecer em qualquer unidade de programa, ´: ca e NAMELIST /<nome-grupo-namelist>/ <lista-nomes-vari´veis> & a [[,] /<nome-grupo-namelist>/ <lista-nomes-vari´veis> [,] ...] a Como se pode notar, ´ poss´ definir-se mais de um grupo NAMELIST na mesma declara¸˜o. O primeiro e ıvel ca campo substitu´ ıvel: <nome-grupo-namelist> , ´ o nome do grupo para uso subseq¨ente nos comandos e u de E/S. A <lista-nomes-vari´veis> , como o nome indica, lista os nomes das vari´veis que comp˜e o a a o grupo. N˜o podem constar desta lista nomes de matrizes mudas de forma assumida, ou objetos autom´ticos, a a vari´veis de caractere de extens˜o vari´vel, matrizes aloc´veis, pointers, ou ser um componente de qualquer a a a a profundidade de uma estrutura que seja um ponteiro ou que seja inacess´ ıvel. Um exemplo v´lido de <listaa nomes-vari´veis> ´: a e REAL :: TV, CARPETE REAL, DIMENSION(10) :: CADEIRAS ... NAMELIST /ITENS_DOMESTICOS/ CARPETE, TV, CADEIRAS Outro exemplo v´lido: a NAMELIST /LISTA1/ A, B, C /LISTA2/ X, Y, Z ´ E poss´ ıvel tamb´m continuar a mesma <lista-nomes-vari´veis> de um dado grupo em mais de uma e a declara¸˜o contidas no campo de declara¸˜es da unidade de programa. Assim, ca co NAMELIST /LISTA/ A, B, C NAMELIST /LISTA/ D, E, F Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 134.
    126 9.2. Declara¸˜o NAMELIST ca Programa9.1: Programa que ilustra leitura de arquivo com n´mero desconhecido de linhas. u ! **************************** PROGRAMA ARQ SAI 3 ****************************** ! Le um a r q u i v o de dados com um numero c o n h e c i d o de e l e m e n t o s por l i n h a , ! mas com um numero d e s c o n h e c i d o de l i n h a s no formato l i v r e , usando ! matrizes temporarias . ! A l e i t u r a do a r q u i v o e r e a l i z a d a de 2 maneiras d i s t i n t a s : ! 1 . Usando a opcao IOSTAT . ! 2 . Usando a opcao END. ! O programa e n t a o imprime na t e l a os dados e o numero de l i n h a s l i d o . ! ! Autor : Rudi G a e l z e r ! Data : Maio /2008 ! program A r q S a i 3 i m p l i c i t none integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 ) integer : : c o n t r o l e , i , npt1= 0 , npt2= 0 character ( len= 1 ) : : c h a r r e a l ( kind=dp ) , dimension ( : , : ) , a l l o c a t a b l e : : temp1 , temp2 , matriz1 , m a t r i z 2 a l l o c a t e ( temp1 ( 2 , 1 0 0 0 ) , temp2 ( 2 , 1 0 0 0 ) ) ! Aloca m a t r i z e s t e m p o r a r i a s . ! Estima um l i m i t e s u p e r i o r no numero ! de l i n h a s . ! Metodo 1 : usando opcao IOSTAT . open ( 1 0 , f i l e =’ ex3 . dat ’ , status =’ old ’ ) do read ( 1 0 , * , i o s t a t= c o n t r o l e ) temp1 ( 1 , npt1 +1) , temp1 ( 2 , npt1 +1) i f ( c o n t r o l e < 0 ) e xi t ! F i n a l de a r q u i v o d e t e c t a d o . npt1= npt1 + 1 end do close (10) a l l o c a t e ( m a t r i z 1 ( 2 , npt1 ) ) m a t r i z 1= temp1 ( : , : npt1 ) write ( * , fmt=” ( ’ Matriz 1 l i d a : ’ , / ) ”) print ’ ( 2 ( e10 . 3 , 1 x ) ) ’ , ( m a t r i z 1 ( : , i ) , i= 1 , npt1 ) deallocate ( temp1 ) ! L i b e r a e s p a c o de memoria ocupado por ! temp1 . print ’ ( / , a ) ’ , ’ P r e s s i o n e ENTER/R T R para c o n t i n u a r . ’ EU N read ( * , ’ ( a ) ’ ) c h a r ! Metodo 2 : usando opcao END. open ( 1 0 , f i l e =’ ex3 . dat ’ , status =’ old ’ ) do read ( 1 0 , * , end= 1 0 0 ) temp2 ( 1 , npt2 +1) , temp2 ( 2 , npt2 +1) npt2= npt2 + 1 end do 100 continue ! Linha i d e n t i f i c a d a com o r o t u l o 1 0 0 . close (10) a l l o c a t e ( m a t r i z 2 ( 2 , npt2 ) ) m a t r i z 2= temp2 ( : , : npt2 ) print ’ ( ”Matriz 2 l i d a : ” , / ) ’ print ’ ( 2 ( e10 . 3 , 1 x ) ) ’ , ( m a t r i z 2 ( : , i ) , i= 1 , npt1 ) deallocate ( temp2 ) ! L i b e r a e s p a c o de memoria ocupado por ! temp2 . print ’ ( / , ”O numero t o t a l de l i n h a s l i d a s e ’ ’ : ” , / , & ”Matriz 1 : ” , i 4 , 3x , ”Matriz 2 : ” , i 4 ) ’ , npt1 , npt2 end program A r q S a i 3 Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 135.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 127 ´ equivalente a uma unica declara¸˜o NAMELIST com os 6 nomes de vari´veis listados na mesma ordem acima. e ´ ca a Al´m disso, um objeto de um grupo NAMELIST pode tamb´m pertencer a outros grupos. e e Se o tipo, parˆmetro de tipo ou forma de uma vari´vel de um grupo ´ especificado em uma declara¸˜o a a e ca na mesma unidade de programa , esta declara¸˜o deve constar antes da declara¸˜o NAMELIST, ou ser uma ca ca declara¸˜o de tipo impl´ ca ıcito que regule o tipo e esp´cie das vari´veis que iniciam com aquele caractere e a explicitado na declara¸˜o. ca Um grupo namelist pode possuir o atributo p´blico ou privado, concedido atrav´s das declara¸˜es PUBLIC u e co ou PRIVATE. Contudo, se o grupo possuir o atributo p´blico, nenhum membro seu pode ser declarado com u o atributo privado ou possuir componentes privados. Para se executar uma opera¸˜o de E/S em algum registro (como um arquivo, por exemplo) que contenha ca um ou mais grupos namelist, o registro sempre ir´ iniciar com o caractere &, seguido, sem espa¸o, pelo a c <nome-grupo-namelist>, vindo ent˜o a lista dos nomes das vari´veis, sendo cada nome seguido por sinais de a a igual e, ent˜o pelo valor da vari´vel, podendo ser precedido ou seguido por espa¸os em branco. Constantes a a c de caractere devem ser sempre delimitadas em registros de entrada. A lista de nomes e valores de um determinado grupo ´ sempre encerrada com o caractere / inserido fora de uma constante de caractere. e Os comandos READ e WRITE, ao serem empregados em conjunto com um namelist, n˜o possuem uma lista a expl´ ıcita de vari´veis ou constantes a ser transferidas, mas sim o nome do grupo NAMELIST como segundo a parˆmetro posicional ou com o especificador NML= contendo o nome do grupo, no lugar do especificador a FMT=. Um exemplo de registro de entrada ´: e INTEGER :: NO_DE_OVOS, LITROS_DE_LEITE, QUILOS_DE_ARROZ NAMELIST /FOME/ NO_DE_OVOS, LITROS_DE_LEITE, QUILOS_DE_ARROZ READ(5, NML=FOME) O associado exemplo de registro (arquivo) de entrada ´: e &FOME LITROS_DE_LEITE= 5, NO_DE_OVOS= 12 / Nota-se no registro acima que a ordem de atribui¸˜o de valores aos nomes n˜o ´ necessariamente a mesma ca a e da declara¸˜o NAMELIST. Al´m disso, a vari´vel QUILOS_DE_ARROZ n˜o tem seu valor atribu´ no registro. ca e a a ıdo Quando isso acontece com uma ou mais vari´veis da lista o valor destas permanece inalterado. a Os valores de uma matriz podem ser atribu´ ıdos atrav´s do nome da mesma seguida por = e a lista de e constantes que ser˜o atribu´ a ıdos aos elementos da matriz de acordo com o ordenamento padr˜o da linguagem, a descrito na se¸˜o 6.6.2. Se a vari´vel for de tipo derivado, a lista de valores deve tamb´m seguir a ordem ca a e ´ e o tipo e esp´cie dos componentes constantes da declara¸˜o do tipo. E poss´ tamb´m definir-se o valor e ca ıvel e de um elemento isolado ou de uma se¸˜o de matriz, ou qualquer sub-objeto, sem alterar os valores dos ca demais elementos, usando um designador de sub-objeto, tal como um tripleto de subscritos. Neste caso, os elementos do tripleto devem todos ser constantes inteiras escalares, sem parˆmetros de esp´cie de tipo a e Na grava¸˜o (sa´ ca ıda) do registro, todos os componentes do grupo s˜o escritos no arquivo especificado, a precedidos por & e o nome do grupo, na mesma ordem da declara¸˜o da <lista-nomes-vari´veis> , com os ca a nomes explicitamente escritos em letras mai´sculas. O registro ´ finalizado com o caractere /. Um exemplo u e de sa´ de um namelist ´: ıda e INTEGER :: NUMERO, I INTEGER, DIMENSION(10) :: LISTA= (/ 14, (0, I= 1,9) /) NAMELIST /SAI/ NUMERO, LISTA WRITE(6, NML=SAI) o qual produz o seguinte registro no arquivo associado ` unidade l´gica 6: a o &SAI NUMERO=1 , LISTA=14, 9*0 / Nota-se que os 9 elementos 0 do vetor LISTA s˜o registrados usando-se a nota¸˜o compacta 9*0. Esta a ca nota¸˜o tamb´m ´ v´lida em registros de entrada. ca e e a Em um processo de leitura de registros (usando o comando READ, por exemplo), n˜o ´ permitida a mistura a e de registros em um NAMELIST com registros que n˜o pertencem a nenhum grupo, como em uma entrada a formatada ou n˜o-formatada. Contudo, em um processo de sa´ de registros (comando WRITE), pode-se a ıda misturar os tipos de registros. Todos os nomes de grupos, nomes de objetos e nomes de componentes s˜o interpretados sem considerar o a caso de capitaliza¸˜o. A lista de valores n˜o pode ter um n´mero excedente de ´ ca a u ıtens, mas ela pode conter um n´mero inferior, como j´ foi mencionado. Se o objeto ´ do tipo caractere e o valor tiver uma extens˜o menor u a e a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 136.
    128 9.2. Declara¸˜o NAMELIST ca quea declarada, espa¸os em branco preenchem o restante do campo. Matrizes ou objetos de tamanho zero c (se¸˜o 6.5) n˜o podem constar no registro de entrada de um NAMELIST. Se ocorrer uma m´ltipla atribui¸˜o ca a u ca de um mesmo objeto, o ultimo valor ´ assumido. ´ e Por fim, coment´rios podem ser inclu´ a ıdos no registro de entrada em seguida a um nome a uma v´ ırgula que separa os nomes. O coment´rio ´ introduzido, como ´ costumeiro a partir do caractere !. Uma linha a e e de coment´rio, iniciada com o caractere !, tamb´m ´ permitida, desde que esta n˜o ocorra em um contexto a e e a de uma constante de caractere. O programa Testa_NAMELIST abaixo ilustra praticamente todos os recursos discutidos nesta se¸˜o a ca respeito de listas NAMELIST. program Testa NAMELIST i m p l i c i t none integer , parameter : : dp= SELECTED REAL KIND( 1 5 , 3 0 0 ) integer : : n o d e o v o s , l i t r o s d e l e i t e , q u i l o s d e a r r o z= 1 2 , numero ! Note que q u i l o s d e a r r o z f o i i n i c i a l i z a d o . integer , dimension ( 1 0 ) : : l i s t a i n t 1 , l i s t a i n t 2 real , dimension ( 1 0 ) : : a l e a t , v e t t e s= 1 . 0 r e a l ( dp ) : : pi , e e u l e r , m e l e c t r o n , c vacuum logical : : tes character ( len= 1 0 ) : : nome namelist / fome / nome , n o d e o v o s , l i t r o s d e l e i t e , q u i l o s d e a r r o z namelist / s a i / numero , l i s t a i n t 1 , l i s t a i n t 2 , v e t t e s namelist / c t e s / t e s , pi , e e u l e r , m e l e c t r o n , c vacuum ! open ( 1 0 , f i l e= ”Dados . e n t ” , status= ” o l d ”) open ( 1 1 , f i l e= ”Dados . dat ”) read ( 1 0 , nml= fome ) read ( 1 0 , nml= s a i ) read ( 1 0 , nml= c t e s ) ! Mostra na t e l a os v a l o r e s l i d o s . print ’ ( a ) ’ , ” L i s t a / fome / l i d a : ” write ( * , nml= fome ) print ’ ( / a ) ’ , ” L i s t a / s a i / l i d a : ” write ( * , nml= s a i ) print ’ ( / a ) ’ , ” L i s t a / c t e s / l i d a : ” write ( * , nml= c t e s ) print ’ ( / a ) ’ , ”Para c o n f i r m a r : ” print ’ ( ”Vetor v e t t e s : ” , 1 0 ( f 4 . 2 , x ) ) ’ , v e t t e s print ’ ( / , ” l i s t a 1 : ” , 1 0 i 3 ) ’ , l i s t a i n t 1 print ’ ( / , ” l i s t a 2 : ” , 1 0 i 3 ) ’ , l i s t a i n t 2 ! A l t e r a a l g u n s v a l o r e s e g r a v a as l i s t a s no a r q u i v o . c a l l random number ( a l e a t ) print ’ ( / , ” L i s t a de No . a l e a t o r i o s : ” , / , 1 0 ( f 7 . 5 , x ) ) ’ , a l e a t l i s t a i n t 1= l i s t a i n t 2 ** 2 l i s t a i n t 2= a l e a t * l i s t a i n t 2 write ( 1 1 , nml= s a i ) write ( 1 1 , nml= c t e s ) write ( 1 1 , nml= fome ) ! V e r i f i q u e Dados . d a t . end program Testa NAMELIST Um exemplo de arquivo de entrada Dados.ent que pode ser fornecido ao programa Testa_NAMELIST ´ e o seguinte: &fome l i t r o s d e l e i t e= 10 , n o d e o v o s= 2 4 , nome= ”Rancho ” / &s a i Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 137.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 129 numero= 5 0 , l i s t a i n t 1= 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 1 0 , l i s t a i n t 2= 3 * 1 , 3 * 5 , 4 * 8 , v e t t e s (4:8)= 5*2.0 / &c t e s t e s= . t r u e . , PI= 3.14159265358979323846264338327950288419717 , e e u l e r= 2 . 7 1 8 2 8 1 8 2 8 4 5 9 0 4 5 2 3 5 3 6 0 2 8 7 4 7 1 3 5 2 6 6 2 4 9 7 7 5 7 2 5 , ! Euler ’ s number . m e l e c t r o n= 9 . 1 0 9 3 8 2 1 5 e −28 , ! E l e c t r o n r e s t mass ( g ) . c vacuum= 2 . 9 9 7 9 2 4 5 8 e10 ! Speed o f l i g h t i n vacuum (cm/ s ) . / 9.3 Unidades l´gicas o Em Fortran, um arquivo est´ conectado a uma unidade l´gica denotada por um n´mero inteiro. Este a o u n´mero deve ser positivo e est´ freq¨entemente limitado entre 1 e 100, dependendo do compilador. Cada u a u unidade l´gica possui muitas propriedades. Por exemplo, o FILE. O nome do arquivo conectado ` unidade. O nome ´ especificado pelo comando OPEN. a e ACTION. Especifica o tipo de a¸˜o que pode ser executada sobre o arquivo. Estas compreendem leitura, ca escrita ou ambas. Se um arquivo ´ aberto para um tipo de a¸˜o e outro tipo ´ tentado, uma mensagem e ca e de erro ser´ gerada. Por exemplo, n˜o ´ permitida escrita sobre um arquivo aberto somente para a a e leitura. STATUS. Estabelece o status de um arquivo. Estes s˜o: velho (old), novo (new) substitui¸˜o (replace), entre a ca outros. Caso um arquivo tente ser acessado com um status incorreto, uma mensagem de erro ´ gerada. e ACCESS. Forma de acesso a um arquivo: direto ou seq¨encial. Alguns arquivos pode ser acessados por u ambos os m´todos, como ´ o caso de arquivos em discos remov´ e e ıveis ou discos r´ ıgidos. J´ outras m´ a ıdias permite acesso somente seq¨encial, como ´ o caso de uma fita magn´tica. u e e ´ Sequencial. E o acesso usual. Os processos de leitura/escrita principiam no in´ ıcio do arquivo e ¨ seguem, linha a linha, at´ o seu final. e Direto. Cada linha ´ acessada por um n´mero, denominado n´mero de grava¸˜o (record number) o e u u ca qual deve ser especificado no comando de leitura/escrita. O n´mero m´ximo de arquivos que podem ser abertos simultaneamente para E/S tamb´m ´ especificado u a e e pelo manual do compilador. 9.4 Comando OPEN O comando OPEN ´ usado para conectar um dado arquivo a uma unidade l´gica. Freq¨entemente ´ e o u e poss´ pr´-conectar um arquivo antes que o programa comece a rodar; neste caso, n˜o ´ necess´rio usarıvel e a e a se o comando OPEN. Contudo, isto depende de conhecimento pr´vio a respeito dos n´meros-padr˜o das e u a unidades l´gicas para E/S, o que geralmente depende do processador e dos sistema operacional em uso. o Para sistemas linux, as unidades pr´-conectadas s˜o, usualmente: e a Uso Mensagens de erro Entrada padr˜o a Sa´ padr˜o ıda a Designa¸˜o ca stderr stdin stdout N´ mero da unidade l´gica u o 0 5 6 Sempre que poss´ ıvel, ´ recomendado evitar-se o uso de unidade pr´-conectadas, o que torna o programa e e mais port´vel. a A sintaxe do comando ´: e OPEN([UNIT=] <int-exp> [,<op-list>]) Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 138.
    130 9.4. Comando OPEN onde<int-exp> ´ uma express˜o escalar inteira que especifica o n´mero da unidade l´gica externa e <ope a u o list> ´ uma lista de especificadores opcional, formada por um conjunto de palavras-chave. Se a palavrae chave “UNIT=” for inclu´ ıda, ela pode aparecer em qualquer posi¸˜o no campo de argumentos do comando ca OPEN. Um especificador n˜o pode aparecer mais de uma vez. Nos especificadores, todas as entidades s˜o a a escalares e todos os caracteres s˜o da esp´cie padr˜o. Em express˜es de caractere, todos os brancos precea e a o dentes s˜o ignorados e, exceto no caso do especificador “FILE=”, quaisquer letras mai´sculas s˜o convertidas a u a a `s correspondentes letras min´sculas. Os especificadores s˜o: u a FILE= <fln>, onde <fln> ´ uma express˜o de caractere que fornece o nome do arquivo. O nome deve e a coincidir exatamente com o arquivo, inclusive com o caminho, caso o arquivo esteja em um diret´rio o distinto do diret´rio de trabalho. Se este especificador ´ omitido e a unidade n˜o ´ conectada a uma o e a e arquivo, o especificador “STATUS=” deve ser especificado com o valor SCRATCH e o arquivo conectado ` a unidade ir´ depender do sistema. a IOSTAT= <ios>, onde <ios> ´ uma vari´vel inteira padr˜o que ´ fixada a zero se o comando executou e a a e corretamente e a um valor positivo em caso contr´rio. a ERR= <r´tulo-erro>, onde <r´tulo-erro> ´ o r´tulo de um comando na mesma unidade de ˆmbito, para o o e o a o qual o controle do fluxo ser´ transferido caso ocorra algum erro na execu¸˜o do comando OPEN. a ca STATUS= <status>, onde <status> ´ uma express˜o de caracteres que fornece o status do arquivo. O e a status pode ser um dos seguintes: ’OLD’– Arquivo deve existir. ’NEW’– Arquivo n˜o deve existir. O arquivo ser´ criado pelo comando OPEN. A partir deste momento, a a o seu status se torna ’OLD’. ’REPLACE’– Se o arquivo n˜o existe, ele ser´ criado. Se o arquivo j´ existe, este ser´ eliminado e um a a a a novo arquivo ´ criado com o mesmo nome. Em ambos os casos, o status ´ ent˜o alterado para e e a ’OLD’. ’SCRATCH’– O arquivo ´ tempor´rio e ser´ deletado quando este for fechado com o comando CLOSE e a a ou na sa´ da unidade de programa. ıda ’UNKNOWN’– Status do arquivo desconhecido; depende do sistema. Este ´ o valor padr˜o do especifie a cador, caso este seja omitido. O especificador “FILE=” deve estar presente se ’NEW’ ou ’REPLACE’ s˜o especificados ou se ’OLD’ ´ a e especificado e a unidade n˜o est´ conectada. a a ACCESS= <acc>, onde <acc> ´ uma express˜o de caracteres que fornece o valor ’SEQUENTIAL’ ou ’DIRECT’. e a Para um arquivo que j´ exista, este valor deve ser uma op¸˜o v´lida. Se o arquivo ainda n˜o existe, ele a ca a a ser´ criado com o m´todo de acesso apropriado. Se o especificador ´ omitido, o valor ’SEQUENTIAL’ ´ a e e e assumido. O significado das especifica¸˜es ´: co e ’DIRECT’– O arquivo consiste em registros acessados por um n´mero de identifica¸˜o. Neste caso, o u ca tamanho do registro deve ser especificado por “RECL=”. Registros individuais podem ser especificados e atualizados sem alterar o restante do arquivo. ’SEQUENTIAL’– O arquivo ´ escrito/lido seq¨encialmente, linha a linha. e u FORM= <fm>, onde <fm> ´ uma express˜o de caracteres que fornece os valores ’FORMATTED’ ou ’UNFORMATe a TED’, determinando se o arquivo deve ser conectado para E/S formatada ou n˜o formatada. Para a um arquivo que j´ exista, o valor deve ser uma op¸˜o v´lida. Se o arquivo ainda n˜o existe, ele ser´ a ca a a a criado com um conjunto de forma que incluem o forma especificada. Se o especificador ´ omitido, os e valores-padr˜o s˜o: a a ’FORMATTED’– Para acesso seq¨encial. u ’UNFORMATTED’– Para conex˜o de acesso direto. a RECL= <rl>, onde <rl> ´ uma express˜o inteira cujo valor deve ser positivo. e a ˆ Para arquivo de acesso direto, a op¸˜o especifica o tamanho dos registros e ´ obrigat´rio. ca e o ˆ Para arquivo seq¨encial, a op¸˜o especifica o tamanho m´ximo de um registro, e ´ opcional com u ca a e um valor padr˜o que depende do processador. a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 139.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 131 – Para arquivos formatados, o tamanho ´ o n´mero de caracteres para registros que contenham e u somente caracteres-padr˜o. a – Para arquivos n˜o formatados, o tamanho depende do sistema, mas o comando INQUIRE a (se¸˜o 9.10) pode ser usado para encontrar o tamanho de uma lista de E/S. ca Em qualquer situa¸˜o, para um arquivo que j´ exista, o valor especificado deve ser permitido para ca a o arquivo. Se o arquivo ainda n˜o existe, ele ´ criado com um conjunto permitido de tamanhos de a e registros que incluem o valor especificado. BLANK= <bl>, onde <bl> ´ uma express˜o de caracteres que fornece os valores ’NULL’ ou ’ZERO’. A e a conex˜o deve ser com E/S formatada. Este especificador determina o padr˜o para a interpreta¸˜o de a a ca brancos em campos de entrada num´ricos. e ’NULL’– Os brancos s˜o ignorados, exceto que se o campo for completamente em branco, ele ´ intera e pretado como zero. ’ZERO’– Os brancos s˜o interpretados como zeros. a Se o especificados ´ omitido, o valor padr˜o ´ ’NULL’. e a e POSITION= <pos>, onde <pos> ´ uma express˜o de caracteres que fornece os valores ’ASIS’, ’REWIND’ ou e a ’APPEND’. O m´todo de acesso deve ser seq¨encial e se o especificador ´ omitido, o valor padr˜o ´ e u e a e ’ASIS’. Um arquivo novo ´ sempre posicionado no seu in´ e ıcio. Para um arquivo que j´ existe e que j´ a a est´ conectado: a ’ASIS’– O arquivo ´ aberto sem alterar a posi¸˜o corrente de leitura/escrita no seu interior. e ca ’REWIND’– O arquivo ´ posicionado no seu ponto inicial. e ’APPEND’– O arquivo ´ posicionado logo ap´s o registro de final de arquivo, possibilitando a inclus˜o e o a de dados novos. Para um arquivo que j´ existe mas que n˜o est´ conectado, o efeito da especifica¸˜o ’ASIS’ no a a a ca posicionamento do arquivo ´ indeterminado. e ACTION= <act>, onde <act> ´ uma express˜o de caracteres que fornece os valores ’READ’, ’WRITE’ ou e a ’READWRITE’. ’READ’– Se esta especifica¸˜o ´ escolhida, os comandos WRITE, PRINT e ENDFILE n˜o devem ser usados ca e a para esta conex˜o. a ’WRITE’– Se esta especifica¸˜o ´ escolhida, o comando READ n˜o pode ser usado. ca e a ’READWRITE’– Se esta especifica¸˜o ´ escolhida, n˜o h´ restri¸˜o. ca e a a ca Se o especificador ´ omitido, o valor padr˜o depende do processador. e a DELIM= <del>, onde <del> ´ uma express˜o de caracteres que fornece os valores ’APOSTROPHE’, ’QUOTE’ e a ou ’NONE’. Se ’APOSTROPHE’ ou ’QUOTE’ s˜o especificados, o caractere correspondente ser´ usado a a para delimitar constantes de caractere escritos com formata¸˜o de lista ou com o uso da declara¸˜o ca ca NAMELIST, e ser´ duplicado onde ele aparecer dentro de tal constante de caractere. Al´m disso, caraca e teres fora do padr˜o ser˜o precedidos por valores da esp´cie. Nenhum caractere delimitador ser´ usado a a e a e nenhuma duplica¸˜o ser´ feita se a especifica¸˜o for ’NONE’. A especifica¸˜o ’NONE’ ´ o valor padr˜o ca a ca ca e a se este especificador for omitido. O especificador somente pode aparecer em arquivos formatados. PAD= <pad>, onde <pad> ´ uma express˜o de caracteres que fornece os valores ’YES’ ou ’NO’. e a ’YES’– Um registro de entrada formatado ser´ considerado preenchido por brancos sempre que uma a lista de entrada e a formata¸˜o associada especificarem mais dados que aqueles que s˜o lidos no ca a registro. ’NO’– Neste caso, o tamanho do registro de entrada deve ser n˜o menor que aquele especificado pela a lista de entrada e pela formata¸˜o associada, exceto na presen¸a de um especificador ADVANCE= ca c ’NO’ e uma das especifica¸˜es “EOR=” ou “IOSTAT=”. co O valor padr˜o se o especificador ´ omitido ´ ’YES’. Para caracteres n˜o padronizados, o caractere de a e e a branco que preenche o espa¸o restante depende do processador. c Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 140.
    132 9.5. Comando READ Aseguir, temos um exemplo do uso deste comando: OPEN(17, FILE= ’SAIDA.DAT’, ERR= 10, STATUS= ’REPLACE’, & ACCESS= ’SEQUENTIAL’, ACTION= ’WRITE’) Neste exemplo, um arquivo SAIDA.DAT ´ aberto para escrita, ´ conectado ao n´mero de unidade l´gica 17, e e u o o arquivo ´ acessado linha a linha e ele j´ existe mas deve ser substitu´ e a ıdo. O r´tulo 10 deve pertencer a um o comando execut´vel v´lido. a a OPEN(14, FILE= ’ENTRADA.DAT’, ERR= 10, STATUS= ’OLD’, RECL=IEXP, ACCESS= ’DIRECT’, ACTION= ’READ’) & Aqui, o arquivo ENTRADA.DAT ´ aberto somente para leitura na unidade 14. O arquivo ´ diretamente acessado e e e deve ser um arquivo previamente existente. 9.5 Comando READ Este ´ o comando que executa a leitura formatada de dados. At´ agora, o comando foi utilizado para e e leitura na entrada padr˜o, que usualmente ´ o teclado: a e READ*, <lista> onde o asterisco “*” indica a entrada padr˜o e <lista> ´ a lista de vari´veis cujo valor ´ lido do teclado. a e a e Este comando ser´ agora generalizado para uma forma com ou sem unidade l´gica. Sem o n´mero de a o u unidade l´gica o comando fica: o READ <format> [,<lista>] e com o n´mero de unidade fica: u READ([UNIT=]<u>, [FMT=] <format>[, IOSTAT= <ios>] & [, ERR= <err-label>][, END= <end-label>] & [, EOR= <eor-label>][, ADVANCE= <mode>] & [, REC= <int-exp>][, SIZE= <size>][, NML= <grp>]) <lista> Os argumentos do comando s˜o os seguintes: a UNIT= <u>, onde <u> ´ um n´mero de unidade l´gica v´lido ou “*” para a entrada padr˜o. Caso esta e u o a a especifica¸˜o seja o primeiro argumento do comando, a palavra-chave ´ opcional. ca e FMT= <format>, onde <format> ´ uma string de caracteres formatadores, um r´tulo v´lido em Fortran ou e o a “*” para formato livre. Caso esta especifica¸˜o seja o segundo argumento do comando, a palavra-chave ca ´ opcional. e IOSTAT= <ios>, onde <ios> ´ uma vari´vel inteira padr˜o que armazena o status do processo de leitura. e a a Os valores poss´ ıveis s˜o: a <ios> = 0, quando o comando ´ executado sem erros. e <ios> > 0, quando ocorre um erro na execu¸˜o do comando. ca <ios> < 0, quando uma condi¸˜o de final de registro ´ detectada em entrada sem avan¸o ou quando ca e c uma condi¸˜o de final de arquivo ´ detectada. ca e ERR= <err-label>, ´ um r´tulo v´lido para onde o controle de fluxo ´ transferido quando ocorre um erro e o a e de leitura. END= <end-label>, ´ um r´tulo v´lido para onde o controle de fluxo ´ transferido se uma condi¸˜o de final e o a e ca de arquivo ´ encontrada. Esta op¸˜o somente existe no comando READ com acesso seq¨encial. e ca u EOR= <eor-label>, ´ um r´tulo v´lido para onde o controle de fluxo ´ transferido se uma condi¸˜o de e o a e ca final de registro ´ encontrada. Esta op¸˜o somente existe no comando READ com acesso seq¨encial e e ca u formatado e somente se a especifica¸˜o ADVANCE= ’NO’ tamb´m estiver presente. ca e Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 141.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 133 ADVANCE= <mode>, onde <mode> possui dois valores: ’YES’ ou ’NO’. A op¸˜o ’NO’ especifica que cada ca comando READ inicia um novo registro na mesma posi¸˜o; isto ´, implementa entrada de dados sem ca e avan¸o (non-advancing I/O). A op¸˜o padr˜o ´ ’YES’, isto ´ a cada leitura o arquivo ´ avan¸ado c ca a e e e c em uma posi¸˜o. Se a entrada sem avan¸o ´ usada, ent˜o o arquivo deve estar conectado para acesso ca c e a seq¨encial e o formato deve ser expl´ u ıcito. REC= <int-exp>, onde <int-exp> ´ uma express˜o inteira escalar cujo valor ´ o n´mero de ´ e a e u ındice do registro lido durante acesso direto. Se REC estiver presente, os especificadores END e NML e o formato livre “*” n˜o podem ser tamb´m usados. a e SIZE= <size>, onde <size> ´ uma vari´vel escalar inteira padr˜o, a qual guarda o n´mero de caracteres e a a u lidos. Este especificador somente existe no comando READ e somente se a especifica¸˜o ADVANCE= ’NO’ ca tamb´m estiver presente. e NML= <grp>, onde <grp> ´ o nome de um grupo NAMELIST previamente definido em uma declara¸˜o NAMEe ca LIST. O nome <grp> n˜o ´ uma constante de caracteres e sim um nome v´lido em Fortran2 . a e a Dado o seguinte exemplo: READ(14, FMT= ’(3(F10.7,1X))’, REC=IEXP) A, B, C este comando especifica que o registro identificado pela vari´vel inteira IEXP seja lido na unidade 14. O a registro deve ser composto por 3 n´meros reais designados pelos descritores F10.7, separados por um espa¸o u c em branco. Estes 3 n´meros ser˜o atribu´ u a ıdos `s vari´veis A, B e C. Outro exemplo: a a READ(*, ’(A)’, ADVANCE= ’NO’, EOR= 12, SIZE= NCH) STR especifica que a leitura ´ sem avan¸o na unidade padr˜o; isto ´, o cursor na tela do monitor ir´ permanecer e c a e a na mesma linha h´ medida que a string STR ser´ lida. O comando lˆ uma constante de caractere porque o a a e descritor no formato ´ “A”. Em uma situa¸˜o normal, isto ´, leitura com avan¸o, o cursor seria posicionado e ca e c no in´ da pr´xima linha na tela. A vari´vel NCH guarda o comprimento da string e o r´tulo 12 indica o ıcio o a o ponto onde o programa deve se encaminhar se uma condi¸˜o de final de registro ´ encontrada. ca e 9.6 Comandos PRINT e WRITE Em compara¸˜o com o comando READ, o comando WRITE suporta os mesmos argumentos, com exce¸˜o ca ca do especificador SIZE. At´ agora, foi usada somente forma do comando PRINT para a sa´ padr˜o de dados, que usualmente ´ e ıda a e a tela do monitor: PRINT*, <lista> O mesmo comando, generalizado para sa´ formatada fica, ıda PRINT <format> [, <lista>] J´ a sintaxe mais geral do comando ´: a e WRITE([UNIT=]<u>, [FMT=] <format>[, IOSTAT= <ios>] & [, ERR= <err-label>][, ADVANCE= <mode>] & [, REC= <int-exp>][, NML= <grp>]) <lista> Os especificadores deste comando executam, na sua maioria, as mesmas fun¸˜es executadas pelos especifico cadores do comando READ, com exce¸˜o dos seguintes, os quais especificam fun¸˜es ligeiramente distintas: ca co UNIT= <u>, onde <u> ´ um n´mero de unidade l´gica v´lido ou “*” para a sa´ padr˜o. Caso esta especie u o a ıda a fica¸˜o seja o primeiro argumento do comando, a palavra-chave ´ opcional. ca e IOSTAT= <ios>, onde <ios> ´ uma vari´vel inteira padr˜o que armazena o status do processo de escrita. e a a Os valores poss´ ıveis s˜o: a <ios> = 0, quando o comando ´ executado sem erros. e 2 Ver se¸˜o 9.2. ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 142.
    134 9.7. Comando FORMATe especificador FMT= <ios> > 0, quando ocorre um erro na execu¸˜o do comando. ca <ios> < 0, quando uma condi¸˜o de final de registro ´ detectada em escrita sem avan¸o ou quando ca e c uma condi¸˜o de final de arquivo ´ detectada. ca e ERR= <err-label>, ´ um r´tulo v´lido para onde o controle de fluxo ´ transferido quando ocorre um erro e o a e de escrita. ADVANCE= <mode>, onde <mode> possui dois valores: ’YES’ ou ’NO’. A op¸˜o ’NO’ especifica que cada ca comando WRITE inicia um novo registro na mesma posi¸˜o; isto ´, implementa sa´ de dados sem ca e ıda avan¸o (non-advancing I/O). A op¸˜o padr˜o ´ ’YES’, isto ´ a cada escrita, o arquivo ´ avan¸ado c ca a e e e c em uma posi¸˜o. Se a sa´ sem avan¸o ´ usada, ent˜o o arquivo deve estar conectado para acesso ca ıda c e a seq¨encial e o formato deve ser expl´ u ıcito. REC= <int-exp>, onde <int-exp> ´ uma express˜o inteira escalar cujo valor ´ o n´mero de ´ e a e u ındice do registro a ser escrito durante acesso direto. Se REC estiver presente, os especificadores END e NML e o formato livre “*” n˜o podem ser tamb´m usados. a e NML= <grp>, onde <grp> ´ o nome de um grupo NAMELIST previamente definido em uma declara¸˜o NAMEe ca LIST. O nome <grp> n˜o ´ uma constante de caracteres e sim um nome v´lido em Fortran3 . a e a Considere o seguinte exemplo, WRITE(17, FMT= ’(I4)’, IOSTAT= ISTAT, ERR= 10) IVAL aqui, ’(I4)’ descreve format de dado inteiro com 4 d´ ıgitos, ISTAT ´ uma vari´vel inteira que indica o status e a do processo de escrita; em caso de erro, o fluxo ´ transferido ao r´tulo 10. IVAL ´ a vari´vel cujo valor ´ e o e a e escrito na unidade 17. Outro exemplo seria: WRITE(*,’(A)’, ADVANCE= ’NO’) ’Entrada: ’ Como a especifica¸˜o de escrita sem avan¸o foi escolhida, o cursor ir´ permanecer na mesma linha que a ca c a string ’Entrada: ’. Em circunstˆncias normais, o cursor passaria ao in´ a ıcio da linha seguinte na tela. Nota-se tamb´m o descritor de formato de constante de caracteres expl´ e ıcito. Como exemplo do uso dos comandos de E/S apresentados nas se¸˜es 9.4 – 9.6, o programa a seguir abre co um novo arquivo seq¨encial chamado notas.dat. O programa ent˜o lˆ o nome de um estudante, seguido u a e por 3 notas, as quais s˜o introduzidas pelo teclado (entrada padr˜o), escrevendo, finalmente, as notas e a a a m´dia final em NOTAS.DAT e no monitor (sa´ padr˜o), na mesma linha do nome. O processo de leitura e e ıda a escrita ´ repetido at´ que um estudante com o nome ’Fim’ ´ introduzido. e e e P O R M Notas RGA IMPLICIT N N O E C A A T R(LEN=20) : : name H R CE REAL : : mark1 , mark2 , mark3 OPEN (UNIT=4,FILE=’NOTAS.DAT’ ) DO READ( * , * ) name, mark1 , mark2 , mark3 IF (name == ’ Fim ’ )EXIT WRITE(UNIT=4,F T= * ) name, mark1 , mark2 , mark3 , ( mark1 + mark2 + mark3 ) / 3 . 0 M WRITE(UNIT= * ,F T= * ) name, mark1 , mark2 , mark3 , ( mark1 + mark2 + mark3 ) / 3 . 0 M END DO CLOSE(UNIT=4) END P O R M Notas RGA 9.7 Comando FORMAT e especificador FMT= O especificador FMT= em um comando READ ou WRITE pode conter ou o s´ ımbolo de formato livre “*”, ou uma constante de caracteres que indica o formato ou um r´tulo que indica a linha onde se encontra um o comando FORMAT. Dado o seguinte exemplo, 3 Ver se¸˜o 9.2. ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 143.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 135 WRITE(17, FMT= ’(2X,2I4,1X,”nome ”,A7)’)I, J, STR este comando escreve no arquivo SAIDA.DAT, aberto em um exemplo anterior, as trˆs vari´veis I, J e STR de e a acordo com o formato especificado: “2 espa¸os em branco (2X), 2 objetos inteiros de 4 d´ c ıgitos em espa¸os c entre eles (2I4), um espa¸o em branco (1X) a constante de caractere ’nome ’ e, finalmente, 7 caracteres c de um objeto de caracteres (A7)”. As vari´veis a ser realmente escritas s˜o tomadas da lista de E/S ap´s a a a o lista de especifica¸˜es do comando. co Outro exemplo: READ(14,*)X, Y Este comando lˆ dos valores do arquivo ENTRADA.DAT usando formato livre e atribuindo os valores `s vari´veis e a a X e Y. Finalmente, no exemplo: WRITE(*,FMT= 10)A, B 10 FORMAT(’Valores: ’,2(F15.6,2X)) O comando WRITE acima usa o formato especificado no r´tulo 10 para escrever na sa´ padr˜o os valores o ıda a das vari´veis A e B. O formato de sa´ pode ser descrito como: “2 instˆncias de: um objeto real com 15 a ıda a colunas ao todo com uma precis˜o de 6 casas decimais (F15.6), seguido por 2 espa¸os em branco (2X)”. a c O formato de E/S de dados ´ definido fazendo-se uso dos descritores de edi¸˜o, abordados na pr´xima e ca o se¸˜o. ca 9.8 Descritores de edi¸˜o ca Nos exemplos apresentados nas se¸˜es anteriores, alguns descritores de edi¸˜o j´ foram mencionados. co ca a Estes editores fornecem uma especifica¸˜o precisa sobre como os valores devem ser convertidos em uma ca string escrita em um dispositivo externo (monitor, impressora, etc) ou em um arquivo interno (disco r´ ıgido, CD-RW, fita, etc), ou convertido de uma string em um dispositivo de entrada de dados (teclado, etc) ou arquivo interno para as diferentes representa¸˜es de tipos de vari´veis suportados pela linguagem. co a Com algumas exce¸˜es, descritores de edi¸˜o aparecem em uma lista separados por v´ co ca ırgulas e somente no caso em que a lista de E/S for vazia ou contiver somente matrizes de tamanho zero que os descritores podem estar totalmente ausentes. Em um processador que suporta tanto caracteres mai´sculos quanto min´sculos, os descritores de edi¸˜o u u ca s˜o interpretados de forma independente com rela¸˜o ao caso. a ca Descritores de edi¸˜o dividem-se em trˆs classes: ca e Descritores de edi¸˜o de dados: I, B, O, Z, F, E, EN, ES, D, G, L, A. ca Descritores de controle: T, TL, TR, X, S, SP, SS, BN, BZ, P, :, /. Descritores de edi¸˜o de strings: H, ’c’, “c” (onde c ´ uma constante de caractere). ca e Estes descritores ser˜o discutidos em mais detalhes a seguir. a 9.8.1 Contadores de repeti¸˜o ca Os descritores de edi¸˜o de dados podem ser precedidos por um contador de repeti¸˜o: uma constante ca ca inteira positiva (sem sinal), como no exemplo 10F12.3 a qual indica 10 constantes reais com 12 posi¸˜es ao todo e com precis˜o de 3 casas decimais cada. Dos co a descritores de edi¸˜o restantes, somente a barra “/” pode ter um contador de repeti¸˜o associado. Um ca ca contador de repeti¸˜o tamb´m pode ser aplicado a um grupo de descritores de edi¸˜o, delimitado por ca e ca parˆnteses: e PRINT ’(4(I5,F8.2))’, (I(J), A(J), J= 1,4) o que ´ equivalente a escrever: e PRINT ’(I5,F8.2,I5,F8.2,I5,F8.2,I5,F8.2)’, (I(J), A(J), J= 1,4) Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 144.
    136 9.8. Descritores deedi¸˜o ca Tabela 9.1: Descritores de edi¸ao que convertem os tipos intr´ c˜ ınsecos. Descritor A B D E EN ES F G I L O Z Tipo de dados convertidos Caractere Inteiro de/para base bin´ria a Real Real com expoente Real com nota¸˜o de engenharia ca Real com nota¸˜o cient´ ca ıfica Real de ponto flutuante (sem expoente) Todos os tipo intr´ ınsecos Inteiro L´gico o Inteiro de/para base octal Inteiro de/para base hexadecimal Note tamb´m o la¸o DO implicado (implied-Do list) e c (I(J), A(J), J= 1,4) o que equivale a escrever I(1), A(1), I(2), A(2), I(3), A(3), I(3), A(3) Contadores de repeti¸˜o como estes podem ser encadeados: ca PRINT ’(2(2I5,2F8.2))’, (I(J),I(J+1),A(J),A(J+1), J=1,4,2) Pode-se ver que esta nota¸˜o possibilita compactar a formata¸˜o de E/S de dados. ca ca Se uma especifica¸˜o de formato ´ usada com uma lista de E/S que cont´m mais elementos que o ca e e n´mero de descritores de formata¸˜o, incluindo os contadores de repeti¸˜o, um novo registro ir´ come¸ar u ca ca a c e a especifica¸˜o de formato ser´ repetida at´ que todos os elementos forem cobertos. Isto acontece, por ca a e exemplo, no comando abaixo: PRINT ’(10I8)’, (I(J), J= 1, 100) 9.8.2 Descritores de edi¸˜o de dados ca Cada tipo intr´ ınseco de vari´veis em Fortran ´ convertido por um conjunto espec´ a e ıfico de descritores, com exce¸˜o do descritor G, que pode converter qualquer tipo intr´ ca ınseco. A tabela 9.1 apresenta uma descri¸˜o ca das convers˜es. o Formato dos descritores de edi¸˜o de dados. ca Um descritor de edi¸˜o de dados pode assumir uma das seguintes formas em uma lista de formata¸˜o de ca ca E/S: [<r>]<c><w> [<r>]<c><w>.<m> [<r>]<c><w>.<d> [<r>]<c><w>.<d>[E<e>] onde os campos <r>, <w>, <d> e <e> devem ser todos constantes inteiras positivas (sem sinal). Parˆmetros a de esp´cie de tipo n˜o podem ser especificados. O significado dos campos ´ o seguinte: e a e <r> ´ o contador de repeti¸˜o. O seu valor pode variar entre 1 e 2147483647 (2**31 - 1). Se <r> for e ca omitido, ele ´ assumido igual a 1. e <c> ´ um dos descritores: I, B, O, Z, F, EN, ES, D, G, L, A. e <w> ´ o n´mero total de d´ e u ıgitos no campo (ou a largura do campo). Se <w> for omitido, ´ assumido um e valor padr˜o que pode variar com o sistema, por´m <w> n˜o pode ser nulo. a e a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 145.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 137 <m> ´ o n´mero m´ e u ınimo de d´ ıgitos que devem aparecer no campo (incluindo zeros precedentes). O intervalo permitido para <m> inicia em 0 mas o valor final depende do sistema. <d> ´ o n´mero de d´ e u ıgitos ` direita do ponto decimal (os d´ a ıgitos significativos). O intervalo de <d> inicia em 0 mas o valor final depende do sistema. O n´mero de d´ u ıgitos significativos ´ afetado se um fator e de escala ´ especificado para o descritor de edi¸˜o. e ca E identifica um campo de expoente. <e> ´ o n´mero de d´ e u ıgitos no expoente. O intervalo de <e> inicia em 1 mas o valor final depende do sistema. Os descritores de edi¸˜o de dados tˆm as seguintes formas espec´ ca e ıficas: Tipo de dado Inteiro Real e Complexo L´gico o Caractere Descritores de dado I<w>[.<m>], B<w>[.<m>], O<w>[.<m>], Z<w>[.<m>], G<w>.<d>[E<e>] F<w>.<d>, E<w>.<d>[E<e>], EN<w>.<d>[E<e>], ES<w>.<d>[E<e>], D<w>.<d>, G<w>.<d>[E<e>] L<w>, G<w>.<d>[E<e>] A[<w>], G<w>.<d>[E<e>] O campo <d> deve ser especificado com os descritores F, E, D e G mesmo se <d> for zero. O ponto decimal tamb´m ´ exigido. Para uma constante de caractere, o campo <w> ´ opcional, independente do e e e tamanho da constante. Para todos os descritores num´ricos, se o campo de escrita for muito estreito para conter o n´mero e u completo, de acordo com a descri¸˜o fornecida, o campo ´ preenchido por <w> asteriscos. ca e Na sa´ os n´meros s˜o geralmente escritos deslocados para a direita no espa¸o de campo especificado ıda u a c por <w>; isto ´ feito preenchendo de espa¸os em branco ` esquerda, caso necess´rio. Valores negativos s˜o e c a a a sempre escritos com o sinal de menos. Na entrada os n´meros tamb´m deveriam ser lidos a partir da direita. Espa¸os em branco ` esquerda u e c a s˜o ignorados. Se o campo ´ todo composto por espa¸os em branco, o registro ser´ lido como zero. a e c a N´ meros inteiros (I<w>[.<m>], B<w>[.<m>], O<w>[.<m>], Z<w>[.<m>]) u Na sua forma b´sica, I<w>, o inteiro ser´ lido ou escrito no campo de largura <w> ajustado ` direita. a a a Representando um espa¸o em branco por , o valor -99 escrito sob o controle de I5 ir´ ser aparecer como c a -99, com o sinal contando como uma posi¸˜o no campo. ca Para impress˜o, uma forma alternativa deste descritor permite que o n´mero de d´ a u ıgitos a ser impressos sejam especificados exatamente, mesmo que alguns deles tenham que ser zeros. Trata-se da forma I<w>.<m>, onde <m> indica o n´mero m´ u ınimo de d´ ıgitos a ser impressos. Neste caso, o valor 99 impresso sob o controle de I5.3 aparecer´ como 099. O valor <m> pode ser zero, em cuja situa¸˜o o campo ser´ preenchido por a ca a brancos se o n´mero impresso for 0. Na entrada, I<w>.<m> ´ interpretado exatamente da mesma forma que u e I<w>. Inteiros tamb´m podem ser convertidos pelos descritores B<w>[.<m>], O<w>[.<m>] e Z<w>[.<m>]. Estes e s˜o similares ao descritor I, por´m destinados a representar o n´mero inteiro nos sistemas num´ricos bin´rio, a e u e a octal e hexadecimal, respectivamente. N´ meros reais (F<w>.<d>, E<w>.<d>[E<e>], EN<w>.<d>[E<e>], ES<w>.<d>[E<e>], D<w>.<d>) u A forma b´sica, F<w>.<d>, gera um n´mero real de ponto flutuante. O ponto decimal conta como uma a u posi¸˜o no campo. Na entrada de dados, se a string possui um ponto decimal, o valor de <d> ´ ignorado. Por ca e exemplo, a leitura da string 9.3729 com o descritor F8.3 causa a transferˆncia do valor 9.3729. Todos e os d´ ıgitos s˜o usados, mas arredondamento pode ocorrer devido ` representa¸˜o finita de um n´mero pelo a a ca u computador. H´ outras duas formas de entrada de n´meros aceit´veis pelo descritor F<w>.<d>: a u a 1. N´mero sem ponto decimal. Neste caso, os <d> d´ u ıgitos mais ` direita ser˜o tomados como a parte a a fracion´rio do n´mero. Por exemplo, a string -14629ser´ lida pelo descritor F7.2 como -146.29. a u a 2. N´mero real na forma padr˜o; a qual envolve uma parte exponencial (se¸˜o 3.3), como o n´mero u a ca u -14.629E-2 ou sua forma variante, onde o expoente sempre tem sinal e o indicador de expoente “E” ´ omitido: -14.629-2. Neste caso, o campo <d> ser´ novamente ignorado e o n´mero na forma e a u exponencial ser´ escrita na forma de ponto flutuante. Sob o controle do descritor F9.1, a string anterior a ser´ convertida ao n´mero 0.14629. a u Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 146.
    138 9.8. Descritores deedi¸˜o ca Estas propriedades aplicam-se ` entrada de dados. a Na sa´ de dados, os valores s˜o arredondados seguindo as regras normais de aritm´tica. Assim, o valor ıda a e 10.9336, sob o controle do descritor F8.3 ir´ aparecer escrito como 10.934 e sob o controle de F4.0 ir´ a a aparecer como 11. (note o ponto). O descritor de edi¸˜o E possui duas formas, E<w>.<d> e E<w>.<d>E<e> e ´ uma maneira mais apropriada ca e de transferir n´meros abaixo de 0.01 ou acima de 1000. u As regras para estes descritores na entrada de dados s˜o idˆnticas `s do descritor F<w>.<d>. Na sa´ a e a ıda com o descritor E<w>.<d>, uma string de caractere contendo a parte inteira com valor absoluto menor que um e quatro caracteres que consistem ou no E seguido por um sinal e dois d´ ıgitos ou de um sinal seguido por trˆs d´ e ıgitos. Assim, o n´mero 1.234 × 1023 , convertido pelo descritor E10.4 vai gerar a string .1234E + 24 u ou .1234 + 024. A forma contendo a letra E n˜o ´ usada se a magnitude do expoente exceder 99. Por a e exemplo, E10.4 ir´ imprimir o n´mero 1.234 × 10−150 como .1234 − 149. Alguns processadores p˜e um a u o zero antes do ponto decimal. Note que agora o valor de <w> deve ser grande o suficiente para acomodar, al´m dos d´ e ıgitos, o sinal (se for negativo), o ponto decimal, a letra E (caso poss´ ıvel), o sinal do expoente e o expoente. Assim, caso se tentasse imprimir o n´mero anterior com o descritor F9.4, apareceria *********. u Na segunda forma do descritor, E<w>.<d>E<e>, o campo <e> determina o n´mero de d´ u ıgitos no expoente. Esta forma ´ obrigat´ria para n´meros cujos expoentes tˆm valor absoluto maior que 999. Assim, o n´mero e o u e u 1.234 × 101234 , com o descritor E12.4E4 ´ transferido como a string .1234E + 1235. e O descritor de edi¸˜o EN implementa a nota¸˜o de engenharia. Ele atua de forma semelhante ao descritor ca ca E, exceto que na sa´ o expoente decimal ´ m´ltiplo de 3, a parte inteira ´ maior ou igual a 1 e menor que ıda e u e 1000 e o fator de escala n˜o tem efeito. Assim, o n´mero 0.0217 transferido sob EN9.2 ser´ convertido a a u a 21.70E-03 ou 21.70-003. O descritor de edi¸˜o ES implementa a nota¸˜o cient´ ca ca ıfica. Ele atua de forma semelhante ao descritor E, exceto que na sa´ o valor absoluto da parte inteira ´ maior ou igual a 1 e menor que 10 e o fator de escala ıda e n˜o tem efeito. Assim, o n´mero 0.0217 transferido sob ES9.2 ser´ convertido a 2.17E-02 ou 2.17E-002. a u a N´ meros complexos (F<w>.<d>, E<w>.<d>[E<e>], EN<w>.<d>[E<e>], ES<w>.<d>[E<e>], D<w>.<d>) u N´meros complexos podem ser editados sob o controle de pares dos mesmos descritores de n´meros reais. u u Os dois descritores n˜o necessitam ser idˆnticos. O valor complexo (0.1,100.), convertido sob o controle a e de F6.1,8.1 seria convertido a 0.1 .1E+03. Os dois descritores podem ser separados por uma constante de caracteres e descritores de controle de edi¸˜o. ca Valores l´gicos (L<w>) o Valores l´gicos podem ser editados usando o descritor L<w>. este define um campo de tamanho <w> o o qual, na entrada consiste de brancos opcionais, opcionalmente seguidos por um ponto decimal, seguido por T ou F. Opcionalmente, este caractere pode ser seguido por caracteres adicionais. Assim, o descritor L7 permite que as strings .TRUE. e .FALSE. sejam lidas com o seu significado correto. Na sa´ ıda, um dos caracteres T ou F ir´ aparecer na posi¸˜o mais ` direita do campo. a ca a Vari´veis de caracteres A[<w>] a Valores de caracteres podem ser editados usando o descritor A com ou sem o campo <w>. Sem o campo, a largura do campo de entrada ou sa´ ´ determinado pelo tamanho real do ´ ıda e ıtem na lista de E/S, medido em termos do n´mero de caracteres de qualquer esp´cie. u e Por outro lado, usando-se o campo <w> pode-se determinar o tamanho desejado da string lida ou escrita. Por exemplo, dada a palavra TEMPORARIO, temos os seguintes resultados no processo de escrita: Descritor A A11 A8 Registro escrito TEMPORARIO TEMPORARIO TEMPORAR Ou seja, quando o campo do descritor ´ menor que o tamanho real do registro, este ´ escrito com os caracteres e e mais ` esquerda. Por outro lado, em caso de leitura da mesma string, as seguintes formas ser˜o geradas: a a Descritor A A11 A8 Autor: Rudi Gaelzer – IFM/UFPel Registro lido TEMPORARIO TEMPORARIO TEMPORAR Impresso: 13 de abril de 2010
  • 147.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 139 Todos os caracteres transferidos sob o controle de um descritor A ou A<w> tˆm a esp´cie do ´ e e ıtem na lista de E/S. Al´m disso, este descritor ´ o unico que pode ser usado para transmitir outros tipos de caracteres, e e ´ distintos dos caracteres padr˜es. o Descritor geral G<w>.<d>[E<e>] O descritor de edi¸˜o geral pode ser usado para qualquer tipo intr´ ca ınseco de dados. Quando usado para os tipos real ou complexo, a sua a¸˜o ´ idˆntica ` do descritor E<w>.<d>[E<e>], exceto que na sa´ de ca e e a ıda dados, quando a magnitude (n) do valor est´ no intervalo a 0.1 − 0.5 × 10−<d>−1 ≤ n < 10<d> − 0.5 ou zero quando <d>= 0, s˜o convertidas como com o descritor F, seguidos pelo mesmo n´mero de brancos que a u o descritor E teria reservado ` parte exponencial. Esta forma ´ util para escrever valores cujas magnitudes a e´ n˜o s˜o bem conhecidas previamente e quando a convers˜o do descritor F ´ prefer´ ` do descritor E. a a a e ıvel a Quando o descritor G ´ usado para os tipos inteiro, l´gico e de caracteres, ele segue as regras dos e o respectivos descritores de edi¸˜o . ca Tipos derivados Valores de tipos derivados s˜o editados pela seq¨ˆncia apropriada de descritores de edi¸˜o correspondena ue ca tes aos tipos intr´ ınsecos dos componentes do tipo derivado. Como exemplo, TYPE :: STRING INTEGER :: COMP CHARACTER(LEN= 20) :: PALAVRA END TYPE STRING TYPE(STRING) :: TEXTO READ(*, ’(I2,A)’)TEXTO Edi¸˜o de tamanho m´ ca ınimo de campo Para possibilitar que os registros de sa´ contenham o m´ ıda ınimo poss´ de espa¸o n˜o usado, os descriıvel c a tores I, F, B, O e Z podem especificar um tamanho de campo igual a zero, como em I0 ou F0.3. Isto n˜o a denota um campo de tamanho nulo, mas um campo com o tamanho m´ ınimo necess´rio para conter o valor a de sa´ em quest˜o. Este recurso existe para que o programador n˜o precise se preocupar se o tamanho de ıda a a um campo ´ suficiente para conter o dado, em cuja situa¸˜o o uso padr˜o destes descritores iria gerar uma e ca a sa´ composta somente por asteriscos. ıda Descritor de edi¸˜o de string de caracteres ca Uma constante de caracteres da esp´cie padr˜o, sem um parˆmetro de esp´cie especificado, pode ser e a a e transferida a um arquivo de sa´ inserindo-a na especifica¸˜o de formato, como no exemplo: ıda ca PRINT”(’Este ´ um exemplo!’)” e O qual vai gerar o registro de sa´ ıda: Este ´ um exemplo e cada vez que o comando seja executado. Descritores de edi¸˜o de string de caracteres n˜o podem ser usados ca a em entrada de dados. 9.8.3 Descritores de controle de edi¸˜o ca Um descritor de controle de edi¸˜o age de duas formas: determinando como texto ´ organizado ou ca e afetando as convers˜es realizadas por descritores de edi¸˜o de dados subseq¨entes. o ca u Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 148.
    140 9.8. Descritores deedi¸˜o ca Formato dos descritores de controle de edi¸˜o ca Um descritor de controle de edi¸˜o pode assumir uma das seguintes formas em uma lista de formata¸˜o ca ca de E/S: <c> <c><n> <n><c> onde: <c> ´ um dos seguintes c´digos de formato: T, TL, TR, X, S, SP, SS, BN, BZ, P, dois pontos (:) e a barra (/). e o <n> ´ um n´mero de posi¸˜es de caracteres. Este n´mero n˜o pode ser uma vari´vel; deve ser uma constante e u co u a a inteira positiva sem especifica¸˜o de parˆmetro de esp´cie de tipo. O intervalo de <n> inicia em 1 at´ ca a e e um valor que depende do sistema. Em processadores Intel de 32 bits, por exemplo, o maior valor ´ e <n>= 2**15 - 1. Em geral, descritores de controle de edi¸˜o n˜o s˜o repet´ ca a a ıveis. A unica exce¸˜o ´ a barra (/), a qual pode ´ ca e tamb´m ser precedida por um contador de repeti¸˜o. e ca Os descritores de controle possuem a seguintes formas espec´ ıficas quanto `s suas fun¸˜es: a co Tipo de controle Posicional Sinal Interpreta¸˜o de brancos ca Fator de escala Miscelˆneo a Descritores de controle T<n>, TL<n>, TR<n>, <n>X S, SP, SS BN, BZ <k>P :, / O descritor P ´ uma exce¸˜o ` sintaxe geral dos descritores. Ele ´ precedido por um fator de escala (<k>), e ca a e em vez de um especificador de posi¸˜o. ca Descritores de controle de edi¸˜o tamb´m podem ser agrupados em parˆnteses e precedidos por um ca e e contador de repeti¸˜o do grupo. ca Edi¸˜o posicional ca Os descritores T, TL, TR e X especificam a posi¸˜o onde o pr´ximo caractere ´ transferido de ou para um ca o e registro. Na sa´ estes descritores n˜o executam a convers˜o e transferˆncia de caracteres propriamente dita, al´m ıda, a a e e de n˜o afetarem o tamanho do registro. Se caracteres s˜o transferidos a posi¸˜es na posi¸˜o especificada por a a co ca um destes descritores, ou ap´s esta, posi¸˜es saltadas e que n˜o eram previamente preenchidas por brancos o co a passam a ser preenchidas. O resultado ´ como se o registro por completo estava inicialmente preenchido por e brancos. Edi¸˜o T ca O descritor T especifica uma posi¸˜o de caractere em um registro de E/S. Ele toma a seguinte forma: ca T<n> onde <n> ´ uma constante positiva que indica a posi¸˜o de caractere do registro, relativa ao limite ` esquerda e ca a do tabulador. Na entrada, o descritor posiciona o registro externo a ser lido na posi¸˜o de caractere especificada por ca <n>. Na sa´ ıda, o descritor indica que a transferˆncia de dados inicia na <n>-´sima posi¸˜o de caractere do e e ca registro externo. Exemplos. Suponha que um arquivo possua um registro contendo o valor ABC de leitura seja executado: XYZe o seguinte comando CHARACTER(LEN= 3) :: VALOR1, VALOR2 ... READ(11,’(T7,A3,T1,A3)’)VALOR1, VALOR2 Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 149.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 141 Os valores lidos ser˜o VALOR1= ’XYZ’ e VALOR2= ’ABC’. a Suponha agora que o seguinte comando seja executado: PRINT 25 25 FORMAT(T51,’COLUNA 2’,T21,’COLUNA 1’) a seguinte linha ´ impressa na tela do monitor (ou na sa´ padr˜o): e ıda a 00000000011111111112222222222333333333344444444445555555555666666666677777777778 12345678901234567890123456789012345678901234567890123456789012345678901234567890 | | COLUNA 1 COLUNA 2 Deve-se notar que as constantes de caractere foram impressas iniciando nas colunas 20 e 50 e n˜o nas colunas a 21 e 51. Isto ocorreu porque o primeiro caractere do registro impresso foi reservado como um caractere de controle. Este ´ o comportamento padr˜o na sa´ de dados. e a ıda Edi¸˜o TL ca O descritor TL especifica uma posi¸˜o de caractere ` esquerda da posi¸˜o corrente no registro de E/S. O ca a ca descritor toma a seguinte forma: TL<n> onde <n> ´ uma constante inteira positiva indicando a <n>-´sima posi¸˜o ` esquerda do caractere corrente. e e ca a Se <n> ´ maior ou igual ` posi¸˜o corrente, o pr´ximo caractere acessado ´ o primeiro caractere do registro. e a ca o e Exemplo. No exemplo anterior, temos: PRINT 25 25 FORMAT(T51,’COLUNA 2’,T21,’COLUNA 1’,TL20,’COLUNA 3’) o que gera na tela: 00000000011111111112222222222333333333344444444445555555555666666666677777777778 12345678901234567890123456789012345678901234567890123456789012345678901234567890 | | | COLUNA 3 COLUNA 1 COLUNA 2 Edi¸˜o TR ca O descritor TR especifica uma posi¸˜o de caractere ` direita da posi¸˜o corrente no registro de E/S. O ca a ca descritor toma a seguinte forma: TR<n> onde <n> ´ uma constante inteira positiva indicando a <n>-´sima posi¸˜o ` direita do caractere corrente. e e ca a Edi¸˜o X ca O descritor X especifica uma posi¸˜o de caractere ` direita da posi¸˜o corrente no registro de E/S. Este ca a ca descritor ´ equivalente ao descritor TR. O descritor X toma a seguinte forma: e <n>X onde <n> ´ uma constante inteira positiva indicando a <n>-´sima posi¸˜o ` direita do caractere corrente. e e ca a Na sa´ ıda, este descritor n˜o gera a grava¸˜o de nenhum caractere quando ele se encontra no final de uma a ca especifica¸˜o de formato. ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 150.
    142 9.8. Descritores deedi¸˜o ca Edi¸˜o de sinal ca Os descritores S, SP e SS controlam a sa´ do sinal de mais (+) opcional dentro de campos de sa´ ıda ıda num´ricos. Estes descritores n˜o tˆm efeito durante a execu¸˜o de comandos de entrada de dados. e a e ca Dentro de uma especifica¸˜o de formato, um descritor de edi¸˜o de sinal afeta todos os descritores de ca ca dados subseq¨entes I, F, E, EN, ES, D e G at´ que outro descritor de edi¸˜o de sinal seja inclu´ na formata¸˜o. u e ca ıdo ca Edi¸˜o SP ca O descritor SP for¸a o processador a produzir um sinal de mais em qualquer posi¸˜o subseq¨ente onde c ca u ele seria opcional. O descritor toma a forma simples SP Edi¸˜o SS ca O descritor SS for¸a o processador a suprimir um sinal de mais em qualquer posi¸˜o subseq¨ente onde c ca u ele seria opcional. O descritor toma a forma simples SS Edi¸˜o S ca O descritor S retorna o status do sinal de mais como opcional para todos os campos num´ricos sube seq¨entes. O descritor toma a forma simples u S Interpreta¸˜o de brancos ca Os descritores BN e BZ controlam a interpreta¸˜o de brancos posteriores embebidos dentro de campos de ca entrada num´ricos. Estes descritores n˜o tˆm efeito durante a execu¸˜o de comandos de sa´ de dados. e a e ca ıda Dentro de uma especifica¸˜o de formato, um descritor de edi¸˜o de brancos afeta todos os descritores de ca ca dados subseq¨entes I, B, O, Z, F, E, EN, ES, D e G at´ que outro descritor de edi¸˜o de brancos seja inclu´ u e ca ıdo na formata¸˜o. ca Os descritores de edi¸˜o de brancos sobrep˜e-se ao efeito do especificador BLANK durante a execu¸˜o de ca o ca um comando de entrada de dados. Edi¸˜o BN ca O descritor BN for¸a o processador a ignorar todos os brancos posteriores embebidos em campos de c entrada num´ricos. O descritor toma a forma simples: e BN O campo de entrada ´ tratado como se todos os brancos tivessem sido removidos e o restante do campo ´ e e escrito na posi¸ao mais ` direita. Um campo todo composto de brancos ´ tratado como zero. c˜ a e Edi¸˜o BZ ca O descritor BZ for¸a o processador a interpretar todos os brancos posteriores embebidos em campos de c entrada num´ricos como zeros. O descritor toma a forma simples: e BN Edi¸˜o de fator de escala P ca O descritor P especifica um fator de escala, o qual move a posi¸˜o do ponto decimal em valores reais e ca das duas partes de valores complexos. O descritor toma a forma <k>P Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 151.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 143 onde <k> ´ uma constante inteira com sinal (o sinal ´ opcional, se positiva) especificando o n´mero de e e u posi¸˜es, para a esquerda ou para a direita, que o ponto decimal deve se mover (o fator de escala). O co intervalo de valores de <k> ´ de -128 a 127. e No in´ de um comando de E/S formatado, o valor do fator de escala ´ zero. Se um descritor de escala ´ ıcio e e especificado, o fator de escala ´ fixado, o qual afeta todos os descritores de edi¸˜o de dados reais subseq¨entes e ca u at´ que outro descritor de escala ocorra. Para redefinir a escala a zero, deve-se obrigatoriamente especificar e 0P. Na entrada, um fator de escala positivo move o ponto decimal para a esquerda e um fator negativo move o ponto decimal para direita. Quando um campo de entrada, usando os descritores F, E, D, EN, ES ou G, cont´m um expoente expl´ e ıcito, o fator de escala n˜o tem efeito. Nos outros casos, o valor interno do dado a lido na lista de E/S ´ igual ao campo externo multiplicado por 10−<k> . Por exemplo, um fator de escala 2P e multiplica um valor de entrada por 0.01, movendo o ponto decimal duas posi¸˜es ` esquerda. Um fator de co a escala -2P multiplica o valor de entrada por 100, movendo o ponto decimal duas posi¸˜es ` direita. co a A seguinte tabela apresenta alguns exemplos do uso do especificador <k>P na entrada de dados: Formato 3PE10.5 3PE10.5 -3PE10.5 Campo de entrada 37.614 37.614E2 37.614 Valor interno .037614 3761.4 37614.0 O fator de escala deve preceder o primeiro descritor de edi¸˜o real associado com ele, mas n˜o necesca a sariamente deve preceder o descritor propriamente dito. Por exemplo, todos os seguintes formatos tˆm o e mesmo efeito: (3P,I6,F6.3,E8.1) (I6,3P,F6.3,E8.1) (I6,3PF6.3,E8.1) Note que se o fator de escala precede imediatamente o descritor real associado, a v´ ırgula ´ opcional. e Na sa´ ıda, um fator de escala positivo move o ponto decimal para a direita e um fator de escala negativo move o ponto decimal para a esquerda. Neste caso, o efeito do fator de escala depende em que tipo de edi¸˜o ca real est´ associada com o mesmo, como segue: a ˆ Para edi¸˜o F, o valor externo iguala o valor interno da lista de E/S multiplicado por 10<k> , alterando ca a magnitude do dado. ˆ Para edi¸˜es E e D, o campo decimal externo da lista de E/S ´ multiplicado por 10<k> e <k> ´ subtra´ co e e ıdo do expoente, alterando a magnitude do dado. Um fator de escala positivo diminui o expoente; um fator de escala negativo aumenta o expoente. Para fator de escala positivo, <k> deve ser menor que <d>+2 sen˜o ocorrer´ um erro no processo de convers˜o de sa´ a a a ıda. ˆ Para edi¸˜o G, o fator de escala n˜o tem efeito se a magnitude do dado a ser impresso est´ dentro do ca a a intervalo efetivo do descritor. Se a magnitude estiver fora do intervalo efetivo do descritor, edi¸˜o E ´ ca e usada e o fator de escala tem o mesmo efeito como neste caso. ˆ Para edi¸˜es EN e ES, o fator de escala n˜o tem efeito. co a A seguir, alguns exemplos de sa´ de dados usando o descritor P: ıda Formato 1PE12.3 1PE12.2 -1PE12.2 Campo de entrada -270.139 -270.139 -270.139 Valor interno -2.701E+02 -2.70E+02 -0.03E+04 O exemplo a seguir tamb´m usa edi¸˜o P: e ca REAL, DIMENSION(6) :: A= 25.0 WRITE(6,10) A 10 FORMAT(’ ’, F8.2,2PF8.2,F8.2) resultando os seguintes valores gravados na unidade 6: 25.00 2500.00 2500.00 2500.00 2500.00 2500.00 Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 152.
    144 9.8. Descritores deedi¸˜o ca Edi¸˜o com barra (/) ca O descritor / termina a transferˆncia de dados para o registro corrente e inicia a transferˆncia de dados e e para um registro novo. Em um arquivo ou na tela, o descritor tem a a¸˜o de iniciar uma nova linha. ca A forma que o descritor toma ´: e [<r>]/ onde <r> ´ um contador de repeti¸˜o. O intervalo de <r> inicia em 1 at´ um valor que depende do sistema. e ca e Em processadores intel de 32 bits, o valor m´ximo ´ <r>= 2**15-1. a e M´ltiplas barras for¸am o sistema a pular registros de entrada ou a gerar registros brancos na sa´ u c ıda, como segue: ˆ Quando n barras consecutivas aparecem entre dois descritores de edi¸˜o, n - 1 registros s˜o pulados na ca a entrada ou n - 1 registros brancos s˜o gerados na sa´ a ıda. A primeira barra termina o registro corrente. A segunda barra termina o primeiro pulo ou registro em branco e assim por diante. ˆ Quando n barras consecutivas aparecem no in´ ou final de uma especifica¸˜o de formato, n registros ıcio ca s˜o pulados ou n registros em branco s˜o gerados na sa´ a a ıda, porque o parˆnteses inicial e final da e especifica¸˜o de formato s˜o, por si mesmos, iniciadores ou finalizadores de registros, respectivamente ca a Por exemplo, dado a seguinte formata¸˜o de sa´ ca ıda: WRITE(6,99) 99 FORMAT(’1’,T51,’Linha Cabe¸alho’//T51,’Sublinha Cabe¸alho’//) c c ir´ gerar os seguintes registros no arquivo: a 00000000011111111112222222222333333333344444444445555555555666666666677777777778 12345678901234567890123456789012345678901234567890123456789012345678901234567890 | Linha Cabe¸alho c <linha em branco> Sublinha Cabe¸alho c <linha em branco> <linha em branco> Edi¸˜o com dois pontos (:) ca O descritor : termina o controle de formato se n˜o houver mais ´ a ıtens na lista de E/S. Por exemplo, supondo os seguintes comandos: PRINT 1, 3 PRINT 2, 13 1 FORMAT(’ I=’,I2,’ J=’,I2) 2 FORMAT(’ K=’,I2,:,’ L=’,I2) as seguintes linhas aparecem na sa´ ıda: I= 3 J= K=13 Se houver ´ ıtens de E/S restantes, o descritor : n˜o tem efeito. a 9.8.4 Descritores de edi¸˜o de strings ca Descritores de edi¸˜o de strings controlam a sa´ das constantes de string. Estes descritores s˜o: ca ıda a ˆ Constantes de caracteres ˆ Descritor de edi¸˜o H (eliminado no Fortran 95). ca Um descritor de edi¸˜o de strings n˜o pode ser precedido por um contador de repeti¸˜o; contudo, eles ca a ca podem fazer parte de um grupo contido entre parˆnteses, o qual, por sua vez, ´ precedido por um contador e e de repeti¸˜o. ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 153.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 145 Edi¸˜o de constantes de caracteres ca O descritor de constante de caracteres provoca a sa´ de uma constante de string em um registro externo. ıda Ele vem em duas formas: ˆ ’<string>’ ˆ “<string>” onde <string> ´ uma constante de caracteres, sem especifica¸˜o de esp´cie. O seu comprimento ´ o n´mero e ca e e u de caracteres entre os delimitadores; dois delimitadores consecutivos s˜o contados como um caractere. a Para incluir um ap´strofe (’) em uma constante de caractere que ´ delimitada por ap´strofes, deve-se o e o colocar duas ap´strofes consecutivas (”) na formata¸˜o. Por exemplo, o ca 50 FORMAT(’Today”s date is: ’,i2,’/’,i2,’/’,i2) Da mesma forma, para incluir aspas (“) em uma constante de caractere que ´ delimitada por aspas, e deve-se colocar duas aspas consecutivas na formata¸˜o. ca Como exemplo do uso dos comandos de E/S apresentados nas se¸˜es 9.4 – 9.8, o programa a seguir abre co o arquivo pessoal.dat, o qual cont´m registros dos nomes de pessoas (at´ 15 caracteres), idade (inteiro de e e 3 d´ ıgitos), altura (em metros e cent´ ımetros) e n´mero de telefone (inteiro de 8 d´ u ıgitos). O programa lˆ estes e dados contidos em pessoal.dat e os imprime no monitor no formato: Altura Nome Idade (metros) Tel. No. -------------------P. A. Silva 45 1,80 33233454 J. C. Pedra 47 1,75 34931458 etc. P O R M Pessoais dados RGA IMPLICIT N N O E C A A T R(LEN=15) : : name H R CE INTEGER : : age , t e l n o , stat REAL : : h e i g h t OPEN(UNIT=8, FILE=’ p e s s o a l . dat ’ ) WRITE( * , 1 0 0 ) 100 F R A T24 , ’ Altura ’ ) O M T( WRITE( * , 2 0 0 ) 200 F R A T4 , ’ Nome ’ , T17 , ’ Idade ’ , T23 , ’ ( metros ) ’ , T32 , ’ Tel . No . ’ ) O M T( WRITE( * , 3 0 0 ) 300 F R A T4,’−−−−’,T17,’−−−−−’,T23 , ’ −−−−−− ’ , T32,’−−−−−−−−’) O M T( DO READ( 8 , F T= ’( a15 , 1 x , i 3 , 1 x , f 4 . 2 , 1 x , i 8 ) ’ , IOSTAT stat ) name, & M = age , h e i g h t , t e l n o IF ( stat <0) EXIT ! Testa f i n a l de a r q u i v o WRITE( * , 4 0 0 ) name, age , h e i g h t , t e l n o 400 F R A O M T(A, T18 , I3 , T25 , F4 . 2 , T32 , I 8 ) END DO END P O R M P e s s o a i s d a d o s RGA sendo que o arquivo pessoal.dat possui a seguinte formata¸˜o: ca P . A. S i l v a J . C . Pedra 045 1 . 8 0 33233454 047 1 . 7 5 34931458 Cabe ressaltar tamb´m que os comandos FORMAT utilizados nos r´tulos 100, 200, 300 e 400 poderiam ser e o igualmente substitu´ ıdos pelo especificador FMT=. Por exemplo, as linhas WRITE(*,200) 200 FORMAT(T4,’Nome’,T17,’Idade’,T23,’(metros)’,T32,’Tel. No.’) s˜o equivalentes a a WRITE(*, FMT=’(T4,”Nome”,T17,”Idade”,T23,”(metros)”,T32,”Tel. Autor: Rudi Gaelzer – IFM/UFPel No.”)’) Impresso: 13 de abril de 2010
  • 154.
    146 9.9. Comando CLOSE 9.9 ComandoCLOSE O prop´sito do comando CLOSE ´ desconectar um arquivo de uma unidade. Sua forma ´: o e e CLOSE([UNIT=]<u>[, IOSTAT=<ios>][, ERR= <err-label>][, STATUS=<status>]) onde <u>, <ios> e <err-label> tˆm os mesmos significados descritos para o comando OPEN (se¸˜o 9.4). e ca Novamente, especificadores em palavras-chaves podem aparecer em qualquer ordem, mas o especificador de unidade deve ser o primeiro ser for usada a forma posicional. A fun¸˜o do especificador STATUS= ´ de determinar o que acontecer´ com o arquivo uma vez desconectado. ca e a O valor de <status>, a qual ´ uma express˜o escalar de caracteres da esp´cie padr˜o, pode ser um dos valores e a e a ’KEEP’ ou ’DELETE’, ignorando qualquer branco posterior. Se o valor ´ ’KEEP’, um arquivo que existe e continuar´ existindo ap´s a execu¸˜o do comando CLOSE, e pode ser posteriormente conectado novamente a o ca a uma unidade. Se o valor ´ ’DELETE’, o arquivo n˜o mais existir´ ap´s a execu¸˜o do comando. Se o e a a o ca especificador for omitido, o valor padr˜o ´ ’KEEP’, exceto se o arquivo tem o status ’SCRATCH’, em cujo a e caso o valor padr˜o ´ ’DELETE’. a e Em qualquer caso, a unidade fica livre para ser conectada novamente a um arquivo. O comando CLOSE pode aparecer em qualquer ponto no programa e se ´ executado para uma unidade n˜o existente ou descoe a nectada, nada acontece. No final da execu¸˜o de um programa, todas as unidades conectadas s˜o fechadas, como se um comando ca a CLOSE sem o especificador STATUS= fosse aplicado a cada unidade conectada. Como exemplo: CLOSE(2, IOSTAT=IOS, ERR=99, STATUS=’DELETE’) 9.10 Comando INQUIRE O status de um arquivo pode ser definido pelo sistema operacional antes da execu¸˜o do programa ou ca pelo programa durante a sua execu¸˜o, seja por um comando OPEN ou seja por alguma a¸˜o sobre um arquivo ca ca pr´-conectado que o faz existir. Em qualquer momento, durante a execu¸˜o do programa, ´ poss´ inquirir e ca e ıvel a respeito do status e atributos de um arquivo usando o comando INQUIRE. Usando uma variante deste comando, ´ poss´ determinar-se o status de uma unidade; por exemplo, e ıvel se o n´mero de unidade existe para o sistema em quest˜o, se o n´mero est´ conectado a um arquivo e, em u a u a caso afirmativo, quais os atributos do arquivo. Outra variante do comando permite inquirir-se a respeito do tamanho de uma lista de sa´ quando usada para escrever um registro n˜o formatado. ıda a Alguns atributos que podem ser determinados pelo uso do comando INQUIRE s˜o dependentes de outros. a Por exemplo, se um arquivo n˜o est´ conectado a uma unidade, n˜o faz sentido inquirir-se a respeito da a a a forma de acesso que est´ sendo usada para este arquivo. Se esta inquiri¸˜o ´ feita, de qualquer forma, o a ca e especificador relevante fica indefinido. As trˆs variantes do comando s˜o conhecidas como INQUIRE por arquivo, INQUIRE por unidade e INQUIRE e a por lista de sa´ ıda. Na descri¸˜o feita a seguir, as primeiras duas variantes s˜o descritas juntas. Suas formas ca a s˜o: a INQUIRE({[UNIT=]<u>|FILE=<arq>}[, IOSTAT=<ios>][, ERR=<err-label>] [, EXIST=<ex>][, OPENED=<open>][, NUMBER=<num>][, NAMED=<nmd>] [, NAME=<nam>][, ACCESS=<acc>][, SEQUENTIAL=<seq>][, DIRECT=<dir>] [, FORM=<frm>][, FORMATTED=<fmt>][, UNFORMATTED=<unf>][, RECL=<rec>] [, NEXTREC=<nr>][, BLANK=<bl>][, POSITION=<pos>][, ACTION=<act>] [, READ=<rd>][, WRITE=<wr>][, READWRITE=<rw>][, DELIM=<del>][, PAD=<pad>]) & & & & & onde os especificadores entre chaves ({}) s˜o excludentes; o primeiro deve ser usado no caso de INQUIRE a por unidade e o segundo no caso de INQUIRE por arquivo. Neste ultimo caso, <arq> ´ uma express˜o escalar ´ e a de caracteres cujo valor, ignorando quaisquer brancos posteriores, fornece o nome do arquivo envolvido, incluindo o caminho. A interpreta¸˜o de <arq> depende do sistema. Em um sistema Unix/Linux, o nome ca depende do caso. Um especificador n˜o pode aparecer mais de uma vez na lista de especificadores opcionais. Todas as a atribui¸˜es de valores aos especificadores seguem as regras usuais e todos os valores do tipo de caracteres, co exceto no caso de NAME= s˜o mai´sculos. Os especificadores, cujos valores s˜o todos escalares e da esp´cie a u a e padr˜o s˜o: a a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 155.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 147 IOSTAT= <ios>, tem o mesmo significado descrito no comando OPEN (se¸˜o 9.4). A vari´vel <ios> ´ a unica ca a e ´ definida se uma condi¸˜o de erro ocorre durante a execu¸˜o do INQUIRE. ca ca ERR= <err-label>, tem o mesmo significado descrito no comando OPEN (se¸˜o 9.4). ca EXIST= <ex>, onde <ex> ´ uma vari´vel l´gica. O valor .TRUE. ´ atribu´ se o arquivo (ou unidade) e a o e ıdo existir e .FALSE. em caso contr´rio. a OPENED= <open>, onde <open> ´ uma vari´vel l´gica. O valor .TRUE. ´ atribu´ se o arquivo (ou unidade) e a o e ıdo estiver conectado a uma unidade (ou arquivo) e .FALSE. em caso contr´rio. a NUMBER= <num>, onde <num> ´ uma vari´vel inteira ` qual ´ atribu´ o n´mero da unidade conectada ao e a a e ıdo u arquivo, ou -1 se nenhuma unidade estiver conectada ao arquivo. NAMED= <nmd>, NAME= <nam>, onde <nmd> ´ uma vari´vel l´gica ` qual o valor .TRUE. ´ atribu´ se o arquivo tem um e a o a e ıdo nome ou .FALSE. em caso contr´rio. Se o arquivo tem um nome, este ser´ atribu´ ` vari´vel de a a ıdo a a caracteres <nam>. Este valor n˜o ´ necessariamente o mesmo que ´ dado no especificador FILE=, se a e e usado, mas pode ser qualificado de alguma forma. Contudo, em qualquer situa¸˜o ´ um nome v´lido ca e a para uso em um comando OPEN subseq¨ente. Assim, o INQUIRE pode ser usado para determinar o u valor real de um arquivo antes deste ser conectado. Dependendo do sistema, o nome depende do caso. ACCESS= <acc>, onde <acc> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos um dos valores ’SEQUENTIAL’ ou ’DIRECT’ dependendo do m´todo de acesso para um arquivo que est´ conectado e ’UNDEe a FINED’ se n˜o houver conex˜o. a a SEQUENTIAL= <seq>, DIRECT= <dir>, onde <seq> e <dir> s˜o vari´veis de caracteres `s quais s˜o atribu´ a a a a ıdos os valores ’YES’, ’NO’ ou ’UNKNOWN’, dependendo se o arquivo puder ser aberto para acesso direto ou seq¨encial, u respectivamente, ou se isto n˜o pode ser determinado. a FORM= <frm>, onde <frm> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos um dos valores ’FORMATTED’ ou ’UNFORMATTED’, dependendo na forma para a qual o arquivo ´ realmente conectado, ou ’UNDEFINED’ e se n˜o houver conex˜o. a a FORMATTED= <fmt>, UNFORMATTED= <unf>, onde <fmt> e <unf> s˜o vari´veis de caracteres `s quais s˜o atribu´ a a a a ıdos os valores ’YES’, ’NO’ ou ’UNKNOWN’, dependendo se o arquivo puder ser aberto para acesso formatado ou n˜o a formatado, respectivamente, ou se isto n˜o pode ser determinado. a RECL= <rec>, onde <rec> ´ uma vari´vel inteira ` qual ´ atribu´ o valor do tamanho do registro de um e a a e ıdo arquivo conectado para acesso direto, ou o tamanho m´ximo do registro permitido para um arquivo a conectado para acesso seq¨encial. O comprimento ´ o n´mero de caracteres para registros formatados u e u contendo somente caracteres do tipo padr˜o e dependente do sistema em caso contr´rio. Se n˜o houver a a a conex˜o, <rec> resulta indefinido. a NEXTREC= <nr>, onde <nr> ´ uma vari´vel inteira ` qual ´ atribu´ o valor do n´mero do ultimo registro e a a e ıdo u ´ lido ou escrito, mais um. Se nenhum registro foi ainda lido ou escrito, <nr>= 1. Se o arquivo n˜o a estiver conectado para acesso direto ou se a posi¸˜o ´ indeterminada devido a um erro anterior, <nr> ca e resulta indefinido. BLANK= <bl>, onde <bl> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos os valores ’NULL’ ou ’ZERO’, dependendo se os brancos em campos num´ricos devem ser por padr˜o interpretados como campos de e a nulos ou de zeros, respectivamente, ou ’UNDEFINED’ se ou n˜o houver conex˜o ou se a conex˜o n˜o a a a a for para E/S formatada. POSITION= <pos>, onde <pos> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos os valores ’REWIND’, ’APPEND’ ou ’ASIS’, conforme especificado no correspondente comando OPEN, se o arquivo n˜o foi a reposicionado desde que foi aberto. Se n˜o houver conex˜o ou se o arquivo est´ conectado para acesso a a a direto, o valor ´ ’UNDEFINED’. Se o arquivo foi reposicionado desde que a conex˜o foi estabelecida, o e a valor depende do processador (mas n˜o deve ser ’REWIND’ ou ’APPEND’ exceto se estes corresponderem a a ` verdadeira posi¸˜o). ca Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 156.
    148 9.11. Outros comandosde posicionamento ACTION= <act>, onde <act> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos os valores ’READ’, ’WRITE’ ou ’READWRITE’, conforme a conex˜o. Se n˜o houver conex˜o, o valor ´ ’UNDEFINED’. a a a e READ= <rd>, onde <rd> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos os valores ’YES’, ’NO’ ou ’UNKNOWN’, dependendo se leitura ´ permitida, n˜o permitida ou indeterminada para o arquivo. e a WRITE= <wr>, onde <wr> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos os valores ’YES’, ’NO’ ou ’UNKNOWN’, dependendo se escrita ´ permitida, n˜o permitida ou indeterminada para o arquivo. e a READWRITE= <rw>, onde <rw> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos os valores ’YES’, ’NO’ ou ’UNKNOWN’, dependendo se leitura e escrita s˜o permitidas, n˜o permitidas ou indeterminadas para o a a arquivo. DELIM= <del>, onde <del> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos os valores ’QUOTE’, ’APOSTROPHE’ ou ’NONE’, conforme especificado pelo correspondente comando OPEN (ou pelo valor padr˜o). a Se n˜o houver conex˜o, ou se o arquivo n˜o estiver conectado para E/S formatada, o valor ´ ’UNDEa a a e FINED’. PAD= <pad>, onde <pad> ´ uma vari´vel de caracteres ` qual s˜o atribu´ e a a a ıdos os valores ’YES’, caso assim especificado pelo correspondente comando OPEN (ou pelo valor padr˜o); em caso contr´rio, o valor ´ a a e ’NO’. Uma vari´vel que ´ a especifica¸˜o em um comando INQUIRE, ou est´ associada com um, n˜o deve aparecer a e ca a a em outra especificador no mesmo comando. A terceira variante do comando INQUIRE, INQUIRE por lista de E/S, tem a forma: INQUIRE(IOLENGTH=<comp>) <lista-sa´da> ı onde <comp> ´ uma vari´vel inteira escalar padr˜o que ´ usada para determinar o comprimento de uma e a a e <lista-sa´da> n˜o formatada em unidades que dependem do processador. Esta vari´vel pode ser usada ı a a para estabelecer se, por exemplo, uma lista de sa´ ´ muito grande para o tamanho do registro dado pelo ıda e especificador RECL= de um comando OPEN, ou ser usado como o valor do comprimento a ser determinado ao especificador RECL=. Um exemplo de uso do comando INQUIRE ´ dado abaixo: e LOGICAL :: EX, OP CHARACTER(LEN= 11) :: NAM, ACC, SEQ, FRM INTEGER :: IREC, NR ... OPEN(2, IOSTAT= IOS, ERR= 99, FILE= ’Cidades’, STATUS= ’NEW’, & ACCESS= ’DIRECT’, RECL= 100) INQUIRE(2, ERR= 99, EXIST= EX, OPENED= OP, NAME= NAM, ACCESS= ACC, & SEQUENTIAL= SEQ, FORM= FRM, RECL= IREC, NEXTREC= NR) Ap´s execu¸˜o bem sucedida dos comandos OPEN e INQUIRE, as vari´veis ter˜o os seguintes valores: o ca a a EX= .TRUE. OP= .TRUE. NAM= ’Cidades ’ ACC= ’DIRECT ’ SEQ= ’NO ’ FRM= ’UNFORMATTED’ IREC= 100 NR= 1 9.11 Outros comandos de posicionamento Outros comandos que exercem fun¸˜es de controle no arquivo, em adi¸˜o ` entrada e sa´ de dados, co ca a ıda s˜o fornecidos abaixo. a Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 157.
    Cap´ ıtulo 9. Comandosde Entrada/Sa´ de Dados ıda 9.11.1 149 Comando BACKSPACE Pode acontecer em um programa que uma s´rie de registros sejam escritos e que, por alguma raz˜o, o e a ultimo registro escrito deve ser substitu´ por um novo; isto ´, o ultimo registro deve ser sobrescrito. De ´ ıdo e ´ forma similar, durante a leitura dos registros, pode ser necess´rio reler o ultimo registro, ou verificar por a ´ leitura o ultimo registro escrito. Para estes prop´sitos, Fortran fornece o comando BACKSPACE, o qual tem ´ o a sintaxe BACKSPACE([UNIT=]<u>[, IOSTAT=<ios>][, ERR=<err-label>]) onde <u> ´ uma express˜o inteira escalar padr˜o que designa o n´mero da unidade e os outros especificadores e a a u opcionais tˆm o mesmo significado que no comando READ (se¸˜o 9.5). e ca A a¸˜o deste comando ´ posicionar o arquivo antes do registro corrente, se houver. Se o comando for ca e tentado quando o registro estiver no in´ do arquivo, nada ocorre. Se o arquivo estiver posicionado ap´s ıcio o um registro de final de arquivo, este resulta posicionado antes deste registro. N˜o ´ poss´ solicitar BACKSPACE em um arquivo que n˜o exista, nem sobre um registro escrito por um a e ıvel a comando NAMELIST. Uma serie de comandos BACKSPACE resultar´ no retrocesso no n´mero correspondente a u de registros. 9.11.2 Comando REWIND De forma semelhante a uma releitura, re-escritura ou verifica¸˜o por leitura de um registro, uma opera¸˜o ca ca similar pode ser realizada sobre um arquivo completo. Com este prop´sito, o comando REWIND: o REWIND([UNIT=]<u>[, IOSTAT=<ios>][ERR=<err-label>]) pode ser usado para reposicionar um arquivo, cujo n´mero de unidade ´ especificado pela express˜o escalar u e a inteira <u>. Novamente, os demais especificadores opcionais tˆm o mesmo significado que no comando READ. e Se o arquivo j´ estiver no seu in´ a ıcio, nada ocorre. O mesmo ocorre caso o arquivo n˜o exista. a 9.11.3 Comando ENDFILE O final de um arquivo conectado para acesso seq¨encial ´ normalmente marcado por um registro especial, u e denominado registro de final de arquivo, o qual ´ assim identificado pelo computador. e Quando necess´rio, ´ poss´ a e ıvel escrever-se um registro de final de arquivo explicitamente, usando o comando ENDFILE: ENDFILE([UNIT=]<u>[, IOSTAT=<ios>][, ERR=<err-label>]) onde todos os argumentos tˆm o mesmo significado que nos comandos anteriores. e O arquivo ´ ent˜o posicionado ap´s o registro de final de arquivo. Este registro, se lido subseq¨entemente e a o u por um programa, deve ser manipulado usado a especifica¸˜o END=<end-label> do comando READ sen˜o a ca a execu¸˜o do programa ir´ normalmente terminar. ca a Antes da transferˆncia de dados, um arquivo n˜o pode estar posicionado ap´s o registro de final de e a o arquivo, mas ´ poss´ retroceder com os comandos BACKSPACE ou REWIND, o que permite a ocorrˆncia de e ıvel e outras transferˆncias de dados. e Um registro de final de arquivo ´ automaticamente escrito sempre quando ou uma opera¸˜o de retrocesso e ca parcial ou completo segue um opera¸˜o de escrita como a opera¸˜o seguinte na unidade; quando o arquivo ca ca ´ fechado por um comando CLOSE, por um novo comando OPEN na mesma unidade ou por encerramento e normal do programa. Se o arquivo tamb´m pode ser conectado para acesso direto, somente os registros al´m do registro de e e final de arquivo s˜o considerados como escritos e somente estes podem ser lidos em uma conex˜o de acesso a a direto subseq¨ente. u Autor: Rudi Gaelzer – IFM/UFPel Impresso: 13 de abril de 2010
  • 158.
    ´ Indice Remissivo ˆ Ambito Nomes, 118 R´tulos,118 o Intr´ ınsecas SINH, 68 Puras, 104 Recursivas, 101 Rotinas de m´dulos, 111 o Valor matricial, 98 COUNT, rotina intr´ ınseca, 74 EXTERNAL, atributo e declara¸˜o, 98 ca SAVE, atributo e declara¸˜o, 103 ca FORALL, comando e construto, 62 WHERE, comando e construto, 57 INTENT, atributo e declara¸˜o, 84 ca Interfaces, 86 Gen´ricas, 114, 117 e INTRINSIC, atributo e declara¸˜o, 65 ca M´dulos, 107 o Dados globais, 108 Rotinas de, 111 Rotinas gen´ricas, 114, 117 e Matrizes Ajust´veis, 93 a Aloc´veis, 59 a Autom´ticas, 95 a Construtores de, 55 Express˜es e atribui¸˜es, 49 o co Format assumida, 94 Se¸˜es de, 51 co Tamanho assumido, 93 Terminologia, 45 Tipos derivados, 47 ONLY, op¸˜o, 107, 110 ca PRIVATE, atributo e declara¸˜o, 113 ca PUBLIC, atributo e declara¸˜o, 113 ca ınseca, 78 RANDOM NUMBER, rotina intr´ RANDOM SEED, rotina intr´ ınseca, 78 RESHAPE, rotina intr´ ınseca, 56, 76 RETURN, comando, 84 Rotinas, 81 Argumentos, 83 Matrizes, 92 Opcionais, 91 Palavras-Chave, 88 Subprogramas como argumentos, 97 Tipos derivados, 92 Elementais, 106 Externas, 86 Gen´ricas, 114 e Internas, 83 150