-
Notifications
You must be signed in to change notification settings - Fork 1
/
gnufortran.tex
278 lines (217 loc) · 10.7 KB
/
gnufortran.tex
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
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
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
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
%Autor: miguev
%miguev: 8
\chapter{GNU Fortran}
\label{gnufortran.tex}
\index{GNU Fortran}
\index{Fortran}
\section{¿Fortran?}
{\tt Fortran} no es un lenguaje muy popular, ni tiene por qué serlo.
Se trata de un lenguaje para un uso específico: cálculo numérico.
Fortran no es un lenguaje de propósito general como C, Pascal, Python
o Perl y por eso sólo se utiliza en entornos científicos como centros
de cálculo.
El lenguaje de programación {\tt Fortran} es importante en entornos
científicos. Su nombre es un acrónimo de {\bf For}mula {\bf
Tran}slator, ya que su mayor uso era traducir las fórmulas de cálculo
matemático al lenguaje de las máquinas. Desde sus principios, el
lenguaje Fortran ha tenido una sintaxis muy peculiar, adaptada al uso
de tarjetas perforadas. En la actualidad, Fortran se utiliza en
asignaturas de Cálculo Numérico en carreras técnicas como Matemáticas,
Física y algunas ingenierías.
Utilizaremos aquí el compilador {\bf GNU Fortran}, compatible con la
mayoría del lenguaje básico de Fortran 77 y algunas extensiones
propias de Fortran 90, suficiente para las prácticas de programación
en Fortran 77. En este libro nos mantendremos dentro del estándar ANSI
Fortran 77.
Para programación en Fortran 95 existe un proyecto de compilador en
marcha en {\tt http://g95.sf.net}, aunque aún se encuentra en estado
larval.
\section{Uso básico del compilador}
\index{Fortran!compilador}
El compilador de GNU Fortran es muy similar al del GNU C/C++, por lo
que los detalles de ambos serán abarcados en el próximo tema. Veamos
una vez más el típico ejemplo de ``HolaMundo''. En el editor que más
te guste, escribe el siguiente código Fortran:
\begin{ejemplo}%
{HolaMundo.for}%
{Primer "Hola Mundo" en Fortran}
Programa básico de holamundo en Fortran 77, define un formato e imprime
un mensaje usándolo. también incluye una línea de comentario.
\end{ejemplo}
El comando para invocar al compilador es {\tt g77}, y su sintaxis es
muy similar a la del compilador {\tt gcc} (GNU C/C++). Estos
compiladores producen la salida por defecto en un ejecutable con el
nombre {\tt a.out}, comportamiento que puedes modificar con la opción
{\tt -o nombreejecutable}.
\begin{verbatim}
$ ls
HolaMundo.for
$ g77 HolaMundo.for
$ ls
a.out HolaMundo.for
$ g77 -o HolaMundo HolaMundo.for
$ ls
HolaMundo HolaMundo.for
$ ./HolaMundo
Hola Mundo
\end{verbatim}
\section{Dividir el código}
Veamos ahora también como podemos dividir un programa en varios
ficheros de código fuente. En el editor escribe los siguientes
códigos fuente Fortran y guárdalos como {\tt HolaMundo2.for} y {\tt
Saludos.for} respectivamente.
\begin{ejemplo}%
{HolaMundo2.for}%
{Segundo ``Hola Mundo'' en Fortran}
Segundo ``Hola Mundo'' en Fortran. Este fichero llama a una función
{\tt saluda()} que no está definida en él, sino en otro fichero.
\end{ejemplo}
\begin{ejemplo}%
{Saludos.for}%
{Segundo ``Hola Mundo'' en Fortran}
Segundo ``Hola Mundo'' en Fortran. Este fichero implementa la función
{\tt saluda()} que es llamada desde el fichero {\tt HolaMundo2.for}.
\end{ejemplo}
Para generar ahora el ejecutable utiliza el comando {\tt g77} dándole
ambos ficheros como argumentos. En general, para compilar un programa
Fortran escrito en varios ficheros bastará con utilizar el comando de
la forma {\tt g77 -o ejecutable fichero1.for ... ficheroN.for}
\begin{verbatim}
$ ls
HolaMundo2.for Saludos.for
$ g77 -o HolaMundo2 HolaMundo2.for Saludos.for
$ ls
HolaMundo2 HolaMundo2.for Saludos.for
$ ./HolaMundo2
Hola Mundo
\end{verbatim}
Si lo prefieres puedes también compilar los ficheros de código fuente
por separado para obtener los ficheros de código objeto, y luego
enlazarlos al final. Esto resulta útil cuando tienes muchos ficheros
de código fuente y sólo estás trabajando en uno de ellos, ya que puede
significar un ahorro de tiempo no tener que compilar todos los
ficheros cada vez que quieras compilar el programa. En este ejemplo
los comandos serían los siguientes:
\begin{verbatim}
$ g77 -c HolaMundo2.for
$ g77 -c Saludos.for
$ g77 -o HolaMundo2 HolaMundo2.o Saludos.o
\end{verbatim}
En los dos primeros comandos, la opción {\tt -c} del compilador
le indica que sólo debe generar el código objeto, sin intentar
enlazarlo. En el último, el compilador está recibiendo los ficheros de
código objeto (y la opción para modificar el nombre del ejecutable
resultante) e interpreta que debe enlazarlos. Es importante notar que
no podemos utilizar el comando {\tt ld} para enlazar código en Fortran
porque faltarían muchos símbolos (mayormente funciones) que {\tt g77}
se encarga de poner pero {\tt ld} desconoce.
Si después de haber compilado el programa de esta forma modificas el
fichero {\tt Saludos.for} y quieres recompilar el programa, sólo has
de recompilar el fichero (o los ficheros) que has modificado y volver
a enlazar los ficheros de código objeto:
\begin{verbatim}
$ g77 -c Saludos.for
$ g77 -o HolaMundo2 HolaMundo2.o Saludos.o
\end{verbatim}
En este ejemplo no se nota la ventaja, pero en una práctica de
programación en la que estás aprovechando tres ficheros de código
fuente de prácticas anteriores y escribiendo otros tres ficheros de
código fuente nuevos, según la máquina en la que trabajes puede que no
te apetezca tener que compilar los seis ficheros cada vez que
modificas uno. Si a esto le sumas el uso de GNU Make (que estudiaremos
más adelante) el proceso de compilación y recompilación resulta mucho
más cómodo.
\section{Mezclar Fortran con C}\label{fortran+c}
\index{Fortran!mezclado con C}
Con lo que has visto en este tema sabes más que suficiente para hacer
prácticas de programación en Fortran 77, pero ahora vamos a rizar el
rizo un poco. Si sabes algo (un poco) de programación en C no te
resultará difícil entender lo siguiente, en caso contrario deja este
apartado para cuando hayas terminado con los temas de GNU C/C++ y GNU
Make.
Fortran es un lenguaje de cálculo numérico, e intentar programar algo
que no sea cálculo numérico en Fortran puede ser un suplicio. Un
ejemplo sencillo de esto es un menú, que permanezca preguntando
opciones hasta que el usuario decida salir del programa. Es posible
programar un menú en Fortran, pero no resulta tan efectivo como en
otros lenguajes como C o Pascal.
C es un lenguaje de propósito general, lo que significa que puedes
programar en C casi cualquier cosa que te propongas. Sin embargo
programar cálculo numérico en C puede no ser tan cómodo como hacerlo
en Fortran. Entonces, unamos ambos lenguajes en un mismo programa,
aprovechando lo mejor de cada uno.
Esta curiosa mezcla es posible con los compiladores de GNU, porque de
hecho el compilador de GNU Fortran está basado en el de GNU C/C++. Sin
embargo hay una serie de consideraciones que debes tener en cuenta, y
es conveniente que sepas programar algo en C porque hay que mirarlo
desde el punto de vista del lenguaje C.
\begin{itemize}
\item {\bf En Fortran las funciones reciben siempre punteros}. Esto
implica que si modificas el valor de un parámetro dentro de una
función en Fortran, ese cambio seguirá siendo efectivo tras terminar
la función.
\item {\bf En Fortran los vectores son también punteros}. Cuando
declaras en Fortran un vector puedes especificar el rango de índices
que será válido dentro del vector, por ejemplo {\tt integer a(-2:8)}
define un vector de enteros que puede ser indexado desde -2 hasta 8
ambos inclusive, de forma que {\tt a(-2)} y {\tt a(8)} son los
extremos del vector. Esto se maneja internamente como un puntero a
entero a partir del cual hay 11 posiciones reservadas. Es decir, su
equivalente en C sería {\tt int a[11]} y {\tt a(-2)} sería {\tt a[0]}.
Incluso programando sólo en Fortran es importante entender esto.
\item {\bf Las funciónes de Fortran se renombran en el código objeto}.
Esto es, si has definido una función en Fortran llamada {\tt spline}
para llamarla desde C debes hacerlo con el nombre {\tt spline\_}
(añadiendo dos caracteres de subrayado). Además debes pasarle los
parámetros como punteros.
\item {\bf Las funciones llamadas desde Fortran también se renombran}.
Para llamar a la función {\tt menu} desde el código Fortran hay que
definirla en C con el nombre {\tt menu\_}.
\item {\bf Los ficheros de código fuente se compilan sin enlazar}.
Para compilar un fichero de código fuente de Fortran utiliza el
comando {\tt g77 -c fichero.for} y para compilar un fichero de código
fuente de C utiliza el comando {\tt gcc -c fichero.for}.
\item {\bf Los ficheros de código objeto se enlazan con g77}. Cuando
hayas compilado todos los fuentes utiliza el compilador {\tt g77} (no
el {\tt gcc}) para enlazarlo y producir el ejecutable.
\end{itemize}
Veamos un ejemplo sencillo de cómo usar esto. Los siguientes ficheros,
dos de Fortran y uno de C, implementan un sencillo algoritmo de
ordenación de datos (selección directa).
\begin{ejemplo}%
{ordena.for}%
{Ejemplo de programación conjunta Fortran y C}
Declara las variables, llama al menú escrito en C y finalmente muestra
el contenido del vector después de terminar el menú. Nótese que el
vector {\tt a} está indexado desde 1 hasta {\tt n}.
\end{ejemplo}
\begin{ejemplo}%
{menu.c}%
{Ejemplo de programación conjunta Fortran y C}
Implementa el menú que permite operar con el vector y llamar a la
función {\tt mysort} programada en Fortran. Además protege al programa
de entradas de datos erróneas o maliciosas. Nótese qe el vector {\tt
a} es de tamaño {\tt *n}, pero sólo se utilizan las {\tt m} primeras
posiciones, indexadas desde {\tt 0} hasta {\tt m - 1}.
\end{ejemplo}
\begin{ejemplo}%
{mysort.for}%
{Ejemplo de programación conjunta Fortran y C}
Implementa en Fortran el método de ordenación por selección directa.
Nótese que el tamaño del vector se recibe como parámetro y sólo se
utilizan las {\tt m} primeras posiciones, indexadas desde {\tt 1}
hasta {\tt m}.
\end{ejemplo}
Para compilar este programa hazlo fichero a fichero, generando primero
los ficheros de código objeto utilizando {\tt g77} o {\tt gcc} según
esté cada fichero de código fuente escrito en Fortran o en C. Luego
enlazalos todos con {\tt g77}.
\begin{verbatim}
$ g77 -c ordena.for
$ gcc -c menu.c
$ g77 -c mysort.for
$ g77 -o ordena ordena.o menu.o mysort.o
\end{verbatim}
Con la ayuda de GNU Make el proceso de recompilado se convierte en
algo casi automático y bastante más cómodo. Para saber más sobre GNU
Make ve a la página \pageref{make}.