// 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) . // // 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 . // // For more information, please consult: . //#include "Debug.h" # include using namespace std; //introduces namespace std #include #include #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 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 Mat_pleine::Resol_syst (const Tableau & 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 ..)\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 ..)\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 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 c(dimtab); Cramer(b,c); return c; break; } default: {Tableau 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 & Mat_pleine::Resol_systID (Tableau & 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 ..)\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 ..)\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 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 Mat_pleine::Simple_Resol_syst (const Tableau & 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 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 c(dimtab); Cramer(b,c); return c; break; } default: { Tableau 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 & Mat_pleine::Simple_Resol_systID (Tableau & 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 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 = " <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 = " <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 Mat_pleine::Coordonnee_Base_associee() const { int nb_col = Nb_colonne(); Tableau 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 Mat_pleine::CoordonneeH_Base_associee() const { int nb_col = Nb_colonne(); Tableau 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 Mat_pleine::CoordonneeB_Base_associee() const { int nb_col = Nb_colonne(); Tableau 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 & b,Tableau & 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