{ File: opervett.pas }

{ Scopo: uso array unidimensionali
         parametri di tipo vettore in procedure e funzioni }

program OperazioniSuVettori;
{ Definisce un insieme di procedure e funzioni per eseguire le seguenti
  operazioni su vettori di reali a 3 componenti:

  - procedura per la lettura di un vettore da input
  - procedura per la stampa di un vettore in output
  - procedura che calcola una delle operazioni aritmetiche (somma, sottrazione,
    prodotto, divisione) tra due vettori, componente per componente
  - funzione  che calcola il modulo di un vettore
  - procedura che calcola il prodotto di un reale per un vettore
  - funzione  che calcola il prodotto scalare tra due vettori
  - procedura che calcola il prodotto vettore tra due vettori

  Realizza un'interfaccia utente che permette di attivare le procedure e
  funzioni.
}

const
  DIM = 3;

type
  TipoIndice  = 1..DIM;
  TipoVettore = array [TipoIndice] of real;

  TipoOperazioneBinaria    = (Somma, Sottrazione, Prodotto, Divisione,
                              ProdottoScalare, ProdottoVettore);
  TipoOperazioneAritmetica = Somma..Divisione;

var
  v1, v2, ris : TipoVettore;  { vettori su cui opera il programma principale }
  x           : real;         { valore reale usato per la moltiplicazione }
  ch          : char;         { carattere di scelta }
  i           : TipoIndice;   { indice dei cicli per l'inizializzazione dei
                                vettori v1 e v2 }


  procedure LeggiVettore (var vet: TipoVettore);
  { Restituisce in vet un vettore le cui componenti vengono lette in input. }
  var
    i : TipoIndice;

  begin { LeggiVettore }
    writeln('Immetti un vettore !');
    for i := 1 to DIM do
    begin
      write('Componente ', i, ' ? ');
      readln(vet[i])
    end;
  end; { LeggiVettore }


  procedure StampaVettore (vet: TipoVettore);
  { Stampa il vettore vet passato come parametro. }
  var
    i : TipoIndice;

  begin { StampaVettore }
    write('(');
    for i := 1 to DIM - 1 do
      write(vet[i]:6:2, ', ');
    write(vet[DIM]:6:2, ')')
  end; { StampaVettore }


  procedure AritmeticaVettori (vet1, vet2 : TipoVettore;
                               oper       : TipoOperazioneAritmetica;
                               var ris    : TipoVettore);
  { Restituisce in ris il vettore ottenuto applicando l'operazione aritmetica
    oper ai vettori vet1 e vet2, componente per componente. }
  var
    i : TipoIndice;

  begin { AritmeticaVettori }
    for i := 1 to DIM do
      case oper of
        Somma       : ris[i] := vet1[i] + vet2[i];
        Sottrazione : ris[i] := vet1[i] - vet2[i];
        Prodotto    : ris[i] := vet1[i] * vet2[i];
        Divisione   : ris[i] := vet1[i] / vet2[i];
      end
  end; { AritmeticaVettori }


  function ModuloVettore(vet: TipoVettore): real;
  { restitutisce il modulo del vettore vet. }
  var
    somma_quadrati : real;
    i              : TipoIndice;

  begin { ModuloVettore }
    somma_quadrati := 0;
    for i := 1 to DIM do
      somma_quadrati := somma_quadrati + sqr(vet[i]);
    ModuloVettore := sqrt(somma_quadrati)
  end; { ModuloVettore }


  procedure ProdottoRealePerVettore (vet     : TipoVettore;
                                     val     : real;
                                     var ris : TipoVettore);
  { Restituisce in ris il vettore prodotto di val per vet. }
  var
    i : TipoIndice;

  begin { ProdottoRealePerVettore }
    for i := 1 to DIM do
      ris[i] := val * vet[i]
  end; { ProdottoRealePerVettore }


  function ProdottoScalareVettori (vet1,vet2: TipoVettore): real;
  { Restituisce il prodotto scalare dei due vettori vet1 e vet2. }
  var
    somma : real;
    i     : TipoIndice;

  begin { ProdottoScalareVettori }
    somma := 0;
    for i := 1 to DIM do
      somma := somma + vet1[i] * vet2[i];
    ProdottoScalareVettori := somma
  end; { ProdottoScalareVettori }


  procedure ProdottoVettori (vet1, vet2 : TipoVettore;
                             var ris    : TipoVettore);
  { Restituisce in ris il prodotto vettore di vet1 e vet2. }
  var
    i : TipoIndice;

  begin { ProdottoVettori }
    for i := 1 to DIM do
      ris[i] := vet1[(i mod 3) + 1] * vet2[((i+1) mod 3) + 1] -
                vet1[((i+1) mod 3) + 1] * vet2[(i mod 3) + 1]
  end; { ProdottoVettori }


  procedure EseguiOperazioneBinaria(nome   : String;
                                    v1, v2 : TipoVettore;
                                    oper   : TipoOperazioneBinaria);
  var
    ris : TipoVettore;

  begin { EseguiOperazioneBinaria }
    write(nome, ' di ');
    StampaVettore(v1);
    write(' e ');
    StampaVettore(v2);
    writeln(':');
    case oper of
      Somma, Sottrazione, Prodotto, Divisione :
        begin
          AritmeticaVettori(v1, v2, oper, ris);
          StampaVettore(ris)
        end;
      ProdottoScalare : write(ProdottoScalareVettori(v1, v2):6:2);
      ProdottoVettore :
        begin
          ProdottoVettori(v1, v2, ris);
          StampaVettore(ris)
        end;
    end; { case }
    writeln
  end; { EseguiOperazioneBinaria }


