package AlgLin;

public abstract class SysLin {
    // Attribut correspondant à la taille du système
    private int ordre;
    
    // Attribut correspondant à la matrice du système
    protected Matrice matriceSystem;
    
    // Attribut correspondant au second membre du système
    protected Vecteur secondMembre;
    
    // Constructeur
    public SysLin(Matrice matrice, Vecteur secondMembre) throws IrregularSysLinException {
        
        if (matrice.nbColonne() != secondMembre.taille()) {
            throw new IrregularSysLinException("La matrice du systeme n'est pas carré");
        }
        this.ordre = matrice.nbLigne();
        this.matriceSystem = matrice;
        this.secondMembre = secondMembre;
    }
    
    
    
    
    // Accesseur en lecture de l'attribut ordre
    public int getOrdre() {
        return this.ordre;
    }
    
    // Accesseur en lecture de l'attribut matriceSystem
    public Matrice getMatriceSystem() {
        return this.matriceSystem;
    }
    
    // Accesseur en lecture de l'attribut secondMembre
    public Vecteur getSecondMembre() {
        return this.secondMembre;
    }
    
    // Modifieur de l'attribut secondMembre
    public void setSecondMembre(Vecteur newSecondMembre) {
		secondMembre = newSecondMembre;
	}
    
    public abstract Vecteur resolution() throws IrregularSysLinException;
    
    // Méthode pour calculer (Ax - b), qu'utilisera toutes les classe filles de SysLin
    public Vecteur calculerAxMoinsB(Matrice a, Vecteur b, Vecteur x) {
    	
        // Création d'un vecteur contenant l'opposé du vecteur b
        Vecteur moinsb = new Vecteur(b.taille());
        for(int i = 0; i < moinsb.taille(); i++) {
            moinsb.remplacerCoefficient(i, -1 * b.getCoef(i));
        }
        
        // Calcul de Ax - b
        Matrice mat = Matrice.addition(Matrice.produit(a, x), moinsb);
        
        // Création d'une copie du résultat pour calculer sa norme
        Vecteur copie = new Vecteur(mat.nbLigne());
        for (int i = 0; i < copie.taille() ; i ++) {
            copie.remplacerCoefficient(i, mat.getCoef(i, 0));
        }
        return copie;
    }
    
    // Méthode pour vérifier la norme par rapport au seuil EPSILON
    public void verifierNorme(Matrice a, Vecteur b, Vecteur x) throws IrregularSysLinException {
        Vecteur copieTest = calculerAxMoinsB(a, b, x);
        
        // Calcul de la norme L1 du résultat et affichage
        double norme = copieTest.normeL1(); // somme des valeurs absolue de Ax-b
        //System.out.println("Norme L1 : " + norme);
        // Vérification de la norme par rapport au seuil EPSILON
        if(norme > Matrice.EPSILON) throw new IrregularSysLinException();
        
        // Calcul de la norme L2 du résultat et affichage
        norme = copieTest.normeL2(); // racine carre de la somme des carré de Ax-b
        //System.out.println("Norme L2 : " + norme);
        // Vérification de la norme par rapport au seuil EPSILON
        if(norme > Matrice.EPSILON) throw new IrregularSysLinException();
        
        // Calcul de la norme infinie du résultat et affichage
        norme = copieTest.normeLinfini(); // valeur absolue maximale des coeff
        //System.out.println("Norme Linfini : " + norme);
        // Vérification de la norme par rapport au seuil EPSILON
        if(norme > Matrice.EPSILON) throw new IrregularSysLinException();
        
        //System.out.println("Verfication terminé, c'est le bon résultat !");
    }

}
