00001 #ifndef gridripper_math_spm_h
00002 #define gridripper_math_spm_h
00003
00004 #include <cstring>
00005
00006 namespace gridripper { namespace math {
00007
00015 template <class TD>
00016 class SpM
00017 {
00018 private:
00019 int numRows;
00020 int numColumns;
00021
00022 protected:
00028 SpM(int nrows, int ncols): numRows(nrows), numColumns(ncols) {
00029 }
00030
00031 void resize(int nrows, int ncols) {
00032 numRows = nrows;
00033 numColumns = ncols;
00034 }
00035
00036 public:
00041 int getNumRows() const {
00042 return numRows;
00043 }
00044
00049 int getNumColumns() const {
00050 return numColumns;
00051 }
00052
00058 virtual int countNonzerosInRow(int row) const =0;
00059
00069 virtual void gmv(TD* y, TD alpha, const TD* x, TD beta, const TD* b)
00070 const =0;
00071
00076 virtual void toDenseMatrix(TD* mat) const =0;
00077 };
00078
00090 template <class TD, class TI>
00091 class DiaSpM: public SpM<TD>
00092 {
00093 private:
00094 TD* data;
00095 TI* offsets;
00096 int numDiagonals;
00097
00098 public:
00106 DiaSpM(int nrows, int ncols, int ndia): SpM<TD>(nrows, ncols), numDiagonals(ndia) {
00107 int n = nrows*ndia;
00108 data = new TD[n];
00109 offsets = new TI[ndia];
00110 for(int i = 0; i < n; ++i) {
00111 data[i] = 0;
00112 }
00113 for(int i = 0; i < ndia; ++i) {
00114 offsets[i] = 0;
00115 }
00116 }
00117
00118 ~DiaSpM() {
00119 delete [] data;
00120 delete [] offsets;
00121 }
00122
00129 void realloc(int nrows, int ncols, int ndia) {
00130 if(nrows == SpM<TD>::getNumRows()
00131 && ncols == SpM<TD>::getNumColumns()
00132 && numDiagonals == ndia) {
00133 return;
00134 }
00135 delete [] data;
00136 delete [] offsets;
00137 SpM<TD>::resize(nrows, ncols);
00138 numDiagonals = ndia;
00139 int n = nrows*ndia;
00140 data = new TD[n];
00141 offsets = new TI[ndia];
00142 }
00143
00149 void setOffset(int dia, TI offset) {
00150 offsets[dia] = offset;
00151 }
00152
00159 void set(int row, int dia, TD v) {
00160 data[row*numDiagonals + dia] = v;
00161 }
00162
00167 const TD* internalArray() const {
00168 return data;
00169 }
00170
00175 TD* internalArray() {
00176 return data;
00177 }
00178
00183 int arrayLength() const {
00184 return SpM<TD>::getNumRows()*numDiagonals;
00185 }
00186
00192 const TI* internalOffsetArray() const {
00193 return offsets;
00194 }
00195
00201 TI* internalOffsetArray() {
00202 return offsets;
00203 }
00204
00209 int getNumDiagonals() const {
00210 return numDiagonals;
00211 }
00212
00218 int countNonzerosInRow(int row) const {
00219 int nrows = SpM<TD>::getNumRows();
00220 int ncols = SpM<TD>::getNumColumns();
00221 int n = 0;
00222 for(int dia = 0; dia < numDiagonals; ++dia) {
00223 int offset = offsets[dia];
00224 int start = offset < 0? -offset : 0;
00225 int end = ncols - offset;
00226 if(end > nrows) {
00227 end = nrows;
00228 }
00229 if(row >= start && row < end) {
00230 ++n;
00231 }
00232 }
00233 return n;
00234 }
00235
00245 void gmv(TD* y, TD alpha, const TD* x, TD beta, const TD* b) const {
00246 int nrows = SpM<TD>::getNumRows();
00247 int ncols = SpM<TD>::getNumColumns();
00248 for(int row = 0; row < nrows; ++row) {
00249 TD v = 0;
00250 for(int dia = 0; dia < numDiagonals; ++dia) {
00251 int offset = offsets[dia];
00252 int start = offset < 0? -offset : 0;
00253 int end = ncols - offset;
00254 if(end > nrows) {
00255 end = nrows;
00256 }
00257 if(row >= start && row < end) {
00258 v += data[row*numDiagonals + dia]*x[row + offset];
00259 }
00260 }
00261 if(b != NULL) {
00262 y[row] = alpha*v + beta*b[row];
00263 } else {
00264 y[row] = alpha*v;
00265 }
00266 }
00267 }
00268
00273 void toDenseMatrix(TD* mat) const {
00274 int nrows = SpM<TD>::getNumRows();
00275 int ncols = SpM<TD>::getNumColumns();
00276 memset(mat, 0, nrows*ncols*sizeof(mat[0]));
00277 for(int dia = 0; dia < numDiagonals; ++dia) {
00278 int offset = offsets[dia];
00279 int row = offset < 0? -offset : 0;
00280 int end = ncols - offset;
00281 if(end > nrows) {
00282 end = nrows;
00283 }
00284 while(row < end) {
00285 mat[row*ncols + row + offset] = data[row*numDiagonals + dia];
00286 ++row;
00287 }
00288 }
00289 }
00290 };
00291
00303 template <class TD, class TI>
00304 class EllSpM: public SpM<TD>
00305 {
00306 private:
00307 TD* data;
00308 TI* columnIndices;
00309 int maxNonzerosPerRow;
00310
00311 public:
00319 EllSpM(int nrows, int ncols, int nonzero): SpM<TD>(nrows, ncols),
00320 maxNonzerosPerRow(nonzero) {
00321 int n = nrows*nonzero;
00322 data = new TD[n];
00323 columnIndices = new TI[n];
00324 for(int i = 0; i < n; ++i) {
00325 data[i] = 0;
00326 columnIndices[i] = -1;
00327 }
00328 }
00329
00330 ~EllSpM() {
00331 delete [] data;
00332 delete [] columnIndices;
00333 }
00334
00341 void realloc(int nrows, int ncols, int nonzero) {
00342 if(nrows == SpM<TD>::getNumRows()
00343 && ncols == SpM<TD>::getNumColumns()
00344 && maxNonzerosPerRow == nonzero) {
00345 return;
00346 }
00347 delete [] data;
00348 delete [] columnIndices;
00349 SpM<TD>::resize(nrows, ncols);
00350 maxNonzerosPerRow = nonzero;
00351 int n = nrows*nonzero;
00352 data = new TD[n];
00353 columnIndices = new TI[n];
00354 for(int i = 0; i < n; ++i) {
00355 columnIndices[i] = -1;
00356 }
00357 }
00358
00366 void set(int row, int col, TD v, int i) {
00367 int k = row*maxNonzerosPerRow + i;
00368 columnIndices[k] = col;
00369 data[k] = v;
00370 }
00371
00376 const TD* internalArray() const {
00377 return data;
00378 }
00379
00384 TD* internalArray() {
00385 return data;
00386 }
00387
00392 const TI* internalColumnIndexArray() const {
00393 return columnIndices;
00394 }
00395
00400 TI* internalColumnIndexArray() {
00401 return columnIndices;
00402 }
00403
00408 int arrayLength() const {
00409 return SpM<TD>::getNumRows()*maxNonzerosPerRow;
00410 }
00411
00417 int countNonzerosInRow(int row) const {
00418 int n = 0;
00419 int offset = row*maxNonzerosPerRow;
00420 for(int i = 0; i < maxNonzerosPerRow; ++i) {
00421 int icol = columnIndices[offset + i];
00422 if(icol < 0) {
00423 break;
00424 }
00425 ++n;
00426 }
00427 return n;
00428 }
00429
00439 void gmv(TD* y, TD alpha, const TD* x, TD beta, const TD* b) const {
00440 int nrows = SpM<TD>::getNumRows();
00441 for(int irow = 0; irow < nrows; ++irow) {
00442 TD v = 0;
00443 int offset = irow*maxNonzerosPerRow;
00444 for(int i = 0; i < maxNonzerosPerRow; ++i) {
00445 int icol = columnIndices[offset + i];
00446 if(icol < 0) {
00447 break;
00448 }
00449 v += data[offset + i]*x[icol];
00450 }
00451 if(b != NULL) {
00452 y[irow] = alpha*v + beta*b[irow];
00453 } else {
00454 y[irow] = alpha*v;
00455 }
00456 }
00457 }
00458
00463 int getMaxNonzerosPerRow() const {
00464 return maxNonzerosPerRow;
00465 }
00466
00471 void toDenseMatrix(TD* mat) const {
00472 int nrows = SpM<TD>::getNumRows();
00473 int ncols = SpM<TD>::getNumColumns();
00474 memset(mat, 0, nrows*ncols*sizeof(mat[0]));
00475 int offset = 0;
00476 for(int irow = 0; irow < nrows; ++irow) {
00477 for(int i = 0; i < maxNonzerosPerRow; ++i) {
00478 int icol = columnIndices[offset + i];
00479 if(icol < 0) {
00480 break;
00481 }
00482 mat[irow*ncols + icol] = data[offset + i];
00483 }
00484 offset += maxNonzerosPerRow;
00485 }
00486 }
00487 };
00488
00500 template <class TD, class TI>
00501 class CooSpM: public SpM<TD>
00502 {
00503 private:
00504 TD* data;
00505 TI* rowIndices;
00506 TI* columnIndices;
00507 int nonzeroCount;
00508
00509 public:
00517 CooSpM(int nrows, int ncols, int maxnonzero): SpM<TD>(nrows, ncols),
00518 nonzeroCount(maxnonzero) {
00519 data = new TD[maxnonzero];
00520 rowIndices = new TI[maxnonzero];
00521 columnIndices = new TI[maxnonzero];
00522 for(int i = 0; i < maxnonzero; ++i) {
00523 data[i] = 0;
00524 rowIndices[i] = 0;
00525 columnIndices[i] = 0;
00526 }
00527 }
00528
00529 ~CooSpM() {
00530 delete [] data;
00531 delete [] rowIndices;
00532 delete [] columnIndices;
00533 }
00534
00541 void realloc(int nrows, int ncols, int nonzero) {
00542 if(nrows == SpM<TD>::getNumRows()
00543 && ncols == SpM<TD>::getNumColumns()
00544 && nonzero == nonzeroCount) {
00545 return;
00546 }
00547 delete [] data;
00548 delete [] rowIndices;
00549 delete [] columnIndices;
00550 SpM<TD>::resize(nrows, ncols);
00551 nonzeroCount = nonzero;
00552 data = new TD[nonzero];
00553 rowIndices = new TI[nonzero];
00554 columnIndices = new TI[nonzero];
00555 }
00556
00564 void set(int row, int col, TD v, int i) {
00565 data[i] = v;
00566 rowIndices[i] = row;
00567 columnIndices[i] = col;
00568 }
00569
00574 const TD* internalArray() const {
00575 return data;
00576 }
00577
00582 TD* internalArray() {
00583 return data;
00584 }
00585
00590 int arrayLength() const {
00591 return nonzeroCount;
00592 }
00593
00598 const TI* internalRowIndexArray() const {
00599 return rowIndices;
00600 }
00601
00606 TI* internalRowIndexArray() {
00607 return rowIndices;
00608 }
00609
00614 const TI* internalColumnIndexArray() const {
00615 return columnIndices;
00616 }
00617
00622 TI* internalColumnIndexArray() {
00623 return columnIndices;
00624 }
00625
00631 int countNonzerosInRow(int row) const {
00632 int n = 0;
00633 for(int i = 0; i < nonzeroCount; ++i) {
00634 if(rowIndices[i] == row) {
00635 ++n;
00636 }
00637 }
00638 return n;
00639 }
00640
00650 void gmv(TD* y, TD alpha, const TD* x, TD beta, const TD* b) const {
00651 int nrows = SpM<TD>::getNumRows();
00652 if(b != NULL) {
00653 for(int row = 0; row < nrows; ++row) {
00654 y[row] = beta*b[row];
00655 }
00656 } else {
00657 for(int row = 0; row < nrows; ++row) {
00658 y[row] = 0;
00659 }
00660 }
00661 for(int i = 0; i < nonzeroCount; ++i) {
00662 int irow = rowIndices[i];
00663 int icol = columnIndices[i];
00664 y[irow] += alpha*data[i]*x[icol];
00665 }
00666 }
00667
00672 int getNonzeroCount() const {
00673 return nonzeroCount;
00674 }
00675
00680 void toDenseMatrix(TD* mat) const {
00681 int nrows = SpM<TD>::getNumRows();
00682 int ncols = SpM<TD>::getNumColumns();
00683 memset(mat, 0, nrows*ncols*sizeof(mat[0]));
00684 for(int i = 0; i < nonzeroCount; ++i) {
00685 int irow = rowIndices[i];
00686 int icol = columnIndices[i];
00687 mat[irow*ncols + icol] = data[i];
00688 }
00689 }
00690 };
00691
00703 template <class TD, class TI>
00704 class CsrSpM: public SpM<TD>
00705 {
00706 private:
00707 TD* data;
00708 TI* columnIndices;
00709 TI* rowPtr;
00710 int nonzeroCount;
00711
00712 public:
00720 CsrSpM(int nrows, int ncols, int nonzero): SpM<TD>(nrows, ncols),
00721 nonzeroCount(nonzero) {
00722 data = new TD[nonzero];
00723 columnIndices = new TI[nonzero];
00724 rowPtr = new TI[nrows + 1];
00725 for(int i = 0; i < nonzero; ++i) {
00726 data[i] = 0;
00727 columnIndices[i] = 0;
00728 }
00729 for(int i = 0; i <= nrows; ++i) {
00730 rowPtr[i] = 0;
00731 }
00732 }
00733
00734 ~CsrSpM() {
00735 delete [] data;
00736 delete [] columnIndices;
00737 delete [] rowPtr;
00738 }
00739
00746 void realloc(int nrows, int ncols, int nonzero) {
00747 if(nrows == SpM<TD>::getNumRows()
00748 && ncols == SpM<TD>::getNumColumns()
00749 && nonzero == nonzeroCount) {
00750 return;
00751 }
00752 delete [] data;
00753 delete [] columnIndices;
00754 delete [] rowPtr;
00755 SpM<TD>::resize(nrows, ncols);
00756 nonzeroCount = nonzero;
00757 data = new TD[nonzero];
00758 columnIndices = new TI[nonzero];
00759 rowPtr = new TI[nrows + 1];
00760 }
00761
00767 void setRowPtr(int row, TI p) {
00768 rowPtr[row] = p;
00769 }
00770
00778 void set(int row, int col, TD v, int i) {
00779 data[i] = v;
00780 columnIndices[i] = col;
00781 }
00782
00787 const TD* internalArray() const {
00788 return data;
00789 }
00790
00795 TD* internalArray() {
00796 return data;
00797 }
00798
00803 int arrayLength() const {
00804 return nonzeroCount;
00805 }
00806
00811 const TI* internalRowPtrArray() const {
00812 return rowPtr;
00813 }
00814
00819 TI* internalRowPtrArray() {
00820 return rowPtr;
00821 }
00822
00827 const TI* internalColumnIndexArray() const {
00828 return columnIndices;
00829 }
00830
00835 TI* internalColumnIndexArray() {
00836 return columnIndices;
00837 }
00838
00844 int countNonzerosInRow(int row) const {
00845 return rowPtr[row + 1] - rowPtr[row];
00846 }
00847
00857 void gmv(TD* y, TD alpha, const TD* x, TD beta, const TD* b) const {
00858 int nrows = SpM<TD>::getNumRows();
00859 if(b != NULL) {
00860 for(int row = 0; row < nrows; ++row) {
00861 y[row] = beta*b[row];
00862 }
00863 } else {
00864 for(int row = 0; row < nrows; ++row) {
00865 y[row] = 0;
00866 }
00867 }
00868 for(int irow = 0; irow < nrows; ++irow) {
00869 int start = rowPtr[irow];
00870 int end = rowPtr[irow + 1];
00871 for(int i = start; i < end; ++i) {
00872 y[irow] += alpha*data[i]*x[columnIndices[i]];
00873 }
00874 }
00875 }
00876
00881 int getNonzeroCount() const {
00882 return nonzeroCount;
00883 }
00884
00889 void toDenseMatrix(TD* mat) const {
00890 int nrows = SpM<TD>::getNumRows();
00891 int ncols = SpM<TD>::getNumColumns();
00892 memset(mat, 0, nrows*ncols*sizeof(mat[0]));
00893 for(int irow = 0; irow < nrows; ++irow) {
00894 int p = rowPtr[irow];
00895 int end = rowPtr[irow + 1];
00896 while(p < end) {
00897 mat[irow*ncols + columnIndices[p]] = data[p];
00898 ++p;
00899 }
00900 }
00901 }
00902 };
00903
00904 } }
00905
00906 #endif