2276 lines
78 KiB
C++
2276 lines
78 KiB
C++
// FICHIER : Mat_pleine.cc
|
|
// CLASSE : Mat_pleine
|
|
|
|
// This file is part of the Herezh++ application.
|
|
//
|
|
// The finite element software Herezh++ is dedicated to the field
|
|
// of mechanics for large transformations of solid structures.
|
|
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
|
|
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
|
|
//
|
|
// Herezh++ is distributed under GPL 3 license ou ultérieure.
|
|
//
|
|
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
|
|
// AUTHOR : Gérard Rio
|
|
// E-MAIL : gerardrio56@free.fr
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// For more information, please consult: <https://herezh.irdl.fr/>.
|
|
|
|
|
|
//#include "Debug.h"
|
|
|
|
# include <iostream>
|
|
using namespace std; //introduces namespace std
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include "Sortie.h"
|
|
#include "ConstMath.h"
|
|
#include "MathUtil.h"
|
|
#include "Mat_pleine.h"
|
|
#include "MatDiag.h"
|
|
#include "ParaGlob.h"
|
|
|
|
#ifndef Mat_pleine_H_deja_inclus
|
|
|
|
// Constructeur par defaut
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine::Mat_pleine ():
|
|
Mat_abstraite(RECTANGLE,CHOLESKY,RIEN_PRECONDITIONNEMENT)
|
|
,val_de_base(),val()
|
|
{ };
|
|
|
|
// Constructeur utile quand les dimensions de la matrice sont connues
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine::Mat_pleine (int nb_ligne,int nb_colonne,double val_init):
|
|
Mat_abstraite(RECTANGLE,CHOLESKY,RIEN_PRECONDITIONNEMENT)
|
|
,val_de_base(nb_ligne*nb_colonne)
|
|
{ if (nb_ligne == nb_colonne)
|
|
{type_matrice = CARREE;
|
|
if (nb_ligne < 4) // par défaut pour de petite matrice on utilise cramer
|
|
type_resolution = CRAMER;
|
|
};
|
|
Creation_tab_val(nb_ligne,nb_colonne);
|
|
Initialise(val_init);
|
|
|
|
// Initialise(nb_ligne,nb_colonne,val_init);
|
|
};
|
|
|
|
// Constructeur de copie
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine::Mat_pleine (const Mat_pleine& mat_pl) :
|
|
Mat_abstraite(mat_pl),val_de_base(mat_pl.val_de_base)
|
|
{Creation_tab_val(mat_pl.Nb_ligne(),mat_pl.Nb_colonne());
|
|
};
|
|
|
|
/// --------- cas très particulier d'un vecteur val_de_base lié
|
|
/// --------- utilisé uniquement par des classes friend
|
|
// c-a-d qui ne gère pas sa mémoire -> memoire = false
|
|
/// il s'agit d'un tuillage, val_de_base est positionné a "vec"
|
|
/// aucun test n'est fait concernant la taille disponible à partir de "vec"
|
|
/// routine dangereuse !!!!!
|
|
/// avec_recopie == true : les infos de mat_pl sont recopiées, sinon non
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine::Mat_pleine(bool avec_recopie,double* vec, const Mat_pleine& mat_pl) :
|
|
Mat_abstraite(mat_pl),val_de_base(mat_pl.val_de_base.Taille(),vec,false)
|
|
{Creation_tab_val(mat_pl.Nb_ligne(),mat_pl.Nb_colonne());
|
|
if (avec_recopie)
|
|
val_de_base = mat_pl.val_de_base;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine::~Mat_pleine ()
|
|
// Destructeur
|
|
{ // val_de_base est automatiquement détruit
|
|
int nb_ligne = val.Taille();
|
|
for (int i =1;i<=nb_ligne;i++)
|
|
delete val(i); // en fait ne fait pas grand chose !! car il s'agit
|
|
// de vecteurs liés, on pourrait zapper !
|
|
};
|
|
|
|
|
|
// fonction permettant de creer une nouvelle instance d'element
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_abstraite * Mat_pleine::NouvelElement() const
|
|
{ Mat_abstraite * a;
|
|
a = new Mat_pleine(*this);
|
|
return a;
|
|
};
|
|
|
|
// surcharge de l'opérateur d'affectation: cas des matrices abstraites
|
|
// il y a ajustement automatique de taille de la matrice en fonction de mat_pl
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_abstraite & Mat_pleine::operator = ( const Mat_abstraite & b)
|
|
{
|
|
// #ifdef MISE_AU_POINT
|
|
// dans le cas où les matrices ne sont pas de caractéristiques identiques
|
|
// il y a un message d'erreur
|
|
if (type_matrice != b.Type_matrice())
|
|
{cout << "erreur dans l'operation d'affectation";
|
|
cout << " les matrices sont de types différents "
|
|
<< Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n';
|
|
cout << "Mat_pleine::operator = ( const Mat_abstraite & b)" << endl;
|
|
Sortie(1);
|
|
};
|
|
// #endif
|
|
const Mat_pleine & mat_pl = *((Mat_pleine*) & b);
|
|
// et on affecte entre matrices Mat_pleine
|
|
*this = mat_pl;
|
|
|
|
// if ( val.Taille() != 0 )
|
|
// // cas ou la matrice se trouvant a gauche du signe = n'est pas vide
|
|
// {
|
|
// Libere(); // desallocation de ce vecteur
|
|
// };
|
|
// // traitement----
|
|
// // cas ou la matrice se trouvant a droite du signe = est vide
|
|
// // on a rien a faire car de toute manière la matrice this viens d'être
|
|
// // supprimé dans le cas où elle était non nul
|
|
// if ( mat_pl.Nb_ligne()!=0 )
|
|
// // autres cas
|
|
// {
|
|
// int taill_ligne = mat_pl.Nb_ligne();
|
|
// val.Change_taille(taill_ligne);
|
|
// for (int i=1;i<=taill_ligne;i++)
|
|
// // affectation de la ieme ligne de la matrice mat_pl a la ieme ligne
|
|
// // de la matrice courante
|
|
// val(i)=mat_pl(i);
|
|
// };
|
|
return (*this);
|
|
};
|
|
|
|
// transfert des informations de *this dans la matrice passée en paramètre
|
|
// la matrice paramètre est au préalable, mise à 0.
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Transfert_vers_mat( Mat_abstraite & b )
|
|
{b.Initialise(0.); // init de la matrice
|
|
// puis on transfert
|
|
int nb_ligne = val.Taille();
|
|
int nb_col = Nb_colonne();
|
|
for (int i=1;i<=nb_ligne;i++)
|
|
{ Vecteur& vee = *(val(i));
|
|
for (int j=1;j<= nb_col; j++)
|
|
b(i,j)=vee(j);
|
|
};
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine& Mat_pleine::operator= ( const Mat_pleine& mat_pl)
|
|
// Surcharge de l'operateur = : affectation d'une matrice a une autre
|
|
// il y a ajustement automatique de taille de la matrice en fonction de mat_pl
|
|
{ if (val_de_base.Taille() == mat_pl.val_de_base.Taille())
|
|
// l'ensemble à la même taille, on regarde le nombre de colonne
|
|
{if (mat_pl.Nb_ligne() != val.Taille())
|
|
// on a la même taille globale mais pas le même nombre de ligne
|
|
// il faut changer le tableau des lignes
|
|
{Change_tailles_tab_val(mat_pl.Nb_ligne(),mat_pl.Nb_colonne());
|
|
};
|
|
// sinon on ne fait rien car tout est ok
|
|
}
|
|
else // cas ou val_de_base n'a pas la bonne taille
|
|
// on réaffecte
|
|
{ val_de_base.Change_taille(mat_pl.val_de_base.Taille());
|
|
// on change le tableau val des vecteurs liés
|
|
Change_tailles_tab_val(mat_pl.Nb_ligne(),mat_pl.Nb_colonne());
|
|
};
|
|
// toutes les tailles sont ok on peut affecter globalement
|
|
val_de_base = mat_pl.val_de_base;
|
|
|
|
//if ( val.Taille() != 0 )
|
|
// // cas ou la matrice se trouvant a gauche du signe = n'est pas vide
|
|
// {
|
|
// Libere(); // desallocation de ce vecteur
|
|
// };
|
|
// // traitement----
|
|
// // cas ou la matrice se trouvant a droite du signe = est vide
|
|
// // on a rien a faire car de toute manière la matrice this viens d'être
|
|
// // supprimé dans le cas où elle était non nul
|
|
// if ( mat_pl.Nb_ligne()!=0 )
|
|
// // autres cas
|
|
// {
|
|
// int taill_ligne = mat_pl.Nb_ligne();
|
|
// val.Change_taille(taill_ligne);
|
|
// for (int i=1;i<=taill_ligne;i++)
|
|
// // affectation de la ieme ligne de la matrice mat_pl a la ieme ligne
|
|
// // de la matrice courante
|
|
// val(i)=mat_pl(i);
|
|
// };
|
|
return (*this);
|
|
};
|
|
|
|
// Surcharge de l'operateur += : addition d'une matrice a la matrice courante
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::operator+= (const Mat_abstraite& b)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où les matrices ne sont pas de caractéristiques identiques
|
|
// il y a un message d'erreur
|
|
if ((type_matrice != b.Type_matrice())&&(b.Type_matrice() != DIAGONALE))
|
|
{cout << " erreur les matrices sont de types differents "
|
|
<< Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n';
|
|
cout << "Mat_pleine::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
// si les tailles ne sont pas identique pb
|
|
if (this->Nb_ligne() != b.Nb_ligne())
|
|
{cout << " les matrices ont un nombre de ligne different "
|
|
<< this->Nb_ligne() << " " << b.Nb_ligne() << '\n';
|
|
cout << "Mat_pleine::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
// on ne vérifie pas le nombre de colonne pour les matrices diagonales
|
|
if ((this->Nb_colonne() != b.Nb_colonne())&&(b.Type_matrice() != DIAGONALE))
|
|
{cout << " les matrices ont un nombre de ligne different "
|
|
<< this->Nb_colonne() << " " << b.Nb_colonne() << '\n';
|
|
cout << "Mat_pleine::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
if (b.Type_matrice() != DIAGONALE)
|
|
{ const Mat_pleine & mat_pl = *((Mat_pleine*) & b);
|
|
this->operator+= (mat_pl);
|
|
}
|
|
else // cas d'une matrice argument diagonale
|
|
{ int nb_lign = val.Taille();
|
|
const MatDiag & mat_d = *((MatDiag*) & b);
|
|
for (int i=1;i<=nb_lign;i++)
|
|
(*this)(i,i) += mat_d(i,i);
|
|
}
|
|
|
|
};
|
|
// Surcharge de l'operateur -= : soustraction d'une matrice a la matrice courante
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::operator-= (const Mat_abstraite& b)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où les matrices ne sont pas de caractéristiques identiques
|
|
// il y a un message d'erreur
|
|
if ((type_matrice != b.Type_matrice())&&(b.Type_matrice() != DIAGONALE))
|
|
{cout << " erreur les matrices sont de types différents "
|
|
<< Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n';
|
|
cout << "Mat_pleine::operator-= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
// si les tailles ne sont pas identique pb
|
|
if (this->Nb_ligne() != b.Nb_ligne())
|
|
{cout << " les matrices ont un nombre de ligne différent "
|
|
<< this->Nb_ligne() << " " << b.Nb_ligne() << '\n';
|
|
cout << "Mat_pleine::operator-= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
// on ne vérifie pas le nombre de colonne pour les matrices diagonales
|
|
if ((this->Nb_colonne() != b.Nb_colonne())&&(b.Type_matrice() != DIAGONALE))
|
|
{cout << " les matrices ont un nombre de ligne différent "
|
|
<< this->Nb_colonne() << " " << b.Nb_colonne() << '\n';
|
|
cout << "Mat_pleine::operator-= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
if (b.Type_matrice() != DIAGONALE)
|
|
{ const Mat_pleine & mat_pl = *((Mat_pleine*) & b);
|
|
this->operator-= (mat_pl);
|
|
}
|
|
else // cas d'une matrice argument diagonale
|
|
{ int nb_lign = val.Taille();
|
|
const MatDiag & mat_d = *((MatDiag*) & b);
|
|
for (int i=1;i<=nb_lign;i++)
|
|
(*this)(i,i) -= mat_d(i,i);
|
|
}
|
|
};
|
|
|
|
// Surcharge de l'operateur == : test d'egalite entre deux matrices
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
int Mat_pleine::operator== (const Mat_abstraite& b) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
// dans le cas où les matrices ne sont pas de caractéristiques identiques
|
|
// il y a un message d'erreur
|
|
if (type_matrice != b.Type_matrice())
|
|
{cout << " erreur les matrices sont de types différents "
|
|
<< Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n';
|
|
cout << "Mat_pleine::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
const Mat_pleine & mat_pl = *((Mat_pleine*) & b);
|
|
#ifdef MISE_AU_POINT
|
|
// si les tailles ne sont pas identique pb
|
|
if (this->Nb_ligne() != b.Nb_ligne())
|
|
{cout << " les matrices ont un nombre de ligne différent "
|
|
<< this->Nb_ligne() << " " << b.Nb_ligne() << '\n';
|
|
cout << "Mat_pleine::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (this->Nb_colonne() != b.Nb_colonne())
|
|
{cout << " les matrices ont un nombre de ligne différent "
|
|
<< this->Nb_colonne() << " " << b.Nb_colonne() << '\n';
|
|
cout << "Mat_pleine::operator+= (const Mat_abstraite& b)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
return this->operator==(mat_pl);
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Affiche () const
|
|
// Affiche les donnees de la matrice : dimensions, composantes
|
|
{int nbligne = Nb_ligne();
|
|
int nbcol = Nb_colonne();
|
|
cout << "\tNombre de lignes : " << nbligne ; //<< "\n";
|
|
cout << "\tNombre de colonnes : " << nbcol << "\n";
|
|
|
|
// for (int i=1;i<=nbligne;i++)
|
|
// {
|
|
// cout << "Ligne " << i << " :\t{\t";
|
|
// for (int j=1;j<=nbcol;j++)
|
|
// cout << (*this)(i,j) << "\t";
|
|
// if (i!= nbligne) {cout << "}\n";}
|
|
// else {cout << "}";}
|
|
// };
|
|
|
|
int i,j;
|
|
cout << " ";
|
|
for (j=1;j<=nbcol;j++) cout << "col " << setw(4) << j << " " ;
|
|
cout << '\n';
|
|
for (i=1;i<=nbligne;i++)
|
|
{ cout << "lig " << setw(4) << i << " * ";
|
|
for (j=1;j<=nbcol;j++)
|
|
cout << setw(14) << setprecision(7) << (*this)(i,j);
|
|
cout << '\n';
|
|
}
|
|
cout << endl;
|
|
};
|
|
|
|
//#ifndef MISE_AU_POINT
|
|
// inline
|
|
//#endif
|
|
//void Mat_pleine::Initialise (double val_init)
|
|
//// Initialise les composantes de la matrice a val_init
|
|
//{ int nb_ligne = val.Taille();
|
|
// int nb_col = Nb_colonne();
|
|
// for (int i=1;i<=nb_ligne;i++)
|
|
// // initialisation des composantes de la matrice a val_init
|
|
// for (int j=1;j<=nb_col;j++)
|
|
// (*this)(i,j)=val_init;
|
|
//};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Initialise (int nb_ligne,int nb_colonne,double val_init)
|
|
// Initialise les composantes de la matrice de nombre de ligne nb_ligne
|
|
// et de nombre de colonne nb_colonne a val_init
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if ( (nb_ligne<0) || (nb_colonne<0) )
|
|
{ cout << "Erreur sur les dimensions de la matrice !\n";
|
|
cout << "MAT_PLEINE::MAT_PLEINE (int ,int ,double )\n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
int taille_glob = nb_ligne * nb_colonne;
|
|
// changement de taille éventuelle
|
|
val_de_base.Change_taille(taille_glob);
|
|
Change_tailles_tab_val(nb_ligne,nb_colonne);
|
|
// initialisation globalle
|
|
val_de_base.Inita(val_init);
|
|
//
|
|
//
|
|
// val.Change_taille(nb_ligne);
|
|
// for (int i=1;i<=nb_ligne;i++)
|
|
// val(i).Change_taille(nb_colonne);
|
|
// for (int i=1;i<=nb_ligne;i++)
|
|
// // initialisation des composantes de la matrice a val_init
|
|
// for (int j=1;j<=nb_colonne;j++)
|
|
// (*this)(i,j)=val_init;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
int Mat_pleine::Symetrie () const
|
|
// Test sur la symetrie de la matrice
|
|
// Retourne 1 si la matrice est symetrique
|
|
// 0 sinon
|
|
{if ( Nb_ligne()!=Nb_colonne() )
|
|
return 0;
|
|
int nb_lign = val.Taille();
|
|
for (int i=1;i<=nb_lign;i++)
|
|
for (int j=1;j<i;j++)
|
|
// if ( (*this)(i,j)!=(*this)(j,i) ) // test d'egalite de la ieme jieme composante
|
|
if ( diffpetit((*this)(i,j),(*this)(j,i))) // test d'egalite de la ieme jieme composante
|
|
{
|
|
// affichage -- débug
|
|
// cout << " ("<<i<<","<<j<<") et ("<<j<<","<<i<<") = "<<(*this)(i,j)<<" "<< (*this)(j,i)<<", " << endl;
|
|
// fin affichage -- débug
|
|
return 0;
|
|
};
|
|
return 1;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// affiche les termes non symétriques de la matrice s'il y en a
|
|
void Mat_pleine::AfficheNonSymetries() const
|
|
{ int nb_lign = val.Taille();
|
|
cout << "\n affichage des termes non symetriques de la matrice: ";
|
|
for (int i=1;i<=nb_lign;i++)
|
|
for (int j=1;j<i;j++)
|
|
if ( diffpetit((*this)(i,j),(*this)(j,i))) // test d'egalite de la ieme jieme composante
|
|
cout << " ("<<i<<","<<j<<") et ("<<j<<","<<i<<") = "<<(*this)(i,j)<<" "<< (*this)(j,i)<<", ";
|
|
};
|
|
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur Mat_pleine::Resol_syst
|
|
(const Vecteur& b,const double &tole, const int maxi, const int rest)
|
|
// Resolution du systeme Ax=b
|
|
// N.B. : dans le cas de la methode de Cholesky, aucun test n'est realise
|
|
// pour verifier que la matrice A est definie positive ( condition necessaire a
|
|
// l'utilisation de la methode de Cholesky )
|
|
// La matrice est decomposee de la facon suivante : A=B.Bt
|
|
// ou :
|
|
// B : matrice triangulaire inferieure reguliere
|
|
// Bt: transposee de la matrice B ( triangulaire superieure )
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
switch (type_resolution)
|
|
{case CHOLESKY:
|
|
// si c'est cholesky normal, il faut une matrice symétrique
|
|
if ( !(*this).Symetrie() )
|
|
{ if (ParaGlob::NiveauImpression() > 2)
|
|
{ cout << "\n warning : attention ne fonctionne qu'avec une matrice symetrique !"
|
|
<< " ce qui n'est pas le cas ici !! "
|
|
<< "\n on utilise ici le triangle inferieure pour la resolution ! \n";
|
|
cout << "MAT_PLEINE::RESOL_SYST (const Vecteur& )\n";
|
|
AfficheNonSymetries();
|
|
};
|
|
};
|
|
// de plus si c'est cramer ou cholesky après symétrisation, on doit avoir une matrice carrée
|
|
case CRAMER : case SYMETRISATION_PUIS_CHOLESKY :
|
|
if ( Nb_ligne()!=Nb_colonne() )
|
|
{ cout << "Erreur : la matrice doit etre carree !\n";
|
|
cout << "MAT_PLEINE::RESOL_SYST (const Vecteur& )\n";
|
|
Sortie(1);
|
|
};
|
|
break;
|
|
default: break;// rien
|
|
}
|
|
#endif
|
|
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case SYMETRISATION_PUIS_CHOLESKY:
|
|
Symetrisation(); // on commence par symétriser
|
|
case CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Vecteur resul(N); // Vecteur solution
|
|
Mat_pleine B(N,N); // B est une matrice triangulaire
|
|
// inferieure reguliere
|
|
Triangulation (N,B);
|
|
Resolution (N,B,b,resul);
|
|
return resul;
|
|
break;
|
|
}
|
|
case CRAMER:
|
|
{ Vecteur resul(b);Cramer(b,resul);
|
|
return resul;
|
|
break;
|
|
}
|
|
default:
|
|
{ Vecteur resul(b);
|
|
Mat_abstraite::Resolution_syst(b,resul,tole,maxi,rest);
|
|
return resul;
|
|
};
|
|
};
|
|
};
|
|
|
|
//2) avec en sortie le vecteur d'entree
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur& Mat_pleine::Resol_systID
|
|
(Vecteur& b,const double &tole, const int maxi, const int rest)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
switch (type_resolution)
|
|
{case CHOLESKY:
|
|
// si c'est cholesky normal, il faut une matrice symétrique
|
|
if ( !(*this).Symetrie() )
|
|
{ if (ParaGlob::NiveauImpression() > 2)
|
|
{ cout << "\n warning : attention ne fonction qu'avec une matrice symetrique !"
|
|
<< " ce qui n'est pas le cas ici !!"
|
|
<< "\n on utilise ici le triangle inferieure pour la resolution ! \n";
|
|
cout << "MAT_PLEINE::RESOL_SYST ( Vecteur& )\n";
|
|
AfficheNonSymetries();
|
|
};
|
|
};
|
|
// de plus si c'est cramer ou cholesky après symétrisation, on doit avoir une matrice carrée
|
|
case CRAMER : case SYMETRISATION_PUIS_CHOLESKY :
|
|
if ( Nb_ligne()!=Nb_colonne() )
|
|
{ cout << "Erreur : la matrice doit etre carree !\n";
|
|
cout << "MAT_PLEINE::RESOL_SYST ( Vecteur& )\n";
|
|
Sortie(1);
|
|
};
|
|
break;
|
|
default: break;// rien
|
|
};
|
|
#endif
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case SYMETRISATION_PUIS_CHOLESKY:
|
|
Symetrisation(); // on commence par symétriser
|
|
case CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Mat_pleine B(N,N); // B est une matrice triangulaire
|
|
// inferieure reguliere
|
|
Triangulation (N,B);
|
|
Resolution (N,B,b,b);
|
|
break;
|
|
}
|
|
case CRAMER:
|
|
{ Cramer(b,b);
|
|
break;
|
|
}
|
|
default:
|
|
{ Vecteur bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest);
|
|
b = bb;
|
|
}
|
|
};
|
|
// retour
|
|
return b;
|
|
};
|
|
|
|
//3) avec en entrée un tableau de vecteur second membre et
|
|
// en sortie un nouveau tableau de vecteurs
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Vecteur> Mat_pleine::Resol_syst
|
|
(const Tableau <Vecteur>& b,const double &tole, const int maxi, const int rest)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
switch (type_resolution)
|
|
{case CHOLESKY:
|
|
// si c'est cholesky normal, il faut une matrice symétrique
|
|
if ( !(*this).Symetrie() )
|
|
{ if (ParaGlob::NiveauImpression() > 2)
|
|
{ cout << "\n warning : attention ne fonction qu'avec une matrice symetrique !"
|
|
<< " ce qui n'est pas le cas ici !!"
|
|
<< "\n on utilise ici le triangle inferieure pour la resolution ! \n";
|
|
cout << "MAT_PLEINE::RESOL_SYST ( const Tableau <Vecteur>..)\n";
|
|
AfficheNonSymetries();
|
|
};
|
|
};
|
|
// de plus si c'est cramer ou cholesky après symétrisation, on doit avoir une matrice carrée
|
|
case CRAMER : case SYMETRISATION_PUIS_CHOLESKY :
|
|
if ( Nb_ligne()!=Nb_colonne() )
|
|
{ cout << "Erreur : la matrice doit etre carree !\n";
|
|
cout << "MAT_PLEINE::RESOL_SYST ( const Tableau <Vecteur>..)\n";
|
|
Sortie(1);
|
|
};
|
|
break;
|
|
default: break;// rien
|
|
}
|
|
#endif
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case SYMETRISATION_PUIS_CHOLESKY:
|
|
Symetrisation(); // on commence par symétriser
|
|
case CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Mat_pleine B(N,N); // B est une matrice triangulaire
|
|
// inferieure reguliere
|
|
Triangulation (N,B);
|
|
int dimtab = b.Taille();
|
|
Tableau <Vecteur> c(dimtab);
|
|
for (int i=1;i<= dimtab;i++)
|
|
{ c(i).Change_taille(b(i).Taille());
|
|
Resolution (N,B,b(i),c(i));
|
|
};
|
|
return c;
|
|
break;
|
|
}
|
|
case CRAMER:
|
|
{int dimtab = b.Taille();
|
|
Tableau <Vecteur> c(dimtab);
|
|
Cramer(b,c);
|
|
return c;
|
|
break;
|
|
}
|
|
default:
|
|
{Tableau <Vecteur> bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest);
|
|
return bb;
|
|
}
|
|
}
|
|
};
|
|
|
|
//4) avec en entrée un tableau de vecteur second membre et
|
|
// en sortie le tableau de vecteurs d'entree
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Vecteur>& Mat_pleine::Resol_systID
|
|
(Tableau <Vecteur>& b,const double &tole, const int maxi, const int rest)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
switch (type_resolution)
|
|
{case CHOLESKY:
|
|
// si c'est cholesky normal, il faut une matrice symétrique
|
|
if ( !(*this).Symetrie() )
|
|
{ if (ParaGlob::NiveauImpression() > 2)
|
|
{ cout << "\n warning : attention ne fonction qu'avec une matrice symetrique !"
|
|
<< " ce qui n'est pas le cas ici !!"
|
|
<< "\n on utilise ici le triangle inferieure pour la resolution ! \n";
|
|
cout << "MAT_PLEINE::RESOL_SYST ( Tableau <Vecteur>..)\n";
|
|
AfficheNonSymetries();
|
|
};
|
|
};
|
|
// de plus si c'est cramer ou cholesky après symétrisation, on doit avoir une matrice carrée
|
|
case CRAMER : case SYMETRISATION_PUIS_CHOLESKY :
|
|
if ( Nb_ligne()!=Nb_colonne() )
|
|
{ cout << "Erreur : la matrice doit etre carree !\n";
|
|
cout << "MAT_PLEINE::RESOL_SYST ( Tableau <Vecteur>..)\n";
|
|
Sortie(1);
|
|
};
|
|
default: break; // sinon pas de pb ici
|
|
};
|
|
#endif
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case SYMETRISATION_PUIS_CHOLESKY:
|
|
Symetrisation(); // on commence par symétriser
|
|
case CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Mat_pleine B(N,N); // B est une matrice triangulaire
|
|
// inferieure reguliere
|
|
Triangulation (N,B);
|
|
int dimtab = b.Taille();
|
|
for (int i=1;i<= dimtab;i++)
|
|
Resolution (N,B,b(i),b(i));
|
|
break;
|
|
}
|
|
case CRAMER:
|
|
{Cramer (b,b);
|
|
break;
|
|
}
|
|
default:
|
|
{Tableau <Vecteur> bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest);
|
|
b = bb;
|
|
}
|
|
};
|
|
return b;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur Mat_pleine::Prod_vec_mat (const Vecteur& vec) const
|
|
// Realise le produit du vecteur vec par la matrice
|
|
{ Vecteur result(Nb_colonne());
|
|
#ifdef MISE_AU_POINT
|
|
if (vec.Taille() != Colonne(1).Taille())
|
|
{cout << "erreur de taille, la première colonne de la matrice n'a pas la même dimension";
|
|
cout << " que le vecteur à multiplier "
|
|
<< "\n Mat_pleine::Prod_vec_mat (const Vecteur& vec)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int nb_col = Nb_colonne();
|
|
for (int j=1;j<=nb_col;j++)
|
|
result(j)=Colonne(j)*vec;
|
|
return result;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur& Mat_pleine::Prod_vec_mat (const Vecteur& vec,Vecteur& result) const
|
|
// Realise le produit du vecteur vec par la matrice
|
|
// ici on se sert du second vecteur pour le résultat
|
|
{ result.Change_taille(Nb_colonne());
|
|
#ifdef MISE_AU_POINT
|
|
if (vec.Taille() != Colonne(1).Taille())
|
|
{cout << "erreur de taille, la première colonne de la matrice n'a pas la même dimension";
|
|
cout << " que le vecteur à multiplier "
|
|
<< "\n Mat_pleine::Prod_vec_mat (const Vecteur& vec,Vecteur& res)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int nb_col = Nb_colonne();
|
|
for (int j=1;j<=nb_col;j++)
|
|
result(j)=Colonne(j)*vec;
|
|
return result;
|
|
};
|
|
|
|
//5) avec en sortie le dernier vecteur d'entree, le premier étant le second membre
|
|
// et restant inchangé, en sortie c'est donc soit le retour ou soit vortie, les
|
|
// deux étant identiques
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur& Mat_pleine::Resol_systID_2 (const Vecteur& b,Vecteur& vortie
|
|
, const double &tole,const int maxi,const int rest)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
switch (type_resolution)
|
|
{case CHOLESKY:
|
|
// si c'est cholesky normal, il faut une matrice symétrique
|
|
if ( !(*this).Symetrie() )
|
|
{ if (ParaGlob::NiveauImpression() > 2)
|
|
{ cout << "\n warning : attention ne fonction qu'avec une matrice symetrique !"
|
|
<< " ce qui n'est pas le cas ici !!"
|
|
<< "\n on utilise ici le triangle inferieure pour la resolution ! \n";
|
|
cout << "Mat_pleine::Resol_systID_2 (...\n";
|
|
AfficheNonSymetries();
|
|
};
|
|
};
|
|
// de plus si c'est cramer ou cholesky après symétrisation, on doit avoir une matrice carrée
|
|
case CRAMER : case SYMETRISATION_PUIS_CHOLESKY :
|
|
if ( Nb_ligne()!=Nb_colonne() )
|
|
{ cout << "Erreur : la matrice doit etre carree !\n";
|
|
cout << "Mat_pleine::Resol_systID_2 (...\n";
|
|
Sortie(1);
|
|
};
|
|
default: break; // sinon pas de pb ici
|
|
}
|
|
#endif
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case SYMETRISATION_PUIS_CHOLESKY:
|
|
Symetrisation(); // on commence par symétriser
|
|
case CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Mat_pleine B(*this); // B est une matrice triangulaire
|
|
// inferieure reguliere
|
|
Triangulation (N,B);
|
|
Resolution (N,B,b,vortie);
|
|
return vortie;
|
|
break;
|
|
}
|
|
case CRAMER:
|
|
{Cramer(b,vortie); return vortie; break;
|
|
}
|
|
default:
|
|
{Mat_abstraite::Resolution_syst(b,vortie,tole,maxi,rest);
|
|
return vortie;
|
|
}
|
|
};
|
|
};
|
|
|
|
// ===== RÉSOLUTION EN DEUX TEMPS ================ :
|
|
// 1) préparation de la matrice donc modification de la matrice éventuellement
|
|
// par exemple pour les matrices bandes avec cholesky : triangulation
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Preparation_resol()
|
|
{
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
#ifdef MISE_AU_POINT
|
|
switch (type_resolution_en_pratique)
|
|
{case CHOLESKY:
|
|
{// si c'est cholesky normal, il faut une matrice symétrique
|
|
if ( !(*this).Symetrie() )
|
|
{ if (ParaGlob::NiveauImpression() > 2)
|
|
{ cout << "\n warning : attention ne fonction qu'avec une matrice symetrique !"
|
|
<< " ce qui n'est pas le cas ici !!"
|
|
<< "\n on utilise ici le triangle inferieure pour la resolution ! \n";
|
|
cout << "Mat_pleine::Preparation_resol() \n";
|
|
AfficheNonSymetries();
|
|
};
|
|
};
|
|
}
|
|
// de plus si c'est cramer ou cholesky après symétrisation, on doit avoir une matrice carrée
|
|
case CRAMER : case SYMETRISATION_PUIS_CHOLESKY :
|
|
{if ( Nb_ligne()!=Nb_colonne() )
|
|
{ cout << "Erreur : la matrice doit etre carree !\n";
|
|
cout << "Mat_pleine::Preparation_resol() \n";
|
|
Sortie(1);
|
|
};
|
|
}
|
|
default: break; // sinon ok ici
|
|
};
|
|
#endif
|
|
// dans le cas de cholesky on triangule
|
|
switch (type_resolution_en_pratique)
|
|
{case SYMETRISATION_PUIS_CHOLESKY:
|
|
Symetrisation(); // on commence par symétriser
|
|
case CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Triangulation (N,*this);
|
|
}
|
|
default: break; // sinon ok ici
|
|
};
|
|
};
|
|
// 2) *** résolution sans modification de la matrice DOIT ÊTRE PRÉCÉDÉ DE L'APPEL DE
|
|
// Preparation_resol
|
|
// a) avec en sortie un new vecteur
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur Mat_pleine::Simple_Resol_syst (const Vecteur& b,const double &tol
|
|
,const int maxi,const int rest) const
|
|
{
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case CHOLESKY: case SYMETRISATION_PUIS_CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Vecteur resul(N); // Vecteur solution
|
|
Resolution (N,*this,b,resul);
|
|
return resul; break;
|
|
}
|
|
case CRAMER:
|
|
{ Vecteur resul(b); Cramer(b,resul); return resul; break; }
|
|
default:
|
|
{ Vecteur resul(b);
|
|
Mat_abstraite::Resolution_syst(b,resul,tol,maxi,rest);
|
|
return resul;
|
|
}
|
|
};
|
|
};
|
|
// b) avec en sortie le vecteur d'entree
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur& Mat_pleine::Simple_Resol_systID (Vecteur& b,const double &tol
|
|
,const int maxi,const int restart ) const
|
|
{
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case CHOLESKY: case SYMETRISATION_PUIS_CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Resolution (N,*this,b,b);
|
|
}
|
|
case CRAMER:
|
|
{ Cramer(b,b);
|
|
break;
|
|
}
|
|
default:
|
|
{ Vecteur bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart);
|
|
b = bb;
|
|
}
|
|
};
|
|
return b;
|
|
};
|
|
// c) avec en entrée un tableau de vecteur second membre et
|
|
// en sortie un nouveau tableau de vecteurs
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Vecteur> Mat_pleine::Simple_Resol_syst
|
|
(const Tableau <Vecteur>& b,const double &tol
|
|
,const int maxi,const int restart ) const
|
|
{
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case CHOLESKY: case SYMETRISATION_PUIS_CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
int dimtab = b.Taille();
|
|
Tableau <Vecteur> c(dimtab);
|
|
for (int i=1;i<= dimtab;i++)
|
|
{ c(i).Change_taille(b(i).Taille());
|
|
Resolution (N,*this,b(i),c(i));
|
|
};
|
|
return c;
|
|
break;
|
|
}
|
|
case CRAMER:
|
|
{int dimtab = b.Taille();
|
|
Tableau <Vecteur> c(dimtab);
|
|
Cramer(b,c);
|
|
return c;
|
|
break;
|
|
}
|
|
default:
|
|
{ Tableau <Vecteur> bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart);
|
|
return bb;
|
|
}
|
|
};
|
|
};
|
|
// d) avec en entrée un tableau de vecteur second membre et
|
|
// en sortie le tableau de vecteurs d'entree
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Vecteur>& Mat_pleine::Simple_Resol_systID
|
|
(Tableau <Vecteur>& b,const double &tol
|
|
,const int maxi,const int restart ) const
|
|
{
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case CHOLESKY: case SYMETRISATION_PUIS_CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
int dimtab = b.Taille();
|
|
for (int i=1;i<= dimtab;i++)
|
|
Resolution (N,*this,b(i),b(i));
|
|
break;
|
|
}
|
|
case CRAMER:
|
|
{ Cramer (b,b);
|
|
break;
|
|
}
|
|
default:
|
|
{ Tableau <Vecteur> bb(b);
|
|
Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart);
|
|
b = bb;
|
|
}
|
|
}
|
|
return b;
|
|
};
|
|
// e) avec en sortie le dernier vecteur d'entree, le premier étant le second membre
|
|
// et restant inchangé, en sortie c'est donc soit le retour ou soit vortie, les
|
|
// deux étant identiques
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur& Mat_pleine::Simple_Resol_systID_2 (const Vecteur& b,Vecteur& vortie
|
|
, const double &tol,const int maxi,const int restart) const
|
|
{
|
|
// dans le cas ou la matrice est uniquement un nombre !! on passe en CRAMER
|
|
// car cholesky est d'une part compliqué et pose pb !!
|
|
Enum_type_resolution_matri type_resolution_en_pratique = type_resolution; // init
|
|
if (Nb_ligne()==1)
|
|
type_resolution_en_pratique = CRAMER;
|
|
|
|
switch (type_resolution_en_pratique)
|
|
{case CHOLESKY: case SYMETRISATION_PUIS_CHOLESKY:
|
|
{int N=Nb_ligne();
|
|
Resolution (N,*this,b,vortie);
|
|
return vortie;
|
|
break;
|
|
}
|
|
case CRAMER:
|
|
{ Cramer(b,vortie); return vortie; break;
|
|
}
|
|
default:
|
|
{ Mat_abstraite::Resolution_syst(b,vortie,tol,maxi,restart);
|
|
return vortie;
|
|
}
|
|
};
|
|
};
|
|
// ===== FIN RÉSOLUTION EN DEUX TEMPS ================ :
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur Mat_pleine::Prod_mat_vec (const Vecteur& vec) const
|
|
// Realise le produit de la matrice par le vecteur vec
|
|
{ Vecteur resul(Nb_ligne());
|
|
#ifdef MISE_AU_POINT
|
|
// il faut que les lignes et vec aient la même dimension
|
|
if (vec.Taille() != Ligne(1).Taille())
|
|
{cout << "erreur de taille, la première ligne de la matrice n'a pas la même dimension";
|
|
cout << " que le vecteur à multiplier "
|
|
<< "\n Mat_pleine::Prod_mat_vec (const Vecteur& vec)" << endl;
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
int nb_lign = val.Taille();
|
|
for (int i=1;i<=nb_lign;i++)
|
|
resul(i)=Ligne(i)*vec;
|
|
return resul;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Vecteur& Mat_pleine::Prod_mat_vec (const Vecteur& vec,Vecteur& result) const
|
|
// Realise le produit de la matrice par le vecteur vec
|
|
// ici on se sert du second vecteur pour le résultat
|
|
{ result.Change_taille(Nb_ligne());
|
|
#ifdef MISE_AU_POINT
|
|
// il faut que les lignes et vec aient la même dimension
|
|
if (vec.Taille() != Ligne(1).Taille())
|
|
{cout << "erreur de taille, la première ligne de la matrice n'a pas la même dimension";
|
|
cout << " que le vecteur à multiplier "
|
|
<< "\n Mat_pleine::Prod_mat_vec (const Vecteur& vec,Vecteur& result)" << endl;
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
int nb_lign = val.Taille();
|
|
for (int i=1;i<=nb_lign;i++)
|
|
result(i)=Ligne(i)*vec;
|
|
return result;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine Mat_pleine::Transpose () const
|
|
// Retourne la transposee de la matrice mat
|
|
{
|
|
int nb_col = Nb_colonne(); int nb_lign = val.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if ( ( nb_lign ==0 ) || ( nb_col ==0 ) )
|
|
{
|
|
cout << "Erreur : dimensions de la matrice non valables\n";
|
|
cout << "MAT_PLEINE::TRANSPOSE ( )\n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
|
|
Mat_pleine result(nb_col,nb_lign);
|
|
for (int i=1;i<=nb_col;i++)
|
|
{
|
|
for (int j=1;j<=nb_lign;j++)
|
|
{
|
|
result(i,j)=(*this)(j,i);
|
|
};
|
|
};
|
|
return result;
|
|
};
|
|
|
|
// determine l'inverse d'une matrice carre
|
|
// actuellement uniquement implemente pour dim = 1,2,3
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine Mat_pleine::Inverse() const
|
|
{ int iL = this->Nb_ligne(); int cC = this->Nb_colonne();
|
|
#ifdef MISE_AU_POINT
|
|
if (iL != cC)
|
|
{ cout << "\nErreur : le nombre de ligne est different du nb de colonne !\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
else if ((iL != 1) && (iL != 2) && (iL!=3))
|
|
{ cout << "\nErreur : desole, actuellement seule les cas dim = 1 ou 2 ou 3"
|
|
<< " sont implante !\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
const Mat_pleine & mat = *this;
|
|
Mat_pleine res (cC,cC);
|
|
Mat_pleine inter (cC,cC); // pour contenir la matrice régularisée
|
|
double det;
|
|
if (cC == 1)
|
|
{if ( Dabs(mat(1,1)) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur1 : le determinant est nulle !\n";
|
|
if (ParaGlob::NiveauImpression() > 3)
|
|
mat.Affiche();
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
}
|
|
else
|
|
res(1,1) = 1./mat(1,1);
|
|
}
|
|
else if (cC == 2)
|
|
{ // on va regulariser la matrice pour limiter les erreurs de dépassement de capacité
|
|
// en espérant que cela fonctionne
|
|
// 1-- on récupère le maxi des valeurs de la matrice
|
|
double maxival = mat(1,1); // init
|
|
maxival = DabsMaX(maxival, mat(1,2));
|
|
maxival = DabsMaX(maxival, mat(2,1));
|
|
maxival = DabsMaX(maxival, mat(2,2));
|
|
if ( maxival <= ConstMath::trespetit)
|
|
{ cout << "\nErreur11 : la matrice est nulle !\n";
|
|
if (ParaGlob::NiveauImpression() > 3)
|
|
mat.Affiche();
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
// 2 --- on régularise
|
|
double unSurMaxival = 1./maxival;
|
|
inter (1,1) = mat(1,1) * unSurMaxival;
|
|
inter (1,2) = mat(1,2) * unSurMaxival;
|
|
inter (2,1) = mat(2,1) * unSurMaxival;
|
|
inter (2,2) = mat(2,2) * unSurMaxival;
|
|
|
|
// suite calcul normal
|
|
det = inter(1,1) * inter(2,2) - inter(1,2) * inter (2,1);
|
|
if ( Dabs(det) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur2 : le determinant est nulle !\n";
|
|
if (ParaGlob::NiveauImpression() > 3)
|
|
mat.Affiche();
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
// 3-- on tient compte de la régularisation
|
|
res (1,1) = unSurMaxival * inter(2,2) / det;
|
|
res(1,2) = - unSurMaxival * inter(1,2) / det;
|
|
res(2,1) = - unSurMaxival * inter(2,1) / det;
|
|
res(2,2) = unSurMaxival * inter(1,1) / det;
|
|
|
|
}
|
|
else if (cC == 3)
|
|
{ // on va regulariser la matrice pour limiter les erreurs de dépassement de capacité
|
|
// en espérant que cela fonctionne
|
|
// 1-- on récupère le maxi des valeurs de la matrice
|
|
double maxival = mat(1,1); // init
|
|
maxival = DabsMaX(maxival, mat(1,2));
|
|
maxival = DabsMaX(maxival, mat(1,3));
|
|
maxival = DabsMaX(maxival, mat(2,1));
|
|
maxival = DabsMaX(maxival, mat(2,2));
|
|
maxival = DabsMaX(maxival, mat(2,3));
|
|
maxival = DabsMaX(maxival, mat(3,1));
|
|
maxival = DabsMaX(maxival, mat(3,2));
|
|
maxival = DabsMaX(maxival, mat(3,3));
|
|
if ( maxival <= ConstMath::trespetit)
|
|
{ cout << "\nErreur12 : la matrice est nulle !\n";
|
|
if (ParaGlob::NiveauImpression() > 3)
|
|
mat.Affiche();
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
// 2 --- on régularise
|
|
double unSurMaxival = 1./maxival;
|
|
inter (1,1) = mat(1,1) * unSurMaxival;
|
|
inter (1,2) = mat(1,2) * unSurMaxival;
|
|
inter (1,3) = mat(1,3) * unSurMaxival;
|
|
inter (2,1) = mat(2,1) * unSurMaxival;
|
|
inter (2,2) = mat(2,2) * unSurMaxival;
|
|
inter (2,3) = mat(2,3) * unSurMaxival;
|
|
inter (3,1) = mat(3,1) * unSurMaxival;
|
|
inter (3,2) = mat(3,2) * unSurMaxival;
|
|
inter (3,3) = mat(3,3) * unSurMaxival;
|
|
//det = ((a11 a22 - a12 a21) a33 + (a13 a21 - a11 a23) a32 + (a12 a23 - a13 a22) a31);
|
|
det = inter(1,1) *( inter(2,2) * inter(3,3) - inter(2,3) * inter (3,2));
|
|
det -= inter(1,2) *( inter(2,1) * inter(3,3) - inter(2,3) * inter (3,1));
|
|
det += inter(1,3) *( inter(2,1) * inter(3,2) - inter(2,2) * inter (3,1));
|
|
if ( Dabs(det) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur3 : le determinant est nulle !\n";
|
|
if (ParaGlob::NiveauImpression() > 3)
|
|
mat.Affiche();
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
// 3-- on tient compte de la régularisation
|
|
res(1,1) = unSurMaxival * (inter(2,2) * inter(3,3) - inter(2,3) * inter (3,2)) / det;
|
|
res(2,2) = unSurMaxival * (inter(1,1) * inter(3,3) - inter(1,3) * inter (3,1)) / det;
|
|
res(3,3) = unSurMaxival * (inter(1,1) * inter(2,2) - inter(1,2) * inter (2,1)) / det;
|
|
res(1,2) = -unSurMaxival * (inter(1,2) * inter(3,3) - inter(1,3) * inter (3,2)) / det;
|
|
res(1,3) = unSurMaxival * (inter(1,2) * inter(2,3) - inter(1,3) * inter (2,2)) / det;
|
|
res(2,1) = -unSurMaxival * (inter(2,1) * inter(3,3) - inter(2,3) * inter (3,1)) / det;
|
|
res(3,1) = unSurMaxival * (inter(2,1) * inter(3,2) - inter(2,2) * inter (3,1)) / det;
|
|
res(3,2) = -unSurMaxival * (inter(1,1) * inter(3,2) - inter(1,2) * inter (3,1)) / det;
|
|
res(2,3) = -unSurMaxival * (inter(1,1) * inter(2,3) - inter(1,3) * inter (2,1)) / det;
|
|
};
|
|
return res;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// determine l'inverse d'une matrice carre
|
|
// actuellement uniquement implemente pour dim = 1,2,3
|
|
// ici retourne l'inverse dans la matrice passée en paramètre
|
|
// qui doit être de même type et de même dimension que this
|
|
Mat_pleine& Mat_pleine::Inverse(Mat_pleine& res) const
|
|
{ int iL = this->Nb_ligne(); int cC = this->Nb_colonne();
|
|
#ifdef MISE_AU_POINT
|
|
if (iL != cC)
|
|
{ cout << "\nErreur : le nombre de ligne est different du nb de colonne !\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
else if ((iL != 1) && (iL != 2) && (iL!=3))
|
|
{ cout << "\nErreur : desole, actuellement seule les cas dim = 1 ou 2 ou 3"
|
|
<< " sont implante !\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
Sortie(1);
|
|
};
|
|
if (iL != res.Nb_ligne())
|
|
{ cout << "\nErreur : le nombre de ligne est different entre this " << iL
|
|
<< " et res " << res.Nb_ligne() << "!\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
else if (cC != res.Nb_colonne())
|
|
{ cout << "\nErreur : le nombre de colonne est different entre this " << cC
|
|
<< " et res " << res.Nb_colonne() << "!\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
const Mat_pleine & mat = *this;
|
|
Mat_pleine inter (cC,cC); // pour contenir la matrice régularisée
|
|
double det;
|
|
if (cC == 1)
|
|
{if ( Dabs(mat(1,1)) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
}
|
|
else
|
|
res(1,1) = 1./mat(1,1);
|
|
}
|
|
else if (cC == 2)
|
|
{ // on va regulariser la matrice pour limiter les erreurs de dépassement de capacité
|
|
// en espérant que cela fonctionne
|
|
// 1-- on récupère le maxi des valeurs de la matrice
|
|
double maxival = mat(1,1); // init
|
|
maxival = DabsMaX(maxival, mat(1,2));
|
|
maxival = DabsMaX(maxival, mat(2,1));
|
|
maxival = DabsMaX(maxival, mat(2,2));
|
|
if ( maxival <= ConstMath::trespetit)
|
|
{ cout << "\nErreur110 : la matrice est nulle !\n";
|
|
if (ParaGlob::NiveauImpression() > 3)
|
|
mat.Affiche();
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
// 2 --- on régularise
|
|
double unSurMaxival = 1./maxival;
|
|
inter (1,1) = mat(1,1) * unSurMaxival;
|
|
inter (1,2) = mat(1,2) * unSurMaxival;
|
|
inter (2,1) = mat(2,1) * unSurMaxival;
|
|
inter (2,2) = mat(2,2) * unSurMaxival;
|
|
|
|
// suite calcul normal
|
|
det = inter(1,1) * inter(2,2) - inter(1,2) * inter (2,1);
|
|
if ( Dabs(det) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
// 3-- on tient compte de la régularisation
|
|
res (1,1) = unSurMaxival * inter(2,2) / det;
|
|
res(1,2) = - unSurMaxival * inter(1,2) / det;
|
|
res(2,1) = - unSurMaxival * inter(2,1) / det;
|
|
res(2,2) = unSurMaxival * inter(1,1) / det;
|
|
// res (1,1) = mat(2,2) / det;
|
|
// res(1,2) = -mat(1,2) / det;
|
|
// res(2,1) = -mat(2,1) / det;
|
|
// res(2,2) = mat(1,1) / det;
|
|
}
|
|
else if (cC == 3)
|
|
{ // on va regulariser la matrice pour limiter les erreurs de dépassement de capacité
|
|
// en espérant que cela fonctionne
|
|
// 1-- on récupère le maxi des valeurs de la matrice
|
|
double maxival = mat(1,1); // init
|
|
maxival = DabsMaX(maxival, mat(1,2));
|
|
maxival = DabsMaX(maxival, mat(1,3));
|
|
maxival = DabsMaX(maxival, mat(2,1));
|
|
maxival = DabsMaX(maxival, mat(2,2));
|
|
maxival = DabsMaX(maxival, mat(2,3));
|
|
maxival = DabsMaX(maxival, mat(3,1));
|
|
maxival = DabsMaX(maxival, mat(3,2));
|
|
maxival = DabsMaX(maxival, mat(3,3));
|
|
if ( maxival <= ConstMath::trespetit)
|
|
{ cout << "\nErreur12 : la matrice est nulle !\n";
|
|
if (ParaGlob::NiveauImpression() > 3)
|
|
mat.Affiche();
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
// 2 --- on régularise
|
|
double unSurMaxival = 1./maxival;
|
|
inter (1,1) = mat(1,1) * unSurMaxival;
|
|
inter (1,2) = mat(1,2) * unSurMaxival;
|
|
inter (1,3) = mat(1,3) * unSurMaxival;
|
|
inter (2,1) = mat(2,1) * unSurMaxival;
|
|
inter (2,2) = mat(2,2) * unSurMaxival;
|
|
inter (2,3) = mat(2,3) * unSurMaxival;
|
|
inter (3,1) = mat(3,1) * unSurMaxival;
|
|
inter (3,2) = mat(3,2) * unSurMaxival;
|
|
inter (3,3) = mat(3,3) * unSurMaxival;
|
|
//det = ((a11 a22 - a12 a21) a33 + (a13 a21 - a11 a23) a32 + (a12 a23 - a13 a22) a31);
|
|
det = inter(1,1) *( inter(2,2) * inter(3,3) - inter(2,3) * inter (3,2));
|
|
det -= inter(1,2) *( inter(2,1) * inter(3,3) - inter(2,3) * inter (3,1));
|
|
det += inter(1,3) *( inter(2,1) * inter(3,2) - inter(2,2) * inter (3,1));
|
|
if ( Dabs(det) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Inverse() \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
// 3-- on tient compte de la régularisation
|
|
res(1,1) = unSurMaxival * (inter(2,2) * inter(3,3) - inter(2,3) * inter (3,2)) / det;
|
|
res(2,2) = unSurMaxival * (inter(1,1) * inter(3,3) - inter(1,3) * inter (3,1)) / det;
|
|
res(3,3) = unSurMaxival * (inter(1,1) * inter(2,2) - inter(1,2) * inter (2,1)) / det;
|
|
res(1,2) = -unSurMaxival * (inter(1,2) * inter(3,3) - inter(1,3) * inter (3,2)) / det;
|
|
res(1,3) = unSurMaxival * (inter(1,2) * inter(2,3) - inter(1,3) * inter (2,2)) / det;
|
|
res(2,1) = -unSurMaxival * (inter(2,1) * inter(3,3) - inter(2,3) * inter (3,1)) / det;
|
|
res(3,1) = unSurMaxival * (inter(2,1) * inter(3,2) - inter(2,2) * inter (3,1)) / det;
|
|
res(3,2) = -unSurMaxival * (inter(1,1) * inter(3,2) - inter(1,2) * inter (3,1)) / det;
|
|
res(2,3) = -unSurMaxival * (inter(1,1) * inter(2,3) - inter(1,3) * inter (2,1)) / det;
|
|
|
|
// res(1,1) = (mat(2,2) * mat(3,3) - mat(2,3) * mat (3,2)) / det;
|
|
// res(2,2) = (mat(1,1) * mat(3,3) - mat(1,3) * mat (3,1)) / det;
|
|
// res(3,3) = (mat(1,1) * mat(2,2) - mat(1,2) * mat (2,1)) / det;
|
|
// res(1,2) = -(mat(1,2) * mat(3,3) - mat(1,3) * mat (3,2)) / det;
|
|
// res(1,3) = (mat(1,2) * mat(2,3) - mat(1,3) * mat (2,2)) / det;
|
|
// res(2,1) = -(mat(2,1) * mat(3,3) - mat(2,3) * mat (3,1)) / det;
|
|
// res(3,1) = (mat(2,1) * mat(3,2) - mat(2,2) * mat (3,1)) / det;
|
|
// res(3,2) = -(mat(1,1) * mat(3,2) - mat(1,2) * mat (3,1)) / det;
|
|
// res(2,3) = -(mat(1,1) * mat(2,3) - mat(1,3) * mat (2,1)) / det;
|
|
};
|
|
return res;
|
|
};
|
|
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// détermine le déterminant d'une matrice
|
|
// actuellement uniquement implemente pour dim = 1,2,3
|
|
double Mat_pleine::Determinant() const
|
|
{ int iL = this->Nb_ligne(); int cC = this->Nb_colonne();
|
|
#ifdef MISE_AU_POINT
|
|
if (iL != cC)
|
|
{ cout << "\nErreur : le nombre de ligne est different du nb de colonne !\n";
|
|
cout << "Mat_pleine::Determinant() \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
else if ((iL != 1) && (iL != 2) && (iL!=3))
|
|
{ cout << "\nErreur : desole, actuellement seule les cas dim = 1 ou 2 ou 3"
|
|
<< " sont implante !\n";
|
|
cout << "Mat_pleine::Determinant() \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
const Mat_pleine & mat = *this;
|
|
double det;
|
|
if (cC == 1)
|
|
{det = mat(1,1);
|
|
}
|
|
else if (cC == 2)
|
|
{det = mat(1,1) * mat(2,2) - mat(1,2) * mat (2,1);
|
|
}
|
|
else if (cC == 3)
|
|
{ //det = ((a11 a22 - a12 a21) a33 + (a13 a21 - a11 a23) a32 + (a12 a23 - a13 a22) a31);
|
|
det = mat(1,1) *( mat(2,2) * mat(3,3) - mat(2,3) * mat (3,2));
|
|
det -= mat(1,2) *( mat(2,1) * mat(3,3) - mat(2,3) * mat (3,1));
|
|
det += mat(1,3) *( mat(2,1) * mat(3,2) - mat(2,2) * mat (3,1));
|
|
};
|
|
return det;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine Mat_pleine::operator+ (const Mat_pleine& mat_pl) const
|
|
// Surcharge de l'operateur + : addition de deux matrices
|
|
{ int nb_lign = val.Taille();
|
|
int nb_col = Nb_colonne();
|
|
#ifdef MISE_AU_POINT
|
|
if ( ( nb_lign != mat_pl.Nb_ligne() )
|
|
|| ( nb_col != mat_pl.Nb_colonne() ) )
|
|
{ cout << "Erreur : dimensions des matrices non egales\n";
|
|
cout << "MAT_PLEINE::OPERATOR+ (const Mat_pleine& )\n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
Mat_pleine result(nb_lign,nb_col);
|
|
result.val_de_base = val_de_base + mat_pl.val_de_base;
|
|
|
|
// result.val.Change_taille(nb_lign);
|
|
// for (int i=1;i<=nb_lign;i++)
|
|
// // addition des composantes a l'aide de la surcharge de l'operateur
|
|
// // + pour les vecteurs
|
|
// result.val(i)=val(i)+mat_pl(i);
|
|
return result;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine Mat_pleine::operator- (const Mat_pleine& mat_pl) const
|
|
// Surcharge de l'operateur - : soustraction entre deux matrices
|
|
{ int nb_lign = val.Taille();
|
|
int nb_col = Nb_colonne();
|
|
#ifdef MISE_AU_POINT
|
|
if ( ( nb_lign != mat_pl.Nb_ligne() )
|
|
|| ( nb_col != mat_pl.Nb_colonne() ) )
|
|
{
|
|
cout << "Erreur : dimensions des matrices non egales\n";
|
|
cout << "MAT_PLEINE::OPERATOR- (const Mat_pleine& )\n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
Mat_pleine result(nb_lign,nb_col);
|
|
result.val_de_base = val_de_base - mat_pl.val_de_base;
|
|
//
|
|
// result.val.Change_taille(nb_lign);
|
|
// for (int i=1;i<=nb_lign;i++)
|
|
// // soustraction des composantes a l'aide de la surcharge de l'operateur
|
|
// // - pour les vecteurs
|
|
// result.val(i)=val(i)-mat_pl(i);
|
|
return result;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine Mat_pleine::operator- () const
|
|
// Surcharge de l'operateur - : oppose d'une matrice
|
|
{ Mat_pleine result(this->Nb_ligne(),this->Nb_colonne());
|
|
result.val_de_base = -val_de_base;
|
|
// int nb_lign = val.Taille();
|
|
// result.val.Change_taille(nb_lign);
|
|
// for (int i=1;i<=nb_lign;i++)
|
|
// // determination de l'oppose des composantes de la matrice courante a l'aide de la surcharge
|
|
// // de l'operateur -= pour les vecteurs
|
|
// result.val(i)=-val(i);
|
|
return result;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::operator+= ( const Mat_pleine& mat_pl)
|
|
// Addition a la matrice courante de la matrice mat_pl
|
|
{ int nb_lign = val.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if ( ( nb_lign!=mat_pl.Nb_ligne() )
|
|
|| ( Nb_colonne()!=mat_pl.Nb_colonne() ) )
|
|
{
|
|
cout << "Erreur : dimensions des matrices non egales\n";
|
|
cout << "MAT_PLEINE::OPERATOR+= (const Mat_pleine& )\n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
val_de_base += mat_pl.val_de_base;
|
|
//
|
|
// for (int i=1;i<=nb_lign;i++)
|
|
// // l'operateur += est l'operateur += des vecteurs
|
|
// val(i)+=mat_pl(i);
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::operator-= ( const Mat_pleine& mat_pl)
|
|
{ // Soustrait a la matrice courante la matrice mat_pl
|
|
int nb_lign = val.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if ( ( nb_lign!=mat_pl.Nb_ligne() )
|
|
|| ( Nb_colonne()!=mat_pl.Nb_colonne() ) )
|
|
{
|
|
cout << "Erreur : dimensions des matrices non egales\n";
|
|
cout << "MAT_PLEINE::OPERATOR-= (const Mat_pleine& )\n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
val_de_base -= mat_pl.val_de_base;
|
|
|
|
// for (int i=1;i<=nb_lign;i++)
|
|
// // l'operateur -= est l'operateur -= des vecteurs
|
|
// val(i)-=mat_pl(i);
|
|
};
|
|
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine Mat_pleine::operator* (const Mat_pleine& mat_pl) const
|
|
// Surcharge de l'operateur * : multiplication de deux matrices
|
|
{ int mat_nb_col = mat_pl.Nb_colonne(); int nb_lign = val.Taille();
|
|
#ifdef MISE_AU_POINT
|
|
if ( Nb_colonne()!=mat_pl.Nb_ligne() )
|
|
{
|
|
cout << "Erreur : dimensions des matrices non valables\n";
|
|
cout << "MAT_PLEINE::OPERATOR* (const Mat_pleine& )\n";
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
Mat_pleine result(nb_lign,mat_nb_col);
|
|
// result.Initialise(nb_lign,mat_nb_col);
|
|
for (int i=1;i<=nb_lign;i++)
|
|
{
|
|
for (int j=1;j<=mat_nb_col;j++)
|
|
// la ieme jieme composante de la matrice result est obtenue par le produit de la
|
|
// ieme ligne de la matrice courante avec la jieme colonne de la matrice mat_pl
|
|
result(i,j)=Ligne(i)*mat_pl.Colonne(j);
|
|
};
|
|
return result;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::operator*= (double coeff)
|
|
//multiplication de la matrice courante par un scalaire
|
|
{ val_de_base *= coeff;
|
|
//
|
|
// int nb_lign = val.Taille();
|
|
// for (int i=1;i<=nb_lign;i++)
|
|
// // l'operateur *= est l'operateur *= des vecteurs
|
|
// val(i) *= coeff;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Mat_pleine Mat_pleine::operator* (double coeff) const
|
|
// Surcharge de l'operateur * : multiplication d'une matrice par un scalaire
|
|
{ Mat_pleine result(*this);
|
|
result *= coeff;
|
|
return result;
|
|
//
|
|
//
|
|
//
|
|
//Mat_pleine result;
|
|
// int nb_lign = val.Taille();int nb_col = Nb_colonne();
|
|
// result.Initialise(nb_lign,nb_col);
|
|
// for (int i=1;i<=nb_lign;i++)
|
|
// {
|
|
// for (int j=1;j<=nb_col;j++)
|
|
// result(i,j)=coeff*(*this)(i,j);
|
|
// };
|
|
// return result;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
int Mat_pleine::operator== (const Mat_pleine& mat_pl) const
|
|
// Surcharge de l'operateur == : test d'egalite entre deux matrices
|
|
// Retourne 1 si les deux matrices sont egales
|
|
// 0 sinon
|
|
{
|
|
int nb_lign = val.Taille();int nb_col = Nb_colonne();
|
|
if ( ( nb_lign != mat_pl.Nb_ligne() ) || ( nb_col != mat_pl.Nb_colonne() ) )
|
|
return 0;
|
|
int taille_glob = val_de_base.Taille();
|
|
for (int i=1;i<=taille_glob;i++)
|
|
{if (val_de_base(i) != mat_pl.val_de_base(i))
|
|
return 0;
|
|
}
|
|
//
|
|
// for (int i=1;i <= nb_lign;i++)
|
|
// {for (int j=1;j <= nb_col;j++)
|
|
// {if ( (*this)(i,j) != mat_pl(i,j) )
|
|
// return 0;
|
|
// };
|
|
// };
|
|
return 1;
|
|
};
|
|
// remplace la ligne de la matrice par la ligne fournie
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::RemplaceLigneSpe(int i,const Vecteur & v)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (val(i)->Taille() != v.Taille())
|
|
{ cout << " \nla taille de la ligne i= " << i <<" a remplacer n est pas bonne " ;
|
|
cout << " taille = " << v.Taille() << " tailleLigneMatrice = " << val(i)->Taille();
|
|
cout << " void Mat_pleine::RemplaceLigne(int i,Vecteur & v)" << endl;
|
|
Sortie (1);
|
|
}
|
|
#endif
|
|
*(val(i)) = v;
|
|
};
|
|
//met une valeur identique sur toute la ligne
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::MetValLigne(int i,double x)
|
|
{ val(i)->Inita(x);
|
|
// Vecteur& v=*(val(i));
|
|
// int vali_taille = val(i)->Taille();
|
|
// for (int j=1;j <= vali_taille;j++)
|
|
// v(j) = x;
|
|
};
|
|
|
|
// remplace la Colonne de la matrice par la colonne fournie
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::RemplaceColonneSpe(int j, const Vecteur & v)
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (val.Taille() != v.Taille())
|
|
{ cout << " \nla taille de la colonne j= " << j <<" a remplacer n est pas bonne " ;
|
|
cout << " taille = " << v.Taille() << " tailleColMatrice = " << val.Taille();
|
|
cout << " void Mat_pleine::RemplaceColonne(int j,Vecteur & v) " << endl;
|
|
Sortie (1);
|
|
}
|
|
#endif
|
|
int nb_lign = val.Taille();
|
|
for (int i=1;i <= nb_lign;i++)
|
|
(*this)(i,j)=v(i);
|
|
};
|
|
//met une valeur identique sur toute la colonne
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::MetValColonne(int j,double y)
|
|
{ int nb_lign = val.Taille();
|
|
for (int i=1;i <= nb_lign;i++)
|
|
(*this)(i,j) = y;
|
|
};
|
|
// Multiplication d'une ligne iligne de la matrice avec un vecteur de
|
|
// dimension = le nombre de colonne de la matrice
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Mat_pleine::Prod_Ligne_vec ( int iligne, const Vecteur& vec) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (val(iligne)->Taille() != vec.Taille())
|
|
{ cout << " \n erreur la taille de la ligne i= " << iligne <<" n est pas correcte ";
|
|
cout << " tailleligneMatrice = " <<val(iligne)->Taille()
|
|
<< " taillevecteur = " << vec.Taille();
|
|
cout << " double Mat_pleine::Prod_Ligne_vec ( int iligne,Vecteur& vec) " << endl;
|
|
Sortie (1);
|
|
}
|
|
#endif
|
|
double res = 0;
|
|
int val_iligne_taille = val(iligne)->Taille();
|
|
for (int j=1;j <= val_iligne_taille;j++)
|
|
res += (*this)(iligne,j) * vec(j);
|
|
return res;
|
|
};
|
|
// Multiplication d'un vecteur avec une colonne icol de la matrice
|
|
// dimension = le nombre de ligne de la matrice
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Mat_pleine::Prod_vec_col( int jcol, const Vecteur& vec) const
|
|
{
|
|
#ifdef MISE_AU_POINT
|
|
if (val.Taille() != vec.Taille())
|
|
{ cout << " \n erreur la taille de la colonne j= " << jcol <<" n est pas correcte ";
|
|
cout << " tailleColMatrice = " <<val.Taille()
|
|
<< " taillevecteur = " << vec.Taille();
|
|
cout << " double Mat_pleine::Prod_vec_col( int jcol,Vecteur& vec) " << endl;
|
|
Sortie (1);
|
|
}
|
|
#endif
|
|
double res = 0;
|
|
int val_taille = val.Taille();
|
|
for (int i=1;i <= val_taille;i++)
|
|
res += vec(i) * (*this)(i,jcol) ;
|
|
return res;
|
|
};
|
|
|
|
// calcul du produit : (vec_1)^T * A * (vect_2)
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Mat_pleine::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2) const
|
|
{ double resu=0.; // valeur de retour
|
|
#ifdef MISE_AU_POINT
|
|
if (vec1.Taille() != val(1)->Taille())
|
|
{cout << "erreur de taille, la dimension de (vec1)^T= " << vec1.Taille() << " n'a pas la même dimension";
|
|
cout << " que le le nombre de ligne de la matrice= " << val(1)->Taille()
|
|
<< "\n Mat_pleine::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2)" << endl;
|
|
Sortie(1);
|
|
}
|
|
if (vec2.Taille() != val.Taille())
|
|
{cout << "erreur de taille, la dimension de (vec2)= " << vec2.Taille() << " n'a pas la même dimension";
|
|
cout << " que le le nombre de colonne de la matrice= " << val.Taille()
|
|
<< "\n Mat_pleine::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2)" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
int nb_col = Nb_colonne();
|
|
int nb_lig = Nb_ligne();
|
|
for (int i=1;i<=nb_col ;i++)
|
|
for (int j=1;j<=nb_lig ;j++)
|
|
resu += vec1(i) * (*this)(i,j) * vec2(j);
|
|
return resu;
|
|
};
|
|
|
|
// ramène un tableau de coordonnées (avec 3 variances possibles) correspondant à la matrice
|
|
// tab(i) = la colonne i de la matrice
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <Coordonnee > Mat_pleine::Coordonnee_Base_associee() const
|
|
{ int nb_col = Nb_colonne();
|
|
Tableau <Coordonnee > tab(nb_col);
|
|
int nb_lig = Nb_ligne();
|
|
for (int i=1;i<=nb_col ;i++)
|
|
{tab(i).Change_dim(nb_lig);
|
|
for (int j=1;j<=nb_lig ;j++)
|
|
tab(i)(j) = (*this)(j,i);
|
|
};
|
|
return tab;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <CoordonneeH > Mat_pleine::CoordonneeH_Base_associee() const
|
|
{ int nb_col = Nb_colonne();
|
|
Tableau <CoordonneeH > tab(nb_col);
|
|
int nb_lig = Nb_ligne();
|
|
for (int i=1;i<=nb_col ;i++)
|
|
{tab(i).Change_dim(nb_lig);
|
|
for (int j=1;j<=nb_lig ;j++)
|
|
tab(i)(j) = (*this)(j,i);
|
|
};
|
|
return tab;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
Tableau <CoordonneeB > Mat_pleine::CoordonneeB_Base_associee() const
|
|
{ int nb_col = Nb_colonne();
|
|
Tableau <CoordonneeB > tab(nb_col);
|
|
int nb_lig = Nb_ligne();
|
|
for (int i=1;i<=nb_col ;i++)
|
|
{tab(i).Change_dim(nb_lig);
|
|
for (int j=1;j<=nb_lig ;j++)
|
|
tab(i)(j) = (*this)(j,i);
|
|
};
|
|
return tab;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
// idem mais une seule colonne i
|
|
Coordonnee Mat_pleine::Coordonnee_Base_associee(int i) const
|
|
{ Coordonnee coo;
|
|
int nb_lig = Nb_ligne();
|
|
coo.Change_dim(nb_lig);
|
|
for (int j=1;j<=nb_lig ;j++)
|
|
coo(j) = (*this)(j,i);
|
|
return coo;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
CoordonneeH Mat_pleine::CoordonneeH_Base_associee(int i) const
|
|
{ CoordonneeH coo;
|
|
int nb_lig = Nb_ligne();
|
|
coo.Change_dim(nb_lig);
|
|
for (int j=1;j<=nb_lig ;j++)
|
|
coo(j) = (*this)(j,i);
|
|
return coo;
|
|
};
|
|
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
CoordonneeB Mat_pleine::CoordonneeB_Base_associee(int i) const
|
|
{ CoordonneeB coo;
|
|
int nb_lig = Nb_ligne();
|
|
coo.Change_dim(nb_lig);
|
|
for (int j=1;j<=nb_lig ;j++)
|
|
coo(j) = (*this)(j,i);
|
|
return coo;
|
|
};
|
|
|
|
// ramène le maxi en valeur absolue des valeurs de la matrice, et les indices associées
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Mat_pleine::MaxiValAbs(int & imax, int & jmax) const
|
|
{ double lemaxi=0.;
|
|
imax = jmax = 0;
|
|
int nb_lig = val.Taille();
|
|
int nb_col = Nb_colonne();
|
|
for (int i=1;i<= nb_lig;i++)
|
|
for (int j=1;j<= nb_col;j++)
|
|
{double valeur = Dabs((*this)(i,j));
|
|
if (valeur > lemaxi)
|
|
{ lemaxi = valeur; imax = i; jmax = j; };
|
|
};
|
|
return lemaxi;
|
|
};
|
|
|
|
// ramène le maxi en valeur absolue de la somme des valeurs absolues de chaque ligne,
|
|
// et l'indice de ligne associé
|
|
// permet d'avoir une approximation de la valeur propre maximale de la matrice via le
|
|
// théorème de Gerschgorin : |lambda| < Max_i (|lambda_i|)
|
|
// avec: |lambda_i| < Max_j somme_j |k_ij|)
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
double Mat_pleine::Maxi_ligne_ValAbs(int & imax) const
|
|
{ double lemaxi=0.;
|
|
imax = 0;
|
|
int nb_lig = val.Taille();
|
|
for (int i=1;i<= nb_lig;i++)
|
|
{double somme_ligne = val(i)->SommeAbs();
|
|
if (somme_ligne > lemaxi)
|
|
{ lemaxi = somme_ligne; imax = i;};
|
|
};
|
|
return lemaxi;
|
|
};
|
|
|
|
|
|
// =================== méthodes protégées =======================
|
|
|
|
// symétrisation de la matrice (il faut qu'elle soit carrée
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Symetrisation()
|
|
{// arrivée ici on considère que l'on a une matrice carrée
|
|
int N=Nb_ligne();
|
|
for (int i=1;i<= N;i++)
|
|
for (int j=i+1;j<=N;j++)
|
|
(*this)(i,j)=(*this)(j,i)=0.5*((*this)(i,j)+(*this)(j,i));
|
|
|
|
};
|
|
|
|
// calcul de la matrice triangulée dans le cadre de la méthode de cholesky
|
|
// utilisation particulière : la matrice résultat B est défini dans le programme
|
|
// appelant.
|
|
// On considère que la matrice B est symétrique, et que l'on utilise uniquement la partie supérieure
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Triangulation (int N,Mat_pleine& B)
|
|
|
|
{ double somme;
|
|
|
|
// Determination des composantes de la matrice
|
|
// triangulaire inferieure B :
|
|
for (int k=1;k<=N;k++)
|
|
{
|
|
somme=0;
|
|
for (int j=1;j<=k-1;j++)
|
|
{
|
|
// somme=somme+ B(k,j)*B(k,j); // pow(B(k,j),2.0);
|
|
somme += B(k,j)*B(k,j); // pow(B(k,j),2.0);
|
|
// somme += B(j,k)*B(j,k); // pow(B(k,j),2.0); on utilise que la sup
|
|
|
|
};
|
|
B(k,k)=sqrt((*this)(k,k)-somme);
|
|
for (int i=k+1;i<=N;i++)
|
|
{
|
|
somme=0;
|
|
for (int j=1;j<=k-1;j++)
|
|
{
|
|
// somme=somme+(B(i,j)*B(k,j));
|
|
somme += (B(i,j)*B(k,j));
|
|
// somme += (B(j,i)*B(j,k)); // on utilise que le triangle sup
|
|
};
|
|
B(i,k)=((*this)(i,k)-somme)/B(k,k);
|
|
};
|
|
};
|
|
};
|
|
|
|
// résolution du problème triangularisé
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Resolution
|
|
(int N, const Mat_pleine& B,const Vecteur& b,Vecteur& resul) const
|
|
{ // Resolution du systeme B.y=b ( avec y=Bt.x )
|
|
// Les valeurs de y sont stockees dans le vecteur result
|
|
for (int i=1;i<=N;i++)
|
|
{
|
|
resul(i)=b(i);
|
|
// for (int j=1;j<=i-1;j++)
|
|
// resul(i)=resul(i)-B(i,j)*resul(j);
|
|
// resul(i)=resul(i)/B(i,i);
|
|
|
|
for (int j=1;j<=i-1;j++)
|
|
resul(i) -= B(i,j)*resul(j);
|
|
resul(i) /= B(i,i);
|
|
};
|
|
|
|
// Resolution du systeme Bt.x=y
|
|
// Les valeurs de x sont stockees dans le vecteur result
|
|
// B=B.Transpose();
|
|
// for (int i=N;i>=1;i--)
|
|
// {
|
|
// for (int j=i+1;j<=N;j++)
|
|
// result(i)=result(i)-B(j,i)*result(j);
|
|
// result(i)=result(i)/B(i,i);
|
|
// };
|
|
for (int i=N;i>=1;i--)
|
|
{
|
|
for (int j=i+1;j<=N;j++)
|
|
resul(i) -= B(j,i)*resul(j);
|
|
// resul(i)=resul(i)-B(j,i)*resul(j);
|
|
// resul(i)=resul(i)/B(i,i);
|
|
resul(i) /= B(i,i);
|
|
};
|
|
};
|
|
|
|
// résolution directe par la méthode de cramer (pour les petits systèmes dim 1,2,3)
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Cramer( const Vecteur& b,Vecteur& res) const
|
|
{ int iL = this->Nb_ligne(); int cC = this->Nb_colonne();
|
|
#ifdef MISE_AU_POINT
|
|
if (iL != cC)
|
|
{ cout << "\nErreur : le nombre de ligne est different du nb de colonne !\n";
|
|
cout << "void Mat_pleine::Cramer(.. \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
else if ((iL != 1) && (iL != 2) && (iL!=3))
|
|
{ cout << "\nErreur : desole, actuellement seule les cas dim = 1 ou 2 ou 3"
|
|
<< " sont implante !\n";
|
|
cout << "void Mat_pleine::Cramer(.. \n" << endl;
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
const Mat_pleine & mat = *this;
|
|
double det;
|
|
switch (cC)
|
|
{ case 1:
|
|
{if ( Dabs(mat(1,1)) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Cramer(.. \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
}
|
|
else
|
|
{ double res11 = 1./mat(1,1); res(1)=res11 * b(1);}
|
|
break;
|
|
}
|
|
case 2:
|
|
{det = mat(1,1) * mat(2,2) - mat(1,2) * mat (2,1);
|
|
if ( Dabs(det) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Cramer(.. \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
double res11 = mat(2,2) / det; double res12 = mat(1,2) / det;
|
|
double res21 = mat(2,1) / det; double res22 = mat(1,1) / det;
|
|
double res1 = res11 * b(1) - res12 * b(2);
|
|
double res2 = -res21 * b(1) + res22 * b(2);
|
|
res(1) = res1; res(2) = res2; // car le vecteur res peut-être égale à b
|
|
break;
|
|
}
|
|
case 3:
|
|
{det = mat(1,1) *( mat(2,2) * mat(3,3) - mat(2,3) * mat (3,2));
|
|
det -= mat(1,2) *( mat(2,1) * mat(3,3) - mat(2,3) * mat (3,1));
|
|
det += mat(1,3) *( mat(2,1) * mat(3,2) - mat(2,2) * mat (3,1));
|
|
if ( Dabs(det) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Cramer(.. \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
double res11 = (mat(2,2) * mat(3,3) - mat(2,3) * mat (3,2)) / det;
|
|
double res22 = (mat(1,1) * mat(3,3) - mat(1,3) * mat (3,1)) / det;
|
|
double res33 = (mat(1,1) * mat(2,2) - mat(1,2) * mat (2,1)) / det;
|
|
double res12 = -(mat(1,2) * mat(3,3) + mat(1,3) * mat (3,2)) / det;
|
|
double res13 = (mat(1,2) * mat(2,3) - mat(1,3) * mat (2,2)) / det;
|
|
double res21 = -(mat(2,1) * mat(3,3) + mat(2,3) * mat (3,1)) / det;
|
|
double res31 = (mat(2,1) * mat(3,2) - mat(2,2) * mat (3,1)) / det;
|
|
double res32 = -(mat(1,1) * mat(3,2) + mat(1,2) * mat (3,1)) / det;
|
|
double res23 = -(mat(1,1) * mat(2,3) - mat(1,3) * mat (2,1)) / det;
|
|
double res1 = res11 * b(1) + res12 * b(2) + res13 * b(3);
|
|
double res2 = res21 * b(1) + res22 * b(2) + res23 * b(3);
|
|
double res3 = res31 * b(1) + res32 * b(2) + res33 * b(3);
|
|
res(1) = res1; res(2) = res2; res(3) = res3; // car res peut-être égale à b
|
|
break;
|
|
}
|
|
};
|
|
};
|
|
|
|
// résolution directe par la méthode de cramer (pour les petits systèmes dim 1,2,3)
|
|
// idem précédent mais pour un tableau de vecteurs
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Cramer( const Tableau <Vecteur>& b,Tableau <Vecteur>& res) const
|
|
{ int iL = this->Nb_ligne(); int cC = this->Nb_colonne();
|
|
#ifdef MISE_AU_POINT
|
|
if (iL != cC)
|
|
{ cout << "\nErreur : le nombre de ligne est different du nb de colonne !\n";
|
|
cout << "void Mat_pleine::Cramer(.. \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
else if ((iL != 1) && (iL != 2) && (iL!=3))
|
|
{ cout << "\nErreur : desole, actuellement seule les cas dim = 1 ou 2 ou 3"
|
|
<< " sont implante !\n";
|
|
cout << "void Mat_pleine::Cramer(.. \n" << endl;
|
|
Sortie(1);
|
|
};
|
|
#endif
|
|
const Mat_pleine & mat = *this;
|
|
double det;
|
|
switch (cC)
|
|
{ case 1:
|
|
{if ( Dabs(mat(1,1)) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Cramer(.. \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
double res11 = 1./mat(1,1);
|
|
int dimtab = b.Taille();
|
|
res.Change_taille(dimtab);
|
|
for (int i=1;i<= dimtab;i++)
|
|
{ res(i).Change_taille(1); res(i)(1)= b(i)(1) * res11;}
|
|
break;
|
|
}
|
|
case 2:
|
|
{det = mat(1,1) * mat(2,2) - mat(1,2) * mat (2,1);
|
|
if ( Dabs(det) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Cramer(.. \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
double res11 = mat(2,2) / det; double res12 = mat(2,1) / det;
|
|
double res21 = mat(1,2) / det; double res22 = mat(1,1) / det;
|
|
int dimtab = b.Taille();
|
|
res.Change_taille(dimtab);
|
|
for (int i=1;i<= dimtab;i++)
|
|
{ res(i).Change_taille(2); Vecteur& bi=b(i);
|
|
double res1 = res11 * bi(1) + res12 * bi(2);
|
|
double res2 = res21 * bi(1) + res22 * bi(2);
|
|
res(i)(1) = res1; res(i)(2) = res2; // car le vecteur res peut-être égale à b
|
|
};
|
|
break;
|
|
}
|
|
case 3:
|
|
{det = mat(1,1) *( mat(2,2) * mat(3,3) - mat(2,3) * mat (3,2));
|
|
det -= mat(1,2) *( mat(2,1) * mat(3,3) - mat(2,3) * mat (3,1));
|
|
det += mat(1,3) *( mat(2,1) * mat(3,2) - mat(2,2) * mat (3,1));
|
|
if ( Dabs(det) <= ConstMath::trespetit)
|
|
{ cout << "\nErreur : le determinant est nulle !\n";
|
|
cout << "Mat_pleine::Cramer(.. \n" << endl;
|
|
throw ErrResolve_system_lineaire(1);
|
|
Sortie(1);
|
|
};
|
|
double res11 = (mat(2,2) * mat(3,3) - mat(2,3) * mat (3,2)) / det;
|
|
double res22 = (mat(1,1) * mat(3,3) - mat(1,3) * mat (3,1)) / det;
|
|
double res33 = (mat(1,1) * mat(2,2) - mat(1,2) * mat (2,1)) / det;
|
|
double res12 = -(mat(1,2) * mat(3,3) + mat(1,3) * mat (3,2)) / det;
|
|
double res13 = (mat(1,2) * mat(2,3) - mat(1,3) * mat (2,2)) / det;
|
|
double res21 = -(mat(2,1) * mat(3,3) + mat(2,3) * mat (3,1)) / det;
|
|
double res31 = (mat(2,1) * mat(3,2) - mat(2,2) * mat (3,1)) / det;
|
|
double res32 = -(mat(1,1) * mat(3,2) + mat(1,2) * mat (3,1)) / det;
|
|
double res23 = -(mat(1,1) * mat(2,3) - mat(1,3) * mat (2,1)) / det;
|
|
int dimtab = b.Taille();
|
|
res.Change_taille(dimtab);
|
|
for (int i=1;i<= dimtab;i++)
|
|
{ res(i).Change_taille(3); Vecteur& bi=b(i); Vecteur& resi=res(i);
|
|
double res1 = res11 * bi(1) + res12 * bi(2) + res13 * bi(3);
|
|
double res2 = res21 * bi(1) + res22 * bi(2) + res23 * bi(3);
|
|
double res3 = res31 * bi(1) + res32 * bi(2) + res33 * bi(3);
|
|
resi(1) = res1; resi(2) = res2; resi(3) = res3; // car res peut-être égale à b
|
|
};
|
|
break;
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// méthode interne pour modifier éventuellement les tailles
|
|
// en liaison entre les deux stockages
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Change_tailles_tab_val(int nb_lig,int nb_col)
|
|
{ // on considère que val_de_base est déjà ok
|
|
#ifdef MISE_AU_POINT
|
|
if (nb_lig*nb_col != val_de_base.Taille())
|
|
{ cout << "\nErreur : la taille de val_de_base: " << val_de_base.Taille()
|
|
<< " est differente de nb_lig*nb_col: " << nb_lig*nb_col;
|
|
cout << "void Change_tailles_tab_val(.. \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// l'objectif est la modification éventuelle de val
|
|
val.Change_taille(nb_lig);
|
|
double* pt = val_de_base.Pointeur_vect(); // init
|
|
for (int i=1;i<= nb_lig;i++)
|
|
{bool creation = false;
|
|
if (val(i) != NULL)
|
|
{ double* pt_val = val(i)->Pointeur_vect();
|
|
if ((pt_val != pt ) // il y a discordance
|
|
|| (val(i)->Taille() != nb_col)
|
|
)
|
|
{delete val(i); // on doit reconstruire le vecteur
|
|
creation = true;
|
|
};
|
|
// sinon c'est ok, on ne fait rien
|
|
}
|
|
else
|
|
{creation = true;};
|
|
if (creation) // on crée un vecteur lié
|
|
{// il n'y a pas d'initialisation de composantes des vecteur
|
|
// elles gardent les valeurs de val_de_base
|
|
bool memoire = false;
|
|
val(i)=new Vecteur(nb_col,pt,memoire);
|
|
};
|
|
// on déplace le pointeur de base sur le vecteur suivant
|
|
for (int j = 1; j<= nb_col; j++)
|
|
pt++;
|
|
};
|
|
};
|
|
|
|
// méthode interne pour créer val en fonction des dimensions
|
|
// ce qui crée une liaison entre les deux stockages
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
void Mat_pleine::Creation_tab_val(int nb_lig,int nb_col)
|
|
{ // on considère que val_de_base est déjà ok
|
|
#ifdef MISE_AU_POINT
|
|
if (nb_lig*nb_col != val_de_base.Taille())
|
|
{ cout << "\nErreur : la taille de val_de_base: " << val_de_base.Taille()
|
|
<< " est differente de nb_lig*nb_col: " << nb_lig*nb_col;
|
|
cout << "void Mat_pleine::Creation_tab_val(.. \n" << endl;
|
|
Sortie(1);
|
|
}
|
|
#endif
|
|
// l'objectif est la construction de val
|
|
if (val.Taille() != 0)
|
|
// si val est déjà construit on voit s'il faut changer quelque chose
|
|
{Change_tailles_tab_val(nb_lig,nb_col);}
|
|
else
|
|
// sinon on construit
|
|
{bool memoire = false;
|
|
val.Change_taille(nb_lig);
|
|
double* pt = val_de_base.Pointeur_vect(); // init
|
|
for (int i=1;i<= nb_lig;i++)
|
|
{// il n'y a pas d'initialisation de composantes des vecteur
|
|
// elles gardent les valeurs de val_de_base
|
|
val(i)=new Vecteur(nb_col,pt,memoire);
|
|
for (int j = 1; j<= nb_col; j++)
|
|
pt++;
|
|
};
|
|
};
|
|
};
|
|
|
|
// surcharge de l'operateur de lecture typée
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
istream & operator >> (istream & entree, Mat_pleine & mat)
|
|
{ // vérification du type
|
|
string type;
|
|
entree >> type;
|
|
if (type != "Mat_pleine")
|
|
{cout << "\n*** erreur en lecture d'une matrice, on attendait Mat_pleine "
|
|
<< " et on a lue: "<< type;
|
|
Sortie (1);
|
|
return entree;
|
|
};
|
|
// les tailles
|
|
int nb_ligne, nb_colonne;
|
|
string toto;
|
|
entree >> nb_ligne >> toto >> nb_colonne;
|
|
// redimentionnement éventuelle de la matrice
|
|
mat.Initialise (nb_ligne,nb_colonne,0.0);
|
|
// on lit les composantes
|
|
entree >> mat.val_de_base ;
|
|
return entree;
|
|
};
|
|
|
|
// surcharge de l'operateur d'ecriture typée
|
|
#ifndef MISE_AU_POINT
|
|
inline
|
|
#endif
|
|
ostream & operator << ( ostream & sort,const Mat_pleine & mat)
|
|
{ // un indicateur donnant le type puis les datas
|
|
sort << "Mat_pleine " << mat.Nb_ligne() << " X "<< mat.Nb_colonne() << " "
|
|
<< mat.val_de_base ;
|
|
return sort;
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|