function [v,errore] =minimi_quadrati(x,y)

%   Detailed explanation goes here
% Approssimazione nel senso dei minimi quadrati
% INPUT:   coppie di dati (x_i,y_i)  i=1,2,.... m
% OUTPUT:  1. parametri che definiscono il polinomio/funzione approssimante
%          2. errore di approssimazione

tipo=menu('Funzione approssimante','Polinomi','e^x','cos(x) e sin(x)') ;
m=length(x) ;
xplot=linspace(min(x),max(x),200) ;

if tipo==1
% Costruzione di una retta di Regressione o di un generico polinomio

 n=input('Inserisci il grado del polinomio approssimante\n') ;
 [v]=polyfit(x,y,n) ;     % polinomio approssimante
 rplot=polyval(v,xplot) ;
 figure
 plot(xplot,rplot)
 hold on
 plot(x,y,'rx')
 errore=norm((y-polyval(v,x)),inf) ;
 text(0,2.8,['Errore di approssimazione = ' num2str(errore)])
 % Risoluzione del sistema delle equazioni normali
 % (A^T)A v=(A^T)y   dove v contiene i coefficienti
 % che definiscono la funzione approssimante
 % n+1: numero di funzioni di base 'fi' che utilizzo per costruire
 % la funzione approssimante
 
elseif tipo==2       % approssimo con combinazione lineare
                     % di esponenziali e^(lambda*x)
     n=input('Quante funzioni di base vuoi usare?\n') ;
     A=zeros(m,n) ;
     lambda=input('Inserisci i valori di lambda in e^\lambda x (in un vettore)\n') ;
     %v=zeros(1,n) ;
     % Costruisco la matrice A
for i=1:m
    for j=1:n
        A(i,j)=exp(lambda(j)*x(i)) ;
    end
end
    B=A'*A ;
    disp(B)
    b=A'*y' ;
    % risolvo il sistema (A^T)A=(A^T)b
    v=B\b ;
    yplot=zeros(1,200) ;
    for i=1:n
        yplot=yplot+v(i)*exp(lambda(i)*xplot) ;
    end
    figure
    plot(xplot,yplot)
    hold on
    plot(x,y,'rx')
    title('Approssimazione con combinazione lineare di esponenziali')
    yapp=zeros(1,m) ;
    for i=1:n
        yapp=yapp+v(i)*exp(lambda(i)*x) ;
    end
    errore=norm(y-yapp,inf) ;
else
     disp('Uso sin(k*pi*x) e cos(k*pi*x) dove k=1/2,1,3/2,2...') 
     n=input('Quante funzioni di base vuoi usare?\n') ;
     A=zeros(m,n) ;
     k=input('Inserisci i valori di k (in un vettore)\n') ;
     fine=n ;
     if mod(n,2)
         fine=n-1 ;
     end
     % Costruisco la matrice A
for i=1:m
    for j=1:2:fine
        A(i,j)=cos(k(j)*pi*x(i)) ;
        A(i,j+1)=sin(k(j+1)*pi*x(i)) ;
    end
    if mod(n,2)
        A(i,n)=cos(k(n)*pi*x(i)) ;
    end
end
    B=A'*A ;
    disp(B)
    b=A'*y' ;
    % risolvo il sistema (A^T)A=(A^T)b
    v=B\b ;
    yplot=zeros(1,200) ;
    for j=1:2:fine
        yplot=yplot+v(j)*cos(k(j)*pi*xplot)+v(j+1)*sin(k(j+1)*pi*xplot) ;
    end
    if mod(n,2)
        yplot=yplot+v(n)*cos(k(n)*pi*xplot) ;
    end
    figure
    plot(xplot,yplot)
    hold on
    plot(x,y,'rx')
    title('Approssimazione con combinazione lineare di funzioni trigonometriche')
    yapp=zeros(1,m) ;
    for j=1:2:fine
        yapp=yapp+v(j)*cos(k(j)*pi*x)+v(j+1)*sin(k(j+1)*pi*x) ;
    end
    if mod(n,2)
        yapp=yapp+v(n)*cos(k(n)*pi*x) ;
    end
    errore=norm(y-yapp,inf) ;
end
grid
end
