// Programa de diagonalizacion por Jacobi
//con busqueda del mayor elemento fuera de la diagonal
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;
    
int main()
{
//Definir la matriz
    ifstream fin("datos4.dat");
    ofstream fout("res4.dat");
    int n;

//Leer dimension del sistema
    fin >> n;


//Leer matriz en datos4.dat;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            fin >> mat[i][j];

//Verificar lectura datos
    for (int i = 0; i < n; i++)
    {
        cout << endl;
        for (int j = 0; j < n; j++)
            cout << setw(nwide) << mat[i][j] << "   ";
    }
    cout << endl;

    jacobi(n, mat, vecp);

//Imprimir matriz diagonalizada

    cout << "Matriz diagonalizada" << endl;
    for (int i = 0; i < n; i++)
    {
        cout << endl;
        for (int j = 0; j < n; j++)
            cout << setw(nwide) << mat[i][j] << "   ";
    }
    cout << endl << endl;
//Imprimir valores propios

    fout << "Los valores propios son "<< endl;
    for (int i = 0; i < n; i++)
    {
        fout << endl;
        fout << mat[i][i] << "   ";
    }
    fout << endl << endl;
//Imprimir matriz vectores propios

    cout << "Vectores propios (columnas) " << endl;
    for (int i = 0; i < n; i++)
    {
        cout << endl;
        for (int j = 0; j < n; j++)
            cout << setw(nwide) << vecp[i][j] << "   ";
    }
    cout << endl << endl;
   
    fout << "Vectores propios (columnas) " << endl;
    for (int i = 0; i < n; i++)
    {
        fout << endl;
        for (int j = 0; j < n; j++)
            fout << setw(nwide) << vecp[i][j] << "   ";
    }
    fout << endl << endl;

//Comprobacion ortogonalidad vectores propios

    cout << "Productos escalares de vectores propios" << endl << endl;

    for (int i = 0; i < n; i++)
    {
        for (int j = i; j < n; j++)
        {
            double temp = 0;

            for (int k = 0; k < n; k++)
                temp = temp + vecp[k][i] * vecp[k][j];
            cout << setw(nwide) <<temp << "  ";
        }
        cout << endl;
    }
//Liberar memoria
    for (int j = 0; j < n; j++) delete[] mat[j];
    delete[] mat;
    delete[] vecp;
    mat = 0;
    vecp = 0;
    return 0;
}
