Académique Documents
Professionnel Documents
Culture Documents
Les
fonc+ons
Une
fonc(on
dispose
d'arguments
qui
correspondent
à
des
informa(ons
qui
lui
sont
transmises
et
elle
fournit
un
résultat
unique,
désigné
par
le
nom
même
de
la
fonc(on
(y
=
f(x))
Exemple.
créa(on
d'une
unité
de
compila(on
(FUNCTION)
FUNCTION
polynome(a,b,c,x)
IMPLICIT
NONE
REAL,
INTENT(IN)
::
a,b,c,x
REAL
::
polynome
polynome
=
a*x*x+b*x+c
END
FUNCTION
polynome
Ici
polynome
sert
au
nom
de
la
fonc(on
et
pour
désigner
le
résultat.
Appel
d'une
fonc-on.
y
=
polynome(a,b,c,x)
est
équivalent
à
y
=
ax2
+
bx
+
c
.
Bien
sûr
y
et
polynome
sont
des
réels.
Il
est
nécessaire
que
le
compilateur
connaisse
le
type
de
la
fonc(on
c-‐à-‐d
le
type
du
résultat
qu'elle
fournit.
On
peut
déclarer
dans
le
programme
principal
:
real
::
polynome
mais
dans
ce
cas
le
compilateur
ne
vérifie
pas
le
type
d'argument
fourni
par
la
fonc(on.
Pour
remédier
à
cet
inconvénient
on
peut
u(liser
une
interface.
3.
Les
interfaces
La
no(on
d'interface
permet
de
fiabiliser
les
appels
de
procédures
et
fonc(ons.
Elle
est
également
indispensable
pour
exploiter
les
possibilités
de
créa(on
de
modules,
de
procédures
génériques.
PROGRAM
fiable
IMPLICIT
NONE
REAL
::
a
=
1.,
b
=
2.
,c
=
5.
,x
=
33.,
y,
z
INTERFACE
FUNCTION
polynome(a,b,c,x)
IMPLICIT
NONE
REAL,
INTENT(IN)
::
a,b,c,x
REAL
::
polynome
END
FUNCTION
polynome
END
INTERFACE
y
=
polynome(x,a,c,b)
z
=
2.
*
y
+
polynome(a+1.,2.*c
,b,y+0.5)
PRINT*,y,z
END
PROGRAM
fiable
L'interface
fournira
alors
non
seulement
le
type
de
la
fonc(on,
mais
aussi
le
type
de
ses
arguments,
ce
qui
signifie
qu'elle
perme]ra
en
outre
un
contrôle
de
ses
arguments.
Ainsi
le
compilateur
renvoît
un
message
d'erreur
si
a,
b,
c
,
x
ne
sont
pas
des
réels.
4.
Les
fonc+ons
récursives
C'est
une
fonc(on
comportant
dans
sa
défini(on
au
moins
un
appel
à
elle-‐même.
Exemple.
calcul
de
n!
RECURSIVE
FUNCTION
factorielle
(n)
RESULT
(res)
IMPLICIT
NONE
INTEGER,
INTENT(IN)
::
n
REAL
::
res
IF
(
n<=
1)
THEN
res
=
1
ELSE
res
=
factorielle(n-‐1)*n
ENDIF
END
FUNCTION
factorielle
L'u(lisa(on
du
mot
clé
RESULT
est
indispensable
pour
dis(nguer
le
résultat
du
nom
de
la
fonc(on.
Bien
sûr
l'interface
doit
être
explicite.
5.
Tableaux
transmis
en
argument
Un
tableau
peut
apparaître
en
argument
d'une
procédure.
Problème
comment
connaitre
le
profil
au
sein
de
la
procédure.
Deux
situa(ons
envisagables
:
•
Le
profil
du
tableau
est
connu
et
fixe.
•
Le
profil
du
tableau
n'est
pas
connu.
Deux
cas
pour
traiter
ce
problème
:
ENTRÉE
transme]re
en
argument,
le
tableau
et
ses
argument
ENTRÉE
déclarer
(en
argument
muet)
un
tableau
de
profil
implicit.
5.1.
Profil
du
tableau
est
connu
SUBROUTINE
connu
(T)
real,
dimension
(10,20)
::
T
...
END
SUBROUTINE
connu
La
dimension
du
tableau
est
figé.
Evidemment,
il
y
a
beaucoup
d'inconvénient
dans
ce]e
démarche.
Par
exemple,
imaginons
qu'on
souhaite
changer
la
taille
du
tableau,
alors
il
faut
parcourir
tous
les
fichiers
où
le
tableau
apparaît
et
changer
ce
qu'il
faut.
5.2.
Transmission
explicite
des
étendues
en
argument.
SUBROUTINE
explicite
(t,
n,p)
IMPLICIT
NONE
!-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐
!
declara(ons
des
arguments
INTEGER,
INTENT(IN)
::
n,p
REAL,
DIMENSION
(n,p),
INTENT(INOUT)
::
t
!-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐
!
declara(ons
des
variables
locales
!-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐
INTEGER
::
i
!-‐-‐-‐-‐-‐-‐debut
du
programme-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐-‐
DO
i
=1,n
t(i,:)
=
i
ENDDO
PRINT*,t
END
SUBROUTINE
explicite
Naturellement,
les
appels
de
la
subrou(ne
explicite
doit
être
fait
dans
le
programme
principal
une
fois
que
le
tableau
a
été
alloué.
5.3.
Tableau
de
profil
implicite
On
souhaite
écrire
une
procédure
générique,
on
suppose
que
le
profil
de
notre
tableau
n'est
pas
connu
par
avance.
SUBROUTINE
implicite
(t)
IMPLICIT
NONE
REAL,
DIMENSION
(:,:),
INTENT(INOUT)
::
t
INTEGER
::
i
DO
i
=
1,
SIZE(t,1)
t(i,:)
=
i
ENDDO
PRINT*,t
END
SUBROUTINE
implicite
DIMENSION(:,:)
précise
que
t
est
un
tableau
de
rang
2
et
que
son
profil
est
implicite
c-‐
à-‐d
qu'il
sera
fourni
à
la
subrou(ne
implicite
lors
de
l'appel.
SIZE
:
Ce]e
fonc(on
intrinseque
fournit
l'étendue
d'un
tableau
suivant
une
direc(on,
ainsi
•
SIZE(t,1)
fournit
l'étendue
de
t
suivant
la
première
dimension
•
SIZE(t,2)
fournit
l'étendue
de
t
suivant
la
deuxième
dimension
q
Pour
u(liser
une
procédure
recevant
en
argument
un
tableau
de
profil
implicit,
son
interface
doit
être
connue.
Exemple
u-lisant
les
subrou-nes
explicite
et
implicite
PROGRAM
affiche_tableau
IMPLICIT
NONE
REAL,
DIMENSION
(4,0:9)
::
t1
REAL,
DIMENSION
(4:10,3:7)
::
t2
INTERFACE
SUBROUTINE
implicite
(t)
IMPLICIT
NONE
REAL,
DIMENSION
(:,:),
INTENT(INOUT)
::
t
END
SUBROUTINE
implicite
END
INTERFACE
CALL
implicite
(t1)
CALL
implicite
(t2)
!
-‐-‐-‐-‐-‐
De
meme
on
peut
faire
la
meme
chose
avec-‐-‐-‐-‐
CALL
explicite
(t1,SIZE(t1,1),
SIZE(t1,2))
CALL
explicite
(t2,SIZE(t2,1),
SIZE(t2,2))
END
PROGRAM
affiche_tableau
L'interface
pour
la
subrou(ne
est
obligatoire
sinon
erreur
d'exécu(on.
La
correspondance
entre
tableau
effec(f
et
tableau
muet
est
uniquement
basée
sur
le
profil.
Les
bornes
exactes
des
indices
n'ont
aucune
incidence
sur
le
déroulement
des
opéra(ons.
Si
nous
faisons
appel
à
t(1,1)
dans
la
subrou(ne
implicite,
il
s'agirait
de
t1(1,0)
pour
le
premier
et
de
t2
(4,3)
pour
le
second.
Il
est
plus
prudent
d'appeler
explicite
en
u(lisant
la
fonc(on
SIZE
Les
tableaux
automa+ques
Les
tableaux
automa(ques
voient
leurs
emplacements
alloués
à
chaque
appel.
Exemple.
Echange
les
valeurs
de
deux
tableaux.
SUBROUTINE
Echange
(Ta,
Tb)
IMPLICIT
NONE
!-‐-‐-‐-‐-‐-‐
arguments
:
tableaux
de
profil
implicite
-‐-‐-‐-‐
INTEGER,
DIMENSION
(:),
INTENT(INOUT)
::
Ta,
Tb
!
tableau
automa(que
:
tableau
local
de
taille
variable
INTEGER,
DIMENSION
(SIZE(Ta))
::
Temp
Temp
=
Ta
Ta
=
Tb
Tb
=
Temp
END
SUBROUTINE
Echange
Bien
entendu,
il
est
nécessaire
que
l'interface
de
ce]e
subrou(ne
soit
explicité
dans
le
programme
principal.
q
Le
profil
d'un
tableau
automa(que
doit
être
donné
en
fonc(on
des
profils
des
arguments.
Les
tableaux
allouables
Il
arrive
parfois
que
la
dimension
d'un
tableau
ne
peut
être
déterminée
qu'après
la
lecture
d'une
donnée.
Ainsi
la
dimension
d'un
tableau
ne
peut
être
connue
lors
de
la
séquence
des
déclara(ons
des
variables
dans
le
programme
principal.
Pour
remédier
à
ceci,
Fortran
offre
la
possibilité
de
décaler
l'alloca(on
de
la
place
mémoire.
PROGRAM
Alloue
IMPLICIT
NONE
INTEGER
::
N
REAL,
DIMENSION
(:,:),
ALLOCATABLE
::
Talloc
READ*,N
ALLOCATE(Talloc(N,0:N+1))
!
alloca(on
de
la
place
memoire
TEMP(2,2)
=
1.
DEALLOCATE
(Talloc)
!
rendre
la
place
memoire
disponible
END
PROGRAM
Alloue
ALLOCATABLE
:
précise
que
le
tableau
doit
être
alloué
ultérieurement,
par
contre
le
rang
du
tableau
doit
être
figé
par
avance.
ALLOCATE
:
réserve
la
place
mémoire
et
le
profil
du
tableau
est
explicité.
DEALLOCATE
:
libére
la
place
mémoire,
et
après
ce]e
instruc(on
on
ne
peut
plus
u(liser
le
tableau
en
ques(on.
Les
modules
et
la
généricité
La
no(on
de
module
ouvre
de
nombreuses
perspec(ves
:
v
Défini(on
des
types
structures
communs
à
plusieurs
unités
de
programme.
v
Partage
de
données
entre
plusieurs
unités
de
programme.
v
bibliothèques
de
procédures.
v
Créa(on
de
types
abstraits
de
données.
No+on
de
module
Les
modules
perme]ent
d'améliorer
la
fiabilité
des
programmes
en
évitant
la
duplica(on
de
déclara(ons
iden(ques.
Exemple
1.
Nous
créons
une
unité
de
compila-on
nommée
'MODULE’
MODULE
typtmod
IMPLICIT
NONE
TYPE
point
INTEGER
::
num
REAL
::
x,
y
END
TYPE
point
END
MODULE
typtmod
Pour
u(liser
ce
module,
il
suffit
de
men(onner
une
instruc(on
USE
(
ici
USE
typtmod)
au
sein
d'un
programme,
d'une
procédure
ou
d'une
fonc(on.
Par
exemple
PROGRAM
exemple_module
USE
typtmod
IMPLICIT
NONE
TYPE(point)
::
a
=
point(3,2,0,5.)
PRINT*,a
END
PROGRAM
exemple_module
Tout
se
passe
alors
comme
si
les
instruc(ons
contenues
dans
le
module
typtmod
avaient
été
introduites
dans
le
programme
principale.
Exemple
2.
Dépendances
entre
modules
et
procédure.
Un
module
peut
faire
appel
à
son
tour
à
un
autre
module.
MODULE
symmod
USE
typtmod
IMPLICIT
NONE
CONTAINS
FUNCTION
symetrique
(p)
TYPE(point),
INTENT(IN)
::
p
TYPE(point)
::
symetrique
symetrique%x
=
-‐p%x
END
FUNCTION
symetrique
END
MODULE
symmod
le
mot
clé
CONTAINS
indique
que
la
fonc(on
symetrique
est
une
fonc(ons
interne
à
l'unité
de
compila(on
(MODULE
symmod)
et
ainsi
le
type
point
n'a
pas
besoin
d'être
déclaré
à
l'intérieur
de
la
fonc(on
symetrique.
PROGRAM
exple_sym
USE
typtmod
USE
symmod
IMPLICIT
NONE
TYPE(point)
::
a
=
point(3,2,0,5.),
b
b
=
symetrique
(a)
PRINT*,a,b
END
PROGRAM
exple_sym
Noter
que
L'INTERFACE
d'une
fonc(on
(ou
d'une
prodédure)
n'est
pas
exigée
si
celle-‐ci
est
définie
dans
un
module.
Exemple3.
Partage
des
données.
MODULE
tabmod
IMPLICIT
NONE
INTEGER,
PARAMETER
::
n
=
10
INTEGER,
DIMENSION
(n)
::
T
END
MODULE
tab
Voici
une
subrou(ne
qui
u(lise
ce
module
SUBROUTINE
init
USE
tabmod
IMPLICIT
NONE
INTEGER
::
I
T=(/
(i,
i=1,n)
/)
END
SUBROUTINE
init
Ce]e
subrou(ne
n'a
pas
d'argument,
mais
par
contre
le
tableau
T
est
connu
via
le
module
tabmod.
PROGRAM
exple_tab
USE
tabmod
IMPLICIT
NONE
CALL
init
PRINT*,T
END
PROGRAM
exple_tab
D'une
maniére
générale,
le
seul
type
de
dépendance
soit
interdit
est
celui
où
un
module
s'appelle
lui-‐même
directement
ou
indirectement
:
A
u(lise
B
qui
u(lise
C
qui
u(lise
A.
Les
procédures
génériques
(MODULE
PROCEDURE)
Le
principe
est
de
regrouper
sous
un
seul
nom
(nom
générique
)
de
procédures
en
laissant
le
compilateur
décider
de
la
bonne
procédure
à
appeler
en
fonc(on
du
type
des
arguments.
Par
exemple,
on
propose
d'écrire
une
famille
de
sous-‐procédures
dont
le
nom
générique
sera
AFFICHE
des(nées
à
écrire
les
valeurs
de
leurs
arguments
de
type
en(er,
réel
ou
tableau.
MODULE
genemod
IMPLICIT
NONE
INTERFACE
affiche
MODULE
PROCEDURE
aff_int,
aff_real,aff_tab
END
INTERFACE
CONTAINS
SUBROUTINE
aff_integer(n)
integer,
intent(in)
::
n
Print*,'en(er
:',
n
END
SUBROUTINE
aff_integer
SUBROUTINE
aff_real(r)
real,
intent(in)
::
r
Print*,'reel
:',
r
END
SUBROUTINE
aff_real
SUBROUTINE
aff_tab(T)
real,
dimension(:),
intent(in)
::
T
Print*,'tableau
:',
T
END
SUBROUTINE
aff_tab
END
MODULE
genemod
les
procédures
qu'on
appellera
sous
le
nom
generique
affiche
sont
affinteger,
affreal
ou
arab.
Le
compilateur
choisira
d'appeler
la
subrou(ne
affinteger
si
l'argument
de
la
subrou(ne
affiche
est
un
en(er.
Voici
un
programme
d'u(lisa(on
de
ce
module
:
PROGRAM
imprime
USE
genemod
IMPLICIT
NONE
integer
::
n,i
real
::
x
real,
dimension
(15)
::
T1=(/
(25.*i,i
=
1,15)
\)
n
=
25
x
=
5.25
CALL
affiche
(n)
CALL
affiche
(x)
CALL
affiche
(T1)
END
PROGRAM
imprime
Selon
le
type
d'argument,
en(er,
réel
ou
tableau
l'interface
générique
choisit
alors
d'exécuter
l'une
des
trois
subrou(ne
affinteger,
affreal
ou
arab
Interface
Operator
Considérons
l'instruc(on:
x
=
a
+
b
le
même
symbole
+
peut
désigner
suivant
le
type
de
a
et
b
des
opéra(ons
différentes
:
x
est
un
en(er
si
a
et
b
sont
des
en(ers
x
est
un
réel
si
a
et
b
sont
des
réels
ou
a
en(er
et
b
réel
...
x
est
un
tableau
du
même
profil
que
a
si
a
et
b
sont
deux
tableaux
de
même
profil.
L'opéra(on
+
(
-‐,/
ou
*)
est
déjà
prédéfinie,
et
selon
le
type
des
opérandes
elle
fournit
un
résultat
différent.
Fortran
offre
la
possibilité
de
:
•
donner
une
significa(on
à
tout
autre
symbole(+,
-‐,
/,
*,...)
lorsqu'il
porte
sur
des
types
différents
de
ceux
pour
lesquels
il
est
déjà
défini.
Exemple.
Interface
operator
(+)
Interface
operator
(-‐)
•
créer
de
nouveaux
opérateurs
de
la
forme
.op.
où
op
désigne
une
suite
quelconque
de
caractères.
Exemple.
Interface
operator
(.SOMME.)
Exemple
de
Surdéfini+on
de
l'opérateur
+
Ce]e
technique
est
u(lisée
pour
doter
d'opérateurs
simples
des
types
dérivées,
afin
d'en
simplifier
la
manipula(on.
MODULE
opplusmod
IMPLICIT
NONE
TYPE
point
INTEGER
::
num
REAL
::
x,y
END
TYPE
point
INTERFACE
OPERATOR(+)
MODULE
PROCEDURE
point_plus_point,
point_plus_en(er
END
INTERFACE
CONTAINS
FUNCTION
point_plus_point(
p1,
p2)
RESULT(ppp)
TYPE(point),
INTENT(IN)
::
p1,p2
TYPE(point)
::
ppp
ppp
=
point(p1%num+p2%num,
p1%x+p2%y,
p1%y+p2%y)
END
FUNCTION
point_plus_point
.
FUNCTION
point_plus_en(er(
p,
n)
RESULT(ppn)
TYPE(point),
INTENT(in)
::
p
INTEGER
,
INTENT(in)
::
n
TYPE(point)
::
ppn
ppn
=
point(p%num+n,
p%x,
p%y)
END
FUNCTION
point_plus_en(er
END
MODULE
opplusmod
Ce
module
a
permis
de
définir
la
somme
de
deux
structures
comme
on
le
souhaite
par
l'interface
operator
(+)
Voici
un
exemple
d'u(lisa(on
de
ce
module
:
Program
operateur
USE
opplusmod
IMPLICIT
NONE
TYPE(point)
::
a,b,c
a
=
point(3,
2.,
3.)
b
=
point(2,
4.,
5.2)
c
=
a+b
PRINT*,'a+b
=',c
PRINT*,'c+14
=',c+14