begin  { OperazioniSuVettori }
  for i := 1 to DIM do
  begin
    v1[i] := 0;
    v2[i] := 0
  end;

  repeat
    writeln;
    writeln('*** IMMETTI UN CARATTERE A SCELTA FRA I SEGUENTI ***');
    writeln('***** 1: leggi il primo vettore');
    writeln('***** 2: leggi il secondo vettore');
    writeln('***** 3: stampa il primo vettore');
    writeln('***** 4: stampa il secondo vettore');
    writeln;
    writeln('***** a: somma i due vettori');
    writeln('***** b: sottrai il secondo vettore dal primo');
    writeln('***** c: moltiplica i due vettori');
    writeln('***** d: dividi il primo vettore per il secondo');
    writeln('***** e: calcola il modulo del primo vettore');
    writeln('***** f: calcola il prodotto del primo vettore per un reale');
    writeln('***** g: calcola il prodotto scalare dei due vettori');
    writeln('***** h: calcola il prodotto vettoriale dei due vettori');
    writeln;
    writeln('***** Q: per terminare il programma');
    writeln;
    readln(ch);  { ATTENZIONE: read NON va bene }

    case ch of
      '1'      : LeggiVettore(v1);
      '2'      : LeggiVettore(v2);
      '3'      : begin
                   write('Primo vettore: ');
                   StampaVettore(v1);
                   writeln
                 end;
      '4'      : begin
                   write('Secondo vettore: ');
                   StampaVettore(v2);
                   writeln
                 end;
      'a', 'A' : EseguiOperazioneBinaria('Somma', v1, v2, Somma);
      'b', 'B' : EseguiOperazioneBinaria('Sottrazione', v1, v2, Sottrazione);
      'c', 'C' : EseguiOperazioneBinaria('Prodotto', v1, v2, Prodotto);
      'd', 'D' : EseguiOperazioneBinaria('Divisione', v1, v2, Divisione);
      'e', 'E' : begin
                   write('Modulo di ');
                   StampaVettore(v1);
                   writeln(':');
                   writeln(ModuloVettore(v1):6:2)
                 end;
      'f', 'F' : begin
                   write('Valore reale ? ');
                   readln(x);
                   write('Prodotto di ', x:6:2, ' per ');
                   StampaVettore(v1);
                   writeln(': ');
                   ProdottoRealePerVettore(v1, x, ris);
                   StampaVettore(ris);
                   writeln
                 end;
      'g', 'G' : EseguiOperazioneBinaria('Prodotto scalare', v1, v2,
                                         ProdottoScalare);
      'h', 'H' : EseguiOperazioneBinaria('Prodotto vettore', v1, v2,
                                         ProdottoVettore);

      'q', 'Q' : writeln('CIAO :-)');
    end; { case }
  until (ch = 'Q') or (ch = 'q')
end. { OperazioniSuVettori }