Sottoprogrammi in Fortran
Paolo Bison
Fondamenti di Informatica
A.A. 2007/08
Università di Padova
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.1
Elementi sintattici
modulo
unità di programma contenente definizioni di user-defined
types, variabili e sottoprogrammi
compilazione separata
visibilità degli elementi dichiarati in un modulo
PUBLIC
elementi accessibili da altri moduli
PRIVATE
elementi condivisi solamente tra gli elementi del modulo
sottoprogrammi
subroutines (procedure)
functions (funzioni)
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.2
Definizione di modulo
sintassi
R1104x
is
R1104
is
R1104z
is
or
or
or
R212
is
R213
is
or
module
private-module
private-module
MODULE module-name
[ use-stmt ] ... [ PRIVATE ]
[ module-entity-def ] ...
[ module-subprogram-part ]
END MODULE module-name
module-entity-def
[ derived-type-def ]
[ other-type-declaration-stmt ]
[ module-procedure-interface-block ]
[ external-procedure-interface-block ]
module-subprogram-part
CONTAINS
module-subprogram
[ module-subprogram ] ...
module-subprogram
function-subprogram
subroutine-subprogram
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.3
Visibilità degli identificatori
per tutti gli elementi si deve dichiarare se sono PRIVATE o
PUBLIC
attributo nella dichiarazione
R511
is
or
access-spec
PUBLIC
PRIVATE
integer, private :: y,k,z
real, public :: t,m
definizione mediante un access-stmt
R522
is
access-stmt
access-spec [ :: access-id-list ]
public :: xx,yy
private :: lc, high
senza lista definisce accesso di default (Fortran 90/95)
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.4
Istruzione USE
definisce da quali moduli si importa gli elementi di tipo
PUBLIC
R1107
use-stmt
is
USE module-name [ , rename-list ]
R1108
rename
is
local-name => use-name
Constraint:A module-name shall appear in at most one USE
statement in a scoping unit.
Constraint:A module shall not be made accessible by more
than one use statement in a scoping unit.
Constraint:The module shall appear in a previously
processed program unit.
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.5
Campo di validità
per gli elementi PRIVATE
il modulo
per gli elementi PUBLIC
il modulo + altri moduli/programmi che dichiarino di
utilizzare tale modulo. Quest’ultimi possono ridefinire gli
identificatori dichiarati nei moduli che usano solo se li
rinominano. con la rename-list
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.6
moduli.f90
!
! moduli.f90
!
module modA
integer,public :: k=10
real, public :: x=5.0
integer,private :: l=-100
end module modA
module modB
integer,public :: k=20
real,public :: y=20.9
integer,private :: l=99
end module modB
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.7
moduli.f90
module modC
use modA
private
integer,public :: l=55
real,private :: y=-8.9
end module modC
program moduli
use modA,pippo=>x
use modB
use modC
integer :: m,n
integer :: x=-333 ! errore se non ci fosse pippo=>x
print *,x,y,l
! print *,k ! errore: k dichiarato sia in modA che in modB
end program moduli
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.8
Definizione di sottoprogramma
sintassi
R1216
is
function-subprogram
function-stmt
specification-part [ execution-part ] end-function-stmt
R1221 subroutine-subprogram
is
subroutine-stmt
[ specification-part ] [ execution-part ] end-subroutine-stmt
R1221v specification-part
is
[ use-stmt ] ... [ dummy-declaration-stmt] ...
[ result-type-declaration-stmt ]
[ other-type-declaration-stmt ] ...
R1217 function-stmt
is
[ RECURSIVE ] FUNCTION function-name
([ dummy-arg-name-list ]) RESULT (result-name)
R1220 end-function-stmt
is
END FUNCTION function-name
R1222 subroutine-stmt
is
[ RECURSIVE ] SUBROUTINE subroutine-name
( [ dummy-arg-list ] )
R1224 end-subroutine-stmt
is
END SUBROUTINE subroutine-name
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.9
Parametri formali
dummy-arg-name-list
lista dei parametri formali (identificatori separati da virgola)
subroutine (x,y,z,c)
dummy-declaration-stmt
dichiarazioni di tipo per i parametri formali (dummy) presenti
nella dummy-arg-name-list
real :: x,y,z
character :: c
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.10
Attributi dei parametri formali
intent ( intent-spec )
indica l’uso inteso per il parametro formale con i seguenti
valori di intent-spec:
in il parametro è utilizzato per fornire dati al chiamato
out il parametro è utilizzato per ritornare dati al chiamante
ed è indefinto alla chiamata
inout il parametro è utilizzato per passare dati in entrambi i
sensi
optional
può non esserci il corrispondente parametro attuale nella
chiamata al sottoprogramma; in tal caso il valore è indefinito
funzione intrinseca present(par-name) per vedere se il
parametro è presente
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.11
Attivazione sottoprogrammi
sintassi
R1210
function-reference
is
function-name ( [ actual-arg-spec-list ] )
R1211
call-stmt
is
CALL subroutine-name ( [ actual-arg-spec-list ] )
R1212
actual-arg-spec
is
[ keyword = ] actual-arg
R1213
keyword
is
dummy-arg-name
R1214
actual-arg
is
expr
or
variable
or
subprogram-name
Constraint: The keyword = may be omitted from an
actual-arg-spec only if the keyword = has been omitted
from each preceding actual-arg-spec in the argument list.
Constraint: A procedure-name actual-arg shall not be
the name of an intrinsic function.
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.12
param.f90
! param.f90
! esempio di passaggio di parametri
module modA
public :: subA
contains
subroutine subA(i,k,l,m)
integer,intent(in) :: i,k
integer,intent(in),optional :: l,m
print *,"-------------"
print *,"i",i,"k",k
if (present(l)) then
print *,"l",l
end if
if (present(m)) then
print *,"m",m
end if
end subroutine subA
end module modA
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.13
param.f90
program moduli
use modA
call subA(5,3)
call subA(k=8,i=-4)
call subA(1,2,3)
call subA(1,2,3,4)
call subA(1,2,m=3)
end program moduli
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.14
Valore di ritorno per le funzioni
dichiarazione del result-name nella
result-type-declaration-stmt
function somma_funct(x,y) result(z)
integer, intent(in) :: x,y
integer :: z
sconsigliabile avere side-effects nelle funzioni
(vietati in F)
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.15
modulo_somma.f90
! modulo_somma.f90
! somma tra due interi realizzata sia con
! una subroutine sia con una function
module somma
public :: somma_subrt,somma_funct
contains
subroutine somma_subrt(x,y,z)
integer, intent(in) :: x,y
integer, intent(out) :: z
z=x+y
end subroutine somma_subrt
function somma_funct(x,y) result(z)
integer, intent(in) :: x,y
integer :: z
z=x+y
end function somma_funct
end module somma
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.16
modulo_somma.f90
program modulo_somma
use somma
integer ::k,l,t
read *,k,l
call somma_subrt(k,l,t)
print *,t
print *,somma_funct(k,l)
end program modulo_somma
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.17
side_effects.f90
module strange
public :: fun,sub
integer, public :: k
contains
function fun() result(ris)
real :: ris
k=3*k
ris=5
end function fun
end module strange
program side_effects
use strange
k=3
print *,k+fun()+k
k=3
print *,k+k+fun()
end program side_effects
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.18
Terminazione dei sottoprogrammi
fine logica
end subroutine / end function
istruzione return
sintassi
R1226
is
return-stmt
RETURN
termina l’esecuzione del sottoprogramma
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.19
return.f90
module test
public :: test_n
contains
function test_n(n) result(f)
! ritorna .FALSE. se n<=0 o somma di tutti
! i numeri tra 1 e n e’ dispari, .TRUE. altrimenti
integer,intent(in) :: n
logical :: f; integer :: somma,i
f=n>0;
if (.not. f) then; return; end if
somma=0; do i=1,n; somma=somma+i; end do
f=modulo(somma,2)==0
end function test_n
end module test
program main
use test
print *,test_n(6); print *,test_n(4)
print *,test_n(7); print *,test_n(-15)
print *,test_n(0)
end program main
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.20
Variabili locali
Horribile Visu
modalità di gestione non definita nelle specifiche del
linguaggio
attributo save
forza attivazione/disattivazione dell’associazione
corrispondente
save implicito
dichiarazione variabile locale con inizializzazione
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.21
local_var.f90
! local_var.f90
!
module somma
public :: media,devstd
contains
function media(n) result(m)
integer,intent(in) :: n
real :: m; integer :: somma,i
somma=0; do i=1,n; somma=somma+i; end do
m=somma/n
end function media
function devstd(n) result(sigma)
integer,intent(in) :: n
real :: sigma
integer :: i; real :: somma=0,m
m=media(n); do i=1,n; somma=somma+(i-m)**2; end do
sigma=sqrt(somma/n)
end function devstd
end module somma
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.22
local_var.f90
program local_var
use somma
print *,media(100)
print *,devstd(100)
end program local_var
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.23
Stringhe/array come parametri
stringhe
specificazione (len = *) nella dichiarazione del parametro
formale
array
ulteriori parametri il cui valore da la dimensione
subroutine calc(data_array,n,m)}
integer,intent(in) :: n,m
real,dimension(n,m),intent(inout) :: data_array}
uso di : per ogni dimensione
subroutine calc(data_array)
real,dimension(:,:),intent(inout) :: data_array}
funzioni intrinseche:
lbound(arr,dim) ubound(arr,dim) size(arr,dim)
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.24
param_array.f90
! param_array.f90
! esempio di passaggio di parametri
module array
public :: subA
contains
subroutine subA(arr_in,arr_out)
integer,dimension(:,:),intent(in) :: arr_in
integer,dimension(:,:),intent(out) :: arr_out
integer :: k,l
if ((size(arr_in,1)/=size(arr_out,1)) .or.
(size(arr_in,2)/=size(arr_out,2))) then
print *,"array differenti"
do k=lbound(arr_out,1),ubound(arr_out,1)
do l=lbound(arr_out,2),ubound(arr_out,2)
arr_out=0
end do
end do
return
end if
arr_out=3*arr_in
end subroutine subA
end module array
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.25
param_array.f90
program param_array
use array
integer,dimension(2,3) :: arrA, arrB
integer,dimension(3,3) :: arrC
arrA=reshape((/1,-1,3,-2,5,4/),(/2,3/))
call subA(arrA,arrB)
print *,arrA
print *,arrB
call subA(arrA,arrC)
print *,arrC
end program param_array
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.26
Array automatici
array locali le cui dimensioni sono specificate con
espressioni in cui possono apparire i parametri
integer,dimension(n+1,m) ::
dati locali
creazione/distruzione dell’associazione
non è possibile la loro inizializzazione nella dichiarazione
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.27
Passaggio di subroutine e/o function
definizione del nome, dei parametri formali e dell’eventuale
valore di ritorno in un blocco INTERFACE
R1202
is
R1205
is
or
dummy-procedure-interface-block
INTERFACE
interface-body
[ interface-body ] ...
END INTERFACE
interface-body
function-stmt
[ specification-part ]
end-function-stmt
subroutine-stmt
[ specification-part ]
end-subroutine-stmt
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.28
func_graph.f90
! func_graph.f90
! rappresentazione grafica di una funzione
module graph
public :: draw_func
contains
subroutine draw_func(func)
interface
function func(x) result(y)
real,intent(in) :: x
real :: y
end function func
end interface
real, parameter :: d = 0.4
! 1/4, 4 campioni
! nell’intervallo [x,x+1]
integer, parameter :: s = 10 ! 10 caratteri di ampiezza
! per l’intervallo [y,y+1]
integer, parameter :: h = s+2 ! massimo valore positivo
! asse x
integer, parameter :: lim =80 ! numero di campionamenti
integer :: i, k
logical, dimension(-h:h,0:lim-1) :: grid
character (len=lim) :: linea
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08
– p.29
func_graph.f90
!
! inizializzazione
!
do i=-h,h
do k=0,lim-1
grid(i,k)=.false.
end do
end do
!
! calcolo campioni
!
do k=0,lim-1
grid(nint(s*func(d*k)),k)=.true.
end do
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.30
func_graph.f90
!
! visualizzazione
!
do i=h,-h,-1
linea = ""
do k=0,lim-1
if (grid(i,k)) then
linea(k+1:k+1) ="*"
else if (i==0) then
linea(k+1:k+1) = "-"
else
linea(k+1:k+1) = " "
end if
end do
print *,linea
end do
end subroutine draw_func
end module graph
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.31
func_graph.f90
module functions
public :: f_sin,f_sinc
contains
function f_sin(x) result(y)
real,intent(in) :: x
real :: y
y=sin(x)
end function f_sin
function f_sinc(x) result(y)
real,intent(in) :: x
real :: y
if (x==0.0) then
y=1.0
else
y=sin(x)/x
end if
end function f_sinc
end module functions
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.32
func_graph.f90
program modulo_graph
use graph
use functions
call draw_func(f_sin)
print *
call draw_func(f_sinc)
end program modulo_graph
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.33
Gestione errori
assegnazione di particolari valori ad elementi visibili
all’esterno del sottoprogramma:
variabile non locale
parametro di tipo out o inout
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.34
gest_errori.f90
module div
integer,public :: err ! /= 0 segnala un errore
public :: div1,div2
contains
subroutine div1(x,y,z)
integer, intent(in) :: x,y
integer, intent(out) :: z
err=0
if (y==0) then; err=1
else; z=x/y
end if
end subroutine div1
subroutine div2(x,y,z,err)
integer, intent(in) :: x,y
integer, intent(out) :: z,err
err=0
if (y==0) then; err=1
else; z=x/y
end if
end subroutine div2
end module div
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.35
gest_errori.f90
program main
use div
integer ::k,l,t,errore
read *,k,l
call div1(k,l,t)
if (err/=0) then; print *,"errore"
else; print *,t
end if
call div2(k,l,t,errore)
if (errore/=0) then; print *,"errore"
else; print *,t
end if
end program main
Sottoprogrammi in Fortran, Paolo Bison, FI07, 2008-01-08 – p.36
Scarica

PUBLIC PRIVATE