1
/************************************************************************************
2
TerraLib - a library for developing GIS applications.
3
Copyright � 2001-2004 INPE and Tecgraf/PUC-Rio.
5
This code is part of the TerraLib library.
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public
8
License as published by the Free Software Foundation; either
9
version 2.1 of the License, or (at your option) any later version.
11
You should have received a copy of the GNU Lesser General Public
12
License along with this library.
14
The authors reassure the license terms regarding the warranties.
15
They specifically disclaim any warranties, including, but not limited to,
16
the implied warranties of merchantability and fitness for a particular purpose.
17
The library provided hereunder is on an "as is" basis, and the authors have no
18
obligation to provide maintenance, support, updates, enhancements, or modifications.
19
In no event shall INPE and Tecgraf / PUC-Rio be held liable to any party for direct,
20
indirect, special, incidental, or consequential damages arising out of the use
21
of this library and its documentation.
22
*************************************************************************************/
24
// TeMatrix.c -- matrix of type double
43
for( i = 0; i < nrow; i++ )
62
TeMatrix::Alloc(int nl, int nc)
65
if( nl <= 0 || nc <= 0 ){
70
if ( (mat = new double*[nrow]) == NULL ){
75
for( i = 0; i < nrow; i++ ) mat[i] = NULL;
76
for( i = 0; i < nrow; i++ ){
77
if( (mat[i] = new double[ncol]) == NULL ){
81
for( j = 0; j < ncol; j++ ) mat[i][j] = (double)0.;
86
TeMatrix::TeMatrix(const TeMatrix& m)
95
TeMatrix::Init( int nl, int nc , double* f )
98
return Init( nl, nc, (double) 0 );
99
if( Alloc( nl, nc ) ){
102
for ( i = 0; i < nrow; i++)
103
for (j = 0; j < ncol; j++)
111
TeMatrix::Init(int nl, int nc, double f )
114
if( Alloc( nl, nc ) ){
116
for (i = 0; i < nrow; i++)
117
for (j = 0; j < ncol; j++)
125
TeMatrix::Init(int k, double* f)
128
return Init( k, k, (double) 0 );
129
if( Alloc(k,k) == false )
132
for ( i = 0; i < nrow; i++ )
133
for (j = 0; j < ncol; j++)
134
mat[i][j] = (i==j)? f[i]: (double)0.;
139
TeMatrix::Init(int k, double f)
141
if( Alloc(k,k) == false )
144
for (i=0; i<nrow; i++)
145
for (j=0; j<ncol; j++)
146
mat[i][j] = (i==j)? (double)f:0;
151
TeMatrix::operator=(const TeMatrix& m)
154
if( Alloc(m.nrow,m.ncol) == false ){
155
printf("\nMatrix::operator=:no memory available \n");
159
for( i = 0; i < nrow; i++)
160
for( j = 0; j < ncol; j++)
161
mat[i][j] = m.mat[i][j];
166
TeMatrix::operator==(const TeMatrix& m) const
168
if( nrow != m.nrow || ncol != m.ncol )
171
for ( i = 0; i < nrow; i++)
172
for ( j = 0; j < ncol; j++)
173
if ( mat[i][j]!= m.mat[i][j] )
179
TeMatrix::operator*=(double f)
182
for( i = 0; i < nrow; i++)
183
for( j = 0; j < ncol; j++)
189
//-------------------------------------------------------------friend methods
192
operator+(const TeMatrix& m,const TeMatrix& n)
194
if( m.nrow != n.nrow || m.ncol != n.ncol ){
195
printf("\nMatrix::operator+ >>> Operandos com tamanhos diferentes\n");
199
if( rm.Init(m.Nrow(),m.Ncol()) == false ){
200
printf("\nMatrix::operator+ >>> Memoria nao disponivel\n");
204
for ( i = 0; i < m.Nrow(); i++)
205
for ( j = 0; j < m.Ncol(); j++)
206
rm.mat[i][j] = m.mat[i][j] + n.mat[i][j];
211
operator-(const TeMatrix& m,const TeMatrix& n)
213
if( m.nrow != n.nrow || m.ncol != n.ncol ){
214
printf("\nMatrix::operator+ >>> Operandos com tamanhos diferentes\n");
218
if( rm.Init(m.Nrow(),m.Ncol()) == false ){
219
printf("\nMatrix::operator- >>> Memoria nao disponivel\n");
224
for ( i = 0; i < m.Nrow(); i++)
225
for ( j = 0; j < m.Ncol(); j++)
226
rm.mat[i][j] = m.mat[i][j] - n.mat[i][j];
231
TeMatrix::operator-()
234
if( rm.Init(Nrow(),Ncol()) == false ){
235
printf("\n operator-:no memory \n");
239
for (i=0; i<Nrow(); i++)
240
for (j=0; j<Ncol(); j++)
241
rm.mat[i][j] = -mat[i][j];
246
operator*(const TeMatrix& m,const TeMatrix& n)
248
if ( m.Ncol() != n.Nrow() ) {
249
printf( "\nMatrix::operator* >>> Operandos com tamanhos diferentes\n");
252
int nr = m.Nrow(), nc =n.Ncol();
254
if( result.Init(nr,nc) == false){
255
printf("\nMatrix::operator* >>> Memoria nao disponivel\n");
259
double sum = (double)0.;
262
for ( l = 0; l < m.Nrow(); l++){
263
for ( c = 0; c < n.Ncol(); c++){
265
for ( i = 0; i < m.Ncol(); i++)
266
sum += m.mat[l][i] * n.mat[i][c];
267
result.mat[l][c] = sum;
275
operator*(double f,const TeMatrix& m)
277
int nr = m.Nrow(), nc =m.Ncol();
279
if( rm.Init(nr,nc) == false){
280
printf("\noperator*:no memory");
284
for (i = 0; i < rm.Nrow(); i++)
285
for (j = 0; j < rm.Ncol(); j++)
286
rm.mat[i][j] = f * m.mat[i][j];
292
TeMatrix::isUpperTriangle() const
294
// elements above diagonal != 0
296
for(j = 0; j < ncol; j++)
297
for(i = j+1; i < nrow; i++)
298
if ( mat[i][j] != (double)0 )
305
TeMatrix::isLowerTriangle() const
307
// elements under diagonal different 0
309
/* for(j=0; j<ncol; j++)
310
for(i=j+1; i<nrow; i++)
311
if ( mat[i][j]!=0 )*/
313
for (i=0; i< nrow; i++)
314
for (j= i+1; j <ncol; j++)
315
if ( mat[i][j] != (double)0)
321
TeMatrix:: Determinant()
323
if (Nrow() != Ncol()) {
324
printf("\nMatrix::Determinant >>> not a square matrix\n");
327
if (Nrow()==1) return mat[0][0];
329
return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
331
return ( mat[0][0] * mat[1][1] * mat[2][2]
332
+mat[0][1] * mat[1][2] * mat[2][0]
333
+mat[0][2] * mat[1][0] * mat[2][1]
334
-mat[0][1] * mat[1][0] * mat[2][2]
335
-mat[0][0] * mat[1][2] * mat[2][1]
336
-mat[0][2] * mat[1][1] * mat[2][0] );
337
if ( isUpperTriangle() ) {
340
for (i = 0; i < Nrow(); i++) val *= mat[i][i];
348
for(j = 0; j < Ncol(); j++) {
349
if( CoFactor(0,j, mt) == false )
351
det = mt.Determinant();
352
val += sign * mat[0][j] * det;
359
TeMatrix::CoFactor(int irow, int jcol, TeMatrix& mt ) const
361
if ( nrow == 1||ncol == 1 ) {
362
printf("\nMatrix::CoFactor >>> can't CoFactor row or column matrix\n");
365
if( mt.Init(nrow-1,ncol-1) == false){
366
printf("\nMatrix::CoFactor: Memoria nao disponivel\n");
369
int getcol, getrow =0;
371
for(i=0; i < mt.Nrow(); i++) {
372
if ( getrow == irow ) ++getrow;
373
if ( getrow == nrow ) break;
375
for(j=0; j < mt.Ncol(); j++) {
376
if ( getcol==jcol ) ++getcol;
377
if ( getcol==ncol ) continue;
378
mt.mat[i][j] = mat[getrow][getcol];
387
TeMatrix::Transpose( TeMatrix &rm ) const
390
printf("\nMatrix::Transpose >>> Operacao usa duas matrizes\n");
394
if( rm.Init( ncol, nrow ) == false){
395
printf("\nMatrix::Transpose >>> Memoria nao disponivel\n");
399
for(i = 0; i < ncol; i++)
400
for( j = 0; j < nrow; j++)
401
rm.mat[i][j] = mat[j][i];
407
TeMatrix::isSimetric() const
412
printf("\nMatrix::isSimetric >>> Memoria nao disponivel\n");
416
for (i = 0; i < nrow; i++)
417
for (j = 0; j < ncol; j++)
418
if ( mat[i][j] != mat[j][i]) return false;
425
TeMatrix::isPositiveDefinide() const
427
int i, j, dim, subdim;
431
printf("\nMatrix::isPositiveDefinide >>> Matriz tem que ser quadrada\n");
436
for (subdim=1 ; subdim <= dim; subdim++)
438
if( Submat.Init( subdim,subdim ) == false ){
439
printf("\nMatrix::isPositiveDefinide>>>Memoria nao disponivel!\n");
443
for ( i=0; i < subdim; i++)
444
for (j = 0; j < subdim; j++)
445
Submat(i,j) = mat[i][j];
447
if (Submat.Determinant() <= 0.) {
448
printf("\nMatrix::isPositiveDefinide>>>Matriz nao e positiva definida!\n");
459
TeMatrix :: MatTransf( TeMatrix& mt )
461
TeMatrix TI; // inverse of a inferior triangular matrix
465
printf("\nMatrix::MatTransf >>> Operacao usa duas matrizes\n");
469
if( nrow <= 0 || ncol <= 0 ){
470
printf("\nMatrix::MatTransf >>> Dimensoes da matriz invalidas!\n");
475
printf("\nMatrix::MatTransf >>> Dimensoes da matriz invalidas!\n");
480
if( mat[0][0] <= 0. ){
481
printf("\nMatrix::MatTranf >>> ERROR\n");
485
if( TI.Init( dim, (double)0. ) == false ){
486
printf("\nMatrix::MatTransf >>> Memoria nao disponivel!\n");
491
//-- Calculate inferior triangular matrix by Cholesky decomposition method
492
if ((*this).CholeskyDecomp(TI) == false) {
493
printf("\nMatrix::MatTransf>>> Nao foi possivel decompor a matriz!\n");
497
//-- Calculate the inverse of Cholesky matrix
498
// if (TI.CholeskyInv(mt) != true)
499
if (!(TI.CholeskyInv(mt)))
501
printf("\nMatrix::MatTransf>>> Matriz nao inversivel!\n");
510
TeMatrix::CholeskyInv (TeMatrix& mt) const
512
if( mt.Init(nrow,(double)0.) == false ){
513
printf("\nMatrix::CholeskyInv >>> Memoria nao disponivel!\n");
518
printf("\nMatrix::CholeskyInv >>> Operacao usa duas matrizes\n");
522
printf("\nMatrix::CholeskyInv>>> Can't invert a non-square matrix");
525
// if (this->isLowerTriangle() != true) {
526
if (!(this->isLowerTriangle())) {
527
printf("\nMatrix::CholeskyInv >>> Matriz nao e triangular inferior\n");
532
for( i = 0; i < nrow; i++ ){
533
if( this->mat[i][i] == (double)0. ){
534
printf("\nMatrix::CholeskyInv >>> ERROR IV\n");
537
mt.mat[i][i] = (double)1. / this->mat[i][i];
539
for( j = i-1; j >= 0; j-- ){
541
for( k = j; k <= i-1; k++ ){
542
rf += ( this->mat[i][k] * mt.mat[k][j] );
544
mt.mat[i][j] = -rf * mt.mat[i][i];
552
TeMatrix::EigenValues( TeMatrix& mt )
554
//--- calcula os eigenvalues de uma
555
// matriz representada na forma vetorial
556
// Os auto valores sao devolvidos em ordem decrescente
557
// e ocupam as posicoes: 0, 2, 5, 9, ... .
560
printf("\nMatrix::EigenValues >>> Operacao usa duas matrizes\n");
564
double *cov = NULL, /* matriz de covariancia */
565
*e_val = NULL; /* " de auto_valores */
567
int dim = (*this).Nrow(); /* ordem da matriz*/
569
int i,j,k, /* cov[], e_val[] */
573
mq,lm, /* |3 4 5 | */
574
ll,mm, /* |6 7 8 9| */
576
im,iq,il,lq, /* (para DIM=4) */
579
double range, /* e_vec[] */
581
anorm, /* |0 4 8 12| */
582
anrmx, /* |1 5 9 13| */
583
thr, /* |2 6 10 14| */
584
x,y,z, /* |3 7 11 15| */
589
int fat = (dim*dim+dim)/2;
592
printf("\nMatrix::EigenValues >>> dimensao da matriz nula!\n");
595
if( mt.Init( dim, (double)1 ) == false ){
596
printf("\nMatrix::EigenValues >>> Memoria nao disponivel\n");
603
cov = new double[fat];
606
printf("\nMatrix::EigenValues >>> Memoria nao disponivel (COV)\n");
610
e_val = new double[fat];
612
delete []cov; //SSL0296
614
printf("\nMatrix::EigenValues >>> Memoria nao disponivel (EVAL)\n");
618
for ( i = 0; i< dim; i++)
619
for ( j = 0; j <= i; j++)
620
cov[k++] = mat[i][j];
622
for (i=0; i < ((dim*dim+dim)/2); i++) e_val[i] = cov[i];
626
for ( j = 0; j < dim; j++){
627
for (i = 0; i <= j; i++){
630
anorm = anorm + e_val[ia] * e_val[ia];
635
if (anorm <= 0) goto l5;
637
anorm = 1.414 * sqrt((double)anorm);
638
anrmx = anorm * range/fdim;
653
if ( fabs((double)(e_val[lm])) >= thr )
659
x = 0.5 * (e_val[ll] - e_val[mm]);
660
z = e_val[lm] * e_val[lm] + x*x;
661
y = - e_val[lm] / sqrt((double)(z));
668
z = sqrt( (double)(1.0-y*y) );
669
sinx = y / sqrt( (double)( 2.0*(1.0 + z) ) );
672
cosx = sqrt( (double)(1.0 - sinx2) );
680
for (i = 0; i < dim; i++)
696
x = e_val[il] * cosx - e_val[im] * sinx;
697
e_val[im] = e_val[il] * sinx + e_val[im] * cosx;
702
x = 2.0 * e_val[lm] * sincs;
703
y = e_val[ll] * cosx2 + e_val[mm] * sinx2 - x;
704
x = e_val[ll] * sinx2 + e_val[mm] * cosx2 + x;
706
e_val[lm] = (e_val[ll]-e_val[mm])*sincs+e_val[lm]*(cosx2-sinx2);
723
if (thr > anrmx) goto l1;
728
for (i = 0; i < dim; i++)
731
ll = i + (i*i + i)/2;
734
for (j = i; j < dim; j++)
737
mm = j + (j*j + j)/2;
739
if (e_val[ll] < e_val[mm])
742
e_val[ll] = e_val[mm];
748
for ( i = 0; i< dim; i++){
749
mt(i,0) = e_val[(i*(i+1))/2+i];
752
delete []cov; //SSL0296
753
delete []e_val; //SSL0296
758
//--------------------------------------------------EigenVectors
760
// Metodo adaptado a partir de uma implementacao em C
761
// utilizada no software SITIM.
764
TeMatrix::EigenVectors( TeMatrix& mt )
767
printf("\nMatrix::EigenVectors >>> Operacao usa duas matrizes\n");
771
double *cov = NULL, /* matriz de covariancia */
772
*e_val = NULL, /* " de auto_valores */
773
*e_vec = NULL; /* " de auto_vetores */
775
int dim = (*this).Nrow(); /* ordem da matriz*/
777
int i,j,ij,k, /* cov[], e_val[] */
781
mq,lm, /* |3 4 5 | */
782
ll,mm, /* |6 7 8 9| */
784
im,iq,il,lq, /* (para DIM=4) */
788
double range, /* e_vec[] */
790
anorm, /* |0 4 8 12| */
791
anrmx, /* |1 5 9 13| */
792
thr, /* |2 6 10 14| */
793
x,y,z, /* |3 7 11 15| */
799
printf("\nMatrix::EigenValues >>> dimensao da matriz nula!\n");
802
if( mt.Init( dim, (double)1 ) == false ){
803
printf("\nMatriz::EigenVectors >>> Memoria nao disponivel!\n");
807
int fat =(dim*dim+dim)/2;
812
cov = new double[fat];
813
e_vec = new double[dim*dim];
814
e_val = new double[fat];
816
if( cov == NULL || e_vec == NULL || e_val == NULL ){
817
printf("\nMatrix::EigenVectors >>> Memoria nao disponivel\n");
822
for ( i = 0; i< dim; i++)
823
for ( j = 0; j <= i; j++)
824
cov[k++] = (*this)(i,j);
826
for (i=0; i < ((dim*dim+dim)/2); i++) e_val[i] = cov[i];
829
for (i = 0; i < dim; i++)
832
for ( j = 0; j < dim; j++)
844
for ( j = 0; j < dim; j++)
846
for (i = 0; i <= j; i++)
851
anorm = anorm + e_val[ia] * e_val[ia];
856
if (anorm <= 0) goto l5;
858
anorm = 1.414 * sqrt((double)anorm);
859
anrmx = anorm * range/fdim;
874
if ( fabs((double)(e_val[lm])) >= thr )
880
x = 0.5 * (e_val[ll] - e_val[mm]);
881
z = e_val[lm] * e_val[lm] + x*x;
882
y = - e_val[lm] / sqrt((double)(z));
889
z = sqrt( (double)(1.0-y*y) );
890
sinx = y / sqrt( (double)( 2.0*(1.0 + z) ) );
893
cosx = sqrt( (double)(1.0 - sinx2) );
901
for (i = 0; i < dim; i++)
917
x = e_val[il] * cosx - e_val[im] * sinx;
918
e_val[im] = e_val[il] * sinx + e_val[im] * cosx;
923
//--- calculate eigenvectors
927
x = e_vec[ilr] * cosx - e_vec[imr] * sinx;
928
e_vec[imr] = e_vec[ilr] * sinx + e_vec[imr] * cosx;
932
x = 2.0 * e_val[lm] * sincs;
933
y = e_val[ll] * cosx2 + e_val[mm] * sinx2 - x;
934
x = e_val[ll] * sinx2 + e_val[mm] * cosx2 + x;
936
e_val[lm] = (e_val[ll]-e_val[mm])*sincs+e_val[lm]*(cosx2-sinx2);
953
if (thr > anrmx) goto l1;
958
for (i = 0; i < dim; i++)
961
ll = i + (i*i + i)/2;
964
for (j = i; j < dim; j++)
967
mm = j + (j*j + j)/2;
969
if (e_val[ll] < e_val[mm])
972
e_val[ll] = e_val[mm];
975
for (k = 0; k < dim; k++)
980
e_vec[ilr] = e_vec[imr];
988
for ( i = 0; i< dim; i++){
989
for ( j = 0; j< dim; j++)
990
mt(j,i) = e_vec[k++];
993
delete []cov; //SSL0296
994
delete []e_vec; //SSL0296
995
delete []e_val; //SSL0296
1000
//--------------------------------------------------EigenVec
1002
// Metodo desenvolvido para suporte de decisao (suporte_stubs.cpp)
1003
// Missae Yamamoto (junho/1999)
1006
TeMatrix::EigenVec( double e_vec[] )
1009
double *e_vec_aux = NULL, soma = 0.0;
1011
int dim = (*this).Nrow(); /* ordem da matriz*/
1013
TeMatrix aux1, aux2, mt;
1019
printf("\nMatrix::EigenVecVal >>> dimensao da matriz nula!\n");
1023
if( aux1.Init( dim, (double)1 ) == false )
1025
printf("\nMatrix::EigenVecVal >>> Memoria nao disponivel!\n");
1029
if( aux2.Init( dim, (double)1 ) == false )
1031
printf("\nMatrix::EigenVecVal >>> Memoria nao disponivel!\n");
1035
e_vec_aux = new double[dim];
1037
if( e_vec_aux == NULL )
1039
printf("\nMatrix::EigenVecVal >>> Memoria nao disponivel\n");
1043
for ( k = 0; k< dim; k++)
1056
for (i=0; i<dim; i++)
1058
for (j=0; j<dim; j++)
1059
e_vec[i] = e_vec[i] + mt(i,j);
1060
soma = soma + e_vec[i];
1063
for (j=0; j<dim; j++)
1064
e_vec[j] = e_vec[j] / soma;
1066
for (j=0; j<dim; j++)
1068
if ( fabs(e_vec_aux[j] - e_vec[j]) < 0.001 )
1073
e_vec_aux[j] = e_vec[j];
1082
//------------------------------------------ Print
1086
//printf("\nMATRIZ ( %d, %d ) LIXO %f **mat %p\n", nrow,ncol, lixo, mat);
1087
printf("\nMATRIZ ( %d, %d )\n\n", nrow,ncol);
1089
printf("\n>>> mat e NULL \n");
1093
for(i = 0; i < nrow; i++){
1094
for( j = 0; j < ncol;j++){
1095
printf("%10.4f ",(float)mat[i][j]);
1103
TeMatrix::CholeskyDecomp( TeMatrix& mt )
1106
//-- Verify if the matrix is simetric
1107
if ((*this).isSimetric() == false){
1108
printf("\nMatrix::CholeskyDecomp >>> Matriz nao e simetrica!\n");
1111
//-- Verify if the matrix is positive definide
1112
if ((*this).isPositiveDefinide() == false){
1113
printf("\nMatrix::CholeskyDecomp >>> Matriz nao e positiva definida!\n");
1117
printf("\nMatrix::CholeskyDecomp >>> Operacao usa duas matrizes\n");
1120
if( mat[0][0] <= 0. ){
1121
printf("\nMatrix::CholeskyDecomp >>> Posicao [0,0] e' nula\n");
1124
if( mt.Init(nrow,ncol) == false ){
1125
printf("\nMatrix::CholeskyDecomp>>>no memory \n");
1128
mt(0,0) = (double)sqrt((double)(*this)(0,0));
1130
//--- Calculate the first column of the TeMatrix mt
1133
for( i= 0; i < nrow; i++){
1134
mt(i,0) = (*this)(i,0)/mt(0,0);
1137
for( i= 1; i < nrow; i++){
1138
for( j= 1; j <= i; j++){
1139
//int m = (j*j - j)/2 + 1;
1142
//for( k = 0;k<=k2;k++)
1143
for( k = 0;k < j;k++)
1144
rf += mt(i,k) * mt(j,k);
1146
rf = (*this)(i,j) - rf;
1148
printf("\nMatrix::CholeskyDecomp:ERRO \n");
1151
mt(i,j) = (double)sqrt((double)rf);
1154
if( mt(j,j) == 0. ){
1155
printf("\nMatrix::CholeskyDecomp:ERRO \n");
1158
mt(i,j) = ((*this)(i,j)-rf)/mt (j,j );
1166
//-------------------------------------------------Inverse(SITIM)
1168
//--- Calcula a matriz inversa pelo metodo de Gauss-Jordan.
1172
TeMatrix::Inverse( TeMatrix& matinv ) const
1175
if( &matinv == this ){
1176
printf("\nMatrix::Inverse >>> Operacao usa duas matrizes\n");
1179
if ( nrow != ncol ){
1180
printf("\nMatrix::Inverse: can't invert a non-square matrix");
1184
if( matinv.Init( this->nrow, (double)1 ) == false ){
1185
printf("\nMatrix::Inverse >>> Memoria nao disponivel\n");
1189
//--- Calculo da inversa se a matriz tem dimensao unitaria
1192
if(mat[0][0] == 0.0) {
1193
printf("\noperator~: can't invert singular matrix");
1196
matinv(0,0) = 1. / mat[0][0];
1200
//--- Formacao da matriz aumentada mataum
1205
if( mataum.Init( nrow , m2 ) == false ){
1206
printf("\nInverse:no memory");
1211
for(i1 = 0 ; i1 < nrow ; i1++){
1212
for( i2 = 0 ; i2 < ncol ; i2++)
1213
mataum(i1,i2) = mat[i1][i2];
1215
for( i3 = nrow ; i3 < m2 ; i3++)
1216
mataum(i1,i3) = 0.0;
1218
mataum( i1, i1 + nrow) = 1.0;
1221
//-- Inicializa ponteiro de linhas
1223
double *maxlinha = NULL;
1225
if( ( maxlinha = new double[nrow] ) == NULL ){
1226
printf("\nMatrix::Inverse>>no memory");
1230
double sup,lcon1,amul,pivo;
1233
if( (lp = new int[nrow]) == NULL ){
1234
printf("\nMatrix::Inverse>>no memory");
1235
if( maxlinha != NULL){delete []maxlinha; maxlinha = NULL;} //SSL0296
1239
for(i1 = 0 ; i1 < nrow ; i1++)
1246
//--- Selecao do maior valor em cada linha . seu inverso e armazenado em maxlinha.
1247
for(i1 = 0 ; i1 < nrow ; i1++){
1249
for(i2 = 0 ; i2 < nrow ; i2++){
1250
lcon1 = (double)fabs(mataum(lp[i1],i2));
1251
if((lcon1 - sup ) > 0.000001 )
1255
printf("\nMatrix::Inverse>>Determinant = 0.");
1256
if( maxlinha != NULL){ delete []maxlinha; maxlinha = NULL; } //SSL0296
1257
if( lp != NULL){ delete []lp; lp = NULL; } //SSL0296
1260
maxlinha[lp[i1]] = 1.0 / sup;
1263
//--- Selecao do pivo em cada linha
1266
double supc = fabs((double)( mataum(lp[lcon],lcon) * maxlinha[lp[lcon]] ));
1267
pivo = mataum(lp[lcon],lcon);
1269
for(i1 = lcon ; i1 < nrow ; i1++){
1270
amul = mataum(lp[i1],lcon) * maxlinha[lp[i1]];
1271
if (fabs(amul) > supc ){
1272
supc = (fabs((double)amul));
1273
pivo = mataum(lp[i1],lcon);
1279
printf("\nMatrix::Inverse>>Determinant = 0.");
1280
if( maxlinha != NULL){ delete []maxlinha; maxlinha = NULL; } //SSL0296
1281
if( lp != NULL){ delete []lp; lp = NULL; } //SSL0296
1285
/* troca de linhas */
1290
//--- Divide a linha pelo pivo
1291
for(i2 = 0 ; i2 < m2 ; i2++){
1292
mataum(lp[lcon],i2) = mataum(lp[lcon],i2) / pivo ;
1295
//--- Realiza subtracoes nas linhas de forma a zerar os elementos da coluna
1296
//--- dada pelo indice lcon
1300
for(i2 = 0; i2 < m1 ; i2++){
1302
if(il >= nrow ) il = 0;
1303
double aux = - mataum(lp[il],lcon);
1304
for(i3 = lcon; i3 < m2 ; i3++)
1305
mataum(lp[il],i3) = mataum(lp[il],i3) + aux * mataum(lp[lcon],i3);
1307
mataum(lp[il],lcon) = 0.0;
1313
//--- Copia a parte extendida de mataum em matinv que passa a ser a matriz inversa
1314
for(i1 = 0 ; i1 < nrow ; i1++){
1315
for(i2 = nrow ; i2 < m2 ; i2++){
1317
matinv(i1,i3) = mataum(lp[i1],i2);
1321
if( maxlinha != NULL){
1322
delete []maxlinha; //SSL0296
1326
delete []lp; //SSL0296
1333
// Esse m�todo, n�o esta correto
1334
//------------------------------------------Inverse
1336
// 1. triangulate: *this = ~P*T
1337
// 2. when T isUpperTriangle ~T isUpperTriangle
1338
// 3. split: T = T.row(0) + subT
1340
// 5. ~T.at(0,0) = 1/T.at(0,0)
1341
// 6. sub~T = ~(subT)
1342
// 7. ~T.row(0) = [1/T.at(0,0)]&B
1343
// where T.at(0,0)*B = [t21 ... t2n]*~subT
1347
TeMatrix::InverseNIH( TeMatrix& mt ) const
1354
if ( nrow!=ncol || nrow <= 0 || ncol <= 0 ){
1355
printf("\nMatrix::Inverse >>> Matriz nao inversivel!\n");
1359
if( mt.Init( this->nrow, (double)1 ) == false ){
1360
printf("\nMatrix::Inverse >>> Memoria nao disponivel\n");
1365
if( mat[0][0] == (double)0 ){
1366
printf("\nMatrix::Inverse >>> Matriz nao inversivel!\n");
1369
mt.mat[0][0] = 1/mat[0][0];
1373
if( T.Initialized() == false ){
1374
printf("\nMatrix::Inverse >>> Memoria nao disponivel\n");
1378
// 1. triangulate: *this = ~P*T
1380
if( P.Init(nrow,ncol) == false){
1381
printf("\nMatrix::Inverse >>> Memoria nao disponivel\n");
1384
if( T.UpperTriangle( P ) == false ){
1385
printf("\nMatriz::Inverse >>> ERRO!\n");
1388
if ( T.Determinant()==0 ) {
1389
printf("\nMatrix::Inverse >>> can't invert singular matrix\n");
1393
// 2. when T isUpperTriangle ~T isUpperTriangle
1394
// 3. split: T = T.row(0) + subT
1396
if( r.Init(1,ncol-1,&(T.mat[0][1])) == false){
1397
printf("\nMatrix::Inverse* >>> Memoria nao disponivel\n");
1403
if( _subT.Initialized() == false){
1404
printf("\nMatrix::Inverse >>> Memoria nao disponivel\n");
1409
B = (-(1/T.mat[0][0])*r*_subT);
1410
if( B.Initialized() == false ){
1411
printf("\nMatrix::Inverse >>> Memoria nao disponivel\n");
1415
if( val.Init(nrow,ncol) == false){
1416
printf("\nMatrix::Inverse >>> Memoria nao disponivel\n");
1420
val.mat[0][0] = 1/T.mat[0][0];
1422
for(i=1; i<ncol; i++) val.mat[0][i]=B.mat[0][i-1];
1423
val.CoFactor(0,0,_subT);
1425
mt = val*P; // P is now the row-reduction transformation
1431
// os m�todos switchRows e combineRows ficarao comentados
1432
// pois s� sao utilizados no calculo da matriz inversa NIH,
1433
// inversaNIH, que tambem foi comentado
1435
TeMatrix::switchRows(int i,int j)
1439
if( i < 0 || j < 0 || i >= nrow || j >= ncol ){
1440
printf("\nMatrix::switchRows >>> Switching linhas invalidas\n");
1449
TeMatrix::combineRows(int i, double a, int j)
1451
if( i < 0 || j < 0 || i >= nrow || j >= ncol ){
1452
printf("\nMatrix::combineRows >>> Combining linhas invalidas\n");
1456
for(h = 0; h < ncol; h++)
1457
mat[i][h] += a * mat[j][h];
1461
//--------Esse metodo nao esta correto e por isso ficar� comentado VRMC
1462
//----------------------------------------------------
1464
TeMatrix::UpperTriangle( TeMatrix& mt )
1467
printf("\nMatrix::UpperTriangle >>> Operacao usa duas matrizes\n");
1470
if( mt.Init(nrow,(double)1) == false){
1471
printf("\nMatrix::UpperTriangle >>> Memoria nao disponivel\n");
1475
if ( this->isUpperTriangle() )
1479
for(j = 0; j < ncol; j++) {
1480
int b_row = nrow-1; // 1st non-zero entry from bottom
1481
int t_row = j; // 1st zero entry from the top
1483
//--- switch rows until all zeros are at
1484
//--- the bottom of jTH column
1486
while ( b_row>=t_row ) {
1487
while ( b_row > j && mat[b_row][j] == 0. )
1490
break; // bottom at diagonal
1491
while ( b_row >= t_row && mat[t_row][j] != 0. )
1493
if ( t_row == Nrow() )
1494
break; // top at last row
1495
if ( t_row > b_row )
1497
switchRows(b_row,t_row);
1498
mt.switchRows(b_row,t_row);
1501
//--- now b_row is last non-zero entry from the top
1502
//--- now t_row is first zero entry from the bottom
1503
//--- combine until all entries below diagonal in jTH column = 0
1508
for( i = j+1; i<= b_row; i++) {
1509
double f = -mat[i][j] / mat[j][j];
1511
mt.combineRows(i,f,j);