00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 #include <stdlib.h>
00144 #include "matrice.h"
00145 #include "proto_f77.h"
00146
00147
00148
00149 void Matrice::del_t() {
00150 if (std != 0x0) delete std ;
00151 std = 0x0 ;
00152 del_deriv() ;
00153 }
00154
00155
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
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
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) {
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 {
00240 std = new Tbl(source) ;
00241 }
00242 band = 0x0 ;
00243 lu = 0x0 ;
00244 permute = 0x0 ;
00245 }
00246
00247
00248 Matrice::~Matrice() {
00249 del_t() ;
00250 }
00251
00252
00253 int Matrice::get_dim(int i) const {
00254 return std->get_dim(i) ;
00255 }
00256
00257
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
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
00349
00350 if ((source.lu != 0x0) && (source.lu->get_etat() != ETATNONDEF))
00351 flux << "LU factorization done." << endl ;
00352
00353 return flux ;
00354 }
00355
00356
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
00385 void Matrice::set_lu() const {
00386 if (lu != 0x0) {
00387 assert (permute != 0x0) ;
00388 return ;
00389 }
00390 else {
00391
00392 int n = std->get_dim(0) ;
00393 int ldab, info ;
00394 permute = new Itbl(n) ;
00395 permute->set_etat_qcq() ;
00396
00397
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 {
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
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) {
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 {
00440 ldab = n ;
00441 trans = "T" ;
00442 F77_dgetrs(trans, &n, &nrhs, lu->t, &ldab, permute->t,
00443 res.t, &ldb, &info) ;
00444 }
00445
00446 return res ;
00447 }
00448
00449
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
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
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
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
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
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 }