// FICHIER : MatLapack.cc // CLASSE : MatLapack // 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 using namespace std; //introduces namespace std #include "MatLapack.h" #include "Sortie.h" #include "ConstMath.h" #include "MathUtil.h" #include "MatDiag.h" #include #include #include "CharUtil.h" #include "ExceptionsMatrices.h" #include "ParaGlob.h" #ifdef ENLINUX_2009 #include "cblas.h" #else #ifdef SYSTEM_MAC_OS_X_unix // #include // #include "Headers/cblas.h" #include #endif #endif #ifdef SYSTEM_MAC_OS_X #include #endif #ifndef MatLapack_H_deja_inclus #ifndef MISE_AU_POINT inline #endif // il est nécessaire ensuite de définir les données pour l'utiliser MatLapack::MatLapack (): Mat_abstraite(RECTANGLE_LAPACK,GAUSS,RIEN_PRECONDITIONNEMENT) ,mat(),ipiv(NULL),ptB(NULL),travail(1) ,nb_lign(0),nb_col(0),ldb(1),kl(0),ku(0),lda(1) // seules les grandeurs pour le stockage rectangle sont bien initialisées { Coor = &MatLapack::Coor_GE; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_GE_const; }; #ifndef MISE_AU_POINT inline #endif // Constructeur pour une matrice carree quelconque, ou symétrique // se servant d'un nombre de lignes = colonnes, et eventuellement // d'une valeur d'initialisation MatLapack::MatLapack (int nb_l,int nb_c, bool symetrique, double val_init ,Enum_type_resolution_matri type_resol ,Enum_preconditionnement type_precondi): Mat_abstraite(CARREE_LAPACK,type_resol,type_precondi) ,mat(0) // on le met à 0 au début ,ipiv(NULL),ptB(NULL),travail(1) ,nb_lign(nb_l),nb_col(nb_c),ldb(MaX(1,nb_l)),lda(MaX(1,nb_l)) ,kl(0),ku(0) // ne servent pas { // on rectifie le type de matrice if (symetrique) {type_matrice = CARREE_SYMETRIQUE_LAPACK; Coor = &MatLapack::Coor_PP; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_PP_const; if (type_resol == RIEN_TYPE_RESOLUTION_MATRI) type_resolution = CHOLESKY; // par défaut si rien n'est défini mat.Change_taille(nb_l*(nb_c-1)/2+nb_c,val_init); } else // sinon on n'est pas en symétrique { Coor = &MatLapack::Coor_GE; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_GE_const; mat.Change_taille(nb_l*nb_c,val_init); }; }; #ifndef MISE_AU_POINT inline #endif // Constructeur pour une matrice bande quelconque, ou symétrique // se servant d'un nombre de lignes, de = colonnes, et eventuellement // d'une valeur d'initialisation et d'un type de résolution MatLapack::MatLapack (Enum_matrice enu_mat, int lb_totale,int dim ,bool symetrique, double val_init ,Enum_type_resolution_matri type_resol ,Enum_preconditionnement type_precondi ): Mat_abstraite(enu_mat,type_resol,type_precondi) ,mat() ,nb_lign(dim),nb_col(lb_totale) ,ipiv(NULL),ptB(NULL),travail(1) ,ldb(MaX(1,dim)),kl(0),ku(0),lda(0) { if (enu_mat == BANDE_NON_SYMETRIQUE_LAPACK) {// les colonnes de 1 à lb= (lb_totale-1)/2 sont utilisée par lapack // pour les routines d'herezh, seules les valeurs à partir de la colonne 1+lb sont utilisées // int lb = (lb_totale-1)/2; kl=ku=((lb_totale-1)/2); lda=2*kl+ku+1; Coor = &MatLapack::Coor_GB; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_GB_const; if (type_resolution == CHOLESKY) #ifdef MISE_AU_POINT { cout << "\n ** attention, le type de resolution par defaut avec BANDE_NON_SYMETRIQUE_LAPACK " << " est GAUSS " ; }; #endif if ((type_resolution == RIEN_TYPE_RESOLUTION_MATRI)||(type_resolution == CHOLESKY)) type_resolution = GAUSS; // par défaut si rien n'est défini } else if (enu_mat == BANDE_SYMETRIQUE_LAPACK) {// là on ne stocke que la partie symétrique, on suppose de plus que la matrice // est définie positive, enfin il n'y a pas de stockage supplémentaire utilisé par lapack // pour les routines d'herezh, les valeurs à partir de la colonne 1 sont utilisées // int lb = lb_totale; kl=ku=lb_totale-1; lda=ku+1; Coor = &MatLapack::Coor_PB; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_PB_const; if (type_resolution == RIEN_TYPE_RESOLUTION_MATRI) type_resolution = CHOLESKY; // par défaut si rien n'est défini } //*** en chantier // else if (enu_mat == TRIDIAGONALE_GENE_LAPACK) // {// matrice quelconque tri: là on stocke toute la matrice // // est définie positive, enfin il n'y a pas de stockage supplémentaire utilisé par lapack // // pour les routines d'herezh, les valeurs à partir de la colonne 1 sont utilisées // // int lb = lb_totale; // kl=ku=lb_totale-1; // lda=ku+1; // Coor = &MatLapack::Coor_PB; // association pour la récupération des coordonnées // Coor_const = &MatLapack::Coor_PB_const; // if (type_resolution == RIEN_TYPE_RESOLUTION_MATRI) // type_resolution = CHOLESKY; // par défaut si rien n'est défini // } // else if (enu_mat == BANDE_SYMETRIQUE_LAPACK) // {// là on ne stocke que la partie symétrique, on suppose de plus que la matrice // // est définie positive, enfin il n'y a pas de stockage supplémentaire utilisé par lapack // // pour les routines d'herezh, les valeurs à partir de la colonne 1 sont utilisées // // int lb = lb_totale; // kl=ku=lb_totale-1; // lda=ku+1; // Coor = &MatLapack::Coor_PB; // association pour la récupération des coordonnées // Coor_const = &MatLapack::Coor_PB_const; // if (type_resolution == RIEN_TYPE_RESOLUTION_MATRI) // type_resolution = CHOLESKY; // par défaut si rien n'est défini // } //*** fin chantier ; // def du conteneur de la matrice mat.Change_taille(lda*ldb,val_init); #ifdef MISE_AU_POINT // pour l'instant on ne considère que des bandes d'étendues égales de part et autres de la diagonale if ((enu_mat == BANDE_NON_SYMETRIQUE_LAPACK) && ((lb_totale % 2) == 0)) { cout << "erreur de dimensionnement d'une matrice bande lapack "; cout << " largeur de bande = " << lb_totale << " devrait etre un nombre impair " ; cout << "\n MatLapack::MatLapack (... " << endl; Sortie(1); }; #endif #ifdef MISE_AU_POINT // vérif que l'on est bien en bande lapack if ((enu_mat != BANDE_SYMETRIQUE_LAPACK) && (enu_mat != BANDE_NON_SYMETRIQUE_LAPACK)) { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(enu_mat) << "\n MatLapack::MatLapack (Enum_matrice enu_mat,..."; Sortie(1); }; if ((nb_lign < 0) || (nb_col < 0)) { cout << "erreur de dimensionnement d une matrice bande"; cout << " LB = " << nb_col << " dim = " << nb_lign << '\n'; cout << "\n MatLapack::MatLapack (Enum_matrice enu_mat..." << endl; Sortie(1); }; #endif }; // Constructeur de copie #ifndef MISE_AU_POINT inline #endif MatLapack::MatLapack (const MatLapack& mat_pl) : Mat_abstraite(mat_pl) ,mat(mat_pl.mat) ,nb_lign(mat_pl.nb_lign),nb_col(mat_pl.nb_col) ,ipiv(NULL),ptB(NULL),travail(1) ,ldb(mat_pl.ldb),lda(mat_pl.lda),ku(mat_pl.ku),kl(mat_pl.kl) { if (type_matrice == CARREE_SYMETRIQUE_LAPACK) {Coor = &MatLapack::Coor_PP; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_PP_const; } else if(type_matrice == CARREE_LAPACK) // sinon on n'est pas en symétrique { Coor = &MatLapack::Coor_GE; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_GE_const; } else if (type_matrice == BANDE_NON_SYMETRIQUE_LAPACK) {Coor = &MatLapack::Coor_GB; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_GB_const; } else if (type_matrice == BANDE_SYMETRIQUE_LAPACK) {Coor = &MatLapack::Coor_PB; // association pour la récupération des coordonnées Coor_const = &MatLapack::Coor_PB_const; } //*** en chantier // else if (enu_mat == TRIDIAGONALE_GENE_LAPACK) // {// matrice quelconque tri: là on stocke toute la matrice // // est définie positive, enfin il n'y a pas de stockage supplémentaire utilisé par lapack // // pour les routines d'herezh, les valeurs à partir de la colonne 1 sont utilisées // // int lb = lb_totale; // kl=ku=lb_totale-1; // lda=ku+1; // Coor = &MatLapack::Coor_PB; // association pour la récupération des coordonnées // Coor_const = &MatLapack::Coor_PB_const; // if (type_resolution == RIEN_TYPE_RESOLUTION_MATRI) // type_resolution = CHOLESKY; // par défaut si rien n'est défini // } // else if (enu_mat == BANDE_SYMETRIQUE_LAPACK) // {// là on ne stocke que la partie symétrique, on suppose de plus que la matrice // // est définie positive, enfin il n'y a pas de stockage supplémentaire utilisé par lapack // // pour les routines d'herezh, les valeurs à partir de la colonne 1 sont utilisées // // int lb = lb_totale; // kl=ku=lb_totale-1; // lda=ku+1; // Coor = &MatLapack::Coor_PB; // association pour la récupération des coordonnées // Coor_const = &MatLapack::Coor_PB_const; // if (type_resolution == RIEN_TYPE_RESOLUTION_MATRI) // type_resolution = CHOLESKY; // par défaut si rien n'est défini // } //*** fin chantier ; }; #ifndef MISE_AU_POINT inline #endif MatLapack::~MatLapack () // Destructeur { if (ipiv != NULL) delete [] ipiv; if (ptB != NULL) delete ptB; }; // fonction permettant de creer une nouvelle instance d'element #ifndef MISE_AU_POINT inline #endif Mat_abstraite * MatLapack::NouvelElement() const { Mat_abstraite * a; a = new MatLapack(*this); return a; }; // surcharge de l'opérateur d'affectation: cas des matrices abstraites // il faut que les matrices soient ici de type et de tailles identiques sinon erreur #ifndef MISE_AU_POINT inline #endif Mat_abstraite & MatLapack::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 << "MatLapack::operator = ( const Mat_abstraite & b)" << endl; Sortie(1); } #endif const MatLapack & mat_pl = *((MatLapack*) & b); (*this)=mat_pl; // retour 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 MatLapack::Transfert_vers_mat( Mat_abstraite & b ) {b.Initialise(0.); // init de la matrice // puis on transfert switch (type_matrice) {case RECTANGLE_LAPACK: case CARREE_LAPACK: case CARREE_SYMETRIQUE_LAPACK: {int le_max = nb_lign+1; // +1 pour un test "inférieur pure" sur la boucle qui suit for (int i=1;i< le_max;i++) {int le_maxj = nb_col+1; // +1 pour un test "inférieur pure" sur la boucle qui suit for (int j=1;j< le_maxj;j++) b(i,j)= (this->*Coor_const)(i,j); }; break; } case BANDE_NON_SYMETRIQUE_LAPACK: {int lb = ku; int le_max = nb_lign+1; // +1 pour un test "inférieur pure" sur la boucle qui suit for (int i=1;i< le_max;i++) {int le_maxj = MiN(nb_lign,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit for (int j= MaX(1,i-lb);j< le_maxj;j++) b(i,j)=(*this)(i,j); }; break; } case BANDE_SYMETRIQUE_LAPACK: {int lb = ku; // largeur de bande hors diagonale int le_max = nb_lign+1; // +1 pour un test "inférieur pure" sur la boucle qui suit for (int i=1;i< le_max;i++) {int le_maxj = MiN(nb_lign,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit for (int j= MaX(1,i-lb);j< le_maxj;j++) b(i,j)=(*this)(i,j); }; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Affiche ()const "< erreur if ((nb_lign != mat_pl.nb_lign) || (nb_col != mat_pl.nb_col)) {cout << "erreur dans l'operation d'affectation"; cout << " les matrices ont un nombre de lignes ou colonnes différents: nb ligne= " << nb_lign << " " << mat_pl.nb_lign << " nb colonne= " << nb_col << " " << mat_pl.nb_col << '\n'; cout << "MatLapack::operator = ( const MatLapack & )" << endl; Sortie(1); }; #endif // les deux matrices sont identiques en type et taille on affecte basiquement // donc toutes les variables intermédiaires de dimensionnement sont identiques, reste le contenu de la matrice mat = mat_pl.mat; // en fait dans le cas d'un stockage bande, on applique également pour la partie travail // qui sert pour la résolution uniquement, cependant, comme c'est difficile de séparer les grandeurs utiles (i,j) // et celles de travail, on applique à toute la matrice (la partie travail sera de toute manière recalculée avant emploi // retour return (*this); }; // Surcharge de l'operateur += : addition d'une matrice a la matrice courante // la matrice à additionner doit être de même type ou diagonale, de même nombre // de ligne #ifndef MISE_AU_POINT inline #endif void MatLapack::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 << "MatLapack::operator+= (const Mat_abstraite& b)" << endl; Sortie(1); }; #endif if (b.Type_matrice() != DIAGONALE) { const MatLapack & mat_pl = *((MatLapack*) & b); this->operator+= (mat_pl); // dans le cas de bande : cf. NBM operator= ( const MatLapack& mat_pl) } else // cas d'une matrice argument diagonale { #ifdef MISE_AU_POINT // il faut que le nombre de ligne soit identique if (nb_lign != b.Nb_ligne()) {cout << " les matrices ont un nombre de ligne différent " << nb_lign << " " << b.Nb_ligne() << '\n'; cout << "MatLapack::operator+= (const Mat_abstraite& b)" << endl; Sortie(1); }; #endif const MatDiag & mat_d = *((MatDiag*) & b); int le_max = nb_lign+1;// +1 pour un test "inférieur pure" sur la boucle qui suit for (int i=1;i< le_max;i++) (*this)(i,i) += mat_d(i,i); // mat += mat_d.Vecteur_MatDiag(); ?? une erreur 2 mai 2012 }; }; // Surcharge de l'operateur -= : soustraction d'une matrice a la matrice courante #ifndef MISE_AU_POINT inline #endif void MatLapack::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 << "MatLapack::operator-= (const Mat_abstraite& b)" << endl; Sortie(1); }; #endif if (b.Type_matrice() != DIAGONALE) { const MatLapack & mat_pl = *((MatLapack*) & b); this->operator-= (mat_pl); // dans le cas de bande : cf. NBM operator= ( const MatLapack& mat_pl) } else // cas d'une matrice argument diagonale { const MatDiag & mat_d = *((MatDiag*) & b); #ifdef MISE_AU_POINT // il faut que le nombre de ligne soit identique if (nb_lign != b.Nb_ligne()) {cout << " les matrices ont un nombre de ligne différent " << nb_lign << " " << b.Nb_ligne() << '\n'; cout << "MatLapack::operator-= (const Mat_abstraite& b)" << endl; Sortie(1); }; #endif int le_max = nb_lign; // +1 pour un test "inférieur pure" sur la boucle qui suit for (int i=1;i< le_max;i++) (*this)(i,i) -= mat_d(i,i); // mat -= mat_d.Vecteur_MatDiag(); ?? une erreur 2 mai 2012 }; }; #ifndef MISE_AU_POINT inline #endif // Addition a la matrice courante de la matrice mat_pl void MatLapack::operator+= ( const MatLapack& mat_pl) { #ifdef MISE_AU_POINT // il faut que les deux matrices de type lapack soient identiques if (type_matrice != mat_pl.type_matrice) {cout << " erreur les matrices sont de types différents " << Nom_matrice(type_matrice) << " " << Nom_matrice(mat_pl.type_matrice) << '\n'; cout << "MatLapack::operator+= (const MatLapack& )" << endl; Sortie(1); }; if ( ( nb_lign!=mat_pl.nb_lign )|| ( nb_col!=mat_pl.nb_col ) ) {cout << "Erreur : dimensions des matrices non egales\n"; cout << "MatLapack::OPERATOR+= (const MatLapack& )\n"; Sortie(1); }; #endif // les deux matrices sont identiques en type et taille on affecte basiquement mat += mat_pl.mat; // dans le cas de bande : cf. NBM operator= ( const MatLapack& mat_pl) }; #ifndef MISE_AU_POINT inline #endif // Soustrait a la matrice courante la matrice mat_pl void MatLapack::operator-= ( const MatLapack& mat_pl) { #ifdef MISE_AU_POINT if (type_matrice != mat_pl.type_matrice) {cout << " erreur les matrices sont de types différents " << Nom_matrice(type_matrice) << " " << Nom_matrice(mat_pl.type_matrice) << '\n'; cout << "MatLapack::operator-= (const MatLapack& )" << endl; Sortie(1); }; if ( ( nb_lign!=mat_pl.nb_lign )|| ( nb_col!=mat_pl.nb_col ) ) {cout << "Erreur : dimensions des matrices non egales\n"; cout << "MatLapack::OPERATOR-= (const MatLapack& )\n"; Sortie(1); }; #endif // les deux matrices sont identiques en type et taille on affecte basiquement mat -= mat_pl.mat; // dans le cas de bande : cf. NBM operator= ( const MatLapack& mat_pl) }; #ifndef MISE_AU_POINT inline #endif //multiplication de la matrice courante par un scalaire void MatLapack::operator*= (double coeff) { mat *= coeff; }; // Surcharge de l'operateur == : test d'egalite entre deux matrices #ifndef MISE_AU_POINT inline #endif int MatLapack::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 << "MatLapack::operator+= (const Mat_abstraite& b)" << endl; Sortie(1); } #endif const MatLapack & mat_pl = *((MatLapack*) & b); return this->operator==(mat_pl); }; #ifndef MISE_AU_POINT inline #endif // Acces aux valeurs de la matrices en écriture // i : indice de ligne, j : indice de colonne double& MatLapack::operator () (int i, int j) { #ifdef MISE_AU_POINT switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: case CARREE_SYMETRIQUE_LAPACK: {if ((i < 1) || (i>nb_lign)) {cout << "erreur d acces aux composantes d une matrice rectangulaire"; cout << "\n erreur l'indice en i; " << i << " est impossible " << " car nb_ligne de la matrice = " << nb_lign << "\n double& MatLapack::operator () ( int i, int j)" << endl; Sortie(1); }; if ((j < 1) || (j > nb_col)) {cout << "erreur d acces aux composantes d une matrice rectangulaire"; cout << "\n erreur l'indice en j; " << j << " est impossible " << " car nb_col de la matrice = " << nb_col << "\n double& MatLapack::operator () ( int i, int j)" << endl; Sortie(1); }; break; } case BANDE_NON_SYMETRIQUE_LAPACK:case BANDE_SYMETRIQUE_LAPACK: { if (i<1 || (abs(i-j) > ku)) {cout << "erreur d acces aux composantes d une matrice bande lapack"; cout << " indice hors borne (" << i << "," << j <<"), lb = " << ku; cout << ", condition inacceptable: i<1 || abs(i-j)="<< abs(i-j)<< " >= lb " << '\n'; cout << "double& MatLapack::operator () (int i, int j )" << endl; }; if (j<1 || j>nb_lign) {cout << "erreur d acces aux composantes d une matrice bande"; cout << " second indice hors borne j = " << j <<" dim = " << nb_lign << '\n'; cout << "double& MatLapack::operator () (int i, int j )" << endl; }; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::operator () (int i, int j) "<*Coor)(i,j); }; #ifndef MISE_AU_POINT inline #endif // Acces aux valeurs de la matrices en lecture // cas ou l'on ne veut pas modifier les valeurs // i : indice de ligne, j : indice de colonne // !!! important, si l'élément n'existe pas du au type de stockage // utilisé, (mais que les indices sont possible) le retour est 0 double MatLapack::operator () ( int i, int j) const {double toto; #ifdef MISE_AU_POINT if ((i < 1) || (i>nb_lign)) {cout << "erreur d acces aux composantes d une matrice "; cout << "\n erreur l'indice en i; " << i << " est impossible " << " car nb_ligne de la matrice = " << nb_lign << "\n MatLapack::operator () ( int i, int j) const " << endl; Sortie(1); }; switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: case CARREE_SYMETRIQUE_LAPACK: {if ((j < 1) || (j > nb_col)) {cout << "erreur d acces aux composantes d une matrice "; cout << "\n erreur l'indice en j; " << j << " est impossible " << " car nb_col de la matrice = " << nb_col << "\n MatLapack::operator () ( int i, int j) const " << endl; Sortie(1); }; break; } case BANDE_NON_SYMETRIQUE_LAPACK: case BANDE_SYMETRIQUE_LAPACK: // {if (i<1 || (abs(i-j) >= (nb_col-1)/2 +1)) {if (i<1) {cout << "erreur d acces aux composantes d une matrice bande lapack"; cout << " indice hors borne (" << i << "," << j <<"), lb = " << ku; cout << ", condition acceptable: i<1 || abs(i-j) >= 2*lb " << '\n'; cout << "MatLapack::operator () ( int i, int j) const" << endl; Sortie(1); }; if (j<1 || j>nb_lign) {cout << "erreur d acces aux composantes d une matrice bande"; cout << " second indice hors borne j = " << j <<" dim = " << nb_lign << '\n'; cout << "MatLapack::operator () ( int i, int j) const" << endl; Sortie(1); }; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::operator () (int i, int j)const "<*Coor_const)(i,j); break;} case BANDE_NON_SYMETRIQUE_LAPACK: case BANDE_SYMETRIQUE_LAPACK: { if (abs(i-j) >= 2*kl) { return 0;} else {return (this->*Coor_const)(i,j);}; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::operator () (int i, int j)const "<*Coor_const)(i,j) << "\t"; cout << "}\n"; }; cout << "\n"; break; } case BANDE_NON_SYMETRIQUE_LAPACK: {cout << "\n affichage d une matrice bande non symetrique de largeur= " << (2*ku+1) << " dimension= " << nb_lign << '\n'; int lb = ku; int le_max = nb_lign+1; // +1 pour un test "inférieur pure" sur la boucle qui suit for (int i=1;i< le_max;i++) {int le_maxj = MiN(nb_lign,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit for (int j= MaX(1,i-lb);j< le_maxj;j++) {cout << setw(4) << " i= " << i << " j= " << j << " * " << setw(14) << setprecision(7) << (*this)(i,j) << '\n'; }; }; cout << endl ; break; } case BANDE_SYMETRIQUE_LAPACK: {cout << "\n affichage d une matrice bande symetrique de largeur= " << 2*ku+1 << " dimension= " << nb_lign << '\n'; int lb = ku; // largeur de bande hors diagonale int le_max = nb_lign+1; // +1 pour un test "inférieur pure" sur la boucle qui suit for (int i=1;i< le_max;i++) {int le_maxj = MiN(nb_lign,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit for (int j= MaX(1,i-lb);j< le_maxj;j++) {cout << setw(4) << " i= " << i << " j= " << j << " * " << setw(14) << setprecision(7) << (*this)(i,j) << '\n'; }; }; cout << endl ; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Affiche ()const "<Libere(); }; #ifndef MISE_AU_POINT inline #endif // changement de taille avec initialisation non nulle éventuelle // si les tailles existantes sont identiques, on ne fait que initialiser void MatLapack::Change_taille(int nb_li,int nb_co, const double& val_init) { #ifdef MISE_AU_POINT if ((nb_li < 0) || (nb_co < 0)) {cout << "erreur de dimensionnement d une matrice "; cout << " nb_li = " << nb_li << " nb_co = " << nb_co << '\n'; cout << "void MatLapack::Change_taille(... " << endl; } #endif if ((nb_li != nb_lign) || (nb_co != nb_col)) { ldb = MaX(1,nb_li); this->Libere(); nb_lign = nb_li; nb_col = nb_co; bool matrice_a_dimensionner = false; // init switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: {// on change de taille lda= MaX(1,nb_lign); kl=ku=0; matrice_a_dimensionner=true; break; } case CARREE_SYMETRIQUE_LAPACK: {// on change de taille, on utilise un stockage compacté, qui utilise la moitié de la taille théorique lda= MaX(1,nb_lign); kl=ku=0; mat.Change_taille(nb_lign*(nb_col+1)/2,val_init); // division entière ! matrice_a_dimensionner=false; // pour signaler que le dimensionnement est déjà fait break; } case BANDE_NON_SYMETRIQUE_LAPACK: {// calcul des grandeurs relatives à la largeur de bande #ifdef MISE_AU_POINT // pour l'instant on ne considère que des bandes d'étendues symétriques de part et autres de la diagonale if ((nb_co % 2) == 0) { cout << "erreur de dimensionnement d'une matrice bande non symetrique lapack "; cout << " largeur de bande = " << nb_co << " devrait etre un nombre impair " ; cout << "\n MatLapack::Change_taille(... " << endl; Sortie(1); }; #endif kl = (nb_col-1)/2; ku=kl; lda = 2*kl+ku+1; matrice_a_dimensionner=true; break; } case BANDE_SYMETRIQUE_LAPACK: {// là on ne stocke que la partie symétrique, on suppose de plus que la matrice // est définie positive, enfin il n'y a pas de stockage supplémentaire utilisé par lapack // pour les routines d'herezh, les valeurs à partir de la colonne 1 sont utilisées // int lb = lb_totale; kl = ku = nb_col-1; lda = nb_col; matrice_a_dimensionner=true; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Change_taille(.. "<*Coor_const)(i,j),(this->*Coor_const)(j,i))) // test d'egalite de la ieme jieme composante return 0; return 1; break; } case BANDE_NON_SYMETRIQUE_LAPACK: { int lb = (nb_col-1)/2; for (int i=1;i<=nb_lign;i++) for (int j=1;j*Coor_const)(i,j),(this->*Coor_const)(j,i))) // test d'egalite de la ieme jieme composante return 0; return 1; break; } case BANDE_SYMETRIQUE_LAPACK:case CARREE_SYMETRIQUE_LAPACK: { return 1; // par construction la matrice est symétrique break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Symetrie(.. "<*Coor_const)(i,j); break; } case BANDE_NON_SYMETRIQUE_LAPACK: {// nb_lign = la dimension de la matrice théorique carrée int lb=(nb_col-1)/2; int dim = nb_lign; int maxJ = MiN(dim,i+lb)+1;// +1 pour inférieur pure sur la ligne qui suit for (int j= MaX(1,i-lb);j< maxJ;j++) ret(j) = (this->*Coor_const)(i,j); break; } case BANDE_SYMETRIQUE_LAPACK: {// nb_lign = la dimension de la matrice théorique carrée int lb=ku; int maxJ=MiN(nb_lign,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit for (int j= MaX(1,i-lb);j< maxJ;j++) ret(j) = (this->*Coor_const)(i,j); break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Ligne(.. "<*Coor_const)(i,j); return ret; break; } case CARREE_SYMETRIQUE_LAPACK: {// comme la ligne adresse deux mêmes parties symétriques, il vaut mieux // sauvegarder toute la ligne Vecteur ret(nb_col); for (int j=1 ;j<=nb_col;j++) ret(j)=(this->*Coor_const)(i,j); return ret; break; } case BANDE_NON_SYMETRIQUE_LAPACK: {Vecteur ligne(nb_col); // mise a zero de ligne int lb=(nb_col-1)/2; int dim = nb_lign; int maxJ = MiN(dim,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit for (int j= MaX(1,i-lb);j< maxJ;j++) ligne(i-j+lb+1) = (this->*Coor_const)(i,j); return ligne; break; } case BANDE_SYMETRIQUE_LAPACK: {// comme la ligne adresse deux mêmes parties symétriques, il vaut mieux // sauvegarder toute la ligne int lb=nb_col-1; int dim = nb_lign; Vecteur ligne(2*lb+1); // mise a zero de ligne int le_max = MiN(dim,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit int le_min = MaX(1,i-lb); for (int j= le_min;j < le_max;j++) // for (int j= MaX(1,i);j<= MiN(dim,i+lb);j++) ligne(i-j+lb+1) = (this->*Coor_const)(i,j); return ligne; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::LigneSpe(.. "<*Coor)(i,j)=v(j); break; } case CARREE_SYMETRIQUE_LAPACK: // comme la ligne adresse deux mêmes parties symétriques, il vaut mieux // sauvegarder toute la ligne {for (int j=1 ;j<=nb_col;j++) (this->*Coor)(i,j)=v(j); break; } case BANDE_NON_SYMETRIQUE_LAPACK: {int lb=(nb_col-1)/2; int dim = nb_lign; int maxJ = MiN(dim,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit for (int j= MaX(1,i-lb);j< maxJ;j++) (this->*Coor)(i,j)=v(i-j+lb+1); break; } case BANDE_SYMETRIQUE_LAPACK: {// comme la ligne adresse deux mêmes parties symétriques, il vaut mieux // sauvegarder toute la ligne int lb=nb_col-1; int dim = nb_lign; Vecteur ligne(2*lb+1); // mise a zero de ligne int le_max = MiN(dim,i+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit int le_min = MaX(1,i-lb); for (int j= le_min;j< le_max;j++) (this->*Coor)(i,j)=v(i-j+lb+1); break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::RemplaceLigneSpe(.. "< MatLapack::Resol_syst (const Tableau & b,const double &tole, const int maxi, const int rest) { ENTIER_POUR_CLAPACK nb_SM = b.Taille(); // a priori plusieurs second membre if (ipiv == NULL) {ipiv = new ENTIER_POUR_CLAPACK [nb_lign];}; ENTIER_POUR_CLAPACK info=0; // info de sortie // on s'occupe de la matrice rectangulaire qui contient tous les seconds membres: init général // ici le type de résolution importe peu, c'est du stockage if (ptB == NULL) {ptB = new MatLapack(nb_lign,nb_SM,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT);} else // on regarde si la taille est correcte { if ((nb_lign != ptB->Nb_ligne()) || (nb_SM != ptB->Nb_colonne())) // c'est différent donc on redimentionne { ptB->Change_taille(nb_lign,nb_SM); }; }; // init particulier for (int k=1;k<=nb_SM;k++) {const Vecteur & bk=b(k); for (int i=1;i<=nb_lign;i++) (ptB->*Coor)(i,k)=bk(i); }; switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { switch (type_resolution) {case GAUSS: { #ifdef MISE_AU_POINT Verif_nb_composante(b,"Resol_syst"); #endif // appel de la routine clapack dgesv_(&nb_lign,&nb_SM,mat.v,&lda,ipiv,(*ptB).mat.v,&ldb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); return bb; } }; break; } case CARREE_SYMETRIQUE_LAPACK: { switch (type_resolution) {case CHOLESKY: {// appel de la routine clapack // /* Subroutine */ int dppsv_(char *uplo, __CLPK_integer *n, __CLPK_integer *nrhs, // __CLPK_doublereal *ap, __CLPK_doublereal *b, __CLPK_integer *ldb, __CLPK_integer *info) char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale dppsv_(&uplo,&nb_lign,&nb_SM,mat.v,(*ptB).mat.v,&ldb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); return bb; } } break; } case BANDE_NON_SYMETRIQUE_LAPACK: { switch (type_resolution) {case GAUSS: {// appel de la routine clapack // /* Subroutine */ int dgbsv_(__CLPK_integer *n, __CLPK_integer *kl, __CLPK_integer *ku, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_integer *ipiv, __CLPK_doublereal *b, // __CLPK_integer *ldb, __CLPK_integer *info); dgbsv_(&nb_lign,&kl,&ku,&nb_SM,mat.v,&lda,ipiv,(*ptB).mat.v,&ldb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles // le résultat est dans b.v break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); return bb; } }; break; } case BANDE_SYMETRIQUE_LAPACK: { switch (type_resolution) {case CHOLESKY: {// ici seule la partie sup de la largeur de bande est définie // appel de la routine clapack ///* Subroutine */ int dpbsv_(char *uplo, __CLPK_integer *n, __CLPK_integer *kd, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_doublereal *b, __CLPK_integer *ldb, // __CLPK_integer *info) __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_4_0); char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale dpbsv_(&uplo,&nb_lign,&ku,&nb_SM,mat.v,&lda,(*ptB).mat.v,&ldb,&info); GestionErreurDpbsv(info); // affichage d'erreurs éventuelles // le résultat est dans b.v break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); return bb; } }; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Resol_syst(..."; Sortie(1); }; }; // récup du résultat Tableau bksortie(nb_SM); for (int k=1;k<=nb_SM;k++) { bksortie(k).Change_taille(nb_lign); Vecteur & bksortie_k=bksortie(k); for (int i=1;i<=nb_lign;i++) bksortie_k(i) = (ptB->*Coor_const)(i,k); }; // retour des résultats return bksortie; }; //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 & MatLapack::Resol_systID (Tableau & b,const double &tole, const int maxi, const int rest) { ENTIER_POUR_CLAPACK nb_SM = b.Taille(); // a priori plusieurs second membre // init général if (ipiv == NULL) {ipiv = new ENTIER_POUR_CLAPACK [nb_lign];}; // pour les seconds membres, le type de résolution importe peu, on met une grandeur par défaut if (ptB == NULL) { ptB = new MatLapack(nb_lign,nb_SM,false,0.,GAUSS,RIEN_PRECONDITIONNEMENT);} else // on regarde si la taille est correcte { if ((nb_lign != ptB->Nb_ligne()) || (nb_SM != ptB->Nb_colonne())) // c'est différent donc on redimentionne { ptB->Change_taille(nb_lign,nb_SM); }; }; ENTIER_POUR_CLAPACK info=0; // info de sortie // init particulier for (int k=1;k<=nb_SM;k++) {const Vecteur & bk=b(k); for (int i=1;i<=nb_lign;i++) (ptB->*Coor)(i,k)=bk(i); }; switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { switch (type_resolution) {case GAUSS: { #ifdef MISE_AU_POINT Verif_nb_composante(b,"Resol_systID"); #endif // appel de la routine clapack dgesv_(&nb_lign,&nb_SM,mat.v,&lda,ipiv,(*ptB).mat.v,&ldb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); b = bb; return b; }; }; break; } case CARREE_SYMETRIQUE_LAPACK: { switch (type_resolution) {case CHOLESKY: {// appel de la routine clapack // /* Subroutine */ int dppsv_(char *uplo, __CLPK_integer *n, __CLPK_integer *nrhs, // __CLPK_doublereal *ap, __CLPK_doublereal *b, __CLPK_integer *ldb, __CLPK_integer *info) char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale dppsv_(&uplo,&nb_lign,&nb_SM,mat.v,(*ptB).mat.v,&ldb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); b = bb; return b; } } break; } case BANDE_NON_SYMETRIQUE_LAPACK: { switch (type_resolution) {case GAUSS: {// appel de la routine clapack // /* Subroutine */ int dgbsv_(__CLPK_integer *n, __CLPK_integer *kl, __CLPK_integer *ku, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_integer *ipiv, __CLPK_doublereal *b, // __CLPK_integer *ldb, __CLPK_integer *info); dgbsv_(&nb_lign,&kl,&ku,&nb_SM,mat.v,&lda,ipiv,(*ptB).mat.v,&ldb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles // le résultat est dans b.v break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); b = bb; return b; }; }; break; } case BANDE_SYMETRIQUE_LAPACK: { switch (type_resolution) {case CHOLESKY: {// ici seule la partie sup de la largeur de bande est définie // appel de la routine clapack ///* Subroutine */ int dpbsv_(char *uplo, __CLPK_integer *n, __CLPK_integer *kd, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_doublereal *b, __CLPK_integer *ldb, // __CLPK_integer *info) __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_4_0); char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale dpbsv_(&uplo,&nb_lign,&ku,&nb_SM,mat.v,&lda,(*ptB).mat.v,&ldb,&info); GestionErreurDpbsv(info); // affichage d'erreurs éventuelles // le résultat est dans b.v break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); b = bb; return b; } }; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Resol_syst(..."; Sortie(1); }; }; // récup du résultat for (int k=1;k<=nb_SM;k++) {Vecteur & bk=b(k); for (int i=1;i<=nb_lign;i++) bk(i) = (ptB->*Coor_const)(i,k); }; return b; }; #ifndef MISE_AU_POINT inline #endif // Realise le produit du vecteur vec par la matrice Vecteur MatLapack::Prod_vec_mat (const Vecteur& vec) const { #ifdef MISE_AU_POINT if (vec.Taille() != nb_lign) {cout << "erreur de taille, la dimension du vecteur: " << vec.Taille() << " devrait etre identique au nombre de ligne de la matrice= " << nb_lign << " " << "\n MatLapack::Prod_vec_mat (const Vecteur& vec)" << endl; Sortie(1); }; #endif switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK:case CARREE_SYMETRIQUE_LAPACK: { Vecteur result(nb_col); for (int j=1;j<= nb_col;j++) {double* pt=&result(j); for (int k=1; k<= nb_lign; k++) (*pt) += vec(k) * (this->*Coor_const)(k,j); }; return result; break; } case BANDE_NON_SYMETRIQUE_LAPACK:case BANDE_SYMETRIQUE_LAPACK: { // on considère que la matrice doit représenter une matrice carrée int lb=ku; int dim = nb_lign; Vecteur res(dim); for (int j=1;j<=dim;j++) for (int i= MaX(1,j-lb);i<= MiN(dim,j+lb);i++) res(j) += vec(i) * (this->*Coor_const)(i,j); return res; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Prod_vec_mat(..."; Sortie(1); }; }; Vecteur ret; // pour taire le compilo return ret; // " }; #ifndef MISE_AU_POINT inline #endif Vecteur& MatLapack::Prod_vec_mat (const Vecteur& vec,Vecteur& res) const // Realise le produit du vecteur vec par la matrice // ici on se sert du second vecteur pour le résultat { #ifdef MISE_AU_POINT if (vec.Taille() != nb_lign) {cout << "erreur de taille, la dimension du vecteur: " << vec.Taille() << " devrait etre identique au nombre de ligne de la matrice= " << nb_lign << " " << "\n MatLapack::Prod_vec_mat(const Vecteur& vec,Vecteur& result)" << endl; Sortie(1); } #endif switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK:case CARREE_SYMETRIQUE_LAPACK: { res.Change_taille(nb_col); for (int j=1;j<= nb_col;j++) { double* pt=&res(j); for (int k=1; k<= nb_lign; k++) (*pt) += vec(k) * (this->*Coor_const)(k,j); }; return res; break; } case BANDE_NON_SYMETRIQUE_LAPACK:case BANDE_SYMETRIQUE_LAPACK: { // on considère que la matrice doit représenter une matrice carrée int lb=ku; int dim = nb_lign; res.Change_taille(dim); for (int j=1;j<=dim;j++) {int maxj = MiN(dim,j+lb)+1; // +1 pour < strict dans la boucle for (int i= MaX(1,j-lb);i< maxj;i++) res(j) += vec(i) * (this->*Coor_const)(i,j); }; return res; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Prod_vec_mat(..."; Sortie(1); }; }; Vecteur ret; // pour taire le compilo return ret; // " }; //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& MatLapack::Resol_systID_2 (const Vecteur& b,Vecteur& vortie , const double &tole,const int maxi,const int rest) {// init général ENTIER_POUR_CLAPACK nb_SM = 1; // un seul second membre if (ipiv == NULL) {ipiv = new ENTIER_POUR_CLAPACK [nb_lign];}; ENTIER_POUR_CLAPACK info = 0; // info de sortie en fait c'est le retour de la fonction vortie=b; // Vecteur solution initialisé = second membre switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: {switch (type_resolution) {case GAUSS: { #ifdef MISE_AU_POINT Verif_nb_composante(b,"Resol_systID_2"); #endif // appel de la routine clapack dgesv_(&nb_lign,&nb_SM,mat.v,&lda,ipiv,vortie.v,&ldb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles break; } default: { Mat_abstraite::Resolution_syst(b,vortie,tole,maxi,rest);}; }; break; } case BANDE_NON_SYMETRIQUE_LAPACK: {switch (type_resolution) {case GAUSS: {// appel de la routine clapack // /* Subroutine */ int dgbsv_(__CLPK_integer *n, __CLPK_integer *kl, __CLPK_integer *ku, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_integer *ipiv, __CLPK_doublereal *b, // __CLPK_integer *ldb, __CLPK_integer *info); dgbsv_(&nb_lign,&kl,&ku,&nb_SM,mat.v,&lda,ipiv,vortie.v,&ldb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles break; } default: { Mat_abstraite::Resolution_syst(b,vortie,tole,maxi,rest);}; }; break; } case BANDE_SYMETRIQUE_LAPACK: { switch (type_resolution) {case CHOLESKY: {// ici seule la partie sup de la largeur de bande est définie // appel de la routine clapack ///* Subroutine */ int dpbsv_(char *uplo, __CLPK_integer *n, __CLPK_integer *kd, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_doublereal *b, __CLPK_integer *ldb, // __CLPK_integer *info) __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_4_0); char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale dpbsv_(&uplo,&nb_lign,&ku,&nb_SM,mat.v,&lda,vortie.v,&ldb,&info); GestionErreurDpbsv(info); // affichage d'erreurs éventuelles // le résultat est dans vortie.v break; } default: { Mat_abstraite::Resolution_syst(b,vortie,tole,maxi,rest);}; }; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Resol_syst(..."; Sortie(1); }; }; // retour return vortie; }; // ===== RÉSOLUTION EN DEUX TEMPS ================ : // 1) préparation de la matrice donc modification de la matrice // ici on calcul la factorisation LU de la matrice #ifndef MISE_AU_POINT inline #endif void MatLapack::Preparation_resol() { // init général if (ipiv == NULL) {ipiv = new ENTIER_POUR_CLAPACK [nb_lign];}; // normalement ipiv doit avoir ici ENTIER_POUR_CLAPACK info = 0; // info de sortie en fait c'est le retour de la fonction switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { switch (type_resolution) { case GAUSS: { // appel de la routine lapack dgetrf_(&nb_lign,&nb_col,mat.v,&lda,ipiv,&info); break; } // dans les autres cas on ne fait rien default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Preparation_resol (.. "< MatLapack::Simple_Resol_syst (const Tableau & b,const double &tol ,const int maxi,const int restart ) const { ENTIER_POUR_CLAPACK nb_SM = 1; // un seul second membre à la fois if ((type_matrice != BANDE_SYMETRIQUE_LAPACK) && (ipiv == NULL)) { cout << "\n erreur: la methode MatLapack::Preparation_resol() n'a pas ete appeled " << " le tableau ipiv n'est pas correcte, on ne peut pas continuer ! " << "\n MatLapack::Simple_Resol_syst (Tableau &.... "; Sortie(1); }; // #ifdef MISE_AU_POINT // Verif_nb_composante(b,"Simple_Resol_syst"); // #endif ENTIER_POUR_CLAPACK ldb = MaX(1,nb_lign); ENTIER_POUR_CLAPACK info = 0; // info de sortie en fait c'est le retour de la fonction char trans = 'N'; // "No transpose" // comme la méthode est const, on doit utiliser des cast, ce qui n'est pas sûr mais difficile de faire autrement ! double * matric_v = (double *) mat.v; // on impose un cast ENTIER_POUR_CLAPACK * ipiva = (ENTIER_POUR_CLAPACK*) ipiv; // "" // toujour à cause du const, on est obligé d'utiliser des variables intermédiaires ENTIER_POUR_CLAPACK nb_ligne=nb_lign; ENTIER_POUR_CLAPACK ldaa = lda; ENTIER_POUR_CLAPACK ldbb = ldb; ENTIER_POUR_CLAPACK kll = kl ; ENTIER_POUR_CLAPACK kuu = ku ; // appel de la routine clapack int nb_vrai_sm=b.Taille(); Tableau bretour(b); switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { switch (type_resolution) { case GAUSS: { #ifdef MISE_AU_POINT Verif_nb_composante(b,"Simple_Resol_systID"); #endif // appel de la routine clapack // /* Subroutine */ int dgetrs_(char *trans, __CLPK_integer *n, __CLPK_integer *nrhs, // __CLPK_doublereal *a, __CLPK_integer *lda, __CLPK_integer *ipiv, __CLPK_doublereal *b, __CLPK_integer * // ldb, __CLPK_integer *info); for (int im=1;im<=nb_vrai_sm;im++) dgetrs_(&trans,&nb_ligne,&nb_SM,matric_v,&ldaa,ipiva,bretour(im).v,&ldbb,&info); break; } default: { Mat_abstraite::Resolution_syst(b,bretour,tol,maxi,restart);}; }; break; } case CARREE_SYMETRIQUE_LAPACK: { switch (type_resolution) {case CHOLESKY: {// appel de la routine clapack // /* Subroutine */ int dpptrs_(char *uplo, __CLPK_integer *n, __CLPK_integer *nrhs, // __CLPK_doublereal *ap, __CLPK_doublereal *b, __CLPK_integer *ldb, __CLPK_integer *info) char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale for (int im=1;im<=nb_vrai_sm;im++) {dpptrs_(&uplo,&nb_ligne,&nb_SM,matric_v,bretour(im).v,&ldbb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles }; break; } default: { Mat_abstraite::Resolution_syst(b,bretour,tol,maxi,restart);}; } break; } case BANDE_NON_SYMETRIQUE_LAPACK: { switch (type_resolution) { case GAUSS: {// appel de la routine clapack // /* Subroutine */ int dgbtrs_(char *trans, __CLPK_integer *n, __CLPK_integer *kl, __CLPK_integer * // ku, __CLPK_integer *nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_integer *ipiv, // __CLPK_doublereal *b, __CLPK_integer *ldb, __CLPK_integer *info); for (int im=1;im<=nb_vrai_sm;im++) dgbtrs_(&trans,&nb_ligne,&kll,&kuu,&nb_SM,matric_v,&ldaa,ipiva,bretour(im).v,&ldbb,&info); break; } default: { Mat_abstraite::Resolution_syst(b,bretour,tol,maxi,restart);}; }; break; } case BANDE_SYMETRIQUE_LAPACK: { switch (type_resolution) { case CHOLESKY: {// appel de la routine clapack // /* Subroutine */ int dpbtrs_(char *uplo, __CLPK_integer *n, __CLPK_integer *kd, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_doublereal *b, __CLPK_integer *ldb, // __CLPK_integer *info) __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_4_0); char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale for (int im=1;im<=nb_vrai_sm;im++) dpbtrs_(&uplo,&nb_ligne,&kuu,&nb_SM,matric_v,&ldaa,bretour(im).v,&ldbb,&info); GestionErreurDpbsv(info); // affichage d'erreurs éventuelles break; } default: { Mat_abstraite::Resolution_syst(b,bretour,tol,maxi,restart);}; }; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Simple_Resol_syst (..."; Sortie(1); }; }; return bretour; }; // 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 & MatLapack::Simple_Resol_systID (Tableau & b,const double &tol ,const int maxi,const int restart ) const { ENTIER_POUR_CLAPACK nb_SM = 1; // un seul second membre à la fois if ((type_matrice != BANDE_SYMETRIQUE_LAPACK) && (ipiv == NULL)) { cout << "\n erreur: la methode MatLapack::Preparation_resol() n'a pas ete appelee " << " le tableau ipiv n'est pas correcte, on ne peut pas continuer ! " << "\n MatLapack::Simple_Resol_systID (Tableau &.... "; Sortie(1); }; // #ifdef MISE_AU_POINT // Verif_nb_composante(b,"Simple_Resol_systID"); // #endif ENTIER_POUR_CLAPACK ldb = MaX(1,nb_lign); ENTIER_POUR_CLAPACK info = 0; // info de sortie en fait c'est le retour de la fonction char trans = 'N'; // "No transpose" // comme la méthode est const, on doit utiliser des cast, ce qui n'est pas sûr mais difficile de faire autrement ! double * matric_v = (double *) mat.v; // on impose un cast ENTIER_POUR_CLAPACK * ipiva = (ENTIER_POUR_CLAPACK*) ipiv; // "" // toujour à cause du const, on est obligé d'utiliser des variables intermédiaires ENTIER_POUR_CLAPACK nb_ligne=nb_lign; ENTIER_POUR_CLAPACK ldaa = lda; ENTIER_POUR_CLAPACK ldbb = ldb; ENTIER_POUR_CLAPACK kll = kl ; ENTIER_POUR_CLAPACK kuu = ku ; // appel de la routine clapack int nb_vrai_sm=b.Taille(); switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { switch (type_resolution) { case GAUSS: { #ifdef MISE_AU_POINT Verif_nb_composante(b,"Simple_Resol_systID"); #endif // appel de la routine clapack // /* Subroutine */ int dgetrs_(char *trans, __CLPK_integer *n, __CLPK_integer *nrhs, // __CLPK_doublereal *a, __CLPK_integer *lda, __CLPK_integer *ipiv, __CLPK_doublereal *b, __CLPK_integer * // ldb, __CLPK_integer *info); for (int im=1;im<=nb_vrai_sm;im++) dgetrs_(&trans,&nb_ligne,&nb_SM,matric_v,&ldaa,ipiva,b(im).v,&ldbb,&info); break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart); b = bb; }; }; break; } case CARREE_SYMETRIQUE_LAPACK: { switch (type_resolution) {case CHOLESKY: {// appel de la routine clapack // /* Subroutine */ int dpptrs_(char *uplo, __CLPK_integer *n, __CLPK_integer *nrhs, // __CLPK_doublereal *ap, __CLPK_doublereal *b, __CLPK_integer *ldb, __CLPK_integer *info) char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale for (int im=1;im<=nb_vrai_sm;im++) {dpptrs_(&uplo,&nb_ligne,&nb_SM,matric_v,b(im).v,&ldbb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles }; break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart); b = bb; }; } break; } case BANDE_NON_SYMETRIQUE_LAPACK: { switch (type_resolution) { case GAUSS: {// appel de la routine clapack // /* Subroutine */ int dgbtrs_(char *trans, __CLPK_integer *n, __CLPK_integer *kl, __CLPK_integer * // ku, __CLPK_integer *nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_integer *ipiv, // __CLPK_doublereal *b, __CLPK_integer *ldb, __CLPK_integer *info); for (int im=1;im<=nb_vrai_sm;im++) dgbtrs_(&trans,&nb_ligne,&kll,&kuu,&nb_SM,matric_v,&ldaa,ipiva,b(im).v,&ldbb,&info); break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart); b = bb; }; }; break; } case BANDE_SYMETRIQUE_LAPACK: { switch (type_resolution) { case CHOLESKY: {// appel de la routine clapack // /* Subroutine */ int dpbtrs_(char *uplo, __CLPK_integer *n, __CLPK_integer *kd, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_doublereal *b, __CLPK_integer *ldb, // __CLPK_integer *info) __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_4_0); char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale for (int im=1;im<=nb_vrai_sm;im++) dpbtrs_(&uplo,&nb_ligne,&kuu,&nb_SM,matric_v,&ldaa,b(im).v,&ldbb,&info); GestionErreurDpbsv(info); // affichage d'erreurs éventuelles break; } default: {Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart); b = bb; }; }; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Simple_Resol_systID (..."; Sortie(1); }; }; 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& MatLapack::Simple_Resol_systID_2 (const Vecteur& b,Vecteur& vortie , const double &tol,const int maxi,const int rest) const {// init général ENTIER_POUR_CLAPACK nb_SM = 1; // un seul second membre if ((type_matrice != BANDE_SYMETRIQUE_LAPACK) && (ipiv == NULL)) {cout << "\n erreur: la methode MatLapack::Preparation_resol() n'a pas ete appelee " << " le tableau ipiv n'est pas correcte, on ne peut pas continuer ! " << "\n MatLapack::Simple_Resol_systID_2 (.... "; Sortie(1); }; ENTIER_POUR_CLAPACK ldb = MaX(1,nb_lign); ENTIER_POUR_CLAPACK info = 0; // info de sortie en fait c'est le retour de la fonction vortie=b; // init char trans = 'N'; // "No transpose" // comme la méthode est const, on doit utiliser des cast, se qui n'est pas sûr mais difficile de faire autrement ! double * matric_v = (double *) mat.v; // on impose un cast ENTIER_POUR_CLAPACK * ipiva = (ENTIER_POUR_CLAPACK*) ipiv; // "" // toujour à cause du const, on est obligé d'utiliser des variables intermédiaires ENTIER_POUR_CLAPACK nb_ligne=nb_lign; ENTIER_POUR_CLAPACK ldaa = lda; ENTIER_POUR_CLAPACK ldbb = ldb; ENTIER_POUR_CLAPACK kll = kl ; ENTIER_POUR_CLAPACK kuu = ku ; switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { switch (type_resolution) { case GAUSS: { #ifdef MISE_AU_POINT Verif_nb_composante(b,"Simple_Resol_systID_2"); #endif // appel de la routine clapack // /* Subroutine */ int dgetrs_(char *trans, __CLPK_integer *n, __CLPK_integer *nrhs, // __CLPK_doublereal *a, __CLPK_integer *lda, __CLPK_integer *ipiv, __CLPK_doublereal *b, __CLPK_integer * // ldb, __CLPK_integer *info); dgetrs_(&trans,&nb_ligne,&nb_SM,matric_v,&ldaa,ipiva,vortie.v,&ldbb,&info); break; } default: { Mat_abstraite::Resolution_syst(b,vortie,tol,maxi,rest);} }; break; } case CARREE_SYMETRIQUE_LAPACK: { switch (type_resolution) {case CHOLESKY: {// appel de la routine clapack // /* Subroutine */ int dpptrs_(char *uplo, __CLPK_integer *n, __CLPK_integer *nrhs, // __CLPK_doublereal *ap, __CLPK_doublereal *b, __CLPK_integer *ldb, __CLPK_integer *info) char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale dpptrs_(&uplo,&nb_ligne,&nb_SM,matric_v,vortie.v,&ldbb,&info); GestionErreurDg_sv(info); // affichage d'erreurs éventuelles break; } default: { Mat_abstraite::Resolution_syst(b,vortie,tol,maxi,rest);} } break; } case BANDE_NON_SYMETRIQUE_LAPACK: { switch (type_resolution) { case GAUSS: {// appel de la routine clapack // /* Subroutine */ int dgbtrs_(char *trans, __CLPK_integer *n, __CLPK_integer *kl, __CLPK_integer * // ku, __CLPK_integer *nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_integer *ipiv, // __CLPK_doublereal *b, __CLPK_integer *ldb, __CLPK_integer *info); dgbtrs_(&trans,&nb_ligne,&kll,&kuu,&nb_SM,matric_v,&ldaa,ipiva,vortie.v,&ldbb,&info); break; } default: { Mat_abstraite::Resolution_syst(b,vortie,tol,maxi,rest);} }; break; } case BANDE_SYMETRIQUE_LAPACK: { switch (type_resolution) { case CHOLESKY: {// appel de la routine clapack // /* Subroutine */ int dpbtrs_(char *uplo, __CLPK_integer *n, __CLPK_integer *kd, __CLPK_integer * // nrhs, __CLPK_doublereal *ab, __CLPK_integer *ldab, __CLPK_doublereal *b, __CLPK_integer *ldb, // __CLPK_integer *info) __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_4_0); char uplo = 'U'; // up diagonal: stockage au dessus de la diagonale dpbtrs_(&uplo,&nb_ligne,&kuu,&nb_SM,matric_v,&ldaa,vortie.v,&ldbb,&info); GestionErreurDpbsv(info); // affichage d'erreurs éventuelles break; } default: { Mat_abstraite::Resolution_syst(b,vortie,tol,maxi,rest);} }; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Simple_Resol_systID_2 (..."; Sortie(1); }; }; // retour return vortie; }; // ===== FIN RÉSOLUTION EN DEUX TEMPS ================ : #ifndef MISE_AU_POINT inline #endif // Realise le produit de la matrice par le vecteur vec Vecteur MatLapack::Prod_mat_vec (const Vecteur& vec) const { Vecteur result(nb_lign); #ifdef MISE_AU_POINT switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: case CARREE_SYMETRIQUE_LAPACK: { if (nb_col != vec.Taille()) { cout << "erreur de taille, le vecteur doit avoir une dimension identique au nombre" << " de colonne de la matrice"; cout << " \n Prod_mat_vec, tailleligneMatrice = " <*Coor_const)(i,k) * vec(k); break; } case BANDE_NON_SYMETRIQUE_LAPACK: { //void cblas_dgbmv(const enum CBLAS_ORDER Order, // const enum CBLAS_TRANSPOSE TransA, const int M, const int N, // const int KL, const int KU, const double alpha, // const double *A, const int lda, const double *X, // const int incX, const double beta, double *Y, const int incY) cblas_dgbmv(CblasRowMajor,CblasNoTrans, nb_lign, lda,kl,ku,alpha,mat.v,lda,vec.v,1,beta,result.v,1); break; } case BANDE_SYMETRIQUE_LAPACK: { //void cblas_dsbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, // const int N, const int K, const double alpha, const double *A, // const int lda, const double *X, const int incX, // const double beta, double *Y, const int incY) __OSX_AVAILABLE_STARTING(__MAC_10_2, cblas_dsbmv(CblasRowMajor, CblasUpper,nb_lign,ku,alpha,mat.v,lda,vec.v,1,beta,result.v,1); break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Simple_Resol_systID_2 (..."; Sortie(1); }; }; return result; }; #ifndef MISE_AU_POINT inline #endif // Realise le produit de la matrice par le vecteur vec // ici on se sert du second vecteur pour le résultat Vecteur& MatLapack::Prod_mat_vec (const Vecteur& vec,Vecteur& result) const { result.Change_taille(nb_lign); #ifdef MISE_AU_POINT switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: case CARREE_SYMETRIQUE_LAPACK: { if (nb_col != vec.Taille()) { cout << "erreur de taille, le vecteur doit avoir une dimension identique au nombre" << " de colonne de la matrice"; cout << " \n Prod_mat_vec, tailleligneMatrice = " <*Coor_const)(i,k) * vec(k); // }; // y := alpha*A*x + beta*y, // avec ici beta = 0., double alpha=1.;double beta = 0.; switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { //void cblas_dgemv(const enum CBLAS_ORDER Order, // const enum CBLAS_TRANSPOSE TransA, const int M, const int N, // const double alpha, const double *A, const int lda, // const double *X, const int incX, const double beta, // double *Y, const int incY) __OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_4_0); cblas_dgemv(CblasRowMajor,CblasNoTrans, nb_lign, lda,alpha,mat.v,lda,vec.v,1,beta,result.v,1); //for (int i=1;i<=nb_lign;i++) // {double* pt= &result(i); // for (int k=1;k<=nb_col;k++) // (*pt) += (this->*Coor_const)(i,k) * vec(k); break; } case BANDE_NON_SYMETRIQUE_LAPACK: { //void cblas_dgbmv(const enum CBLAS_ORDER Order, // const enum CBLAS_TRANSPOSE TransA, const int M, const int N, // const int KL, const int KU, const double alpha, // const double *A, const int lda, const double *X, // const int incX, const double beta, double *Y, const int incY) cblas_dgbmv(CblasRowMajor,CblasNoTrans, nb_lign, lda,kl,ku,alpha,mat.v,lda,vec.v,1,beta,result.v,1); break; } case BANDE_SYMETRIQUE_LAPACK: { //void cblas_dsbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, // const int N, const int K, const double alpha, const double *A, // const int lda, const double *X, const int incX, // const double beta, double *Y, const int incY) __OSX_AVAILABLE_STARTING(__MAC_10_2, cblas_dsbmv(CblasRowMajor, CblasUpper,nb_lign,ku,alpha,mat.v,lda,vec.v,1,beta,result.v,1); break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Simple_Resol_systID_2 (..."; Sortie(1); }; }; return result; }; #ifndef MISE_AU_POINT inline #endif // Retourne la transposee de la matrice mat // il y a création d'une matrice de sortie MatLapack MatLapack::Transpose () const { #ifdef MISE_AU_POINT if ( ( nb_lign ==0 ) || ( nb_col ==0 ) ) { cout << "Erreur : une des dimensions de la matrice:NxM= " << nb_lign <<"x"<< nb_col << " est nulle, la transposee n'a pas de sens ici "; cout << "\n MatLapack::TRANSPOSE ( )\n"; Sortie(1); }; #endif // comme résolution et type de matrice on met la même chose que this // for (int i=1;i <= nb_col;i++) // for (int j=1;j <= nb_lign;j++) // (result.*Coor)(i,j)=(this->*Coor_const)(j,i); switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { // dans le cas d'une matrice carrée ou rectangulaire on inverse les dimensions // car on considère que le stockage décri la forme réelle de la matrice MatLapack result(nb_col,nb_lign ,Symetrique_Enum_matrice(this->type_matrice),0. ,this->type_resolution,this->type_preconditionnement); for (int i=1;i <= nb_col;i++) for (int j=2;j <= nb_lign;j++) // on commence à 2, car la diag ne change pas (result.*Coor)(i,j)=(this->*Coor_const)(j,i); return result; break; } case BANDE_NON_SYMETRIQUE_LAPACK: { // on considère que la matrice réelle est carrée, et que son stockage bande n'est là // que pour l'optimisation. Donc la matrice transposée est exactement de même type // même largeur de bande etc, et dans notre cas on considère que la bande est de même 1/2 largeur // dessus et dessous, donc kl = ku MatLapack result(*this); for (int i=1;i <= nb_col;i++) for (int j=2;j <= nb_lign;j++) // on commence à 2, car la diag ne change pas (result.*Coor)(i,j)=(this->*Coor_const)(j,i); return result; break; } case BANDE_SYMETRIQUE_LAPACK:case CARREE_SYMETRIQUE_LAPACK: { // on considère que la matrice réelle est carrée, et que son stockage bande est symétrique supérieur // donc la transposée est identique MatLapack result(*this); return result; break; } default: { cout << "\n **** erreur: mauvais choix de matrice: " << Nom_matrice(type_matrice) << "\n MatLapack::Simple_Resol_systID_2 (..."; Sortie(1); }; }; MatLapack toto; return toto; // pour taire le compilo }; // determine l'inverse d'une matrice carre #ifndef MISE_AU_POINT inline #endif MatLapack MatLapack::Inverse() {switch (type_resolution) {case GAUSS: { #ifdef MISE_AU_POINT // l'appel n'est possible que si la matrice est carré if (nb_lign != nb_col) {cout << "\n erreur la matrice n'est pas carree, resolution impossible " << " nb_ligne= " << nb_lign << " nb_colonne= " << nb_col << "\n MatLapack::Inverse(..." << endl; Sortie(1); } // l'appel n'est pas possible si la matrice a des coefficients if (nb_lign == 0) {cout << "\n erreur la matrice n'a pas de coefficient, resolution impossible " << " nb_ligne= " << nb_lign << " nb_colonne= " << nb_col << "\n MatLapack::Inverse(..." << endl; Sortie(1); } #endif ENTIER_POUR_CLAPACK info = 0; // info de sortie en fait c'est le retour de la fonction // init général if (ipiv == NULL) {ipiv = new ENTIER_POUR_CLAPACK [nb_lign];}; MatLapack Msortie(*this); // def de la taille adoc pour le vecteur de travail // au premier appel on défini la taille ENTIER_POUR_CLAPACK lwork = -1; // pour demander la taille a doc de la zone de travail dgetri_(&Msortie.nb_lign,Msortie.mat.v,&lda,ipiv,travail.v,&lwork,&info); GestionErreurInverse(info,1,"dgetri_"); // gestion d'erreurs éventuelles int dim_optimal=travail(1); // sgetri sauvegarde la taille optimale dans v[0] travail.Change_taille(dim_optimal); // appel de la triangulation dgetrf_(&Msortie.nb_lign,&Msortie.nb_col,Msortie.mat.v,&lda,ipiv,&info); GestionErreurInverse(info,2,"dgetrf_"); // gestion d'erreurs éventuelles // calcul de l'inverse lwork=MaX(1,dim_optimal); dgetri_(&Msortie.nb_lign,Msortie.mat.v,&lda,ipiv,travail.v,&lwork,&info); GestionErreurInverse(info,3,"dgetri_"); // gestion d'erreurs éventuelles // retour return Msortie; break; } default: { cout << "\n erreur , methode non implante pour la matrice lapack: " << Nom_resolution(type_resolution) << "\n MatLapack::Inverse()"<< endl; Sortie(1); }; }; // pour taire le warning return MatLapack(); }; #ifndef MISE_AU_POINT inline #endif // determine l'inverse d'une matrice carre // mais en retournant l'inverse dans la matrice passée en paramètre // qui doit être de même taille MatLapack& MatLapack::Inverse(MatLapack& Msortie) {switch (type_resolution) {case GAUSS: { #ifdef MISE_AU_POINT // l'appel n'est possible que si la matrice est carré if (nb_lign != nb_col) {cout << "\n erreur la matrice n'est pas carree, resolution impossible " << " nb_ligne= " << nb_lign << " nb_colonne= " << nb_col << "\n MatLapack::Inverse(..." << endl; Sortie(1); }; // l'appel n'est pas possible si la matrice a des coefficients if (nb_lign == 0) {cout << "\n erreur la matrice n'a pas de coefficient, resolution impossible " << " nb_ligne= " << nb_lign << " nb_colonne= " << nb_col << "\n MatLapack::Inverse(..." << endl; Sortie(1); }; if (nb_lign != Msortie.nb_lign) {cout << "\n erreur la matrice resultat n'a pas le meme nombre de ligne ("<< Msortie.nb_lign << ") que this (" << nb_lign << "), resolution impossible " << "\n MatLapack::Inverse(..." << endl; Sortie(1); } else if (nb_col != Msortie.nb_col) {cout << "\n erreur la matrice resultat n'a pas le meme nombre de colonne ("<< Msortie.nb_col << ") que this (" << nb_col << "), resolution impossible " << "\n MatLapack::Inverse(..." << endl; Sortie(1); }; #endif ENTIER_POUR_CLAPACK info = 0; // info de sortie en fait c'est le retour de la fonction // init général if (ipiv == NULL) {ipiv = new ENTIER_POUR_CLAPACK [nb_lign];}; Msortie = (*this); // def de la taille adoc pour le vecteur de travail // au premier appel on défini la taille ENTIER_POUR_CLAPACK lwork = -1; // pour demander la taille a doc de la zone de travail dgetri_(&Msortie.nb_lign,Msortie.mat.v,&lda,ipiv,travail.v,&lwork,&info); GestionErreurInverse(info,1,"dgetri_"); // gestion d'erreurs éventuelles int dim_optimal=travail(1); // sgetri sauvegarde la taille optimale dans v[0] travail.Change_taille(dim_optimal); // appel de la triangulation dgetrf_(&Msortie.nb_lign,&Msortie.nb_col,Msortie.mat.v,&lda,ipiv,&info); GestionErreurInverse(info,2,"dgetrf_"); // gestion d'erreurs éventuelles // calcul de l'inverse lwork=MaX(1,dim_optimal); dgetri_(&Msortie.nb_lign,Msortie.mat.v,&lda,ipiv,travail.v,&lwork,&info); GestionErreurInverse(info,3,"dgetri_"); // gestion d'erreurs éventuelles // retour return Msortie; break; } default: { cout << "\n erreur , methode non implante pour la matrice lapack: " << Nom_resolution(type_resolution) << "\n MatLapack::Inverse()"<< endl; Sortie(1); }; }; // pour taire le warning return Msortie; }; #ifndef MISE_AU_POINT inline #endif // Surcharge de l'operateur + : addition de deux matrices // il y a création d'une matrice de sortie MatLapack MatLapack::operator + (const MatLapack& mat_pl) const { #ifdef MISE_AU_POINT if ( ( nb_lign!=mat_pl.nb_lign )|| ( nb_col != mat_pl.nb_col ) ) { cout << "Erreur : dimensions des matrices non egales\n" << " nb_ligne= " << nb_lign << " " << mat_pl.nb_lign << " nb_colonne= " << nb_col << " " << mat_pl.nb_col << " "; cout << "MatLapack::OPERATOR+ (const MatLapack& )\n"; Sortie(1); }; if (type_matrice != mat_pl.type_matrice) {cout << " erreur les matrices sont de types différents " << Nom_matrice(type_matrice) << " " << Nom_matrice(mat_pl.type_matrice) << '\n'; cout << "MatLapack::operator+ (const MatLapack& mat_pl)" << endl; Sortie(1); }; #endif MatLapack result(*this); result.mat +=mat_pl.mat; return result; }; #ifndef MISE_AU_POINT inline #endif // Surcharge de l'operateur - : soustraction entre deux matrices MatLapack MatLapack::operator- (const MatLapack& mat_pl) const { #ifdef MISE_AU_POINT if ( ( nb_lign!=mat_pl.nb_lign )|| ( nb_col != mat_pl.nb_col ) ) { cout << "Erreur : dimensions des matrices non egales\n" << " nb_ligne= " << nb_lign << " " << mat_pl.nb_lign << " nb_colonne= " << nb_col << " " << mat_pl.nb_col << " "; cout << "MatLapack::OPERATOR- (const MatLapack& )\n"; Sortie(1); }; if (type_matrice != mat_pl.type_matrice) {cout << " erreur les matrices sont de types différents " << Nom_matrice(type_matrice) << " " << Nom_matrice(mat_pl.type_matrice) << '\n'; cout << "MatLapack::operator- (const MatLapack& mat_pl)" << endl; Sortie(1); }; #endif MatLapack result(*this); // initialisation result.mat -= mat_pl.mat; return result; }; #ifndef MISE_AU_POINT inline #endif // Surcharge de l'operateur - : oppose d'une matrice MatLapack MatLapack::operator- () const { MatLapack result(*this); // initialisation result.mat = - mat; return result; }; #ifndef MISE_AU_POINT inline #endif MatLapack MatLapack::operator* (const MatLapack& mat_pl) const // Surcharge de l'operateur * : multiplication de deux matrices { #ifdef MISE_AU_POINT if ( nb_col!= mat_pl.nb_lign ) { cout << "Erreur : dimensions des matrices non valables, " << " pour la multiplication le nombre de colonne de la premiere matrice " << " doit etre egale au nombre de ligne de la seconde alors qu'ici on a respectivement: " << nb_col << " " << mat_pl.nb_lign << "\n"; cout << "MatLapack::OPERATOR* (const MatLapack& )\n"; Sortie(1); }; if (type_matrice != mat_pl.type_matrice) { cout << " erreur les matrices sont de types différents " << Nom_matrice(type_matrice) << " " << Nom_matrice(mat_pl.type_matrice) << '\n'; cout << "MatLapack::operator* (const MatLapack& mat_pl)" << endl; Sortie(1); }; #endif switch (type_matrice) { case RECTANGLE_LAPACK: case CARREE_LAPACK: { // par défaut on initialise la matrice résultat en non symétrique (car le produit de deux matrices symétriques // en en général non symétrique, et on ne renseigne pas la résolution // la première matrice : n_lign x nb_col // la deuxième matrice : mat_pl.n_lign x mat_pl.nb_col // la matrice résultat : n_lign x mat_pl.nb_col MatLapack result(nb_lign,mat_pl.nb_col,false,0.,RIEN_TYPE_RESOLUTION_MATRI,RIEN_PRECONDITIONNEMENT); // utilisation de blas3 // void cblas_dgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, // const enum CBLAS_TRANSPOSE TransB, const int M, const int N, // const int K, const double alpha, const double *A, // const int lda, const double *B, const int ldb, // const double beta, double *C, const int ldc) __OSX_AVAILABLE_STARTING(__MAC_10_2, // C := alpha*op( A )*op( B ) + beta*C, // ici on prend alpha = 1. et beta = 0. double alpha = 1.; double beta = 0.; // MatLapack inter(nb_lign,mat_pl.nb_col,false,0.,RIEN_TYPE_RESOLUTION_MATRI,RIEN_PRECONDITIONNEMENT); // le mat.v de la fin, ne sert à rien car beta = 0 cblas_dgemm(CblasRowMajor, CblasNoTrans,CblasNoTrans,nb_lign,mat_pl.nb_col,nb_col,alpha ,mat.v,nb_lign,mat_pl.mat.v,mat_pl.nb_lign,beta,result.mat.v,nb_col); // for (int i=1;i<=nb_lign;i++) // { for (int j=1;j<= nb_col;j++) // for (int k=1;k<=nb_col;k++) // (result.*Coor)(i,j) += (this->*Coor_const)(i,k) * (mat_pl.*Coor_const)(k,j); // }; return result; break; } // effectivement la suite n'est pas intéressante et ne sera pas utilisée, donc on laisse l'erreur s'afficher // case BANDE_NON_SYMETRIQUE_LAPACK: // { // dans le cas du produit de deux matrices bandes, les bandes s'ajoutent // MatLapack result(type_matrice,2*nb_col,nb_lign,false,0.,RIEN_TYPE_RESOLUTION_MATRI,RIEN_PRECONDITIONNEMENT); // // mais pour l'instant je ne suis pas sûr que cela serve à quelque chose donc je met un message d'erreur // cout << "\n erreur **** le produit de deux matrices bandes n'est pas implante " // << "\n MatLapack::operator* ( ... " << endl; // Sortie(1); // return result; // break; // } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Colonne (.. "<*Coor)(i,j)=x; break; } case BANDE_NON_SYMETRIQUE_LAPACK: { int lb=(nb_col-1)/2; int dim = nb_lign; int maxJ = MiN(dim,i+lb)+1;// +1 pour un test "inférieur pure" sur la ligne qui suit for (int j= MaX(1,i-lb);j< maxJ;j++) (this->*Coor)(i,j) = x; break; } case BANDE_SYMETRIQUE_LAPACK: // même symétrique il faut imposer sur toute la ligne car au-dessus et en-dessous de la diagonale, // on n'adresse pas des grandeurs identiques {int lb=nb_col-1; int dim = nb_lign; int le_max = MiN(dim,i+lb)+1;// +1 pour un test "inférieur pure" sur la ligne qui suit int le_min = MaX(1,i-lb); // on fait comme pour MatBand // for (int j= MaX(1,i);j< le_max;j++) for (int j= le_min;j< le_max;j++) (this->*Coor)(i,j)=x; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::MetValLigne (.. "<*Coor_const)(i,j); break; } case BANDE_NON_SYMETRIQUE_LAPACK: { int lb=(nb_col-1)/2; int dim = nb_lign; int maxI = MiN(dim,j+lb)+1;// +1 pour un test "inférieur pure" sur la ligne qui suit for (int i= MaX(1,j-lb);i< maxI;i++) ret(i) = (this->*Coor_const)(i,j); break; } case BANDE_SYMETRIQUE_LAPACK: // bande supérieure {int lb=nb_col-1; int dim = nb_lign; int le_max = MiN(dim,j+lb)+1;// +1 pour un test "inférieur pure" sur la boucle qui suit int le_min = MaX(1,j-lb); for (int i= le_min;i< le_max;i++) ret(i) = (this->*Coor_const)(i,j); break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Colonne (.. "<*Coor_const)(i,j); return ret; break; } case CARREE_SYMETRIQUE_LAPACK: // on fait pareil pour la matrice symétrique, car la colonne complète adresse // deux parties différentes de symétrie, donc il faut récupérer toute la colonne { Vecteur ret(nb_lign); for (int i=1;i<=nb_lign;i++) ret(i)=(this->*Coor_const)(i,j); return ret; break; } case BANDE_NON_SYMETRIQUE_LAPACK: { Vecteur col(nb_col); // mise a zero de ligne, nb_col = largeur totale de la bande int lb=(nb_col-1)/2; int dim = nb_lign; int maxI = MiN(dim,j+lb)+1; // +1 pour le test < sur le for qui suit for (int i= MaX(1,j-lb);i< maxI;i++) col(i-j+lb+1) = (this->*Coor_const)(i,j); return col; break; } case BANDE_SYMETRIQUE_LAPACK: // bande supérieure {int lb=nb_col-1; int dim = nb_lign; Vecteur col(1+2*lb); // mise a zero de ligne, // méthode identique au cas de la matrice symétrique, car la colonne complète adresse // deux parties différentes de symétrie, donc il faut récupérer toute la colonne int le_max = MiN(dim,j+lb)+1;// +1 pour le test < sur le for qui suit int le_min = MaX(1,j-lb); for (int i= le_min;i < le_max;i++) col(i-j+lb+1) = (this->*Coor_const)(i,j); return col; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::ColonneSpe (.. "<*Coor)(i,j)=v(i); break; } case CARREE_SYMETRIQUE_LAPACK: // méthode identique au cas de la matrice non symétrique, car la colonne complète adresse // deux parties différentes de symétrie, donc il faut récupérer toute la colonne { for(int i=1; i <= nb_lign ; i++) (this->*Coor)(i,j)=v(i); break; } case BANDE_NON_SYMETRIQUE_LAPACK: { int lb=(nb_col-1)/2; int dim = nb_lign; int maxI = MiN(dim,j+lb)+1;// +1 pour inférieur pure sur la ligne qui suit for (int i= MaX(1,j-lb);i< maxI;i++) (this->*Coor)(i,j)=v(i); break; } case BANDE_SYMETRIQUE_LAPACK: // bande supérieure {int lb=nb_col-1; int dim = nb_lign; Vecteur col(1+2*lb); // mise a zero de ligne, // méthode identique au cas de la matrice non symétrique, car la colonne complète adresse // deux parties différentes de symétrie, donc il faut récupérer toute la colonne int le_max = MiN(dim,j+lb)+1;// +1 pour le test < sur le for qui suit int le_min = MaX(1,j-lb); for (int i= le_min;i*Coor)(i,j) = col(i-j+lb+1); break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::RemplaceColonneSpe (.. "<*Coor)(i,j)=y; break; } case BANDE_NON_SYMETRIQUE_LAPACK: {int lb=(nb_col-1)/2; int dim = nb_lign; int maxI = MiN(dim,j+lb)+1;// +1 pour le test < sur le for qui suit for (int i= MaX(1,j-lb);i< maxI;i++) (this->*Coor)(i,j)=y; break; } case BANDE_SYMETRIQUE_LAPACK: // bande supérieure // méthode identique au cas de la matrice non symétrique, car la colonne complète adresse // deux parties différentes de symétrie, donc il faut récupérer toute la colonne {int lb=nb_col-1; int dim = nb_lign; int maxI = MiN(dim,j+lb)+1;// +1 pour le test < sur le for qui suit int le_min = MaX(1,j-lb); // on fait comme MatBand for (int i= le_min;i*Coor)(i,j) = y; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::MetValColonne (.. "<*Coor_const)(iligne,j) * vec(j); break; } case BANDE_NON_SYMETRIQUE_LAPACK:case BANDE_SYMETRIQUE_LAPACK: {int lb=(nb_col-1)/2; int dim = nb_lign; int maxJ = MiN(dim,iligne+lb)+1;// +1 pour le test < sur le for qui suit for (int j=MaX(1,iligne-lb);j< maxJ;j++) res += (this->*Coor_const)(iligne,j) * vec(j); break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Prod_Ligne_vec (.. "<*Coor_const)(i,jcol) ; break; } case BANDE_NON_SYMETRIQUE_LAPACK: case BANDE_SYMETRIQUE_LAPACK: {int lb=(nb_col-1)/2; int dim = nb_lign; int maxI = MiN(jcol+lb,dim)+1;// +1 pour le test < sur le for qui suit for (int i=MaX(1,jcol-lb);i< maxI;i++) res += vec(i) * (this->*Coor_const)(i,jcol) ; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::Prod_vec_col (.. "<*Coor_const)(i,j) * vec2(j); break; } case BANDE_NON_SYMETRIQUE_LAPACK: case BANDE_SYMETRIQUE_LAPACK: { int lb=(nb_col-1)/2; int dim = nb_lign; for (int i=1;i<=dim;i++) { int maxJ = MiN(dim,i+lb)+1;// +1 pour inférieur pure sur la ligne qui suit for (int j= MaX(1,i-lb);j< maxJ;j++) resu += vec1(i) * (this->*Coor_const)(i,j) * vec2(j); }; break; } default: cout << "\n erreur: cas de type de matrice: "<< Nom_matrice(type_matrice) << " non implante " << "\n MatLapack::vectT_mat_vec (.. "<=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); }; }; */ // surcharge de l'operateur de lecture typée #ifndef MISE_AU_POINT inline #endif istream & operator >> (istream & entree, MatLapack & mat_pl) { // vérification du type string typa; entree >> typa; if (typa != "MatLapack_NxM") {cout << "\n erreur en lecture d'une matrice type lapack on attendait la chaine: MatLapack_NxM" << " et on a lue: " << typa << "\n operator >> (istream & entree ... "; Sortie (1); }; // on lit le nombre de ligne et de colonne int nb_l,nb_c; entree >> nb_l >> nb_c; // on lit le type et on vérifie que la matrice à le même type que this entree >> typa; if (Id_nom_matrice(typa.c_str()) != mat_pl.type_matrice) {cout << "\n erreur en lecture du type de la matrice on attendait " << Nom_matrice(mat_pl.type_matrice) << " et on a lue: " << typa << "\n operator >> (istream & entree ... "; Sortie (1); }; // on redimentionne en fonction du type if ((nb_l != mat_pl.nb_lign) || (nb_c != mat_pl.nb_col)) { mat_pl.Change_taille(nb_l,nb_c);} else { // même si la place est ok on met à jour le nombre de ligne et de colonne mat_pl.nb_lign=nb_l;mat_pl.nb_col=nb_c; }; // maintenant on peut lire les coordonnées entree >> typa; // pour passer le mot clé valeurs= int nb=mat_pl.mat.Taille(); for(int j=1; j <= nb; j++) entree >> mat_pl.mat(j); return entree; }; // surcharge de l'operateur d'ecriture typée #ifndef MISE_AU_POINT inline #endif ostream & operator << ( ostream & sort,const MatLapack & mat_pl) { // un indicateur donnant le type puis les datas sort << "MatLapack_NxM " << mat_pl.nb_lign << " " << mat_pl.nb_col << " " << Nom_matrice(mat_pl.type_matrice) << " valeurs= " ; int nb = mat_pl.mat.Taille(); for(int j=1; j <= nb; j++) sort << setprecision(ParaGlob::NbdigdoCA()) << mat_pl.mat(j); // retour return sort; }; // fonction interne de vérification des composantes // arrêt si pb #ifndef MISE_AU_POINT inline #endif void MatLapack::Verif_nb_composante(const Vecteur& b,string nom_routine) const { // l'appel n'est possible que si la matrice est carré if (nb_lign != nb_col) {cout << "\n erreur la matrice n'est pas carree, resolution impossible " << " nb_ligne= " << nb_lign << " nb_colonne= " << nb_col << "\n MatLapack::" << nom_routine << "(..." << endl; Sortie(1); } // l'appel n'est pas possible si la matrice a des coefficients if (nb_lign == 0) {cout << "\n erreur la matrice n'a pas de coefficient, resolution impossible " << " nb_ligne= " << nb_lign << " nb_colonne= " << nb_col << "\n MatLapack::" << nom_routine << "(..." << endl; Sortie(1); } // vérif du nombre de composante de b if (b.Taille()!=nb_lign) {cout << "\n erreur le nombre de composante du second membre: " << b.Taille() << " est differant du nombre de ligne de la matrice: " << nb_lign << " " << "\n MatLapack::" << nom_routine << "(..." << endl; Sortie(1); } }; // fonction interne de vérification des composantes // arrêt si pb #ifndef MISE_AU_POINT inline #endif void MatLapack::Verif_nb_composante(const Tableau & b,string nom_routine) const { // l'appel n'est possible que si la matrice est carré if (nb_lign != nb_col) {cout << "\n erreur la matrice n'est pas carree, resolution impossible " << " nb_ligne= " << nb_lign << " nb_colonne= " << nb_col << "\n MatLapack::" << nom_routine << "(..." << endl; Sortie(1); }; // l'appel n'est pas possible si la matrice a des coefficients if (nb_lign == 0) {cout << "\n erreur la matrice n'a pas de coefficient, resolution impossible " << " nb_ligne= " << nb_lign << " nb_colonne= " << nb_col << "\n MatLapack::" << nom_routine << "(..." << endl; Sortie(1); }; // vérif du nombre de composante des seconds membres b int nb_SM = b.Taille(); for (int i=1;i<=nb_SM;i++) if (b(i).Taille()!=nb_lign) {cout << "\n erreur le nombre de composante: " << b(i).Taille() << " du second membre numero: " << i << " est differant du nombre de ligne de la matrice: " << nb_lign << " " << "\n MatLapack::Resol_syst(const Tableau &..." << endl; Sortie(1); }; }; #ifndef MISE_AU_POINT inline #endif // gestion erreur dgesv void MatLapack::GestionErreurDg_sv(const int& info) const { if (info == 0) { return;} else if (info < 0) { cout << "\n pb resolution Dg_sv, le " << -info << " argument de la fonction" << " a une valeur illegale " << "\n arguments: ( N, NRHS, A, LDA, IPIV, B, LDB, INFO ) " << " \n MatLapack::GestionErreurDg_sv(const int& info) "; // on génère une exception throw ErrResolve_system_lineaire(1); Sortie(1); } else if (info > 0) { cout << "\n pb resolution Dg_sv, U(" << info << "," << info <<") est exactement null" << " (cf doc lapack) la factorisation est complete, mais U est exactement singuliere" << " donc la solution ne peut-etre calculee " << " \n MatLapack::GestionErreurDg_sv(const int& info) "; // on génère une exception throw ErrResolve_system_lineaire(1); // cout << "\n corriger le debug de Matlapack "; // Sortie(1); }; }; #ifndef MISE_AU_POINT inline #endif // gestion erreur dpbsv void MatLapack::GestionErreurDpbsv(const int& info) const { if (info == 0) { return;} else if (info < 0) { cout << "\n pb resolution Dpbsv, le " << -info << " argument de la fonction" << " a une valeur illegale " << "\n arguments: ( UPLO, N, KD, NRHS, AB, LDAB, B, LDB, INFO ) " << " \n MatLapack::GestionErreurDpbsv(const int& info) "; // on génère une exception throw ErrResolve_system_lineaire(1); Sortie(1); } else if (info > 0) { cout << "\n pb resolution Dpbsv, le mineur prindipal d'ordre (" << info << ") de la matrice est non defini positif" << " (cf doc lapack) la factorisation complete ne peut-etre effectuee, " << " donc la solution ne peut-etre calculee " << " \n MatLapack::GestionErreurDpbsv(const int& info) "; // on génère une exception throw ErrResolve_system_lineaire(1); // cout << "\n corriger le debug de Matlapack "; // Sortie(1); }; }; #ifndef MISE_AU_POINT inline #endif // gestion erreur Inverse void MatLapack::GestionErreurInverse(const int& info,int cas,const string nom_routine_lapack) const { if (info == 0) { return;}; // cas pas de pb // cas de pb éventuel if (info < 0) { cout << "\n pb resolution, le " << -info << " argument de la fonction" << " a une valeur illegale (cf doc lapack)"; } else if (info > 0) { cout << "\n pb resolution, U(" << info << "," << info <<") est exactement null" << " (cf doc lapack) la factorisation est complete, mais U est exactement singuliere" << " donc la solution ne peut-etre calculee "; }; switch (cas) { case 2: {cout << "\n arguments: ( N, A, LDA, IPIV, WORK, LWORK, INFO ) "; break;} case 1: case 3: {cout << "\n arguments: ( M, N, A, LDA, IPIV, INFO ) "; break;} default: { cout << "\n **** erreur: cas= " << cas <<" non pris en compte" << "\n MatLapack::GestionErreurInverse(..."; // on génère une exception throw ErrResolve_system_lineaire(1); Sortie(1); }; }; cout << " \n routine : " << nom_routine_lapack << " cas = " << cas << "\n MatLapack::GestionErreurInverse(... "; // on génère une exception throw ErrResolve_system_lineaire(1); Sortie(1); }; #endif