module mod
implicit none
private ! tutte le quantita' non esplicitamente public
! sono private (visibili solo nel modulo)
integer,parameter :: k=selected_real_kind(14)
public :: Poly, f, set_interval, k
real(kind=k) :: a,b
real(kind =k),dimension(:),allocatable :: nodo
contains
! set_interval copia gli argomenti x e y nelle variabili (private) globali
! a e b del modulo: ogni sottoprogramma del modulo ha accesso ad a e b ma
! non i programmi esterni al modulo
subroutine set_interval(x,y)
real(kind=k),intent(in) :: x,y
a = x
b = y
end subroutine set_interval
! f(x) : funzione da interpolare
function f(x) result(y)
real(kind =k),intent(in) ::x
real(kind =k) ::y
if ( x == 0) then
y = 0 ! prolungamento per continuita' nell' origine
else
y= exp (-1.0/x**2)
end if
end function f
! funzione di Lagrange relativa al j-esimo nodo dell' interpolante
! di grado n
function Lagrange(n,j,x) result (u)
real(kind =k),intent(in) :: x
integer,intent(in) :: n,j
real(kind =k) :: den,u,num
integer :: i
num=1.0
den=1.0
do i=0,n
if (i == j) cycle !il prodotto deve escludere x==xi
num=num*(x-nodo(i)) !prodotto dei numeratori
den=den*(nodo(j)-nodo(i)) !prodotto dei denominatori
end do
u=num/den
end function Lagrange
! interpolante polinomiale di grado g nel punto x
! la function calcola i nodi
function Poly(g,x) result(pol)
integer, intent(in) :: g ! grado del polinomio (n.punti - 1)
real(kind =k),intent(in) :: x !
integer :: i,errall
real(kind =k) :: pol
allocate(nodo(0:g),stat=errall)
if(errall /= 0) stop 'errore alloc. nodo '
do i=0,g
nodo(i) = a + i*(b-a)/g
end do
pol=0.0
do i = 0, g
pol = pol + f(nodo(i))*Lagrange(g,i,x) !formula di Lagrange
end do
deallocate(nodo)
end function Poly
end module mod
program lagra
use mod
implicit none
integer :: m, i, j, mi, ma, step
real(kind =k) :: x, dx, a, b
a =-1.0
b = 1.0
call set_interval(a,b) ! passa al modulo gli estremi dell' intervallo
do
print*,"numero di punti (equispaziati) sui cui valutare funzione ed interpolanti per graficarle"
print*,"(deve essere > 1)"
read*,m
if(m > 1)exit
end do
print*," grado min, max e step delle interpolanti"
print*," (verranno calcolate le int. di grado min,min+step, min+2*step..."
print*," per tutti i valori di n che garantiscono min + n*step <= max )"
do
read*,mi,ma,step
if( mi>=1 .and. &
ma>=mi .and. &
step>=1 )exit
print*," deve essere : min >=1, max>=min, step >=1 "
end do
dx = (b-a)/(m-1)
do i = 1,m
x = a + (i-1)*dx
write(unit = 1,fmt = *)x,f(x)
write(unit = 2,fmt = *)x,(Poly(j,x),j=mi,ma,step)
end do
print*," il file fort.1 contiene i valori dell' ascissa e della funzione "
print*," il file fort.2 contiene i valori dell' ascissa e delle interpolanti su ",&
2+(ma-mi)/step," colonne"
print*," "
print*," il file fort.3 contiene comandi per visualizzare le curve mediante gnuplot"
print*," uso: gnuplot fort.3 "
print*," e poi invio per terminare "
write(unit=3,fmt=*)"set style data lin "
write(unit=3,fmt=*)"p 'fort.1' ,'fort.2' \"
i=3
do j=mi+1,ma,step
write(unit=3,fmt=*)",'' u 1:",i,"\"
i=i+1
end do
write(unit=3,fmt=*)" "
write(unit=3,fmt=*)"pause -1"
end program lagra