// This file is part of the Herezh++ application. // // The finite element software Herezh++ is dedicated to the field // of mechanics for large transformations of solid structures. // It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600) // INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) . // // Herezh++ is distributed under GPL 3 license ou ultérieure. // // Copyright (C) 1997-2022 Université Bretagne Sud (France) // AUTHOR : Gérard Rio // E-MAIL : gerardrio56@free.fr // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information, please consult: . //#include "Debug.h" #include "Mat_creuse_CompCol.h" #include #include "CharUtil.h" #include #include "MatDiag.h" #include "Vector_io.h" // constructeur par défaut Mat_creuse_CompCol::Mat_creuse_CompCol () : Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL) ,CompCol_Mat_double() {}; // constructeur parmettant la création d'une matrice creuse // ici aucun élément de la matrice n'est créé, il faut ensuite utiliser l'initialisation // pour créer les éléments non nulles dans la matrice // M : nombre de lignes // N : nombre de colonnes Mat_creuse_CompCol::Mat_creuse_CompCol(int M, int N) : Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL) // ,CompCol_Mat_double(M,N,0,NULL,NULL,NULL) ,CompCol_Mat_double() { // dimensionnement et initialisation this->newsize(M,N,0); #ifdef MISE_AU_POINT if ((M < 0) || (N < 0)) {cout << "erreur de dimensionnement d une matrice creuse"; cout << " M = " << M << " N = " << N << '\n'; cout << "Mat_creuse_CompCol::Mat_creuse_CompCol (int M, int N )" << endl; Sortie(1); } #endif }; // constructeur parmettant la création d'une matrice creuse complete // à partir de la donnée d'un ensemble de sous matrices // M : nombre de lignes // N : nombre de colonnes // Mat_creuse_CompCol::Mat_creuse_CompCol (int M, int N,const Tableau < Tableau >& petites_matrices): Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL) // ,CompCol_Mat_double(M,N,0,NULL,NULL,NULL) ,CompCol_Mat_double() { // dimensionnement et initialisation this->newsize(M,N,0); // appel de la routine permettant le dimentionnement effectif Change_taille(M,N,petites_matrices); }; // de copie à partir d'une sparse matrice compressée par ligne //Mat_creuse_CompCol::Mat_creuse_CompCol(const Mat_creuse_CompRow &R) : // Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL) // ,CompRow_Mat_double(R) // {}; // de copie à partir d'une sparse matrice non compressée //Mat_creuse_CompCol::Mat_creuse_CompCol(const Mat_creuse_Coord &CO) : // Mat_abstraite(CREUSE_COMPRESSEE_COLONNE,BI_CONJUG_STAB,DIAGONAL) // ,Coord_Mat_double(CO) // {}; // constructeur de copie à partir d'une même instance Mat_creuse_CompCol::Mat_creuse_CompCol(const Mat_creuse_CompCol &S) : Mat_abstraite(S),CompCol_Mat_double(S) {}; // fonction permettant de creer une nouvelle instance d'element Mat_abstraite * Mat_creuse_CompCol::NouvelElement() const { Mat_abstraite * a; a = new Mat_creuse_CompCol(*this); return a; }; // surcharge de l'opérateur d'affectation, cas de matrices abstraites Mat_abstraite & Mat_creuse_CompCol::operator = ( const Mat_abstraite & b) { #ifdef MISE_AU_POINT // dans le cas où les matrices ne sont pas de caractéristiques identiques // il y a un message d'erreur if (type_matrice != b.Type_matrice()) {cout << "erreur dans l'operation d'affectation"; cout << " les matrices sont de types différents " << Nom_matrice(type_matrice) << " " << Nom_matrice(b.Type_matrice()) << '\n'; cout << "Mat_creuse_CompCol::operator = ( const Mat_abstraite & b)" << endl; Sortie(1); } #endif const Mat_creuse_CompCol & a = *((Mat_creuse_CompCol*) & b); // affectation de la partie matrice creuse (CompCol_Mat_double) a = (CompCol_Mat_double) *this; return *this; }; // surcharge de l'opérateur d'affectation, cas de matrices creuses Mat_creuse_CompCol & Mat_creuse_CompCol::operator = ( const Mat_creuse_CompCol & a) { // affectation de la partie matrice creuse (CompCol_Mat_double) a = (CompCol_Mat_double) *this; 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. void Mat_creuse_CompCol::Transfert_vers_mat( Mat_abstraite & b ) {b.Initialise(0.); // init de la matrice // puis on transfert int taille_j = colptr_.size(); // int nb_col_plus_1 = colptr_.size(); for (int j=1;jNb_ligne() != b.Nb_ligne()) {cout << " les matrices ont un nombre de ligne différent " << this->Nb_ligne() << " " << b.Nb_ligne() << '\n'; cout << "Mat_creuse_CompCol::operator+= (const Mat_abstraite& b)" << endl; Sortie(1); } #endif if (b.Type_matrice() == CREUSE_COMPRESSEE_COLONNE) // cas matrice creuse, on travaille directement sur les données de base { const Mat_creuse_CompCol & mat_b = *((Mat_creuse_CompCol*) & b); val_ += mat_b.val_; } else // cas d'une matrice diagonale { const MatDiag & mat_b = *((MatDiag*) & b); int taille = this->Nb_ligne(); for (int i=1;i<= taille; i++) (*this)(i,i) += mat_b(i,i); } }; // Surcharge de l'operateur -= : soustraction d'une matrice a la matrice courante // cette méthode n'est possible si et seulement les termes existant de mat_pl void Mat_creuse_CompCol::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 ((b.Type_matrice() != DIAGONALE) && ((*this) != b)) {cout << " erreur la matrice b à ajouter n'est pas soit diagonale ou soit " << " matrice creuse de même topologie " << Nom_matrice(b.Type_matrice()); cout << "Mat_creuse_CompCol::operator-= (const Mat_abstraite& b)" << endl; Sortie(1); } // si les tailles ne sont pas identique pb if (this->Nb_ligne() != b.Nb_ligne()) {cout << " les matrices ont un nombre de ligne différent " << this->Nb_ligne() << " " << b.Nb_ligne() << '\n'; cout << "Mat_creuse_CompCol::operator-= (const Mat_abstraite& b)" << endl; Sortie(1); } #endif if (b.Type_matrice() == CREUSE_COMPRESSEE_COLONNE) // cas matrice creuse, on travaille directement sur les données de base { const Mat_creuse_CompCol & mat_b = *((Mat_creuse_CompCol*) & b); val_ -= mat_b.val_; } else // cas d'une matrice diagonale { const MatDiag & mat_b = *((MatDiag*) & b); int taille = this->Nb_ligne(); for (int i=1;i<= taille; i++) (*this)(i,i) -= mat_b(i,i); } }; // Surcharge de l'operateur *= : multiplication de la matrice courante par un scalaire void Mat_creuse_CompCol::operator*= (const double r) { // on multiplie les valeurs de la matrice val_ *= r; }; // Surcharge de l'operateur == : test d'egalite entre deux matrices int Mat_creuse_CompCol::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 << "int Mat_creuse_CompCol::operator== (const Mat_abstraite& mat_pl)" << endl; Sortie(1); } #endif const Mat_creuse_CompCol & mat_b = *((Mat_creuse_CompCol*) & b); // on regarde si la partie classe de base CompCol_Mat_double // est égale ou pas if ( val_ != mat_b.val_ ) return 0; if ( rowind_ != mat_b.rowind_ ) return 0; if ( colptr_ != mat_b.colptr_ ) return 0; if (base_ != mat_b.base_) return 0; if (nz_ != mat_b.nz_) return 0; if (dim_[0] != mat_b.dim_[0]) return 0; if (dim_[1] != mat_b.dim_[1]) return 0; // pour les données de classe abstraite, à part le type de matrice // on autorise que les autres variables soient différentes return 1; }; // Retourne la ieme ligne de la matrice Vecteur Mat_creuse_CompCol::Ligne(int i) const { Vecteur ligne(dim(1)); // mise a zero de ligne for (int j=0;j >& pet_mat) { // def du tableau d'indice de colonnes et de lignes // mat(j) représente contiend l'ensemble des indices de lignes non nuls pour la colonne j Tableau < Vector_io > mat(N); // on remplit le tableau int nb_matrices = pet_mat.Taille(); for (int k= 1; k<= nb_matrices; k++) { int ligcol_max = pet_mat(k).Taille(); for (int j=1;j<= ligcol_max;j++) { // le vecteur des indices de colonne Vector_io & v_col = mat(pet_mat(k)(j)); // boucle sur les lignes for (int i=1;i<= ligcol_max;i++) // on recherche la position à insérer {int jmat_glob = pet_mat(k)(i); // le numero de ligne // cout << "\n le vecteur " ; // for (int a=0;a< v_col.size();a++) // cout << v_col[a] << ""; // cout << endl; // cout << "\n v_col.begin() " << v_col.begin() << ", v_col.end() " << v_col.end() // << " jmat_glob " << jmat_glob ; Vector_io::iterator p = lower_bound(v_col.begin(),v_col.end(),jmat_glob); // int truc; // cout << "\n valeur de *p " << *p << endl; cin >> truc; // insertion s'il n'existe pas déjà // normalement l'insertion respecte l'ordre déjà existant // premier test est-ce que l'on doit mettre à la fin if (p == v_col.end()) // cas ou le nouvel élément est le plus grand v_col.insert(p,jmat_glob); else if (*p != jmat_glob) // cas ou l'on est inférieur au maxi, on teste s'il n'existe pas déjà v_col.insert(p,jmat_glob); // cout << "\n le vecteur après insertion" ; // for (int a=0;a< v_col.size();a++) // cout << v_col[a] << ""; // cout << endl; cin >> truc; } } } // maintenant on va passer en revue les éléments non nulle de la matrice // 1) on regarde les éléments non nuls int nb_nonnul = 0; for (int j=1;j<= N;j++) { // le vecteur des indices de colonne Vector_io & v_cal = mat(j); int taille_v_cal = (int) v_cal.size(); // le nb d'élément non nul de la colonne // dans le cas ou aucun élément de la colonne n'est nulle // on prévoit de retenir l'élément diagonal quand même, il sera donc nulle // car a priori il y a un pb si aucun élément de la colonne n'exite if (taille_v_cal == 0) { v_cal.push_back(min(j,M)); taille_v_cal++; } // mise a jour du pointeur global nb_nonnul += taille_v_cal; } // 2) on redimentionne newsize(M,N,nb_nonnul); // on met à zéro les termes de la matrice for (int iv=0;iv& v_cul = mat(jcol); int taille_v_cul = (int) v_cul.size(); // le nb d'élément non nul de la colonne // les indices de lignes avec mise à jour du pointeur iptcol for (int i_v_cul = 1; i_v_cul <= taille_v_cul; i_v_cul++,iptcol++) rowind_(iptcol) = v_cul[(unsigned long) i_v_cul-1] - 1; // on ressort de la boucle avec iptcol bon pour le jcol suivant // mise a jour du pointeur de colonne colptr_(jcol) = iptcol; } }; // 2) cas d'un utilisateur qui connait le stockage par colonne // M et N : nb ligne et nb colonne, // pointeur_colonne : donne dans le vecteur de stockage global le début de chaque colonne // nz : nb de termes non nulles dans la matrice void Mat_creuse_CompCol::Change_taille (const int M,const int N , const Tableau& pointeur_colonne,const int nz) { #ifdef MISE_AU_POINT if ((M < 0) || (N < 0)) {cout << "erreur de dimensionnement d une matrice creuse compressée colonne"; cout << " nb ligne " << M << " nb col = " << N << '\n'; cout << "void Mat_creuse_CompCol::Change_taille(int M, int N )" << endl; Sortie(1); } #endif CompCol_Mat_double::newsize(M,N,nz); // dimensionnement générique // puis on définit précisément le vecteur pointeur #ifdef MISE_AU_POINT // on vérifie la taille if (pointeur_colonne.Taille() != (dim_[1]+1) ) {cout << "\n erreur de dimensionnement d une matrice creuse compressée colonne"; cout << " la taille du vecteur pointeur colonne= " << pointeur_colonne.Taille() << " devrait être de " << (dim_[1]+1) << '\n'; cout << "\n void Mat_creuse_CompCol::Change_taille(int M, int N," << " Tableau pointeur_colonne, )" << endl; Sortie(1); } #endif for (int i=1;i<= dim_[1]+1;i++) colptr_(i-1) = pointeur_colonne(i); }; void Mat_creuse_CompCol::Initialise (double a) // initialisation de la matrice a la valeur "a" { CompCol_Mat_double::val_ = a; }; void Mat_creuse_CompCol::Libere () // Liberation de la place memoire { CompCol_Mat_double::newsize(0,0,0); }; // --------------------------------------------------------------- // Resolution du systeme Ax=b // --------------------------------------------------------------- //1) avec en sortie un new vecteur Vecteur Mat_creuse_CompCol::Resol_syst (const Vecteur& b,const double &tole, const int maxi, const int rest) { // sauvegarde du vecteur b Vecteur bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); return bb; }; //2) avec en sortie le vecteur d'entree Vecteur& Mat_creuse_CompCol::Resol_systID (Vecteur& b,const double &tole, const int maxi, const int rest) { // résolution Vecteur bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); b=bb; return b; }; //3) avec en entrée un tableau de vecteur second membre et // en sortie un nouveau tableau de vecteurs Tableau Mat_creuse_CompCol::Resol_syst (const Tableau & b,const double &tole, const int maxi, const int rest) { // sauvegarde de b Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); return bb; }; //4) avec en entrée un tableau de vecteur second membre et // en sortie le tableau de vecteurs d'entree Tableau & Mat_creuse_CompCol::Resol_systID (Tableau & b,const double &tole, const int maxi, const int rest) { // résolution Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tole,maxi,rest); b=bb; return b; }; //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 Vecteur& Mat_creuse_CompCol::Resol_systID_2 (const Vecteur& b,Vecteur& vortie , const double &tole,const int maxi,const int rest) { Mat_abstraite::Resolution_syst(b,vortie,tole,maxi,rest); return vortie; }; // ===== RÉSOLUTION EN DEUX TEMPS ================ : // 1) préparation de la matrice donc modification de la matrice éventuellement // par exemple pour les matrices bandes avec cholesky : triangulation void Mat_creuse_CompCol::Preparation_resol() { // les seules résolutions possibles sont celles itératives qui laissent la matrice inchangée // donc ici on n'a rien à préparer }; // 2) *** résolution sans modification de la matrice DOIT ÊTRE PRÉCÉDÉ DE L'APPEL DE // Preparation_resol // a) avec en sortie un new vecteur Vecteur Mat_creuse_CompCol::Simple_Resol_syst (const Vecteur& b,const double &tol ,const int maxi,const int rest) const { // sauvegarde du vecteur b Vecteur bb(b); Mat_abstraite::Resolution_syst(b,bb,tol,maxi,rest); return bb; }; // b) avec en sortie le vecteur d'entree Vecteur& Mat_creuse_CompCol::Simple_Resol_systID (Vecteur& b,const double &tol ,const int maxi,const int restart ) const { // résolution Vecteur bb(b); Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart); b=bb; return b; }; // c) avec en entrée un tableau de vecteur second membre et // en sortie un nouveau tableau de vecteurs Tableau Mat_creuse_CompCol::Simple_Resol_syst (const Tableau & b,const double &tol ,const int maxi,const int restart ) const { // sauvegarde de b Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart); return bb; }; // d) avec en entrée un tableau de vecteur second membre et // en sortie le tableau de vecteurs d'entree Tableau & Mat_creuse_CompCol::Simple_Resol_systID (Tableau & b,const double &tol ,const int maxi,const int restart ) const { // résolution Tableau bb(b); Mat_abstraite::Resolution_syst(b,bb,tol,maxi,restart); b=bb; return b; }; // e) avec en sortie le dernier vecteur d'entree, le premier étant le second membre // et restant inchangé, en sortie c'est donc soit le retour ou soit vortie, les // deux étant identiques Vecteur& Mat_creuse_CompCol::Simple_Resol_systID_2 (const Vecteur& b,Vecteur& vortie , const double &tol,const int maxi,const int restart) const { Mat_abstraite::Resolution_syst(b,vortie,tol,maxi,restart); return vortie; }; // ===== FIN RÉSOLUTION EN DEUX TEMPS ================ : */ // Multiplication d'un vecteur par une matrice ( (vec)t * A ) Vecteur Mat_creuse_CompCol::Prod_vec_mat ( const Vecteur& vec) const { #ifdef MISE_AU_POINT if (dim(0) != vec.Taille()) {cout << "erreur taille matrice < taille vecteur"; cout << "dimMat = " << dim(0) << " dimVect = " << vec.Taille() << '\n'; cout << "Vecteur Mat_creuse_CompCol::Prod_vec_mat ( Vecteur& vec)" << endl; } #endif // récup de l'homologue de vec en vecteur_double const VECTOR_double vec_double(vec.MV_vecteur_double()); // définition du vecteur de retour Vecteur res(dim(1)); // utilisation de la multiplication dèjà définie VECTOR_double res_double = this->CompCol_Mat_double::trans_mult(vec_double); res = res_double; return res; }; // Multiplication d'un vecteur par une matrice ( (vec)t * A ) // ici on se sert du second vecteur pour le résultat Vecteur& Mat_creuse_CompCol::Prod_vec_mat ( const Vecteur& vec,Vecteur& res) const { #ifdef MISE_AU_POINT if (dim(0) != vec.Taille()) {cout << "erreur taille matrice < taille vecteur"; cout << "dimMat = " << dim(0) << " dimVect = " << vec.Taille() << '\n'; cout << "Vecteur& Mat_creuse_CompCol::Prod_vec_mat ( Vecteur& vec,Vecteur& res)" << endl; } #endif // récup de l'homologue de vec en vecteur_double const VECTOR_double vec_double(vec.MV_vecteur_double()); // définition du vecteur de retour res.Change_taille(dim(1)); // utilisation de la multiplication dèjà définie VECTOR_double res_double = this->CompCol_Mat_double::trans_mult(vec_double); res = res_double; return res; }; // Multiplication d'une matrice par un vecteur ( A * vec ) Vecteur Mat_creuse_CompCol::Prod_mat_vec (const Vecteur& vec) const { #ifdef MISE_AU_POINT if (dim(1) != vec.Taille()) {cout << "erreur taille matrice < taille vecteur"; cout << "dimMat = " << dim(1) << " dimVect = " << vec.Taille() << '\n'; cout << "Vecteur Mat_creuse_CompCol::Prod_mat_vec (const Vecteur& vec)" << endl; } #endif // récup de l'homologue de vec en vecteur_double const VECTOR_double * vec_double_pt = vec.Nouveau_MV_Vector_double_const(); const VECTOR_double& vec_double = (*vec_double_pt); // const VECTOR_double vec_double(vec.MV_vecteur_double()); // définition du vecteur de retour Vecteur res(dim(0)); // utilisation de la multiplication dèjà définie VECTOR_double res_double = this->CompCol_Mat_double::operator *(vec_double); res = res_double; delete vec_double_pt; return res; }; // Multiplication d'une matrice par un vecteur ( A * vec ) // ici on se sert du second vecteur pour le résultat Vecteur& Mat_creuse_CompCol::Prod_mat_vec (const Vecteur& vec,Vecteur& res) const { #ifdef MISE_AU_POINT if (dim(1)> vec.Taille()) {cout << "erreur taille matrice < taille vecteur"; cout << "dimMat = " << dim(1) << " dimVect = " << vec.Taille() << '\n'; cout << "Vecteur& Mat_creuse_CompCol::Prod_mat_vec (const Vecteur& vec,Vecteur& res)" << endl; } #endif // récup de l'homologue de vec en vecteur_double const VECTOR_double * vec_double_pt = vec.Nouveau_MV_Vector_double_const(); const VECTOR_double& vec_double = (*vec_double_pt); // const VECTOR_double vec_double(vec.MV_vecteur_double()); // définition du vecteur de retour res.Change_taille(dim(0)); // utilisation de la multiplication dèjà définie VECTOR_double res_double = this->CompCol_Mat_double::operator *(vec_double); res = res_double; delete vec_double_pt; return res; }; // Multiplication d'une ligne iligne de la matrice avec un vecteur de // dimension = le nombre de colonne de la matrice double Mat_creuse_CompCol::Prod_Ligne_vec ( int iligne,const Vecteur& vec) const { #ifdef MISE_AU_POINT if (dim(1) != vec.Taille()) { cout << " \n erreur la taille du vecteur = " << vec.Taille() <<" n est pas correcte "; cout << " dimMatrice = " << dim(1); cout << " double Mat_creuse_CompCol::Prod_Ligne_vec ( int iligne,Vecteur& vec)" << endl; Sortie (1); } #endif // retour du produit scalaire return Ligne(iligne) * vec; }; // Multiplication d'un vecteur avec une colonne icol de la matrice // dimension = le nombre de ligne de la matrice double Mat_creuse_CompCol::Prod_vec_col( int jcol,const Vecteur& vec) const { #ifdef MISE_AU_POINT if (dim(0) != vec.Taille()) { cout << " \n erreur la taille du vecteur = " << vec.Taille() <<" n est pas correcte "; cout << " dimMatrice = " << dim(0); cout << " double Mat_creuse_CompCol::Prod_vec_col( int icol,Vecteur& vec)" << endl; Sortie (1); } #endif // retour du produit scalaire return Colonne(jcol) * vec; }; // calcul du produit : (vec_1)^T * A * (vect_2) double Mat_creuse_CompCol::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2) const { #ifdef MISE_AU_POINT if (vec1.Taille() != dim(0)) {cout << "erreur de taille, la dimension de (vec1)^T= " << vec1.Taille() << " n'a pas la même dimension"; cout << " que le le nombre de ligne de la matrice= " << dim(0) << "\n Mat_creuse_CompCol::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2)" << endl; Sortie(1); } if (vec2.Taille() != dim(1)) {cout << "erreur de taille, la dimension de (vec2)= " << vec2.Taille() << " n'a pas la même dimension"; cout << " que le le nombre de colonne de la matrice= " << dim(1) << "\n Mat_creuse_CompCol::vectT_mat_vec(const Vecteur& vec1, const Vecteur& vec2)" << endl; Sortie(1); } #endif // récup de l'homologue de vec2 en vecteur_double const VECTOR_double * vec_double_pt = vec2.Nouveau_MV_Vector_double_const(); const VECTOR_double& vec_double = (*vec_double_pt); // utilisation de la multiplication dèjà définie VECTOR_double res_double = this->CompCol_Mat_double::operator *(vec_double); // produit scalaire double retour = 0.; for (int i=0;i> (istream & entree, Mat_creuse_CompCol & mat) { // vérification du type string type; entree >> type; if (type != "Mat_creuse_CompCol") {Sortie (1); return entree; } // les dimensions entree >> mat.dim_[0] >> mat.dim_[1] >> mat.nz_ >> mat.base_; // les datas string toto; entree >> toto >> mat.val_; entree >> toto >> mat.rowind_; entree >> toto >> mat.colptr_; return entree; }; // surcharge de l'operateur d'ecriture typée ostream & operator << ( ostream & sort,const Mat_creuse_CompCol & mat) { // un indicateur donnant le type puis les dimensions sort << "Mat_creuse_CompCol " << mat.dim(0) << " " << mat.dim(1) << " " << mat.nz_ << " " << mat.base_; // les datas sort << "\n données " << mat.val_; sort << "\n indices_ligne " << mat.rowind_; sort << "\n indices_colonnes " << mat.colptr_; return sort; };