Professional Documents
Culture Documents
Paris VI
Introduction
au fortran
90/95/2003
Avertissement
Ce document est diffus dans une version en volution, qui reste encore trs inacheve, notamment
concernant les apports du fortran 2003. Plusieurs chapitres ne sont que des bauches, en particulier
ceux sur les structures, les pointeurs et linteroprabilit avec le C ; dautres questions sont peine
abordes. Lobjectif reste de complter progressivement le document.
Dans ce contexte, je vous remercie par avance de me signaler les erreurs aussi bien que les formulations
obscures. Vos commentaires et suggestions seront les bienvenus.
Jacques.Lefrere@upmc.fr
10 novembre 2015
ii
Remerciements
Je tiens remercier mes collgues enseignants de la Matrise de Physique et Applications
de lUniversit Pierre et Marie Curie, Paris VI, Marie-Claude et Jean-Claude Justice, Michel
Karatchenzeff, Ma Pham, ainsi que mes collgues du M1 du Master de lUPMC, Albert
Hertzog, Philippe Sindzingre et Franois Ravetta, pour leurs encouragements et leurs conseils
au cours de la rdaction de ce document.
Je remercie aussi Marie-Alice Foujols de lInstitut Pierre Simon Laplace pour ses sminaires
enthousiastes qui nous ont sensibiliss au fortran 90.
Merci aussi aux collgues du Service daronomie pour les nombreuses discussions au sujet
du fortran au sein du laboratoire, et en particulier Franoise Pinsard, Francis Dalaudier et
Stphane Marchand pour leurs patientes relectures critiques.
Je remercie aussi Frdric Bernardo sans lequel le chapitre sur linter-oprabilit avec le
langage C naurait pas vu le jour.
Merci enfin tous ceux qui ont contribu de prs ou de loin llaboration de ce document, et
surtout aux tudiants de la Matrise de Physique et Applications de Paris VI, puis ceux du M1
du Master (mentions P&A et SDUEE) de lUPMC, car cest avant tout pour eux mais aussi grce
eux quil a t rdig.
iii
Notations
La police machine crire , espacement fixe, est utilise pour indiquer les lments du
code source du fortran.
Les crochets [. . . ] dlimitent les lments optionnels de la syntaxe ou les arguments optionnels des procdures ; ces symboles ne font pas partie de la syntaxe.
Lors de la description de la syntaxe, les symboles < et > indiquent o lutilisateur doit substituer les identificateurs, expressions, ou valeurs quil a choisis ; ces symboles ne font pas partie
de la syntaxe.
Exemple
La syntaxe dcrite comme suit :
Indications de lecture
f95
Conseils pratiques
Les rgles de bon usage du langage, qui, au del de la norme, sont motives par des objectifs
de lisibilit, de portabilit ou de robustesse du code source, sont repres par le symbole dans la
marge extrieure du texte, comme pour ce paragraphe.
Difficults
Les points prsentant des difficults particulires ou des risques derreur sont indiqus par le B
symbole B dans la marge extrieure du texte, comme pour ce paragraphe.
iv
Avertissement
Ce document nest pas un manuel de rfrence du fortran 90/95/2003 dcrivant exhaustivement la norme du langage. Il sagit dun document largement inspir des rfrences cites dans
la bibliographie, rfrences auxquelles il est vivement conseill de se reporter pour une tude plus
approfondie ou plus systmatique. Incomplet, notamment sur certains aspects les plus rcents du
fortran, il sapparente plus un guide de lutilisateur du fortran pour le calcul scientifique. Il
sadresse essentiellement des tudiants ayant dj une exprience de la programmation dans un
langage structur (fortran ou C) souhaitant sinitier aux nouvelles fonctionnalits du langage
partir du fortran 90, notamment :
la notation tableaux, les oprateurs et fonctions manipulant globalement des tableaux multidimensionnels,
lallocation dynamique, les types drivs et les pointeurs,
le contrle des passages darguments entre procdures via les modules.
Prsentation
Aprs un chapitre 1 introductif (p. 1) prsentant lvolution du fortran, les tapes de mise au
point des programmes et les lments du langage, le chapitre 2 (p. 10) dcrit les types dobjets
du langage et leurs attributs, en particulier numriques, avant daborder au chapitre 3 (p. 21) les
oprateurs qui permettent de les manipuler.
Le chapitre 4 (p. 26) est entirement consacr aux structures de contrle du fortran : cest un
chapitre essentiel et facile qui doit tre tudi ds la premire lecture.
Le chapitre 5 entres-sorties (p. 35) aborde les instructions de lecture et dcriture et les formats
de conversion des donnes : il est conseill de commencer par les sections dintroduction et de
terminologie, quitte revenir ensuite sur la description dtaille des instructions et surtout des
formats, pour laquelle des allers et retours avec les sections dexemples ainsi quavec le chapitre 8
(p. 94) sur les chanes de caractres sont ncessaires.
Le chapitre 6 intitul procdures (p. 57) constitue le deuxime thme majeur du document : il
prsente les fonctions et les sous-programmes en partant de la notion de procdure interne attache
un programme pour aboutir aux procdures de module rutilisables grce la compilation spare.
La dernire section (6.5) abordant les fonctionnalits avances peut tre passe en premire lecture.
Le troisime thme majeur du fortran, les tableaux, fait lobjet du chapitre 7 (p. 79) : il constitue latout principal du fortran 90 pour le calcul scientifique avec lintroduction des notations
matricielles et des fonctions intrinsques manipulant les tableaux multidimensionnels. Ce chapitre
essentiel peut tre abord en deux tapes : la premire lecture doit inclure lallocation dynamique
ainsi que le lien entre procdures et tableaux, mais on peut garder pour une deuxime lecture les
notions de sections non-rgulires, les masques et la structure FORALL.
Le chapitre 8 (p. 94) prsente la manipulation des chanes de caractres et les fonctions associes : cest un chapitre facile, mme sil nest pas central pour les applications au calcul scientifique.
Les chapitres 9 sur les types drivs (p. 102), 10 sur la gnricit (p. 111) et 11 sur les pointeurs
(p. 118) prsentent des fonctionnalits orientes objet du fortran, et peuvent tre rservs une
deuxime lecture. Quant au chapitre 12 (p. 129), qui prsente les techniques dappel de fonctions
crites en C depuis le fortran et rciproquement, il peut intresser des non-spcialistes du fortran
pour linterfacer avec le langage C.
Enfin, les annexes ont plus vocation servir de rfrence qu tre lues de faon linaire, mme
sil est utile de les parcourir pour connatre leur existence. Cela vaut par exemple pour la liste
des fonctions intrinsques du fortran (A, p. 138) quitte revenir au document ponctuellement
pour vrifier une syntaxe dappel. De la mme faon, parcourir lannexe C, p. 154 sur la norme
IEEE de reprsentation des nombres rels permet de visualiser concrtement les approximations
des calculs en machine. Par ailleurs, les utilisateurs du langage C pourront trouver dans lannexe D,
p. 160, un aide-mmoire prsentant une comparaison approximative des syntaxes et fonctions des
deux langages. Pour terminer, lannexe E, p. 165 fournit de brves indications sur lutilisation de
quelques compilateurs.
. . . . .
lecture
. . . . .
. . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
iii
iii
iv
iv
v
1 Introduction
1.1 Historique du fortran . . . . . . . . . . . . . .
1.2 Les tapes de mise en uvre dun programme
1.2.1 dition du fichier source . . . . . . . .
1.2.2 Compilation et dition de liens . . . .
1.2.3 Excution . . . . . . . . . . . . . . . .
1.2.4 Cas des fichiers sources multiples . . .
1.3 Les lments du langage . . . . . . . . . . . .
1.3.1 Les caractres du fortran . . . . . . .
1.3.2 Les identificateurs des objets . . . . .
1.4 Les formats du code source fortran . . . . . .
1.4.1 Format fixe . . . . . . . . . . . . . . .
1.4.2 Format libre du fortran 90 . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
des types prdfinis
. . . . . . . . . . .
. . . . . . . . . . .
3 Oprateurs et expressions
3.1 Les oprateurs numriques . . . . . . . . . . . . . . . . . . . . . . .
3.1.1 Rgles de priorit entre les oprateurs numriques binaires .
3.1.2 Imperfections numriques des oprations lies aux types . .
3.1.3 Conversions implicites . . . . . . . . . . . . . . . . . . . . .
3.2 Les oprateurs de comparaison . . . . . . . . . . . . . . . . . . . .
3.3 Les oprateurs boolens . . . . . . . . . . . . . . . . . . . . . . . .
3.4 Oprateur de concatnation des chanes de caractres . . . . . . . .
3.5 Priorits entre les oprateurs . . . . . . . . . . . . . . . . . . . . .
v
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
2
3
3
5
5
6
6
7
7
7
8
10
10
10
10
12
14
16
17
17
18
18
19
19
20
21
21
21
21
22
23
24
25
25
vi
4 Structures de contrle
4.1 Structures IF . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1 Linstruction IF . . . . . . . . . . . . . . . . . . . . .
4.1.2 La structure IF ... END IF . . . . . . . . . . . . . .
4.1.3 Utilisation du ELSE IF . . . . . . . . . . . . . . . . . .
4.2 Structure SELECT CASE . . . . . . . . . . . . . . . . . . . . .
4.3 Structures de boucles . . . . . . . . . . . . . . . . . . . . . . .
4.3.1 Boucles DO avec compteur . . . . . . . . . . . . . . . .
4.3.2 Boucles DO WHILE . . . . . . . . . . . . . . . . . . . .
4.3.3 Ruptures de squence dans les boucles : EXIT et CYCLE
4.3.4 Boucles DO sans compteur . . . . . . . . . . . . . . . .
4.4 La structure BLOCK . . . . . . . . . . . . . . . . . . . . . . . .
4.5 Sortie de structure quelconque avec linstruction EXIT nomm
4.6 Autres instructions de contrle . . . . . . . . . . . . . . . . .
4.6.1 Instruction CONTINUE . . . . . . . . . . . . . . . . . .
4.6.2 Branchement par GO TO . . . . . . . . . . . . . . . . .
4.6.3 Instruction STOP . . . . . . . . . . . . . . . . . . . . .
4.6.4 Instruction RETURN . . . . . . . . . . . . . . . . . . . .
4.6.5 Remarques sur les instructions STOP et RETURN . . . .
4.6.6 Branchements dans les entres-sorties . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
26
26
26
26
27
27
29
29
29
30
31
31
32
32
32
32
33
33
34
34
5 Entressorties, fichiers
5.1 Introduction : entres et sorties standard . . . . . . . .
5.1.1 Une instruction dE/S = un enregistrement . .
5.1.2 Saisie de donnes au clavier . . . . . . . . . . .
5.2 Gnralits et terminologie . . . . . . . . . . . . . . .
5.2.1 Fichiers externes et fichiers internes . . . . . .
5.2.2 Notion denregistrement . . . . . . . . . . . . .
5.2.3 Fichiers formats et fichiers non formats . . .
5.2.4 Mthodes daccs aux donnes . . . . . . . . .
5.2.5 Notion de liste dentre-sortie . . . . . . . . . .
5.3 Instructions dentres-sorties . . . . . . . . . . . . . .
5.3.1 Le module intrinsque ISO_FORTRAN_ENV . . .
5.3.2 OPEN . . . . . . . . . . . . . . . . . . . . . . . .
5.3.3 CLOSE . . . . . . . . . . . . . . . . . . . . . . .
5.3.4 READ . . . . . . . . . . . . . . . . . . . . . . . .
5.3.5 WRITE . . . . . . . . . . . . . . . . . . . . . . .
5.3.6 PRINT . . . . . . . . . . . . . . . . . . . . . . .
5.3.7 INQUIRE . . . . . . . . . . . . . . . . . . . . . .
5.3.8 Instructions de positionnement dans les fichiers
5.3.9 Entres-sorties sans avancement automatique .
5.4 Descripteurs de format . . . . . . . . . . . . . . . . . .
5.4.1 Descripteurs actifs . . . . . . . . . . . . . . . .
5.4.2 Descripteurs de contrle . . . . . . . . . . . . .
5.4.3 Syntaxe des formats et rgles dexploration . .
5.4.4 Boucles et changements denregistrement . . .
5.4.5 Format variable . . . . . . . . . . . . . . . . . .
5.5 Exemples dentres-sorties formates . . . . . . . . . .
5.5.1 Descripteurs de donnes numriques en criture
5.5.2 Descripteurs de contrle en criture . . . . . .
5.6 Exemples de fichiers en accs direct . . . . . . . . . . .
5.6.1 Exemple de fichier format en accs direct . .
5.6.2 Exemple de fichier non-format en accs direct
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
35
35
35
36
37
37
38
38
39
40
41
41
42
44
44
45
45
45
46
47
47
48
49
50
50
51
52
52
53
54
54
55
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
vii
6 Procdures
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . .
6.1.1 Intrt des procdures . . . . . . . . . . . .
6.1.2 Variables locales, automatiques et statiques
6.1.3 Arguments des procdures . . . . . . . . . .
6.1.4 Lattribut INTENT des arguments . . . . . .
6.2 Sous-programmes et fonctions . . . . . . . . . . . .
6.2.1 Sous-programmes . . . . . . . . . . . . . . .
6.2.2 Fonctions . . . . . . . . . . . . . . . . . . .
6.3 Procdures internes et procdures externes . . . . .
6.3.1 Procdures internes : CONTAINS . . . . . . .
6.3.2 Procdures externes . . . . . . . . . . . . .
6.3.3 La notion dinterface . . . . . . . . . . . . .
6.4 Les modules . . . . . . . . . . . . . . . . . . . . . .
6.4.1 Exemple de procdure de module . . . . . .
6.4.2 Partage de donnes via des modules . . . .
6.4.3 lments dencapsulation . . . . . . . . . .
6.4.4 Linstruction IMPORT dans les interfaces . .
6.4.5 Modules intrinsques . . . . . . . . . . . . .
6.5 Fonctionnalits avances . . . . . . . . . . . . . . .
6.5.1 Arguments optionnels . . . . . . . . . . . .
6.5.2 Transmission darguments par mot-clef . . .
6.5.3 Noms de procdures passs en argument . .
6.5.4 La dclaration PROCEDURE . . . . . . . . . .
6.5.5 Interfaces abstraites . . . . . . . . . . . . .
6.5.6 Procdures rcursives . . . . . . . . . . . .
6.5.7 Procdures pures . . . . . . . . . . . . . . .
6.5.8 Procdures lmentaires . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
57
57
57
58
58
59
59
60
61
61
62
63
63
64
64
65
67
69
69
69
69
70
71
74
74
76
78
78
7 Tableaux
7.1 Gnralits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.1.1 Terminologie des tableaux . . . . . . . . . . . . . . . . . .
7.1.2 Ordre des lments dans un tableau multidimensionnel . .
7.1.3 Constructeurs de tableaux . . . . . . . . . . . . . . . . . .
7.2 Sections de tableaux . . . . . . . . . . . . . . . . . . . . . . . . .
7.2.1 Sections rgulires . . . . . . . . . . . . . . . . . . . . . .
7.2.2 Sections non-rgulires . . . . . . . . . . . . . . . . . . . .
7.3 Oprations sur les tableaux . . . . . . . . . . . . . . . . . . . . .
7.3.1 Extension des oprations lmentaires aux tableaux . . .
7.3.2 Instruction et structure WHERE . . . . . . . . . . . . . . .
7.3.3 Affectation dune section non-rgulire . . . . . . . . . . .
7.4 Fonctions intrinsques particulires aux tableaux . . . . . . . . .
7.4.1 Fonctions dinterrogation . . . . . . . . . . . . . . . . . .
7.4.2 Fonctions de rduction . . . . . . . . . . . . . . . . . . . .
7.4.3 Fonctions de transformation . . . . . . . . . . . . . . . . .
7.4.4 Notion de masque . . . . . . . . . . . . . . . . . . . . . .
7.4.5 ALL, ANY, COUNT . . . . . . . . . . . . . . . . . . . . . . . .
7.4.6 Instruction et structure FORALL . . . . . . . . . . . . . . .
7.5 Tableaux, procdures et allocation dynamique . . . . . . . . . . .
7.5.1 Les trois mthodes dallocation des tableaux . . . . . . .
7.5.2 Tableaux en arguments muets des procdures . . . . . . .
7.5.3 Tableaux dynamiques allouables . . . . . . . . . . . . . .
7.5.4 Allocation au vol de tableaux dynamiques par affectation
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
79
79
79
80
81
81
82
82
83
83
84
84
85
85
85
86
88
88
88
89
89
90
91
93
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
viii
8 Chanes de caractres
8.1 Le type chane de caractres . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.1 Les constantes chanes de caractres . . . . . . . . . . . . . . . .
8.1.2 Les dclarations de chanes de caractres . . . . . . . . . . . . . .
8.1.3 Les variantes du type chanes de caractres . . . . . . . . . . . .
8.2 Expressions de type chane de caractres . . . . . . . . . . . . . . . . . .
8.2.1 Concatnation de chanes . . . . . . . . . . . . . . . . . . . . . .
8.2.2 Sous-chanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.3 Affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.3 Les fonctions oprant sur les chanes de caractres . . . . . . . . . . . .
8.3.1 Suppression des espaces terminaux avec TRIM . . . . . . . . . . .
8.3.2 Justification gauche avec ADJUSTL . . . . . . . . . . . . . . . .
8.3.3 Justification droite avec ADJUSTR . . . . . . . . . . . . . . . . .
8.3.4 Les fonctions LEN et LEN_TRIM . . . . . . . . . . . . . . . . . . .
8.3.5 Recherche de sous-chane avec INDEX . . . . . . . . . . . . . . . .
8.3.6 Recherche des caractres dun ensemble avec SCAN . . . . . . . .
8.3.7 Recherche des caractres hors dun ensemble avec VERIFY . . . .
8.3.8 Duplication de chanes avec REPEAT . . . . . . . . . . . . . . . .
8.3.9 Conversion de caractre en entier . . . . . . . . . . . . . . . . . .
8.3.10 Conversion dentier en caractre . . . . . . . . . . . . . . . . . .
8.3.11 Comparaison de chanes de caractres . . . . . . . . . . . . . . .
8.3.12 Le caractre de fin de ligne NEW_LINE . . . . . . . . . . . . . . .
8.4 Les entres-sorties de chanes de caractres . . . . . . . . . . . . . . . .
8.4.1 Les entres-sorties de chanes formates . . . . . . . . . . . . . .
8.4.2 Les entres de chanes en format libre . . . . . . . . . . . . . . .
8.4.3 Les fichiers internes : codage en chane de caractres et dcodage
8.5 Les tableaux de chanes de caractres . . . . . . . . . . . . . . . . . . . .
8.6 Chanes et procdures . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
94
94
94
94
95
95
95
95
96
96
96
96
97
97
97
97
97
98
98
98
98
98
98
98
99
99
99
100
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
102
102
103
103
103
103
104
104
105
105
106
106
107
109
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
111
111
112
113
114
114
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
ix
11 Pointeurs
11.1 Pointeurs, cibles et association . . . . . . . . . . . .
11.1.1 Association une cible nomme . . . . . . .
11.1.2 Association une cible dynamique anonyme .
11.2 Pointeurs sur des tableaux . . . . . . . . . . . . . . .
11.3 Tableaux de types drivs contenant des pointeurs .
11.4 Pointeurs de procdures . . . . . . . . . . . . . . . .
11.5 Manipulation de listes chanes . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
118
118
119
120
121
123
126
126
12 Inter-oprabilit avec le C
12.1 Interoprabilit des types intrinsques . . . . . . . . . . . . . . . . . . . . .
12.2 Inter-oprabilit des types drivs . . . . . . . . . . . . . . . . . . . . . . . .
12.3 Inter-oprabilit avec les pointeurs du C . . . . . . . . . . . . . . . . . . . .
12.4 Inter-oprabilit des procdures . . . . . . . . . . . . . . . . . . . . . . . . .
12.4.1 Le passage par copie de valeur (value) . . . . . . . . . . . . . . . . .
12.4.2 Exemple : appel de fonctions C depuis le fortran . . . . . . . . . . .
12.4.3 Exemple : appel de sous-programmes fortran depuis le C . . . . . . .
12.5 Inter-oprabilit des tableaux . . . . . . . . . . . . . . . . . . . . . . . . . .
12.5.1 Exemple : fonctions C manipulant des tableaux dfinis en fortran . .
12.5.2 Exemple : fortran manipulant des tableaux dynamiques allous en C
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
129
129
130
130
130
131
131
132
133
133
135
.
.
.
.
.
.
.
.
.
.
.
.
.
138
138
140
140
142
143
144
144
145
145
146
147
148
149
A Procdures intrinsques
A.1 Fonctions numriques de base . . . .
A.2 Conversion, arrondi et troncature . .
A.3 Gnrateur pseudo-alatoire . . . . .
A.4 Reprsentation des nombres . . . . .
A.5 Fonctions oprant sur des tableaux .
A.6 Manipulation de bits . . . . . . . . .
A.7 Divers . . . . . . . . . . . . . . . . .
A.8 Pointeurs . . . . . . . . . . . . . . .
A.9 Accs lenvironnement fortran . . .
A.10 Accs lenvironnement systme . .
A.11 Excution dune commande systme
A.12 Gestion du temps . . . . . . . . . . .
A.13 Caractres et chanes de caractres .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
153
154
154
154
155
155
155
155
156
156
157
157
158
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
160
160
160
161
161
161
162
162
163
164
164
164
164
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
165
165
165
166
167
167
167
168
168
169
170
171
171
172
172
173
173
.
.
.
.
.
.
.
.
.
.
.
.
Bibliographie
174
Index
179
Chapitre 1
Introduction
1.1
Historique du fortran
CHAPITRE 1. INTRODUCTION
La nouvelle norme fortran 2008 constitue une volution mineure 4 par rapport au fortran 2003
avec notamment la notion de sous-module, des outils de programmation parallle (en particulier
les tableaux distribus, ou coarrays 5 ), la notion de bloc avec ses variables locales, de nouvelles
fonctions mathmatiques intrinsques... Le document final du standard fortran 2008 (Metcalf
et al. (2011)) a t approuv 6 en septembre 2010. Les discussions sur le prochain standard (fortran
2015) sont en cours 7 .
1.2
Outre lanalyse de lalgorithme, la mise en uvre dun programme en fortran comporte essentiellement quatre phases, schmatises ci-contre dans le cas dun seul fichier source 8 :
(1) dition
vi essai.f90
?
fichier source
essai.f90
(2) compilation
gfortran -c essai.f90
?
fichier objet
essai.o
fichier excutable
essai.x
(4) excution
essai.x
?
Seul le fichier source est portable dune machine une autre, condition quil respecte un
standard du langage. Le fichier objet est une traduction en langage machine de bas niveau des
instructions du fichier source. Pour constituer le fichier excutable, il faut rsoudre les appels
des fonctions intrinsques du langage et ventuellement dautres bibliothques : cest le rle de
lditeur de liens, ld, daller extraire des bibliothques les codes objets des procdures appeles
pour les agrger au fichier objet compil, de faon constituer le fichier excutable, en principe
autonome. Les fichiers objets et le fichier excutable sont des fichiers binaires spcifiques de la
machine et du compilateur utilis.
4. Voir la prsentation des apports de fortran 2008 ftp://ftp.nag.co.uk/sc22wg5/N1851-N1900/N1891.pdf par
John Reid.
5. Les coarrays sont dj implments sous le compilateur g95.
6. La dernire version en discussion : ftp://ftp.nag.co.uk/sc22wg5/N1801-N1850/N1830.pdf du standard 2008
ntant plus disponible, on peut consulter celle daot 2009 : ftp://ftp.nag.co.uk/sc22wg5/N1751-N1800/N1791.pdf
7. Voir le projet de norme fortran 2015 publi en mai 2014 : ftp://ftp.nag.co.uk/sc22wg5/N2001-N2050/N2014.
pdf
8. Le cas plus raliste de plusieurs fichiers sources est abord en 1.2.4, p. 5 et dtaill dans le contexte des modules
en 6.4, p 64 avec notamment la Fig. 6.1, p. 66.
Les erreurs...
Si certaines erreurs peuvent tre dtectes lors de la compilation (essentiellement les erreurs
de syntaxe), voire lors de ldition de liens, dautres peuvent ne se manifester que dans la phase
dexcution (run-time errors) : elles devront tre corriges en reprenant le processus la phase (1),
ldition des programmes source.
N.-B. : il est vivement conseill de corriger les erreurs diagnostiques par le compilateur dans
lordre dapparition, car une premire erreur 9 peut en induire une quantit dautres 10 dans la suite
du programme (par exemple quand elle porte sur une dclaration de variable).
1.2.1
Nimporte quel diteur de texte peut permettre la saisie des programmes sources, qui sont des
fichiers texte. Mais certaines fonctions de lditeur seront particulirement utiles pour diter un
langage structur comme le fortran. Par exemple, sous lditeur vi, la cohrence des parenthses
ventuellement embotes peut tre vrifie par la simple frappe de la touche % qui, si le curseur est
plac sur un dlimiteur ouvrant, le dplace sur le dlimiteur fermant associ, et rciproquement.
Certains diteurs de texte sont dits sensibles au langage , dont la syntaxe est dcrite par
lintermdiaire de fichiers spcifiques. Parmi ces diteurs intelligents , citons emacs et xemacs,
gedit, kedit et la version vim 11 (vi improved) de lditeur vi disponible sous linux.
Ils sont alors capables de reprer les commentaires, les chanes de caractres, de reconnatre
les mots-clefs du langage, ses structures de contrle, ses fonctions intrinsques, et dautoriser leur
saisie abrge. La structure syntaxique du fichier source peut alors tre mise en vidence par lusage
de couleurs spcifiques, ce qui constitue une aide prcieuse pour contrler la syntaxe ds la phase
ddition.
Les diteurs emacs et xemacs possdent un mode fortran 90 12 activ automatiquement au
vu du suffixe (extension) du fichier dit. Dans ce mode, il est possible de lancer une compilation
depuis lditeur, dindenter automatiquement les structures... La prsentation syntaxique du fichier
source est elle-mme configurable : par exemple, le degr de marquage syntaxique est ajustable
sur 4 niveaux et laffichage des mots-clefs peut tre bascul de minuscules en majuscules, ou en
minuscules avec linitiale en capitale.
Un fichier source lmentaire ne comportant quun programme principal dbute par linstruction
PROGRAM, suivie du nom du programme et se termine par END PROGRAM, suivi du mme nom. Par
exemple, le programme suivant nomm bienvenue permet dafficher le message Bonjour.
PROGRAM bienvenue
WRITE(*,*) "Bonjour"
END PROGRAM bienvenue
1.2.2
CHAPITRE 1. INTRODUCTION
loption -o suivie dun nom de fichier permet de spcifier le nom du fichier produit par le
compilateur 13 , que ce soit un fichier objet (dans le cas o lon utilise aussi loption -c) ou
un fichier excutable si ldition de liens est lance.
B
<essai >.f90
-lnrecip
les options de type -O<n >, o <n > est un entier, contrlent loptimisation du code. Plus <n >
est lev, plus le code peut sexcuter rapidement, mais les optimisations fortes ne sont pas
forcment sres. Il est conseill de commencer la mise au point dun code avec loption -O0.
Dans la mise au point des programmes, il est recommand dutiliser toute la puissance du
compilateur pour dtecter ds la compilation les erreurs ou les fragilits dun code. En choisissant
les options adquates, on lui demandera la plus grande svrit et le maximum de diagnostics.
On exploitera en particulier les avertissements (warnings) qui bien souvent dtectent des sources
derreur potentielles qui ne se manifestent quau moment de ldition de liens ou, pire, de lexcution
(les messages derreur produits sont alors plus difficiles interprter).
Bibliothques et excutables statiques ou dynamiques
On doit aujourdhui distinguer deux sortes de bibliothques et deux sortes dexcutables :
Les bibliothques statiques, de suffixe .a, sont des archives de fichiers objets, cres avec la
commande ar 15 .
Elles permettent deffectuer une dition de liens statique, avec loption -static du compilateur et de lditeur de liens, afin de crer des excutables autonomes 16 .
Les bibliothques dynamiques partageables, de plus en plus souvent adoptes, de suffixe .so
(shared object).
Elles permettent deffectuer (par dfaut) une dition de liens dynamique, et de crer des
excutables beaucoup moins volumineux, pour lesquels lagrgation des objets est diffre
au moment de lexcution. Les excutables dynamiques ne sont donc plus autonomes et
ncessitent la prsence des bibliothques dynamiques 17 lors de lexcution.
En pratique, fortran dispose dune bibliothque intrinsque, dont lemplacement est connu du
compilateur : cest pourquoi on charge gnralement le compilateur dappeler lditeur de liens ld
en lui indiquant le chemin de la bibliothque fortran 18 .
13. En labsence de loption -o, le fichier objet est nomm en substituant le suffixe .o au suffixe du fichier source
et le fichier excutable est nomm a.out
14. On insrera si ncessaire, avant loption -l, le chemin daccs la bibliothque, -L<rep > si elle nest pas place
dans un des rpertoires scruts par dfaut lors de sa recherche.
15. La commande ar est similaire tar : elle permet de crer des archives de codes objets, de les mettre jour,
dextraire les objets des bibliothques, den afficher la liste.... Par exemple, on peut afficher la liste des objets dans
la bibliothque intrinsque de gfortran par la commande :
ar -t /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgfortran.a dans laquelle on va trouver par exemple les diffrentes fonctions mathmatiques spcifiques des rels sur 4, 8, 10 et 16 octets de la fonction gnrique sin :
_sin_r4.o,_sin_r8.o, _sin_r10.o,_sin_r16.o.
16. Ldition de liens statique est en particulier ncessaire sil on souhaite gnrer un excutable destin une
machine (de mme architecture) o fortran nest pas install.
17. On peut afficher la liste des bibliothques dynamiques dont dpend un excutable via la commande ldd.
18. De plus, comme les fonctions mathmatiques usuelles sont dans la bibliothque intrinsque du fortran, il nest
pas ncessaire de la mentionner avec loption -l si ldition de liens est lance par le compilateur fortran. Il faudrait
au contraire la rfrencer explicitement si on faisait ldition de liens avec un compilateur C, par exemple dans le
cas des codes mixtes en C et fortran (cf. chap. 12, p. 129).
1.2.3
Excution
Le fichier excutable 19 sappelle par dfaut a.out. On peut aussi spcifier son nom lors de la
compilation par loption -o <fichier_excutable >. Ce fichier excutable se comporte comme
une commande du systme dexploitation, lance en tapant a.out 20 par exemple. En particulier,
sous unix, ses flux dentre, de sortie et derreur standard (cf. 5.2.1, p. 38) peuvent tre redirigs
vers des fichiers ou dautres commandes. De mme, comme pour les autres processus, linterruption
en cours dexcution est possible en frappant ^C.
Dbogueur
Dans la phase de mise au point et de recherche derreurs, on peut tre amen excuter le
programme sous le contrle dun dbogueur (debugger) pour analyser en dtail son comportement,
notamment le contenu des mmoires o sont stockes les variables et le cheminement dans les
instructions. Pour cela, il est ncessaire de compiler le programme avec loption -g pour produire
un excutable spcifique que pourra lancer le dbogueur.
Par exemple, sur les systmes o le compilateur gcc est install, le dbogueur gdb est disponible
et peut analyser des codes compils avec gfortran ou g95. Aprs avoir lanc le dbogueur, on peut
placer des points darrt (breakpoints) dans le programme source avant de le lancer sous son contrle.
Il est alors possible dexaminer des variables et mme de les modifier avant de relancer lexcution
pas pas ou jusquau prochain point darrt... Des interfaces graphiques de gdb sont disponibles,
notamment ddd.
1.2.4
Ds quune application est un peu importante, elle fait appel plusieurs procdures (sousprogrammes ou fonctions) quil est souvent prfrable de stocker dans des fichiers distincts,
condition quil sagisse de procdures externes (cf. 6.3.2, p. 63). Dans ce cas, on peut procder
la compilation spare des sous-programmes et fonctions, produisant ainsi des fichiers objets (que
lon pourra ventuellement rassembler dans une bibliothque personnelle).
gfortran -c <subpr1 >.f90
<subpr2 >.f90
Puis on lance la compilation du programme principal et ldition de liens en fournissant au compilateur le fichier source du programme principal et la liste des fichiers objets produits par la
compilation prcdente.
gfortran <principal >.f90
<subpr1 >.o
<subpr2 >.o
Mais on verra (cf. 6.4, p. 64) quil est prfrable dintgrer les procdures dans des modules :
la compilation dun module produit, en plus du fichier objet, un fichier de module dextension
.mod permettant de stocker des informations (notamment les interfaces des procdures compiles 21 )
utiles pour compiler ultrieurement dautres procdures qui leur font appel : grce linstruction
USE portant sur ce module, elles pourront acqurir la visibilit sur linterface des procdures du
module (cf. Figure 6.1, p. 66). On notera que ces fichiers de module ne sont pas portables : ils
dpendent du compilateur et ventuellement de sa version.
Enfin, dans le cas o on fait appel une bibliothque constitue de modules pr-compils, il
faut ventuellement indiquer au compilateur dans quel rpertoire trouver les fichiers de module
associs la bibliothque grce loption -I<mod_rep > 22 .
19. Sous unix, lattribut excutable est automatiquement positionn par lditeur de liens lors de la cration de
ce fichier. Lappel la commande chmod nest donc pas ncessaire.
20. Cela suppose que le rpertoire o se situe lexcutable fasse partie des chemins contenus dans la variable denvironnement PATH sous unix. Sinon, il faut prciser le chemin daccs, en lanant par exemple ./a.out si lexcutable
est dans le rpertoire courant.
21. Ces fichiers jouent un rle comparable aux fichiers dentte du langage C.
22. Comme pour les fichiers inclure par le prprocesseur.
CHAPITRE 1. INTRODUCTION
Loutil make
La maintenance (gnration et mise jour) dapplications sappuyant sur plusieurs fichiers
source et ventuellement des bibliothques peut tre automatise par des outils comme lutilitaire
make sous unix.
La commande make permet dautomatiser la gnration et la mise jour de cibles (target), en
gnral un fichier excutable, qui dpendent dautres fichiers, par exemple les fichiers sources, en
mettant en uvre certaines rgles (rules) de construction, constitues de commandes unix.
Elle sappuie sur un fichier makefile qui liste les cibles, dcrit larbre des dpendances et les
rgles de production des cibles. Pour plus dtails, on pourra consulter la documentation en ligne
de gnumake : http://www.gnu.org/software/make/manual/make.html.
Les compilateurs g95 et gfortran 23 possdent une option permettant daider lcriture des
dpendances aprs une compilation effectue la main :
gfortran -M <fichier.f90 > affiche les dpendances du fichier <fichier.o >.
1.3
1.3.1
,
<
+
.
>
:
%
=
;
!
*
'
&
(
"
$
)
/
?
Noter que le caractre de tabulation (qui pourrait faciliter lindentation du code) nest pas autoris
dans les fichiers source fortran, mme si plusieurs compilateurs se contentent de produire un avertissement en rencontrant une tabulation. Il est donc prudent de configurer les diteurs de faon
traduire chaque tabulation en un nombre despaces adquat ; si ncessaire, on peut utiliser le filtre
unix expand pour effectuer cette conversion a posteriori.
f2003
Les crochets carrs [ et ] peuvent tre utiliss comme dlimiteurs dans les constructeurs de tableaux
monodimensionnels (cf. 7.1.3, p. 81).
23. Sous gfortran, loption -M nest disponible qu partir de la version 4.6.
24. Le langage C comporte plus de caractres avec les dlimiteurs (accolades {}, crochets []), la contre-oblique \,
les oprateurs %, ~, ^ et |. Le caractre # est en fait interprt par le prprocesseur qui peut agir aussi bien sur un
programme en C que sur un programme en fortran.
1.3.2
Les objets (variables, procdures et units de programme) sont identifis laide de mots commenant par une lettre et constitus en fortran 95 dau plus 31 caractres alphanumriques 25 (plus
le soulign _ qui permet un pseudo-dcoupage des noms en mots). Le nombre de caractres f2003
des identificateurs est port 63 en fortran 2003. Noter quil nexiste quun seul espace de noms
en fortran : il est en particulier interdit dutiliser le mme identifiant pour une variable et un programme ou une procdure et un module. Contrairement dautres langages (notamment le C et
unix), le fortran ne distingue pas majuscules et minuscules en dehors des chanes de caractres.
N.-B. : pour des raisons de lisibilit, il est videmment dconseill den profiter pour introduire
des variantes dans lorthographe des identificateurs, nommant successivement par exemple une
mme variable TOTAL, puis total quelques lignes plus loin. On prconise linverse de rserver les
capitales pour les mots clefs du langage 26 et dcrire les identificateurs dfinis par lutilisateur en
minuscules, ou ventuellement avec les initiales en majuscules pour mettre en vidence les mots
dans les noms des objets, comme par exemple dans TotalPartiel.
Dautres conventions sont possibles, (consulter par exemple Clerman et Spector (2011) pour
les questions de style) sachant que les mots-clefs du langage seront mis en vidence par colorisation
lors de ldition. Lessentiel est de se tenir une rgle prcise tout au long du programme.
1.4
Pour des raisons de compatiblit ascendante, les compilateurs fortran 90 acceptent deux formats
pour les fichiers sources :
le format fixe (fixed format) qui est celui du fortran 77 (lui-mme hrit des contraintes
imposes par les cartes perfores), avec deux extensions ;
le format libre (free format), qui permet une criture plus souple du code source, et est
fortement prconis 27 pour les programmes nouveaux.
Ces deux formats sont incompatibles et le compilateur doit tre inform (soit au vu du suffixe du
nom de fichier, soit grce une option, cf. annexe E) du format choisi dans les fichiers sources
qui lui sont soumis. Lutilisation conjointe de sources aux deux formats est possible en compilant
sparment (cf. 1.2.4, p. 5) les fichiers sources au format fixe, puis ceux au format libre, et en
assemblant ensuite les objets.
1.4.1
Format fixe
En format fixe, les instructions peuvent stendre de la colonne 7 jusqu la colonne 72.
Au-del de la colonne 72, les caractres ne sont pas pris en compte comme instruction par B
un compilateur standard 28 ;
Une ligne de commentaire peut tre introduite grce au caractre C plac en premire colonne.
Une ligne ne peut contenir quune instruction, mais une instruction peut stendre sur plusieurs lignes en plaant un caractre quelconque, mais diffrent de 0 et dun blanc en colonne 6
des lignes de continuation. Toutefois, la coupure de ligne ne peut pas se faire lintrieur
dune chane de caractres dlimite par des "..." ou des '...'.
En dehors dune ligne de commentaires, les colonnes 2 5 sont destines des tiquettes
numriques permettant de reprer certaines instructions (pour les formats, les branchements
ou les boucles).
25. En fortran 66 standard, la norme ne diffrenciait que les six premiers caractres. Heureusement, la plupart des
compilateurs sont plus tolrants ce qui permet de choisir des identificateurs plus vocateurs.
26. Rappelons que certains diteurs (Language Sensitive Editors), tels quemacs (cf. 1.2.1, p. 3), permettent de
basculer globalement la prsentation des mots-clefs du fortran entre minuscules, majuscules ou capitalisation des
initiales.
27. Le format fixe est dj obsolescent en fortran 95.
28. Sur les cartes perfores, o chaque carte reprsentait une ligne de code, ces colonnes permettaient dindiquer
des commentaires, voire de numroter les cartes pour pouvoir les reclasser en cas de chute du paquet de cartes qui
constitue maintenant un fichier. Cependant, en utilisant certaines options des compilateurs (parfois actives par
dfaut), les colonnes de 73 80 (ou 132) peuvent tre interprtes comme des instructions.
CHAPITRE 1. INTRODUCTION
Dans la partie instruction de la ligne et hors chane de caractres, les blancs ne sont pas
significatifs : dune part, ils ne sont pas ncessaires pour sparer les mots-clefs entre eux ou
des identifiants, mais on peut aussi insrer des blancs lintrieur des mots-clefs, des noms
de variables et des constantes numriques. Utiliser ces facilits est fortement dconseill,
dautant que les blancs sont significatifs en format libre ; mais il est bon de les connatre pour
dcrypter certains codes en format fixe qui les exploitaient 29 .
Les deux extensions suivantes au format du fortran 77 dfinissent le format fixe du fortran 90 :
en plus de C, les caractres c, * et ! placs en premire colonne sont considrs comme
introducteurs de commentaire.
une ligne peut contenir plusieurs instructions, condition quelles soient spares par des
; (points-virgules).
C
exemple d'extrait de fichier source fortran au format fixe
C
C2345678901234567890123456789012345678901234567890123456789012345678901234567890
C
1
2
3
4
5
6
7
8
C
||||||||
SOMME = TERME_1 +
1
TERME_2 +
1
TERME_3
C
dbut de la boucle
DO 100 I = 1, N
DEBUT
K = K + I
100 CONTINUE
FIN
C
fin de la boucle
1.4.2
prfrer =
Les caractres ! et & perdent leur interprtation spciale lorsquils sont situs lintrieur
dune chane de caractres (entre "..." ou entre '...'). Mais, dans le cas o la chane nest
pas ferme en fin de ligne, un & en dernier caractre non blanc est interprt comme indiquant
que la fin de ligne ne termine pas linstruction. Le nombre maximum de lignes sur lesquelles
peut stendre une instruction est limit 40 en fortran 95 (39 lignes de suite), et 256 en f2003
fortran 2003 (255 lignes de suite).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
PROGRAM essai
!
exemple de source fortran 90 au format libre
IMPLICIT NONE
REAL :: somme, terme_1 = 1., terme_2 = 2., terme_3 = 3.
!
! une instruction longue scinde en plusieurs lignes
somme = terme_1 + &
! description du premier terme
terme_2 + &
! description du deuxime terme
terme_3
! description du troisime terme
! cas o la coupure se fait au sein d'une chane de caractres
WRITE (*,*) ' chane de caractres comportant plusieurs lignes dans &
&le programme source'
!
ce & est obligatoire pour marquer la continuation de la chane
END PROGRAM essai
Lordre dcriture suivant
WRITE (*,*) 'chane avec des & et des ! normaux et deux &&
& spciaux' ! suivie d'un commentaire
affichera sur une seule ligne :
chane avec des & et des ! normaux et deux & spciaux
Les blancs Noter que les espaces sont significatifs en format libre. En particulier, en labsence
de sparateur (virgule, parenthse...), un blanc est obligatoire pour dlimiter deux mots-clefs. Mais
lespace est facultatif dans certains cas, comme ELSEIF, DOUBLEPRECISION, INOUT, SELECTCASE,
ainsi que pour toutes les fins de structures introduites par END : ENDIF, ENDDO, ...
Interposer des espaces permet damliorer la lisibilit du code, avec par exemple les rgles
suivantes (cf. Clerman et Spector (2011)), en veillant maintenir une prsentation homogne
dans tout le code :
mettre en retrait (indent) les blocs (structures de contrle, dclaration de types drivs,
interfaces, ...), sans utiliser de tabulation (cf. 1.3.1, p. 6) et avec toujours le mme nombre
despaces (2 ou 4 suffisent, mais choisir 8 espaces provoquerait des retraits trop importants
pour les structures imbriques) ;
entourer dune espace le signe = daffectation dans les expressions ;
entourer dune espace les oprateurs de lopration principale des expressions ;
ajouter une espace aprs la virgule, et seulement aprs, dans les listes (attributs, arguments
des procdures, objets lors de la dclaration, ...).
Chapitre 2
2.2
Les entiers sont reprsents en mmoire de faon exacte, donc sans perte de prcision, mais leur
domaine est limit par le nombre de bits choisi pour les reprsenter.
Au contraire, les rels ne peuvent pas, en gnral, tre reprsents exactement en mmoire :
cest pourquoi on vitera les tests dgalit sur les rels ; cest aussi ce qui explique limpossibilit
dappliquer des expressions relles des tests de type numration de valeurs 2 .
On verra en particulier que lcart entre deux rels successifs assez grands ( 107 ) peut dpasser
1 : il est donc extrmement dconseill de compter en utilisant des variables de type rel.
Pour plus de dtail sur la reprsentation des nombres et limplmentation des oprations arithmtiques, on consultera le chapitre 9 Arithmtique des ordinateurs de Stallings (2003).
2.2.1
Si la reprsentation la plus connue des entiers positifs est celle de la base 10 (qui utilise 10
symboles de 0 9), la plupart des ordinateurs utilisent une reprsentation en base 2 ne ncessitant
que 2 symboles (0 et 1) ; en reprsentation binaire, lquivalent du chiffre de la reprsentation
1. En fortran, un caractre est stock dans une chane de type CHARACTER et de longueur 1, contrairement ce
qui se passe en langage C, o seul le type caractre est natif et les chanes ne sont que des tableaux de caractres.
2. select case en fortran ou switch ... case en C.
10
11
dcimale est le bit. La reprsentation en octal (base 8) utilise les 8 symboles de 0 7 alors que la
reprsentation hexadcimale 3 (base 16) utilise 16 symboles : 0,1, ..., 9, A, B, ...F.
Reprsentation des entiers positifs
La reprsentation des entiers positifs utilise des codes poids, dont les poids sont les puissances
successives de la base b ; soit, avec q coefficients :
n=
q1
X
p i bi
o 0 6 pi < b
(2.1)
i=0
Rciproquement, les coefficients pi peuvent tre obtenus par des divisions entires successives par b :
p0 , coefficient de plus faible poids, est le reste de la division de n par b ;
p1 le reste dans la division par b2 ; ...
Dans le cas o b = 2, chaque coefficient pi peut tre reprsent par un bit. Par exemple, pour
lentier 13 :
13 = 1 101 + 3 100
13 = 1 2 + 1 2 + 0 21 + 1 20
3
Si on consacre q bits la reprsentation dun entier positif, on peut couvrir le domaine [0, 2q 1].
Reprsentation des entiers ngatifs
Les entiers ngatifs sont reprsents habituellement avec le symbole complmentaire quil
va falloir traduire en codage binaire par un bit complmentaire appel bit de signe.
En binaire, un entier relatif est donc reprsent sur q + 1 bits. On choisit de coder le signe sur
le bit de plus fort poids avec 0 pour les entiers positifs et 1 pour les ngatifs. Mais si on codait
simplement la valeur absolue en binaire de n sur les q bits restants, une opration arithmtique
lmentaire comme laddition entre entiers de signes diffrents ne seffectuerait pas comme celle de
deux entiers de mme signe.
On choisit au contraire de reprsenter lentier n ngatif par un bit de signe 1 suivi des bits du
complment 2q+1 de |n|, cest--dire ceux de lentier positif 2q+1 |n|. On parle alors (abusivement)
de complment deux, obtenu en inversant tous les bits puis en ajoutant 1 avec perte de la retenue.
Larithmtique entire ainsi mise en uvre fonctionne modulo 2q+1 . Le domaine couvert va donc
de 2q 2q 1 (voir par exemple 2.2.3, p. 15). Par exemple, les entiers cods sur 8 bits, soit 1 octet
(q = 7) couvrent le domaine 27 = 128 27 1 = +127 (cf. Fig 2.1 et Table 2.1) :
+28 1
+0
+1
+0
+1
28
n<0
+26
+27 + 1
+27 1
+27
+127
+129
+128
n>0
+26
27 + 1
+27 1
27
+127
127
128
Figure 2.1 Entiers positifs ( gauche) et entiers relatifs ( droite) sur 8 bits : pour passer des
positifs aux relatifs, on soustrait 28 dans la partie gauche (pointille) du cercle. La discontinuit
initialement en haut gauche de 0 pour les positifs, se retrouve en bas entre +127 et 128.
3. La base 16 a t utilise sur certains calculateurs ibm.
12
n
128
127
...
1
0
+1
...
+127
signe
26
25
24
23
22
21
20
1
1
...
1
0
0
...
0
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
0
...
1
0
1
...
1
0
1
...
1
Traditionnellement, comme en dcimal, on range les bits par poids dcroissant, le plus fort poids
gauche. Mais des variantes dans lordre de stockage 4 des octets ou des groupes de deux octets
existent : on distingue les conventions little-endian o les octets de poids fort sont stocks en fin et
big-endian o les octets de poids fort sont stocks en tte.
2.2.2
Si on codait les rels en virgule fixe 5 , la prcision absolue de la reprsentation serait fixe ; mais
la prcision relative dpendrait de lordre de grandeur. Pour conserver une prcision relative plus
indpendante de lordre de grandeur, cest--dire pour travailler avec un nombre fixe de chiffres
significatifs, on prfre une reprsentation en virgule flottante 6 , avec une mantisse, reprsentant la
partie fractionnaire et un exposant qui fixe lordre de grandeur (cf qu. 2.2, p. 13).
Par exemple en base 10, avec 4 chiffres aprs la virgule, on peut comparer dans la table 2.2,
p. 13, les deux reprsentations approches (obtenues, pour simplifier, par troncature et non par
arrondi) : on constate quen virgule fixe, plus les valeurs sont petites, moins on conserve de chiffres.
4. On peut faire lanalogie avec les modes dcriture de la date suivant les pays qui diffrent notamment par
lordre entre le jour, le mois et lanne.
5. On peut, pour simplifier, envisager le cas de la base dcimale, et faire lanalogie avec le format F en fortran ou
%f en C, avec un nombre fixe de chiffres aprs la virgule.
6. Pour poursuivre la comparaison, cela correspond la notation exponentielle en format E en fortran ou %e en C
13
nombre exact
0.0000123456789
0.000123456789
0.00123456789
0.0123456789
0.123456789
1.23456789
12.3456789
123.456789
1234.56789
0.1234
0.1234
0.1234
0.1234
0.1234
0.1234
0.1234
0.1234
0.1234
.0000
.0001
.0012
.0123
.1234
1.2345
12.3456
123.4567
1234.5678
104
103
102
101
100
101
102
103
104
q
X
(2.2)
pi bi
i=1
o
s = 1 est le signe ;
e est un entier qualifi dexposant ;
la partie fractionnaire m est la mantisse.
Mais cette reprsentation nest pas unique. Afin de choisir parmi les combinaisons de mantisse et
dexposant, on impose que la mantisse soit comprise entre 1/b inclus 7 et 1 exclus soit p1 6= 0. Par
exemple en dcimal, 1,234 101 peut scrire 0,1234 100 ou 0,01234 101 : on exclut donc la
deuxime combinaison.
Chaque variante du type rel (dtermine via le paramtre KIND) est caractrise par :
un nombre q de symboles (chiffres dcimaux en base 10 et bits en base 2) de la mantisse qui
fixe la prcision relative des rels ;
un nombre de symboles pour lexposant qui fixe le domaine de valeurs couvert.
Dans cette reprsentation, en dcimal, les rels en virgule flottante sont rpartis en progression
arithmtique dans chaque dcade avec un nombre fixe de valeurs par dcade et un pas multipli
par 10 chaque changement de dcade. En binaire, cest dans chaque octave (intervalle de type
[2p , 2p+1 [) quils sont en progression arithmtique avec un nombre n = 2q1 de valeurs par octave ;
le pas double chaque changement doctave (cf. Annexe C, p. 154 sur le codage ieee).
2
+0
1/4
MIN
chelle log
1/2
+1
+2
+4
MAX
une octave (n valeurs)
chelle linaire ( exposant fix)
Figure 2.2 Reprsentation des rels positifs en virgule flottante base 2 : domaine en chelle log.
Seules sont reprsentes ici les puissances exactes de 2 lorsque lexposant est incrment mantisse
fixe. Le nombre de bits de lexposant dtermine le domaine couvert. Le zoom sur une octave,
exposant fix, est, lui, en chelle linaire (cf. Fig. 2.3, p. 14).
7. Si la mantisse est infrieure 1/b, on perd des chiffres significatifs, mais, exposant fix, cela permet de
reprsenter des nombres plus petits qualifis de dnormaliss (cf. C.2.2, p. 155).
14
X(1 + (n 1))
X = 2p
X(1 + 2)
X(1 + )
X/2
X/2
X/2 = nX/2
X = X/n = X
2X
chelle linaire
X = nX
Figure 2.3 Reprsentation en virgule flottante base 2 : deux octaves en chelle linaire. X =
X est le pas dans loctave [X, 2X[ qui comporte n = 2q1 intervalles, o q est le nombre de bits
de la mantisse (avec le 1er bit 1), qui dtermine la prcision relative de la reprsentation.
2.2.3
Les nombres tant stocks sur un nombre de bits fixe, ne sont reprsents que dans un domaine
fini. De plus, seul le type entier permet une reprsentation exacte des valeurs numriques, alors
que les nombres rels ne sont en gnral reprsents en virgule flottante quapproximativement 8 .
Fonctions dinterrogation sur le codage des types numriques
Plusieurs fonctions intrinsques permettent de caractriser globalement 9 la reprsentation du
type numrique de leur argument du point de vue :
de la base b (en gnral 2) employe dans la reprsentation (2.1) pour les entiers ou (2.2)
pour les rels du type de x : RADIX(x) ;
du nombre de digits utiliss pour le reprsenter : DIGITS(x) donne le nombre de symboles
(cest--dire de bits dans le cas usuel de la base 2) consacrs au stockage de la mantisse de x
dans le type de x. Plus prcisment :
si x est un entier, DIGITS(x) est le nombre q de bits sur lesquels lentier est stock
hors bit de signe. Il dtermine donc le domaine couvert par ce type. Dans le cas entier,
BIT_SIZE(x) rend le nombre total de bits utiliss pour le stocker (bit de signe inclus).
si x est un rel en virgule flottante, DIGITS(x) est le nombre de bits (ici q) 10 sur lesquels
est stocke sa mantisse. Il dtermine alors la prcision relative de la reprsentation de x.
du domaine couvert par un type donn :
HUGE(x), la plus grande valeur (entire ou relle) reprsentable dans le type de x.
TINY(x), la plus petite valeur absolue flottante reprsentable 11 dans le type de x.
RANGE(x) qui donne :
la puissance de 10 du plus grand entier dfini dans le type de x sil sagit dun entier :
ainsi tout entier x tel que |x| 6 10r o r est la valeur de RANGE est reprsentable
dans ce type et RANGE(x) = INT(LOG10(HUGE(x))
la plus petite des valeurs absolues des puissances de 10 du plus petit et du plus
grand des rels dans le type de x, si x est un flottant :
RANGE(x) = INT(MIN(LOG10(HUGE(x)), -LOG10(TINY(x))))
ainsi tout rel x scrivant sous la forme x= 0.????? 10k avec k entier et |k| 6 r
o r est la valeur de RANGE, est reprsentable dans ce type ;
8. Plus prcisment, ne peuvent ventuellement tre exactement reprsents que les rationnels dont le dnominateur est une puissance de la base, donc en pratique du type n/2p avec des contraintes sur n et p. Ainsi les entiers de
valeur absolue assez faible, et certains nombres rationnels de dnominateur 2p sont reprsents exactement en virgule
flottante. En revanche la majorit des nombres dcimaux, 0.1 par exemple, ne sont pas reprsentables exactement.
9. Seul le type et non la valeur de largument de ces fonctions dinterrogation a une importance.
10. Dans le cas dune mantisse normalise, son premier bit, toujours gal 1, nest pas stock (cf. C.2.1, p. 155).
Cela permet de gagner un bit, mais ce bit cach est pris en compte dans la fonction DIGITS.
11. On se limite ici aux reprsentations normalises, cf. annexe C, p. 154, sachant quil est possible de reprsenter
des valeurs absolues plus petites au prix dune perte de prcision.
15
BIT_SIZE
DIGITS
HUGE
RANGE
32
31
2147483647 = 2
64
63
9223372036854775807 = 2
31
1
63
9
1
18
DIGITS
24
53
PRECISION
6
15
EPSILON
1.192093E-7
2.220446049250313E-016
TINY
1.175494E-38
2.225073858507201E-308
HUGE
3.402823E+38
1.797693134862316E+308
12. Avec le compilateur nagfor de nag, par dfaut, les variantes de type sont numrotes en squence (option
-kind=sequential du compilateur). Mais si on prcise loption de compilation -kind=byte, les valeurs de KIND
reprsentent le nombre doctets occups par la variante de type (cf. Annexe E.2, p. 166).
16
2.3
Dclaration
Les objets doivent tre dclars en tout dbut 13 de programme, sous-programme, fonction ou
module, prcisment avant les instructions excutables, selon la syntaxe gnrale suivante :
VALUE pour le passage dargument par copie de valeur (cf. 12.4.1, p. 131)
pour les objets encapsuls dans des modules (cf. 6.4.3 p. 67) :
PUBLIC rend accessible un objet lextrieur du module courant : cest lattribut par
dfaut
PRIVATE limite la visibilit dun objet au module courant
f2003
Par dfaut, les variables numriques non dclares suivent un typage implicite dtermin par
leur initiale : les variables dont linitiale est I, J, K, L, M ou N sont des entiers et les autres des
flottants. Lordre IMPLICIT permet de modifier ventuellement cette convention. La dclaration
dune variable impose explicitement son type et prvaut sur ces conventions.
Mais, il est trs fortement conseill de sobliger dclarer toutes les variables, sans mettre en
uvre le typage implicite 14 , grce lordre IMPLICIT NONE, plac avant toutes les dclarations.
Cette contrainte permet en autres de confier au compilateur le reprage des erreurs typographiques
dans les noms de variables : si on a dclar la variable somme et que lon utilise ensuite some sans
dclaration, le compilateur va diagnostiquer une erreur. Elle oblige aussi constituer en tte de
programme une sorte de dictionnaire des variables quil est conseill de commenter et qui facilite
la lecture et la maintenance du code.
13. En fortran 2008, il est possible de dclarer tardivement des objets (comme en C89) au dbut dune structure
de bloc (BLOCK ... END BLOCK), elle mme place aprs des instructions excutables (cf. 4.4, p. 31). La porte et la
dure de vie de ces objets sont alors limites au bloc.
14. Ainsi, le comportement du fortran 90 se rapproche de celui du langage C, dans lequel toutes les variables
doivent tre dclares.
IMPLICIT NONE
CHARACTER(LEN=5)
LOGICAL
REAL
COMPLEX
::
::
::
::
17
On peut spcifier une variante de type en indiquant la valeur du paramtre KIND entre parenthses, mais cette valeur doit tre une constante :
<type >(KIND=<kind >) :: <liste_d_objets >
2.4
Les constantes
Les constantes sont des objets dont la valeur ne peut pas tre modifie lors de lexcution
du programme ; elles ne peuvent constituer le membre de gauche dune instruction daffectation.
On distingue les vraies constantes (literal constants) ou constantes non nommes dune part et les
constantes nommes dautre part (cf. 2.5.1, p. 18), qui sont values lors de la compilation. Il est
fortement conseill de nommer les constantes utilises dans un programme, pour sassurer que la
mme valeur est utilise dans tout le programme et pour simplifier un ventuel changement de
prcision dune constante flottante, voire la transformer en une variable lors dune gnralisation
du programme.
2.5
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
entier
entier
entier en binaire : 5
entier en octal : 15
entier en hexadcimal : 31
rel en notation dcimale
rel en notation dcimale
rel en notation mantisse et exposant
rel en notation mantisse et exposant
double prcision
complexe 1,5 - 2i
boolen: vrai
boolen: faux
chane de caractres dlimite par des apostrophes (')
chane de caractres dlimite par guillemets (")
chane de caractres (entre les ', seul ' est interprt)
chane de caractres (l'apostrophe est autorise entre les ")
chane de caractres (l'apostrophe double permet
d'insrer une seule apostrophe dans la chane)
chane de caractres vide
Initialisation
Il est possible dinitialiser des objets ds leur dclaration 15 , en leur affectant comme valeur des
constantes vraies du mme type 16 , par exemple
15. Une variable locale une procdure devient statique si on linitialise au moment de la dclaration, elle se
comporte donc comme si elle possdait lattribut SAVE (cf. 6.1.2, p. 58). Ce nest pas le cas en C, o linitialisation
se fait chaque appel de la fonction, sauf si on spcifie lattribut static pour la variable.
16. Veiller initialiser par exemple les variables de type DOUBLE PRECISION avec des constantes du mme type,
sous peine de perte de prcision : dans lexemple qui suit, les derniers chiffres significatifs de r nauraient pas de
18
IMPLICIT NONE
CHARACTER(LEN=5)
LOGICAL
REAL
COMPLEX
DOUBLE PRECISION
::
::
::
::
::
nom_a_5_lettres = 'dbut'
test = .TRUE. , test1 = .FALSE.
a = 0. , longueur = 1.e3
nombre_complexe = (1.,-1.)
r = 1.23456789012345d0
Mais des expressions simples, dites expressions dinitialisation peuvent aussi tre utilises pour
initialiser les variables : elles doivent pouvoir tre values par le compilateur.
IMPLICIT NONE
REAL :: longueur = 10., largeur = 2.
REAL :: surface = longueur * largeur
REAL :: pi = 4.*ATAN(1.)
REAL :: enorme = HUGE(1.e0)
f2003 Sont notamment autoriss dans les expressions dinitialisation les fonctions intrinsques lmentaires (cf. annexe A, p. 138), les fonctions intrinsques de transformation (portant sur les tableaux),
et les constructeurs de tableaux 17 (cf. 7.1.3, p. 81) et de structures (cf. 9.2.1, p. 103).
2.5.1
Pour dclarer une constante nomme, cest dire attribuer une valeur fixe la compilation
un identificateur, il faut lui adjoindre lattribut PARAMETER, et linitialiser.
IMPLICIT NONE
INTEGER, PARAMETER :: n_points = 100
REAL, PARAMETER
:: pi = 3.1416
Il nest alors plus possible de modifier la valeur de ces constantes nommes, par exemple en crivant
pi=3.15.
Les constantes entires nommes peuvent aussi tre utilises pour paramtrer les dimensions de
certains tableaux (cf. 7.5.1, p. 89), qui seront ainsi fixes au moment de la compilation 18 .
2.5.2
Les types prdfinis comportent des variantes (sous-types), notamment selon le nombre doctets
choisis pour stocker lobjet, variantes que lon peut slectionner laide du paramtre KIND.
f2008
En fortran 2008, la liste des paramtres de variantes de type a t introduite dans le standard.
ils sont dfinis dans le module intrinsque ISO_FORTRAN_ENV 19 (cf. 6.4.5, p. 69), en particulier :
les 4 variantes dentiers obligatoires nomms en fonction de leur nombre de bits INT8, INT16,
INT32, INT64 20 , ainsi que le tableau des paramtres des variantes dentiers INTEGER_KINDS
qui comporte au moins 4 lments.
sens en labsence de d0
17. En fortran 95, les fonctions intrinsques ntaient gnralement pas autorises dans les expressions dinitialisation, quelques exceptions prs, parmi lesquelles les fonctions de prcision numrique et certaines fonctions lies au
profil des tableaux, dont REPEAT, RESHAPE, SELECTED_INT_KIND, SELECTED_REAL_KIND, TRANSFER, TRIM, LBOUND,
UBOUND, SHAPE, SIZE, KIND, LEN, BIT_SIZE, HUGE, EPSILON, TINY...
Ainsi, REAL :: enorme = HUGE(1.e0) tait autoris, mais REAL :: pi = 4.*ATAN(1.) ntait pas admis en fortran 95. Ces restrictions ont t leves avec le fortran 2003.
18. En C, dclarer une variable avec lattribut const permet de diagnostiquer une ventuelle tentative de modification (erreur dtecte par le compilateur gcc depuis la version 4.0), mais ne suffit pas pour en faire une constante
nomme, susceptible par exemple de dfinir la dimension dun tableau. Pour ce faire, il faut recourir la directive
#define du prprocesseur.
19. Avant la norme 2008, le compilateur nag (cf. Annexe E.2, p. 166) fournissait un module f90_kind.f90 qui
dfinissant lensemble des variantes de type.
20. Ces types entiers dont le nombre de bits est impos sont rapprocher des entiers de taille exacte int8_t,
int16_t et int32_t du C99 dfinis via stdint.h.
2.5. INITIALISATION
19
les 3 variantes de rels obligatoires nomms en fonction de leur nombre doctets REAL32,
REAL64, REAL128, ainsi que le tableau des paramtres des variantes de rels REAL_KINDS, qui
comporte au moins 3 lments, mais parfois plus.
La norme du fortran 2008 impose donc la prsence dentiers sur 64 bits et de rels sur 128 bits 21 .
chaque type est associ un sous-type par dfaut, qui peut dpendre de la machine ; ainsi,
les types numriques prdfinis ne garantissent pas une prcision indpendante de la machine. Si
lon veut sassurer de la portabilit numrique dune dclaration, en termes de domaine (range)
couvert ou de prcision, il faut faire appel des fonctions intrinsques afin de choisir les sous-types
en fonction du domaine et de la prcision.
pour les entiers, la fonction SELECTED_INT_KIND(r) o r est un entier positif, renvoie un
entier donnant le numro de la variante du type entier qui permet de couvrir le domaine
[10+r , 10+r ]. Si aucune variante entire ne convient, cette fonction renvoie la valeur -1 ;
pour les rels, la fonction SELECTED_REAL_KIND([p][,r]) renvoie un entier donnant le numro de la variante du type rel dont la prcision est au moins p (au sens donn par la
fonction PRECISION) ou une tendue couvrant le domaine fix par r (au sens donn par la
fonction RANGE, cest dire dont la valeur absolue reste dans lintervalle [10r , 10+r ]). Si
aucune variante flottante ne convient, cette fonction renvoie une valeur ngative.
Enfin la notion de portabilit numrique reste limite par la disponibilit des variantes dans un
environnement (processeur et compilateur) donn de programmation. Un programme qui requiert
une prcision ou un domaine exigeants pourra, dans certains environnements, ne pas trouver les
variantes ncessaires pour sexcuter. Mais il existe des bibliothques qui permettent des calculs
dans des prcisions non limites par le compilateur, par exemple avec des types drivs, notamment
fmlib en fortran.
2.5.3
2.5.4
Dans le cadre dun programme sensible la prcision des rels, il est important de disposer dun
moyen rapide et portable de modifier le sous-type de tous les rels utiliss (constantes et variables),
21. Sur les processeurs ne disposant pas dunit flottante suffisante, les rels sur 128 bits, qualifis de quad, sont
simuls de faon logicielle, au dtriment des performances.
22. La variante elle-mme peut tre une constante vraie ou une constante nomme.
20
sans sappuyer sur des options de compilation (cf. E.7.2). Il suffit pour cela de dfinir la variante
de travail dans un module my_precision sous la forme dune constante nomme (wp), puis de
dclarer toutes les variables relles dans ce sous-type. Noter quil faut aussi exprimer toutes les
B constantes relles dans ce sous-type et spcifier le paramtre optionnel KIND=wp dans les fonctions
o la gnricit ne suffit pas assurer un calcul dans le sous-type voulu. Sachant que les sous-types
rels courants utilisent 32, 64 ou 80 bits, on pourra dfinir les paramtres de type associs (sp, dp,
edp) dans un module prliminaire real_precisions et faire le choix (ligne 11) par renommage via
=> dans le USE (cf. 6.4.3). Cest une mthode largement utilise par les bibliothques.
1
2
3
4
5
6
7
MODULE real_precisions
IMPLICIT NONE
! les differentes variantes de reels disponibles (g95/gfortran)
INTEGER, PARAMETER :: sp=SELECTED_REAL_KIND(p=6)
! simple precision 32 bits
INTEGER, PARAMETER :: dp=SELECTED_REAL_KIND(p=15) ! double precision 64 bits
INTEGER, PARAMETER :: edp=SELECTED_REAL_KIND(p=18) ! extra double precision 80
END MODULE real_precisions
8
9
10
11
12
13
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2.6
Fortran possde de nombreuses fonctions de conversion (explicite) entre les types numriques et
leurs variantes, fonctions dcrites dans lannexe A.2, p. 140. En particulier, la conversion implicite
dentier en flottant est assure par REAL et celle de flottant en entier par INT qui tronque vers zro,
mais dautres choix sont possibles pour les conversions explicites : au plus proche avec NINT, par
excs avec CEILING, par dfaut avec FLOOR.
Ces fonctions de conversion numrique admettent un paramtre optionnel de KIND qui permet
de prciser la variante de type du rsultat.
Chapitre 3
Oprateurs et expressions
3.1
Outre loprateur unaire - qui calcule loppos dun nombre 1 , le fortran dispose des quatre
oprateurs binaires daddition (+), de soustraction (-), de multiplication (*) et de division (/).
Ces quatre oprateurs binaires sont prvus pour travailler avec des oprandes de mme type (et
mme sous-type).
Mais le fortran 2 possde aussi un oprateur dlvation la puissance, not ** et qui est dfini
diffremment suivant la nature de lexposant :
si n est entier positif, a**n est dfini pour tout a rel ou entier par le produit de n facteurs
a a a (lexposant nest pas converti en rel) ;
si n est entier ngatif, a**n est dfini comme 1/a**(-n) ;
si x est rel, a**x nest dfini que si a est strictement positif et vaut alors exp(x ln(a))
Ainsi, pour lever un nombre une puissance entire positive, il faudra viter dutiliser un exposant
rel, comme par exemple dans a**4., qui forcerait lutilisation de la deuxime mthode, moins
prcise numriquement et plus coteuse.
3.1.1
Quand lordre dvaluation nest pas impos par lutilisation de parenthses, les expressions
numriques sont values en respectant lordre de priorit suivant : (1) ** (2) * et / (3) + et -.
niveau de priorit gal et en labsence de parenthses, les valuations seffectuent en principe de
gauche droite, sauf pour loprateur **, pour lequel lvaluation se fait de droite gauche pour
c
c
respecter linterprtation classique de la notation mathmatique ab = a(b ) .
expression
value comme
a + b ** c / d / e
a + ( ( (b**c) / d ) / e )
a ** b ** c * d + e
( ( a ** (b**c) ) * d ) + e
cest--dire
bc /d
a+
e
bc
a d+e
Mais un compilateur peut sautoriser de modifier cet ordre, par exemple pour des raisons de
rapidit de calcul. Ainsi a/b/c est a priori valu comme (a/b)/c , mais si le compilateur
optimise la vitesse de calcul et considre que le processeur est plus rapide pour effectuer une
multiplication quune division, il pourra demander dvaluer dans lordre a/(b*c) .
3.1.2
Les oprations associatives algbriquement peuvent savrer non associatives sur ordinateur B
cause :
1. + peut aussi tre utilis comme oprateur unaire.
2. Contrairement au langage C, qui doit faire appel la fonction pow.
21
22
De mme, quand on doit parcourir un intervalle pas constant avec une variable relle x dans
une boucle DO avec compteur 4 , le calcul par addition qui accumule les erreurs darrondi doit tre
vit au profit du calcul par multiplication.
x = xmin - dx
DO i=1, n
x = x + dx
END DO
3.1.3
DO i=1, n
x = xmin + REAL(i-1) * dx
END DO
Conversions implicites
Lors de laffectation dune expression numrique dun type donn une variable dun type
numrique diffrent, il y a conversion implicite, avec ventuellement perte de prcision (par exemple
dans la cas dune expression entire affecte une variable relle), voire dpassement de capacit
(comme dans le cas dune expression relle affecte un entier). Noter que le compilateur gfortran
est capable de signaler les conversions implicites, grce loption -Wconversion (cf. E.6.1, p. 171).
REAL
:: r = 3.14, s
INTEGER, PARAMETER :: ki=SELECTED_INT_KIND(14) ! variante pour stocker 10**14
INTEGER :: j
INTEGER(KIND=ki) :: i = 1000000000000_ki ! = 10**12
j = r
! donnera j = 3, comme j = int(r)
s = i
! donnera s trs proche de 1000000000000 environ 1,2 10**5 prs
! mais stock approximativement comme s = real(i)
Il en est de mme lors de lvaluation dexpressions dites mixtes impliquant des oprandes de types
numriques diffrents : les oprandes sont alors promus au type le plus riche avant valuation. La
3. Noter cependant que lunit de calcul flottant (Floating Processor Unit) effectue bien souvent les calculs dans
des registres de 80, voire 128 bits permettant une prcision et un domaine tendus pour reprsenter les rsultats intermdiaires. Le dpassement ventuel peut tre mis en vidence en activant une option de compilation (-ffloat-store
cf. E.5.1 pour g95 et gfortran, -float-storecf. E.2.1 pour nagfor) interdisant lusage des registres tendus.
4. On rappelle que le compteur lui-mme est forcment entier pour viter les erreurs darrondi.
23
hirarchie des types numriques comporte, par ordre de richesse croissante, les entiers, suivis des
flottants et au plus haut niveau les complexes. Au sein dun type donn, les variantes de type sont
classes selon le nombre doctets utiliss : par exemple le type DOUBLE PRECISION est plus riche
que le type prdfini REAL.
COMPLEX
REAL
INTEGER
v = u +
v = u +
s = r +
!
j = u +
r
i
i
r
:: u, v
:: r, s
:: i, j
! est calcul comme v = u + cmplx(r)
! est calcul comme v = u + cmplx(i)
! est calcul comme s = r + real(i)
combinaison des deux conversions implicites
! est calcul comme j = int(u + cmplx(r))
Pour une bonne lisibilit, on sefforcera de rendre explicites de telles conversions, en utilisant les
fonctions intrinsques dites de conversion de type 5 (cf. Annexe A.2, p. 140).
Noter enfin que llvation dun entier une puissance entire ngative va donner lieu une B
division entire : par exemple 10**(-3) sera interprt 7 comme 1/10**3 ou encore 1/1000 qui est
nul. Mais 10.**(-3) donnera bien .001.
3.2
Fortran possde six oprateurs de comparaison dont le rsultat est une variable boolenne.
Lancienne notation du fortran 77 est accepte (cf. table 3.1, p. 24).
5. Ces fonctions sont les quivalents de loprateur de conversion explicite du langage C ou cast, not en prfixant
lexpression par le type darrive entre parenthses.
6. Ce comportement est commun beaucoup dautres langages. Mais il est source de tellement derreurs que par
exemple le langage python a chang de convention au passage de la version 2 la version 3 en ajoutant un oprateur
spcifique, not // pour la division entire !
7. En particulier, si la constante relle 1.5e-3 vaut 1, 5 103 , lexpression constante relle 1.5*10.**(-3) a la
mme valeur alors que lexpression 1.5*10**(-3) est nulle.
24
fortran
<
<=
==
>=
>
/=
fortran77
.LT.
.LE.
.EQ.
.GE.
.GT.
.NE.
signification
infrieur
infrieur ou gal
gal
suprieur ou gal
suprieur
diffrent de
REAL
INTEGER
IF( a > 0 ) b = LOG(a)
IF( i /= 0 ) r = 1. / REAL(i)
:: a, b, r
:: i
! a > 0 est valu .true. si a est positif
tant donn que les nombres flottants ne sont reprsents quapproximativement en machine, les
tests dgalit entre flottants sont dconseills ; on prfrera comparer les diffrences un seuil, en
utilisant la fonction intrinsque EPSILON (cf. annexe A.4, p. 142).
On remplacera par exemple : IF ( a == b ) THEN par :
IF ( ABS(a-b) <= c *ABS(a) * EPSILON(a) ) THEN
o c est une constante suprieure 1.
3.3
Fortran dispose de quatre oprateurs logiques binaires permettant de combiner des expressions
logiques entre elles, ainsi que de loprateur unaire de ngation (cf. table 3.2, p. 24).
.AND.
.OR.
.NOT.
.EQV.
.NEQV.
ET
OU (inclusif)
Ngation unaire
quivalence
OU exclusif
REAL
LOGICAL
grand = r > 1000.
petit = r < .0001
moyen = .NOT. (grand .OR. petit)
:: r
:: grand, petit, moyen
Lvaluation dune expression logique ne ncessite pas forcment celle de toutes ses sousexpressions : en particulier, si le premier oprande dun AND est faux ou si le premier oprande
dun OR est vrai, le rsultat ne dpend pas du second, mais la norme 8 ne garantit pas quil ne soit
B pas valu 9 . Afin dcrire du code portable, on ne sappuiera donc pas sur cette proprit pour
conditionner un calcul (cf. par exemple 6.5.1, p. 69).
8. Le compilateur g95 fournit cependant une option -fshort-circuit qui assure que le second membre dun
.AND. ou dun .OR. ne soit valu que si ncessaire.
9. Le langage C, linverse, assure une valuation minimale des oprandes du && et du ||.
3.4
25
3.5
:: jour='mardi'
:: mois='juin'
:: date
! contiendra 'mardi-04-juin'
oprateurs
**
* et /
+ et - unaires
+ et - binaires
//
==, /=, <, <=, >=, >
.NOT.
.AND.
.OR.
.EQV. et .NEQV.
Table 3.3 Hirarchie des oprateurs intrinsques, classs par ordre de priorit dcroissante ; les
oprateurs figurant sur une mme ligne ont la mme priorit.
Par exemple, si x et y sont des rels, et ch1 et ch2 des chanes de longueur 2, lexpression :
x-y > -2. .or. x+y < 1. .and. ch1//ch2=='oui!'
est value comme :
((x-y) > -2.) .or. (((x+y) < 1.) .and. ((ch1//ch2) == 'oui!'))
Mais, par prudence et pour la lisibilit du code, on nhsitera pas expliciter les priorits par des
parenthses.
Noter que les oprateurs surchargs (cf. 10.2.1, p. 113) hritent de leur position intrinsque
dans la hirarchie. En revanche, les oprateurs nouvellement dfinis (cf. 10.2.2, p. 114) acquirent
la plus forte priorit sils ont unaires et la plus faible sils sont binaires.
10. En langage C, la concatnation de chanes de caractres est obtenue par simple juxtaposition, sans oprateur
explicite.
11. En C, la situation est nettement plus complexe : dune part, les oprateurs de comparaison donnent des rsultats
de type entier, susceptibles dintervenir dans des oprations numriques. dautre part, loprateur = daffectation
peut tre employ plusieurs fois dans une expression. Lusage des parenthses est donc encore plus conseill pour
faciliter linterprtation dune expression en C.
Chapitre 4
Structures de contrle
Le nommage des structures de contrle est facultatif, mais savre prcieux pour la lisibilit des
codes et leur maintenance ; il svre cependant ncessaire dans le cas dune rupture de squence
(cf. 4.3.3) qui ne concerne pas la boucle intrieure. Plus gnralement, il est fortement conseill de
nommer systmatiquement les structures comportant des ruptures de squence.
4.1
4.1.1
Structures IF
Linstruction IF
La forme la plus simple de lexcution conditionnelle est rserve au cas dune instruction
unique.
4.1.2
Pour conditionner lexcution dun bloc dinstructions une condition, on emploie la structure :
26
27
4.1.3
Utilisation du ELSE IF
! a <= 0
! a > 0
et
b <= 0
! a > 0
et
b > 0
le test ELSE IF permet de raccourcir lcriture. Noter qualors un seul END IF ferme la
structure globale.
REAL :: a, b
IF ( a <= 0. ) THEN
...
ELSE IF ( b <= 0. ) THEN
...
ELSE
...
END IF
! a <= 0
! a > 0
et
b <= 0
! a > 0
et
b > 0
Sous cette dernire forme (non-imbrique), il est possible dajouter autant de clauses ELSE IF(...) THEN
que ncessaire et la dernire clause ELSE nest pas obligatoire.
4.2
Lorsque les choix possibles sont nombreux, et portent sur une mme expression, la structure
SELECT CASE est souvent plus efficace que son quivalent laide de IF imbriqus. Elle permet, au
28
vu de la valeur dune expression, de choisir un traitement parmi un ensemble de cas qui doivent tre
numrs : lexpression tester doit faire lobjet dun test dgalit ; cest pourquoi cette structure
ne peut sappliquer qu des types possdant une reprsentation exacte, lexclusion des rels.
CHARACTER(len=3) :: rep
valid: SELECT CASE (rep)
CASE('oui','OUI') valid
WRITE(*,*) ' oui'
CASE('non','NON') valid
WRITE(*,*) ' non'
CASE DEFAULT valid
WRITE(*,*) 'rponse invalide'
END SELECT valid
2. Comme dans les shells de type sh dunix, mais contrairement au comportement du switch en langage C et des
shells de type csh, ds quun choix a t slectionn (et donc un bloc dinstructions excut), le contrle est pass
la fin de la structure ; cela quivaudrait en C faire suivre chaque bloc par linstruction break (ou breaksw en csh).
4.3
29
Structures de boucles
Pour effectuer des itrations, le fortran dispose des boucles DO avec ou sans compteur, et de la
boucle DO WHILE. Mais, lorsquil sagit de conditionner le traitement des lments dun tableau par
un test portant sur un tableau conformant (cf. 7.1.1), lutilisation de linstruction WHERE, ou de la
structure WHERE ... END WHERE (cf. 7.3.2, p. 84) savre plus efficace.
4.3.1
4.3.2
Boucles DO WHILE
Si le nombre de passages nest pas connu avant lentre dans la boucle, elle doit tre contrle
non par un compteur mais par un test logique : cest lobjet de la boucle WHILE qui intervient de
faon classique dans les mthodes itratives. Par prudence, on comptera malgr tout le nombre de
passages pour dclencher une sortie par EXIT (cf. 4.3.3) si le nombre de passages dpasse une limite
raisonnable.
30
4.3.3
Les ruptures de squence dans les boucles sont possibles grce aux branchements EXIT et
CYCLE 4 .
Branchement lindice suivant (ventuel) : CYCLE
Linstruction CYCLE lintrieur dune structure DO ... END DO permet de court-circuiter la
fin du bloc et de passer le contrle lindice de boucle suivant.
INTEGER :: i, imax = 10, n
n = 0
impairs : DO i = 1, imax
! a priori 1,2,3,4, ... 10
IF ( modulo(i,2) == 0 ) CYCLE ! ne pas considrer les entiers pairs
n = n + i
END DO impairs
WRITE (*,*) 'somme des entiers impairs infrieurs 10', n
En cas de boucles imbriques, linstruction CYCLE concerne a priori la boucle la plus interne dans
laquelle elle est situe. Pour quelle puisse sadresser une boucle externe, il est ncessaire de
nommer la boucle et dutiliser son nom comme argument de CYCLE 5 .
INTEGER :: i, imax, j, jmax
externe: DO i = 1, imax
...
interne: DO j = 1, jmax
...
IF (<expr_log >) CYCLE externe ! fait passer au i suivant
...
END DO interne
...
END DO externe
Sortie de boucle : EXIT
Linstruction EXIT lintrieur dune structure DO ... END DO permet de sortir immdiatement
de la boucle et de passer le contrle linstruction qui suit le END DO.
INTEGER :: i, n
n = 0
DO i = 1, 1000, 2
! a priori de 1 999
IF ( i > 10 ) EXIT
! limitation 10 (un seul EXIT excut)
n = n + i
END DO
WRITE (*,*) 'somme des entiers impairs infrieurs 10', n
Dans le cas de boucles imbriques, comme pour linstruction CYCLE, linstruction EXIT ne sort
que de la boucle la plus interne dans laquelle elle est situe. Pour pouvoir sortir directement dune
boucle externe, il faut nommer la-dite boucle et utiliser la syntaxe EXIT <nom > 6 .
4. Ces instructions correspondent respectivement break et continue en langage C.
5. Ces possibilits de branchement sadressant une boucle externe nomme suivant la mme syntaxe quen
fortran existent aussi en java pour les branchements break et continue concernant des structures de contrle itratives
comme while ou for.
6. En fortran 2008, cette syntaxe sapplique dautres structures que les blocs (cf. 4.5, p. 32).
4.3.4
31
[<nom > :] DO
<bloc d'instructions >
END DO [<nom >]
Cette structure de boucle, a priori infinie, na dintrt que si le bloc comporte une instruction
EXIT permettant de sortir de la boucle au vu dun test IF 7 .
INTEGER :: i
positifs: DO
WRITE(*,*) 'entrer un entier positif, sinon 0 pour terminer'
READ(*,*) i
IF ( i == 0 ) EXIT positifs
...
! bloc d'instructions
END DO positifs
f2008
4.4
La structure BLOCK
Fortran 2008 a introduit une structure de bloc, comparable celle dlimite par des accolades
en C89, entit o il est possible de dclarer des types, des variables, des constantes locales, aprs
des instructions excutables 8 . Les blocs peuvent tre imbriqus et nomms.
32
tmp = 2*i
WRITE(*,*) "locale", tmp
END BLOCK
END DO
WRITE(*,*) "globale", tmp
END PROGRAM bloc
f2008
4.5
En fortran 2008, linstruction de sortie EXIT peut sappliquer dautres structures que les
boucles, condition quelles soient nommes. En plus des boucles, EXIT suivi dun nom permet
notamment de sortir des structures nommes BLOCK, IF, SELECT CASE. Il faut donc distinguer deux
syntaxes :
EXIT suivi dun nom de structure transfre le contrle la fin de la structure ainsi nomme,
quelle quelle soit ;
EXIT non suivi dun nom de structure transfre le contrle la fin de la boucle englobante la
plus interne.
Pour viter toute ambigut en fortran 2008, on suivra le conseil de Metcalf et al. (2011) en
utilisant systmatiquement la syntaxe EXIT <nom >, y compris pour indiquer la sortie de la boucle
la plus interne.
externe : do i=1,n
interne: block
if(i >2) then
write(*,*) "sortie"
! exit ! sortie de la boucle do
! exit externe ! sortie de la boucle do
exit interne ! sortie du bloc nomm
end if
write(*,*) "dans le bloc", 2*i
end block interne
write(*,*) "dans la boucle", -2*i
end do externe
4.6
4.6.1
Linstruction vide CONTINUE, trs utilise pour dlimiter les fins de boucles dans les anciennes
versions du fortran, voit, avec lapparition du END DO, son emploi rduit aux rares branchements
spcifis par des tiquettes numriques (cf. 4.6.2, p. 32 et 4.6.6, p. 34).
4.6.2
Branchement par GO TO
4.6.3
33
Instruction STOP
Linstruction STOP [<code d'arrt >] impose larrt immdiat du programme et laffichage
ventuel du code darrt (une chane de caractres ou un entier dau plus 5 chiffres) qui peut tre
lui-mme repris par certains systmes dexploitation. Elle est utilise pour interrompre lexcution
en fin de programme principal ou un endroit quelconque depuis une procdure quelconque dans
des circonstances exceptionnelles ne permettant plus de poursuivre le traitement.
PROGRAM trait
...
CALL sub_prog
...
IF ( ... ) STOP 10
...
STOP
END PROGRAM trait
SUBROUTINE sub_prog
...
IF ( ... ) STOP 12
...
RETURN
END SUBROUTINE sub_prog
4.6.4
! interruption exceptionnelle
! fin normale
! arret exceptionnel
! retour normal au programme principal
Instruction RETURN
34
4.6.5
En fortran 77, linstruction STOP dans le programme principal, de mme que linstruction RETURN
dans les sous-programmes et fonctions, taient obligatoires juste avant END, quand END ntait quun
dlimiteur. En fortran 90, END est aussi un ordre excutable et STOP en fin de programme principal
ainsi que RETURN en fin de sous-programme ou de fonction sont donc devenus facultatifs.
4.6.6
Certains ordres dentre-sorties (cf. 5.3, p. 41), notamment OPEN, READ, WRITE 10 possdent
des arguments optionnels (accessibles par mot-clef) de branchement des instructions tiquetes
permettant de traiter des circonstances particulires quil est toujours prudent de prvoir :
en cas derreur : ERR=<tiquette_numrique > (OPEN, READ, WRITE) ;
en cas de fin de fichier : END=<tiquette_numrique > (READ) ;
en cas de fin denregistrement : EOR=<tiquette_numrique > (READ).
...
OPEN(...)
READ(..., ERR=900, ...)
...
STOP
900 CONTINUE
WRITE(*,*) 'erreur de lecture'
STOP 12
END PROGRAM ...
! traitement normal
! arrt normal
! branchement en cas d'erreur de lecture
! arrt exceptionnel aprs erreur de lecture
Pour viter les branchements sur des tiquettes numriques, on prfrera tester si le code de
retour IOSTAT des oprations dentres-sorties est non nul pour traiter ces cas particuliers laide
f2003 des structures de contrle classiques. Avec fortran 2003, les constantes IOSTAT_END et IOSTAT_EOR
du module ISO_FORTRAN_ENV permettent de distinguer dans ces cas les fins de fichier et denregistrement (cf. 5.3.1 p. 41). On peut aussi appeler une des fonctions boolennes IS_IOSTAT_END ou
IS_IOSTAT_EOR.
10. BACKSPACE, CLOSE, ENDFILE, INQUIRE et REWIND possdent aussi un argument optionnel de mot-clef ERR.
Chapitre 5
Entressorties, fichiers
Fortran dispose doutils sophistiqus pour raliser des transferts dinformations avec des fichiers,
mais il nest pas ncessaire de connatre toutes leurs possibilits pour mettre en uvre des programmes lmentaires. En sortie comme en entre, la mise en forme des donnes peut en effet tre
effectue avec dautres outils (filtres sous unix par exemple) plus adapts la manipulation des
chanes de caractres dans ces tapes de pr- ou post-traitement qui nimpliquent pas de calculs
lourds. Cest pourquoi, nous aborderons dabord (5.1) les entres-sorties standard (interactions
avec le terminal) avant de prsenter les concepts gnraux (5.2) et la syntaxe dtaille (5.3) des
instructions dentres-sorties. Ltude des nombreux exemples prsents dans les dernires sections
5.5 et 5.6 du chapitre devrait clairer les notions introduites dans les sections 5.2 et 5.3.
5.1
Nous avons dj utilis, sans les prsenter explicitement, les instructions daffichage (PRINT) et
de lecture (READ) au format libre. Ils respectent la syntaxe suivante :
5.1.1
La principale rgle rgissant la progression par dfaut des lignes dans les entres-sorties veut
que :
Chaque instruction de lecture ou dcriture provoque le passage la ligne suivante.
35
36
En particulier, si la liste est vide, en criture linstruction PRINT * produit un saut de ligne, de
mme quen lecture linstruction READ * saute une ligne dentres qui reste inexploite.
Cette rgle, essentielle pour comprendre en particulier criture et lecture des tableaux implique
que, si on utilise une boucle explicite pour afficher les lments dun tableau, on affiche un lment
par ligne (affichage en colonne). Pour afficher le tableau en une seule ligne, il faut (cf. 5.4.4, p. 50) :
soit, comme en fortran 77, utiliser une boucle implicite, qui produit au vol la liste des
lments pour linstruction dcriture,
soit, de faon plus concise, utiliser la notation globale pour lensemble des lments du tableau
afficher.
5.1.2
Les donnes doivent tre crites au clavier sous une des formes admissibles pour les constantes
(cf. 2.4, p. 17) du type de la variable affecter. la conversion implicite prs des entiers en rels,
une diffrence de type provoque une erreur dexcution lors de la lecture.
Lors de la lecture dun enregistrement, une combinaison quelconque des saisies suivantes au
clavier :
un ou plusieurs espaces ;
une virgule 1 ;
un ou plusieurs changements de ligne,
est considre comme un sparateur de donnes, permettant de passer la lecture de la variable
suivante.
Au lieu de rpter <n > fois une valeur <val >, on peut utiliser la notation <n >*<val >. Tant que
la liste des variables 2 nest pas pas puise, la lecture des donnes peut se poursuivre sur plusieurs
lignes, donc la lecture dun enregistrement peut correspondre la saisie de plusieurs lignes.
Mais on peut arrter la lecture de lenregistrement avant davoir puis la liste par la saisie du
caractre / de fin denregistrement. Il est aussi possible de sauter une variable au sein de la
liste en saisissant deux virgules successivement. Dans ces deux cas, les variables non lues gardent
leur valeur antrieure.
Par exemple, pour les jeux dentres indiqus gauche de la flche (=), le programme suivant
affichera ce qui est indiqu droite.
PROGRAM lecture
IMPLICIT NONE
INTEGER :: i=10, j=20, k=30
! 3 entiers initialiss
PRINT *, 'donner 3 entiers'
READ *, i, j, k
PRINT *, ' i=', i, ' j=', j , ' k=', k
END PROGRAM lecture
1 2 3
1,,3
1,
3
1,2,3
2,
1
2
3
i= 1
j= 2
k= 3
1
,
,
3
i= 1
j= 20
k= 3
1 2 ,,
i= 1
j= 2
k= 30
1. Le sparateur de donnes virgule , est chang en point-virgule ; dans le cas o on a choisi la virgule
comme sparateur dcimal (cf. 5.4.2, p. 49).
2. Au sens scalaire du terme, donc par exemple chacun des lments dun tableau de rels.
37
3*1
6*1
i= 1
j= 1
k= 1
Si on fournit plus de donnes que ncessaire, les donnes superflues sont perdues : ne pas croire
quelles sont disponibles pour linstruction de lecture suivante.
Le programme suivant comporte deux instructions de lecture, et ne peut lire lentier l quaprs
un changement denregistrement.
PROGRAM lecture2
IMPLICIT NONE
INTEGER :: i=10, j=20, k=30, l=40
! 4 entiers initialiss
PRINT *, 'donner 3 entiers puis 1 entier'
READ *, i, j, k
READ *, l
PRINT *, ' i=', i, ' j=', j, ' k=', k, ' l=', l
END PROGRAM lecture2
1
2
i= 1 j= 2 k= 3 l=4
=
3
4
Dans les applications lmentaires et en phase de mise au point, on se contente souvent du
format libre pour les entres et les sorties avec le terminal. Sil est parfois ncessaire de contraindre
le format en sortie pour amliorer la lisibilit, mme lcran, linverse, pour la lecture au clavier,
il est conseill dutiliser le format libre, sauf informer explicitement lutilisateur des contraintes
du format de saisie. En revanche, lorsque la quantit des donnes dentre devient importante, il
est souvent plus efficace de les saisir dans un fichier avec toutes les possibilits dun diteur, puis
de faire lire ce fichier par le programme.
1 2 3
4
5.2
1 2 3 -4 -5
4 -4
Gnralits et terminologie
Dans les changes de donnes plus massifs quavec le terminal, ou avec des fichiers dont le
format peut tre impos par dautres applications, il est souvent ncessaire de prciser les rgles
de conversion en entre ou en sortie grce une spcification de format.
INTEGER :: k
INTEGER, DIMENSION(100) :: ti ! tableau de 100 entiers
REAL, DIMENSION(100) :: tr
! tableau de 100 rels
OPEN(9, FILE='donnees.dat')
! ouverture du fichier => connect l'unit 9
DO k = 1, 100
READ(9, '(i4, f9.5)') ti(k), tr(k) ! lecture d'un enregistrement
END DO
CLOSE(9)
! fermeture du fichier
Dans cet exemple, chaque instruction READ lit dans le fichier donnees.dat un enregistrement
constitu dun entier cod sur 4 chiffres, suivi dun rel sur 9 caractres dont 5 aprs le point
dcimal. La chane de caractres i4, f9.5 constitue le format de lecture. Lobjectif de ce chapitre
est de dcrire les diffrentes instructions permettant les changes de donnes et dintroduire la
syntaxe des spcificateurs de format.
5.2.1
Fichiers externes
Outre les entressorties standard qui soprent via le terminal, fortran peut contrler plusieurs
flux de donnes en lecture ou en criture associs des fichiers externes (external files), hbergs
38
5.2.2
Notion denregistrement
5.2.3
39
soit dabord une lecture de chanes de caractres, puis une conversion en reprsentation
interne ;
soit dabord une conversion de la reprsentation interne en chanes de caractres, puis une
criture de chanes de caractres.
Si la conversion provoque une erreur lexcution, cest lensemble de linstruction qui choue,
ce qui savre particulirement gnant par exemple pour les entres interactives, en cas de faute de
frappe. Pour fiabiliser les saisies au clavier, on est amen exploiter les codes de retour de READ 8 .
La lecture seffectue alors dans une boucle qui ne sarrte que lorsquil ny a plus derreur.
1
2
3
4
5
6
7
8
9
10
11
PROGRAM robust_lect
IMPLICIT NONE
INTEGER :: i=-100, ok
WRITE(*,*) 'entrer un entier'
DO
READ(*, *, iostat=ok) i
IF(ok==0) EXIT
WRITE(*,*) 'erreur: recommencez'
END DO
WRITE(*,*) 'i=', i
END PROGRAM robust_lect
Choix entre fichier format ou non-format
Le choix entre les deux types de fichiers pour stocker des donnes numriques est dict par les
critres suivants :
non-formats : pas de conversion, donc transfert plus rapide et sans perte de prcision, fichiers
plus compacts ; mais fichiers non portables 9 et difficiles lire par dautres outils 10 ; en particulier, dans les fichiers binaires en accs squentiel, fortran crit et sattend lire, en tte
et en fin (cest moins gnant) de chaque enregistrement, une balise denregistrement (record
marker), sous forme dun entier 11 indiquant le nombre doctets de lenregistrement : il faut
en tenir compte si on accde au fichier au travers de programmes utilisant dautres langages ;
formats : lisibilit par dautres outils (filtres ou simples diteurs de texte), portabilit entre
applications et entre machines ; mais fichiers plus volumineux et accs plus lent ; perte de
prcision possible.
5.2.4
On distingue deux mthodes daccs aux enregistrements stocks dans des fichiers :
8. Cela impose dutiliser la deuxime syntaxe, plus complte, de READ, cf. 5.3.4, p. 44.
9. Les donnes numriques sur plusieurs octets peuvent tre enregistres en mmoire de deux faons, selon lordre
choisi entre les octets qui reprsentent la valeur en binaire :
dans lordre des poids dcroissants (octets de poids fort au dbut) : on parle dorientation big-endian ou
gros-boutiste.
dans lordre des poids croissants (octets de poids faible au dbut) : on parle dorientation little-endian ou
petit-boutiste.
Si la majorit les processeurs de PC, en particulier les x86 ont adopt lorientation litte-endian, les processeurs
de serveurs ibm, les PowerPC et les ia64 notamment sont dorientation big-endian. On notera que ces diffrences
peuvent concerner les entiers, mais aussi les flottants, car la norme IEEE 754 (cf. annexe C, p. 154) ne spcifie pas
lorientation des octets, et les caractres multi-octets dunicode (UTF-16 et UTF-32).
10. Sous unix, la commande od (octal dump) permet dafficher sous diverses formes le contenu binaire dun fichier.
Elle permet entre autres dafficher un aperu du contenu de fichiers binaires grce une ou plusieurs options -t qui
spcifient comment interprter les octets (nombre doctets grouper et conversion suivant un type), par exemple :
od -t d4 pour des entiers en dcimal sur 4 octets (32 bits) ;
od -t f4 ou od -t fF pour des rels sur 4 octets (32 bits) ;
od -t f8 ou od -t fD pour des rels en double prcision sur 8 octets (64 bits).
11. Cet entier peut tre cod sur 64 bits sur les processeurs 64 bits.
40
laccs squentiel (sequential), o les enregistrements sont stocks les uns la suite des
autres 12 et o, pour accder un enregistrement particulier, il est ncessaire de lire tous
les enregistrements prcdents ; dans ce mode, il nest pas possible de modifier un enregistrement sans compromettre lintgrit de tous les suivants ;
laccs direct (direct), o les enregistrements sont reprs par un numro qui permet (moyennant la connaissance de la taille, ncessairement fixe, des enregistrements) de calculer la
position de lenregistrement dans le fichier et daccder ainsi un enregistrement particulier
(y compris en criture) sans lire explicitement ceux qui le prcdent, ni affecter les suivants
(cf. 5.6, p. 54).
f2003 Le fortran 2003 a introduit une troisime mthode inspire du langage C, laccs stream ou flot,
combinant des avantages des deux prcdents. Le positionnement dans le fichier se fait en spcifiant le numro dunits de stockage (en gnral des octets) en commenant 1 en dbut de
fichier. Les fichiers formats en accs stream ont aussi une structure denregistrement, mais les fins
denregistrement doivent tre explicitement spcifies en crivant le caractre fourni par la fonction
intrinsque NEW_LINE 13 .
Choix entre accs direct et accs squentiel
Le choix entre les mthodes daccs aux donnes dpend de leur nature (qui peut dterminer
la taille des enregistrements), de leur volume (stockable facilement ou non dans des tableaux en
mmoire) et de lusage quon leur prvoit. Ce choix est parfois impos par les contraintes suivantes :
les enregistrements dun fichier accs direct sont ncessairement de taille fixe ;
seul laccs direct permet dcrire un enregistrement sans avoir rcrire la totalit du fichier.
Ainsi, les fichiers de bases de donnes, dont les enregistrements doivent pouvoir tre mis jour
de faon individuelle, et dont le volume ne permet pas un stockage facile en mmoire vive, sont
stocks dans des fichiers accs direct.
Parfois, alors que les deux mthodes sont envisageables, des considrations de performances
(mme en lecture seule) peuvent amener prfrer laccs direct, si par exemple on doit trs souvent
accder des donnes non contiges, de faon alatoire. Supposons par exemple quune fonction soit
chantillonne dans le plan au sein dun fichier selon une grille en coordonnes rectangulaires et que
lon souhaite la rchantillonner selon des coordonnes polaires ; lorsque lon calculera les valeurs
de la fonction en suivant un cercle, on devra accder des donnes certainement non contiges
dans le fichier initial, quil sera donc prfrable de lire en accs direct ; il sera donc prfrable de
crer le fichier initial en accs direct.
5.2.5
Dans une instruction dentre-sortie, les informations changes sont spcifies par une liste
dentre-sortie (i/o-list), qui est une liste dexpressions pour une instruction dcriture, mais doit
tre une liste de variables pour une instruction de lecture. Si un lment de la liste est un tableau,
il est quivalent la liste des lments du tableau 14 ; sil sagit dune structure, elle doit tre interprte comme la liste des champs de la structure. Enfin, la liste dentre-sortie peut comporter des
boucles implicites (aussi utilises comme constructeurs de tableau, cf. 7.1.3, p. 81), ventuellement
imbriques.
Dans lexemple suivant, chacune des trois instructions affiche le tableau t de la mme faon sur
une ligne.
INTEGER, DIMENSION(3) :: t = (/ 1, 2, 3 /)
INTEGER :: i
WRITE(*, '(3i4)') t
! tableau initialis
! affichage global
12. Comme sur une bande magntique qui est un support physique accs squentiel.
13. La fonction intrinsque NEW_LINE prend pour argument un caractre quelconque et rend le caractre de fin de
ligne de mme sous-type. Cest lquivalent du \n du langage C.
14. Le tableau est transform en liste en faisant varier dabord le premier indice, puis le deuxime, ... (cf. 7.1.2,
p. 80).
41
5.3
! liste exhaustive
! boucle implicite
Instructions dentres-sorties
Une opration de transfert de donnes requiert en gnral une instruction OPEN de connexion
entre unit logique et fichier, des instructions dchange READ ou WRITE, et enfin une instruction
CLOSE de libration de lunit logique. Les instructions dentres-sorties OPEN, READ, WRITE, PRINT
et INQUIRE se partagent des arguments obligatoires ou optionnels accessibles par mot-clef dont on
va dcrire les plus usits.
f2003
5.3.1
Depuis fortran 2003, le module intrinsque ISO_FORTRAN_ENV dfinit des constantes nommes
qui permettent de dsigner de faon portable des paramtres concernant les entres sorties, notamment :
Les numros des units logiques prconnectes aux flux standard :
INPUT_UNIT, qui dsigne lentre standard (descripteur 0 sous unix permettant des redirections dentre via < fichier) ;
OUTPUT_UNIT, qui dsigne la sortie standard (descripteur 1 sous unix permettant des
redirections de sortie via > fichier) ;
ERROR_UNIT, qui dsigne la sortie derreur standard (descripteur 2 sous unix permettant
des redirections derreur standard via 2> fichier).
Si les units dentre et de sortie standard peuvent tre dsignes par * de faon plus rapide
que INPUT_UNIT et OUTPUT_UNIT, lutilisation de ERROR_UNIT est ncessaire pour dsigner la
sortie derreur de faon indpendante du compilateur.
Les entiers rendus par IOSTAT= dans les cas dchec doprations dentres/sorties suivants :
IOSTAT_END qui dsigne la fin de fichier ;
IOSTAT_EOR qui dsigne la fin denregistrement (End Of Record) ;
La valeur du code de retour IOSTAT peut tre compare ces paramtres pour effectuer
des traitements spcifiques au lieu davoir recours aux arguments optionnels END= ou EOR=
(cf. 4.6.6 p. 34), qui, eux, ncessitent le branchement sur une tiquette numrique.
FILE_STORAGE_UNIT qui dsigne lunit de mesure en bits (en gnral 8) des tailles denregistrement (RECL) dans les oprations OPEN (cf. 5.3.2 p. 42) et INQUIRE (cf. 5.3.7 p. 45).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PROGRAM unites_standard
! standard fortran 2003 : emploi du module ISO_FORTRAN_ENV
USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY : error_unit, input_unit, output_unit
IMPLICIT NONE
INTEGER :: i
WRITE(*,*) "entrer un entier"
! lecture sur l'entre standard (descripteur 0 sous unix)
! redirection d'entre par < fichier
READ(input_unit, *)i
WRITE(*,*) "i vaut ", i
! criture sur la sortie standard (descripteur 1 sous unix)
! redirection par 2> fichier
WRITE(output_unit,*) "message sur la sortie standard"
! criture sur la sortie standard d'erreur (descripteur 2 sous unix)
! redirection par 2> fichier
WRITE(error_unit,*) "message d'erreur"
END PROGRAM unites_standard
42
Noter que fortran 2003 fournit aussi les deux fonctions IS_IOSTAT_END et IS_IOSTAT_EOR qui
attendent pour argument la valeur du code de retour IOSTAT et rendent un boolen vrai en cas de fin
de fichier ou de fin denregistrement. Ces fonctions boolennes testent donc lgalit IOSTAT_END
ou IOSTAT_EOR.
5.3.2
OPEN
NEWUNIT=<nu > renvoie un numro dunit logique non utilis dans la variable entire <nu >.
Cet argument, introduit par fortran 2008, permet dviter davoir prendre en charge soimme (cf. 5.3.7, p. 45) la recherche dun numro libre. Pour viter toute collision avec des
numros (positifs) attribus avec UNIT=, le numro rendu est ngatif (et diffrent de -1).
FORM=<fmt > o <fmt > est une chane de caractres gale 'FORMATTED' (valeur par dfaut)
ou 'UNFORMATTED' pour un fichier non format ;
FILE=<nom_fichier > dsigne le nom du fichier connecter, sous forme dune chane de
caractres (constante ou variable) ;
ERR=<tiquette > dsigne une tiquette numrique permettant un branchement 16 en cas
derreur ;
IOSTAT=<iostat > est un paramtre de sortie qui rend une variable entire nulle si lopration
sest droule sans erreur, ou sinon une valeur prcisant le type derreur rencontre ;
STATUS=<status > dsigne ltat du fichier ouvrir et peut valoir :
'OLD' dans le cas dun fichier prexistant
'NEW' dans le cas o le fichier nexiste pas
'REPLACE' qui permet le remplacement ou la cration suivant que le fichier existe ou
non
'UNKNOWN' dans le cas o on ne sait pas a priori si le fichier existe
'SCRATCH' pour un fichier temporaire qui sera dtruit lors de linstruction CLOSE
f2003
ACCESS=<mthode > spcifie si le fichier est en accs squentiel 'SEQUENTIAL' (par dfaut),
en accs direct 'DIRECT' ou (en fortran 2003 seulement) en accs stream 'STREAM' ;
ACTION=<mode > indique les oprations possibles sur le fichier (elles supposent que lutilisateur
possde des droits daccs suffisants sur le fichier)
'READ' si ouvert en lecture seule
'WRITE' si ouvert en criture seule
'READWRITE' (dfaut) si ouvert en lecture et criture
POSITION=<pos > prcise la position louverture dun fichier en accs squentiel :
'APPEND' positionne la fin du dernier enregistrement avant la marque de fin de fichier
et permet dajouter des informations la fin dun fichier existant
'REWIND' positionne en dbut de fichier
15. On peut vrifier quun numro dunit logique est disponible en utilisant linstruction INQUIRE (cf. 5.3.7, p. 45).
16. On vitera ce branchement en testant si le code de retour IOSTAT est non nul.
43
'ASIS' ouvre le fichier la position courante sil est dj connect, mais dpend du
processeur sinon
RECL=<entier > indique la longueur des enregistrements pour un fichier accs direct (paramtre obligatoire dans ce cas) ou la longueur maximale des enregistrements pour un fichier
squentiel (paramtre optionnel dans ce cas, la valeur par dfaut dpendant du compilateur) ;RECL sexprime en nombre de caractres pour les fichiers formats, mais dans une unit
qui peut tre loctet ou le mot de 32 bits, selon le compilateur et ses options ;
BLANK est une chane de caractres spcifiant linterprtation des blancs dans les lectures de
donnes numriques : si elle vaut 'null' (par dfaut), les blancs sont ignors, si elle vaut
'zero', ils sont interprts comme des zros ;
DELIM spcifie le dlimiteur des chanes de caractres en criture, qui peut tre 'none' (dfaut), 'quote' ou 'apostrophe'.
DECIMAL spcifie le sparateur entre la partie entire et la partie fractionnaire des nombres flottants. Par dfaut, cest le point, mais la virgule peut lui tre substitue par DECIMAL='comma'. f2003
Pour rtablir le point, il faut prciser DECIMAL='point'.
Noter que ces conventions peuvent aussi tre modifies dans les ordres de lecture (cf. 5.3.4,
p. 44) et dcriture (cf. 5.3.5, p. 45).
ENCODING permet de prciser le codage des chanes de caractres dans le fichier format
ouvrir. Les fichiers texte au codage UTF-8 dUnicode sont pris en charge par le standard f2003
2003 grce au paramtre optionnel ENCODING='UTF-8' de OPEN. Il est prudent de lire de
tels fichiers dans des variables chane de caractres dont la variante de type, par exemple
'ISO_10646' (cf. 8.1.3, p. 95), permet de reprsenter les caractres dUnicode.
Exemple de lecture dun fichier de 6 caractres cods en UTF-8 et dcriture en
code ISO-8859-1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PROGRAM io_utf8_latin1
IMPLICIT NONE
! 9 oct 2012 fichier source en iso-latin1
! avec NAG Fortran Compiler Release 5.3(854)
! les kind des chanes (4 en utf-32 et 1 en default)
INTEGER, PARAMETER :: utf32=SELECTED_CHAR_KIND('ISO_10646') ! UCS_4 = UTF-32
INTEGER, PARAMETER :: def_char=SELECTED_CHAR_KIND('DEFAULT') ! Default=latin1
CHARACTER(LEN=6, KIND=def_char) :: latin
CHARACTER(LEN=6, KIND=utf32) :: lu_utf32 ! chane UTF-32
! lecture sur fichier externe cod UTF-8
OPEN(UNIT=10, FILE='fichier-utf8.txt', ENCODING='utf-8')
READ(10, *) lu_utf32(1:)
CLOSE(10)
latin = lu_utf32 ! transcodage UTF32-> default =latin1
WRITE(*,*) "latin1:", latin ! affichage iso-latin1
! criture sur fichier externe en latin1
OPEN(UNIT=10, FILE='fichier-latin1.txt', ENCODING='DEFAULT') ! latin1
WRITE(10,'(a)') latin
CLOSE(10)
END PROGRAM io_utf8_latin1
Le texte du fichier cod UTF-8 est lu dans des variables de type chanes UTF-32, puis converti 17
dans des variables de type ISO-8859-1 et enfin crit dans un fichier au codage par dfaut.
Exemples
Pour connecter le fichier format lect.dat lunit 10 en accs squentiel, on peut se contenter
de linstruction :
17. Noter que dans la norme fortran 2003, seul le transcodage depuis et vers le code par dfaut est requis : ici, le
dfaut tant ISO-8859-1, il permet de transcoder des chanes avec des caractres non-ascii en UTF-32 vers du latin1.
44
OPEN(UNIT=10, FILE='lect.dat')
Il est aussi possible de prciser :
OPEN(UNIT=10, FILE='lect.dat', FORM='formatted', ACCESS='sequential')
Mais il est prudent de prvoir une gestion des erreurs avec par exemple :
INTEGER :: ok ! status de retour
OPEN(UNIT=10, FILE='lect.dat', IOSTAT=ok)
IF( ok /= 0 ) THEN
PRINT *, 'erreur fichier lect.dat'
STOP
! arrt dfaut de meilleure solution
END IF
5.3.3
CLOSE
Linstruction CLOSE permet de dconnecter une unit logique dun fichier 18 . Elle libre lunit
logique pour une nouvelle connexion.
&
Les arguments de CLOSE sont tous optionnels sauf lunit logique et ont la mme signification
que dans linstruction OPEN, sauf STATUS=<status > qui dsigne ici le devenir du fichier aprs
dconnexion et peut valoir :
'KEEP' (par dfaut 19 ) pour conserver un fichier prexistant ;
'DELETE' pour dtruire le fichier la dconnexion.
5.3.4
READ
45
largument optionnel POS=<position > permet de choisir la position en units de stokage f2003
dans les fichiers en accs stream.
Les branchements conditionnels EOR= et END= sont dconseills en fortran 2003, o lusage du f2003
module intrinsque ISO_FORTRAN_ENV ou des fonctions boolennes IS_IOSTAT_END ou IS_IOSTAT_EOR
(cf. 5.3.1, p. 41) permet de tester si le code de retour IOSTAT vaut IOSTAT_EOR ou IOSTAT_END.
5.3.5
WRITE
5.3.6
Linstruction PRINT <fmt > [, <liste >] permet dcrire en mode format sur la sortie standard la liste optionnelle des variables ou constantes indiques aprs la virgule ; elle est quivalente
WRITE(*, <fmt >) [, <liste >].
5.3.7
INQUIRE
Larrt dun programme provoque implicitement un CLOSE sur toutes les units connectes par le programme
Sauf pour les fichiers ouverts avec STATUS='scratch', pour lesquels la valeur par dfaut est DELETE.
avec un sens identique celui ventuellement donn pour linstruction OPEN
En fortran 2008, on prfrera utiliser largument NEWUNIT de OPEN (cf. 5.3.2, p. 42).
46
IF(present) THEN
OPEN(UNIT=n, FILE='fichier', ...)
...
ELSE
...
END IF
! le fichier existe
Le paramtre de sortie ENCODING du standard 2003 permet dobtenir le codage des chanes de
f2003 caractres dans un fichier format connect une unit logique. On peut ainsi dtecter le codage
'UTF-8' dUnicode mais 'UNKNOWN sera rendu si la dtection nest pas possible.
Dautre part, linstruction INQUIRE permet dvaluer la taille de lenregistrement que crerait
lcriture non-formate dune liste 22 . Elle permet ainsi de connatre la longueur dun enregistrement
dun fichier non-format en accs direct avant de le connecter une unit logique (cf. 5.6.2, p. 55),
de faon rendre linstruction douverture du fichier indpendante de la machine.
INTEGER :: long, iunit
INQUIRE(IOLENGTH=long) <liste d'expressions >
...
OPEN(iunit, FILE=..., ACCESS='direct', FORM='unformatted', RECL=long)
...
Enfin, pour les fichiers en accs stream, INQUIRE permet de senqurir de la position courante
dans le fichier exprime en units de stockage qui sont souvent des octets. Dans le cas dun fichier
non format, les dcalages peuvent tre calculs avec INQUIRE(IOLENGTH=variable).
INTEGER :: iunit, positionx
REAL :: x, y
OPEN(iunit, FILE=..., ACCESS='stream', FORM='unformatted')
...
INQUIRE(iunit, POS = positionx) ! POS = argument de sortie (prochaine I/O)
READ(iunit) x ! lecture de x
...
WRITE(iunit, POS = positionx) y ! POS = argument d'entre
! criture de y la place de x
...
5.3.8
Il existe enfin des instructions permettant, sans effectuer de transfert de donnes, de modifier
la position courante dans un fichier daccs squentiel :
REWIND ([UNIT=]<entier > [, ERR=<tiquette >] [, IOSTAT=<iostat >])
positionne en dbut de fichier ;
BACKSPACE ([UNIT=]<entier > [, ERR=<tiquette >] [, IOSTAT=<iostat >])
positionne avant lenregistrement courant si on est dans un enregistrement ou avant le prcdent enregistrement si on est entre deux enregistrements (cette instruction permet la relecture
dun enregistrement) ;
ENDFILE ([UNIT=]<entier > [, ERR=<tiquette >] [, IOSTAT=<iostat >])
crit 23 une marque de fin de fichier la position courante et positionne juste aprs cette
marque de fin de fichier.
22. Cette taille dpend en gnral de la machine.
23. Ne pas croire que ENDFILE est une simple instruction de positionnement en fin de fichier. Ce positionnement
est possible louverture du fichier via loption POSITION='APPEND' de linstruction OPEN (cf. 5.3.2).
47
5.3.9
5.4
Descripteurs de format
Les rgles de conversion entre reprsentation interne des donnes et chane de caractres des
fichiers formats sont dtermines par le format de lecture ou dcriture. Le format peut tre spcifi
sous une des formes suivantes :
le format libre, dsign par * ;
une chane de caractres constante ou variable, dcrivant le format entre parenthses ;
une tiquette numrique (entier positif) faisant rfrence une instruction dite de format.
Le format libre est utilis pour les changes avec le terminal, en phase de test ou pour accder des
fichiers manipuls toujours sur la mme machine, car il nest pas portable. Mais, pour des changes
de donnes plus massifs avec des fichiers ou de donnes dont le format peut tre impos par des
applications externes, il est souvent ncessaire de prciser les rgles de conversion en entre ou en
sortie grce une spcification de format. La dernire forme, avec tiquette numrique dinstruction
est prfre lorsquune mme spcification de format est utilise plusieurs fois dans une unit de
programme ; il est alors dusage de regrouper les instructions de format en fin de programme et de
leur rserver une plage dtiquettes numriques particulire.
CHARACTER(LEN=4) :: fmt1, fmt2
INTEGER :: j = 12
WRITE(*, *) 'bonjour'
WRITE(*, '("bonjour")')
WRITE(*, '(a7)') 'bonjour'
fmt1='(a7)'
WRITE(*, fmt1) 'bonjour'
WRITE(*, 1000) 'bonjour'
1000 FORMAT(a7)
!
WRITE(*, *) j
WRITE(*, '(i)') j
! format libre
! chane de caractres constante
! chane de caractres variable
! tiquette numrique
! format libre
! chane de caractres constante
24. Cest le comportement par dfaut en langage C, o les changements de ligne doivent tre explicitement spcifis
par des \n. On retrouve ce comportement par dfaut avec laccs STREAM du fortran 2003.
48
WRITE(*, '(i2)') j
fmt2='(i2)'
WRITE(*, fmt2) j
fmt2='(i4)'
WRITE(*, fmt2) j
WRITE(*, 1100) j
1100 FORMAT(i2)
Comme le format est une expression de type chane de caractres, il peut tre dfini par une
variable value lors de lexcution : cette mthode sera prsente la sous-section 5.4.5, p. 51.
On distingue les descripteurs actifs, qui spcifient le mode de conversion dune donne en chane
de caractres ou rciproquement (a priori un descripteur actif par lment de la liste dentre-sortie),
les chanes de caractres et les descripteurs de contrle, qui, entre autres, rglent le positionnement,
grent les espaces et les changements denregistrement.
5.4.1
Descripteurs actifs
Dune faon gnrale, le premier paramtre (entier), n , dtermine le nombre total de caractres
occups par la donne code, cest dire avant conversion en lecture ou aprs conversion en criture.
La signification de lventuel deuxime paramtre dpend du type de donne convertir.
Si le champ est plus large que ncessaire, la donne code est justifie droite ; en criture, le
champ est complt par des blancs gauche. Si la largeur n du champ de sortie est insuffisante
compte tenu de tous les caractres requis (signe, exposant ventuel avec son signe, ...), la conversion
en sortie est impossible et provoque lcriture de n signes * 25 .
entiers (en sortie, p prcise le nombre minimal de caractres de chiffres ou de lettres (hors
signe et blancs), quitte complter par des zros gauche) :
In [.p ] en base 10
rels (p spcifie le nombre de chiffres aprs la virgule) :
Fn.p en notation dcimale
en virgule flottante :
mantisse (<1) plus exposant : En.p
mantisse (<1) plus exposant avec q chiffres : En.p [eq ]
notation scientifique (mantisse entre 1 et 10) : ESn.p
notation ingnieur (mantisse entre 1 et 1000, exposant multiple de 3) : ENn.p
boolens : Ln
chane de caractres : An
Pour une analyse plus bas niveau, les descripteurs B, O et Z (voir les notations associes pour les
f2008 constantes, 2.4, p. 17) sont utilisables pour les entiers et, en fortran 2008, les rels :
Bn [.p ] en binaire
On [.p ] en octal
Zn [.p ] en hexadcimal
Enfin, un descripteur qualifi de gnral permet la conversion de tous les types de donnes : Gn.p .
Dans le cas des rels, il assure une conversion en virgule fixe (format Fn.p ) si possible (si la valeur
absolue de lexposant nest pas trop grande) ou sinon en virgule flottante (format En.p ).
Les nombres complexes sont traits comme un couple de nombres rels, entre parenthses et spars par une virgule, comme dans les constantes complexes ; ils ncessitent donc deux descripteurs
de format rels.
f95
Enfin, on peut demander que la largeur du champ sajuste lexcution de faon nutiliser
que le minimum de caractres ncessaires en spcifiant une largeur nulle pour les spcificateurs I,
25. Ce comportement est contraire celui du langage C, qui tendrait alors le champ occup pour convertir la
donne.
49
5.4.2
Descripteurs de contrle
50
prochain descripteur dp ou dc. Ce choix 31 peut aussi tre fait au niveau des instructions
OPEN (cf. 5.3.2, p. 42), READ (cf. 5.3.4, p. 44), et WRITE (cf. 5.3.5, p. 45), selon la syntaxe
decimal='point' ou decimal='comma'. Dans le cas o le sparateur dcimal est la virgule,
en entre, le sparateur entre valeurs passe de la virgule au point-virgule ; (cf. 5.1.2, p. 36).
Exemple :
PROGRAM decimal_comma
IMPLICIT NONE
REAL :: r,t
WRITE(*,*) 'entrer 2 rels spars par ; (notation dcimale avec virgule)'
READ(*, *, decimal='comma') r, t
WRITE(*, '("avec virgule", dc, 2e12.4)') r, t
WRITE(*, '("avec point ", dp, 2e12.4)') r, t
END PROGRAM decimal_comma
affiche :
avec virgule
avec point
5.4.3
0,1230E+01
0.1230E+01
0,5670E+09
0.5670E+09
Une liste de descripteurs, spare par des virgules, peut tre rige en groupe de descripteurs,
dlimit par des parenthses.
Un facteur de rptition (entier positif prfixant le descripteur) peut tre appliqu un
descripteur de format ou un groupe de descripteurs.
Chaque instruction dentre-sortie provoque le passage lenregistrement suivant, sauf si largument optionnel ADVANCE='no' a t spcifi.
En principe la liste dentre-sortie comporte autant dlments quil y a de descripteurs actifs
dans le format. Dans le cas contraire, on applique les principes suivants :
B
5.4.4
Comme, en accs squentiel, chaque instruction dentre-sortie fait par dfaut progresser dun
enregistrement dans le fichier, une boucle explicite sur le nombre dlments dun tableau avec une
instruction READ/WRITE dans la boucle ne permet pas de lire ou crire tous les lments du tableau
dans un enregistrement unique. On peut alors utiliser soit une instruction agissant sur le tableau
global, soit une boucle implicite. Mais, pour viter des changements denregistrements intempestifs,
il faut aussi sassurer (cf. 5.4.3, p. 50) que le format spcifi nest pas puis par la liste, ce qui
provoquerait une rexploration du format.
31. Avec le compilateur g95, il est possible de choisir la virgule comme sparateur dcimal au moment de lexcution, grce la variable denvironnement G95_COMMA boolenne, par dfaut FALSE (cf. E.5, p. 169).
32. Sauf pour les fichiers accs stream ou dans le cas o ADVANCE=no a t pralablement spcifi.
51
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PROGRAM format_tab
IMPLICIT NONE
INTEGER, DIMENSION(3) :: t = (/ 1, 2, 3 /)
! tableau initialis
INTEGER :: i
WRITE(*, '(3i4)') t(:)
! tableau global => affichage en ligne
DO i = 1, 3
! boucle explicite
WRITE(*, '(i4)') -t(i)
! => un changement d'enregistrement par ordre
END DO
! => affichage en colonne
WRITE(*, '(3i4)') (2* t(i), i=1, 3)! boucle implicite => affichage en ligne
WRITE(*, '(i4)') (-2*t(i), i=1, 3) ! format rexplor => en colonne
DO i = 1, 3
! boucle explicite
WRITE(*, '(i4)', ADVANCE='no') 3*t(i) ! mais option advance='no'
END DO
! => affichage en ligne
WRITE(*, *)
!passage l'enregistrement suivant la fin
END PROGRAM format_tab
Le programme prcdent affiche successivement :
t en ligne avec le tableau global (ligne 5) ;
-t en colonne avec la boucle explicite (lignes 6 8) ;
2*t en ligne avec la boucle implicite (ligne 9) ;
-2*t en colonne malgr la boucle implicite (ligne 10),
car le format ne satisfait quun lment de la liste et
est donc rexplor ;
3*t en ligne malgr la boucle explicite (lignes 11
13), grce ADVANCE='no'.
5.4.5
1
-1
-2
-3
2
-2
-4
-6
3
Format variable
Il nexiste pas proprement parler 33 de format variable en fortran. Mais il est possible de
dterminer le format lexcution, car il peut tre dfini par une variable chane de caractres.
Lopration seffectue donc en deux tapes, avec par exemple :
une instruction dcriture sur un fichier interne qui construit la variable de type chane contenant le format ;
linstruction dentre-sortie utilisant ce format.
titre dexemple, le programme suivant montre comment choisir le nombre n de chiffres (entre
1 et 9) pour afficher un entier i.
1
2
3
4
5
6
7
8
9
10
PROGRAM var_fmt
! format variable l'excution
IMPLICIT NONE
INTEGER :: i = 123 ! le nombre (au maximum 9 chiffres) afficher
INTEGER :: n
! le nombre de chiffres (<=9) pour l'afficher"
CHARACTER(LEN=1) :: chiffres ! n cod sur un caractre
CHARACTER(LEN=6) :: fmt="(i?.?)" ! la chane de format modifier
n = 4
! premier cas
! criture sur fichier interne (en format fixe !)
WRITE(fmt(3:3), '(i1)') n
33. Certaines extensions propritaires du fortran, notamment le compilateur dIntel (cf. chap. E.4, p. 168) , celui
dIbm, xlf, (cf. chap. E.1, p. 165) et celui de Portland (cf. chap. E.3, p. 167), permettent le format variable : des
expressions numriques entires encadres par les dlimiteurs < et > peuvent figurer dans la chane de caractres dfinissant le format ; elles sont interprtes chaque opration dentre-sortie. Par exemple, WRITE(*,"(I<j>.<j>)") j
permet dcrire lentier j avec exactement j chiffres. Le format variable est aussi disponible dans le langage C avec
le spcificateur de format * : printf("%*d\n", n, i); imprime lentier i avec n chiffres.
52
11
12
13
14
15
16
17
18
19
WRITE(fmt(5:5), '(i1)') n
WRITE(*, fmt) i
n = 7
! deuxime cas
! autre mthode : criture sur une sous-chane
WRITE(chiffres, '(i1)') n
! concatnation pour construire le format
fmt = "(i" // chiffres // "." // chiffres // ")"
WRITE(*, fmt) i
END PROGRAM var_fmt
Avec n=4 puis n=7, il produit les affichages successifs :
0123
0000123
5.5
5.5.1
34
35
36
36
37
37
|b8.8|...|00000001|00010100|********|********|********|********|00000000|
format B0 largeur ajustable (f95/2003 seulement)
|b0|.....|1|10100|100101100|11111111111111111111111111111111|111111111111111111111
11111101100|11111111111111111111111011010100|0|
|b0.4|...|0001|10100|100101100|11111111111111111111111111111111|111111111111111111
11111111101100|11111111111111111111111011010100|0000|
criture de donnes relles
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
5.5.2
1
2
3
4
5
6
7
8
9
10
11
12
53
54
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Liste plus courte => arrt avant le 1er descripteur actif inutilis
arrt aprs "[<" dans le format (8("[","<",i4,">","]"))
[<1>][<20>][<300>][<-1>][<-20>][<-300>][<
Liste plus courte avec ":" => arrt juste aprs le ":"
suivant le dernier descripteur actif utile
arrt via ":" (8("[","<",i4,">",:,"]"))
[<1>][<20>][<300>][<-1>][<-20>][<-300>
31
32
33
34
35
36
37
38
39
40
5.6
Les deux exemples lmentaires suivants prsentent lcriture dun fichier accs direct, sa
lecture avec affichage des donnes et la mise jour dun des enregistrements.
5.6.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PROGRAM direct
! fichier format en accs direct
IMPLICIT NONE
INTEGER :: ok=0, i, ir, nr
REAL :: a
INTEGER, PARAMETER :: iunit=11, n=10, recl=12
! cration du fichier en accs direct
OPEN(FILE='base.dat', UNIT=iunit, ACCESS='direct', RECL=recl, &
FORM='formatted', STATUS='replace')
ecriture: DO i=1, n
WRITE(UNIT=iunit, REC=i, FMT='(i4, 2x, f6.2)') 1000+i, 10*i + float(i)/10.
END DO ecriture
! lecture du fichier en accs direct et affichage
ir=1
lecture: DO ! on ne sait pas a priori o s'arrter
READ(UNIT=iunit, REC=ir, FMT='(i4, 2x, f6.2)', IOSTAT=ok) i, a
IF (ok /= 0) EXIT ! fin de fichier
WRITE(*, '(i4, 2x, f6.2)') i, a
ir = ir + 1
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
55
END DO lecture
WRITE(*,*) ir-1, ' enregistrements lus'
ok=0
! modification d'un enregistrement du fichier en accs direct
WRITE(*,*) 'choisir un numro d''enregistrement modifier'
READ *, nr
READ(UNIT=iunit, REC=nr, FMT='(i4, 2x, f6.2)') i, a
WRITE(*,*) 'ancienne valeur ', a, ' entrer la nouvelle valeur relle'
READ *, a
WRITE(UNIT=iunit, REC=nr, FMT='(i4, 2x, f6.2)') i, a
ir=1
relecture: DO ! on ne sait pas a priori o s'arrter
READ(UNIT=iunit, REC=ir, FMT='(i4, 2x, f6.2)', IOSTAT=ok) i, a
IF (ok /= 0) EXIT ! fin de fichier
WRITE(*, '(i4, 2x, f6.2)') i, a
ir = ir + 1
END DO relecture
WRITE(*,*) ir-1, ' enregistrements lus'
ok=0
CLOSE(iunit)
END PROGRAM direct
5.6.2
Dans le cas non-format, cest linstruction INQUIRE (ligne 8) qui permet de dterminer la taille
de lenregistrement, qui dpend du processeur.
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
PROGRAM direct
! fichier non format en accs direct
IMPLICIT NONE
INTEGER :: ok=0, i, ir, nr, recl
REAL :: a
INTEGER, PARAMETER :: iunit=11, n=10
! calcul de la longueur d'un enregistrement via INQUIRE
INQUIRE(IOLENGTH=recl) i, a !
WRITE(*,*) 'longueur d''un enregistrement ', recl
! cration du fichier en accs direct
OPEN(FILE='base.dat', UNIT=iunit, ACCESS='direct', RECL=recl, &
FORM='unformatted', STATUS='replace')
ecriture: DO i=1, n
WRITE(UNIT=iunit, REC=i) 1000+i, float(10*i) + float(i)/10.
END DO ecriture
! lecture du fichier en accs direct et affichage
ir=1
lecture: DO ! on ne sait pas a priori o s'arrter
READ(UNIT=iunit, REC=ir, IOSTAT=ok) i, a
IF (ok /= 0) EXIT ! fin de fichier
WRITE(*, '(i4, 2x, f6.2)') i, a
ir = ir + 1
END DO lecture
WRITE(*,*) ir-1, ' enregistrements lus'
ok=0
! modification d'un enregistrement du fichier en accs direct
WRITE(*,*) 'choisir un numro d''enregistrement modifier'
READ *, nr
READ(UNIT=iunit, REC=nr) i, a
56
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Chapitre 6
Procdures
6.1
6.1.1
Introduction
Intrt des procdures
Ds quun programme commence dpasser une page ou comporte des duplications dinstructions, il savre avantageux de le scinder en sous-ensembles plus lmentaires, nomms procdures,
qui seront appeles par le programme principal. En itrant ce processus, on structure le code source
en une hirarchie de procdures plus concises et modulaires, qui permet :
damliorer la lisibilit et de faciliter la vrification et la maintenance ;
de rutiliser des outils dj mis au point par dautres applications, au prix dune gnralisation
et dun paramtrage des procdures.
Par exemple, au lieu de dupliquer chaque usage toutes les instructions de calcul de la somme
des n premiers entiers (le seul paramtrage de cet exemple lmentaire), il est prfrable de les
crire une fois pour toutes dans un sous-programme not cumul qui sera appel chaque fois que
ncessaire. Ce sous-programme devra communiquer avec lappelant via deux arguments :
le nombre des entiers sommer fourni par lappelant (argument dentre) ;
la valeur de la somme renvoye lappelant (argument de sortie).
SUBROUTINE cumul(n, s)
IMPLICIT NONE
INTEGER, INTENT(in) :: n
INTEGER, INTENT(out) :: s
INTEGER
:: i
s = 0
DO i = 1, n
s = s + i
END DO
END SUBROUTINE cumul
! argument d'entre
! argument de sortie
! variable locale
58
CHAPITRE 6. PROCDURES
6.1.2
Les variables dclares au sein dune procdure sont, a priori, locales. On dit que leur porte
(scope) est limite lunit de programme. Par dfaut, les variables locales dune procdure nont
dexistence garantie que pendant son excution : elles sont qualifies dautomatiques ; elles ne sont
pas ncessairement mmorises 1 entre deux appels. Cest le cas de la variable i dans la procdure
cumul (cf. 6.1.1, p. 57).
On peut cependant forcer cette mmorisation, pour en faire des variables statiques, grce
B lattribut SAVE. Ne pas croire qualors la porte de la variable soit tendue : elle reste locale
mais est alors permanente. De plus, si une variable locale est initialise lors de sa dclaration,
elle devient immdiatement une variable statique 2 . Ne pas oublier que linitialisation est effectue
par le compilateur, une fois pour toute et diffre donc dune instruction excutable daffectation
effectue chaque appel 3 .
Par exemple, le sous-programme compte suivant affiche le nombre de fois quil a t appel. Si la
variable locale ntait pas statique, il faudrait passer n en argument de compte pour le mmoriser.
SUBROUTINE compte
IMPLICIT NONE
INTEGER, SAVE :: n = 0 !
n = n + 1
print *, n
END SUBROUTINE compte
Si lon souhaite rendre statiques toutes les variables locales dune procdure, ce qui est fortement
dconseill 4 , il suffit dinsrer lordre SAVE 5 avant toutes les dclarations. On peut aussi passer
une option au compilateur (cf. annexe E, p.165) : -fnoautomatic pour le compilateur gfortran,
-fstatic pour le compilateur g95, -qsave pour xlf dibm, -save pour le compilateur nag, -save
pour le compilateur ifort dintel, -static pour celui f90 de dec.
6.1.3
La communication entre une procdure et le programme appelant peut se faire par le passage
de paramtres appels arguments de la procdure. Ces arguments sont :
dclars comme arguments muets (dummy arguments) formels ou symboliques lors de la dfinition de la procdure ;
spcifis comme arguments effectifs (actual arguments) lors des appels de la procdure, pouvant prendre des valeurs diffrentes chaque appel.
En fortran, les passages darguments se font par rfrence 6 ce qui permet de partager les zones
mmoires des variables stockant les arguments entre appel et appelant. Lors de lappel de la
procdure, la liste des arguments effectifs doit respecter :
le nombre (hormis dans le cas darguments optionnels, cf. 6.5.1, p. 69),
lordre (hormis en cas de passage par mot-clef, cf. 6.5.2, p. 70),
1. Cela dpend des options de compilation qui peuvent forcer ou non un stockage statique ;
2. Par souci de lisibilit, on prcisera explicitement lattribut SAVE dans la dclaration de toute variable locale
initialise, au lieu de sappuyer sur le caractre statique implicite.
3. Au contraire, en C, une variable locale initialise est initialise lexcution, chaque appel la fonction hte ;
pour la rendre permanente (statique), il faut lui adjoindre lattribut static.
4. Sauf lors de certaines oprations de dboggage.
5. Linstruction SAVE doit alors tre seule sur la ligne. Elle peut aussi tre utilise sous la forme
SAVE :: liste_de variables pour dclarer statiques une liste de variables.
6. Au contraire, dans le langage C, les passages darguments se font par copie : cela permet deffectuer des
conversions si le type de largument effectif diffre de celui de largument formel. Mais, si lon souhaite modifier des
variables de lappelant, cela impose de transmettre des copies de leurs adresses la fonction appele : les arguments
de la fonction appele seront donc des pointeurs vers le type de la variable modifier ; on accdera alors aux zones
mmoire de ces variables par indirection depuis la fonction appele.
59
6.1.4
Si on avait prcis que largument base est un argument dentre, le compilateur naurait pas
accept la modification de la variable base dans le sous-programme aire.
SUBROUTINE aire(base, hauteur, surface)
IMPLICIT NONE
REAL, INTENT(IN)
:: base, hauteur
REAL, INTENT(OUT) :: surface
base = base / 2.
surface = base * hauteur
END SUBROUTINE aire
6.2
Sous-programmes et fonctions
60
CHAPITRE 6. PROCDURES
Les fonctions (function) sont des procdures qui renvoient un rsultat sous leur nom, rsultat
qui est ensuite utilis dans une expression au sein de lunit de programme appelante : la
simple mention de la fonction (avec ses arguments) dans lexpression provoque lexcution
des instructions que comprend la procdure. Cette notion sapparente ainsi celle de fonction
au sens mathmatique du terme.
Remarques :
Une fonction pourrait tre considre comme un cas particulier dun sous-programme, qui
renverrait un rsultat accessible sous le nom de la fonction. On peut donc en gnral transformer une fonction en sous-programme, quitte utiliser un argument supplmentaire pour
le rsultat et une ou ventuellement plusieurs variables supplmentaires dans lappelant, si
plusieurs appels la fonction coexistent dans une mme expression.
linverse, sil sagit deffectuer une action qui nest pas un simple calcul et par exemple
modifier les arguments dappel, on prfre le sous-programme. Paralllement, il est dusage de
ne pas modifier les paramtres dappel dune fonction, considrs comme arguments dentre
(cf. 6.1.4, p. 59).
6.2.1
Sous-programmes
! arguments muets
! dclaration des arguments d'entre
! dclaration des arguments de sortie
! calcul de surface
6.2.2
61
Fonctions
Une fonction est encadre par les dclarations FUNCTION, suivie du nom de la fonction et de la
liste ventuelle de ses arguments muets et linstruction END 10 , ventuellement suivie de FUNCTION,
ventuellement suivie du nom de la fonction 11 . Le type du rsultat peut tre soit dclar dans
lentte, comme prfixe de FUNCTION, soit dclar en mme temps que les arguments, mais il ne
faut pas lui attribuer une vocation INTENT(OUT). La fonction doit comporter une ou plusieurs
instructions qui affectent une valeur au rsultat.
! arguments muets
! dclaration du rsultat
! dclaration des arguments muets
! affectation du rsultat
6.3
62
6.3.1
CHAPITRE 6. PROCDURES
Les procdures internes sont compiles en mme temps que la procdure qui les appelle, ce qui
permet un contrle de la cohrence des arguments. Mais elles se prtent peu une rutilisation : on
les rservera des procdures trs dpendantes de leur procdure hte. Un seul niveau dimbrication
est possible : une seule instruction CONTAINS est possible dans une procdure 13 .
PROGRAM principal
...
CALL sub1(...)
...
x = fonc1(...)
...
CONTAINS
FUNCTION fonc1(...)
...
END FUNCTION fonc1
SUBROUTINE sub1(...)
...
END SUBROUTINE sub1
END PROGRAM principal
B
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Dans une procdure interne, toutes les entits dclares au sein de la procdure hte sont a
priori accessibles, sauf si on les redclare localement 14 , donc les communications entre lhte et la
procdure interne ne ncessitent pas forcment lemploi darguments.
Voici un exemple mettant profit le caractre global des variables, au dtriment de la lisibilit :
PROGRAM principal
! version sans passage d'arguments
IMPLICIT NONE
REAL :: base, hauteur, surface
! variables globales
base = 30.
hauteur = 2.
CALL aire
PRINT *, ' Surface = ', surface
! surface = 30.
base = 2.
hauteur = 5.
CALL aire
PRINT *, ' Surface = ', surface
! surface = 5.
CONTAINS
SUBROUTINE aire
! version dconseille
! ne pas redclarer base, hauteur ou surface (variables globales)
! sous peine de crer des variables locales distinctes !!!
surface = base * hauteur / 2.
! calcul de surface
END SUBROUTINE aire
END PROGRAM principal
Le simple ajout dune dclaration du type REAL :: base dans le sous-programme aire crerait
une variable locale base, empchant toute visibilit de la variable base du programme principal et
rendant le sous-programme inutilisable : on dit que la variable locale masque la variable globale.
Dans un souci de clart et de portabilit, on vitera de tirer parti de la visibilit des variables
globales 15 ; au contraire, on transmettra explicitement en arguments les variables partages et on
donnera aux variables locales la procdure interne des noms non utiliss par la procdure hte.
13. Sauf en ce qui concerne les procdures de module, qui peuvent inclure une procdure interne.
14. Si on dclare une variable locale dans une procdure interne avec le mme nom quune variable de porte
globale, la dclaration locale masque la variable globale.
15. En particulier, si une procdure interne a t crite en sappuyant sur cette lisibilit, elle ne sera pas aisment
transformable en procdure externe par la suite.
6.3.2
63
Procdures externes
Seules les procdures externes se prtent la rutilisation du code, mais nous verrons que le
contexte le plus fiable de leur utilisation est celui des modules (cf. 6.4, p. 64). Quelles soient places
dans des fichiers spars, ou dans le mme fichier que lappelant, leur compilation, hors contexte
des modules, se droule de faon indpendante. Les communications entre procdure externe et les
procdures appelantes se font au travers des arguments transmis.
Les procdures crites dans dautres langages sont videmment des procdures externes.
6.3.3
La notion dinterface
INTERFACE
! dbut de bloc d'interface
SUBROUTINE sub1(...)
... dclaration des arguments de sub1
END SUBROUTINE sub1
SUBROUTINE sub2(...)
... dclaration des arguments de sub2
END SUBROUTINE sub2
END INTERFACE
! fin de bloc d'interface
Par exemple, avec la fonction externe surf,
FUNCTION surf(base, hauteur)
IMPLICIT NONE
REAL
:: surf
REAL, INTENT(IN) :: base, hauteur
surf = base * hauteur / 2.
END FUNCTION surf
! dclaration du rsultat
! dclaration des arguments muets
! calcul de surface
64
CHAPITRE 6. PROCDURES
...
b1 = 30.
h1 = 2.
PRINT *, ' Surface= ', surf(b1, h1)
...
Linconvnient immdiat du bloc dinterface explicite est que la dclaration des arguments doit
tre fidlement duplique entre la procdure appele et la ou les blocs dinterface dans la ou les
procdures appelantes. Lors des mises jour du code, il est possible de crer des incohrences entre
ces dclarations et cette technique est donc dconseille. Seule linsertion des procdures externes
dans des modules (cf. 6.4, p. 64) fournit une solution satisfaisante cette question.
6.4
Les modules
Les modules (modules) sont des entits compilables sparment (mais non excutables) permettant dhberger des lments de code ou de donnes qui ont vocation tre utiliss par plusieurs
procdures sans ncessit de dupliquer linformation. Un module est dlimit par les instructions :
MODULE <nom_de_module > et END MODULE <nom_de_module >. Il peut comporter :
des dclarations de types drivs, (cf. 9.6, p. 106) et des dclarations de variables, susceptibles
dtre partags entre plusieurs units de programme,
un bloc dinterface,
et des procdures dites de module (module procedure) introduites par linstruction CONTAINS.
Linstruction USE <nom_de_module >, place avant toutes les dclarations, assure lunit de
programme ou la procdure o elle est place la visibilit de toutes les entits publiques 19 (variables, types drivs, procdures, blocs dinterface) du module 20 .
La compilation du module produit un fichier de module 21 , dont le nom est celui du module et le
suffixe gnralement .mod 22 . Ce fichier sera exploit par linstruction USE lors de la compilation des
modules appelants afin deffectuer notamment les contrles inter-procduraux de respect dinterface
(type, vocation des arguments, ...) : il est donc ncessaire de compiler le ou les modules avant les
procdures qui les utilisent.
Il est fortement recommand dinclure les procdures dans des modules afin que les entits qui
les utilisent disposent dune interface explicite extraite automatiquement par le compilateur.
6.4.1
! dclaration du rsultat
65
La visibilit du module m_mod et donc de sa procdure interne surf, est assure dans une procdure
appelante par linstruction USE m_mod :
...
USE m_mod
! assure la visiblit du module sans duplication de code
REAL :: b1, h1
b1 = 30.
h1 = 2.
PRINT *, ' Surface= ', surf(b1, h1)
! arguments effectifs de mme type
...
La compilation du module m_mod cre un fichier de module m_mod.mod (dont le nom ne dpend B
pas du nom du fichier source) qui sera consult par le compilateur lorquil rencontrera linstruction
USE m_mod et qui assurera aux units de programmes qui utilisent le module la visibilit de ce
quil dfinit (dclarations, interfaces, ...).
Si on place le module m_mod dans un fichier source spar f_modul.f90, il faut le compiler
(avant les units de programme qui lui font appel), via la commande gfortran -c f_modul.f90,
qui crera deux fichiers (cf. Figure 6.1, p. 66) :
un fichier de module de suffixe .mod : m_mod.mod destin au compilateur ;
un fichier objet de suffixe .o : f_modul.o qui sera utilis par lditeur de liens pour construire
lexcutable partir des objets (via la commande gfortran f_ppal.o f_modul.o -o f_ppal.x).
Une autre mthode consisterait lancer une seule commande :
gfortran f_modul.f90 f_ppal.f90 -o f_ppal.x
(en compilant le module avant lappelant) qui dclencherait la compilation, puis ldition de liens.
6.4.2
66
CHAPITRE 6. PROCDURES
fichier source
PROGRAM ppal
...
USE surface
...
fichier source
f_ppal.f90
MODULE surface
CONTAINS
...
f_surf.f90
END PROGRAM ppal
Compilations
2) f90 c f_ppal.f90
fichier de module
1) f90 c f_surf.f90
surface.mod
fichier objet
fichier objet
f_ppal.o
f_surf.o
dition de liens
3) f90 f_ppal.o f_surf.o o f_ppal.x
fichier excutable
f_ppal.x
Figure 6.1 Modules et fichiers impliqus en compilation spare. Respecter lordre des trois
oprations : 1) compilation du module, 2) compilation de lappelant, 3) dition de liens.
USE initialisation ! rend explicite l'interface de la procdure de module init
REAL :: y, x
CALL init
...
y = sin ( pi * x )
...
END PROGRAM principal
Cette technique de partage des informations entre procdures est puissante, mais elle nest pas
aussi explicite que le passage par argument qui reste la mthode privilgier. Elle reste cependant
incontournable dans le cas dappels de procdures imbriqus o la procdure intermdiaire ne
peut pas voir les donnes transmettre 23 : un exemple classique est lapplication dune procdure
fonctionnelle (intgration, drivation, ...) une fonction dune variable, qui possde des paramtres
que la procdure fonctionnelle ignore alors quelle effectue des appels la fonction. Le seul moyen
23. La transmission des donnes seffectue linsu de la procdure intermdiaire : celle qui lappelle et celle quelle
appelle se partagent les donnes grce un USE commun inconnue de la procdure intermdiaire !
67
MODULE mod_fonct
! module dfinissant la fct effective
IMPLICIT NONE
INTEGER :: puissance
! masqu la procdure d'intgration
CONTAINS
FUNCTION fonct(x)
! dfinition de la fonction effective
REAL, INTENT(IN)
:: x
REAL
:: fonct
fonct = x**puissance
! paramtr par puissance par exemple
END FUNCTION fonct
END MODULE mod_fonct
!
MODULE mod_integr
! module dfinissant le sous-programme
IMPLICIT NONE
CONTAINS
SUBROUTINE integr(f, xmin, xmax, somme, n_points) ! f = argument muet
REAL, INTENT(IN)
:: xmin, xmax
REAL, INTENT(OUT)
:: somme
INTEGER, INTENT(IN)
:: n_points
INTERFACE
! interface de la fonction muette
FUNCTION f(x)
REAL, INTENT(IN)
:: x
REAL
:: f
END FUNCTION f
END INTERFACE
REAL
:: x, pas
INTEGER
:: i
pas = (xmax - xmin) / n_points
somme = pas * (f(xmin) + f(xmax)) / 2.
DO i = 2, n_points
x = xmin + (i - 1) * pas
somme = somme + pas * f(x)
END DO
END SUBROUTINE integr
END MODULE mod_integr
PROGRAM principal
USE mod_fonct
! accs au module de la fonction effective
USE mod_integr
! accs au module du sous-programme
IMPLICIT NONE
REAL
:: x0 = 0., x1 = 1., s
INTEGER :: n = 100
puissance = 1
! ne pas redclarer: visibilit assure par use
CALL integr(fonct, x0, x1, s, n)
WRITE(*,*) 'somme de f(x) = x : ', s
puissance = 2
! partag avec fonct, mais inconnu de integr
CALL integr(fonct, x0, x1, s, n)
WRITE(*,*) 'somme de f(x) = x*x : ', s
END PROGRAM principal
6.4.3
lments dencapsulation
Les modules permettent de faciliter la rutilisation des codes et leur maintenance. Au sein dune
procdure que lon souhaite partager, on peut distinguer :
68
CHAPITRE 6. PROCDURES
linterface (qui doit rester parfaitement stable), qui doit tre visible de ses procdures appelantes et doit donc tre publique ;
les dtails de limplmentation (qui peuvent voluer) quil est souvent prudent de masquer
aux utilisateurs, en les rendant privs.
Par dfaut, les entits (types drivs, variables, procdures) dfinies dans un module mon_module
sont publiques et donc rendues accessibles (et, pour les variables, modifiables) par linstruction USE
mon_module. lintrieur dun module, on peut utiliser la dclaration PRIVATE pour masquer toutes
les entits qui suivent cette dclaration en dehors du module o elles sont dclares. On dispose
aussi des attributs PUBLIC et PRIVATE pour spcifier plus finement la visibilit des objets lors de
leur dclaration.
Par ailleurs, on peut aussi, dans la procdure appelante, restreindre la visibilit des objets
publics dun module en spcifiant la liste exhaustive des objets auxquels on souhaite accder 24 :
USE nom_de_module , ONLY: liste_d'objets
Ces deux approches ne sont pas destines aux mmes usages : la premire mthode permet au
concepteur de la procdure de restreindre la visibilit alors que la seconde permet lutilisateur de
choisir les procdures dont il souhaite faire usage.
B
De plus, lorsque lon rutilise des modules rdigs dans un autre contexte, on peut tre confront
des conflits de nommage des identificateurs. Linstruction USE permet le renommage des entits
publiques du module quelle appelle, selon la syntaxe suivante, similaire celle de lassociation
dun pointeur (cf. 11.1.1, p. 119) :
USE nom_de_module , nom_local => nom_dans_le_module
Ce renommage permet aussi une sorte de paramtrage au niveau de la compilation (cf. lexemple
2.5.4 p. 19).
Enfin, sans restreindre la visibilit dune variable, on souhaite parfois rserver aux procdures
f2003 du module o elles sont dclares le droit de modifier leur valeur. La norme fortran 2003 a introduit
lattribut PROTECTED dans cet objectif. Le programme suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
MODULE m_protege
IMPLICIT NONE
INTEGER, PRIVATE
:: m ! non visible en dehors du module
INTEGER, PUBLIC
:: n ! visible et modifiable en dehors du module
INTEGER, PROTECTED :: p ! visible mais non modifiable en dehors du module
! => oblige passer par une des procdures du module pour le modifier
CONTAINS
SUBROUTINE sub1 ! pas de paramtres : m, n et p ont une porte suffisante
m = 1
n = 2
p = 3
WRITE(*,*) "m, n, p dans sub1 ", m, n, p
END SUBROUTINE sub1
SUBROUTINE sub2 ! pas de paramtres : m, n et p ont une porte suffisante
m = 10
n = 20
p = 30
WRITE(*,*) "m, n, p dans sub2 ", m, n, p
END SUBROUTINE sub2
END MODULE m_protege
21
22
23
24
25
26
27
28
29
PROGRAM t_protege
USE m_protege
CALL sub1
WRITE(*,*) "n, p dans l'appelant aprs appel de sub1 ", n, p
CALL sub2
WRITE(*,*) "n, p dans l'appelant aprs appel de sub2 ", n, p
! m = -1 ! serait incorrect car m n'est pas visible ici (priv)
n = -2 ! autoris car n est public dans le module
24. Cette technique savre indispensable lorsque lon utilise une bibliothque : elle permet dviter les trop nombreux avertissements concernant les procdures de la bibliothque non appeles.
30
31
32
33
69
! p = -3 ! serait incorrect car p est protg => non modifiable hors du module
! comparer avec l'attribut intent(in) mais ici dans l'appelant
WRITE(*,*) "n, p dans l'appelant aprs affectation de n ", n, p
END PROGRAM t_protege
produit laffichage :
m,
n,
m,
n,
n,
f2003
n, p dans sub1 1 2 3
p dans l'appelant aprs appel de sub1 2 3
n, p dans sub2 10 20 30
p dans l'appelant aprs appel de sub2 20 30
p dans l'appelant aprs affectation de n -2 30
6.4.4
Contrairement aux procdures, en fortran 95, les interfaces encapsules dans un module nont
pas de visibilit sur les entits dclares (ou simplement visibles) dans le module qui les hberge. Le
fortran 2003 a introduit linstruction IMPORT qui permet dans une interface, daccder aux entits
du module soit globalement si on ne spcifie pas de liste, soit seulement celles spcifies par la
liste (voir par exemple les sous-programmes 12.4.2, p. 131).
f2003
6.4.5
Modules intrinsques
6.5
6.5.1
Fonctionnalits avances
Arguments optionnels
Lors de la dclaration dune procdure, il est possible de prciser que certains arguments pourront tre omis lors de certains appels, en leur spcifiant lattribut OPTIONAL. Sauf utiliser un
passage darguments par mot-clef (cf. 6.5.2, p. 70), les arguments optionnels doivent tre placs
en fin de liste 25 . Lors de lcriture de la procdure, il faut prvoir un traitement conditionnel suivant que largument a t ou non fourni lors de lappel ; la fonction intrinsque dinterrogation
PRESENT(<arg> ), de rsultat boolen, permet de tester si largument a t effectivement pass.
Par exemple, le sous-programme integr de calcul dintgrale dune fonction (pour le moment
fixe et non paramtre) sur un intervalle [xmin, xmax] pass en argument, comporte deux paramtres optionnels : le nombre de points dvaluation (n_points) et la prcision relative (precision)
demande pour le calcul.
MODULE util
IMPLICIT NONE
CONTAINS
SUBROUTINE integr(xmin, xmax, somme, precision, n_points)
REAL, INTENT(IN)
:: xmin, xmax ! arguments d'entre requis
25. Si tous les arguments sont omis, lappel se fera sous la forme CALL sub() pour un sous-programme et fct()
pour une fonction.
70
CHAPITRE 6. PROCDURES
REAL, INTENT(OUT)
:: somme
! argument de sortie requis
REAL, INTENT(IN), OPTIONAL
:: precision ! argument d'entre optionnel
INTEGER, INTENT(IN), OPTIONAL :: n_points
! argument d'entre optionnel
!
INTEGER
:: points
! variable locale indispensable
...
IF( PRESENT(n_points) ) THEN
points = n_points
! utiliser la valeur transmise
ELSE
points = 200
! valeur par dfaut
END IF
...
somme = ...
END SUBROUTINE integr
END MODULE util
!
PROGRAM principal
USE util
...
CALL integr(xmin1, xmax1, somme1, .1, 100) ! tous les arguments sont passs
CALL integr(xmin2, xmax2, somme2, .1)
! n_points est omis
...
END PROGRAM principal
Remarques : dans cet exemple, la variable locale points est ncessaire, car n_points, dclar
comme argument dentre (INTENT(IN)), ne peut pas tre modifi dans la procdure. Noter par
ailleurs, quil faut conditionner toute rfrence au paramtre optionnel sa fourniture effective et
que la formulation suivante
IF( PRESENT(n_points) .AND. n_points > 1 ) points = n_points
est incorrecte car elle suppose que le second oprande du .AND. nest pas valu (cf. 3.3, p. 24) si
le paramtre optionnel na pas t spcifi.
6.5.2
Ds le fortran 77, certaines procdures intrinsques comme linstruction OPEN par exemple
autorisaient le passage dargument par mot-clef, ce qui permettait de saffranchir de lordre des
arguments. Cependant le passage dargument aux procdures dfinies par lutilisateur restait ncessairement positionnel.
En fortran 90, on peut passer certains arguments par un mot-clef, en utilisant la syntaxe
<argument_muet> = <argument_effectif> . Cette possibilit prend tout son sens quand la procdure possde des arguments optionnels. En effet, dans ce cas, le passage par mot-clef est le seul
moyen de fournir un argument qui suit un argument optionnel non spcifi lors de lappel 26 . Plus
prcisment, ds quun argument optionnel a t omis, les arguments qui le suivent ne peuvent plus
tre passs de faon positionnelle.
En reprenant lexemple prcdant (cf. 6.5.2, p. 70), on peut mixer les modes de passage darguments :
...
CALL integr(0., 1., precision=.1, n_points=100, somme=resultat)
!
plus de passage positionnel partir du troisime
! tous les arguments passs, mais en ordre modifi avec les mots-clefs
CALL integr(xmin2, xmax2, somme2, n_points=500)
26. Un appel du type f(x1, , x3) nest pas autoris en fortran.
71
! precision est omis, mais on veut passer n_points, donc par mot-clef car aprs
...
6.5.3
72
28
29
30
31
32
33
34
35
36
37
38
39
DO i = 2, n_points
x = xmin + (i - 1) * pas
somme = somme + pas * f(x)
END DO
END SUBROUTINE integr
! fonction externe
FUNCTION fonct(x)
IMPLICIT NONE
REAL, INTENT(IN)
REAL
fonct = x
END FUNCTION fonct
CHAPITRE 6. PROCDURES
Lexemple suivant prsente encore une version du programme principal avec des procdures
externes, mais qui comporte aussi les interfaces explicites du sous-programme integr (lignes 12
18) dans le programme principal et de la fonction symbolique f (lignes 29 34) au sein du
sous-programme integr. Ces deux interfaces sont facultatives ici, mais vivement conseilles.
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
Enfin, pour viter la lourdeur des interfaces explicites, on prfre souvent intgrer les procdures dans des modules. Avec les modules mod_fonct (lignes 2 11) pour la fonction effective et
73
mod_integr (lignes 13 38) pour le sous-programme, seule demeure linterface explicite (lignes 23
28) de la fonction symbolique 29 f.
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
29. on pourrait la remplacer par une simple dclaration de f, ligne 21, moins prcise, car elle ne permet pas de
vrifier le type des arguments.
74
f2003
CHAPITRE 6. PROCDURES
6.5.4
La dclaration PROCEDURE
En fortran 2003, si linterface dune procdure fmodele est visible dans une unit de compilation, on peut sen servir comme modle pour dclarer linterface dautres procdures de mme
interface grce la dclaration PROCEDURE, avec pour argument le nom de la procdure modle.
PROCEDURE(fmodele ) :: f1 , f2
Cette dclaration admet des attributs optionnels, en particulier POINTER, PUBLIC ou PRIVATE. Cette
possibilit, utilise notamment pour les pointeurs de procdures (cf. 11.4, p. 126) et les procdures
passes en argument est le plus souvent associe la dclaration dune interface abstraite de
prfrence un modle. Cest dans ce cadre que sont prsents les exemples (cf. 6.5.5, p. 74). Bien
entendu, PROCEDURE ne peut pas tre utilis pour des procdures gnriques : cette dclaration
dinterface est rserve aux procdures spcifiques (cf. 10.1, p. 111).
Noter que PROCEDURE permet aussi de dclarer des procdures dinterface implicite avec un
argument vide (quivalent dun EXTERNAL), ou dinterface incomplte avec seulement le type de
retour dans le cas dune fonction (par exemple PROCEDURE(REAL) :: freel pour une fonction
valeur de type REAL sans prcision sur les arguments).
f2003
6.5.5
Interfaces abstraites
Lorsque lon doit dclarer linterface commune de plusieurs procdures, il est prfrable de
dclarer une seule fois cette interface, dans un bloc dit dinterface abstraite, en la nommant tel
un type particulier. On peut ensuite faire rfrence cette interface nomme via la dclaration
PROCEDURE pour dclarer de faon beaucoup plus synthtique les interfaces des procdures effectives.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
MODULE abstr_interf
IMPLICIT NONE
! bloc d'interface abstraite avec des interfaces nommes
ABSTRACT INTERFACE
FUNCTION fr_de_r(x)
! fonction relle d'un rel
REAL :: fr_de_r
REAL, INTENT(in) :: x
END FUNCTION fr_de_r
FUNCTION fr_de_2r(x, y)
! fonction relle de 2 rels
REAL :: fr_de_2r
REAL, INTENT(in) :: x, y
END FUNCTION fr_de_2r
END INTERFACE
END MODULE abstr_interf
Ces interfaces abstraites, sortes de patrons de procdures pourront tre invoques pour
rendre explicite linterface de procdures dinterface a priori implicite respectant ce modle (par
exemples dfinies hors module ou dans un module non visible du ct appelant). Il suffit de dclarer
PROCEDURE avec comme argument le nom de linterface abstraite pour expliciter linterface.
Dans lexemple suivant, le non-respect des interfaces est dtect ds la compilation :
75
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PROGRAM t_abstract
USE abstr_interf
IMPLICIT NONE
PROCEDURE(fr_de_r) :: f1
! mais interface rendue ainsi visible
PROCEDURE(fr_de_2r) :: f2
REAL :: x, y
INTEGER :: i
x = 10
y = 5
WRITE(*,*) x, f1(x)
WRITE(*,*) i, f1(i) ! => erreur de compilation
! Error: Type mismatch in parameter 'x'
! Passing INTEGER(4) to REAL(4)
WRITE(*,*) x, y, f2(x, y)
WRITE(*,*) f2(x) ! => erreur de compilation
! Error: Missing actual argument for argument 'y'
END PROGRAM t_abstract
Les interfaces abstraites prennent tout leur intrt dans les cas o plusieurs procdures de mme
interface sont susceptibles dtre utilises :
lorsquune mthode sapplique une procdure passe en argument (cf. 6.5.3, p. 71) ;
lorsquon utilise des pointeurs de procdures (cf. 11.4, p. 126) pour une partie de code pouvant
sappliquer plusieurs procdures.
Lexemple de la mthode dintgration integr prend alors la forme suivante :
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
76
36
37
38
39
40
41
42
43
44
45
46
47
CHAPITRE 6. PROCDURES
fonct = x
! par exemple
END FUNCTION fonct
END MODULE mod_fonct
PROGRAM principal
USE mod_fonct
! visibilit de l'interface de la fonction effective
USE mod_integr
! visibilit de l'interface de la mthode
IMPLICIT NONE
REAL :: x0 = 0., x1 = 1., s
INTEGER :: n = 100
CALL integr(fonct, x0, x1, s, n)
WRITE(*,*) 'somme = ', s
END PROGRAM principal
6.5.6
Procdures rcursives
Lorsquune procdure sappelle elle-mme, de faon directe ou indirecte, au travers dune chane
dautres procdures, on la qualifie de rcursive. Contrairement au fortran 77, le fortran 90 permet la rcursivit directe ou indirecte des procdures, par la dclaration explicite via le mot-clef
RECURSIVE.
Mais, dans le cas dune fonction rcursive, le nom de la fonction ne peut plus tre utilis pour
B dsigner le rsultat : on doit alors introduire, aprs le mot-clef RESULT 30 , le nom de la variable
qui stockera le rsultat. Dans une procdure rcursive, une variable avec lattribut SAVE (cf. 6.1.2,
p. 58) est partage par toutes les instances de la procdure, alors que ses variables automatiques
sont spcifiques de chaque instance.
Larchtype de la rcursivit directe est le calcul de la factorielle : n! = n (n 1)! avec 1! = 1,
B quil est imprudent de programmer en type entier sur 32 bits cause du dpassement de capacit
ds n dpasse 12.
INTEGER RECURSIVE FUNCTION fact(n) RESULT(factorielle)
! le type entier s'applique en fait au rsultat : factorielle
IMPLICIT NONE
INTEGER, INTENT(IN)
:: n
IF ( n > 0 ) THEN
factorielle = n * fact(n-1)
! provoque un nouvel appel de fact
ELSE
factorielle = 1
! ne pas oublier d'arrter la rcursion
END IF
END FUNCTION fact
On peut aussi programmer la factorielle comme sous-programme :
RECURSIVE SUBROUTINE fact(n, factorielle)
IMPLICIT NONE
INTEGER, INTENT(IN)
:: n
INTEGER, INTENT(OUT) :: factorielle
IF ( n > 0 ) THEN
CALL fact(n-1, factorielle)
! appel rcursif
factorielle = n * factorielle
ELSE
factorielle = 1
END IF
END SUBROUTINE fact
30. Lutilisation de la clause RESULT est aussi possible pour des fonctions non rcursives.
77
On peut rencontrer la rcursivit indirecte lors des calculs numriques dintgrale double, si on
utilise la mme procdure
R x integr (cf. 6.5.3, p. 71) pour intgrer selon chacune des variables : la
fonction de y, F (y) = x01 f (x, y) dx, fait appel, dans son valuation numrique pour chaque valeur
de y, la procdure integr, et lintgrale double sera value en appliquant integr F (y). La
procdure integr devra donc tre dclare rcursive. De plus, il faudra masquer le paramtre y B
lors de lintgration en x pour simuler le passage dune fonction dune seule variable la procdure
dintgration : il sera transmis F par partage via un module (cf. 6.4.2, p. 66).
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
MODULE mod_fonct
! module dfinissant la fct effective
IMPLICIT NONE
REAL :: yy
! y fix
CONTAINS
FUNCTION fonct(x)
! dfinition de la fonction effective de x
REAL, INTENT(IN)
:: x
REAL
:: fonct
fonct = x**2 - yy**2
END FUNCTION fonct
END MODULE mod_fonct
!
MODULE mod_param_y
! module des paramtres cachs fonct
IMPLICIT NONE
REAL :: x0, x1
! bornes en x
INTEGER :: nx
! nombre de points en x
END MODULE mod_param_y
!
MODULE mod_integr
! module dfinissant le sous-programme
IMPLICIT NONE
CONTAINS
RECURSIVE SUBROUTINE integr(f, xmin, xmax, somme, n_points)
! f = argument muet de type fonction
REAL, INTENT(IN)
:: xmin, xmax ! bornes
REAL, INTENT(OUT)
:: somme
! rsultat
INTEGER, INTENT(IN)
:: n_points
! nombre de points
INTERFACE
! interface de la fonction muette
FUNCTION f(x)
REAL, INTENT(IN)
:: x
REAL
:: f
END FUNCTION f
END INTERFACE
REAL
:: x, pas
INTEGER
:: i
pas = (xmax - xmin) / n_points
somme = pas * (f(xmin) + f(xmax)) / 2.
DO i = 2, n_points
x = xmin + (i - 1) * pas
somme = somme + pas * f(x)
END DO
END SUBROUTINE integr
END MODULE mod_integr
42
43
44
45
46
47
48
49
50
51
52
MODULE mod_fy
USE mod_param_y
USE mod_fonct, only: yy, fonct
USE mod_integr
CONTAINS
FUNCTION fy(y)
REAL
REAL, INTENT(IN)
REAL
yy = y
78
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
f95
CHAPITRE 6. PROCDURES
6.5.7
Procdures pures
Dans certaines circonstances de paralllisation des codes, comme lintrieur dune structure
FORALL (cf. 7.4.6, p. 88), seules sont admises les procdures sans effet de bord. Un attribut PURE
permet de certifier quune procdure est sans effet de bord, cest dire :
quelle ne modifie pas de variables non locales : en particulier, sil sagit dune fonction, tous
ses arguments doivent possder lattribut INTENT(IN) ;
quelle ne modifie pas de variables non locales soit visibles car la procdure est interne, soit
rendues visibles par un USE ;
quelle ne fait pas de lecture ou dcriture sur un fichier externe : en particulier, elle ne peut
rien lire au clavier ou afficher ;
quelle ne contient pas de variable locale avec lattribut SAVE : en particulier, pas de variable
initialise la dclaration (cf. 2.5, p. 17) ;
quelle ne comporte pas dinstruction STOP.
Ces conditions imposent quune procdure pure nappelle que des procdures pures. Toutes
les procdures intrinsques sont pures. Les procdures lmentaires (cf. 6.5.8, p. 78) possdent
automatiquement lattribut PURE.
f95
6.5.8
Procdures lmentaires
Une procdure est qualifie dlmentaire (attribut ELEMENTAL) si elle peut tre appele avec
des arguments tableaux conformes de la mme faon quavec des arguments scalaires. La majorit
des procdures intrinsques (cf. annexe A, p. 138) sont lmentaires.
Une procdure lmentaire est automatiquement pure, mais de plus tous ses arguments muets
(ainsi que la valeur renvoye pour une fonction) doivent tre des scalaires sans lattribut POINTER.
Une procdure rcursive (cf. 6.5.6, p. 76) ne peut pas tre lmentaire. Une procdure lmentaire
non-intrinsque ne peut pas tre passe en argument effectif dune autre procdure.
ELEMENTAL REAL FUNCTION my_log(x) ! une fonction log protge pour les x<=0
REAL, INTENT(IN) :: x
IF ( x > 0 ) THEN
my_log = LOG (x)
ELSE
my_log = -1000.
END IF
END FUNCTION my_log
Chapitre 7
Tableaux
7.1
Gnralits
Un tableau (array) est un ensemble rectangulaire 1 dlments de mme type 2 (plus prcisment de mme variante de type), reprs au moyen dindices entiers. Par opposition, on qualifiera
de scalaire un lment du tableau. Les lments dun tableau sont rangs selon un ou plusieurs
axes appels dimensions du tableau. Dans les tableaux une dimension (qui permettent de
reprsenter par exemple des vecteurs au sens mathmatique du terme), chaque lment est repr
par un seul entier, mais le fortran accepte des tableaux jusqu 7 dimensions 3 , o chaque lment
est dsign par un 7-uplet dentiers 4 .
7.1.1
:: vecteur
REAL, DIMENSION(-2:2)
:: table
!
!
!
!
tableau
indics
tableau
indics
1. Lassemblage non-rectangulaire dlments du mme type est possible grce aux pointeurs, cf. 11.3, p. 123.
2. Lassemblage dlments de types diffrents est possible au sein dun type driv ou structure, cf. chapitre 9,
p. 102. Mais les lments constitutifs dun tableau peuvent tre des structures, et ... les lments de ces structures
peuvent eux-mmes comporter des tableaux !
3. Cette limite est porte 15 en fortran 2008.
4. Certains termes employs en informatique propos des tableaux peuvent avoir un sens profondment diffrent
de leur sens en mathmatiques dans le domaine des espaces vectoriels. Cest le cas, par exemple, de la notion
de dimension : un vecteur trois dimensions de la gomtrie dans lespace peut tre reprsent par un tableau
monodimensionnel, de rang un et de taille trois.
5. Ne pas confondre avec le C o lindexation des tableaux commence zro.
6. Noter que deux tableaux conformants nont pas forcment les mmes bornes.
79
80
CHAPITRE 7. TABLEAUX
REAL, DIMENSION(2,3)
:: m
Les tableaux vecteur et table sont de dimension 1 et ont mme profil : ils sont conformants.
Un lment (scalaire) dun tableau est dsign en prcisant entre parenthses les indices selon
toutes ses dimensions, spars par des virgules. vecteur(2), table(-1) et m(2,2) sont des lments
des tableaux dfinis prcdemment. Cependant, le fortran distingue un tableau monodimensionnel
un seul lment de llment scalaire quil contient :
INTEGER, DIMENSION(1)
INTEGER
i = t(1)
i = t
7.1.2
:: t
:: i
!
!
!
!
tableau un lment
entier
affectation autorise
affectation illicite
Le caractre multidimensionnel des tableaux nest pas respect dans la mmoire des calculateurs,
o les tableaux sont en gnral stocks dans une mmoire un seul indice dadressage. En fortran,
lordre classiquement utilis pour stocker les lments des tableaux est celui o le premier
indice varie le plus vite 7 , cest dire que deux lments dont seul le premier indice diffre dune
unit sont contigus en mmoire.
Pour des tableaux de rang 2, cela signifie que le rangement seffectue colonne par colonne 8 .
Par exemple, la matrice m de 2 lignes par 3 colonnes (au sens mathmatique), est stocke dans le
tableau m dimensionn par lattribut DIMENSION(2,3) de la manire suivante :
matrice
1
m11
3
m12
5
m13
2
m21
4
m22
6
m23
tableau associ
m(1,1)
m(2,1)
m(1,2)
m(2,2)
m(1,3)
m(2,3)
Mais la norme fortran 90 ne spcifie pas lordre de rangement en mmoire des lments dun
tableau, laiss la disposition du compilateur, entre autres pour des raisons defficacit de calcul
suivant les processeurs utiliss : on ne pourra donc pas sappuyer sur cet ordre de stockage pour le
passage de tableaux multidimensionnels en argument de procdures 9 .
Cependant, cet ordre est respect dans les instructions dentre-sortie et, par exemple, par la
fonction RESHAPE (cf. 7.4.3, p. 86) de restructuration des tableaux.
Un exemple de lecture de matrice errone
En particulier, une lecture globale de matrice dans un fichier par un seul ordre READ (sans boucle
implicite) stockera les lments contigus (sur une mme ligne) dans le fichier en incrmentant
B lindice le plus gauche du tableau de rang 2, cest--dire... celui des lignes ! Dans le cas dun
matrice carre, cette lecture remplira le tableau avec la transpose de la matrice figurant sous la
forme habituelle dans le fichier.
7. Contrairement au choix fait en langage C, o lindice qui varie le plus rapidement est celui de la dernire
dimension. Dailleurs, en C, il ny a pas, proprement parler, de tableaux multidimensionnels, mais des tableaux
de tableaux. Cette reprsentation implique une hirarchie qui, par exemple dans le cas des tableaux 2D, permet de
dsigner une ligne, mais pas une colonne de matrice.
8. On suppose ici que, dans un tableau de rang 2 reprsentant un objet mathmatique de type matrice, on
attribue au premier indice le rle de numro de ligne et au deuxime celui de numro de colonne. Cette convention,
qui semble naturelle, peut tre inverse pour des raisons de performance des codes. Par exemple, dans des boucles
imbriques portant sur les lignes et les colonnes, il est plus efficace daccder des lments contigus en mmoire
dans la boucle interne, qui doit donc porter sur lindice rapide, cest dire le premier.
9. En fortran 77, o lordre de stockage tait garanti, on mettait profit la disposition des lments des tableaux
pour passer des sections de tableaux multidimensionnels en tant quarguments effectifs des procdures dans lesquelles largument muet tait dclar monodimensionnel : il suffisait que la section de tableau stende uniquement
selon la dernire dimension du tableau.
81
11
21
12
,
22
11 21
; en particulier mat(1,2) = 21
12 22
et mat(2,1) = 12. Mais laffichage global en format libre reproduira (sur une seule ligne) lordre
du fichier initial, 11 12 21 22 , bien que le premier indice du tableau mat soit celui des colonnes.
les ordres prcdents rempliront le tableau mat avec :
7.1.3
Constructeurs de tableaux
::
::
::
::
vecteur = (/ 3, 5, 1 /)
vecteur = [ 3, 5, 1 ] ! en fortran 2003
i
v = (/ (2*i, i=1, 4), vecteur /) ! boucle implicite
7.2
Sections de tableaux
Une section de tableau est un sous-tableau, de rang et dtendues infrieurs ou gaux ceux du
tableau dont il est extrait.
82
CHAPITRE 7. TABLEAUX
7.2.1
Sections rgulires
Une section rgulire (regular section) est un sous-tableau dont les indices dans le tableau initial
sont en progression arithmtique. Une section rgulire peut donc tre dfinie, pour chaque dimension, par un triplet <debut >:<fin >:<pas > 10 . Chacun des lments du triplet est optionnel et les
valeurs par dfaut sont :
<debut > : la borne infrieure selon la dimension, telle quelle a t spcifie lors de la dclaration (donc 1 si elle na pas t prcise dans la dclaration)
<fin > : la borne suprieure selon la dimension, telle quelle a t spcifie lors de la dclaration
<pas > : 1
Noter que le pas peut tre ngatif, ce qui permet dinverser lordre des lments. Comme dans les
boucles DO, si le pas est diffrent de 1, il est possible que la borne finale ne soit pas atteinte.
REAL, DIMENSION(3,6)
:: matrice
REAL, DIMENSION(3)
:: vecteur
REAL, DIMENSION(3,3)
:: sous_matrice
vecteur(:) = matrice(:,5)
vecteur(:) = matrice(1,1:3)
sous_matrice(:,:) = matrice(:,2:6:2)
matrice(1:2,2:6:2)
x
x
x
x
!
!
!
!
!
!
!
matrice(::2,2:6:2)
x
x
matrice(2:,3::2)
x
x
x
x
Remarque : chaque fois que lon fixe un indice, on diminue dune unit le rang du tableau,
B mais si on restreint lintervalle dun des indices de faon ne slectionner quune valeur, le rang
7.2.2
Sections non-rgulires
Les sections non rgulires sont obtenues par indexation indirecte, grce un vecteur dindices.
INTEGER, DIMENSION(3)
:: vecteur_indice = (/ 3, 5, 1 /)
INTEGER, DIMENSION(4,6) :: m
INTEGER, DIMENSION(2,3) :: sous_matrice
sous_matrice = m(1:3:2, vecteur_indice)
Le sous-tableau sous_matrice est alors constitu des lments suivants de m :
m(1,3)
m(3,3)
m(1,5)
m(3,5)
m(1,1)
m(3,1)
10. Ne pas confondre avec scilab, octave ou matlab dans lesquels lordre est dbut:pas:fin.
11. Il est dailleurs trs rare en fortran de dclarer des tableaux dont ltendue est limite 1 sur un des axes,
contrairement ce qui se fait sous scilab ou matlab qui distinguent vecteurs lignes et vecteurs colonnes tous les
deux reprsents par des matrices avec un seul lment selon un des deux axes.
7.3
7.3.1
83
Les oprateurs agissant sur des types scalaires peuvent tre appliqus des tableaux, par
extension de leur fonction scalaire chacun des lments des tableaux. De telles oprations sont
qualifies doprations lmentaires. Dans le cas des oprateurs binaires, les tableaux oprandes
doivent tre conformants pour que cette opration puisse seffectuer terme terme. Un scalaire est
considr comme conformant avec un tableau quelconque. Dans le cas o les types des lments de
deux tableaux diffrent, il y a conversion implicite avant application de loprateur comme pour
des oprations scalaires.
Pour des raisons de lisibilit, on pourra indiquer le rang des tableaux manipuls par une notation
de section de tableau, par exemple tab(:,:) pour un tableau deux dimensions, au lieu de la
notation plus concise tab qui occulte le caractre multidimensionnel des variables manipules. Mais
dsigner ainsi un tableau allouable comme section de tableau nest pas quivalent : cela inhibe les B
possibilits de (r-)allocation au vol par affectation (cf. 7.5.4, p. 93).
REAL, DIMENSION(2,3)
:: tab, tab1 ! profil [2,3]
REAL, DIMENSION(0:1,-1:1)
:: tab2
! profil [2,3] identique
tab(:,:) = tab(:,:) + 1
! le scalaire 1 est ajout chaque terme du tableau
tab(:,:) = - tab(:,:)
tab(:,:) = tab(:,:) * tab(:,:)
! attention: produit terme terme
! (et non produit matriciel)
tab(:,:) = cos(tab(:,:))
! cosinus de chacun des termes du tableau
tab(:,:) = tab1(:,:) + tab2(:,:) ! tab(1,1) = tab1(1,1) + tab2(0,-1) ...
! seul compte le profil
La multiplication matricielle de deux tableaux peut par exemple seffectuer des deux faons suivantes (en pratique, on utilisera la fonction intrinsque MATMUL, cf 7.4.2, p. 85) :
REAL, DIMENSION(2,3) :: a
! matrice 2 lignes x 3 colonnes
REAL, DIMENSION(3,4) :: b
! matrice 3 lignes x 4 colonnes
REAL, DIMENSION(2,4) :: c
! matrice 2 lignes x 4 colonnes
INTEGER
:: i, j, k
c = 0
! initialisation du tableau c 0
DO i = 1, 2
! boucle sur les lignes de c
DO k = 1, 4
! boucle sur les colonnes de c
somme: DO j = 1, 3
! calcul de la somme : produit scalaire
c(i,k) = c(i,k) + a(i,j) * b(j,k)
!
de a(i,:) par b(:,k)
END DO somme
END DO
END DO
c(:,:) = 0.
! rinitialisation de c
DO k = 1, 4
! boucle sur les colonnes de c
somme_v: DO j = 1, 3
! calcul vectoriel des sommes
c(:,k) = c(:,k) + a(:,j) * b(j,k)
END DO somme_v
END DO
84
CHAPITRE 7. TABLEAUX
Le second membre dune instruction daffectation dans un tableau est compltement valu avant
laffectation elle-mme.
INTEGER
INTEGER, DIMENSION(5)
tab = tab(5:1:-1)
:: i
:: tab = (/ (i, i = 1, 5) /)
! permet d'inverser l'ordre des lments de tab
Une version scalaire aurait ncessit lemploi dune variable tampon supplmentaire pour viter
dcraser des valeurs lors de lchange entre 2 coefficients placs symtriquement :
INTEGER
INTEGER, DIMENSION(5)
INTEGER
do i = 1, 5/2
tampon = tab(i)
tab(i) = tab(6-i)
tab(6-i) = tampon
end do
f95
7.3.2
::
::
::
i=1,
i
tab = (/ (i, i = 1, 5) /)
tampon
2 ici : on s'arrte la moiti du tableau
Lorsque les oprations effectuer sur les lments dun tableau dpendent dune condition
portant sur ce tableau ou un autre tableau conforme, on peut utiliser linstruction WHERE, ou la
structure WHERE ... END WHERE, bien adapte au calcul parallle 12 .
7.3.3
Dans le cas o lopration provoque laffectation dune section non-rgulire de tableau, il est
interdit daffecter plusieurs fois le mme lment, cest dire quil ne peut y avoir de recouvrement
lintrieur du membre de gauche de lopration daffectation 13 .
12. Depuis le fortran 95, il est possible dimbriquer des structures WHERE.
13. Comme lordre daffectation nest pas garanti lexcution, on conoit quautoriser laffectation multiple de
certains lments introduirait une ambigut dans le rsultat. Il est donc logique dinterdire cette possibilit, mais
... parfois difficile de prvoir quand elle pourrait intervenir dans le cas o les indices dterminant les sections sont
variables.
85
7.4
La majorit des procdures intrinsques sont lmentaires et peuvent donc tre appeles avec
des arguments tableaux. Mais il existe des fonctions intrinsques spcifiquement consacres la
manipulation des tableaux (cf. A.5, p. 143).
7.4.1
Fonctions dinterrogation
SIZE(array [, dim]) donne ltendue dun tableau selon la dimension dim si cet argument
optionnel est fourni, et le nombre total dlments sinon ;
SHAPE donne le vecteur profil dun tableau (son tendue est le rang du tableau) ;
LBOUND et UBOUND fournissent un vecteur constitu des bornes respectivement infrieures et
suprieures des indices selon chacune des dimensions du tableau. Si une dimension est prcise
comme argument optionnel, elles fournissent un scalaire indiquant les bornes des indices selon
cette dimension.
MINLOC et MAXLOC fournissent le vecteur des indices du premier lment respectivement minimum ou maximum du tableau, mais en indexant le tableau partir dune borne infrieure B
gale 1 selon chaque dimension, quelles que soient les bornes dclares.
Attention : mme si on appelle LBOUND, UBOUND, MINLOC ou MAXLOC dun tableau de rang 1, le B
rsultat reste un tableau de rang 1 un seul lment ; pour obtenir un rsultat scalaire, il faut
utiliser largument optionnel DIM=1.
INTEGER,
INTEGER,
INTEGER
tab(:,1)
tab(:,2)
tab(:,3)
DIMENSION(0:3)
DIMENSION(-2:2,3)
:: v = (/
:: tab
:: i
= (/ (i, i=-2, 2) /)
!
= (/ (2*i, i=-2, 2) /)
!
= (/ (3*i, i=-2, 2) /)
!
SIZE(v)
SHAPE(v)
LBOUND(v)
LBOUND(v, DIM=1)
MINLOC(v)
MAXLOC(v)
MAXLOC(v, DIM=1)
7.4.2
2
1
0
1
2
4
(/ 4 /)
(/ 0 /)
0
(/ 2 /)
(/ 1 /)
1
3, 2, 2, 3 /)
| -2
| -4
| -6
4
2
0
2
4
6
3
0
3
6
-1
-2
-3
0
0
0
1
2
3
2 |
4 | (transpose de tab)
6 |
SIZE(tab)
SIZE(tab,1)
SIZE(tab,2)
SHAPE(tab)
LBOUND(tab)
UBOUND(tab)
LBOUND(tab,1)
MINLOC(tab)
MAXLOC(tab)
15
5
3
(/ 5, 3 /)
(/ -2, 1 /)
(/ 2, 3 /)
-2
(/ 1, 3 /)
(/ 5, 3 /)
Fonctions de rduction
86
CHAPITRE 7. TABLEAUX
(/ -48, -6, 0, 6, 48 )/
(/ -12, -6, 0, 6, 12 )/
0
(/ -2, -1, 0, 3, 6 )/
(/ 2, 4, 6 /)
6
(/ -6, -3, 0, 1, 2 )/
30
Par exemple, les calculs de moments dune srie statistique stocke dans un tableau monodimensionnel peuvent sexprimer de faon trs concise laide de ces fonctions.
INTEGER, PARAMETER
:: n = 1000
REAL, DIMENSION(n)
:: x, y
REAL
:: moyenne_x, moyenne_y, variance_x, covariance
moyenne_x = SUM( x(:) ) / REAL( SIZE( x(:) ) )
moyenne_y = SUM( y(:) ) / REAL( SIZE( y(:) ) )
variance_x = SUM( (x(:) - moyenne_x) ** 2 ) / REAL(SIZE(x(:)) - 1)
covariance = SUM((x(:)-moyenne_x) * (y(:)-moyenne_y)) / REAL(SIZE(x(:)) - 1)
7.4.3
Fonctions de transformation
87
UNPACK(vector, mask, field) recopie les lments du tableau de rang 1 vector dans un
tableau sous le contrle du masque mask conformant avec le tableau rsultat. Cest donc
mask qui dtermine le profil du tableau rsultat. Si llment du masque est vrai, llment
correspondant du tableau rsultat est pris dans vector, sinon, on lui donne la valeur field.
SPREAD(source, dim, ncopies) cre, par duplication (ncopies fois selon la dimension dim)
du scalaire ou tableau source, un tableau de rang immdiatement suprieur source.
MERGE(tsource, fsource, mask) fusionne les tableaux tsource et fsource selon le masque
mask : les trois arguments et le rsultat sont des tableaux conformants.
CSHIFT(array, shift [, dim]) et EOSHIFT(array, shift [, boundary][, dim]) effectuent des dcalages de shift des lments du tableau selon la dimension ventuellement spcifie (si le paramtre dim nest pas prcis, cela implique dim=1 16 ). Si shift est positif, les
dcalages se font vers les indices dcroissants et rciproquement. CSHIFT effectue des dcalages circulaires (sans perte dlments) alors que EOSHIFT remplace les lments perdus par
des zros du type des lments de array ou par boundary si cet argument optionnel est
prcis.
TRANSPOSE calcule la transpose dune matrice.
INTEGER
:: i
INTEGER, DIMENSION(8)
:: v = (/ (i, i = 1, 8) /), w
INTEGER, DIMENSION(3,4) :: tab1, tab2, tab3
tab1 = RESHAPE(v, (/ 3, 4 /), pad = (/ 0 /) )
w = CSHIFT(v, 2)
tab2 = CSHIFT(tab1, SHIFT=-1 ) ! dcalage des lignes vers le bas
tab3 = CSHIFT(tab1, (/ 1, -2, 2 /), DIM=2) ! un dcalage diffrent par ligne
1
2
3
4
5
6
7
8
0
0
0
0
1
2
3
4
5
6
7
8
0
0
0
0
1
2
3
4
5
6
7
8
9
CSHIFT(v,SHIFT=2)
EOSHIFT(v,SHIFT=2)
RESHAPE(v,(/3,4/),pad=(/0/))
PACK(tab1,mod(tab1,2)==1)
1
-1
2
UNPACK(v(1:4),mod(tab1,2)==1, -1)
-1
3
-1
4
-1
-1
1
1
SPREAD((/1, 2, 3/),dim=1,ncopies=2)
SPREAD((/1, 2, 3/),dim=2,ncopies=2)
-1
-2
-3
-4
-5
-6
-7
-8
-9
F
T
F
T
F
T
F
T
F
-1
2
-3
MERGE
16. Les dcalages sont appliqus chacun des vecteurs constituant le tableau et non globalement.
-1
-1
-1
2
2
3
3
1
2
3
1
2
3
4
-5
6
-7
8
-9
88
CHAPITRE 7. TABLEAUX
1
2
3
4
5
6
7
8
0
0
0
0
CSHIFT(tab1,SHIFT=-1)
ou
CSHIFT(tab1,SHIFT=+2)
1
2
3
4
5
6
7
8
0
0
0
0
7.4.4
+1
2
+2
3
1
2
6
4
5
0
7
8
0
0
0
4
8
0
7
0
0
0
2
3
1
5
6
Notion de masque
Parfois, un traitement a priori vectoriel via une fonction intrinsque ne doit pas tre appliqu
tous les lments dun tableau, mais une expression logique tableau peut servir dcider quels
lments seront concerns par linstruction tableau. Certaines procdures intrinsques portant sur
des tableaux acceptent un tel tableau boolen conforme largument trait, appel masque (mask),
en argument optionnel (de mot-clef MASK=).
INTEGER
:: i, produit, somme
INTEGER, DIMENSION(5)
:: v = (/ (i, i = -2, 2) /), w = 2 * v
produit = PRODUCT(v, MASK = v /= 0)
! produit des lments non nuls de v
somme = SUM(w, MASK = v /=0) ! somme des lments de w(i) tels que v(i) non nul
7.4.5
Trois fonctions intrinsques oprent sur des tableaux de boolens pour vrifier la validit dune
expression logique sur les lments dun tableau :
ALL(<mask >) rend .TRUE. si tous les lments du tableau boolen <mask > sont vrais, .FALSE.
sinon ; elle ralise un ET logique entre les lments du tableau
ANY(<mask >) rend .TRUE. si un au moins des lments du tableau boolen <mask > est vrai,
.FALSE. si tous sont .FALSE. ; elle ralise un OU logique entre les lments du tableau
COUNT(<mask >) rend le nombre (entier) des lments du tableau <mask > qui valent .TRUE..
En pratique, <mask > est produit par application dun test un tableau (ou des tableaux conformes).
INTEGER
:: i, nb_positifs
INTEGER, DIMENSION(5)
:: v = (/ (i, i=-2, 2) /)
REAL, DIMENSION(5)
:: u, u_log
...
nb_positifs = COUNT (v > 0)
! nombre d'lments positifs (2 ici)
IF (ALL(u > 0)) u_log = log(u) ! calcul si tous les lments de u sont > 0
f95
7.4.6
Certaines affectations de tableaux, par exemple combinant deux indices, ne peuvent pas sexprimer de faon globale sur le tableau, malgr leur facilit tre traites en parallle. Par exemple,
une affectation entre tableaux de rang diffrent :
DO i = 1, n
tab(i, i) = v(i) ! copie du vecteur v sur la diagonale de tab
END DO
peut sexprimer laide de linstruction FORALL :
FORALL (i = 1:n) tab(i, i) = v(i)
89
Les expressions de droite sont alors calcules en parallle pour toutes les valeurs de lindice, comme
si les rsultats intermdiaires taient stocks dans des variables temporaires jusqu la fin des calculs
en attendant laffectation finale du membre de gauche. En particulier, au contraire de ce qui se
passe dans une boucle classique, lordre de parcours des indices est indiffrent ; plus prcisment il
peut tre choisi par le processeur pour optimiser (vectoriser) le calcul. Cette construction savre
donc trs adapte aux calculs de filtrage numrique linaire. Par exemple, linstruction suivante
calcule bien une diffrence finie pour estimer une drive, alors quune boucle dans le sens croissant
des indices ne donnerait pas le mme rsultat.
FORALL (i = 1: size(v)-1 )
La structure FORALL ... END FORALL permet dexprimer une srie daffectations successives portant sur les mmes indices 17 .
FORALL (i=1:n, j=1:p)
a(i, j) = i + j
b(i, j) = a(i, j) ** i
END FORALL
Linstruction et la structure FORALL admettent de plus un masque (cf. 7.4.4, p. 88), qui linverse
de celui de WHERE, doit tre scalaire, avec une condition logique permettant de slectionner les
indices.
FORALL (i = 1:n, v(i) /=0 ) tab(i, i) = 1./v(i)
Une structure FORALL peut contenir aussi des constructions FORALL et WHERE (cf. 7.3.2, p. 84), mais
ne peut pas appeler des fonctions de transformation de tableaux.
7.5
7.5.1
Lallocation despace mmoire pour des tableaux peut seffectuer, en excluant provisoirement
les arguments muets de procdures, de trois faons diffrentes :
Pour les tableaux de profil fixe, la rservation despace mmoire se fait une fois pour toutes
la compilation. Porte et dure de vie dpendent alors de la procdure hte.
Noter quil est possible, et conseill de paramtrer les profils de ces tableaux par des ex-
pressions entires constantes, en utilisant des constantes symboliques (grce lattribut
PARAMETER). Cette prcaution permet de simplifier un changement de taille de ces tableaux
qui se rduit au changement de constantes symboliques une seule fois dans le code, suivi
dune recompilation.
Au dbut dune procdure, il est possible de dclarer des tableaux locaux de rang fixe dont
le profil dpend dun argument dentre de la procdure ou dun paramtre partag via un
module. Lespace mmoire leur est attribu automatiquement sur la pile (stack), au moment
de lappel de la procdure, et il est bien sr libr la fin de son excution. Cela limite leur
dure de vie lappel de la procdure, et restreint leur porte (scope) cette procdure et
ventuellement celles quelle appelle. Ces tableaux sont qualifis de tableaux automatiques.
Enfin, il est possible de dclarer des tableaux de rang fix la compilation, mais dont le
profil est dfini en cours dexcution : porte et dure de vie de ces tableaux sont dcides par
lutilisateur qui doit prendre en charge lui-mme lallocation et la libration de la mmoire,
prise cette fois sur le tas (heap). Ces tableaux profil diffr sont aussi qualifis de tableaux
dynamiques (cf. 7.5.3, p. 91).
17. Chaque instruction est alors excute sur tous les indices avant de passer la suivante.
90
CHAPITRE 7. TABLEAUX
7.5.2
Bien entendu, si on travaille avec des tableaux de profil fixe, on peut dclarer leur profil la
fois dans le programme principal et les procdures appeles : on dit que ces tableaux sont profil
B explicite. Rappelons que, dans ce cas, seul compte le profil du tableau et non ses bornes.
MODULE util
IMPLICIT NONE
CONTAINS
SUBROUTINE sub(tab)
REAL, DIMENSION(5), INTENT(INOUT) :: tab
...
! tab(1) contient tab0(-2) au premier appel
...
! tab(1) contient tab1(1) au deuxime appel
END SUBROUTINE SUB
END MODULE util
...
USE UTIL
REAL, DIMENSION(-2:2)
:: tab0
REAL, DIMENSION(5)
:: tab1
CALL sub(tab0)
CALL sub(tab1)
...
Mais, il est plus frquent que des procdures ncessitent lusage de tableaux de rang connu, mais
de profil variable dun appel lautre. On peut passer les tendues en argument de la procdure
pour dclarer ensuite les arguments tableaux, mais cela constitue un risque dincohrence.
La mthode la plus fiable consiste attribuer aux tableaux arguments muets de la procdure
un profil implicite (assumed-shape, profil suppos ), symbolis par des deux points la place
des tendues qui seront dtermines chaque appel par le tableau argument effectif. Pour pouvoir
appeler une procdure utilisant comme argument muet des tableaux de profil implicite, la procdure
appelante doit connatre linterface de la procdure appele. Trois possibilits sont envisageables,
dont la dernire est prfrable :
une procdure interne (cf. 6.3.1, p. 62) ;
une procdure externe complte par son interface explicite (cf. 6.3.3, p. 63) ;
de prfrence, une procdure de module (cf. 6.4, p. 64), dont linterface est rendue explicite
via linstruction USE.
MODULE util
IMPLICIT NONE
CONTAINS
SUBROUTINE sub(tab)
REAL, DIMENSION(:,:)
...
RETURN
END SUBROUTINE sub
SUBROUTINE sub2(tab)
REAL, DIMENSION(:,:)
:: tab ! profil implicite
REAL, DIMENSION(SIZE(tab,1),SIZE(tab,2)) :: aux ! tableau local automatique
...
RETURN
END SUBROUTINE sub2
...
END MODULE util
PROGRAM principal
USE util
INTEGER, PARAMETER
REAL, DIMENSION(lignes,colonnes)
REAL, DIMENSION(2*colonnes,2*lignes)
...
CALL sub(tab)
CALL sub2(tab)
CALL sub(tab2)
CALL sub2(tab2)
...
END PROGRAM principal
7.5.3
91
:: lignes = 3, colonnes = 4
:: tab
:: tab2
Lorsque, par exemple, le profil dun tableau nest connu qu lexcution, on peut lui allouer
dynamiquement la mmoire ncessaire. Il faut alors dclarer ce tableau en prcisant son rang 18
et lattribut ALLOCATABLE, qui en fait un tableau profil diffr (deferred-shape array). Une fois
le profil dtermin, linstruction ALLOCATE permettra dallouer effectivement la mmoire requise,
avant toute opration daffectation sur ce tableau. Aprs avoir utilis le tableau, il est recommand
de librer la mmoire alloue par linstruction DEALLOCATE 19 , en particulier si on souhaite rutiliser
le mme identificateur de tableau avec une autre taille.
Dans un souci de fiabilit des programmes, on prendra soin de tester le statut de retour de la
procdure ALLOCATE et, avant toute opration dallocation ou de libration de mmoire, de tester
ltat dallocation des tableaux grce la fonction dinterrogation ALLOCATED qui fournit un rsultat
boolen.
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
92
CHAPITRE 7. TABLEAUX
Un tableau dynamique local une procdure et allou dans cette procdure est automatiquement
libr la sortie de la procdure (via END ou RETURN), sauf sil est rendu permanent par lattribut
SAVE.
f2003
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
Tableau dynamique en paramtre Un tableau dynamique peut aussi tre pass en argument dune procdure, mais, en fortran 95, il doit tre dj allou avant lappel de la procdure et
nest pas considr comme allouable dans la procdure. Ces restrictions sont leves en fortran 2003,
ainsi quavec les extensions spcifiques de la plupart des compilateurs fortran 95 20 . Le tableau doit
alors possder lattribut ALLOCATABLE dans la procdure, qui peut se charger de lallocation. Sil
sagit dun argument de sortie (INTENT(OUT)), il est dsallou si ncessaire lors de lappel de la
procdure.
MODULE m_alloc_sub
IMPLICIT NONE
CONTAINS
SUBROUTINE init_tab(tab, m, n)
INTEGER, INTENT(in) :: m, n
INTEGER, ALLOCATABLE, INTENT(out) :: tab(:,:)
INTEGER :: ok, i, j
IF(.NOT.ALLOCATED(tab)) THEN
ALLOCATE(tab(m, n), stat = ok)
IF (ok /= 0) THEN
WRITE(*, *) 'erreur allocation'
STOP
END IF
DO i = 1, m
DO j = 1, n
tab(i, j) = 1000 * i + j
END DO
END DO
ELSE ! ne devrait pas se produire en fortran 2003 car tab est INTENT(OUT)
WRITE(*, *) 'tableau dj allou'
STOP
END IF
END SUBROUTINE init_tab
END MODULE m_alloc_sub
PROGRAM alloc_proc
USE m_alloc_sub
IMPLICIT NONE
INTEGER, ALLOCATABLE :: t(:,:)
INTEGER :: m, n, i
WRITE (*, *) 'entrer les dimensions du tableau: m et n'
READ (*, *) m, n
! appel du sous programme qui alloue et initialise le tableau
CALL init_tab(t, m, n)
DO i = 1 ,m
WRITE (*, *) t(i, :)
END DO
m = 2 * m
n = 2 * n
! deuxime appel du sous programme avec tab dj allou, mais
! ncessitant une rallocation car les dimensions ont chang
CALL init_tab(t, m, n)
DO i = 1 ,m
WRITE (*, *) t(i, :)
END DO
IF(ALLOCATED(t)) THEN
20. En particulier xlf dibm, le compilateur nag et g95 avec loption -std=f2003 ou -std=f95 assortie de -ftr15581
(cf. E.5.1, p. 170) autorisent lallocation de largument tableau dans la procdure.
46
47
48
f2003
93
DEALLOCATE(t)
END IF
END PROGRAM alloc_proc
7.5.4
En fortran 2003, un tableau allouable peut tre (r-)allou automatiquement si on lui affecte
une expression tableau :
sil ntait pas allou auparavant, il est allou avec le profil de lexpression qui lui est affecte ;
sil tait dj allou avec un profil diffrent, il est rallou pour ajuster son profil celui du
membre de droite de laffectation.
Noter que si le membre de gauche de laffectation est une section de tableau, aucune allocation B
nest effectue. La rallocation automatique peut donc tre inhibe pour un tableau complet si on
le dsigne comme une section de tableau en prcisant dans le membre de gauche le symbole :
pour chaque dimension. Dans ce cas, les lments de lexpression de droite en dehors du profil du
tableau de gauche sont ignors.
Par exemple, pour des tableaux de rang 1, le programme suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
de
de
de
de
de
v1=
v2=
v3=
v1=
v3=
2
3
2
3
2
v1=
v2=
v3=
v1=
v3=
1 2
-3 -2 -1
1 2
-3 -2 -1
-3 -2
La (r-)allocation automatique de tableaux par affectation peut entrer en conflit avec certaines
optimisations effectues par le compilateur. Cest pourquoi certains compilateurs disposent dune
option 21 pour choisir si on lautorise, indpendamment du choix du standard fortran 2003 ou
antrieur.
21. -fno-realloc-lhs ou -f-realloc-lhs pour gfortran (cf. E.6.1, p. 171), -Mallocatable=95 ou
-Mallocatable=03 pour pgf95 (cf. E.3.1, p. 167), -assume realloc_lhs ou -assume no-realloc_lhs pour ifort
(cf. E.4.1, p. 168).
Chapitre 8
Chanes de caractres
Ce court chapitre regroupe les outils, dont certains dj introduits dans les chapitres prcdents,
permettant la manipulation des chanes de caractres en fortran : le type chane (cf. chapitre 2), les
expressions de type chane (cf. chapitre 3) , les sous-chanes, les fonctions manipulant des chanes,
les entres/sorties de chanes (cf. chapitre 5), les tableaux de chanes et le passage darguments
chanes dans les procdures.
8.1
Le langage fortran comporte le type intrinsque CHARACTER pour stocker les chanes de caractres. chaque objet de type CHARACTER est associe une longueur LEN qui est le nombre des
caractres de la chane.
8.1.1
Les constantes chanes de caractres sont dlimites par des apostrophes simples ' ou 1 des
guillemets ". lintrieur dun des types de dlimiteur, lautre est considr comme un caractre
quelconque, ce qui permet dcrire par exemple "aujourd'hui". Toutefois, on peut aussi introduire
le dlimiteur lintrieur de la chane condition de le dupliquer, comme dans 'aujourd''hui'.
Pour crire une constante chane sur plusieurs lignes, il faut terminer toutes les lignes sauf la
dernire par le symbole & de continuation de ligne. Par dfaut tous les espaces en dbut de ligne
de suite sont alors significatifs (cf. 1.4.2 p. 8) ; mais on peut adopter une prsentation plus agrable
en spcifiant par un symbole & supplmentaire le dbut de la suite de la chane, ignorant ainsi tous
les espaces situs avant.
WRITE (*,*) 'chane de caractres comportant plusieurs lignes dans &
&le programme source sans espace superflu'
8.1.2
94
95
8.1.3
Fortran 90 doit donner accs un type de caractres par dfaut, et peut aussi fournir dautres
jeux de caractres dpendant du compilateur de la machine.
Mais fortran 2003 a introduit la possibilit daccder des variantes du type chane associes diffrents codage des caractres, notamment pour les caractres unicode. La fonction
SELECTED_CHAR_KIND rend un entier indiquant le numro du sous-type chane demand en paramtre : parmi les sous-types possibles on trouve DEFAULT, ASCII et ISO_10646 pour les caractres
Unicode (encore not UCS_4 assimilable UTF-32) 4 , mais seul DEFAULT est requis par la norme. Si
la variante demande nest pas disponible, la fonction SELECTED_CHAR_KIND rend -1. La variante
ISO_10646 sera ncessaire pour lire des fichiers texte cods en UTF-8 (cf. 5.3.2, p. 43).
Les constantes chanes de variante de type autre que le dfaut sont dsignes en les prfixant par
le numro du sous-type donn par SELECTED_CHAR_KIND suivi du symbole soulign 5 . Par exemple,
si le codage par dfaut est ISO-8859-1 :
INTEGER, PARAMETER :: defchar = SELECTED_CHAR_KIND('DEFAULT')
CHARACTER(LEN=3, KIND=defchar) :: mot=defchar_"t"
Pour dsigner un caractre unicode en UTF-32, on peut utiliser la fonction CHAR en lui fournissant
les codes-points unicode comme des entiers en hexadcimal (cf. 2.4, p. 17), par exemple :
INTEGER, PARAMETER :: utf32=SELECTED_CHAR_KIND('ISO_10646') ! UCS_4 = UTF-32
CHARACTER(LEN=1, KIND=utf32) :: car1_utf32, car2_utf32
car1_utf32 = CHAR(INT(Z'00E6'), KIND=utf32) ! ligature ae
car2_utf32 = CHAR(INT(Z'FB03'), KIND=utf32) ! ligature ffi (3 octets en UTF-8)
8.2
Une expression de type chane de caractres peut construite par concatnation de variables ou
de constantes chanes, par extraction de sous-chane ou enfin laide fonctions rsultat chane de
caractres.
8.2.1
Concatnation de chanes
8.2.2
Sous-chanes
De faon assez semblable aux sous-sections des tableaux, le langage fortran permet de manipuler
des sous-chanes de caractres, selon la syntaxe suivante 7 :
4. Par exemple, le compilateur nag possde quatre variantes du type chane, de paramtres KIND :
1 pour lASCII sur 1 octet qui comporte en fait le codage ISO-8859-1 ;
2 sur deux octets pour le codage UCS_2, qui concide avec UTF-16 ;
3 pour le codage JIS X 0213 permettant daccder aux caractres japonais ;
4 sur quatre octets pour UCS_4, assimilable UTF-32.
5. Ainsi, pour les chanes, on prfixe la variante de type, alors que pour les autres types (entiers, rels), on suffixe
la variante de type.
6. En langage C, la concatnation de chanes de caractres est obtenue par simple juxtaposition, sans oprateur
explicite.
7. On notera que le symbole : nest pas facultatif, mme si on veut dsigner une sous-chane rduite un
caractre.
96
8.2.3
Affectation
Laffectation globale dexpressions chanes de caractres est possible en fortran 8 sachant que le
membre de gauche peut tre une chane ou une sous-chane et le membre de droite une expression
de type chane. Au cas o la longueur des chanes de part et dautre du signe = diffre,
si lexpression chane du membre de droite est plus longue que la variable laquelle on doit
laffecter, la chane de droite est tronque ct droit ;
si lexpression chane du membre de droite est plus courte que la variable laquelle on doit
laffecter, la chane de droite est complte par des espaces pour aboutir la longueur de la
chane de gauche.
Avec les dclarations et les affectations suivantes :
CHARACTER(LEN=7) :: mot1 = "bonjour"
CHARACTER(LEN=9) :: mot2 = "au revoir"
CHARACTER(LEN=17) :: mot3
CHARACTER(LEN=7) :: mot4
CHARACTER(LEN=5) :: mot5
mot3 = mot1 // " " // mot2
mot4 = mot2(1:3) // mot1(4:)
mot5 = mot1(4:7)
mot2(1:2) = "A "
on obtient mot3="bonjour au revoir", mot4="au jour", mot5="jour " et mot2="A
8.3
8.3.1
revoir".
La fonction TRIM(STRING=ch ) dargument et de rsultat de type chane de caractre supprime les blancs droite de la chane passe en argument. Elle rend donc une chane de longueur
LEN_TRIM(ch ) infrieure au gale celle LEN(ch ) de ch .
TRIM(" ab cd ") donne " ab cd"
8.3.2
8.3.3
97
8.3.4
8.3.5
La fonction lmentaire INDEX(STRING=ch1 , SUBSTRING=ch2 ) rend un entier donnant la position du dbut de la sous-chane ch2 dans la chane ch1 . Seule la premire occurrence est recherche
et la fonction INDEX rend 0 si la sous-chane cherche nest pas prsente dans la chane ch1 .
Par dfaut, la recherche se fait de gauche droite dans ch1 . Mais cette fonction admet un
paramtre optionnel BACK de type boolen qui, lorsquil est fourni avec la valeur .true. prcise
que la recherche se fait en commenant par la droite : dans ce cas, si la sous-chane ch2 nest pas
prsente dans ch1 , INDEX rend LEN(ch1 ) + 1.
INDEX("attente", "te") donne 3
INDEX("attente", "te", BACK=.true.) donne 6
8.3.6
La fonction lmentaire SCAN(STRING=ch1 , SET=ch2 ) recherche dans la chane ch1 lun des
caractres de lensemble ch2 (peu importe lordre) et rend un entier donnant la position du premier
trouv. Si aucun des caractres de ch2 nest prsent dans ch1 , elle rend 0.
Par dfaut, la recherche se fait de gauche droite dans ch1 . Mais cette fonction admet un
paramtre optionnel BACK de type boolen qui, lorsquil est fourni avec la valeur .true., prcise
que la recherche se fait en commenant par la droite : dans ce cas, lentier rendu est donc la position
dans ch1 du dernier caractre de lensemble ch2 .
SCAN("aujourd'hui", "ru") donne 2 pour le premier u
SCAN("aujourd'hui", "ru", BACK=.true.) donne 10 pour le dernier u
8.3.7
La fonction lmentaire VERIFY(STRING=ch1 , SET=ch2 ) recherche dans la chane ch1 le premier caractre hors de lensemble ch2 (peu importe lordre) et rend un entier donnant la position
du premier trouv. Si tous les caractres de ch1 appartiennent ch2 , elle rend 0.
Par dfaut, la recherche se fait de gauche droite dans ch1 . La fonction VERIFY admet, comme
SCAN, un argument optionnel boolen BACK, qui, sil est positionn .true., prcise que la recherche
se fait de droite gauche.
VERIFY("aujourd'hui", "aeiouy") donne 3 pour le j
VERIFY("aujourd'hui", "aeiouy", BACK=.true.) donne 9 pour le h
98
Les fonctions VERIFY et SCAN jouent des rles identiques, ceci prs que leurs arguments
SET=ch2 devraient tre des ensembles complmentaires (relativement lensemble des caractres
prsents dans ch1 ) pour quelles donnent le mme rsultat.
SCAN("aujourd'hui", "dhjr'") donne 3 pour le j
VERIFY("aujourd'hui", "aiou") donne 3 pour le j
8.3.8
8.3.9
8.3.10
8.3.11
Les fonctions lmentaires de comparaison selon lordre lexicographique LLT, LLE, LGE et LGT
admettent deux arguments chanes de caractres et donnent un rsultat boolen. La comparaison
sappuie sur lordre lexicographique de lascii alors que les oprateurs logiques associs effectuent
la comparaison selon lordre lexicographique du jeu de caractres par dfaut, qui dpend de la
machine. Ces fonctions sont donc plus portables que les oprateurs associs. Si les deux chanes
comparer nont pas la mme longueur, la plus courte est complte par des espaces droites avant
comparaison.
LLT
LLE
LGE
LGT
lexically
lexically
lexically
lexically
lower than
lower or equal
greater or equal
greater than
<
<=
>=
>
IF (LGE(c, '0') .AND. LLE(c, '9')) permet aussi de tester si le caractre c est numrique.
f2003
8.3.12
Pour permettre lcriture de fichiers en mode stream (cf. 5.2.4, p.40), fortran 2003 a introduit
la fonction NEW_LINE(CHAR=ch ) qui rend le caractre de fin de ligne (new-line associ \n du C)
dans la variante de type caractre de son argument.
8.4
8.4.1
Le descripteur de conversion des chanes de caractres est soit (cf. 5.4.1, p.48) :
A : dans ce cas, le nombre de caractres est celui de la variable associe.
99
An o n est un entier spcifiant le nombre de caractres. Si n est plus grand que la longueur
de la chane crire, on complte par des blancs gauche. Si linverse, n est plus petit que
la longueur de la chane crire, celle-ci est tronque 9 aux n premiers caractres.
Par exemple, si on crit "salut" avec diffrentes largeurs, on obtient :
format
A
A5
A8
A2
8.4.2
rsultat
[salut]
[salut]
[
salut]
[sa]
8.4.3
Lcriture de donnes numriques sur des chanes de caractres ou la lecture de donnes dans
des chanes de caractres 10 mettent en uvre les mthodes de conversion voques plus haut, o
les chanes dans lesquelles on crit ou on lit sont qualifies de fichiers internes (cf. 5.2.1, 38).
Par exemple, le programme suivant convertit i et j en chacun 3 caractres quil crit dans la
variable f_int ; puis il lit dans cette mme variable (ou fichier interne) lentier k sur 6 chiffres
obtenus par concatnation de ceux de i et j.
1
2
3
4
5
6
7
8
9
10
PROGRAM fich_int
IMPLICIT NONE
CHARACTER(len=6) :: f_int
INTEGER :: i=100 , j=200 , k
WRITE(*,*) 'i=', i, 'j=', j
WRITE(f_int(1:6), '(2i3.0)') i, j ! criture dans le fichier interne f_int
! les chiffres de i et j sont juxtaposs dans la chane f_int
READ(f_int(1:6), '(i6.0)') k
! lecture de k sur le fichier interne f_int
WRITE(*,*) 'i=', i, 'j=', j, 'k=', k
END PROGRAM fich_int
Il affiche :
i= 100 j= 200
i= 100 j= 200 k= 100200
On utilise notamment la conversion dentiers en chanes de caractres pour composer des formats
variables pour effectuer des oprations dentre-sortie (cf. 5.4.5, p. 51).
8.5
Lassemblage de plusieurs chanes de caractres sous forme de tableau de chanes nest possible B
que si toutes les chanes ont la mme longueur, conformment la structure rectangulaire des
tableaux.
9. Ce comportement diffre du cas de lcriture de donnes numriques, o la conversion ne se fait pas si la largeur
du champ est insuffisante : on crit alors n symboles * .
10. En langage C, ces oprations se font grce aux fonctions sprintf et sscanf.
100
PROGRAM tab_chaines
IMPLICIT NONE
CHARACTER(LEN=4), DIMENSION(3) :: tab_ch
CHARACTER(LEN=4) :: ch
INTEGER :: i
tab_ch(1:2) = (/ "abcd", "ABCD" /) ! avec constructeur
tab_ch(3) = "1234"
WRITE(*,*) "lgueur commune des chaines ", LEN(tab_ch)
WRITE(*,*) "affichage en colonnes "
DO i=1, SIZE(tab_ch)
WRITE(*,*) tab_ch(i)
END DO
WRITE(*,*) "... en ligne: ", tab_ch
! extraction de sous-chanes pour construire une chane
ch = tab_ch(1)(1:2) // tab_ch(2)(3:4)
WRITE(*,*) "dduite par extraction ", ch
! autre formulation avec des sous-chanes
ch(1:2) = tab_ch(1)(1:2)
ch(3:4) = tab_ch(2)(3:4)
WRITE(*,*) "dduite par extraction ", ch
! remplacer les fins de chane par 1, 2 ou 3 blancs
DO i=1, SIZE(tab_ch)
tab_ch(i)(5-i:) = repeat(" ", i)
END DO
WRITE(*,*) "des blancs en fin "
WRITE(*,*) "affichage en colonnes entre [] "
DO i=1, SIZE(tab_ch)
WRITE(*,*) "[", tab_ch(i), "]"
END DO
WRITE(*,*) "LEN(tab_ch) ", LEN(tab_ch)
WRITE(*,*) "LEN_TRIM(tab_ch) ", LEN_TRIM(tab_ch)
END PROGRAM tab_chaines
8.6
affichage associ
lgueur commune des chaines 4
affichage en colonnes
abcd
ABCD
1234
... en ligne: abcdABCD1234
dduite par extraction abCD
dduite par extraction abCD
des blancs en fin
affichage en colonnes entre []
[abc ]
[AB ]
[1
]
LEN(tab_ch) 4
LEN_TRIM(tab_ch) 3 2 1
Chanes et procdures
Les chanes de caractres peuvent tre passes en argument de procdures sans que leur longueur
soit indique explicitement dans largument formel de type chane, comme on peut le faire pour le
profil des tableaux (si le rang est connu). Au moment de lappel, la longueur de la chane passe
en argument effectif est dtermine dans lappelant et transmise de faon implicite lappel.
Il est aussi possible de dclarer des chanes de caractres automatiques dans les procdures,
chanes dont la longueur dpend dun argument pass la procdure.
Lexemple suivant montre une fonction create_ch qui rend une chane dont la longueur est
passe en argument, ainsi quun sous-programme imprime_tab qui admet en argument un tableau
1D de taille quelconque constitu de chanes de caractres de longueur quelconque (mais identique).
101
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
MODULE m_proc_ch
IMPLICIT NONE
CONTAINS
FUNCTION create_ch(deb, n)
CHARACTER(LEN=n) :: create_ch
INTEGER, INTENT(IN) :: deb, n
CHARACTER(LEN=n) :: ch ! automatique
INTEGER :: k
DO k=1, n ! pris dans l'ordre ascii
ch(k:k) = ACHAR(k + deb -1 )
END DO
create_ch = ch
END FUNCTION create_ch
SUBROUTINE imprime(ch)
CHARACTER(LEN=*), INTENT(IN) :: ch
WRITE(*,*) "ch de lg ", LEN(ch), "[", ch, "]"
RETURN
END SUBROUTINE imprime
SUBROUTINE imprime_tab(tab_ch)
CHARACTER(LEN=*), DIMENSION(:), INTENT(IN) :: tab_ch
CHARACTER(LEN=LEN(tab_ch)+2) :: ch ! automatique
INTEGER :: i
WRITE(*,*) "tableau de ", SIZE(tab_ch), " chaines"
WRITE(*,*) " de longueur ", LEN(tab_ch)
DO i=1, SIZE(tab_ch)
ch = "["// tab_ch(i) // "]"
WRITE(*,*) ch
END DO
RETURN
END SUBROUTINE imprime_tab
END MODULE m_proc_ch
32
33
34
35
36
37
38
39
40
41
42
43
44
PROGRAM proc_chaines
USE m_proc_ch
CHARACTER(LEN=4) :: ch4
CHARACTER(LEN=6) :: ch6
CHARACTER(LEN=4), DIMENSION(3) :: tab_ch
ch4 = create_ch(33, 4)
ch6 = create_ch(33, 6)
CALL imprime(ch4)
CALL imprime(ch6)
tab_ch = (/ "abcd", "ABCD", "1234" /)
CALL imprime_tab(tab_ch)
END PROGRAM proc_chaines
affichage associ
ch de lg 4 [!"#$]
ch de lg 6 [!"#$%&]
tableau de 3 chaines
de longueur 4
[abcd]
[ABCD]
[1234]
Chapitre 9
9.1
On peut, par exemple, dfinir un type driv point dont les trois composantes sont : une lettre
didentification lettre, suivie des coordonnes (relles) abscisse et ordonnee du point.
TYPE :: point
CHARACTER(LEN=1) :: lettre
REAL :: abscisse
REAL :: ordonnee
END TYPE point
langage fortran
type driv
composante
langage C
structure
champ
mais on emploiera parfois les termes du C, en particulier structure pour dsigner une variable de type driv.
1. La terminologie du fortran et celle du langage C diffrent,
102
103
Plus gnralement, la syntaxe de dfinition dun type driv, bien souvent encapsule dans un
module (avant linstruction CONTAINS), est :
9.1.1
Lattribut SEQUENCE
La dfinition dun type driv nimplique pas en gnral un ordre ni une taille 2 pour le stockage
en mmoire des composantes, laisss libres pour le compilateur. Dans certains cas, notamment si
on souhaite transmettre des donnes de type driv une procdure crite dans un autre langage
(hormis le C, pour lequel dautres techniques dinteroprabilit existent, cf. chap. 12), on peut
imposer, par linstruction SEQUENCE, le stockage des composantes par concatnation en respectant
lordre de dfinition. Sil sagit de structures imbriques, il est videmment ncessaire que toutes
les sous-structures aient t dfinies avec lattribut SEQUENCE.
9.2
9.2.1
Une fois le type driv point dfini, on peut dclarer les variables a et b du type point, et leur
affecter une valeur en utilisant le constructeur de structure, qui est une fonction (automatiquement
cre) nomme comme le type driv. Appeler le constructeur est par exemple ncessaire pour
initialiser une structure lors de sa dclaration (comme pour b ci-aprs) :
TYPE(point) :: a, b = point('B', 1. ,-1.)
a = point('A', 0., 1.)
En fortran 95, les composantes doivent tre passes au constructeur en respectant leur position
dans le type driv, mais depuis fortran 2003, elles peuvent aussi tre dsignes par mot-clef. Les f2003
composantes initialises sont alors considres comme des arguments optionnels du constructeur.
TYPE(point) :: a
a = point(abscisse = 0., lettre ='A', ordonnee = 1.) ! fortran 2003
9.2.2
Slecteur de champ %
Rfrences et affectations une variable de type driv peuvent concerner la structure globale.
Mais seul loprateur daffectation est dfini par dfaut pour les types drivs ; les autres oprateurs B
(y compris le test dgalit ==) doivent tre tendus par lutilisateur (cf. chap 10).
Par exemple :
2. Ne pas croire que la taille dune variable de type driv soit toujours la somme des tailles de ses composantes.
En gnral, pour des raisons defficacit, le compilateur procde un alignement des composantes sur des mots par
exemple de 32 bits par adjonction de zros (zero padding). On a donc intrt dclarer les composantes les plus
volumineuses en tte de structure pour limiter ce remplissage. Enfin, il existe des options de compilation comme
-fpack-derived sous g96 ou gfortran, -noalign records de ifort, pour lviter, au dtriment des performances,
104
a = b
! suppose a et b de mme type driv
IF(a==b) WRITE(*,*) "a=b" ! interdit car oprateur de comparaison pas dfini
affecte au point a les mmes composantes que celles du point b.
Les entres/sorties globales de la structure sont quivalentes celles de la liste des composantes
ultimes, dans lordre de la dfinition du type. Elles peuvent se faire au format libre ou en spcifiant
autant de descripteurs de format actifs que de composantes ultimes.
WRITE(*, *) a ! affiche (dans l'ordre) les champs qui constituent la structure a
WRITE(*,'("a= ", A, " x=", F6.2, " y=", F6.2)') a
affiche successivement :
a A
0.00000000
a= A x= 0.00 y=
1.00
1.00000000
Mais on peut aussi accder individuellement chacun des champs qui composent la structure
grce au slecteur de champ % pour les affecter :
a%lettre = 'A'
a%abscisse = 0.
a%ordonnee = 1.
ou pour les rfrencer, y compris dans des expressions :
CHARACTER(LEN=1) :: c
c = a%lettre
WRITE(*, *) a%abscisse, a%ordonnee
WRITE(*, *) sqrt(a%abscisse**2 + a%ordonnee**2)
9.3
9.3.1
Les structures peuvent comporter des composantes qui sont elles-mmes des structures condition que les types des composantes aient t dfinis pralablement. On peut par exemple dfinir
une structure cercle dont un champ est une structure point :
TYPE :: cercle
TYPE(point) :: centre ! de type dfini au pralable
REAL :: rayon
END TYPE cercle
et dclarer ensuite une variable de type cercle et lui affecter une valeur, par exemple grce son
constructeur. Le slecteur % permet daccder aux composantes ultimes du type driv imbriqu.
TYPE(cercle) :: rond
rond = cercle(b, 2.) ! o b est de type point
WRITE(*, *) 'rond = ', rond
WRITE(*, *) 'rond = ', rond%centre, rond%rayon
WRITE(*, *) 'abscisse du centre :', rond%centre%abscisse
WRITE(*, *) 'primtre :', 2.* 3.14159 * rond%rayon
f2003
9.3.2
105
La norme fortran 2003 prvoit aussi que lon puisse tendre un type driv en lui adjoignant des
composantes, grce lattribut EXTENDS 3 . Ce mcanisme permet dhriter des outils conus pour
le type parent (cf. 9.7.1, 109). Le constructeur du type tendu admet deux syntaxes (voir exemple
ci-aprs) :
la syntaxe classique (pour circle1) o lon passe toutes les composantes ;
le passage dun objet du type parent (a de type point) et des seules composantes ncessaires
(ici le rayon) pour ltendre.
TYPE, EXTENDS(point) :: pt_ext_cerc
REAL :: rayon
END TYPE pt_ext_cerc
TYPE(pt_ext_cerc) :: circle1, circle2
circle1 = pt_ext_cerc('B', 2., -0., 2.) ! constructeur du type tendu
circle2 = pt_ext_cerc(a, 2.) ! constructeur partir du type parent
N.-B. : un type driv portant lattribut SEQUENCE (cf. 9.1.1, p. 103) ou BIND (cf. 12.2 p. 130) B
nest pas extensible.
Laccs aux composantes du type parent peut se faire soit directement, soit via le type parent :
WRITE(*,*) "circle1%lettre = ", circle1%lettre ! accs direct
WRITE(*,*) "circle1%point%lettre = ", circle1%point%lettre ! via type parent
9.4
Structures et tableaux
106
supposerait de composer un tableau 2D partir des indices des objets drivs et de ceux de leurs
coordonnes. La norme prcise que dans une telle expression, au plus une des rfrences peut tre
de rang non nul (cest--dire non scalaire).
f2003
9.5
Pour manipuler des structures comportant des tableaux de dimensions allouables dynamiquement en fortran 95, il tait ncessaire (comme en C) de faire appel aux pointeurs (cf. chap. 11).
Mais ces limitations ont disparu avec la norme fortran 2003 ainsi quavec les options spcifiques de
certains compilateurs fortran 95 4 .
Dans ce cas, lappel du constructeur ainsi que loprateur daffectation se chargent de lallocation des composantes allouables (par un mcanisme dj voqu pour lallocation implicite
des tableaux par affectation, cf. 7.5.4, p. 93). Lopration de copie dune variable de type driv
comportant des composantes de taille variable (tableau, chane...) ralise donc une copie profonde
(deep copy), o les donnes elles-mmes sont dupliques. linverse, en fortran 95 ou en langage
C, la structure ne comporte que des pointeurs vers les donnes dynamiques et la recopie simple par
affectation ne duplique que les pointeurs, ralisant ainsi une copie superficielle (shallow copy). Il est
ncessaire de crer une fonction de recopie profonde qui prend en charge lallocation des donnes
dynamiques que lon souhaite dupliquer.
TYPE :: point
CHARACTER(LEN=1) :: lettre
REAL, DIMENSION(:), ALLOCATABLE :: coord
END TYPE point
...
TYPE(point) :: a, b
! dclaration
a = point('A', (/1. ,-1./) ) ! construction de a => allocation de a%coord
WRITE(*,*) 'a ', a%lettre, a%coord
! affichage de a composante par composante
! WRITE(*,*) 'a ', a ! pas autoris en fortran 2003
b = a ! affectation globale => allocation de b%coord
Noter quil nest pas possible de lire ou dcrire globalement une variable de type driv com-
B posante allouable ou dattribut pointeur via READ ou WRITE, moins de dfinir soi-mme des
9.6
La transmission de structures en argument de procdures externes suppose que les types drivs
soient connus de lensemble des procdures qui les manipulent. La mthode la plus fiable 5 consiste
insrer la dfinition du type driv dans un module (cf. 6.4, p. 64) qui sera appel par toutes les
procdures utilisant ce type.
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
107
9.7
Dans le contexte de la programmation oriente objet, il est possible dattacher un type driv
un ensemble de procdures (bound procedures), qui apparatront comme des composantes du type
driv : on les qualifie alors de mthodes. Lensemble, donnes et mthodes constitue alors un objet.
Elles sont introduites aprs le mot-clef CONTAINS, lintrieur de la dfinition du type, par
la dclaration PROCEDURE, suivie du nom de la mthode. Le slecteur de composantes % permet
ensuite de les rfrencer pour les appliquer une structure. Par dfaut, cette structure sera passe
implicitement la procdure comme premier argument ; on peut le prciser par lattribut PASS.
Au contraire, il faut prciser NOPASS pour viter cette transmission par dfaut.
Les procdures attaches au type driv sont dfinies en dehors du type, comme des procdures
classiques, aprs le mot-clef CONTAINS.
Lexemple suivant prsente plusieurs procdures permettant de dterminer le symtrique dun
point du plan par rapport la premire bissectrice des axes (change entre abscisse et ordonne) :
le sous-programme bound_sym_sub attach au type point, que lon peut appeler avec linstruction CALL a%bound_sym_sub(b), o la structure a est transmise implicitement par dfaut ;
la fonction bound_sym_fct attache au type point que lon peut appeler avec lexpression
a%bound_sym_sub(), o la structure a est transmise implicitement par dfaut ;
leurs variantes bound_nopass_sym_sub et bound_nopass_sym_fct avec lattribut NOPASS, o
la structure nest pas transmise implicitement ;
le sous-programme sym non attach au type point, qui nest donc pas accessible avec le
slecteur %.
Seules celles attaches au type point sont dclares dans le type (lignes 14 17).
6
7
8
9
10
11
108
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
109
9.7.1
Si lon tend le type point au type point_num par ajout dune composante, on peut lui appliquer
les procdures attaches au type parent. Cest lintrt de la dclaration CLASS(point) au lieu de
TYPE(point) de leur argument implicite. Dans lexemple suivant, on ajoute un sous-programme
bound_sym_sub_ext dont largument de sortie est de classe point :
dans le cas particulier o largument effectif est plus prcisment de type point_num, la
procdure construit une structure de type point_num ;
sinon, la procdure construit simplement une structure de type point.
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
110
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
Cette procdure utilise la structure de contrle SELECT TYPE (cf. lignes 41 et 43) qui sapplique
aux variables dont le type peut varier lexcution (typage dynamique) selon la syntaxe gnrale
suivante :
Chapitre 10
10.1
Le fortran 77 comportait dj la notion de procdure gnrique, mais elle tait rserve aux
procdures intrinsques. Avec les versions 90 et au del, cette notion devient accessible pour les
procdures dfinies par lutilisateur. En fortran 1 , de nombreuses fonctions intrinsques numriques
(cf. annexe A, p. 138) invoquables sous leur nom gnrique font en ralit appel, suivant le type de
leurs paramtres effectifs, une version spcifique particulire. Par exemple, la fonction gnrique
intrinsque MAX rfrence les fonctions spcifiques :
MAX0 si les arguments sont entiers ;
AMAX1 si les arguments sont rels ;
DMAX1 si les arguments sont double prcision.
Pour regrouper sous une mme procdure gnrique plusieurs procdures spcifiques, il faut
dclarer une interface commune obligatoirement nomme et ensuite dresser la liste des procdures
spcifiques qui seront effectivement appeles, avec chacune leur interface. Au moment de lappel
de la procdure gnrique le choix de la procdure spcifique sera fait en fonction :
du nombre des arguments effectifs dappel ;
et du type de ces arguments.
Par exemple dans le cas de fonctions 2 :
111
112
Dans linterface gnrique, au lieu de recopier les interfaces des procdures spcifiques, on
f2003 peut se contenter den donner la liste, chacune prcde par MODULE 3 PROCEDURE ::, condition
que chaque procdure spcifique possde une interface explicite visible dans le module hbergeant
linterface gnrique.
Par exemple, pour dfinir une fonction gnrique moy qui calcule la moyenne (en flottant) dun
tableau de rels ou dentiers, il faut dfinir deux fonctions spcifiques moy_reel et moy_int que
lon peut placer dans un module :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
MODULE m_moyenne
IMPLICIT NONE
INTERFACE moy ! interface gnrique pour une famille de procdures spcifiques
MODULE PROCEDURE moy_reel ! version avec tableau de rels
MODULE PROCEDURE moy_int ! version avec tableau d'entiers
! le choix se fera sur le type de l'argument
END INTERFACE moy ! nommage possible en fortran 95 seulement
CONTAINS
FUNCTION moy_reel(tab_r) ! version rels
REAL :: moy_reel
REAL, DIMENSION(:), INTENT(in) :: tab_r
moy_reel = SUM(tab_r(:)) / REAL(SIZE(tab_r(:)))
END FUNCTION moy_reel
FUNCTION moy_int(tab_i)
! version entiers
REAL :: moy_int
INTEGER, DIMENSION(:), INTENT(in) :: tab_i
moy_int = REAL(SUM(tab_i(:))) / REAL(SIZE(tab_i(:)))
END FUNCTION moy_int
END MODULE m_moyenne
20
21
22
23
24
25
26
27
28
29
30
31
PROGRAM t_moyenne
USE m_moyenne
IMPLICIT NONE
INTEGER :: i
INTEGER, DIMENSION(10) :: ti =(/ (i, i=1, 10) /)
REAL, DIMENSION(10) :: tr
tr(:) = REAL(ti(:)) / 10.
! appel de la procdure avec le nom gnrique (moy)
WRITE(*,*) moy( tr(:) ) ! argument tableau de rels => appelle moy_reel
WRITE(*,*) moy( ti(:) ) ! argument tableau d'entiers => appelle moy_int
END PROGRAM t_moyenne
Dans le cas de procdures externes dont le code source est inaccessible ou ne peut pas tre
modifi, il suffit de fournir explicitement linterface des procdures spcifiques pour pouvoir les
intgrer dans une interface gnrique. Cest ce qui est pratiqu pour les bibliothques.
10.2
Linterface-oprateur
En fortran, les oprateurs intrinsques sont soit monadiques, comme +, - et .not. suivis de
leur oprande, soit plus souvent dyadiques et alors entours par leurs deux oprandes. partir de
fortran 90, il est possible :
de dfinir de nouveaux oprateurs ;
et dtendre la porte des oprateurs intrinsques du fortran (surcharge, overloading en anglais) des types pour lesquels leur action nest pas dfinie par le langage.
3. En fortran 2003, le mot-clef MODULE est devenu facultatif.
10.2. LINTERFACE-OPRATEUR
113
Les procdures spcifiques qui permettent de dfinir laction dun oprateur rendent un rsultat
qui peut tre utilis dans une expression ; elles doivent donc tre des fonctions :
un argument (opration monadique) ;
ou deux arguments (opration dyadique).
Surcharge doprateurs
Pour surcharger un oprateur, seules doivent tre fournies les fonctions qui dfinissent le rle
de loprateur sur les types pour lesquels il nest pas intrinsquement dfini. Le choix entre les
fonctions spcifiques est fait en fonction du nombre des arguments (1 ou 2) et de leur type. La
priorit de loprateur surcharg est celle de loprateur intrinsque (cf. 3.5, p. 25).
titre dexemple, loprateur // ralise la concatnation entre deux chanes de caractres et on
peut ltendre, en tant quoprateur dyadique 4 sur des rels, au calcul de la rsistance quivalente
une association de deux rsistances en parallle.
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
MODULE m_resist
! l'oprateur // est dfini entre deux chanes de caractres seulement
! on le surcharge pour les rels (reprsentant ici des rsistances par ex)
INTERFACE OPERATOR(//)
MODULE PROCEDURE parallele ! liste des fonctions qui tendent l'oprateur
END INTERFACE
CONTAINS
FUNCTION parallele(r1,r2)
IMPLICIT NONE
REAL :: parallele
REAL, INTENT(in) :: r1, r2
parallele = 1. / (1./r1 + 1./r2)
RETURN
END FUNCTION parallele
END MODULE m_resist
!
PROGRAM elec
USE m_resist
IMPLICIT NONE
REAL :: r1, r2
WRITE(*,*) ' entrer deux valeurs de rsistances'
READ *, r1, r2
WRITE(*,*) 'r1 = ', r1, ' r2 = ', r2
WRITE(*,*) 'r1 '//'srie r2 = ' , r1+r2 ! utilisation de // natif
WRITE(*,*) 'r1 // r2 = ' , r1//r2
! utilisation de // surcharg
END PROGRAM elec
4. Loprateur // ne pourrait pas tre dfini comme monadique.
114
10.2.2
Cration doprateurs
Un oprateur nouveau est introduit (identificateur entour par des points, comme les oprateurs
de comparaison) suivant une syntaxe similaire celle de la surcharge des oprateurs existants. Le
nouvel oprateur a la priorit maximale sil est unaire et la plus faible sil est binaire (cf. 3.5, p. 25).
Par exemple, on peut dfinir loprateur .para. dassociation en parallle :
pour les rels, en particulier pour les rsistances ;
pour un type driv capacite reprsentant les capacits.
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
MODULE m_parallele
IMPLICIT NONE
TYPE :: capacite
REAL :: capa
END TYPE capacite
INTERFACE OPERATOR(.para.)
! liste des fonctions qui dfinissent l'oprateur
MODULE PROCEDURE parallele_res
! pour les rels (dont les rsistances)
MODULE PROCEDURE parallele_capa
! pour les capacits (type driv)
END INTERFACE
CONTAINS
FUNCTION parallele_res(r1,r2)
REAL :: parallele_res
REAL, INTENT(in) :: r1, r2
parallele_res = 1. / (1./r1 + 1./r2)
RETURN
END FUNCTION parallele_res
FUNCTION parallele_capa(c1,c2)
TYPE(capacite) :: parallele_capa
TYPE(capacite), INTENT(in) :: c1, c2
parallele_capa%capa = c1%capa + c2%capa
RETURN
END FUNCTION parallele_capa
END MODULE m_parallele
!
PROGRAM elec
USE m_parallele
IMPLICIT NONE
REAL :: r1, r2
TYPE(capacite) :: c1, c2, c3
WRITE(*,*) ' entrer deux valeurs de rsistances'
READ(*,*) r1, r2
WRITE(*,*) 'r1 = ', r1, ' r2 = ', r2
WRITE(*,*) 'r1 // r2 = ' , r1.para.r2
! .para. appelle parallele_res
WRITE(*,*) ' entrer deux valeurs de capacits'
READ(*, *) c1%capa, c2%capa
WRITE(*,*) 'c1 = ', c1%capa, ' c2 = ', c2%capa
c3 = c1.para.c2
! .para. appelle parallele_capa
WRITE(*,*) 'c1 // c2 = ' , c3%capa
END PROGRAM elec
10.3
Linterface-affectation
10.3. LINTERFACE-AFFECTATION
115
Il est possible dtendre la porte du symbole daffectation des types pour lesquels son sens
nest pas dfini intrinsquement. On parle alors de surcharge de laffectation et on utilise une syntaxe
particulire qui regroupe les interfaces des sous-programmes deux arguments (le premier est la
variable affecter ou membre de gauche, le second lexpression qui lui sera affecte ou membre de
droite) qui dfinissent le sens de cette affectation. Le choix du sous-programme spcifique appeler
se fait en fonction du type des deux arguments.
Dans lexemple suivant, on dfinit un type hms, heures, minutes, secondes. En surchargeant
laffectation (cf. ligne 10 et suivantes), on construit les conversions en secondes (type entier) et
heures fractionnaires et les conversions rciproques. Via ces conversions, il est possible de surcharger
les oprateurs +, - (monadique opp_hms, ligne 84 et dyadique diff_hms, ligne 75), * et >.
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
116
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
10.3. LINTERFACE-AFFECTATION
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
117
INTEGER :: sx, sy
sx = x ! conversion en secondes par hms2s
sy = y ! conversion en secondes par hms2s
sup_hms = sx > sy
END FUNCTION sup_hms
END MODULE m_hms
!
PROGRAM t_hms
! traitement des temps en heures, minutes, secondes
USE m_hms
IMPLICIT NONE
TYPE(hms) :: hms1, hms2, hms3, hms4, hms5
REAL :: h1, h2
INTEGER :: s1, s2
WRITE(*,*) 'entrer deux instants en heures minutes secondes'
READ(*,*) hms1, hms2
h1 = hms1 ! conversion implicite en fraction d'heures
h2 = hms2 ! conversion implicite en fraction d'heures
s1 = hms1 ! conversion implicite en secondes
s2 = hms2 ! conversion implicite en secondes
hms3 = hms1 + hms2 ! addition de deux types hms
hms4 = hms1 - hms2 ! soustraction de deux types hms
hms5 = - 2*hms1
! oppos d'un multiple entier
WRITE(*,*) ' en heures minutes secondes'
WRITE(*,*) ' hms1 = ', hms1, ' hms2 = ', hms2
WRITE(*,*) ' en heures fractionnaires'
WRITE(*,*) ' h1 = ', h1, ' h2 = ', h2
WRITE(*,*) ' en secondes '
WRITE(*,*) ' s1 = ', s1, ' s2 = ', s2
WRITE(*,*) ' somme en h m s ', hms3
WRITE(*,*) ' diffrence en h m s ', hms4
WRITE(*,*) ' -2 fois h1 en h m s ', hms5
IF (hms1 > hms2) THEN ! comparaison
WRITE(*,*) 'hms1 > hms2'
ELSE
WRITE(*,*) 'hms1 <= hms2'
END IF
END PROGRAM t_hms
Lexemple prcdent reste une bauche trs lmentaire. En particulier, la surcharge de laffectation suppose que tous les entiers sont des secondes et tous les rels des heures dcimales : il
faudrait restreindre ces conversions des types spcialiss une seule composante stockant des
temps, mais alors aussi dfinir les oprateurs numriques associs pour ces types.
Pour fiabiliser lusage de type driv hms, il faudrait contraindre les composantes heures, minutes, secondes possder un signe commun, et limiter minutes et secondes lintervalle ouvert
] 60, +60[. On pourrait par exemple interdire laccs direct aux composantes (attribut PRIVATE,
cf. 9.1, p. 102) du type hms, quitte dfinir des procdures publiques de saisie et de communication
des donnes hms prcisment charges de cet accs restreint.
Chapitre 11
Pointeurs
Historiquement, la notion de pointeur a t introduite dans dautres langages, en particulier
le C 1 , pour manipuler les donnes via les adresses de la mmoire quelles occupent : dans cette
vision, un pointeur est une variable type ; le type permet de connatre la taille de la zone mmoire
ncessaire et le mcanisme de codage et de dcodage 2 pour stocker lobjet (variable, structure, ...)
point 3 ; le pointeur est destin stocker des valeurs qui sont les adresses des objets points, mais
ces adresses seules seraient inutilisables sans la connaissance du type de lobjet point.
Mais la notion de pointeur en fortran sapparente plus un descripteur comportant non seulement une adresse, mais aussi dautres informations sur la nature et la structure de la cible que le
pointeur permet de dsigner, notamment afin den assurer une gestion dynamique. La cible peut
tre une donne de type quelconque (scalaire, tableau, structure, voire pointeur), ou une procdure,
mais doit avoir t dclare comme cible potentielle. Dautre part, fortran ne permet pas daccder explicitement ladresse que stocke le pointeur. Dailleurs, il nexiste en fortran ni oprateur
dadresse 4 , ni doprateur dindirection 5 et la cible est dsigne par le pointeur lui-mme.
Dans la norme fortran 95, les pointeurs taient ncessaires pour grer les tableaux dynamiques
dans certains contextes en tant que rsultats de fonctions, arguments formels de procdures ou
composantes de types drivs. La norme 2003 apporte une gestion plus performante des tableaux
dynamiques sans faire appel explicitement aux pointeurs. On rservera donc les pointeurs des
usages plus spcifiques comme la manipulation de structures dynamiques telles que les arbres ou
les listes chanes, ou, dans le cadre de la programmation objet, lincorporation de mthodes dans
les types drivs grce aux pointeurs de procdures.
11.1
Une variable est considre comme un pointeur si on prcise lattribut POINTER lors de sa
dclaration ; noter que cette dclaration ne rserve alors pas despace pour stocker les valeurs
quelle est susceptible de pointer.
1. Le tableau annexe (cf. D.7, p. 162) rsume approximativement les syntaxes employes dans les deux langages
pour manipuler des pointeurs.
2. Le type ne renseigne pas seulement sur la taille, mais aussi sur le codage de la valeur : par exemple si, sur
une machine 32 bits, 4 octets permettent de stocker un entier par dfaut et aussi un rel simple prcision, le motif
binaire qui reprsente par exemple la valeur numrique 10 ne sera pas le mme en entier et en rel.
3. Cest cette information qui permet en C de faire de larithmtique sur les pointeurs : incrmentation,
diffrence...
4. Si var est une variable, son adresse est dsigne en C par &var. Dailleurs, dans le cadre de linteroprabilit
entre fortran et C (cf. 12.3, p. 130), il faut faire appel en fortran, une fonction spcifique du module ISO_C_BINDING,
c_loc pour accder ladresse dune variable au sens du C.
5. Si ptr est un pointeur, la cible pointe est dsigne par *ptr en C alors quen fortran, ptr dsigne la cible.
118
119
11.1.1
Un pointeur peut tre associ une variable de mme type (et ventuellement sous-type)
qualifie de cible si celle-ci a t dclare avec lattribut TARGET 6 . Linstruction
PROGRAM pointeurs
IMPLICIT NONE
INTEGER, TARGET :: i=1 , j=2 ! target obligatoire pour pointer vers i ou j
INTEGER, POINTER :: pi, pj, pk
! association entre pointeur et cible : ncessite le mme type
pi => i
! pi pointe sur i
pj => j
! pj pointe sur j
pk => i
! pk pointe aussi sur i
WRITE(*, *) "associations : i, j = ", i, j, " pi, pj, pk = ", pi, pj, pk
! affectation : conversions implicites possibles
pi = 3.5
! affecte int(3.5) la variable i, pointe par pi
pj = pi + 10 ! ajoute 10 la variable pointe (i) et place le rsultat dans j
pk => j
! maintenant pk pointe sur j et plus sur i
WRITE(*, *) "affectations : i, j = ", i, j, " pi, pj, pk = ", pi, pj, pk
! association d'un pointeur un autre (en fait sa cible)
pi => pj
! pi pointe maintenant sur la cible de pj, soit j
WRITE(*, *) "association d'un pointeur un autre : pi, pj, pk = ", pi, pj, pk
END PROGRAM pointeurs
affichera
associations : i, j = 1 2 pi, pj, pk = 1 2 1
affectations : i, j = 3 13 pi, pj, pk = 3 13 13
association d'un pointeur un autre : pi, pj, pk =
13 13 13
En fortran 2008, il est possible dassocier un pointeur une cible ds la dclaration du pointeur,
condition que la cible ait lattribut SAVE et ne soit pas allouable. Cette initialisation de pointeur f2008
est aussi possible vers une cible constituant une partie constante dune variable statique.
Fonctions concernant lassociation des pointeurs
La fonction intrinsque ASSOCIATED qui rend un boolen permet de sinformer sur ltat dassociation dun pointeur. Elle admet deux formes dappel :
ASSOCIATED(<ptr> ) rend .true. si le pointeur <ptr> est associ ;
ASSOCIATED(<ptr> , <target> ) rend .true. si le pointeur <ptr> est associ la cible
<target> .
La dclaration dun pointeur lui donne par dfaut un statut dassociation indtermin. Il est
6. Cette restriction permet dviter de manipuler accidentellement des variables via des pointeurs dune part et
de laisser le compilateur optimiser plus efficacement les instructions manipulant des variables non accessibles via des
pointeurs dautre part. linverse, le langage C nimpose pas cette prcaution, mais la notion de pointeur restreint
introduite en C99 a un objectif similaire.
120
donc recommand de le dsassocier explicitement ds la dclaration 7 par <ptr> => NULL() ou,
en dbut de programme par linstruction NULLIFY(<ptr> ).
REAL, POINTER :: ptr1 => NULL()
REAL, TARGET :: r1, r2
WRITE(*, *) ASSOCIATED(ptr1)
ptr1 => r1
WRITE(*, *) ASSOCIATED(ptr1)
WRITE(*, *) ASSOCIATED(ptr1, r1)
WRITE(*, *) ASSOCIATED(ptr1, r2)
11.1.2
! affichera .false.
! affichera .true.
! affichera .true.
! affichera .false.
Une autre faon dassocier un pointeur est de lui allouer une zone mmoire, par linstruction
ALLOCATE (cf. ligne 3 du programme suivant), qui, dans le cas dun pointeur, rserve lespace
mmoire et associe le pointeur la mmoire rserve. Comme cette zone mmoire nest pas dsigne
par une variable cible, la cible dynamique est qualifie danonyme. Elle nest accessible quau travers
des pointeurs dont elle est la cible.
Lassociation cesse ds que lon libre la zone mmoire par une instruction DEALLOCATE (cf.
ligne 8). Linstruction DEALLOCATE(<ptr> ) applique un pointeur a donc deux effets :
elle libre la mmoire alloue pour la cible anonyme ;
elle dsassocie le pointeur <ptr> .
B Si on a, entre temps, associ dautres pointeurs cette mme cible (cf. ligne 6), seul celui qui a per-
mis la libration de mmoire est dsassoci par linstruction DEALLOCATE : les autres continuent de
pointer vers une zone mmoire dont rien de garantit quelle ne soit occupe par dautres donnes...
Il est donc fortement conseill de dsassocier (cf. ligne 12), tous les pointeurs qui se partagent cette
cible immdiatement aprs la dsallocation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PROGRAM alloc_assoc_pointeurs
REAL, POINTER :: ptr => NULL(), ptr2 => NULL()
ALLOCATE(ptr) ! reservation de mmoire et association de ptr
WRITE(*, *) "ptr associ ? ", ASSOCIATED(ptr) ! affichera .true.
ptr = .25 ! affectation d'une valeur la cible
ptr2 => ptr ! ptr2 pointe aussi vers la cible alloue
WRITE(*, *) "ptr2 associ ptr ?", ASSOCIATED(ptr2, ptr) ! affichera .true.
DEALLOCATE(ptr) ! libre la mmoire et desassocie ptr
WRITE(*, *) "ptr associ ? ", ASSOCIATED(ptr) ! affichera .false.
WRITE(*, *) "ptr2 associ ?", ASSOCIATED(ptr2) ! affichera .true.
WRITE(*, *) "ptr2 associ ptr ?", ASSOCIATED(ptr2, ptr) ! affichera .false.
NULLIFY(ptr2) ! fortement conseill
! si ptr2 est dsassoci, l'instruction suivante provoquerait une erreur
! si ptr2 n'tait pas dsassoci, elle donnerait un rsultat alatoire
! WRITE(*, *) "cible de ptr2 ", ptr2
END PROGRAM alloc_assoc_pointeurs
Mais si on dsassocie tous les pointeurs associs une cible anonyme alloue sans instruction
B DEALLOCATE, la zone mmoire alloue reste rserve, mais nest dfinitivement plus accessible :
on parle alors de fuite de mmoire (memory leak). Si cette fuite de mmoire se produit de faon
rptitive dans une boucle par exemple, elle peut provoquer un dpassement de capacit de la
mmoire. On veillera donc viter de telles pertes de mmoire dans les procdures.
7. Loption -fpointer=null du compilateur g95 (cf. E.5.1, p. 170) permet aussi dinitialiser null les pointeurs
non initialiss dans le code, mais ce nest quune prudence supplmentaire.
1
2
3
4
5
6
7
8
9
121
PROGRAM ALLOC_PTR
IMPLICIT NONE
REAL, POINTER :: ptr => NULL()
ALLOCATE(ptr) ! allocation du pointeur
WRITE(*, *) ASSOCIATED(ptr) ! affichera .true.
ptr = 2 ! utilisation de la mmoire alloue
NULLIFY(ptr) ! dassociation avant dallocation ! => memory leak
WRITE(*, *) ASSOCIATED(ptr) ! affichera .false.
END PROGRAM ALLOC_PTR
Lors de lexcution, le programme prcdent compil avec g95 affichera T (true) puis F (false)
et signalera cette fuite de mmoire : Remaining memory: 4 bytes allocated at line 4
Noter quaffecter une valeur un pointeur non associ nest pas autoris, car rien ne spcifie
alors la zone mmoire o stocker la valeur.
11.2
Lattribut pointeur peut tre donn une variable tableau condition que seul son rang et non
son profil (cf. 7.1.1, 79) soit spcifi.
INTEGER, DIMENSION(10), POINTEUR :: ptab ! est interdit
INTEGER, DIMENSION(:), POINTEUR :: ptab ! est autoris
Dans le cas de tableaux dont lindice ne commence pas 1, on distinguera les deux formes
dassociation :
INTEGER, DIMENSION(-2:2), TARGET :: tab
INTEGER, DIMENSION(:), POINTER
:: pt1, pt2
pt1 => tab
! qui conserve l'indexation initiale
pt2 => tab(:) ! qui renumrote partir de 1 car tab(:) est une section de tab
Plus gnralement, il est enfin possible de pointer vers une section rgulire de tableau, de rang
infrieur ou gal celui du tableau dont la section est issue.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PROGRAM section_ptr
INTEGER, DIMENSION(3,5), TARGET :: mat
INTEGER, DIMENSION(:), POINTER
:: pt1 => NULL() ! rang 1
INTEGER, DIMENSION(:,:), POINTER :: pt2 => NULL() ! rang 2
INTEGER :: i, j
WRITE(*,*) "matrice initiale"
DO i=1, 3
mat(i,:) = i* (/ (j, j=1, 5) /)
WRITE(*,*) mat(i,:)
END DO
pt1 => mat(2,:)
pt2 => mat(1:3:2, 2:4)
WRITE(*,*) "deuxime ligne de mat"
WRITE(*,*) pt1
WRITE(*,*) "sous-matrice de mat (lignes 1 et 3 , colonnes 2 4)"
DO i=1, 2
WRITE(*,*) pt2(i,:)
END DO
END PROGRAM section_ptr
122
affiche
matrice initiale
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
deuxime ligne de mat
2 4 6 8 10
sous-matrice de mat (lignes 1 et 3 , colonnes 2 4)
2 3 4
6 9 12
Il y aura alors rindexation partir de 1 de la section pointe sauf si on dsigne lindice de dpart
f2003 du pointeur 8 .
pt2(1:, 2:) => mat(1:3:2, 2:4)
MODULE m_fct_ptr
IMPLICIT NONE
CONTAINS
FUNCTION positifs(x) ! fonction valeur pointeur sur un tableau de rang 1
INTEGER, DIMENSION(:), POINTER :: positifs
INTEGER, DIMENSION(:), INTENT(in) :: x
INTEGER :: p, ok, i, j
p = COUNT( x>0 ) ! comptage du nombre de positifs
ALLOCATE (positifs(p), stat=ok) ! allocation du pointeur
IF(ok /= 0) STOP 'erreur allocation'
j = 0
DO i=1, SIZE(x)
IF (x(i) <= 0 ) CYCLE
j = j +1
positifs(j) = x(i) ! affectation du pointeur
END DO
END FUNCTION positifs
END MODULE m_fct_ptr
19
20
21
22
23
24
25
26
27
28
29
30
PROGRAM ppal
USE m_fct_ptr
IMPLICIT NONE
INTEGER :: i
INTEGER, DIMENSION(10) :: t=(/(i, i=-5, 4) /)
INTEGER, DIMENSION(:), POINTER :: tp => NULL()
WRITE(*, *) "tableau initial ", t(:)
tp => positifs(t) ! appel de la fonction qui alloue le pointeur
WRITE(*, *) size(tp), " lments positifs :", tp(:)
DEALLOCATE(tp) ! pour librer la mmoire
END PROGRAM ppal
8. Cette possibilit nest pas implmente sous gfortran 4.4.3 ni sous g95.
9. Ctait la seule mthode en fortran 95 standard qui nautorisait pas les fonctions rsultat tableau allouable.
Mais ces restrictions nexistent plus en fortran 2003, ou grce certaines extensions propres des compilateurs, en
particulier -ftr15581 pour le compilateur g95 (cf. E.5.1, p. 170).
123
qui affiche
tableau initial -5 -4 -3 -2 -1 0 1 2 3 4
4 positifs : 1 2 3 4
Les pointeurs permettent de nombreuses autres applications dans le domaine des donnes dynamiques, notamment pour grer les listes chanes.
11.3
Lorsquun pointeur possde un attribut de dimension, son profil qui dtermine la taille de la
cible ne peut pas tre fix la dclaration (on parle de profil diffr). Il nest donc pas possible
de dfinir directement des tableaux de pointeurs. Mais il suffit dencapsuler le pointeur dans un B
type driv pour pouvoir simuler un tableau de pointeurs avec un tableau dlments du type
driv qui ne contient que le pointeur. Il est ainsi possible de reprsenter des assemblages nonrectangulaires dlments du mme type, qui ne sont pas reprsentables sous forme de tableaux.
Cela vaut par exemple pour les parties triangulaires infrieure et suprieure dune matrice.
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
PROGRAM lower_upper_alloc
IMPLICIT NONE
! pas de tableau de pointeurs => les encapsuler dans un type driv
TYPE iptr
INTEGER, DIMENSION(:), POINTER :: pt => null()
! pointeur de tableau 1D d'entiers
END TYPE iptr
TYPE(iptr), DIMENSION(:), POINTER :: lower=> null(), upper => null()
! tableaux d'lments de type iptr pour stocker les parties triang. inf et sup
INTEGER, ALLOCATABLE, DIMENSION(:,:) :: mat
INTEGER :: ligne, colonne, n
DO
WRITE(*,*) "entrer la dimension de la matrice carre"
READ(*,* ) n
IF (n <=0) EXIT
ALLOCATE(mat(n,n))
DO ligne = 1, n
DO colonne = 1, n
mat(ligne, colonne) = 10*ligne + colonne
END DO
END DO
WRITE(*,*) "matrice complte"
DO ligne = 1, n
WRITE(*,*) mat(ligne, :)
END DO
ALLOCATE(lower(n)) ! allocation du tableau-pointeur de n lignes
ALLOCATE(upper(n)) ! allocation du tableau-pointeur de n lignes
DO ligne = 1, n
ALLOCATE(lower(ligne)%pt(ligne)) ! une allocation par ligne
ALLOCATE(upper(ligne)%pt(n-ligne +1)) ! une allocation par ligne
lower(ligne)%pt = mat(ligne, 1:ligne) ! affectation ligne ligne
upper(ligne)%pt = mat(ligne, ligne:n) ! affectation ligne ligne
END DO
DEALLOCATE(mat) ! libration de la matrice
WRITE(*,*) "partie triangulaire infrieure"
DO ligne = 1, n
WRITE(*,*) lower(ligne)%pt(:) ! impression de la partie triang. inf.
END DO
WRITE(*,*) "partie triangulaire suprieure (non aligne)"
124
40
41
42
43
44
45
46
47
48
DO ligne = 1, n
WRITE(*,*) upper(ligne)%pt(:) ! impression de la partie triang. sup.
END DO
DO ligne = 1, n
DEALLOCATE(lower(ligne)%pt, upper(ligne)%pt)
END DO
DEALLOCATE(lower, upper)
END DO
END PROGRAM lower_upper_alloc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PROGRAM lower_upper_ptr
IMPLICIT NONE
! pas de tableau de pointeurs => les encapsuler dans un type driv
TYPE iptr
INTEGER, DIMENSION(:), POINTER :: pt => null()
! pointeur de tableau 1D d'entiers
END TYPE iptr
TYPE(iptr), DIMENSION(:), POINTER :: lower=> null(), upper => null()
! tableaux d'lments de type iptr pour stocker les parties triang. inf et sup
INTEGER, ALLOCATABLE, DIMENSION(:,:), TARGET :: mat
INTEGER :: ligne, colonne, n
DO
WRITE(*,*) "entrer la dimension de la matrice carre"
READ(*,* ) n
IF (n <=0) EXIT
ALLOCATE(mat(n,n))
DO ligne = 1, n
DO colonne = 1, n
mat(ligne, colonne) = 10*ligne + colonne
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
END DO
END DO
WRITE(*,*) "matrice complte"
DO ligne = 1, n
WRITE(*,*) mat(ligne, :)
END DO
ALLOCATE(lower(n)) ! allocation du tableau-pointeur de n lignes
ALLOCATE(upper(n)) ! allocation du tableau-pointeur de n lignes
DO ligne = 1, n
! dsignation de la cible des pointeurs
lower(ligne)%pt => mat(ligne, 1:ligne) !
upper(ligne)%pt => mat(ligne, ligne:n)
END DO
WRITE(*,*) "partie triangulaire infrieure"
DO ligne = 1, n
WRITE(*,*) lower(ligne)%pt(:) ! impression de la partie triang. inf.
END DO
WRITE(*,*) "partie triangulaire suprieure (non aligne)"
DO ligne = 1, n
WRITE(*,*) upper(ligne)%pt(:) ! impression de la partie triang. sup.
END DO
mat = - mat ! modification de la matrice
WRITE(*,*) "mat change de signe"
WRITE(*,*) "partie triangulaire infrieure"
DO ligne = 1, n
WRITE(*,*) lower(ligne)%pt(:) ! impression de la partie triang. inf.
END DO
WRITE(*,*) "partie triangulaire suprieure (non aligne)"
DO ligne = 1, n
WRITE(*,*) upper(ligne)%pt(:) ! impression de la partie triang. sup.
END DO
DEALLOCATE(mat) ! libration de la matrice aprs usage des parties sup/inf
DO ligne = 1, n ! par prudence (ils pointent alors vers une zone dsalloue)
NULLIFY(lower(ligne)%pt, upper(ligne)%pt)
END DO
DEALLOCATE(lower, upper)
END DO
END PROGRAM lower_upper_ptr
entrer la dimension
3
matrice complte
11 12 13
21 22 23
31 32 33
partie triangulaire
11
21 22
31 32 33
partie triangulaire
11 12 13
22 23
33
mat change de signe
partie triangulaire
-11
-21 -22
-31 -32 -33
partie triangulaire
-11 -12 -13
-22 -23
-33
de la matrice carre
infrieure
infrieure
125
126
11.4
Pointeurs de procdures
Un pointeur de procdure est un pointeur destin tre associ une procdure. Il est gnralement dclar via la spcification PROCEDURE (cf. 6.5.4, p. 74) avec lattribut POINTER. Comme
pour les autres objets, le pointeur, une fois associ, dsigne sa cible.
11.5
Les composantes des types drivs peuvent possder lattribut pointeur, ce qui permet la constitution de listes chanes : les listes chanes permettent de reprsenter des ensembles ordonns
dlments (appels noeuds de la liste) dont non seulement le contenu, mais aussi le nombre peut
voluer en cours de lexcution du programme. On peut en particulier insrer ou supprimer des
lments dans la liste tout en conservant lordre : lallocation se fait donc lment par lment,
contrairement ce qui passe pour les tableaux o lallocation, si elle peut tre dynamique, reste
globale. Mais, laccs un lment donn de la liste ncessite de parcourir tous les prcdents alors
quon peut accder directement un lment dindice donn dun tableau.
Dans une liste simplement chane, chaque lment comporte un pointeur vers llment suivant
sauf le pointeur du dernier lment de la liste qui est nul.
donnes 1
donnes 2
donnes 3
pointeur
pointeur
pointeur
pointeur
Figure 11.1 Liste simplement chane trois lments : le dernier lment pointe vers NULL.
Lexemple suivant montre une liste chane permettant de reprsenter une courbe dans le plan :
le type driv point comporte donc un pointeur vers une donne de type point pour chaner la liste.
Pour simplifier, la courbe initialement cre est la deuxime bissectrice des axes. Les procdures
dimpression imprime_chaine (ligne 10, p. 126) et de libration libere_chaine (ligne 26, p.127)
de la liste sont ici implmentes sous forme rcursive. Pour librer la mmoire, il est ncessaire de
commencer par la fin de la liste afin dviter de perdre laccs aux lments suivants. En revanche,
limpression de la liste se fait dans lordre si on imprime avant lappel rcursif (en descendant
la rcurrence) ou dans lordre inverse (procdure imprime_chaine_inverse (ligne 18, p. 127) si on
imprime aprs (en remontant la rcurrence). Enfin, les oprations dinsertion, insere_point
(ligne 57, p. 127) ou de suppression, supprime_point (ligne 35, p. 127) dun point intrieur se
font dans une boucle qui parcourt lensemble de la liste jusquau pointeur nul signifiant laccs au
dernier point.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
MODULE m_chaine
IMPLICIT NONE
TYPE point
! dfinition du type driv point avec un pointeur vers le suivant
REAL :: x
REAL :: y
TYPE(point), POINTER :: next => null() ! f95 seulement (par prudence)
END TYPE point
CONTAINS
RECURSIVE SUBROUTINE imprime_chaine(courant) !
TYPE(point), POINTER :: courant
! affichage en commenant par le dbut : imprimer avant la rcursion
WRITE(*,*) courant%x, courant%y
IF(ASSOCIATED(courant%next)) THEN
CALL imprime_chaine(courant%next)
END IF
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
127
128
78
79
80
81
82
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
PROGRAM linked_list
USE m_chaine
INTEGER :: i, n
TYPE(point), POINTER :: courant => null(), suivant=>null()
TYPE(point), POINTER :: debut => null()
! construction d'une liste chane de n points
WRITE(*,*) 'entrer le nb de points'
READ(*,* ) n
! premier point qui permettra l'accs toute la chane
ALLOCATE(debut)
courant => debut
DO i = 1, n-1
courant%x = REAL(i)
courant%y = -REAL(i)
ALLOCATE(suivant)
courant%next => suivant
courant => suivant
END DO
! dernier point sans successeur
courant%x = REAL(n)
courant%y = -REAL(n)
courant%next => null() ! fin de la liste
WRITE(*,*) "impression dans le sens direct"
CALL imprime_chaine(debut) ! impression dans le sens direct
WRITE(*,*) "impression dans le sens inverse"
CALL imprime_chaine_inverse(debut) ! impression en sens inverse
WRITE(*,*) "suppression de points"
CALL supprime_point(debut) ! suppression de points intrieurs
WRITE(*,*) "impression dans le sens direct"
CALL imprime_chaine(debut) ! impression dans le sens direct
WRITE(*,*) "insertion de points"
CALL insere_point(debut)
! insertion de points intrieurs
WRITE(*,*) "impression dans le sens direct"
CALL imprime_chaine(debut) ! impression dans le sens direct
WRITE(*,*) "libration de la chane"
CALL libere_chaine(debut) ! libration de la chane
END PROGRAM linked_list
donnes 1
donnes 2
donnes 3
pointeur
pointeur
pointeur
pointeur
Figure 11.2 Suppression dun lment intrieur dune liste simplement chane trois lments
Chapitre 12
Inter-oprabilit avec le C
La standardisation de linterfaage entre les langages C et fortran est intervenue seulement
avec la norme fortran 2003. Elle permet de rendre portables les appels de fonctions en C depuis le
fortran et rciproquement. Elle sappuie sur la dfinition en fortran dentits (types, variables et
procdures) dites inter-oprables car quivalentes celles du langage C.
La construction dun excutable partir de code C et de code fortran ncessite une compilation
spare avec des compilateurs C et fortran compatibles, puis une dition de lien qui fournisse toutes
les bibliothques ncessaires. En particulier dans le cas o le programme principal est en C, il faut
spcifier explicitement la bibliothque du fortran lors de ldition de liens si elle est lance par
le compilateur C 1 . Une autre solution consiste confier ldition de liens au compilateur fortran
associ, quitte lui indiquer par une option 2 que le programme principal nest pas en fortran.
12.1
Le module intrinsque iso_c_binding dfinit les paramtres de codage (kind) sous forme de
constantes symboliques pour les sous-types intrinsques inter-oprables avec le langage C. Le tableau suivant dcrit les quivalences entre les principaux types inter-oprables du fortran 2003 et
ceux de la norme C89 du langage C :
C89
char
short_int
int
long int
long long int
size_t
float
double
long double
fortran 2005
CHARACTER(kind=c_char)
INTEGER(kind=c_short)
INTEGER(kind=c_int)
INTEGER(kind=c_long)
INTEGER(kind=c_lon_long)
INTEGER(kind=c_size_t)
REAL(kind=c_float)
REAL(kind=c_double)
REAL(kind=c_long_double)
Ce module dfinit de mme des types complexes et un type boolen inter-oprables respectivement avec les types complexes et le type boolen du C99.
C99
float _Complex
double _Complex
long double _Complex
_bool
fortran 2005
COMPLEX(kind=c_float_complex)
COMPLEX(kind=c_double_complex)
COMPLEX(kind=c_long_double_complex)
LOGICAL(kind=c_bool)
1. Avec le compilateur g95 sous linux et un processeur Intel 32 bits, on lancera par exemple, sous rserve que la
bibliothque fortran soit installe dans ce rpertoire,
gcc partie_c.o partie_fortran.o -L/usr/lib/g95/lib/gcc-lib/i686-pc-linux-gnu/4.0.3/ -lf95 suivi ventuellement de -lm
De plus on sassurera de la compatibilit des versions des compilateurs utiliss.
2. Par exemple gfortran ou g95 avec gcc, ou ifort et loption -nofor-main (cf. E.4.1, p. 168) avec icc.
129
130
Il dfinit aussi des types inter-oprables quivalents aux variantes de type entier dfinies en C99,
int8_t, int16_t, int32_t et int64_t nombre de bits fix ainsi que les versions nombre minimal
de bits int_least8_t et suivants ou les plus rapides avec un nombre de bits fix int_fast8_t et
suivants : le nommage en fortran est obtenu par adjonction du prfixe c_, par exemple c_int8_t.
Le module iso_c_binding dfinit enfin des constantes caractres de paramtre de codage (kind)
c_char pour les caractres spciaux du C, comme c_null_char ou c_new_line.
12.2
Les types drivs du fortran peuvent tre rendus inter-oprables avec les structures du C
condition que 3 :
les composantes du type driv fortran soient inter-oprables, publiques, quelles ne soient
pas allouables et ne comportent pas de pointeur (au sens de lattribut pointer en fortran 4 ) ;
Le type driv fortran ne soit pas une extension de type (cf. 9.3.2, p. 105), ne soit pas de type
SEQUENCE (cf. 9.1.1, p. 103), ni un type paramtr et ne possde pas de procdures attaches ;
lattribut bind(c) soit spcifi en fortran dans la dfinition du type driv ;
la structure du C ne comporte pas de champ de bits.
12.3
Le module iso_c_binding dfinit des types drivs ( composantes prives) c_ptr et c_funptr
inter-oprables respectivement avec les pointeurs dobjets et de fonctions du C. Les constantes
nommes c_null_ptr et c_null_funptr sont les quivalents en fortran du pointeur nul du C.
Ce module dfinit aussi des procdures de manipulation des pointeurs du C depuis le fortran.
c_loc(x) renvoie une valeur du type c_ptr contenant ladresse au sens du C de son argument.
Cette fonction joue le rle de loprateur & du langage C.
c_funloc(f) renvoie ladresse dune procdure inter-oprable.
c_f_pointer(cptr, fptr, profil) est un sous-programme qui permet de traduire un pointeur du C et un profil ventuel en un pointeur au sens du fortran. Largument dentre cptr
est du type c_ptr. Largument de sortie fptr est un pointeur vers un type inter-oprable. En
sortie, fptr est associ la cible de cptr. Largument dentre profil en gnral optionnel,
est requis si fptr est un tableau.
c_f_procpointer(cptr, fptr) est un sous-programme qui effectue la mme conversion que
c_f_pointer mais pour des procdures.
12.4
Linter-oprabilit des procdures entre fortran et C requiert que les paramtres changs soient
inter-oprables, que linterface de la procdure fortran soit explicite et dclare avec lattribut
BIND(C). Lattribut BIND permet aussi de spcifier le nom de la fonction C associe grce au mot
clef NAME selon la syntaxe : BIND(C, NAME=nom_de_la_fonction_en_C ). dfaut du paramtre
NAME dans lattribut BIND le nom en C est le mme quen fortran, mais en minuscule 5 .
Elle exclut notamment :
les procdures internes du fortran ;
les arguments optionnels en fortran et le nombre variable darguments en C ;
les rsultats de fonction non scalaires en fortran ;
Les sous-programmes du fortran correspondent aux fonctions sans valeur de retour (type void)
en C.
3. Lespace occup par les structures est soumis des contraintes dalignement en mmoire qui conduisent parfois
complter une structure par des octets de remplissage. Ces contraintes diffrent suivant les langages, les processeurs
et les compilateurs et peuvent ainsi affecter linter-oprabilit des structures.
4. Mais un type driv inter-oprable peut comporter une composante de type c_ptr ou c_funptr.
5. On rappelle quen fortran, la casse nest pas distingue, cf 1.3.2, p. 7.
12.4.1
131
Comme le passage de paramtre en C se fait par copie de valeur, alors quil se fait par rfrence
en fortran, le fortran 2003 a introduit lattribut VALUE pour modifier le mcanisme de passage
dargument du fortran dans le sens du C. Cette mthode permet de travailler sur la copie passe en
argument sans que cela affecte la valeur ct appelant en retour. Lattribut VALUE peut tre utilis
en dehors de linter-oprabilit avec le C mais nest pas applicable aux paramtres pointeurs ou
allouables et est videmment incompatible avec les vocations INTENT(OUT) et INTENT(INOUT).
linverse, un argument sans lattribut VALUE doit correspondre dans la fonction en C un
pointeur vers le type de largument (inter-oprable) du fortran.
12.4.2
Lexemple suivant montre lappel en fortran de fonctions C sans valeur de retour pour saisir
des rels et les afficher. Elles sont vues du fortran comme des sous-programmes de mme nom en
labsence du paramtre NAME dans lattribut BIND (cf. lignes 6 et 12).
Laccs au type c_float dans linterface fortran (cf. lignes 8 et 14) ncessite soit un USE, soit
un IMPORT (cf. 6.4.4, p. 69).
Le sous-programme daffichage c_write_float peut se contenter dun passage par copie de
valeur, do lattribut VALUE en fortran (cf. ligne 15), car il ne modifie pas la valeur du paramtre. En
revanche, la fonction de lecture, c_read_float, ncessite un passage par pointeur en C, directement
compatible avec le passage dargument utilis par dfaut en fortran.
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
1
2
PROGRAM f_appel_c_sub_io
USE m_interf
REAL(kind=c_float) :: r
CALL c_read_float(r)
WRITE (*,*) "float en fortran aprs lecture en C ", r
CALL c_write_float(r)
END PROGRAM f_appel_c_sub_io
#include <stdio.h>
#include <stdlib.h>
3
4
Partie langage C
132
6
7
8
9
10
11
12
13
14
15
16
17
18
12.4.3
Lexemple suivant montre lappel en C de sous-programmes fortran pour saisir des rels et les
afficher. Ils sont vus depuis le C comme des fonctions sans valeur de retour dont le nom est donn
par le paramtre NAME dans le BIND (cf. lignes 6 et 13). Le sous-programme daffichage write_float
peut se contenter dun passage par copie de valeur, do lattribut VALUE en fortran (cf. ligne 14),
car il ne modifie pas la valeur du paramtre. En revanche, la fonction de lecture, f_read_float,
ncessite un passage par pointeur en C, directement compatible avec le passage dargument utilis
par le fortran.
1
2
#include <stdio.h>
#include <stdlib.h>
Partie langage C
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
int main(void){
float f;
/* f est saisi en fortran */
f_read_float(&f);
printf("valeur du float affiche en C %g\n", f);
f_write_float(f);
exit(EXIT_SUCCESS);
}
Partie fortran 2003
MODULE m_io
USE, INTRINSIC :: iso_c_binding, ONLY:c_float
IMPLICIT NONE
CONTAINS
! void f_read_float(float *px);
SUBROUTINE read_float(x) BIND(c, name="f_read_float") !
REAL(kind=c_float), INTENT(out) :: x
WRITE (*, *) "saisie en fortran: entrer un float"
READ (*,*) x
WRITE (*,*) "float lu en fortran avant passage en C", x
END SUBROUTINE read_float
! void f_write_float(float x);
SUBROUTINE write_float(x) BIND(c, name="f_write_float") !
14
15
16
17
18
133
12.5
Les tableaux ne peuvent tre inter-oprables que si leurs lments sont de type et de paramtres
inter-oprables. De plus, ils doivent soit tre de profil explicite, soit ne comporter quune dimension
indtermine :
la dernire spcifie par * en fortran ;
la premire spcifie par [] en C.
Dans le cas dun tableau de rang 1, si la taille est explicite, elle doit tre prcise et identique dans
les deux langages. Si elle est indtermine en fortran, elle ne doit pas tre prcise en C.
Linter-oprabilit des tableaux de rang suprieur 1 sappuie sur un ordre de rangement en
mmoire qui veut quen fortran, ce soit le premier indice qui dfile le plus vite 6 alors quen C, o
il sagit alors de tableaux de tableaux, cest le dernier indice qui dfile le plus vite. Il faudra donc
systmatiquement changer lordre des tailles pour passer dun langage lautre.
Par exemple le tableau fortran dclar : INTEGER(kind=c_int) :: tab(3,5,6)
pourra tre inter-oprable avec le tableau C : int tab[6][5][3];
Sil reste une dimension indtermine, ce sera la dernire en fortran, tab(3,5,*) et la premire
en C tab[][5][3].
12.5.1
Les tableaux sont ici de rang deux et de taille fixe pour le compilateur dans le programme principal en fortran afin dviter lallocation dynamique. Mais les fonctions en C supposent seulement
quune tendue est connue : celle dont la connaissance permet de calculer les dcalages effectuer
dans les adresses mmoire pour accder aux lments du tableau, cest dire celle de droite en C,
note C_N2 (cf. ligne 8, partie C), qui correspond celle de gauche en fortran, note F_LIG (cf.
ligne 12, partie fortran). Cette dimension commune, fixe ici grce au prprocesseur, devrait ltre
sous un seul nom dans un fichier unique inclus par le source C et par le source fortran. Avec les
conventions de nommage classiques des compilateurs (cf. annexe E), il est ncessaire de nommer
le source fortran avec comme suffixe .F90 au lieu de .f90 pour le voir trait par le prprocesseur.
1
2
3
4
!
!
!
!
5
6
7
8
9
10
11
12
#define F_LIG 3 !
13
14
15
16
MODULE m_interf
USE, INTRINSIC :: iso_c_binding, ONLY:c_int
IMPLICIT NONE
6. Les lments qui ne diffrent que dune unit de cet indice sont supposs tre contigus en mmoire.
134
17
18
19
20
21
22
23
24
25
26
27
28
29
INTERFACE
SUBROUTINE c_print_tab2d(mat, f_col) BIND(c)
IMPORT ::c_int !
INTEGER(kind=c_int), INTENT(in) :: mat(F_LIG, *)
INTEGER(kind=c_int), value :: f_col
END SUBROUTINE c_print_tab2d
SUBROUTINE c_mult_tab2d(mat, f_col) BIND(c)
IMPORT ::c_int !
INTEGER(kind=c_int), INTENT(inout) :: mat(F_LIG, *)
INTEGER(kind=c_int), value :: f_col
END SUBROUTINE c_mult_tab2d
END INTERFACE
END MODULE m_interf
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
1
2
PROGRAM f_appel_sub_c_tab2d
USE m_interf
IMPLICIT NONE
! f_col est connu du compilateur en fortran
! mais est un paramtre pour la fonction dfinie en C
INTEGER(kind=c_int), PARAMETER :: f_col = 4, f_col2 = 2
INTEGER(kind=c_int) :: mat(F_LIG, f_col), mat2(F_LIG, f_col2)
INTEGER :: i, j
! remplissage des tableaux
DO i = 1, F_LIG
DO j = 1, f_col
mat(i,j) = 10 * i + j
END DO
END DO
mat2(:,:) = - mat(:,1:f_col2)
! affichage en fortran
WRITE (*,*) "tableau 2d affich en fortran: 1er indice = ligne"
DO i = 1, F_LIG
WRITE(*,*) mat(i,:)
END DO
WRITE (*,*) "2me tableau 2d affich en fortran: 1er indice = ligne"
DO i = 1, F_LIG
WRITE(*,*) mat2(i,:)
END DO
! appel pour l'affichage en C
CALL c_print_tab2d(mat, f_col)
WRITE(*,*) "deuxime tableau"
CALL c_print_tab2d(mat2, f_col2)
! on multiplie chaque ligne par son numro
WRITE (*,*) "tableau 2d multipli par l'indice de ligne fortran"
CALL c_mult_tab2d(mat, f_col)
! appel pour l'affichage en C
CALL c_print_tab2d(mat, f_col)
END PROGRAM f_appel_sub_c_tab2d
#include <stdio.h>
#include <stdlib.h>
Partie langage C
3
4
5
135
7
8
#define C_N2 3
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
12.5.2
On peut utiliser les fonctions avances du fortran portant sur les tableaux partir du langage
C, y compris dans le cas de tableaux dynamiques allous et dsallous en C. Dans le cas de tableaux
de rang 1, on dfinit en C une structure vecteur (lignes 11 14) comportant un pointeur C sur le
dbut du tableau (de float ici) et un entier spcifiant le nombre de ses lments. On dfinit un type
driv vecteur inter-oprable en fortran (module m_vecteur) constitu des mmes composantes
en utilisant les types inter-oprables c_ptr et c_int associs en fortran.
Une fois largument vecteur pass au fortran par copie 7 (ligne 8), il sagit de lui associer un
tableau de rang 1 de la taille prcise et dont les lments sont ceux points par le pointeur C. Les
tableaux allouables ou les tableaux attribut pointeur du fortran sont plus riches que les pointeurs
du C, car ils comportent les informations sur le profil du tableau.
On utilise donc le sous-programme c_f_pointer (ligne 16) pour effectuer le transfert des informations de la structure C vers le pointeur fortran. ce propos, noter que la conversion du
7. Avec le passage par valeur, on sinterdit de modifier le pointeur C et la taille du tableau, donc de librer ou
de rallouer le tableau en fortran. Bien sr les valeurs des lments du tableau sont modifiables en fortran.
136
B paramtre de taille de INTEGER(kind=c_int) en entier par dfaut (ligne 13) est ncessaire pour
spcifier le profil du tableau de faon portable en fortran. Une fois le tableau connu du fortran, on
peut lui appliquer toutes les transformations possibles avec les fonctions-tableau du fortran, tant
que lon ne modifie pas sa taille.
1
2
3
4
5
6
7
8
9
10
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
137
typedef struct {
int n ;
float *v;
} vecteur;
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
int main(void) {
vecteur v1 = {0, NULL};
int i;
/* Lecture du nombre de dimensions */
while(
printf("Entrez le nombre de composantes : (0 pour terminer) \n"),
scanf("%d", &(v1.n)),
v1.n > 0){
/* Allocation mmoire en C */
v1.v = (float *) calloc((size_t) v1.n, sizeof (float));
/*
size_t: conversion ncessaire en 64 bits */
/* Affectation des composantes */
for (i=0; i<v1.n; i++) {
v1.v[i] = (float) (i+1) ;
}
/* Affichage des composantes */
printf("affichage des %d composantes\n", v1.n);
for (i=0; i<v1.n; i++) {
printf("%f ", v1.v[i]);
}
printf("\n");
/* appel de la subroutine fortran */
printf("appel fortran \n"),
f_modif_vect(v1); /* pointeur vers la structure de vecteur*/
/* Impression du rsultat */
printf("affichage des composantes aprs appel fortran\n");
for (i=0; i<v1.n; i++) {
printf("%f ", v1.v[i]);
}
printf("\n");
/* Libration de la memoire dans le mme langage */
/* on suppose que libration <=> v1.n =0 */
if (v1.n > 0 || v1.v != NULL ) {
free(v1.v);
v1.n = 0;
v1.v = NULL ;
printf("mmoire libre en C\n");
}
}
exit (EXIT_SUCCESS);
}
Si on passe la structure vecteur par pointeur en C, le pointeur du tableau et le nombre de
composantes seront modifiables : il est ainsi possible de librer le tableau et de le rallouer avec
ventuellement une taille diffrente. Cette opration peut tre dclenche par le fortran, mais en
appelant une fonction C laquelle on repasse la structure vecteur. En effet, plus globalement, un
espace mmoire allou dans un langage doit tre dsallou dans ce mme langage.
Annexe A
Procdures intrinsques
Les procdures intrinsques sont des procdures intgres au langage, en ce sens que leur interface est connue (aucune dclaration explicite via USE par exemple nest ncessaire) et que leur code
objet est inclus dans la bibliothque du fortran (aucune autre bibliothque nest requise lors de
ldition de liens). La plupart des procdures intrinsques font partie du standard du fortran 90,
dautres ont t ajoutes en fortran 95 puis en fortran 2003, et en fortran 2008 (les fonctions inverses de trigonomtrie hyperbolique, les fonctions erreur et gamma ainsi que certaines fonctions
de Bessel, voir Site gfortran, de la collection de compilateurs gcc par exemple). Par ailleurs, des
options de compilation (cf. E.5.1, p. 170 pour g95, et E.6.1, p. 171 pour gfortran) permettent
dautoriser lemploi dautres fonctions intrinsques comme extension au standard.
Cette annexe rassemble les principales procdures intrinsques standard du fortran 90, 2003 et
2008. Les fonctions lmentaires (elemental) (cf. 6.5.8, p. 78) sont prcdes du signe .
A.1
ABS(a)
ACOS(x)
ACOSH(x)
ASIN(x)
ASINH(x)
ATAN(x)
ATAN2(y,x)
ATANH(x)
BESSEL_J0(x)
BESSEL_J1(x)
BESSEL_JN(n,x)
BESSEL_Y0(x)
BESSEL_Y1(x)
BESSEL_YN(n,x)
CONJG(x)
COS(x)
COSH(x)
DIM(a,b)
ERF(x)
ERFC(x)
EXP(x)
GAMMA(x)
138
f2008
f2008
[, ]
f2008
f2008
f2008
f2008
f2008
f2008
f2008
f2008
f2008
f2008
139
HYPOT(x,y)
LOG(x)
LOG10(x)
LOG_GAMMA(x)
MAX(a1,a2,...)
MIN(a1,a2,...)
MOD(a,p)
MODULO(a,p)
SIGN(a,b)
SIN(x)
SINH(x)
SQRT(x)
TAN(x)
TANH(x)
x
tan(x)
tanh(x)
p
p
p
u
4
u
2
0
+1
u
+2
+3
u
+4
+5
1
2
u
4
u
2
0u
1
+1
u
+2
+3
u
+4
+5
4
u
2
u
+1
+2
u
+3
+4
u
+5
a
-
1
2
140
A.2
AIMAG(z)
AINT(a[,kind])
ANINT(a[,kind])
CEILING(a[,kind])
CMPLX(x[,y][,kind])
FLOOR(a[,kind])
INT(a[,kind])
LOGICAL(L[,kind])
NINT(a[,kind])
REAL(a[,kind])
CEILING(a) 6
FLOOR(a) 6
u
+2
+1
0u
2
+1
+2
0u
2
+1
+1
+2
A.3
+2
u
0
3/2 1/2 +1/2 +3/2
u 1
u
0
1
+2
NINT(a) 6
+2
+1
1
u 1
+1
+1
u 1
u
+2
u
1
u
Gnrateur pseudo-alatoire
Les gnrateurs pseudo-alatoires fournissent des tirages successifs statistiquement indpendants pris dans une suite finie de trs longue priode qui dpend du processeur et du compilateur,
141
mais dont linterface dappel RANDOM_NUMBER est, elle, portable. Le gnrateur possde une mmoire, ou tableau dtat, qui progresse naturellement chaque invocation, mais qui peut aussi
tre manipule grce au sous-programme RANDOM_SEED. En mmorisant ltat du gnrateur un
instant donn, et en lui imposant 1 plus tard la valeur mmorise, on peut forcer le gnrateur
reprendre les tirages partir dun tat dtermin et reproduire ainsi plusieurs fois la mme
squence.
RANDOM_NUMBER(harvest)
gnrateur de nombres pseudo-alatoires distribus uniformment
sur [0, 1[; harvest est un scalaire ou un tableau de rels.
RANDOM_SEED(SIZE|PUT|GET) initialisation du gnrateur de nombres pseudo-alatoires a , quatre usages possibles en fonction du mot-clef choisi :
() initialisation des valeurs dpendant du processeur
call RANDOM_SEED()
(SIZE) lecture de la dimension du tableau dtat INTENT(out)
INTEGER :: n
call RANDOM_SEED(SIZE = n)
PRINT *, ' taille ', n
(GET) lecture des valeurs du tableau dtat INTENT(out)
INTEGER :: n
INTEGER, DIMENSION(n) :: tab
call RANDOM_SEED(GET = tab(1:n))
PRINT *, ' tableau d''tat ', tab
(PUT) rinitialisation du tableau dtat INTENT(in)
INTEGER :: n
INTEGER, DIMENSION(n) :: tab
tab(1:n) = ... ! au moins une valeur non nulle
call RANDOM_SEED(PUT = tab(1:n))
Avec le compilateur xlf dibm, un autre mot-clef, GENERATOR
est disponible, qui permet de choisir entre le gnrateur de base
(GENERATOR=1, valeur par dfaut) ou un gnrateur optimis
(GENERATOR=2), plus rapide et de priode plus grande.
a. La taille du tableau dtat du gnrateur alatoire nest pas spcifie par le standard. Elle dpend du compilateur utilis. Sous Linux et processeur Intel ou amd 32 bits, elle est de 1 avec le compilateur f95 de nag, de
2 avec le traducteur f90 (de fortran 90 vers fortran 77) Vast (Pacific Sierra) et le compilateur ifort dIntel, de 4
avec g95 et de 34 avec pgf90 de Portland. Avec un processeur amd 64 bits, cette taille passe 2 avec g95, qui utilise
des entiers par dfaut sur 64 bits, mais cela correspond au mme nombre doctets. Avec gfortran et un processeur
64 bits, la taille du tableau dtat dpend de la version du compilateur (8 en v4.4.7 et 12 en v4.9.2).
Avec le compilateur de Portland sous Solaris de sun, elle est de 4. Sur la machine nec SX5 de lIDRIS, elle est
de 128. Sous dec-osf1 et processeur Alpha de 64 bits, elle est de 2, comme sous aix avec le compilateur xlf dibm.
PROGRAM random_test
IMPLICIT NONE
REAL
:: x
REAL, DIMENSION(3,4) :: alea
INTEGER :: n_alea ! taille de la mmoire du gnrateur alatoire de fortran90
INTEGER, DIMENSION(:), ALLOCATABLE :: mem_alea, mem_alea2 ! tableaux d'tat
1. Ds que lon force le tableau dtat, on risque de perdre lindpendance entre des tirages successifs.
142
10
15
20
25
30
35
40
45
INTEGER :: i, erreur_alloc
! tirage d'un nombre pseudo-alatoire entre 0 et 1
CALL RANDOM_NUMBER(x)
WRITE (*, *) ' valeur tire: x = ',x
! tirage d'un tableau de nombres pseudo-alatoires indpendants entre 0 et 1
CALL RANDOM_NUMBER(alea)
WRITE (*, *) ' tableau des valeurs tires:'
DO i = 1, SIZE(alea, 1)
WRITE (*, *) alea(i, :)
END DO
! recherche de la taille du tableau d'tat
CALL RANDOM_SEED(SIZE = n_alea)
WRITE(*, *) ' taille de la mmoire du gnrateur alatoire : ', n_alea
! rservation de mmoire pour deux tableaux d'tat
ALLOCATE(mem_alea(n_alea), stat = erreur_alloc)
IF(erreur_alloc /= 0 ) STOP
ALLOCATE(mem_alea2(n_alea), stat = erreur_alloc)
IF(erreur_alloc /= 0 ) STOP
! lecture et mmorisation du tableau d'tat courant avant la boucle
CALL RANDOM_SEED(GET = mem_alea)
WRITE(*, *) '- tableau d''tat du gnrateur avant la boucle:', mem_alea(:)
DO i = 1 , 3
! lecture et affichage du tableau d'tat courant puis tirage
CALL RANDOM_SEED(GET = mem_alea2)
WRITE(*, *) ' tableau d''tat du gnrateur :', mem_alea2(:)
CALL RANDOM_NUMBER(x)
WRITE (*, *) ' valeur tire: x = ',x
END DO
! rinitialisation avec le tableau d'tat mmoris avant la boucle
! pour repartir du mme tat et donc obtenir la mme srie
CALL RANDOM_SEED(PUT = mem_alea)
WRITE (*, *) '- puis rinitialisation l''tat avant la boucle '
DO i = 1 , 3
! lecture et affichage du tableau d'tat courant puis tirage
CALL RANDOM_SEED(GET = mem_alea2)
WRITE(*, *) ' tableau d''tat du gnrateur :', mem_alea2(:)
CALL RANDOM_NUMBER(x)
WRITE (*, *) ' valeur tire: x = ',x
END DO
END PROGRAM random_test
A.4
DIGITS(x)
EPSILON(x)
EXPONENT(x)
FRACTION(x)
HUGE(x)
KIND(x)
MAXEXPONENT(x)
MINEXPONENT(x)
NEAREST(x,s)
PRECISION(x)
RADIX(x)
RANGE(x)
RRSPACING(x)
SCALE(x, i)
SELECTED_INT_KIND(r)
SELECTED_REAL_KIND(p,r)
SET_EXPONENT(x, i)
SPACING(a)
TINY(x)
BIT_SIZE(i)
143
a. Largument i peut aussi tre un tableau dentiers, mais la taille est celle du scalaire.
A.5
ALL(array[,dim])
144
PRODUCT(array[,dim][,mask])
RESHAPE(source,shape[,pad][,order])
SHAPE(array)
SIZE(array[,dim])
SPREAD(source,dim,ncopies)
SUM(array[,dim][,mask])
TRANSPOSE(matrix)
UBOUND(array[,dim])
UNPACK(vector, mask, field)
A.6
Manipulation de bits
Les fonctions intrinsques suivantes permettent la manipulation directe de bits sur les entiers :
BTEST(i, pos)
IAND(i, j)
IBCLR(i, pos)
IBITS(i, pos, len)
IBSET(i, pos)
IEOR(i, j)
IOR(i, j)
ISHFT(i, shift)
ISHFTC(i, shift)
NOT(i)
A.7
Divers
PRESENT(a)
TRANSFER(source, mold [, size])
Lusage de la fonction TRANSFER est susceptible de nuire la portabilit des codes 2 , car cette
fonction sappuie sur la reprsentation binaire des variables qui peut dpendre de lordinateur. Noter
que cette opration peut aussi tre ralise par criture puis relecture sur fichier texte externe au
format binaire (format B, cf. 5.4.1). Elle permet par exemple de considrer les 32 bits dune zone
de la mmoire codant un entier comme les 32 bits codant un rel ; la valeur numrique de ce rel
est videmment diffrente de celle de lentier ; les bits considrs peuvent mme reprsenter un rel
invalide ou une valeur spciale telle que Inf ou Nan.
2. Cette rinterprtation dun motif binaire selon un autre type constitue une opration de bas niveau, facile
coder en C avec des pointeurs par transtypage : float a; int i; int * p; p =&i; a = *((float *) p);. En
fortran, lassociation entre pointeurs de types diffrents est au contraire interdite.
145
A.8. POINTEURS
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
A.8
ASSOCIATED(pointer [, target])
NULL([mold])
A.9
partir de la norme fortran 2008, le module intrinsque ISO_FORTRAN_ENV (cf. 5.3.1, p. 41)
fournit deux fonctions dinterrogation sans argument qui renvoient une chane de caractres sur
lenvironnement de compilation :
COMPILER_OPTIONS() indique la liste des options du compilateur actives.
f2008
COMPILER_VERSION() indique la version du compilateur.
f2008
146
Exemple dutilisation :
1
2
3
4
5
6
7
8
PROGRAM compiler_info
! standard fortran 2008 : emploi du module ISO_FORTRAN_ENV
! juin 2013: pas OK en gfortran 4.4, mais OK en gfortran 4.6
USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY : compiler_version, compiler_options
IMPLICIT NONE
WRITE(*,*) "version du compilateur : ", compiler_version()
WRITE(*,*) "options du compilateur : ", compiler_options()
END PROGRAM compiler_info
Affichage obtenu :
1
2
f2003
A.10
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
147
PROGRAM t_environ
IMPLICIT NONE
CHARACTER(len=20) :: nom, valeur, arg0, arg
CHARACTER(len=80) :: commande
INTEGER :: longueur, statut, n_param, i
WRITE(*,*) "rcupration d'une variable d'environnement"
nom(1:) = "SHELL"
CALL get_environment_variable(nom, valeur, longueur, statut)
IF (statut /= 0) STOP "erreur get_environment_variable"
WRITE(*,*) nom(1:5), "=", valeur(1:longueur)
CALL get_command(COMMAND=commande, LENGTH=longueur, STATUS=statut)
IF (statut /= 0) STOP "erreur get_command"
WRITE(*,*) "longueur de la ligne de commande", longueur
WRITE(*,*) "ligne de commande = |", commande(1:longueur), "|"
CALL get_command_argument(0, arg0, longueur, statut)
IF (statut /= 0) STOP "erreur get_command_argument"
WRITE(*,*) "commande ayant lanc ce programme=", arg0(1:longueur)
n_param = command_argument_count()
WRITE(*,*) "nb de paramtres de la commande = ", n_param
DO i=1, n_param
CALL get_command_argument(i, arg, longueur, statut)
IF (statut /= 0) STOP "erreur get_command_argument"
WRITE(*,*) "paramtre ", i, " de la commande=", arg(1:longueur)
END DO
END PROGRAM t_environ
f2008
A.11
EXECUTE_COMMAND_LINE(command [,wait] [,exitstat] [,cmdstat], [,cmdmsg]) est un sousprogramme qui permet de passer la commande command (argument dentre de type chane de
caractres) au systme dexploitation. Tous ses autres arguments sont optionnels :
wait est un argument dentre de type boolen, vrai par dfaut, qui permet dautoriser une
excution asynchrone de la commande.
exitstat est un argument entier de vocation inout, qui, sauf si la commande est lance en
asynchrone, rcupre le statut de retour de la commande systme.
cmdstat est un argument de sortie entier qui vaut 0 si la commande sest excute sans erreur,
-1 si le processeur ne peut pas lexcuter et -2 si le processeur ne peut honorer lexcution
synchrone requise (wait=.true.) et une valeur positive pour les autres erreurs.
cmdmsg est un argument de type chane de caractres de vocation inout, qui, si cmdstat est
positif, contient un message dexplication.
148
f95
A.12
Gestion du temps
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
MODULE util_time
IMPLICIT NONE
CONTAINS
REAL FUNCTION deltat(td, tf)
! calcul de la duree en secondes
! attention : incorrect si changement de date
INTEGER, DIMENSION(8), INTENT(in) :: td, tf
deltat = (tf(8) -td(8))/1000. + (tf(7) -td(7)) + &
60 * ( (tf(6) -td(6)) + 60 *(tf(5) -td(5)))
END FUNCTION deltat
SUBROUTINE affiche(t)
! affichage de la date suivie du temps
! en heures, minutes, secondes et millisecondes
INTEGER, DIMENSION(8), INTENT(in) :: t
WRITE(*,'(i2.2,a,i2.2,a,i4.4, a, i2.2,a,i2.2,a,i2.2,a,i3.3, a)') &
t(3),"/",t(2),"/",t(1), " ", &
t(5), "h", t(6), "'", t(7), '"', t(8), "ms "
END SUBROUTINE
END MODULE util_time
PROGRAM datetime ! test du sous-programme date_and_time
USE util_time
INTEGER, DIMENSION(8) :: debut, fin
CHARACTER(len=8) :: jour
CHARACTER(len=10) :: instant
INTEGER:: i, j
CALL DATE_AND_TIME(date=jour, time=instant)
WRITE(*,*) "date (AAAAMMJJ) : ", jour
WRITE(*,*) "heure (hhmmss.*): ", instant
CALL DATE_AND_TIME(values=debut)
WRITE(*,'(a)', advance="no") "debut "
CALL affiche(debut)
DO i=1, 1000000 ! ajuster < huge(i)
j = 1 - i
END DO
CALL DATE_AND_TIME(values=fin)
WRITE(*,'(a)', advance="no") "fin
"
CALL affiche(fin)
WRITE(*,*) "duree de la boucle", deltat(debut, fin), 's'
END PROGRAM datetime
1
2
3
4
5
149
CPU_TIME(time)
sous-programme permettant daccder au temps du processeur exprim en secondes avec une rsolution de la microseconde : lorigine est arbitraire, seules les diffrences sont pertinentes. Ce
sous-programme permet notamment dvaluer des dures dexcution de code. Le paramtre est
un argument de sortie rel.
SYSTEM_CLOCK([count] [,count_rate] [,count_max])
sous-programme permettant daccder au temps exprim en nombre de tops dhorloge de frquence
COUNT_RATE modulo une valeur maximale COUNT_MAX. Les trois arguments sont des arguments de
sortie entiers optionnels.
A.13
ACHAR(i)
CHAR(i [, kind])
IACHAR(c)
ICHAR(c)
NEW_LINE(a)
SELECTED_CHAR_KIND(name)
ADJUSTL(string)
ADJUSTR(string)
LEN(string)
LEN_TRIM(string)
REPEAT(string,ncopies)
TRIM(string)
LGE(string_a,string_b)
vrai si string_a est plac aprs string_b dans lordre lexicographique de lascii ou concide avec string_b
vrai si string_a est plac strictement aprs string_b dans
lordre lexicographique de lascii
vrai si string_a est plac avant string_b dans lordre lexicographique de lascii ou concide avec string_b
vrai si string_a est plac strictement avant string_b dans
lordre lexicographique de lascii
LGT(string_a,string_b)
LLE(string_a,string_b)
LLT(string_a,string_b)
INDEX(string,substring)
SCAN(string,set)
VERIFY(string,set)
150
Dec
Hex
Char
Oct
Dec
Hex
Char
000
001
002
003
004
005
006
007
010
011
012
013
014
015
016
017
020
021
022
023
024
025
026
027
030
031
032
033
034
035
036
037
040
041
042
043
044
045
046
047
050
051
052
053
054
055
056
057
060
061
062
063
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
00
01
02
03
04
05
06
07
08
09
0A
0B
0C
0D
0E
0F
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F
20
21
22
23
24
25
26
27
28
29
2A
2B
2C
2D
2E
2F
30
31
32
33
NUL \0
SOH
STX
ETX
EOT
ENQ
ACK
BEL \a
BS \b
HT \t
LF \n
VT \v
FF \f
CR \r
SO
SI
DLE
DC1
DC2
DC3
DC4
NAK
SYN
ETB
CAN
EM
SUB
ESC
FS
GS
RS
US
SPACE
!
"
#
$
%
&
'
(
)
*
+
,
.
/
0
1
2
3
100
101
102
103
104
105
106
107
110
111
112
113
114
115
116
117
120
121
122
123
124
125
126
127
130
131
132
133
134
135
136
137
140
141
142
143
144
145
146
147
150
151
152
153
154
155
156
157
160
161
162
163
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
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
60
61
62
63
64
65
66
67
68
69
6A
6B
6C
6D
6E
6F
70
71
72
73
@
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
[
\
]
^
&
`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
\\
151
064
065
066
067
070
071
072
073
074
075
076
077
52
53
54
55
56
57
58
59
60
61
62
63
34
35
36
37
38
39
3A
3B
3C
3D
3E
3F
4
5
6
7
8
9
:
;
<
=
>
?
164
165
166
167
170
171
172
173
174
175
176
177
116
117
118
119
120
121
122
123
124
125
126
127
74
75
76
77
78
79
7A
7B
7C
7D
7E
7F
t
u
v
w
x
y
z
{
|
}
~
DEL
Plusieurs codages des caractres sur 8 bits permettent dtendre le code ascii en reprsentant
aussi les caractres dots de signes diacritiques (accents, cdille, ...) prsents dans les langages
europens. Le tableau suivant indique les caractres du codage iso-8859-1 (alphabet latin 1, pour
les langues de lEurope occidentale) qui sont imprimables et ne figurent pas dans le codage ascii.
Oct
Dec
Hex
Char
Description
240
241
242
243
244
245
246
247
250
251
252
253
254
255
256
257
260
261
262
263
264
265
266
267
270
271
272
273
274
275
276
277
300
301
302
303
304
305
306
307
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
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
AA
AB
AC
AD
AE
AF
B0
B1
B2
B3
B4
B5
B6
B7
B8
B9
BA
BB
BC
BD
BE
BF
C0
C1
C2
C3
C4
C5
C6
C7
NO-BREAK SPACE
INVERTED EXCLAMATION MARK
CENT SIGN
POUND SIGN
CURRENCY SIGN
YEN SIGN
BROKEN BAR
SECTION SIGN
DIAERESIS
COPYRIGHT SIGN
FEMININE ORDINAL INDICATOR
LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
NOT SIGN
SOFT HYPHEN
REGISTERED SIGN
MACRON
DEGREE SIGN
PLUS-MINUS SIGN
SUPERSCRIPT TWO
SUPERSCRIPT THREE
ACUTE ACCENT
MICRO SIGN
PILCROW SIGN
MIDDLE DOT
CEDILLA
SUPERSCRIPT ONE
MASCULINE ORDINAL INDICATOR
RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
VULGAR FRACTION ONE QUARTER
VULGAR FRACTION ONE HALF
VULGAR FRACTION THREE QUARTERS
INVERTED QUESTION MARK
LATIN CAPITAL LETTER A WITH GRAVE
LATIN CAPITAL LETTER A WITH ACUTE
LATIN CAPITAL LETTER A WITH CIRCUMFLEX
LATIN CAPITAL LETTER A WITH TILDE
LATIN CAPITAL LETTER A WITH DIAERESIS
LATIN CAPITAL LETTER A WITH RING ABOVE
LATIN CAPITAL LETTER AE
LATIN CAPITAL LETTER C WITH CEDILLA
152
310
311
312
313
314
315
316
317
320
321
322
323
324
325
326
327
330
331
332
333
334
335
336
337
340
341
342
343
344
345
346
347
350
351
352
353
354
355
356
357
360
361
362
363
364
365
366
367
370
371
372
373
374
375
376
377
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
C8
C9
CA
CB
CC
CD
CE
CF
D0
D1
D2
D3
D4
D5
D6
D7
D8
D9
DA
DB
DC
DD
DE
DF
E0
E1
E2
E3
E4
E5
E6
E7
E8
E9
EA
EB
EC
ED
EE
EF
F0
F1
F2
F3
F4
F5
F6
F7
F8
F9
FA
FB
FC
FD
FE
FF
Annexe B
PARAMETER
IMPLICIT
PARAMETER et DATA
DATA
instructions excutables
CONTAINS
153
Annexe C
Introduction
Reprsentation des rels en virgules flottante
Reprsenter un rel (non nul) en virgule flottante dans une base b consiste en donner une
approximation finie sous la forme :
0
e0
e0
r=sb m =sb
0
q
X
(C.1)
pi bi
i=0
o
s = 1 est le signe ;
e0 est un entier qualifi dexposant ;
m0 est le significande, appel abusivement la mantisse que lon peut dcomposer sur la base
b selon les q 0 + 1 poids entiers pi tels que 0 6 pi < b
Plusieurs dcompositions mantisseexposant tant possibles (de la mme faon quen dcimal, on
peut crire 1,2 100 ou 0,12 101 ), on choisit ici lexposant pour que 1 6 m0 < b (qui correspondrait lintervalle [1., 10.[ si on travaillait en dcimal). Cette reprsentation diffre donc de
celle introduite plus haut (cf. 2.2, p. 13), avec une mantisse m entre 1/b et 1 (qui correspondrait
lintervalle [.1, 1.[ si on travaillait en dcimal), choix qui tait plus en accord avec les fonctions
intrinsques FRACTION et EXPONENT. Ces deux reprsentations sont lies par e0 = e 1 et q 0 = q 1.
Dans le cas de la base 2 et en prenant en compte le choix dun premier bit p0 de m0 1,
lexpression (C.1) prend la forme :
r = (1) 2
s
e0
1+
q1
X
pi
i=1
q1
2i
e0
= (1) 2 (1 + f ) = (1) 2
s
1 X pi
+
2 i=1 2i+1
!
(C.2)
exposant
E bits
154
mantisse
M bits
C.1.2
155
Arithmtique tendue
Mais la norme IEEE-754-2008 permet aussi de reprsenter des rsultats doprations arithmtiques qui ne svaluent pas comme des rels, tels que :
1./0. soit + affich +Inf
-1./0. soit affich -Inf
0./0. qui est indtermin, ou sqrt(-1.) qui est une opration invalide : il est cod comme
NaN soit Not-A-Number . NaN possde aussi une variante ngative. Enfin, les rsultats NaN
peuvent donner lieu des messages (signaling NaN) ou tre propags sans avertissement dans
les calculs (quiet NaN) : un bit particulier permet de dterminer ce comportement.
Larithmtique traditionnelle stend ces valeurs spciales de faon naturelle si on prcise
que ds quun NaN intervient dans une expression, le rsultat est aussi reprsent par un NaN. Par
exemple, Inf + Inf donne +Inf, mais Inf - Inf donne NaN. Enfin, le codage IEEE permet de
reprsenter un zro positif et un zro ngatif qui interviennent naturellement dans des
oprations arithmtiques tendues telles que 1./+Inf ou 1./-Inf.
C.2
Lexposant e0 cod sur E bits qui dtermine lintervalle couvert dfinissant ainsi le domaine, est
de signe a priori quelconque entre 2E1 + 1 et 2E1 : on lui ajoute 2E1 1 de faon stocker le
nombre sans signe e00 = e0 + 2E1 1, appel exposant biais, qui est un entier compris entre 0 et
2E 1. Mais on exclut les deux valeurs extrmes de lexposant pour rserver ces codes spciaux (o
les bits de lexposant e00 sont tous 0 ou tous 1) aux deux zros signs et larithmtique tendue
de la norme IEEE. Ainsi, pour les codes normaux, 1 6 e00 6 2E 2, donc 2E1 +2 6 e0 6 2E1 1.
C.2.1
En binaire, pour les nombres normaliss, le bit de plus fort poids de la mantisse m0 vaut donc 1.
On convient alors de ne pas le stocker pour gagner un bit sur la prcision de la reprsentation ; on
stocke donc la partie fractionnaire f de la mantisse sur M = q 0 = q 1 bits seulement. Mais le
nombre de bits de la mantisse donn par la fonction intrinsque DIGITS est M + 1 = q car il prend
en compte ce bit cach.
00
E1
Ainsi pour les flottants normaliss, r = (1)s 2e 2 +1 1.f o f est la partie fractionnaire
n n+1
de la mantisse. Dans chaque octave [2 , 2
[, il y a 2M nombres reprsents exactement, en
nM
progression arithmtique de raison 2
; cette raison double chaque changement doctave. Si le
successeur de 2n est 2n (1 + 2M ), son prdcesseur est 2n (1 2M 1 ).
Valeurs extrmes
Le plus grand rel normalis positif ainsi reprsentable, donn par la fonction HUGE,
est donc
Pi=M
obtenu pour e00 = 2E 2, soit e0 = 2E1 1 avec p0 = 1 et pi = 1 pour i > 0, soit m0 = i=0 2i =
E1
(1 2M 1 ). Si un calcul donne une valeur absolue suprieure
2(1 2M +1 ). Il vaut donc 22
HUGE(x), il y a thoriquement dpassement de capacit par valeur suprieure (floating overflow).
Le plus petit rel positif normalis ainsi reprsentable, donn par la fonction TINY, est donc
obtenu pour e00 = 1, soit e0 = 2E1 + 2 avec p0 = 1 et pi = 0 pour i > 1, soit f = 0. Il vaut
E1
donc 22 +2 . Si un calcul donne une valeur absolue non nulle mais infrieure TINY(x), il y a
thoriquement dpassement de capacit par valeur infrieure (floating underflow).
Le nombre doctaves de rels positifs est e00max e00min + 1, soit 2E 2.
C.2.2
Mais, quitte perdre en prcision, on peut aussi reprsenter des nombres de valeur absolue
infrieure la plus petite valeur ayant un exposant dcal e00 nul : on travaille alors en virgule
fixe. Si lexposant dcal e00 est nul, les M bits suivants reprsentent exactement la mantisse sans
156
bit cach 1 : on dfinit ainsi les nombres dnormaliss. Le plus petit nombre dnormalis positif
E1
(tous les bits 0 sauf le dernier) vaut donc 22 +2M .
10R
EPSILON(1.)
- +HUGE(1.)
TINY(1.) 0 +TINY(1.)
HUGE(1.)
1
10R
dnormaliss
o R= RANGE(1.)
+10R
+1
EPSILON(1.)/2
+10R
SPACING(X)
-
NEAREST(X,-1)
NEAREST(X,+1)
Figure C.1 Reprsentation des rels. Mme si lchelle sapparente une chelle log, celle-ci
nest pas respecte afin de figurer le zro. De plus, successeur (NEAREST(X,1.))et prdcesseur
de X (NEAREST(X,-1.)) sont en gnral gale distance de X (progression arithmtique de raison
SPACING(X) dans chaque octave) sauf si X est la limite dune octave, cest dire une puissance
entire de 2 (dans ce cas le pas est deux fois plus faible du ct de zro).
C.3
Les codes employs pour les valeurs spciales de larithmtique tendue sont caractriss par le
fait que tous leurs bits dexposant sont 1. On note aussi les deux zros signs avec tous les bits
dexposant 0.
+0
-0
quiet NaN > 0
signaling NaN > 0
quiet NaN < 0
signaling NaN < 0
+Inf
-Inf
C.3.1
signe
0
1
0
0
1
1
0
1
exposant
E bits 0
E bits 0
E bits 1
E bits 1
E bits 1
E bits 1
E bits 1
E bits 1
mantisse
M bits zro
M bits zro
1 suivi de (M-1) bits quelconques
0 suivi dau moins 1 bit 1
1 suivi de (M-1) bits quelconques
0 suivi dau moins 1 bit 1
M bits 0
M bits 0
Il est cependant ncessaire de choisir les options de compilation adquates pour imposer le
respect de la norme IEEE (voir par exemple E.4.1 p. 168 pour ifort et E.3.1 p. 167 pour pgf95)
dans la propagation des drapeaux indiquant la sortie de larithmtique classique. On peut en effet
constater une grande diversit de comportement par dfaut entre plusieurs compilateurs sur le
simple cas dun calcul dont le rsultat devrait tre indtermin.
PROGRAM nan_indeterm
IMPLICIT NONE
REAL :: zero, infini, indet
zero = 0.
infini = 1./zero
indet = infini * zero ! en principe indtermin
WRITE(*,*) " 0. ,
1./0.,
WRITE(*,*) zero, infini, indet
END PROGRAM nan_indeterm
157
(1./0.)*0."
C.4
C.4.1
Les rels par dfaut sont gnralement stocks sur 32 bits avec 8 bits dexposant et 23 bits plus
un bit 1 non stock pour la mantisse. Le dcalage de lexposant est de 127.
signe
s
1 bit
exposant biais
e00
8 bits
r = (1)s 2e
127
1.f o f = m0 1
(C.3)
Pour des flottants sur 32 bits (cf. table C.1, p. 158), la plus petite valeur positive en normalis,
cest--dire le rsultat de la fonction TINY, vaut 2126 soit approximativement 1.175494E-38. La
plus grande valeur, cest--dire le rsultat de la fonction HUGE, est obtenue avec les 23 bits de la
mantisse 1 et le plus grand exposant (7 bits 1 et le dernier 0). Elle vaut 2+127 (2223 ) 2128 ,
soit approximativement 3.402823E+38. Quant la prcision relative, elle est caractrise par la
fonction EPSILON, lcart relatif maximal entre deux flottants successifs, soit 223 1.192093E-7.
Dans chaque octave, de 2n 2n+1 par exemple, il y a 223 , soit environ 8 millions de rels en
progression arithmtique de raison 2n23 . Pour conserver approximativement la prcision relative,
le pas double quand on progresse dune octave en sloignant de zro. Noter que le voisin gauche
de +1., soit NEAREST(+1.,-1.) est deux fois plus proche de +1. que son voisin de droite, soit
NEAREST(+1.,+1.). Enfin, le nombre doctaves 1 de rels positifs normaliss est de 28 2 = 254.
1. Le nombre total de rels normaliss non nuls sur 32 bits est donc 2 223 (28 2), soit 232 225 . Si on y ajoute
158
00000000
00000000
00000001
11111110
01111111
01111111
01111111
10000000
10000000
01111111
01111110
00000000
11111111
00000000000000000000000
00000000000000000000000
00000000000000000000000
11111111111111111111111
00000000000000000000000
10000000000000000000000
11000000000000000000000
11111111111111111111111
00000000000000000000000
00000000000000000000001
11111111111111111111111
00000000000000000000001
00000000000000000000000
+0
-0
TINY(1.) 21127 1. = 2126
HUGE(1.) 2254127 2
1 = 2127127
1.5 = 2127127 (1 + 21 )
1.75 = 2127127 (1 + 21 + 22 )
2 223 = NEAREST(2.,-1.)
2
NEAREST(1.,+1.)=1+EPSILON(1.) = 1 + 223
NEAREST(1.,-1.) = 1 224
2127 222 = 2149 (plus petit dnormalis > 0)
+Inf
Pour vrifier le codage binaire, on peut utiliser le format binaire b (cf. 5.4.1, p. 48) des rels :
en criture, il permet de convertir un rel dcimal en binaire et en lecture de convertir du binaire
en rel affich en dcimal.
PROGRAM bin_real
! format B avec des rels = norme 2008
! accepte par gfortran et ifort, pas par g95
IMPLICIT NONE
REAL :: r0 = 1. ! rel par dfaut (32 bits)
CHARACTER(len=32) :: binreal
WRITE(*, *) "mantisse sur",DIGITS(r0),"bits (1 cach)"
! criture d'un rel en binaire
WRITE(*, *) r0
WRITE(*, "(a)") "seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm"
WRITE(*, "(b32.32)") r0
! lecture d'un rel saisi en binaire
!
"seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm"
binreal="00111111100000000000000000000000" ! 1.
READ(binreal, "(b32.32)") r0
WRITE(*, "(es16.9)") r0
END PROGRAM bin_real
C.4.2
Les rels en double prcision sont gnralement stocks sur 64 bits avec 11 bits dexposant et
52 bits plus un bit 1 non stock pour la mantisse. Le dcalage de lexposant est de 1023.
signe
s
1 bit
exposant biais
e00
11 bits
r = (1)s 2e
1023
1.f o f = m0 1
(C.4)
2 223 rels dnormaliss et 2 zros, cela donne 232 224 + 2 valeurs normales, parmi les 232 codes disponibles. Au
contraire, tous les codes sur 32 bits reprsentent des entiers valides, qui sont donc trs lgrement plus nombreux
que les rels sur 32 bits !
10
159
Annexe D
D.1
D.2
C89
complments C99
int var;
float var;
char var;
complex var ;
bool var ;
addition
soustraction
multiplication
division
lvation la puissance
reste modulo j
fortran 90
+
*
/
**
MOD(i,j) ou MODULO(i,j)
160
langage C
+
*
/
pow(x,y)
%
161
D.3
infrieur
infrieur ou gal
gal
suprieur ou gal
suprieur
diffrent de
D.4
C
<
<=
==
>=
>
!=
fortran 90
ET
OU
NON
quivalence
OU exclusif
D.5
fortran 90
<
<=
==
>=
>
/=
.AND.
.OR.
.NOT.
.EQV.
.NEQV.
C
C89
&& (valuation minimale)
|| (valuation minimale)
!
C95
and
or
not
Les arguments des fonctions (en fortran) et les oprandes des oprateurs (en C) agissant bit
bit sont des entiers.
fortran 90
NOT(i)
IAND(i, j)
IOR(i, j)
IEOR(i, j)
ISHFT(i, j)
ISHFT(i, -j)
signification
ngation bit bit
et
ou (inclusif)
ou exclusif
dcalage gauche de j bits
dcalage droite de j bits
langage C
~i
i & j
i | j
i ^ j
i << j
i >> j
162
D.6
D.7
C
if (expr. log.)
bloc
else
bloc
switch ( expr. entire) {
case slecteur :
bloc
break;
default :
bloc
}
for (expr1 ; expr2 ; expr3 )
bloc
while (expr. log.)
bloc
continue;
break;
goto tiquette;
return;
exit;
fortran 90
REAL, POINTER:: ptr, pts
REAL, TARGET:: r
ptr => r
pts => ptr
ptr
ptr => null()
IF(ASSOCIATED(ptr))
IF(ASSOCIATED(ptr, pts))
ALLOCATE(ptr[...])
de plus, associe ptr
DEALLOCATE(ptr)
de plus, dsassocie ptr
pt_real = pt_int
pt_real => entier
pt_real => pt_entier
C
float *ptr, *pts;
float r;
ptr = &r;
pts = ptr;
*ptr
ptr = NULL;
if(ptr != NULL);
if(ptr == pts);
ptr=malloc(...);
ptr=calloc(...);
free(ptr);
ajouter ptr = NULL;
*pt_real = *pt_int
pt_real = &entier
pt_real = pt_entier
163
D.8
Les fonctions mathmatiques intrinsques du fortran sont utilisables sans faire appel un
quelconque USE, ni lier explicitement une bibliothque. linverse, pour utiliser les fonctions de la
bibliothque mathmatique en langage C, il est ncessaire dune part dinclure le fichier dentte
math.h et dautre part de lier la bibliothque libm.a. De plus, ces fonctions sont gnriques en
fortran, alors quen C, chaque type utilise une fonction spcifique 1 , do les variantes pour argument
entier (i), double (r), voire complexe (c) en C99, et les sous-variantes pour un argument de type
rel (double par dfaut) suffixes f pour les float, et l pour les long double.
fortran
ABS(a)
ACOS(a)
AIMAG(a)
ASIN(a)
ATAN(a)
ATAN2(a,b)
CEILING(a)
CONJG(a)
COS(a)
COSH(a)
EXP(a)
FLOOR(a)
LOG(a)
LOG10(a)
MOD(a,p)
MODULO(a,p)
NINT(a)
a**b
REAL(a)
SIGN(a,b)
SIN(a)
SINH(a)
SQRT(a)
TAN(a)
TANH(a)
NEAREST(a,s)
fortran 2008
ACOSH(a)
ASINH(a)
ATANH(a)
BESSEL_J0(a)
BESSEL_J1(a)
BESSEL_JN(n,a)
BESSEL_Y0(a)
BESSEL_Y1(a)
BESSEL_YN(n,a)
ERF(a)
ERFC(a)
GAMMA(a)
LOG_GAMMA(a)
HYPOT(a, b)
C89
abs(a) (i) fabs/f/l(a) (r)
acos/f/l(a) (r)
asin/f/l(a) (r)
atan/f/l(a) (r)
atan2/f/l(a,b)
ceil/f/l(a)
cos/f/l(a) (r)
cosh/f/l(a) (r)
exp/f/l(a) (r)
floor/f/l(a)
log/f/l(a) (r)
log10/f/l(a)
a%p si positifs
a%p si positifs
lrint/f/l(a)
pow/f/l(a,b) (r)
sin/f/l(a) (r)
sinh/f/l(a) (r)
sqrt/f/l(a) (r)
tan/f/l(a) (r)
tanh/f/l(a) (r)
C89 (r)
acosh/f/l(a)
asinh/f/l(a)
atanh/f/l(a)
j0/f/l(a)
j1/f/l(a)
jn/f/l(n,a)
y0/f/l(a)
y1/f/l(a)
yn/f/l(n,a)
erf/f/l(a)
erfc/f/l(a)
tgamma/f/l(a)
lgamma/f/l(a)
hypot/f/l(a,b)
C99
cabs(a) (z)
cacos/f/l(a)
cimag/f/l(a)
casin/f/l(a)
catan/f/l(a)
remarques
abs pour les entiers en C
(z)
(z)
(z)
(z)
norme C99
rsultat flottant en C
norme C99
conj/f/l(a) (z)
ccos/f/l(a) (z)
ccosh(a) (z)
cexp/f/l(a) (z)
rsultat flottant en C
clog/f/l(a) (z)
a%p
oprateur en C
oprateur en C
rsultat entier long en C
oprateur en fortran
cpow/f/l(a,b) (z)
creal/f/l(a,b)
copysign/f/l(a,b)
csin/f/l(a) (z)
csinh/f/l(a) (z)
csqrt(a) (z)
ctan/f/l(a) (z)
ctanh/f/l(a) (z)
nextafter/f/l(a,s)
C99 (z) avec tgmath.h
cacosh(a) acosh
casinh/f/l(a) asin
catanh/f/l(a) atanh
les fonctions de Bessel j0,
j1, jn, y0, y1 et yn ne sont
pas standard en C, y
compris dans les normes
C99 ou C2011
remarques
C99 + tgmath.h
C99 + tgmath.h
C99 + tgmath.h
J0 (a)
J1 (a)
Jn (n, a)
Y0 (a)
Y1 (a)
Yn (n, a)
R a t2
2
e
dt
R0
t2
2
dt
(a)
ln(|(a)|)
a2 + b2
1. En C99, il est cependant possible dimplmenter des fonctions mathmatiques gnriques pour les nombres
rels flottants grce au prprocesseur en incluant le fichier tgmath.h.
f2008
164
D.9
B Les comportements des deux langages pour les entres-sorties sont assez diffrents : en particulier
en criture, lorsque la taille du champ de sortie prcise dans la spcification de format savre
insuffisante pour permettre lcriture, le C prend la libert dtendre cette taille (quitte ne pas
respecter la taille prvue) alors que le fortran refuse de dborder et affiche des caractres * en lieu
et place de la valeur crire.
B
Dautre part, le fortran donne la priorit la liste dentres/sorties sur le nombre de descripteurs
actifs du format, alors que le langage C cherche satisfaire en priorit les descripteurs actifs. En
particulier, si le nombre de descripteurs actifs est infrieur au nombre dentits coder ou dcoder,
le fortran r-explore le format, alors que dans le cas contraire, il ignore les descripteurs actifs
superflus. linverse, en C, si le nombre de descripteurs actifs est infrieur au nombre dlments
de la liste, seuls ceux qui correspondent un descripteur sont cods ou dcods, alors que dans
le cas contraire, les descripteurs actifs superflus provoquent des accs des zones mmoires non
rserves avec des consquences imprvisibles mais souvent plus graves en entre quen sortie.
entier en dcimal
entier en octal
entier en hexadcimal
flottant en virgule fixe
flottant en mantisse et exponentielle
gnral
chane de caractres
fortran
In
I0
On
O0
Zn
Z0
Fn.p
F0.p
En.p
Gn.p
G0
An
C
%nd
%d
%nO
%O
%nX
%X
%n.pf
%f
%n.pe
%n.pg
%g
%n.ps
D.10
D.10.1
D.10.2
langage C
Entiers sur 32 bits
2147483647 = 231 1 2 109
Entiers sur 64 bits
9223372036854775807 = 263 1 9 1018
INT32_MAX
INT64_MAX
langage C
Flottants sur 32 bits
3.402823 10+38
1.175494 1038
1.192093 107
Flottants sur 64 bits
1.7976931348623157 10+308
2.2250738585072014 10308
2.220446049250313 1016
FLT_MAX
FLT_MIN
FLT_EPSILON
DBL_MAX
DBL_MIN
DBL_EPSILON
Annexe E
Compilateurs et options de
compilation
Certains compilateurs fortran sont disponibles sur plusieurs plates-formes comme pgf95 de
Portland ou nagfor (ex-f95) de nag (The Numerical Algorithms Group). Dautres sont plus
spcifiques de certains systmes propritaires, comme xlf sur aix dibm, ou f90, celui de hp
issu de Compaq... lui-mme issu de Digital Equipment Corporation, dont la version pour
linux sur processeur alpha est libre dans le cadre dune licence particulire. Le compilateur ifort
dIntel sous linux (http://www.intel.com/cd/software/products/asmo-na/eng/compilers/
flin/index.htm) est aussi utilisable sans frais pour un usage non commercial.
Enfin, deux compilateurs fortran libres (sur le modle de g77) de la collection de compilateurs
gcc ont t dvelopps :
g95 (http://www.g95.org)
et gfortran (http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gfortran/)
disponibles pour plusieurs plates-formes dont Linux (sur processeurs 32 bits et 64 bits), Windows
et Macintosh OS X.
E.1
Le compilateur fortran des machines ibm fonctionnant sous aix 1 ou sur processeur Powerpc sous linux est xlf 2 (voir Manuels Fortran IBM). Pour compiler du fortran 90 au format libre
(cf. 1.4.2, p. 8), il faut utiliser xlf90 ou xlf -qfree=f90. Pour respecter la convention de nommage
*.f90 des fichiers sources au format libre, on doit spcifier loption -qsuffix=f=f90 :
xlf90 -qsuffix=f=f90 <essai >.f90
ou
xlf -qfree=f90 -qsuffix=f=f90 <essai >.f90
E.1.1
165
166
De plus, au moins dans la phase de mise au point, on peut lui demander de vrifier le nondpassement des bornes des tableaux par loption -qcheck (version longue de loption -C), ainsi
que la compatibilit des arguments passs entre procdures par loption -qextchk.
Enfin, il est prudent de provoquer une interruption de lexcution dans les cas o les calculs en
virgule flottante aboutissent des rsultats non garantis 3 :
ENable : ncessaire pour permettre linterruption la suite dun des problmes suivants
INValid : opration invalide
OVerflow : dpassement de capacit vers le haut (quantit trop grande en valeur absolue pour tre
reprsente sur la machine, car lexposant serait trop grand et positif)
ZEROdivide : division par zro
Cette prcaution est assure en compilant avec loption -qflttrap, suivie des sous-options ncessaires : xlf90 -qflttrap=en:inv:ov:zero
Enfin, loption -qinit=f90ptr permet dimposer aux pointeurs un tat non associ leur
cration, au lieu de ltat indtermin (obtenu par dfaut).
Loption -F fichier.cfg permet de spcifier un fichier de configuration personnel (inspir de
/etc/xlf.cfg qui reprsente la configuration par dfaut) qui rassemble les options choisies.
E.2
E.2.1
167
Les options suivantes sont conseilles pour forcer des vrifications complmentaires, au moins
dans la phase de mise au point des programmes :
-C=array signale les dpassements de bornes des tableaux et des chanes de caractres ;
-C=calls vrifie les rfrences aux procdures ;
-C=dangling signale les pointeurs indfinis ;
-C=do signale les boucles do dont le pas est nul ;
-C=recursion signale les rcursivits invalides ;
-nan initialise les variables de type REAL ou COMPLEX NaN (Not A Number), ce qui provoque un
arrt si elles sont utilises avant dtre dfinies.
Cet ensemble doptions peut tre slectionn globalement avec la syntaxe -C=all, laquelle il
est prudent dajouter -C=undefined 4 pour rechercher les variables non dfinies.
Loption -float-store interdit lutilisation de registres de capacit suprieure 64 bits pour
les calculs flottants : en effet lunit de calcul flottant (Floating Processor Unit) effectue bien souvent
les calculs dans des registres de 80 voire 128 bits permettant une prcision et un domaine tendus
pour reprsenter les rsultats intermdiaires. Cette option ne doit tre active qu titre de test car
elle dgrade les performances des programmes mme si elle contribue leur portabilit !
Enfin loption -gline permet de retracer lorigine dune erreur lexcution en indiquant les
lignes de code 5 o elle sest produite. Comme cette option est consommatrice de temps et de place,
on ne lactivera quen cas derreur lexcution et on relancera le programme ainsi recompil pour
analyser lerreur.
E.3
E.3.1
Pour compiler des procdures rcursives, il est ncessaire de prciser loption -Mrecursive, car
loption par dfaut est -Mnorecursive. Par dfaut, les variables locales ne sont pas sauvegardes
dun appel lautre (option -Mnosave). Le stockage statique des variables locales peut tre vit
avec loption -Mrecursive.
Les options suivantes sont conseilles pour signaler aider crire un code robuste, au moins
dans la phase de mise au point des programmes :
-Mdclchk requiert que toutes les variables soient dclares (loption par dfaut est -Mnodclchk) ;
-Mstandard demande au compilateur de signaler les carts la syntaxe du fortran standard selon
la norme choisie ;
-Minform=inform choisit le niveau maximum dinformation (erreurs, avertissements et informations)
-Mbounds signale les dpassements de bornes des tableaux et des chanes de caractres.
4. Une procdure compile avec loption -C=undefined peut ne pas tre compatible avec une procdure compile
sans cette option. De plus, cette option est incompatible avec les fonctions rsultat allouable.
5. En remontant dans la hirarchie des appels de procdures.
168
De plus, loption -Mallocatable=95 ou -Mallocatable=03 permet de choisir le comportement des affectations de variables allouables : allocation pralable ncessaire en fortran 95 ou
(r-)allocation implicite en fortran 2003 (cf. 7.5.4, p. 93).
Par ailleurs, loption -Mbyteswapio permet dintervertir lordre des octets dans les entressorties sur des fichiers binaires (conversion litte endian vers big-endian et rciproquement) (cf. note 9,
p. 39).
Enfin loption -Ktrap=fp force linterruption en cas de problme doprations en flottant (division par zro, opration invalide, dpassement de capacit) lexcution. On peut aussi activer
loption -Kieee pour respecter la norme IEEE 754 (cf. annexe C, p. 154) lors des calculs en
flottant, au prix ventuel dun moins bon temps de calcul.
E.4
Sous linux, avec des processeurs intel ou compatibles, on peut utiliser le compilateur ifort
(voir Manuels Fortran Intel), disponible gratuitement sous conditions pour un usage non commercial.
Par dfaut, les fichiers sources de suffixes 6 .f90 sont considrs comme crits au format libre
(cf. 1.4.2, p. 8), alors que ceux de suffixes .f, .for et .ftn sont supposs au format fixe (cf. 1.4.1,
p. 7). Les options -free et -fixed permettent de spcifier le type de format indpendamment
de ces conventions. Les options -i8 et -r8 permettent de promouvoir respectivement les variables
entires par dfaut en 64 bits et les variables relles par dfaut en double prcision (64 bits). De plus
loption -fpconstant permet de promouvoir les constantes relles par dfaut en double prcision
si elles sont affectes des variables double prcision. Enfin, loption -nofor-main spcifie lors de
ldition de lien que le programme principal nest pas en fortran (cf. chapitre 12, p. 129).
E.4.1
Le stockage statique des variables locales peut tre vit avec loption -automatic, -nosave ou
-auto. Pour compiler des procdures rcursives, il est ncessaire de prciser loption -recursive
(qui implique -automatic), car loption par dfaut est -norecursive.
Les options suivantes sont conseilles pour signaler des erreurs lexcution, au moins dans la
phase de mise au point des programmes :
-stand f90 ou -stand f95 ou -stand f03 demande au compilateur de signaler tous les carts
la syntaxe du fortran standard selon la norme choisie ;
B
Noter ce propos que malgr le choix de la norme 2003, le compilateur ifort ne met pas
en uvre lallocation automatique par affectation (cf. 7.5.4, p. 93) : il faut ajouter loption
-assume realloc_lhs.
-warn declarations ou -implicitnone signale les identifiants utiliss sans tre dclars (typage
implicite) ;
-warn uncalled signale les fonctions qui ne sont jamais appeles ;
-warn unused signale les variables dclares mais jamais utilises ;
-warn all demande dmettre tous les avertissements que le compilateur peut diagnostiquer (cela
implique notamment -warn declarations, -warn uncalled, -warn unused, ...)
-check bounds ou -CB signale les dpassements de bornes des tableaux et des chanes de caractres ;
-check format dtecte une inconsistance entre une valeur et son format de sortie ;
-check all ou -C permet de spcifier globalement toutes les vrifications du type -check
-diag-error-limit1 permet darrter la compilation la premire erreur.
-traceback ajoute dans le code objet des informations complmentaires permettant, en cas derreur grave, de retrouver la ligne de code, la procdure et le fichier source associs afin de
localiser lorigine de lerreur.
6. Contrairement dautres compilateurs, ifort nadmet ni le suffixe .f95 ni le suffixe .f03 pour des sources au
standard fortran 95 ou 2003.
169
-assume byterecl permet dexprimer les longueurs des enregistrements (argument RECL de OPEN
et INQUIRE) des fichiers non-formats en octets, au lieu des mots longs de 4 octets par dfaut.
Enfin loption -ftrapuv qui initialise les variables alloues sur la pile des valeurs invalides
peut permettre de dtecter des dfauts dinitialisation.
Dautre part, loption -fltconsistency, ou -mieee-fp requiert des calculs en virgule flottante
plus portables et conformes la norme ieee (cf. exemple C.3.1, p. 156), au prix dune perte de
performances, de la mme faon que loption -ffloat-store de gfortran. Elle limite par exemple
certaines optimisations du compilateur affectant lordre des oprations et respecte la prcision des
calculs associ au type des variables.
Par ailleurs, lalignement des types drivs (sans attribut SEQUENCE ou BIND, cf. 9.1.1, p. 103)
par des octets de remplissage est conditionn par les options :
-noalign records pour viter le remplissage ;
-align records pour forcer lalignement sur des frontires de mots ;
-align recnbyte pour aligner sur un nombre n doctets, o n peut valoir 1, 2, 4, 8 ou 16.
Des variables denvironnement permettent de spcifier le contexte dexcution des programmes
compils avec ifort. Parmi celles-ci, on notera celle qui permet de dsigner lordre des octets (cf.
note 9, p. 39) dans la reprsentation des donnes binaires : F_UFMTENDIAN. Elle permet dindiquer
(sous diverses formes) la liste des numros dunits logiques pour lesquels les entres/sorties se
feront avec conversion entre little et big, sachant que le format par dfaut est little sur les
processeurs o ce compilateur fonctionne.
E.5
Compilateur g95
Le compilateur g95 (voir Vaught, 2009) est issu de gcc 7 , la collection de compilateurs du GNU,
capable de compiler les langages C, C++, Objective-C, Fortran, Java, et Ada. Plus prcisment,
il sappuie sur gcc, suit sa syntaxe et admet donc ses options gnrales, mais propose aussi des
options spcifiques pour le langage fortran.
Par dfaut, les fichiers sources de suffixes .f90, .f95, .f03 et leurs variantes majuscules sont
considrs comme crits au format libre (cf. 1.4.2, p. 8), alors que ceux de suffixes .f, .for et
leurs variantes majuscules sont supposs au format fixe (cf. 1.4.1, p. 7). Les options -ffree-form
et -ffixed-form permettent de spcifier le type de format indpendamment de ces conventions.
Dans le cas du format fixe, on peut prciser la longueur maximale des lignes avec les options
-ffixed-line-length-80 ou -ffixed-line-length-132.
Les fichiers sources de suffixe en majuscules sont par dfaut traits par le prprocesseur du C,
alors que ceux dont le suffixe est en minuscules ne le sont pas par dfaut.
Avec loption -fmod=, il est possible de fixer le rpertoire o seront crs les fichiers .mod
de module lors de la compilation. On pourra lassocier avec loption -I qui permet dajouter un
rpertoire au chemin de recherche des fichiers de module.
Loption -M permet laffichage des dpendances des fichiers objets et fichiers de module, en vue
de la rdaction du fichier makefile :
g95 -M <fichier.f90 > affiche les dpendances du fichier <fichier.o >.
Enfin, une liste de variables denvironnement (prfixes par G95_) permet dadapter lenvironnement dexcution des programmes compils par g95. Lavantage de tels rglages par rapport
aux options de compilation est quils peuvent tre modifis une fois lexcutable cr et ajusts a
posteriori lors de lexploitation. On peut connatre les valeurs de ces variables denvironnement en
lanant lexcutable produit par g95 avec loption --g95. Ces variables concernent notamment les
entres/sorties, avec, entre autres (cf. 5.2.1, p. 38) :
G95_STDIN_UNIT de type entier qui permet de choisir le numro de lunit logique prconnecte lentre standard ;
G95_STDOUT_UNIT de type entier qui permet de choisir le numro de lunit logique prconnecte la sortie standard ;
7. En fait, le dveloppement dun compilateur fortran 90 au sein de gcc est en cours sous le projet gfortran
(cf. E.6, p. 171). Mais un des anciens membres de lquipe de gfortran a entrepris un dveloppement en parallle
qui a abouti plus rapidement avec g95. Cependant g95 semble maintenant fig depuis aot 2010.
170
G95_STDERR_UNIT de type entier qui permet de choisir le numro de lunit logique prconnecte la sortie derreur standard ;
G95_COMMA de type boolen qui permet de choisir la virgule comme sparateur dcimal
(cf. 5.3.2, p. 43) ;
G95_ENDIAN de type chane de caractres et de valeurs possibles BIG, LITTLE, SWAP ou NATIVE
(par dfaut), qui permet de choisir lordre des octets (cf. note 9, p. 39) dans la reprsentation
des donnes pour les lectures et critures de fichiers binaires.
E.5.1
Le stockage statique des variables locales peut tre vit avec loption -fno-static.
Il est possible de demander au compilateur dinterdire tous les carts la syntaxe du fortran
standard avec loption -std=f95 8 ou -std=f2003. Cette option exclut lemploi des procdures
intrinsques non standard, telles que la fonction system qui permet de lancer des commandes
du systme dexploitation depuis le fortran. Mais des options 9 sont prvues pour autoriser
toutes ou partie seulement des extensions intrinsques tout en respectant le standard par
ailleurs.
Loption -Wimplicit-none permet de signaler toutes les variables non dclares. Loption
-fimplicit-none interdit lusage de variables non dclares.
Si on souhaite tre inform quune variable a t dclare, mais nest pas utilise 10 , il faut
prciser loption -Wunused.
linverse, loption -Wunset avertit quand on nattribue pas de valeur une variable, ce qui
est suspect si elle est utilise.
Afin de bnficier au mieux de lanalyse du code faite par le compilateur, il est utile de lui demander
la plupart des avertissements disponibles : on utilise cet effet loption -Wall qui regroupe les avertissements plus importants et on peut ajouter -Wextra pour activer notamment -Wmissing-intent
et -Wobsolescent.
Les options suivantes sont conseilles pour signaler des erreurs lexcution, au moins dans la
phase de mise au point des programmes :
-fbounds-check signale les dpassements de bornes des tableaux et des chanes de caractres ;
-ftrapv provoque une erreur lors dun dpassement de capacit dans les oprations daddition, de
soustraction et de multiplication.
-freal=nan initialise les variables scalaires relles et complexes (non explicitement initialises)
not a number, produisant des erreurs de calcul si on les utilise sans leur attribuer dautre
valeur.
-fpointer=null initialise les pointeurs scalaires (non explicitement initialiss) null()
-ftrace=full permet retrouver le numro de ligne dune ventuelle erreur arithmtique, mais
ralentit lexcution.
-ffloat-store interdit lutilisation de registres de capacit suprieure pour les calculs flottants :
en effet lunit de calcul flottant (Floating Processor Unit) effectue bien souvent les calculs
dans des registres de 80 voire 128 bits permettant une prcision et un domaine tendus pour
reprsenter les rsultats intermdiaires. Cette option ne doit tre active qu titre de test
car elle dgrade les performances des programmes mme si elle contribue leur portabilit !
8. On peut cependant dans ce cas autoriser certaines extensions relevant du standard 2003. En particulier lallocation de tableaux dynamiques arguments de procdures (cf. 7.5.3, p. 92) et les tableaux allouables dans les structures
(cf. 9.5, p. 106) en ajoutant loption -ftr15581.
9. Loption -fintrinsic-extensions permet daccder toutes les fonctions intrinsques de g95 alors que
-fintrinsic-extensions= permet de spcifier la liste explicite des fonctions intrinsques non-standard (par exemple
les fonctions GAMMA, ERF, ERFC... et aussi la fonction system) accepter en exigeant par ailleurs le respect dun
standard.
10. Ces avertissements peuvent paratre au premier abord superflus, en particulier dans la phase de mise au point
du code. Mais ils peuvent permettre de dcouvrir des erreurs de codage de faon assez subtile, comme dans cet
exemple, vcu par un tudiant : en signalant que, dans lexpression x**(1/3), la variable x est en fait inutilise, le
compilateur g95 a permis de dtecter une grossire erreur de codage dans le calcul de la racine cubique. La division
1/3 tant ici programme en entier, elle donne un exposant nul, rendant lexpression indpendante de x car x0 = 1.
171
-fone-error peut tre active pour arrter la compilation ds la premire erreur, vitant ainsi
lavalanche de messages concernant les erreurs provoques par exemple par une dclaration
inexacte.
G95_MEM_INIT=NAN cette variable denvironnement permet de choisir dinitialiser la mmoire alloue de faon dynamique, par exemple Not A Number, quitte ralentir lallocation.
En pratique, sur les postes clients linux de lUTES, des alias ou des fonctions du shell g95-mni
et g2003-mni ont t dfinis pour activer simplement les options conseilles.
Pour plus de dtails, consulter le manuel du compilateur, maintenant disponible en ligne
(Vaught, 2006), y compris traduit en franais (http://ftp.g95.org/G95Manual.fr.pdf).
E.6
Compilateur gfortran
E.6.1
Par dfaut, les variables locales sans lattribut SAVE des procdures ne sont pas stockes en
statique mais sur la pile, sauf si elles dpassent une taille spcifie en octets par loption
-fmax-stack-var-size (dfaut 32768). Loption -frecursive empche leur stockage en
mmoire statique.
Loption -fimplicit-none interdit le typage implicite des variables comme le fait linstruction IMPLICIT NONE.
Loption -std=f95, -std=f2003 ou -std=f2008 permet dexiger un code conforme la
norme fortran 95, fortran 2003 ou fortran 2008. Les carts la norme requise gnrent
des erreurs et les instructions obsolescentes sont signales par des avertissements. Cette option exclut lemploi des procdures intrinsques non standard, sauf si on ajoute loption B
-fall-intrinsics 12 qui autorise toutes les procdures intrinsques qui sont des extensions
la norme (comme GAMMA, ERF, ERFC... qui font partie du standard fortran 2008). Par ailleurs,
partir de la version 4.6, gfortran permet lallocation dynamique implicite par affectation
(cf. 7.5.4, p. 93) si le standard demand est 2003 ou 2008, mais il est possible de linhiber
avec loption -fno-realloc-lhs ou de lautoriser en standard 95 avec -frealloc-lhs.
Loption -fmax-errors=n peut tre active pour arrter la compilation ds la ne erreur, vitant ainsi lavalanche de messages concernant les nombreuses erreurs provoques par exemple
par une dclaration inexacte.
Loption -fbacktrace permet dafficher la hirarchie des appels avec les numros de ligne en
cas derreur lexcution.
Les options suivantes initialisent respectivement les entiers -finit-integer=<n >, les rels
et les complexes -finit-real=nan, par exemple Not a Number de signalisation.
11. En fait, cest le compilateur fortran 90 officiel de gcc et il a atteint un degr de dveloppement comparable
g95 (cf. E.5, p. 169). Il est maintenant distribu avec les outils de dveloppement dans la plupart des distributions
linux (http://gcc.gnu.org/wiki/GFortranBinaries). Noter quil est parfois accessible sous le nom f95.
12. Avec g95, il est possible de spcifier la liste des procdures non standard autorises, cf. E.5.1, p. 170.
172
On conseille, pour la compilation, les options -Wall qui requirent des avertissements classiques
et -W pour des avertissements complmentaires. Pour la mise au point, -fbounds-check 13 ou (
partir de la version 4.5) -fcheck=bounds active la vrification des bornes des tableaux lexcution.
Noter que loption -Wconversion, qui signale les conversions implicites induites par les oprateurs (cf. 3.1.3, p. 22), peut savrer trop bavarde pour tre utilise systmatiquement, si on
ne simpose pas de rendre toutes ces conversions explicites pour viter dalourdir les codes. On
peut lajouter ponctuellement pour localiser les conversions implicites dans des codes sensibles aux
erreurs numriques de conversion.
Loption -ffloat-store de gcc a le mme effet (cf. exemple C.3.1, p. 156), quavec g95
(cf. E.5.1).
Si lon dispose dune version optimise de la bibliothque blas (Basic Linear Algebra Subroutines), comme par exemple OpenBlas (cf. http://xianyi.github.com/OpenBLAS/), il est
possible de dlguer les calculs de MATMUL cette bibliothque dans le cas des tableaux de taille
importante, avec loption -fexternal-blas. Le compilateur gnre alors un appel blas si la
taille des matrices est suprieure ou gale 30 par dfaut, seuil qui peut tre modifi via loption
-fblas-matmul-limit=n.
Loption -static impose une dition de liens statique, pour produire un excutable autonome ; en effet, de nombreux environnements fonctionnent aujourdhui par dfaut avec des bibliothques dynamiques partageables. Sil sagit simplement de produire un excutable embarquant
la version statique des objets issus de la bibliothque du fortran, on peut se contenter de loption
-static-libgfortran, qui produit cependant un excutable li dynamiquement, mais ne requiert
plus la bibliothque du fortran au chargement, comme on peut le vrifier avec ldd.
Avec loption -J, suivie du chemin dun rpertoire, il est possible de fixer le rpertoire o seront
crs les fichiers .mod de module lors de la compilation. On pourra lassocier avec loption -I
qui permet dajouter un rpertoire 14 la liste des chemins de recherche des fichiers de module
requis par linstruction USE. Cest une option ncessaire pour utiliser les fichiers de module dune
bibliothque fortran installe en dehors des rpertoires standard.
Il est possible de limiter ladjonction doctets de remplissage destins respecter des contraintes
dalignement dans les types drivs (cf. 9.1.1, p 103) avec loption -fpack-derived.
On notera que les variables denvironnement qui permettent dajuster le comportement de
lexcutable sont ici prfixes par GFORTRAN_ au lieu de G95_. De plus, le choix de lordre des octets
dans les fichiers binaires (cf. note 9, p. 39) peut se faire unit logique par unit logique grce la
variable GFORTRAN_CONVERT_UNIT, comme avec ifort (cf. E.4.1, p. 168).
E.7
E.7.1
compilateur
g95
g95
gfortran
nagfor (nag)
pgf95 (portland)
ifort (intel)
f90 (hp)
xlf (ibm)
option
-i8/-d8
par dfaut
-fdefault-integer-8
-double
-i8
-integer_size 64 ou -i8
-integer_size 64
-qintsize=8
173
E.7.2
E.8
compilateur
g95
gfortran
nagfor (nag)
pgf95 (portland)
ifort (intel)
f90 (hp)
xlf (ibm)
option
-r8/-d8
-fdefault-real-8
-r8/-double
-r8
-real_size 64 ou -r8
-real_size 64
-qrealsize=8
Ce tableau rcapitule les principales options dont les noms diffrent selon les compilateurs. Il ne
sagit que dun aide-mmoire grossirement simplifi pouvant aider migrer des applications dun
compilateur un autre : les correspondances sont parfois assez approximatives et on se rfrera
aux manuels respectifs pour sassurer dans le dtail de leffet de chaque option.
gfortran
-ffloat-store
-fmax-errors=1
-std=f95
-std=f2003
-realloc-lhs
-fckeck=bounds
-fimplicit-none
-static
g95
-ffloat-store
-fone-error
-std=f95
-std=f2003
-fbound-checks
-fimplicit-none
ifort
-fltconsistency
-diag-error-limit1
-std f95
-std f03
-assume realloc_lhs
-check bounds
-implicitnone
-nofor-main
-Bstatic
nagfor
-f95
-f2003
-C=array
-u
-Bstatic
pgfortran
-Kieee
-Mallocatable=03
-Mbounds
-Mdclchk
-Mnomain
-Bstatic
Bibliographie
Adams, Jeanne, Walter Brainerd, Richard Hendrickson, Richard Maine, Jeanne
Martin et Brain Smith, The Fortran 2003 Handbook : The Complete Syntax, Features and
Procedures, 712 pages (Springer, 2009), ISBN 978-1846283789.
Akin, Ed, Object-oriented programming via fortran 90/95, 360 pages (Cambridge University Press,
2003), ISBN 0-521-52408-3.
Cet ouvrage prsente les aspects programmation oriente objet du fortran 90/95 au travers de nombreux
exemples comments. Il comporte des tableaux synthtiques mettant en parallle les syntaxes du fortran,
du C++ et de matlab ainsi quune annexe rsumant succintement le langage fortran 90.
Chapman, Stephen J., Fortran 95/2003 for Scientists and Engineers, 974 pages (Mc Graw-Hill,
2007), 3e dition, ISBN 978-0-07-319157-7.
La troisime dition de ce livre est un des rares ouvrages qui prsente dlibrment le fortran du standard
2003, tout en distinguant explicitement par la prsentation les lments non disponibles dans le standard
fortran 95. Toutefois, linteroprabilit avec le C nest pas aborde. Contrairement Metcalf et al.
(2004), il peut tre abord par des dbutants car lapproche est progressive et assortie de nombreux
conseils, exemples et exercices.
Chivers, Ian et Jane Sleightholme, Introduction to Programming with Fortran With Coverage
of Fortran 90, 95, 2003, 2008 and 77, 619 pages (Springer, 2012), 2e dition, ISBN 978-0-85729232-2.
Clerman, Norman S. et Walter Spector, Modern fortran : Style and Usage, 360 pages (Cambridge University Press, 2011), ISBN 978-0521514538.
Comme son titre lindique, cet ouvrage prsente des rgles de bon usage du fortran 2003 aussi bien
dans lcriture du code (nommage, mise en page, ...) que dans sa documentation. Il sadresse donc un
public possdant dj une certaine exprience du langage.
1.3.2, 1.4.2
Corde, Patrick et Herv Delouis, Langage Fortran (F2003), Institut du Dveloppement et
des Ressources en Informatique Scientifique (IDRIS) CNRS, 2012, URL : http://www.idris.
fr/data/cours/lang/fortran/choix_doc.html.
Un des rares documents en franais prsentant les nouveauts du fortran 2003 par rapport au fortran 95,
en une srie de 246 transparents. Linter-oprabilit entre le fortran et le langage C et surtout les aspects
objet du fortran 2003 y sont tudis en dtail.
E.8
174
BIBLIOGRAPHIE
175
Delannoy, Claude, Programmer en Fortran 90 Guide complet, 413 pages (Eyrolles, 1997), ISBN
2-212-08982-1.
crit par un auteur bien connu pour le succs de ses nombreux ouvrages sur les langages de programmation, ce livre prsente le fortran 90 de faon progressive et concise. Il est accompagn dexemples et
dexercices corrigs, et peut constituer un trs bon manuel dapprentissage. Depuis 2015, on lui prfrera
la deuxime dition (Delannoy (2015)) qui couvre une partie des standards 2003 et 2008.
E.8
Delannoy, Claude, Programmer en Fortran : Fortran 90 et ses volutions Fortran 95, 2003
et 2008, 480 pages (Eyrolles, 2015), deuxime dition, ISBN 978-2-212-14020-0.
Deuxime dition de louvrage de 1997 (Delannoy (1997)), qui sarrtait fortran 95, cet ouvrage
aborde maintenant les standards 2003 et 2008 dans son annexe I , ainsi que la programmation oriente
objet avec fortran 2003 dans son annexe H.
E.8
Dubesset, Claude et Jean Vignes, Les spcificits du Fortran 90, 367 pages (ditions Technip,
1993), ISBN 2-7108-0652-5.
Cet ouvrage en franais sadresse avant tout ceux qui connaissent dj le fortran 77. Il prsente avec
beaucoup de prcision et de clart les apports de la norme fortran 90. Il est dot de prcieuses annexes
et notamment dun lexique et dun glossaire.
E.8
Lignelet, Patrice, Manuel complet du langage Fortran 90 et Fortran 95 : calcul intensif et gnie
logiciel, 314 pages (Masson, 1996), ISBN 2-225-85229-4.
Au del du langage fortran, cet ouvrage en franais dun auteur de nombreux ouvrages dans ce domaine,
aborde les questions de calcul numrique, de vectorisation et de gnricit.
Manuel Fortran DEC, Digital Fortran, Langage Reference Manual, Digital Equipment Corporation,
Maynard, Massachusetts, USA, 1997.
Le manuel papier du compilateur f90 de Digital Equipment Corporation, repris successivement par
Compaq, puis par hp. Trs bien prsent, il distingue clairement les extensions propritaires de la norme
du fortran 90.
Manuels Fortran IBM, XL Fortran for AIX, Langage Reference and Users Guide, IBM, 8200
Warden Avenue, Markham, Ontario, Canada, 2005, URL : http://publib.boulder.ibm.com/
infocenter/comphelp/. E.1
Manuels Fortran Intel, Intel Fortran Compiler Documentation, Intel Corporation, 2010,
URL : http://software.intel.com/sites/products/documentation/hpc/compilerpro/
en-us/fortran/lin/compiler_f/index.htm.
Site dintel qui prsente un manuel en ligne du compilateur ifort.
E.4
Manuels Fortran NAG, NAGWare Fortran 95 Compiler, Numerical Algorithms Group, The Numerical Algorithms Group Ltd, Wilkinson House, Jordan Hill Road, Oxford, OX2 8DR, UK, 2011,
URL : http://www.nag.co.uk/nagware/np.asp.
Site du Numerical Algorithms Group permettant daccder aux pages de manuel en ligne du compilateur nagfor (ex f95) et des modules associs.
176
BIBLIOGRAPHIE
E.2
Manuels Fortran PGI, PGI Fortran Compiler, The Portland Group, The Portland Group, STMicroelectronics, Two Centerpointe Drive, Suite 320, Lake Oswego, OR 97035, 2011, URL : http:
//www.pgroup.com/resources/docs.htm.
Site de The Portland Group, permettant daccder au manuel de rfrence du compilateur fortran
PGI au format pdf.
E.3
Markus, Arjen, Modern fortran in Practice, 253 pages (Cambridge University Press, 2012), ISBN
978-1-107-60347-9.
Marshall, A.C., J.S. Morgan et J. L. Schofelder, Fortran 90 Course Notes, The University
of Liverpool, 1997, URL : http://www.liv.ac.uk/HPC/F90page.html.
Le site de lUniversit de Liverpool propose une srie de cours de diffrents niveaux sur le fortran 90 :
les documents associs (transparents, notes, exercices, codes ...) sont accessibles via ftp lurl ftp:
//ftp.liv.ac.uk/pub/F90Course/.
Metcalf, Michael, John Reid et Malcolm Cohen, Fortran 95/2003 explained, 434 pages
(Oxford University Press, 2004), 3e dition, ISBN 0-19-852693-8.
Rdige par des promoteurs des nouveaux standards du fortran, la troisime dition de ce livre est un des
rares ouvrages qui aborde les apports du fortran 2003. Il constitue une rfrence majeure dans ce domaine.
Les apports de la norme fortran 2003 y sont prsents dans les 7 derniers chapitres, permettant ainsi
de les sparer de la norme fortran 95. Il aborde notamment linteroprabilit avec le C. Cette rfrence
nest cependant pas conseille pour dbuter.
E.8
Metcalf, Michael, John Reid et Malcolm Cohen, Modern Fortran explained, Numerical
Mathematics and Scientific Computation, 488 pages (Oxford University Press, 2011), 4e dition,
ISBN 978-019-960142-4.
La quatrime dition de ce classique est le premier ouvrage aborder la norme 2008 du fortran. Succdant
ldition Metcalf et al. (2004) sur le fortran 2003, cette version rvise comporte notamment un
chapitre sur les co-tableaux (coarrays) et un sur les nouveauts du fortran 2008. Cette rfrence nest
cependant pas conseille pour dbuter et rares sont encore les compilateurs honorer la norme 2008.
1.1, 4.5
Nyhoff, Larry R. et Sandfird C. Leestma, Fortran 90 for Engineers and Scientists, 1070
pages (Prentice-Hall, 1997), ISBN 0-13-6571209-2.
Un ouvrage volumineux mais trs bien illustr avec des applications concrtes dans le domaine du calcul
scientifique. Sa prsentation trs progressive permet de lutiliser pour dcouvrir le fortran 90 y compris
comme premier langage de programmation.
Olagnon, Michel, Traitement des donnes numriques avec Fortran 90, 244 pages (Masson,
1996), ISBN 2-225-85259-6.
Cet ouvrage ne prsente pas le langage fortran en tant que tel, mais des mthodes de traitement des
donnes (en particulier statistiques) mises en uvre en fortran 90. Cette approche pragmatique sappuyant sur de nombreux exemples permet daborder rapidement les applications tout en respectant les
rgles de bon usage du langage.
BIBLIOGRAPHIE
177
Site gfortran, de la collection de compilateurs gcc, Documentation de gfortran, Free Software Foundation, 2011, URL : http://gcc.gnu.org/onlinedocs/gfortran/. A, E.6
Stallings, W., Organisation et architecture de lordinateur, 829 pages (Pearson Education, 2003),
sixime dition, ISBN 9782744070075. 2.2, C.4.2
Vaught, Andy, Manuel de g95, 2006, URL : http://ftp.g95.org/G95Manual.pdf. E.5.1
Vaught, Andy, Documentation de g95, 2009, URL : http://www.g95.org/docs.html.
Le site du compilateur libre g95 do il est possible de tlcharger les binaires pour les diffrentes
architectures. Ce site comporte des liens vers la documentation. Il liste les bibliothques qui ont t
compiles avec succs avec g95.
E.5
Vickery, Christopher, IEEE-754 calculators, 2009, URL : http://babbage.cs.qc.edu/
IEEE-754/. C.4.2
wikipedia, The IEEE-754-2008 standard, 2010, URL : http://en.wikipedia.org/wiki/IEEE_
754. C.4.2
178
BIBLIOGRAPHIE
Index
Symboles
! commentaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 8, 9
dlimiteur de chane . . . . . . . . . . . . . . . . . 17, 94
(/ constructeur de tableau . . . . . . . . . . . . . . . . 81
*
format libre dentre sortie . . . . . . . . 35, 47
oprateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
rptition dentre . . . . . . . . . . . . . . . . . . . . 36
unit logique standard . . . . . . . . . . . . . . . . 38
** lvation la puissance . . . . . . . . . . . . 21, 163
, sparateur
dcimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
de donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
. sparateur dcimal . . . . . . . . . . . . . . . . . . . . . . 49
.AND. ET logique . . . . . . . . . . . . . . . . . . . . . . . . . 24
.EQV. quivalence logique . . . . . . . . . . . . . . . . . 24
.NEQV. OU exclusif . . . . . . . . . . . . . . . . . . . . . . . . 24
.NOT. ngation logique . . . . . . . . . . . . . . . . . . . . 24
.OR. OU logique . . . . . . . . . . . . . . . . . . . . . . . . . . 24
/
descripteur de contrle . . . . . . . . . . . . . . . . 49
oprateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
/) constructeur de tableau . . . . . . . . . . . . . . . . 81
// oprateur de concatnation . . . . . . . . . 25, 95
/= diffrent de . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
:
bornes dun tableau . . . . . . . . . . . . . . . . . . . 79
bornes dune sous-chane . . . . . . . . . . . . . . 96
descripteur de format . . . . . . . . . . . . . . 49, 50
section de tableau . . . . . . . . . . . . . . . . . . . . . 82
sparateur entre nom de la structure et structure de contrle . . . . . . . . . . . . . . . . . . . . .
26-31
:: dans les dclarations . . . . . . . . . . . . . . . . . . . . 16
; sparateur
dinstructions . . . . . . . . . . . . . . . . . . . . . . . . . . 8
de donnes . . . . . . . . . . . . . . . . . . . . . . . . 36, 50
< infrieur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
<= infrieur ou gal . . . . . . . . . . . . . . . . . . . . . . 23
== gal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
=>
association de pointeur . . . . . . . . . . . . . . . 119
renommage . . . . . . . . . . . . . . . . . . . . . voir USE
> suprieur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
>= suprieur ou gal . . . . . . . . . . . . . . . . . . . . . 23
[
%
&
"
]
_
constructeur de tableau . . . . . . . . . . . . . . . 6, 81
slecteur de champ . . . . . . . . . . . . . . . . . . . . . 104
continuation dinstruction . . . . . . . . . . . . . 8, 94
dlimiteur de chane . . . . . . . . . . . . . . . . . 17, 94
constructeur de tableau . . . . . . . . . . . . . . . 6, 81
variante de type
caractre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
numrique . . . . . . . . . . . . . . . . . . . . . . . . . 19, 20
A
ABS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138, 163
ABSTRACT INTERFACE . . . . . . . . . . . . . . . . . . . 74-76
accs
direct . . . . . . . . . . . . . . . . . . . . . . 40, 42, 44, 54
squentiel . . . . . . . . . . . . . . . . . . . . . . 40, 42, 44
stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40, 45
ACCESS, mot-clef de OPEN . . . . . . . . . . . . . . . . . . 42
ACHAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98, 149
ACOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138, 163
ACOSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
ACTION, mot-clef de OPEN . . . . . . . . . . . . . . . . . . 42
ADJUSTL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96, 149
ADJUSTR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97, 149
ADVANCE=, mot-clef de READ ou WRITE . 44, 45,
47, 50, 51
affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22, 114
AIMAG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140, 163
AINT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
alatoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
-align recnbyte, option de ifort . . . . . . . 169
-align records, option de ifort . . . . . . . . 169
ALL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88, 143
ALLOCATABLE . . . . . . . . . . . . . 16, 91, 92, 106, 130
ALLOCATE . . . . . . . . . . . 91, 92, 120, 122, 124, 126
ALLOCATED . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91, 143
allocation dynamique 16, 89, 91-93, 106, 122,
126, 130
An, format chane . . . . . . . . . . . . . . . . . . . . . . . . . . 48
ANINT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
ANY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88, 143
'APPEND', argument de POSITION dans OPEN . .
42, 46
ar, gestion des bibliothques statiques . . . . . . 4
argument
chane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
179
180
INDEX
181
INDEX
codage
des caractres . . . . . . . . . . . . . . . . . 43, 46, 95
des entiers . . . . . . . . . . . . . . . . . . . . . . . . 10-12
des flottants . . . . . . . . . . . . . . . . . . . . . . . 12-13
norme IEEE . . . . . . . . . . . . . . . . . 154-159
comma . . . . . . . . . . . . . . . . . . . . . . . . . . voir DECIMAL
COMMAND_ARGUMENT_COUNT . . . . . . . . . . . 146, 147
commande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
commentaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7, 8
COMMON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
comparaison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
compilateur
g95 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165, 169
gfortran . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
ifort dintel . . . . . . . . . . . . . . 51, 165, 168
nagfor (ex-f95) de nag . . . . . . . . 165, 166
pgf95 de portland . . . . . . . . 51, 165, 167
xlf sur ibm . . . . . . . . . . . . . . . . . . . . . 51, 165
compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
de module . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
options de
avec g95 . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
avec gfortran . . . . . . . . . . . . . . . . . . . . . 171
avec ifort dintel . . . . . . . . . . . . . . . . 168
avec nagfor . . . . . . . . . . . . . . . . . . . . . . . 167
avec pgf95 de Portland . . . . . . . . . 167
avec xlf . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
spare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5, 66
COMPILER_OPTIONS() . . . . . . . . . . . . . . . . . . . . . 145
COMPILER_VERSION() . . . . . . . . . . . . . . . . . . . . . 145
COMPLEX (type) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
complexe . . . . . voir COMPLEX, voir aussi CMPLX
composante . . . . . . . . . . . . . . . . . . . . 102, 106, 130
concatnation . . . . . . . . . . . . . . . . . . . . . . . . . . 25, 95
conformants . . . . . . . . . . . . . . . . . . . . voir tableaux
CONJG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138, 163
constante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
constante symbolique . . . . . . . . . . . . . . . . . . . . . . 18
constructeur voir tableau, voir aussi structure
CONTAINS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62, 103
continuation dinstruction . . . . . . . . . . . . . . . 8, 94
CONTINUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
conversion
de type . . . . . . . . . . . . . . . . . . . . . . 20, 114, 140
implicite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
-convert=, option de nagfor . . . . . . . . . . . . . 166
copie
profonde . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
superficielle . . . . . . . . . . . . . . . . . . . . . . . . . . 106
COS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138, 163
COSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138, 163
COUNT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88, 143
CPU_TIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
CSHIFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87, 143
CYCLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30, 162
D
-d8, option de g95 . . . . . . . . . . . . . . . . . . . . . . . 173
DATE_AND_TIME . . . . . . . . . . . . . . . . . . . . . . . . . . 148
dc (decimal comma) . . . . . . . . . . . . . . . . . . . 36, 49
ddd, interface graphique du dboggueur gdb 5
DEALLOCATE . . . . . . . . . . . . . . . . . . . . . . . . . . 91, 120
dbogueur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
debugger . . . . . . . . . . . . . . . . . . . . . . voir dbogueur
dcalage des lments dun tableau . . . . . . . voir
CSHIfT et EOSHIFT
DECIMAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
DECIMAL, mot-clef de OPEN . . . . . . . . . . . . . . . . 43
dclaration . . . 16-17, 17, 19, 58, 62-65, 68, 69
darguments . . . . . . . . . . . . . . . . . . . . . . . 58, 69
dinterface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
dune fonction . . . . . . . . . . . . . . . . . . . . . . . . 61
de chane de caractres . . . . . . . . . . . . 94, 97
de cible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
de fonction . . . . . . . . . . . . . . . . . . . . . . . . 71, 73
de pointeur . . . . . . . . . . . . . . . . . . . . . 118, 119
de tableau . . . . . . . . . . . . . . 79, 80, 82, 89, 90
allouable . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
de type driv . . . . . . . . . . . . . . . . . . . 103, 104
deep copy . . . . . . . . . . . . . . . . . voir copie profonde
DEFAULT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
deferred-shape array voir tableau profil diffr
dfinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
dun type driv . . . . . . . . . . . . 102, 106, 153
'DELETE', argument de STATUS dans CLOSE 44
DELIM=, mot-clef de OPEN . . . . . . . . . . . . . . . . . . 43
dnormalis . . . . . . . . . . . . . . . . . . . . . . 13, 14, 156
dpassement
de bornes . . . . . . . . . . . . . . . . . . 166, 167, 170
de capacit . 15, 19, 22, 139, 155, 166, 170
descripteur
actif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
de contrle . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
-diag-error-limit, option de ifort . . 3, 168
DIGITS . . . . . . . . . . . . . . . . . . . . . . 14, 15, 142, 155
DIM fonction intrinsque . . . . . . . . . . . . . . . . . . 138
DIM= . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85, 86-88
DIMENSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16, 79
dimension . . . . . . . . . . . . . . . . . . . . . . . voir tableau
'DIRECT', argument de ACCESS dans OPEN . 42
DO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29, 162
DO WHILE . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29, 162
domaine . . . . . . 12, 143, 154, 155, 159, 167, 170
DOT_PRODUCT . . . . . . . . . . . . . . . . . . . . . . . . . 86, 143
DOUBLE PRECISION . . . . . . . . . . . . . . . . . . . . . . . . 10
dp (decimal point) . . . . . . . . . . . . . . . . . . . . . . . . . 49
duplication dlments de tableaux . . . . . . . voir
SPREAD
E
dition de liens . . . . . . . . . . . . . . . . . . . . . . . 2, 4, 65
effet de bord . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
182
INDEX
F
f95 de nag . . . . . . . . . . . . . . . . . voir compilateur
-fall-intrinsics, option de gfortran . . 171
-fbacktrace, option de gfortran . . . . . . . . 171
-fblas-matmul-limit=
option de gfortran . . . . . . . . . . . . . . . . . . 172
-fbounds-check
option de g95 . . . . . . . . . . . . . . . . . . . . . . . . 170
option de gfortran . . . . . . . . . . . . . . . . . . 172
-fcheck=bounds, option de gfortran . . . . 172
-fdefault-integer-8, option de gfortran . .
172
-fdefault-real-8, option de gfortran . . 173
-fexternal-blas
option de gfortran . . . . . . . . . . . . . . 86, 172
-ffloat-store
option de g95 . . . . . . . . . . . . . . . . . . . . 22, 170
option de gfortran . . . . . . . . . 22, 169, 172
fichier
de module . . . . . . . . . . . . . . . . . . . . . . . . . . 5, 65
excutable . . . . . . . . . . . . . . . . . . . . . . . 2, 5, 65
externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
format . . . . . . . . . . . . . . . . . . . . . . . . . . . 38, 39
interne . . . . . . . . . . . . . . . . . . . . . . . . 38, 51, 99
non-format . . . . . . . . . . . . . . . . . . . . . . . 38, 39
objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2, 5, 65
source . . . . . . . . . 2, 3, 5-7, 65, 133, 165-169
FILE=, mot-clef de OPEN . . . . . . . . . . . . . . . . . . . 42
FILE_STORAGE_UNIT . . . . . . . . . . . . . . . . . . . . . . . 41
-fimplicit-none
option de g95 . . . . . . . . . . . . . . . . . . . . . . . . 170
option de gfortran . . . . . . . . . . . . . . . . . . 171
-finit-integer=, option de gfortran . . . 171
-finit-real=, option de gfortran . . . . . . . 171
-fintrinsic-extensions, option de g95 . 170
-float-store, option de nagfor . . . . . 22, 167
FLOOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20, 140, 163
-fltconsistency, option de ifort . . . . . . . 169
-fmax-errors=n, option de gfortran . . 3, 171
-fmax-stack-var-size=, option de gfortran
171
-fmode, option de g95 . . . . . . . . . . . . . . . . . . . . 169
FMT=
mot-clef de OPEN . . . . . . . . . . . . . . . . . . . . . . 44
mot-clef de READ . . . . . . . . . . . . . . . . . . . . . . 44
mot-clef de WRITE . . . . . . . . . . . . . . . . . 45, 54
Fn.p, format virgule fixe . . . . . . . . . . . . . . . . . 48
-fno-realloc-lhs, option de gfortran . . 93,
171
fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60, 61
-fone-error, option de g95 . . . . . . . . . . . 3, 171
FORALL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78, 88
FORM=, mot-clef de OPEN . . . . . . . . . . . . . . . . . . . 42
FORMAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
format
binaire . . . . . . . . . . . . . . . . . . . . . . . . voir Bn.p
183
INDEX
chane . . . . . . . . . . . . . . . . . . . . . . . . . . . voir An
dcimal . . . . . . . . . . . . . . . . . . . . . . . . voir In.p
descripteur de . . . . . . . . . . . . . . . . . . . . . . . . . 48
fixe du code source . . . . 1, 7, 7-8, 166-169
hexadcimal . . . . . . . . . . . . . . . . . . . voir Zn.p
libre dentre sortie . . . . . 35, 37, 47, 81, 99
libre du code source . . . . . . 7, 8-9, 165-169
octal . . . . . . . . . . . . . . . . . . . . . . . . . . voir On.p
variable . . . . . . . . . . . . . . . . . . . . . . . . . . . 51, 99
'FORMATTED', argument de FORM dans OPEN 42
FORT_CONVERTn , compilateur nagfor . . . . . 166
-fpack-derived, option de gfortran 103, 172
-fpointer, option de g95 . . . . . . . . . . . 120, 170
FRACTION . . . . . . . . . . . . . . . . . . . . . . . . 15, 142, 154
-freal, option de g95 . . . . . . . . . . . . . . . . . . . . 170
-frealloc-lhs, option de gfortran . . 93, 171
-frecursive, option de gfortran . . . . . . . . 171
FSOURCE=, mot-clef de SPREAD . . . . . . . . . . . . . 87
-ftr15581, option de g95 . . . 92, 106, 122, 170
-ftrace=, option de g95 . . . . . . . . . . . . . . . . . 170
-ftrapv, option de g95 . . . . . . . . . . . . . . . 15, 170
fuite de mmoire . . . . . . . . . . . . . . . . . . . . . . . . . 120
FUNCTION . . . . . . . . . . . . 60, 61, 76, 100, 122, 153
fusion de tableaux . . . . . . . . . . . . . . . . voir MERGE
G
g95 . . . . . . . . . . . . . . . . . . . . . . . . . voir compilateur
G95_COMMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50, 170
G95_ENDIAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
G95_MEM_INIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
G95_STDERR_UNIT . . . . . . . . . . . . . . . . . . . . . . . . 170
G95_STDIN_UNIT . . . . . . . . . . . . . . . . . . . . . . . . . 169
G95_STDOUT_UNIT . . . . . . . . . . . . . . . . . . . . . . . . 169
GAMMA, (x) . . . . . . . . . . . . . . . . . . . . . 138, 170, 171
gdb, dboggueur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
gnrique . voir procdure gnrique, interface
gnrique
GET_COMMAND . . . . . . . . . . . . . . . . . . . . . . . . 146, 147
GET_COMMAND_VARIABLE . . . . . . . . . . . . . 146, 147
GET_ENVIRONMENT_VARIABLE . . . . . . . . . 146, 147
gfortran . . . . . . . . . . . . . . . . . . . voir compilateur
GFORTRAN_CONVERT_UNIT, gfortran . . . . . . 172
Gn.p, format gnral . . . . . . . . . . . . . . . . . . . . . . . 48
GO TO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32, 162
H
hritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
hexadcimal
constante entire en . . . . . . . . . . . voir Zn
format . . . . . . . . . . . . . . . . . . . . . . . . . voir Zn.p
HUGE . . . 12, 14, 15, 18, 142, 155, 157-159, 164
HYPOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
I
-I, option de gfortran . . . . . . . . . . . . . . . . . . . 172
-i8, option de g95 . . . . . . . . . . . . . . . . . . . . . . . 172
184
INDEX
J
-J, option de gfortran . . . . . . . . . . . . . . . . . . . 172
J0 (x), J1 (x), Jn (x) . . . . voir BESSEL_J0/J1/JN
justification
droite . . . . . . . . . . . . . . . . . . . . voir ADJUSTR
gauche . . . . . . . . . . . . . . . . . . . voir ADJUSTL
K
'KEEP', argument de STATUS dans CLOSE . . 44
KIND 10, 13, 18, 18, 20, 129, 130, 142, 154, 166
L
LBOUND . . . . . . . . . . . . . . . . . . . . . . . . . . . 18, 85, 143
ld diteur de liens . . . . . . . . . . . . . . . . . . . . . . . 2, 4
ldd affichage des bibliothques dynamiques . 4
LEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
fonction . . . . . . . . . . . . . . . . . . . . . 97, 100, 149
paramtre de type . . . . . . . . . . . . . . . . 17, 94
LEN_TRIM . . . . . . . . . . . . . . . . . . . . . . . . 97, 100, 149
LGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98, 149
LGT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98, 149
library . . . . . . . . . . . . . . . . . . . . . . . voir bibliothque
ligne
dentre-sortie . . . 35, 36, 38, 40, 47, 49, 98
dinstruction . . . . . . . . . . . . . . . . . . . . . . 7-9, 94
de commentaire . . . . . . . . . . . . . . . . . . . . . . . . 7
link . . . . . . . . . . . . . . . . . . . . . . voir dition de liens
liste chane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
liste dentre-sortie . . . . . . . . . . . . . . . . . . . . . . . . 40
little endian . . . . . . . 12, 39, 166, 168-170, 172
LLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98, 149
LLT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98, 149
Ln, format boolen . . . . . . . . . . . . . . . . . . . . . . . . 48
LOG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139, 163
LOG10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139, 163
LOG_GAMMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
LOGICAL
fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10, 160
longueur dune chane . . . . . . . . . . . . . . 94, 96-100
N
nagfor de nag . . . . . . . . . . . . . . voir compilateur
NAME=, mot-clef de BIND . . . . . . . . . . . . . . . . . . 130
NaN, Not a Number . . . . . . . . . . . . . . . . . . . . 22, 155
NCOPIES=, mot-clef de SPREAD . . . . . . . . . . . . . 87
NEAREST . . . . . . . . . . . . . . . . 15, 142, 156-158, 163
'NEW', argument de STATUS dans OPEN . . . . . 42
NEW_LINE . . . . . . . . . . . . . . . . . . . . . . . . . 40, 98, 149
NEWUNIT=, mot-clef de OPEN . . . . . . . . . . . . 42, 45
NINT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20, 140, 163
-noalign records, option de ifort . 103, 169
NOPASS, attribut de PROCEDURE . . . . . . . . . . . 107
normalis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 155
NOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144, 161
NULL . . . . . . . . . . . . . . . . . . . . . . . . . . . 120, 145, 170
NULLIFY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
185
INDEX
P
PACK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86, 143
PAD=, mot-clef de RESHAPE . . . . . . . . . . . . . . . . . 86
PARAMETER . . . . . . . . . . . . . . . . . 16, 18, 89, 90, 94
partie entire . . . . voir CEILING, FLOOR, INT,
NINT
partie imaginaire . . . . . . . . . . . . . . . . . . voir AIMAG
partie relle . . . . . . . . . . . . . . . . . . . . . . . . voir REAL
PASS, attribut de PROCEDURE . . . . . . . . . . . . . 107
pgf95 . . . . . . . . . . . . . . . . . . . . . . . voir compilateur
point . . . . . . . . . . . . . . . . . . . . . . . . . . voir DECIMAL
POINTER . . . . . . . . . . . . . . . . . . . . . 16, 78, 118-128
pointeur . . . . . . . . . . . . . . 118-128, 130, 145, 162
porte . . . . . . . . . . . . . . . . . . . . . . . . . . 16, 31, 58, 65
POS=, mot-clef de INQUIRE, READ, WRITE 45, 46
POSITION=, mot-clef de OPEN . . . . . . . . . . . 42, 46
PRECISION . . . . . . . . . . . . . . . . . . . . . . . . 15, 15, 143
prcision numrique 12-15, 19, 21, 154-159, 168
prdcesseur . . . . . . . . . . . . . . . . . . . . . . . . . . 15, 142
PRESENT, fonction dinterrogation . . . . . 69, 144
PRINT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35, 45
priorit des oprateurs . . . . . . . . . . . . . . . . . . . . . 21
PRIVATE . . . . . . . . . . . . . . . . 16, 68, 103, 117, 130
PROCEDURE . . . . . . . . . . . . . . . . . . . . . . . . 74, 76, 112
procdure
attache un type . . . . . . . . . . . 1, 107-110
lmentaire . . . . . . . 18, 78, 96-98, 100, 138
externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
gnrique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
interface de . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
interne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
intrinsque . . . . . . . . . . . . . . 16, 18, 138, 170
pointeur de . . . . . . . . . . . . . . . . . . . . . . . . . . 126
pure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
rcursive . . . . . . . . . . . . . . . . . . . . . . . . . 76, 126
spcifique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
standard . . . . . . . . . . . . . . . . . . . . . . . . 138, 170
PRODUCT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86, 144
produit matriciel . . . . . . . . . . . . . . . . . . . . . . . . . . 86
produit scalaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
profil . . . . . . . . . . . . . . . . . . . . . . . . . . . . voir tableau
diffr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
PROGRAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3, 153
PROTECTED . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16, 68
Q
quiet NaN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
R
-r8, option de g95 . . . . . . . . . . . . . . . . . . . . . . . 173
RADIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 143
RANDOM_NUMBER . . . . . . . . . . . . . . . . . . . . . . . . . . 140
RANDOM_SEED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
rang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . voir tableau
RANGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11, 14, 143
range . . . . . . . . . . . . . . . . . . . . . . . . . . . voir domaine
READ
argument de ACTION dans OPEN . . . . . . . 42
instruction . . . . . . . . . . . . . . . . . . . . 35, 44-45
READWRITE
argument de ACTION dans OPEN . . . . . . . 42
REAL
fonction . . . . . . . . . . . . . . . . . . . . . 20, 140, 163
type . . . . . . . . . . . . . . . . . . . . . . . . . . 10, 19, 160
REAL32, aussi REAL64 et REAL128 . . . . . . . . . . 19
REAL_KINDS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
realloc_lhs . . . . . voir -assume realloc_lhs
REC=, mot-clef de READ ou WRITE . . . . . . . 44, 45
recherche
de caractres . . . . . . . . . . voir SCAN, VERIFY
de motif . . . . . . . . . . . . . . . . . . . . . . voir INDEX
RECL=, mot-clef OPEN . . . . . . . . . . . . . . . . . . . . . . 41
RECL=, mot-clef de OPEN . . . . . . . . . . . . . . . . . . . 43
record . . . . . . . . . . . . . . . . . . . . voir enregistrement
record marker . . . . . voir balise denregistrement
RECURSIVE . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76, 78
relle (partie -) . . . . . . . . . . . . . . . . . . . . . voir REAL
registre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167, 170
REPEAT . . . . . . . . . . . . . . . . . . . . . . . . . . . 18, 98, 149
'REPLACE', argument de STATUS dans OPEN 42
RESHAPE . . . . . . . . . . . . . . . . . . . 18, 80, 81, 86, 144
reste . . . . . . . . . . . . . . . . . . . voir MODULO, voir MOD
RESULT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
RETURN . . . . . . . . . . . . . . . . . . . . . . . . . . . 33, 34, 162
'REWIND', argument de POSITION dans OPEN . .
42
REWIND, instruction de positionnement en dbut
de fichier . . . . . . . . . . . . . . . . . . . . . . . . . 46
RRSPACING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
run-time error . . . . . . . . . voir erreur dexcution
S
S, format signe plus selon processeur . . . . . . . 49
SAVE . . . . . . . . . . . . . . . . . . . . . . . 16, 17, 58, 76, 78
SCALE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
SCAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97, 149
scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . voir porte
'SCRATCH', argument de STATUS dans OPEN 42
186
INDEX
surcharge
doprateur . . . . . . . . . . . . . . . . . . . . . . 25,
de laffectation . . . . . . . . . . . . . . . . . . . . . . .
system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SYSTEM_CLOCK . . . . . . . . . . . . . . . . . . . . . . . . . . . .
113
114
170
149
T
tableau
profil
diffr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
explicite . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
implicite . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
automatique . . . . . . . . . . . . . . . . . . . . . . . . . . 89
bornes dun . . . . . . . . . . . . . . . . . . 79, 85, 121
constructeur de . . . . . . . . . . . . . . . . . . . . . . . 81
de chanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
dimensions dun . . . . . . . . . . . . . . . . . . . . . . . 79
dynamique . . . . . . . . . . . . . . . . . . . . . . . . 89, 90
et pointeurs . . . . . . . . . . . . . . . . . . . . . . . . . . 123
tendue dun . . . . . . . . . . . . . . . . . . . . . . . . . . 79
indexation de . . . . . . . . . . . . . 79-82, 85, 133
masque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
pointeur sur un . . . . . . . . . . . . . . . . . . . . . . 121
profil dun . . . . . . . . . . . . . . . . . . . . 79, 85, 121
rang dun . . . . . . . . . . . . . . . . . . . . . . . . 79, 121
section de . . . . . . . . . . . . . . . . . . . . . . . . . 81, 93
non-rgulire . . . . . . . . . . . . . . . . . . . . . . . 82
rgulire . . . . . . . . . . . . . . . . . . . . . . . 82, 121
taille dun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
tableaux
conformants . . . . . . . . . . . . . . . . . . . . . . . . . . 79
tabulation
dans le code source . . . . . . . . . . . . . . . . . . . . . 6
dans les formats . . . . . . . . . . . . . . . . . . . . . . 49
taille . . . . . . . . . . . . . . . . . . . . . . . . . . . . voir tableau
TAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139, 163
TANH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139, 163
TARGET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16, 119
temps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
THEN . . . . . . . . . . . . . . . . . . . . . . . voir IF ... THEN
TINY . . . . . . . . . . . 14, 18, 143, 155, 157-159, 164
TLn, format tabulation vers la gauche . . . . . . 49
Tn, format tabulation . . . . . . . . . . . . . . . . . . . . . . 49
-traceback, option de ifort . . . . . . . . . . . . . 168
TRANSFER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18, 144
TRANSPOSE . . . . . . . . . . . . . . . . . . . . . . . . . . . 87, 144
TRIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18, 96, 149
TRn, format tabulation vers la droite . . . . . . . 49
TSOURCE=, mot-clef de SPREAD . . . . . . . . . . . . . 87
TYPE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102-107
type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79, 111, 160
driv . . . 19, 102-107, 114, 117, 118, 123,
126, 130, 135
implicite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
interoprable . . . . . . . . . . . . . . . . . . . . . . . . 129
intrinsque . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
187
INDEX
V
VALUE, attribut dargument . . . . . . . . . . . 16, 131
variable
automatique . . . . . . . 58, 167, 168, 170, 171
locale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
statique . . 16, 17, 58, 58, 65, 76, 167, 168,
170, 171
VERIFY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97, 149
visibilit . . . . . . . . . . . . . . . . . . . . . . . . 62-65, 68, 69
W
-Wall, option de g95 . . . . . . . . . . . . . . . . . . . . . 170
warning . . . . . . . . . . . . . . . . . . . . voir avertissement
-Wconversion, option de gfortran . . . 22, 172
-Wextra, option de g95 . . . . . . . . . . . . . . . . . . . 170
WHERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 89
-Wimplicit-none, option de g95 . . . . . . . . . 170
WRITE
argument de ACTION dans OPEN . . . . . . . 42
instruction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
X
X, format espace . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
xlf . . . . . . . . . . . . . . . . . . . . . . . . . voir compilateur
Y
Y0 (x), Y1 (x), Yn (x) . . voir BESSEL_Y0/Y1/YN
Z
Z'n' constante entire en hexadcimal . 17, 95