{ File: prodmat2.pas }

{ Scopo: lettura e scrittura di matrici da file }

program ProdottoMatrici;
{ Legge da file due matrici di dimensioni massime prefissate, ma di dimensioni
  effettive variabili e memorizzate nella prima riga del file, ne calcola la
  matrice prodotto e la salva su un terzo file, scrivendo nella prima riga le
  dimensioni effettive.
}

const
  MaxRighe   = 10;
  MaxColonne = 10;

type
  TipoIndiceRiga      = 1..MaxRighe;
  TipoIndiceColonna   = 1..MaxColonne;
  TipoElementoMatrice = integer;

  TipoArrayMatrice = array [TipoIndiceRiga, TipoIndiceColonna] of TipoElementoMatrice;
  TipoMatrice      = record
                       righe    : 0..MaxRighe;
                       colonne  : 0..MaxColonne;
                       elementi : TipoArrayMatrice
                     end;       

var
  m1, m2, mprod : TipoMatrice;
  i, j          : integer;


  procedure LeggiMatrice (var matrice: TipoMatrice);
  { Legge una matrice da file. }
  var
    nome : string;    { nome del file dal quale leggere la matrice }
    f    : text;      { file logico }
    i, j : integer;

  begin { LeggiMatrice }
    write('Nome del file dal quale leggere la matrice ? ');
    readln(nome);

    assign(f, nome);
    reset(f);

    with matrice do
    begin
      read(f, righe, colonne);
      for i := 1 to righe do
        for j := 1 to colonne do
          read(f, elementi[i,j])
    end;

    close(f)
  end; { LeggiMatrice }


  procedure SalvaMatrice (matrice: TipoMatrice);
  { Salva una matrice su file }
  var
    nome : string;    { nome del file dal quale leggere la matrice }
    f    : text;      { file logico }
    i, j : integer;

  begin { SalvaMatrice }
    write('Nome del file sul quale scrivere la matrice ? ');
    readln(nome);

    assign(f, nome);
    rewrite(f);

    with matrice do
    begin
      writeln(f, righe, ' ', colonne);
      for i := 1 to righe do
      begin
        for j := 1 to colonne do
          write(f, elementi[i,j]:7);
        writeln(f)
      end
    end;

    close(f);
  end; { SalvaMatrice }


  procedure StampaMatrice (matrice: TipoMatrice);
  { Stampa una matrice su video. }
  var
    i, j : integer;

  begin { StampaMatrice }
    with matrice do
      for i := 1 to righe do
      begin
        for j := 1 to colonne do
          write(elementi[i,j]:7);
        writeln
      end;
    writeln
  end; { StampaMatrice }


  procedure MoltiplicaMatrici (matrice1, matrice2: TipoMatrice;
                               var matrice_prod: TipoMatrice);
  { Moltiplicazione fra matrici quadrate. }
  var
    i, j, k : integer;
  begin { MoltiplicaMatrici }
    if matrice1.colonne = matrice2.righe then
    begin
      matrice_prod.righe := matrice1.righe;
      matrice_prod.colonne := matrice2.colonne;
      for i := 1 to matrice_prod.righe do
        for j := 1 to matrice_prod.colonne do
        begin
          matrice_prod.elementi[i,j] := 0;
          for k := 1 to matrice1.colonne do
            matrice_prod.elementi[i,j] := matrice_prod.elementi[i,j] +
                             matrice1.elementi[i,k] * matrice2.elementi[k,j]
        end
    end
    else
    begin
      writeln('Errore. Le matrici sono di dimensioni incompatibili');
      matrice_prod.righe := 0;
      matrice_prod.colonne := 0
    end
  end; { MoltiplicaMatrici }


begin { ProdottoMatrici }
  LeggiMatrice(m1);                     { lettura della prima matrice }
  writeln('Matrice 1:');
  StampaMatrice(m1);                    { stampa di verifica su video }

  LeggiMatrice(m2);                     { lettura della seconda matrice }
  writeln('Matrice 2:');
  StampaMatrice(m2);                    { stampa di verifica su video }

  MoltiplicaMatrici(m1, m2, mprod);     { calcolo della matrice prodotto }
  writeln('Matrice prodotto:');

  StampaMatrice(mprod);                 { stampa di verifica su video }
  SalvaMatrice(mprod)                   { salvataggio su file }
end. { ProdottoMatrici }