// 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