%
% TIPI DI DATO FONDAMENTALI IN MATLAB:
%
d = 2.4435895647;  % numero floating-point in doppia precisione ("double")
c = 'w';           % carattere
%
% con essi e' possibile definire vettori e matrici :
%
v = [3.12 2.22 5.00];                              % vettore
M = [1.2 2.0 8.88; 7.75 4.0 3.33; 4.25 2.2 2.12];  % matrice
s = ['c' 'i' 'a' 'o'];                             % "stringa" (vettore di caratteri)
C = ['c' 'i' 'a' 'o' ' '; 'm' 'o' 'n' 'd' 'o'];    % vettore di stringhe (matrice di caratteri)
%
% CREAZIONE E GESTIONE DI STRINGHE DI CARATTERI :
%
s1 = 'ciao';
s2 = 'mondo';
% per le stringhe valgono le normali operazioni sulle matrici:
str = ['un grande ' s1 ' al ' s2];   % concatenazione
substr = str(4:7);            % sottostringa
str2num('2.23');              % conversione da stringa a double
num2str(2.23);                % conversione da double a stringa
% 
% VARIE MODALITA' DI CREAZIONE DI MATRICI E VETTORI
% 
n=100;   m=120;
A=ones(n,n); B=A;  % A e B sono due matrici [n x n] in cui ogni componente vale "1.0"
A=zeros(n,n) + 4.75;      % A è una matrice [n x n] in cui ogni componente vale "4.75"
H=repmat(44.2,m,n);       % A è una matrice [m x n] in cui ogni componente vale "44.2"
v=[12 3 15 18 10 6];
w=[2 6 9 15 4 12];
2:5:13;  % è un vettore ==[2 7 12] . L'operatore ":" serve a costruire facilmente sequenze di questo tipo,
         % che poi risultano utili nei cicli "for" (es. "for i=1:10") e nell'estrazioni di sottomatici o parti di vettori
         % (es. A(2,1:3) corrisponde a [A(2,1) A(2,2) A(2,3)]. La forma generale è:  <primo elemento>:<incremento>:<limite>
%
% OPERAZIONI VETTORIALI
%
v + w;   % somma dei due vettori
v * w';  % prodotto interno dei due vettori
v' * w;  % prodotto esterno (vettore) dei due vettori 
z = v .* w;   % prodotto "per componenti" dei due vettori: produce un vettore con elementi pari al prodotto degli elementi corrispondenti di "v" e "w": z_i = v_i * w_i
A + B;   % somma delle due matrici
A + 3.2; % sommo 3.2 ad ogni elemento di A
sqrt(A); % matrice con elementi pari alle radici quadrate del corrispondente elemento di A
sin(A);  % matrice con elementi pari al seno del corrispondente elemento di A
C = A * B;   % prodotto matriciale 
C = A .* B;  % prodotto "per componenti" delle due matrici: produce una matrice con elementi pari al prodotto degli elementi corrispondenti di A e B: c_i_j = a_i_j * b_i_j
% NB: il punto "." prima dell'operatore aritmetico indica che l'operazione viene compiuta componente-per-componente
%
%
%
%
%  ISTRUZIONI DI CONTROLLO:
%
%
%
% IF-THEN-ELSE : permette di esprimere un'alternativa in base ad una condizione da testare durante l'esecuzione del programma :
% 
% if <condizione>
%   <istruzioni ....>
% else
%   <istruzioni ....>
% end
% 
% Dal punto di vista del calcolo numerico, questo è un costrutto poco favorevole poichè, in generale:
% - nella valutazione della condizione non vengono eseguiti propriamente dei conti;
% - non favorisce la creazione di un flusso omogeneo di calcoli (condizione ideale per ottenere una 
%   buona velocità di esecuzione nelle macchine di calcolo moderne).
% Dunque, esso va messo in un algoritmo solo se strettamente necessario e preferibilmente non all'interno di un ciclo.
% Esempio:
acc=1;
tic
for i=1:100000
  acc=acc+1;
end
senzaif=toc;
acc=1;
tic
for i=1:100000
  if acc==0
    error('acc non può essere ==0 !')
  else
    acc=acc+1;
  end;
end
conif=toc;
disp(' ');
disp(['tempo di esecuzione senza istruzione ''if'': ' num2str(senzaif) ' [sec]'])
disp(['tempo di esecuzione con istruzione ''if''  : ' num2str(conif) ' [sec]'])
disp(['incremento percentuale dovuto alla presenza di ''if'' :  ' num2str((conif-senzaif)/senzaif*100) ' %'])
disp(' ');
disp(['Notare che le operazioni numeriche sono esattamente le stesse in entrambi i casi.'])
return


% ciclo FOR : permette di ripetere un certo insieme di istruzioni per un numero prefissato di iterazioni
% 
% for <variabile> = <vettore di interi>
%   <istruzioni ...>
% end
% 
% "<vettore di interi>" può essere espresso in vari modi (tutti quelli con cui è possibile esprimere un vettore in Matlab/Octave),
%                       e <variabile> assume al passo i-esimo il valore della sua i-esima componente :
% 1)  "i = 1:10:2000", che significa " i parte da 1, si incrementa con passo 10 ed il ciclo si arresta quando i>2000" (in linguaggio C, sarebbe "for (i=10; i<=2000; i+=10) {...});
%     varianti: "100:-1:0", "a:delta:b", ecc...
% 2)  "i = [1 2 4 6 25]", che significa " il ciclo esegue 5 iterazioni; alla prima i vale 1, alla seconda 2, alla terza 4, alla quarta 6, alla quinta 25"
%     varianti: "i = mio_vettore", "i=[mio_vettore_1 mio_vettore_2]", ecc....
% Questo costrutto è largamente utilizzato nel calcolo numerico e si presta a vari tipi di ottimizzazioni, 
% sia su calcolatori sequenziali che paralleli. 
% Tipicamente la <variabile> assume valori da 1 a N, dove N è una dimensione del problema, ad es. il numero 
% di componenti di un vettore o di righe (o colonne) di una matrice.
% Esempio: prodotto di due matrici, C=A*B
n=5;
A=ones(n,n); B=A;  % A e B sono due matrici 1000x1000 di 1
C=zeros(n,n);
for i=1:n  % indice riga della matrice C
  for j=1:n  % indice colonna della matrice C
    for k=1:n  % indice lungo i vettori riga_i(A) e colonna_j(B)
      C(i,j)=C(i,j)+A(i,k)*B(k,j);
    end
  end
