matrice.C

00001 /*
00002  *  Methods of class Matrice
00003  *
00004  *   (see file matrice.h for documentation)
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 1999-2001 Philippe Grandclement
00010  *
00011  *   This file is part of LORENE.
00012  *
00013  *   LORENE is free software; you can redistribute it and/or modify
00014  *   it under the terms of the GNU General Public License as published by
00015  *   the Free Software Foundation; either version 2 of the License, or
00016  *   (at your option) any later version.
00017  *
00018  *   LORENE is distributed in the hope that it will be useful,
00019  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  *   GNU General Public License for more details.
00022  *
00023  *   You should have received a copy of the GNU General Public License
00024  *   along with LORENE; if not, write to the Free Software
00025  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  */
00028 
00029 
00030 char matrice_C[] = "$Header: /cvsroot/Lorene/C++/Source/Matrice/matrice.C,v 1.17 2008/08/19 06:42:00 j_novak Exp $" ;
00031 
00032 /*
00033  * $Id: matrice.C,v 1.17 2008/08/19 06:42:00 j_novak Exp $
00034  * $Log: matrice.C,v $
00035  * Revision 1.17  2008/08/19 06:42:00  j_novak
00036  * Minor modifications to avoid warnings with gcc 4.3. Most of them concern
00037  * cast-type operations, and constant strings that must be defined as const char*
00038  *
00039  * Revision 1.16  2006/06/05 09:47:42  j_novak
00040  * Initialisation of the member band to zero, in order not to have messages from
00041  * the memory debugger.
00042  *
00043  * Revision 1.15  2005/11/24 14:07:29  j_novak
00044  * Minor speed enhancement for annule_hard().
00045  *
00046  * Revision 1.14  2005/10/24 12:42:32  p_grandclement
00047  * correction of annule_hard
00048  *
00049  * Revision 1.13  2005/10/24 09:22:24  p_grandclement
00050  * addition of annule_hard for matrices
00051  *
00052  * Revision 1.12  2005/09/16 12:29:02  j_novak
00053  * New method del_deriv() and reorganization of band, lu, permute handling.
00054  *
00055  * Revision 1.11  2005/01/25 12:47:34  j_novak
00056  * Added some member arithmetic and operator=(Tbl).
00057  *
00058  * Revision 1.10  2004/12/29 12:27:36  j_novak
00059  * permute is now a Itbl* which array is sent directly to the LAPACK routines.
00060  * It is now possible to solve a general system (i.e. even if the Matrice
00061  * is not in a banded form).
00062  *
00063  * Revision 1.9  2004/10/05 15:44:19  j_novak
00064  * Minor speed enhancements.
00065  *
00066  * Revision 1.8  2004/08/24 09:14:43  p_grandclement
00067  * Addition of some new operators, like Poisson in 2d... It now requieres the
00068  * GSL library to work.
00069  *
00070  * Also, the way a variable change is stored by a Param_elliptic is changed and
00071  * no longer uses Change_var but rather 2 Scalars. The codes using that feature
00072  * will requiere some modification. (It should concern only the ones about monopoles)
00073  *
00074  * Revision 1.7  2003/12/19 16:21:44  j_novak
00075  * Shadow hunt
00076  *
00077  * Revision 1.6  2002/10/16 14:36:42  j_novak
00078  * Reorganization of #include instructions of standard C++, in order to
00079  * use experimental version 3 of gcc.
00080  *
00081  * Revision 1.5  2002/09/24 10:51:16  e_gourgoulhon
00082  *
00083  * The case of a 1D Tbl in the constructor from Tbl is now taken into account
00084  * (resulting in a single-column matrix).
00085  *
00086  * Revision 1.4  2002/09/24 08:36:44  e_gourgoulhon
00087  *
00088  * Corrected error in output (operator<<) : permutted number of rows and columns
00089  *
00090  * Added matrix multiplication
00091  * Added function transpose()
00092  *
00093  * Revision 1.3  2002/09/09 13:00:39  e_gourgoulhon
00094  * Modification of declaration of Fortran 77 prototypes for
00095  * a better portability (in particular on IBM AIX systems):
00096  * All Fortran subroutine names are now written F77_* and are
00097  * defined in the new file C++/Include/proto_f77.h.
00098  *
00099  * Revision 1.2  2002/01/03 13:18:41  j_novak
00100  * Optimization: the members set(i,j) and operator(i,j) of class Matrice are
00101  * now defined inline. Matrice is a friend class of Tbl.
00102  *
00103  * Revision 1.1.1.1  2001/11/20 15:19:28  e_gourgoulhon
00104  * LORENE
00105  *
00106  * Revision 2.9  1999/12/24  10:19:16  eric
00107  * Suppression des definitions de nbl et nbc lignes 149 et 150.
00108  *
00109  * Revision 2.8  1999/11/30  17:45:16  phil
00110  * changerment prototypage
00111  *
00112  * Revision 2.7  1999/10/12  15:49:16  phil
00113  * apres set band, lu et permute ne sont plus a jour ...
00114  *
00115  * Revision 2.6  1999/10/12  09:42:17  phil
00116  * retrour versian anterieure
00117  *
00118  * Revision 2.5  1999/10/12  09:39:07  phil
00119  * passage en const
00120  *
00121  * Revision 2.4  1999/10/11  09:35:07  phil
00122  * ajout de determinant et val_propre  + modif de operator= (const Matrice&)
00123  *
00124  * Revision 2.3  1999/10/05  17:02:46  phil
00125  * ajout de determinant et val_propre
00126  *
00127  * Revision 2.2  1999/04/13  13:57:23  phil
00128  * ajout proto.h
00129  *
00130  * Revision 2.1  1999/04/07  14:18:51  phil
00131  * optimisation egalite
00132  *
00133  * Revision 2.0  1999/04/07  14:10:05  phil
00134  * *** empty log message ***
00135  *
00136  *
00137  * $Header: /cvsroot/Lorene/C++/Source/Matrice/matrice.C,v 1.17 2008/08/19 06:42:00 j_novak Exp $
00138  *
00139  */
00140 
00141 
00142 //fichiers includes
00143 #include <stdlib.h>
00144 #include "matrice.h"
00145 #include "proto_f77.h"
00146 
00147 //Destructeur logique
00148 
00149 void Matrice::del_t() {
00150     if (std != 0x0) delete std ;
00151     std = 0x0 ; 
00152     del_deriv() ;
00153 }
00154 
00155 //Destructeur des quantites derivees
00156 
00157 void Matrice::del_deriv() {
00158     if (band != 0x0) delete band ;
00159     if (lu != 0x0) delete lu ;
00160     if (permute != 0x0) delete permute ;
00161     band = 0x0 ;
00162     lu = 0x0 ;
00163     permute = 0x0 ;
00164 }
00165 
00166 //Manipulation des etats
00167 
00168 void Matrice::set_etat_qcq() {
00169     std->set_etat_qcq() ;
00170     del_deriv() ;
00171     etat = ETATQCQ ;
00172 }
00173 
00174 void Matrice::set_etat_zero() {
00175     std->set_etat_zero() ;
00176     del_deriv() ;
00177     etat = ETATZERO ;
00178 }
00179 
00180 void Matrice::set_etat_nondef() {
00181     if (std != 0x0) std->set_etat_nondef() ;
00182     del_deriv() ;
00183     etat = ETATNONDEF ;
00184 }
00185 
00186 void Matrice::annule_hard() {
00187     std->set_etat_qcq() ;
00188     del_deriv() ;
00189     etat = ETATQCQ ;
00190 
00191     for (int i=0 ; i<std->get_taille() ; i++)
00192     std->t[i] = 0 ;
00193 }
00194      
00195 // Constructeurs
00196 Matrice::Matrice (int i, int j) {
00197     etat = ETATNONDEF ;
00198     std = new Tbl(i, j) ;
00199     kl = 0 ;
00200     ku = 0 ;
00201     band = 0x0 ;
00202     lu = 0x0 ;
00203     permute = 0x0 ;
00204 }
00205 
00206 
00207 Matrice::Matrice (const Matrice & source) {
00208     etat = source.etat ;
00209     kl = source.kl ;
00210     ku = source.ku ;
00211     std = new Tbl(*source.std) ;
00212     if (source.band != 0x0) band = new Tbl(*source.band) ;
00213     else band = 0x0 ;
00214     if (source.lu != 0x0) lu = new Tbl(*source.lu) ;
00215     else lu = 0x0 ;
00216     if (source.permute != 0x0) permute = new Itbl(*source.permute) ;
00217     else permute = 0x0 ;
00218 }
00219 
00220 
00221 Matrice::Matrice (const Tbl & source) {
00222     etat = source.get_etat() ;
00223     kl = 0 ;
00224     ku = 0 ;
00225     if (source.get_ndim() == 1) {     // column vector
00226         int n = source.get_taille() ;
00227         std = new Tbl(n,1) ;
00228         if (source.get_etat() == ETATZERO) {
00229             std->set_etat_zero() ;
00230         }
00231     else  {
00232                 assert( source.get_etat() == ETATQCQ ) ;
00233                 std->set_etat_qcq() ;
00234                 for (int i=0; i<n; i++) {
00235                         std->t[i] = source.t[i] ;
00236                 }
00237     }
00238     }
00239     else {                        // 2D Tbl
00240         std = new Tbl(source) ;
00241     }
00242     band = 0x0 ;
00243     lu = 0x0 ;
00244     permute = 0x0 ;
00245 }
00246 
00247 // destructeur
00248 Matrice::~Matrice() {
00249     del_t() ;
00250 }
00251 
00252 // Extraction des dimensions
00253 int Matrice::get_dim(int i) const {
00254     return std->get_dim(i) ;
00255 }
00256 
00257 // affectation
00258 void Matrice::operator= (double x) {
00259     if (x == 0 ) set_etat_zero() ;
00260     else {
00261     set_etat_qcq() ;
00262     *std = x ;
00263     }
00264 }
00265 
00266 void Matrice::operator= (const Matrice &source) {
00267     
00268     assert (std->get_dim(0) == source.std->get_dim(0)) ;
00269     assert (std->get_dim(1) == source.std->get_dim(1)) ;
00270     
00271     switch (source.etat) {
00272     case ETATNONDEF :
00273         set_etat_nondef() ;
00274         break ;
00275     case ETATZERO :
00276         set_etat_zero() ;
00277         break ;
00278     case ETATQCQ :
00279         set_etat_qcq() ;
00280         del_t() ;
00281         
00282         if (source.std != 0x0)
00283         std = new Tbl(*source.std) ;
00284         
00285         if (source.band != 0x0) {
00286         band = new Tbl(*source.band) ;
00287         ku = source.ku ;
00288         kl = source.kl ;
00289         }
00290         
00291         if (source.lu != 0x0) {
00292         lu = new Tbl(*source.lu) ;
00293         permute = new Itbl(*source.permute) ;
00294         }
00295         break ;
00296     }
00297 }
00298 
00299 void Matrice::operator= (const Tbl &source) {
00300     
00301     assert (std->get_dim(0) == source.get_dim(0)) ;
00302     assert (std->get_dim(1) == source.get_dim(1)) ;
00303     
00304     switch (source.etat) {
00305     case ETATNONDEF :
00306         set_etat_nondef() ;
00307         break ;
00308     case ETATZERO :
00309         set_etat_zero() ;
00310         break ;
00311     case ETATQCQ :
00312         set_etat_qcq() ;
00313         del_t() ;
00314         
00315         assert (source.t != 0x0) ;
00316         std = new Tbl(source) ;
00317         break ;
00318     }
00319 }
00320 
00321 
00322 //Impression
00323 ostream& operator<< (ostream& flux, const Matrice & source) {
00324     switch (source.std->get_etat()) {
00325     case ETATZERO :
00326         flux << "Null matrix. " << endl ;
00327         break ;
00328     case ETATNONDEF :
00329         flux << "Undefined matrix. " << endl ;
00330         break ;
00331     case ETATQCQ :
00332         int nbl = source.std->get_dim(1) ;
00333         int nbc = source.std->get_dim(0) ;
00334         flux << "Matrix " << nbl << " * " << nbc << endl ;
00335         for (int i=0 ; i<nbl ; i++) {
00336         for (int j=0 ; j<nbc ; j++)
00337             flux << (*source.std)(i, j) << "  " ;
00338         flux << endl ;      
00339         }
00340     }
00341     
00342     flux << endl ;
00343     
00344     if ((source.band != 0x0) && (source.band->get_etat() != ETATNONDEF)) {
00345     flux << "Matrix : " << source.ku << " upper diags. and  "
00346          << source.kl << " lower diags." << endl ;
00347     }
00348     //    else flux << "Diagonalisation non faite." << endl ;
00349     
00350     if ((source.lu != 0x0) && (source.lu->get_etat() != ETATNONDEF))
00351     flux << "LU factorization done." << endl ;
00352 
00353 return flux ;
00354 }
00355 
00356 // Passage matrice a bande : stockage LAPACK
00357 void Matrice::set_band (int u, int l) const {
00358     if (band != 0x0) return ;
00359     else {
00360     int n = std->get_dim(0) ;
00361     assert (n == std->get_dim(1)) ;
00362     
00363     ku = u ; kl = l ;
00364     int ldab = 2*l+u+1 ;
00365     band = new Tbl(ldab*n) ;
00366     
00367     band->annule_hard() ; 
00368     
00369     for (int i=0 ; i<u ; i++)
00370         for (int j=u-i ; j<n ; j++)
00371         band->set(j*ldab+i+l) = (*this)(j-u+i, j) ;
00372     
00373     for (int j=0 ; j<n ; j++)
00374         band->set(j*ldab+u+l) = (*this)(j, j) ;
00375     
00376     for (int i=u+1 ; i<u+l+1 ; i++)
00377         for (int j=0 ; j<n-i+u ; j++)
00378         band->set(j*ldab+i+l) = (*this) (i+j-u, j) ;
00379 
00380     }
00381     return ; 
00382 }
00383 
00384 //Decomposition UL : stockage LAPACK
00385 void Matrice::set_lu() const {
00386     if (lu != 0x0) {
00387     assert (permute != 0x0) ;
00388     return ;
00389     }
00390     else {
00391     // Decomposition LU
00392     int n = std->get_dim(0) ;
00393     int ldab, info ;
00394     permute = new Itbl(n) ;
00395     permute->set_etat_qcq() ;
00396 
00397     // Cas d'une matrice a bandes
00398     if (band != 0x0) {
00399         assert (band->get_etat() == ETATQCQ) ;
00400         ldab = 2*kl+ku+1 ;
00401         lu = new Tbl(*band) ;
00402         
00403         F77_dgbtrf(&n, &n, &kl, &ku, lu->t, &ldab, permute->t, &info) ;
00404     }
00405     else { // matrice generale
00406         assert (std->get_etat() == ETATQCQ) ;
00407         ldab = n ;
00408         lu = new Tbl(*std) ;
00409         
00410         F77_dgetrf(&n, &n, lu->t, &ldab, permute->t, &info) ;
00411     }
00412     }
00413     return ;
00414 }
00415 
00416 // Solution de Ax = B : utilisation de LAPACK et decomposition lu.
00417 Tbl Matrice::inverse (const Tbl& source) const {
00418     
00419     assert(lu != 0x0) ;
00420     assert(lu->get_etat() == ETATQCQ) ;
00421     assert(permute != 0x0) ;
00422     assert(permute->get_etat() == ETATQCQ) ;
00423        
00424     int n = source.get_dim(0) ;
00425     assert (get_dim(1) == n) ;
00426     int ldab, info ;
00427     const char* trans ;
00428     int nrhs = 1 ;
00429     int ldb = n ;
00430         
00431     Tbl res(source) ;
00432     
00433     if (band != 0x0) { //Cas d'une matrice a bandes
00434     ldab = 2*kl+ku+1 ;
00435     trans = "N" ;
00436     F77_dgbtrs(trans, &n, &kl, &ku, &nrhs, lu->t,
00437            &ldab, permute->t, res.t, &ldb, &info);
00438     }
00439     else { // Cas general
00440     ldab = n ;
00441     trans = "T" ; // stockage different entre le C et le fortran
00442     F77_dgetrs(trans, &n, &nrhs, lu->t, &ldab, permute->t,
00443            res.t, &ldb, &info) ;
00444     }
00445     
00446     return res ;
00447 }
00448 
00449 // Renvoit les valeurs propres de la matrice (appel de LAPACK) :
00450 Tbl Matrice::val_propre() const {
00451     
00452     assert (etat != ETATNONDEF) ;
00453     assert (std != 0x0) ;
00454     
00455     const char* jobvl = "N" ;
00456     const char* jobvr = "N" ;
00457     
00458     int n = get_dim(0) ;
00459     assert (n == get_dim(1)) ;
00460     
00461     double* a = new double [n*n] ;
00462     for (int i=0 ; i<n*n ; i++)
00463     a[i] = std->t[i] ;
00464     
00465     int lda = n ;
00466     double* wr = new double[n] ;
00467     double* wi = new double[n] ;
00468     
00469     int ldvl = 1 ;
00470     double* vl = 0x0 ;
00471     int ldvr = 1 ;
00472     double* vr = 0x0 ;
00473     
00474     int ldwork = 3*n ;
00475     double* work = new double[ldwork] ;
00476     
00477     int info ;
00478     
00479     F77_dgeev(jobvl, jobvr, &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr,
00480         work, &ldwork, &info) ;
00481     
00482     Tbl result(2, n) ;
00483     result.set_etat_qcq() ;
00484     
00485     for (int i=0 ; i<n ; i++) {
00486     result.set(0, i) = wr[n-i-1] ;
00487     result.set(1, i) = wi[n-i-1] ;
00488     }
00489     
00490     delete [] wr ;
00491     delete [] wi ;
00492     delete [] a ;
00493     delete [] work ;
00494     
00495     return result ; 
00496     
00497 }
00498 
00499 // les valeurs vecteurs propres de la matrice (appel de LAPACK) :
00500 Matrice Matrice::vect_propre() const {
00501     
00502     assert (etat != ETATNONDEF) ;
00503     assert (std != 0x0) ;
00504     
00505     const char* jobvl = "V" ;
00506     const char* jobvr = "N" ;
00507     
00508     int n = get_dim(0) ;
00509     assert (n == get_dim(1)) ;
00510     
00511     double* a = new double [n*n] ;
00512     for (int i=0 ; i<n*n ; i++)
00513     a[i] = std->t[i] ;
00514     
00515     int lda = n ;
00516     double* wr = new double[n] ;
00517     double* wi = new double[n] ;
00518     
00519     int ldvl = n ;
00520     double* vl = new double[ldvl*ldvl] ;
00521     int ldvr = 1 ;
00522     double* vr = 0x0 ;
00523     
00524     int ldwork = 4*n ;
00525     double* work = new double[ldwork] ;
00526     
00527     int info ;
00528     
00529     F77_dgeev(jobvl, jobvr, &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr,
00530         work, &ldwork, &info) ;
00531     
00532    
00533     Matrice res (n,n) ;
00534     res.set_etat_qcq() ;
00535 
00536     int conte = 0 ;
00537     for (int i=0 ; i<n ; i++)
00538       for (int j=0 ; j<n ; j++) {
00539     res.set(j,n-i-1) = vl[conte] ;
00540     conte ++ ;
00541       }
00542     
00543     delete [] wr ;
00544     delete [] wi ;
00545     delete [] a ;
00546     delete [] work ;
00547     delete [] vl ;
00548 
00549     return res ;
00550 }
00551 
00552 // Calcul le determinant :
00553 double Matrice::determinant() const {
00554     
00555     int n = get_dim(0) ;
00556     assert(n == get_dim(1)) ;
00557     
00558     Tbl valp(val_propre()) ;
00559     double result = 1 ;
00560     for (int i = 0 ; i<n ; i++)
00561     if (valp(1, i) == 0)
00562         result *= valp(0, i) ;
00563     else {
00564         result*= valp(0, i)*valp(0, i)+valp(1, i)*valp(1, i) ;
00565         i++ ;
00566     }
00567     return result ;
00568 }
00569 
00570 // Transposee
00571 Matrice Matrice::transpose() const {
00572 
00573     int nbl = std->get_dim(1) ;
00574     int nbc = std->get_dim(0) ;
00575 
00576     Matrice resu(nbc, nbl) ;
00577     
00578     if (etat == ETATZERO) {
00579         resu.set_etat_zero() ;
00580     }
00581     else{
00582         assert(etat == ETATQCQ) ;
00583         resu.set_etat_qcq() ;
00584         for (int i=0; i<nbc; i++) {
00585             for (int j=0; j<nbl; j++) {
00586                 resu.set(i,j) = (*std)(j,i) ;
00587             }
00588         }
00589     }
00590     return resu ;
00591 }
00592 
00593 
00594 // Operateurs d'arithmetique
00595 void Matrice::operator+=(const Matrice& a) {
00596     assert((std != 0x0)&&(a.std != 0x0)) ;
00597     std->operator+=(*a.std) ;
00598 }
00599 
00600 void Matrice::operator-=(const Matrice& a) {
00601     assert((std != 0x0)&&(a.std != 0x0)) ;
00602     std->operator-=(*a.std) ;
00603 }
00604 
00605 void Matrice::operator+=(double x) {
00606     assert(std != 0x0);
00607     std->operator+=(x) ;
00608 }
00609 
00610 void Matrice::operator-=(double x) {
00611     assert(std != 0x0);
00612     std->operator-=(x) ;
00613 }
00614 
00615 void Matrice::operator*=(double x) {
00616     assert(std != 0x0);
00617     std->operator*=(x) ;
00618 }
00619 
00620 void Matrice::operator/=(double x) {
00621     assert(std != 0x0);
00622     assert(x != 0) ;
00623     std->operator/=(x) ;
00624 }
00625 
00626 // Operateurs d'arithmetique non membres
00627 Matrice operator+ (const Matrice& a, const Matrice& b) {
00628     assert((a.std != 0x0) && (b.std != 0x0)) ;
00629     Matrice res(*a.std+*b.std) ;
00630     return res ;
00631 }
00632 
00633 Matrice operator- (const Matrice& a, const Matrice& b) {
00634     assert((a.std != 0x0) && (b.std != 0x0)) ;
00635     Matrice res(*a.std-*b.std) ;
00636     return res ;
00637 }
00638 
00639 Matrice operator* (const Matrice& a, double x) {
00640     assert(a.std != 0x0) ;
00641     Matrice res(*a.std*x);
00642     return res ;
00643 }
00644 
00645 Matrice operator* (double x, const Matrice& a) {
00646     assert(a.std != 0x0) ;
00647     Matrice res(*a.std*x);
00648     return res ;
00649 }
00650 
00651 Matrice operator* (const Matrice& aa, const Matrice& bb) {
00652 
00653     int nbla = aa.std->get_dim(1) ;
00654     int nbca = aa.std->get_dim(0) ;
00655 #ifndef NDEBUG
00656     int nblb = bb.std->get_dim(1) ;
00657 #endif
00658     int nbcb = bb.std->get_dim(0) ;
00659     
00660     assert( nbca == nblb ) ;
00661     
00662     Matrice resu(nbla, nbcb) ;
00663     
00664     if ( (aa.get_etat() == ETATZERO) || (bb.get_etat() == ETATZERO) ) {
00665         resu.set_etat_zero() ;
00666     }
00667     else {
00668         assert( aa.get_etat() == ETATQCQ ) ;
00669         assert( bb.get_etat() == ETATQCQ ) ;
00670         resu.set_etat_qcq() ;
00671         for (int i=0; i<nbla; i++) {
00672             for (int j=0; j<nbcb; j++) {
00673                 double sum = 0 ;
00674                 for (int k=0; k<nbca; k++) {
00675                     sum += aa(i,k) * bb(k, j) ;
00676                 }
00677                 resu.set(i,j) = sum ;
00678             }
00679             
00680         }
00681     }
00682 
00683     return resu ;
00684 }
00685 
00686 Matrice operator/ (const Matrice& a, double x) {
00687     assert (x != 0) ;
00688     assert(a.std != 0x0) ;
00689     Matrice res(*a.std/x);
00690     return res ;
00691 }

Generated on Tue Feb 7 01:35:18 2012 for LORENE by  doxygen 1.4.6