00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00039 #ifndef __SparseMatrix_h
00040 #define __SparseMatrix_h
00041
00042
00043
00044 #include "_math.h"
00045 #include "BitArray.h"
00046 #include "CharString.h"
00047 #include "DoubleVector.h"
00048 #include "IntVector.h"
00049 #include "Ereal.h"
00050
00051
00052
00053
00054
00055 template <class T>
00056 class UTILIB_API CMSparseMatrix;
00057
00058 template <class T>
00059 class UTILIB_API RMSparseMatrix;
00060
00061
00062
00063
00064 template <class T>
00065 inline void product(NumArray<T>& res, const RMSparseMatrix<T>& mat,
00066 const NumArray<T>& vec)
00067 {
00068 res.resize(mat.get_nrows());
00069
00070 int nrows=mat.get_nrows();
00071 for (int i=0; i<nrows; i++) {
00072 res[i] = 0.0;
00073 const T* val = &(mat.matval[mat.matbeg[i]]);
00074 const int* col = &(mat.matind[mat.matbeg[i]]);
00075 for (int k=0; k<mat.matcnt[i]; k++, val++, col++) {
00076 res[i] += vec[*col] * (*val);
00077 }
00078 }
00079 }
00080
00081
00082
00083
00084 template <class T>
00085 class UTILIB_API SparseMatrix
00086 {
00087 public:
00088
00090 int get_ncols( void ) const { return ncols; }
00092 int get_nrows( void ) const { return nrows; }
00094 int get_nnzero( void ) const {return nnzeros;}
00096 IntVector& get_matbeg( void ) { return matbeg; }
00098 IntVector& get_matcnt( void ) { return matcnt; }
00100 IntVector& get_matind( void ) { return matind; }
00102 NumArray<T>& get_matval( void ) { return matval; }
00103
00105 virtual T& operator()(const int row, const int col) = 0;
00107 virtual const T& operator()(const int row, const int col) const = 0;
00108
00110 virtual int pretty_print(ostream& ostr) const;
00112 virtual int write(ostream& ostr) const = 0;
00114 virtual int read(istream& istr) = 0;
00116 int write(PackBuffer& ostr) const;
00118 int read(UnPackBuffer& istr);
00119
00121 virtual void delete_row(const int i) = 0;
00123 virtual void delete_col(const int i) = 0;
00125 virtual void delete_element(const int row, const int col) = 0;
00126
00127 protected:
00128
00130 SparseMatrix( void ) :
00131 ncols(0), nrows(0), nnzeros(0) {}
00133 virtual ~SparseMatrix() {}
00134
00136 virtual void initialize(int nrow, int ncol, int nnzero) = 0;
00138 void setup(int ncol, int nrow, int nnzero, int flag);
00140 int ncols;
00142 int nrows;
00144 int nnzeros;
00146 IntVector matbeg;
00148 IntVector matcnt;
00150 IntVector matind;
00152 NumArray<T> matval;
00153
00154 };
00155
00156
00157 template <class T>
00158 inline ostream& operator<<(ostream& output, const SparseMatrix<T>& array)
00159 { array.write(output); return(output); }
00160
00161 template <class T>
00162 inline istream& operator>>(istream& input, SparseMatrix<T>& array)
00163 { array.read(input); return(input); }
00164
00165
00167 template <class T>
00168 inline UTILIB_API PackBuffer& operator<<(PackBuffer& output, const SparseMatrix<T
00169 >& array)
00170 { array.write(output); return(output); }
00171
00173 template <class T>
00174 inline UTILIB_API UnPackBuffer& operator>>(UnPackBuffer& input, SparseMatrix<T>&
00175 array)
00176 { array.read(input); return(input); }
00177
00178
00179
00180 template <class T>
00181 class UTILIB_API CMSparseMatrix : public SparseMatrix<T>
00182 {
00183 public:
00184
00185 friend RMSparseMatrix<T>;
00186
00188 CMSparseMatrix( void ) {}
00190 CMSparseMatrix( int nrow, int ncol, int nnzero )
00191 {setup(nrow,ncol,nnzero,1);}
00193 CMSparseMatrix( CMSparseMatrix<Ereal<T> >& mat);
00195 ~CMSparseMatrix() {}
00196
00198 void initialize(int nrow, int ncol, int nnzero)
00199 {
00200 setup(nrow,ncol,nnzero,1);
00201 ncols=ncol;
00202 nrows=nrow;
00203 nnzeros=nnzero;
00204 }
00205
00207 T& operator()(const int row, const int col);
00209 const T& operator()(const int row, const int col) const;
00210
00212 int adjoinColumn(int count, int* rowPosition, T* value);
00213
00215 int write(ostream& ostr) const;
00217 int read(istream& istr);
00219 void convert(const RMSparseMatrix<T>& rowmajor);
00220
00222 void delete_row(const int i);
00224 void delete_col(const int i);
00226 void delete_element(const int row, const int col);
00227 };
00228
00229
00230
00231
00232 template <class T>
00233 class UTILIB_API RMSparseMatrix : public SparseMatrix<T>
00234 {
00235 public:
00236
00237 friend CMSparseMatrix<T>;
00238
00239 friend UTILIB_API void product<T>(NumArray<T>& res,
00240 const RMSparseMatrix<T>& mat,
00241 const NumArray<T>& vec);
00242
00244 RMSparseMatrix( void ) {}
00246 RMSparseMatrix( int nrow, int ncol, int nnzero )
00247 {setup(nrow,ncol,nnzero,0);}
00249 virtual ~RMSparseMatrix() {}
00250
00252 void initialize(int nrow, int ncol, int nnzero)
00253 {
00254 setup(nrow,ncol,nnzero,0);
00255 ncols=ncol;
00256 nrows=nrow;
00257 nnzeros=nnzero;
00258 }
00260 void resize(const int rowndx, const int rowlen);
00261
00263 T& operator()(const int row, const int col);
00265 const T& operator()(const int row, const int col) const;
00266
00268 int adjoinRow(int count, int* colPosition, T* value);
00269
00271 int write(ostream& ostr) const;
00273 int read(istream& istr);
00275 void convert(const CMSparseMatrix<T>& colmajor);
00276
00278 void delete_row(const int i);
00280 void delete_col(const int i);
00282 void delete_element(const int row, const int col);
00283 };
00284
00285
00286
00287
00288
00289
00290
00291
00292 template <class T>
00293 void SparseMatrix<T>::setup(int nrow, int ncol, int nnzero, int flag)
00294 {
00295 matind.resize(nnzero);
00296 matval.resize(nnzero);
00297 if (flag) {
00298 matbeg.resize(ncol);
00299 matcnt.resize(ncol);
00300 }
00301 else {
00302 matbeg.resize(nrow);
00303 matcnt.resize(nrow);
00304 }
00305 }
00306
00307
00308 template <class T>
00309 CMSparseMatrix<T>::CMSparseMatrix( CMSparseMatrix<Ereal<T> >& mat)
00310 {
00311 initialize(mat.get_nrows(), mat.get_ncols(), mat.get_nnzero());
00312 matind << mat.get_matind();
00313 matval << mat.get_matval();
00314 matbeg << mat.get_matbeg();
00315 matcnt << mat.get_matcnt();
00316 }
00317
00318
00319 template <class T>
00320 T& CMSparseMatrix<T>::operator()(const int row, const int col)
00321 {
00322 if ((row < 0) || (row >= nrows) || (col < 0) || (col >= ncols))
00323 ErrAbort(errmsg("CMSparseMatrix<T>::operator : iterator out of range. %dx%d not in %dx%d",row,col,nrows,ncols));
00324
00325 int pt = matbeg[col];
00326 for (int i=0; i<matcnt[col]; i++)
00327 if (matind[pt+i] == row)
00328 return matval[pt+i];
00329
00330 return matval[0];
00331 }
00332
00333
00334 template <class T>
00335 const T& CMSparseMatrix<T>::operator()(const int row, const int col) const
00336 {
00337 if ((row < 0) || (row >= nrows) || (col < 0) || (col >= ncols))
00338 ErrAbort(errmsg("CMSparseMatrix<T>::operator : iterator out of range. %dx%d not in %dx%d",row,col,nrows,ncols));
00339
00340 int pt = matbeg[col];
00341 for (int i=0; i<matcnt[col]; i++)
00342 if (matind[pt+i] == row)
00343 return matval[pt+i];
00344
00345 return matval[0];
00346 }
00347
00348
00349 template <class T>
00350 T& RMSparseMatrix<T>::operator()(const int row, const int col)
00351 {
00352 if ((row < 0) || (row >= nrows) || (col < 0) || (col >= ncols))
00353 ErrAbort(errmsg("RMSparseMatrix<T>::operator : iterator out of range. %dx%d not in %dx%d",row,col,nrows,ncols));
00354
00355 int pt = matbeg[row];
00356 for (int i=0; i<matcnt[row]; i++)
00357 if (matind[pt+i] == col)
00358 return matval[pt+i];
00359
00360 return matval[0];
00361 }
00362
00363
00364 template <class T>
00365 const T& RMSparseMatrix<T>::operator()(const int row, const int col) const
00366 {
00367 if ((row < 0) || (row >= nrows) || (col < 0) || (col >= ncols))
00368 ErrAbort(errmsg("RMSparseMatrix<T>::operator : iterator out of range. %dx%d not in %dx%d",row,col,nrows,ncols));
00369
00370 int pt = matbeg[row];
00371 for (int i=0; i<matcnt[row]; i++)
00372 if (matind[pt+i] == col)
00373 return matval[pt+i];
00374
00375 return matval[0];
00376 }
00377
00378
00379 template <class T>
00380 int SparseMatrix<T>::pretty_print(ostream& ostr) const
00381 {
00382 for (int i=0; i<nrows; i++) {
00383 for (int j=0; j<ncols; j++)
00384 ostr << operator()(i,j) << " ";
00385 ostr << endl;
00386 }
00387 return OK;
00388 }
00389
00390
00391 template <class T>
00392 int CMSparseMatrix<T>::write(ostream& ostr) const
00393 {
00394 ostr << nrows << " " << ncols << " " << nnzeros << ":" << endl;
00395 int ndx=0;
00396 for (int i=0; i<ncols; i++)
00397 for (int j=0; j<matcnt[i]; j++) {
00398 ostr << " (" << matind[ndx] << "," << i << ") " << matval[ndx] << endl;
00399 ndx++;
00400 }
00401
00402 return OK;
00403 }
00404
00405
00406 template <class T>
00407 int CMSparseMatrix<T>::read(istream& istr)
00408 {
00409 ErrAbort("CMSparseMatrix<T>::read - not implemented!");
00410 return ERR;
00411 }
00412
00413
00414 template <class T>
00415 int SparseMatrix<T>::write(PackBuffer& ostr) const
00416 {
00417 ostr << nrows << ncols << nnzeros;
00418 ostr << matbeg << matcnt << matind << matval;
00419
00420 return OK;
00421 }
00422
00423
00424 template <class T>
00425 int SparseMatrix<T>::read(UnPackBuffer& istr)
00426 {
00427 int ntmp, ctmp, ztmp;
00428 istr >> ntmp >> ctmp >> ztmp;
00429 initialize(ntmp,ctmp,ztmp);
00430 istr >> matbeg >> matcnt >> matind >> matval;
00431 return OK;
00432 }
00433
00434
00435 template <class T>
00436 int RMSparseMatrix<T>::write(ostream& ostr) const
00437 {
00438 ostr << nrows << " " << ncols << " " << nnzeros << ":" << endl;
00439 int ndx=0;
00440 for (int i=0; i<nrows; i++)
00441 for (int j=0; j<matcnt[i]; j++) {
00442 ostr << " (" << i << "," << matind[ndx] << ") " << matval[ndx] << endl;
00443 ndx++;
00444 }
00445
00446 return OK;
00447 }
00448
00449
00450 template <class T>
00451 int RMSparseMatrix<T>::read(istream& istr)
00452 {
00453 ErrAbort("RMSparseMatrix<T>::read - not implemented!");
00454 return ERR;
00455 }
00456
00457
00458
00459 template <class T>
00460 void RMSparseMatrix<T>::delete_row(const int i)
00461 {
00462
00463
00464
00465 while (matcnt[i] > 0)
00466 delete_element(i,matind[matbeg[i]]);
00467
00468
00469
00470 for (int j=i; j<(nrows-1); j++) {
00471 matbeg[j] = matbeg[j+1];
00472 matcnt[j] = matcnt[j+1];
00473 }
00474 nrows--;
00475 }
00476
00477
00478 template <class T>
00479 void RMSparseMatrix<T>::delete_col(const int i)
00480 {
00481
00482
00483
00484 for (int j=0; j<nrows; j++) {
00485
00486
00487
00488 int k=0;
00489 while (k < matcnt[j]) {
00490 if (matind[matbeg[j]+k] == i)
00491 delete_element(j,i);
00492 else {
00493 if (matind[matbeg[j]+k] > i)
00494 matind[matbeg[j]+k]--;
00495 k++;
00496 }
00497 }
00498 }
00499
00500
00501
00502 ncols--;
00503 }
00504
00505
00506 template <class T>
00507 void RMSparseMatrix<T>::delete_element(const int rowndx, const int colndx)
00508 {
00509 int k=0;
00510 for (; k<matcnt[rowndx]; k++)
00511 if (matind[matbeg[rowndx]+k] == colndx) {
00512 break;
00513 }
00514 if (k == matcnt[rowndx]) return;
00515
00516 for (int i=matbeg[rowndx]+k; i<(nnzeros-1); i++) {
00517 matind[i] = matind[i+1];
00518 matval[i] = matval[i+i];
00519 }
00520 matcnt[rowndx]--;
00521 for (int j=rowndx+1; j<nrows; j++)
00522 matbeg[j]--;
00523 nnzeros--;
00524 }
00525
00526
00527 template <class T>
00528 void RMSparseMatrix<T>::resize(const int rowndx, const int rowlen)
00529 {
00530 if (rowlen == matcnt[rowndx])
00531 return;
00532 else if (rowlen > matcnt[rowndx]) {
00533
00534 }
00535 else {
00536 int diff = rowlen-matcnt[rowndx];
00537
00538 if (diff < 0) {
00539 for (int i=matbeg[rowndx]+rowlen; i<(nnzeros+diff); i++) {
00540 matind[i] = matind[i-diff];
00541 matval[i] = matval[i-diff];
00542 }
00543 }
00544 matcnt[rowndx] += diff;
00545 for (int j=rowndx+1; j<nrows; j++)
00546 matbeg[j] += diff;
00547 nnzeros += diff;
00548 }
00549 }
00550
00551
00552 template <class T>
00553 void CMSparseMatrix<T>::convert(const RMSparseMatrix<T>& rowmajor)
00554 {
00555 matval.resize(rowmajor.nnzeros);
00556 matind.resize(rowmajor.nnzeros);
00557
00558 ncols = rowmajor.ncols;
00559 nrows = rowmajor.nrows;
00560 nnzeros = rowmajor.nnzeros;
00561 matcnt.resize(ncols);
00562 matcnt=0;
00563 matbeg.resize(ncols);
00564
00565 IntVector rowndx(nrows);
00566 rowndx=0;
00567 int prev_cndx=0;
00568
00569 for (int i=0; i<nnzeros; i++) {
00570
00571
00572
00573 int cndx=ncols;
00574 int rndx=-1;
00575
00576
00577
00578 for (int j=0; j<nrows; j++) {
00579 if ((rowmajor.matcnt[j] > 0) && (rowmajor.matcnt[j] > rowndx[j])) {
00580 if (rowmajor.matind[rowmajor.matbeg[j]+rowndx[j]] < cndx) {
00581 cndx = rowmajor.matind[rowmajor.matbeg[j]+rowndx[j]];
00582 rndx = j;
00583 }
00584 }
00585 if (cndx == prev_cndx)
00586 break;
00587 }
00588
00589
00590
00591 if (matcnt[cndx] == 0)
00592 matbeg[cndx] = i;
00593 matcnt[cndx]++;
00594 matind[i] = rndx;
00595 matval[i] = rowmajor.matval[rowmajor.matbeg[rndx]+rowndx[rndx]];
00596
00597 rowndx[rndx]++;
00598 prev_cndx=cndx;
00599 }
00600 }
00601
00602
00603 template <class T>
00604 void RMSparseMatrix<T>::convert(const CMSparseMatrix<T>& colmajor)
00605 {
00606 matval.resize(colmajor.nnzeros);
00607 matind.resize(colmajor.nnzeros);
00608
00609 ncols = colmajor.ncols;
00610 nrows = colmajor.nrows;
00611 nnzeros = colmajor.nnzeros;
00612 matcnt.resize(nrows);
00613 matcnt=0;
00614 matbeg.resize(nrows);
00615
00616 IntVector colndx(ncols);
00617 colndx=0;
00618 int prev_rndx=0;
00619
00620 for (int i=0; i<nnzeros; i++) {
00621
00622
00623
00624 int cndx=-1;
00625 int rndx=nrows;
00626 for (int j=0; j<ncols; j++) {
00627 if ((colmajor.matcnt[j] > 0) && (colmajor.matcnt[j] > colndx[j])) {
00628 if (colmajor.matind[colmajor.matbeg[j]+colndx[j]] < rndx) {
00629 cndx = j;
00630 rndx = colmajor.matind[colmajor.matbeg[j]+colndx[j]];
00631 }
00632 }
00633 if (prev_rndx == rndx)
00634 break;
00635 }
00636
00637
00638
00639
00640 if (matcnt[rndx] == 0)
00641 matbeg[rndx] = i;
00642 matcnt[rndx]++;
00643 matind[i] = cndx;
00644 matval[i] = colmajor.matval[colmajor.matbeg[cndx]+colndx[cndx]];
00645
00646 colndx[cndx]++;
00647 prev_rndx=rndx;
00648 }
00649 }
00650
00651
00652
00653 template <class T>
00654 int CMSparseMatrix<T>::adjoinColumn(int count, int* rowPosition, T* value)
00655 {
00656 if (ncols == (int) matcnt.size()) {
00657 matcnt.resize(ncols+32);
00658 matbeg.resize(ncols+32);
00659 }
00660
00661 if (nnzeros + count > (int) matval.size()) {
00662 matval.resize(nnzeros+max(count,64));
00663 matind.resize(nnzeros+max(count,64));
00664 }
00665
00666 matbeg[ncols] = nnzeros;
00667 matcnt[ncols++] = count;
00668 for (int i=0; i<count; i++) {
00669 matind[nnzeros] = rowPosition[i];
00670
00671
00672 if (rowPosition[i] >= nrows)
00673 nrows = rowPosition[i] + 1;
00674 matval[nnzeros++] = value[i];
00675 }
00676
00677 return nnzeros;
00678 }
00679
00680
00681 template <class T>
00682 void CMSparseMatrix<T>::delete_col(const int i)
00683 {
00684
00685
00686
00687 while (matcnt[i])
00688 delete_element(matind[matbeg[i]],i);
00689
00690
00691
00692 for (int j=i; j<(ncols-1); j++) {
00693 matbeg[j] = matbeg[j+1];
00694 matcnt[j] = matcnt[j+1];
00695 }
00696 ncols--;
00697 }
00698
00699
00700 template <class T>
00701 void CMSparseMatrix<T>::delete_row(const int i)
00702 {
00703
00704
00705
00706 for (int j=0; j<ncols; j++) {
00707
00708
00709
00710 int k=0;
00711 while (k < matcnt[j]) {
00712 if (matind[matbeg[j]+k] == i)
00713 delete_element(i,j);
00714 else {
00715 if (matind[matbeg[j]+k] > i)
00716 matind[matbeg[j]+k]--;
00717 k++;
00718 }
00719 }
00720 }
00721
00722
00723
00724 nrows--;
00725 }
00726
00727
00728 template <class T>
00729 void CMSparseMatrix<T>::delete_element(const int rowndx, const int colndx)
00730 {
00731 int k=0;
00732 for (; k<matcnt[colndx]; k++)
00733 if (matind[matbeg[colndx]+k] == rowndx) {
00734 break;
00735 }
00736 if (k == matcnt[colndx]) return;
00737
00738 for (int i=matbeg[colndx]+k; i<(nnzeros-1); i++) {
00739 matind[i] = matind[i+1];
00740 matval[i] = matval[i+1];
00741 }
00742 matcnt[colndx]--;
00743 for (int j=colndx+1; j<ncols; j++)
00744 matbeg[j]--;
00745 nnzeros--;
00746 }
00747
00748
00749
00750 template <class T>
00751 int RMSparseMatrix<T>::adjoinRow(int count, int* colPosition, T* value)
00752 {
00753 if (nrows == (int) matcnt.size()) {
00754 matcnt.resize(nrows+32);
00755 matbeg.resize(nrows+32);
00756 }
00757
00758 if (nnzeros + count > (int) matval.size()) {
00759 matval.resize(nnzeros+max(count,64));
00760 matind.resize(nnzeros+max(count,64));
00761 }
00762
00763 matbeg[nrows] = nnzeros;
00764 matcnt[nrows++] = count;
00765 for (int i=0; i<count; i++) {
00766 matind[nnzeros] = colPosition[i];
00767 matval[nnzeros++] = value[i];
00768 }
00769
00770 return nnzeros;
00771 }
00772
00773
00774
00775 #endif