end
% questo programma funziona nel modo seguente: 
% - il ciclo più esterno, in "i", seleziona ogni riga di C (lo si vede dall'istruzione di assegnazione C(i,j)=...); 
% - per ogni valore di "i", il ciclo immediatamente più interno, in "j", seleziona ogni colonna di C e dunque 
%   l'esecuzione del ciclo più interno comporta l'assegnazione degli elementi della riga i-esima di C;
% - l'assegnazione dell'elemento C(i,j) comporta il prodotto interno di due vettori v1 e v2 (= somma_i(v1(i)*v2(i)) ),
%   rispettivamente la riga i-esima di A e la colonna j-esima di B; il ciclo più interno, in "k", seleziona ogni elemento
%   di tali vettori



% ciclo WHILE : permette di ripetere un insieme di istruzioni per un numero di iterazioni condizionato dal
%                 soddisfacimento di una condizione di arresto
% 
% while <variabile> == <espressione>
%   <istruzioni ...>
% end
% 
% Questo costrutto è frequentemente utilizzato nel calcolo numerico, ad es. per l'implementazione di metodi iterativi (largamente
% utilizzati per la risoluzione di varie classi di problemi numerici), e cioè di metodi che, partendo da un'approssimazione iniziale 
% della soluzione esatta, la migliorano per incrementi successivi utilizzando un metodo di dimostrata convergenza.
% Esempio astratto :
% <assegnazione della soluzione approssimata iniziale>
% <assegnazione della soglia_1 e della soglia_2>
% <assegnazione dell'incremento della soluzione al valore "maxint">
% <assegnazione della distanza della soluzione approssimata dalla soluzione vera al valore "maxint">
% while (incremento della soluzione > soglia_1) oppure (distanza della soluzione approssimata dalla soluzione vera > soglia_2)
%   <calcolo dell'incremento alla soluzione approssimata>
%   <aggiornamento della soluzione approssimata>
%   <calcolo approssimato della distanza dalla soluzione esatta del problema>
% end



