Commit 9dc936391813e06d7d806068caa97326a993cf03
1 parent
53893431
Implement block memory allocating scheme
Showing
12 changed files
with
431 additions
and
162 deletions
src/GMatrix.cpp
| ... | ... | @@ -33,6 +33,7 @@ GMatrix::GMatrix(void) |
| 33 | 33 | m_rows = 0; |
| 34 | 34 | m_cols = 0; |
| 35 | 35 | m_elements = 0; |
| 36 | + m_alloc = 0; | |
| 36 | 37 | m_num_rowsel = 0; |
| 37 | 38 | m_num_colsel = 0; |
| 38 | 39 | m_data = NULL; |
| ... | ... | @@ -54,6 +55,7 @@ GMatrix::GMatrix(int rows, int cols) |
| 54 | 55 | m_rows = 0; |
| 55 | 56 | m_cols = 0; |
| 56 | 57 | m_elements = 0; |
| 58 | + m_alloc = 0; | |
| 57 | 59 | m_num_rowsel = 0; |
| 58 | 60 | m_num_colsel = 0; |
| 59 | 61 | m_data = NULL; |
| ... | ... | @@ -61,7 +63,7 @@ GMatrix::GMatrix(int rows, int cols) |
| 61 | 63 | m_rowsel = NULL; |
| 62 | 64 | m_colsel = NULL; |
| 63 | 65 | |
| 64 | - // Determine number of physical elements in matrix | |
| 66 | + // Determine number of elements to store in matrix | |
| 65 | 67 | int elements = rows*cols; |
| 66 | 68 | |
| 67 | 69 | // Throw exception if requested matrix size is zero |
| ... | ... | @@ -75,10 +77,11 @@ GMatrix::GMatrix(int rows, int cols) |
| 75 | 77 | if (m_data == NULL || m_colstart == NULL) |
| 76 | 78 | throw mem_alloc("GMatrix constructor", elements); |
| 77 | 79 | |
| 78 | - // Store matrix size (logical and physical) | |
| 80 | + // Store matrix size (logical, storage, allocated) | |
| 79 | 81 | m_rows = rows; |
| 80 | 82 | m_cols = cols; |
| 81 | 83 | m_elements = elements; |
| 84 | + m_alloc = elements; | |
| 82 | 85 | |
| 83 | 86 | // Set-up column start indices |
| 84 | 87 | m_colstart[0] = 0; |
| ... | ... | @@ -106,6 +109,7 @@ GMatrix::GMatrix(const GMatrix& m) |
| 106 | 109 | m_rows = 0; |
| 107 | 110 | m_cols = 0; |
| 108 | 111 | m_elements = 0; |
| 112 | + m_alloc = 0; | |
| 109 | 113 | m_num_rowsel = 0; |
| 110 | 114 | m_num_colsel = 0; |
| 111 | 115 | m_data = NULL; |
| ... | ... | @@ -121,10 +125,10 @@ GMatrix::GMatrix(const GMatrix& m) |
| 121 | 125 | m_colstart[i] = m.m_colstart[i]; |
| 122 | 126 | |
| 123 | 127 | // Allocate memory for elements and copy them (only if there are elements) |
| 124 | - if (m.m_elements > 0) { | |
| 125 | - m_data = new double[m.m_elements]; | |
| 128 | + if (m.m_alloc > 0) { | |
| 129 | + m_data = new double[m.m_alloc]; | |
| 126 | 130 | if (m_data == NULL) |
| 127 | - throw mem_alloc("GMatrix copy constructor", m.m_elements); | |
| 131 | + throw mem_alloc("GMatrix copy constructor", m.m_alloc); | |
| 128 | 132 | for (int i = 0; i < m.m_elements; ++i) |
| 129 | 133 | m_data[i] = m.m_data[i]; |
| 130 | 134 | } |
| ... | ... | @@ -153,6 +157,7 @@ GMatrix::GMatrix(const GMatrix& m) |
| 153 | 157 | m_rows = m.m_rows; |
| 154 | 158 | m_cols = m.m_cols; |
| 155 | 159 | m_elements = m.m_elements; |
| 160 | + m_alloc = m.m_alloc; | |
| 156 | 161 | |
| 157 | 162 | // Return |
| 158 | 163 | return; |
| ... | ... | @@ -199,6 +204,7 @@ GMatrix& GMatrix::operator= (const GMatrix& m) |
| 199 | 204 | m_rows = 0; |
| 200 | 205 | m_cols = 0; |
| 201 | 206 | m_elements = 0; |
| 207 | + m_alloc = 0; | |
| 202 | 208 | m_num_rowsel = 0; |
| 203 | 209 | m_num_colsel = 0; |
| 204 | 210 | m_data = NULL; |
| ... | ... | @@ -214,10 +220,10 @@ GMatrix& GMatrix::operator= (const GMatrix& m) |
| 214 | 220 | m_colstart[i] = m.m_colstart[i]; |
| 215 | 221 | |
| 216 | 222 | // Allocate memory for elements and copy them (only if there are elements) |
| 217 | - if (m.m_elements > 0) { | |
| 218 | - m_data = new double[m.m_elements]; | |
| 223 | + if (m.m_alloc > 0) { | |
| 224 | + m_data = new double[m.m_alloc]; | |
| 219 | 225 | if (m_data == NULL) |
| 220 | - throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_elements); | |
| 226 | + throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_alloc); | |
| 221 | 227 | for (int i = 0; i < m.m_elements; ++i) |
| 222 | 228 | m_data[i] = m.m_data[i]; |
| 223 | 229 | } |
| ... | ... | @@ -246,6 +252,8 @@ GMatrix& GMatrix::operator= (const GMatrix& m) |
| 246 | 252 | m_rows = m.m_rows; |
| 247 | 253 | m_cols = m.m_cols; |
| 248 | 254 | m_elements = m.m_elements; |
| 255 | + m_alloc = m.m_alloc; | |
| 256 | + | |
| 249 | 257 | } // endif: object was not identical |
| 250 | 258 | |
| 251 | 259 | // Return this object |
| ... | ... | @@ -709,6 +717,7 @@ void GMatrix::select_non_zero(void) |
| 709 | 717 | return; |
| 710 | 718 | } |
| 711 | 719 | |
| 720 | + | |
| 712 | 721 | /*========================================================================== |
| 713 | 722 | = = |
| 714 | 723 | = GMatrix friends = |
| ... | ... | @@ -720,8 +729,24 @@ void GMatrix::select_non_zero(void) |
| 720 | 729 | ***************************************************************************/ |
| 721 | 730 | ostream& operator<< (ostream& os, const GMatrix& m) |
| 722 | 731 | { |
| 732 | + // Put header in stream | |
| 733 | + os << "=== GMatrix ===" << endl; | |
| 734 | + if (m.m_rowsel != NULL) | |
| 735 | + os << " Number of rows ............: " << m.m_rows << " (compressed " << | |
| 736 | + m.m_num_rowsel << ")" << endl; | |
| 737 | + else | |
| 738 | + os << " Number of rows ............: " << m.m_rows << endl; | |
| 739 | + if (m.m_colsel != NULL) | |
| 740 | + os << " Number of columns .........: " << m.m_cols << " (compressed " << | |
| 741 | + m.m_num_colsel << ")" << endl; | |
| 742 | + else | |
| 743 | + os << " Number of columns .........: " << m.m_cols << endl; | |
| 744 | + os << " Number of elements ........: " << m.m_elements << endl; | |
| 745 | + os << " Number of allocated cells .: " << m.m_alloc << endl; | |
| 746 | + | |
| 723 | 747 | // Loop over all matrix elements |
| 724 | 748 | for (int row = 0; row < m.m_rows; ++row) { |
| 749 | + os << " "; | |
| 725 | 750 | for (int col = 0; col < m.m_cols; ++col) { |
| 726 | 751 | os << m(row,col); |
| 727 | 752 | if (col != m.m_cols-1) |
| ... | ... | @@ -730,6 +755,20 @@ ostream& operator<< (ostream& os, const GMatrix& m) |
| 730 | 755 | if (row != m.m_rows-1) |
| 731 | 756 | os << endl; |
| 732 | 757 | } |
| 758 | + | |
| 759 | + // If there is a row compression the show scheme | |
| 760 | + if (m.m_rowsel != NULL) { | |
| 761 | + os << endl << " Row selection ..:"; | |
| 762 | + for (int row = 0; row < m.m_num_rowsel; ++row) | |
| 763 | + os << " " << m.m_rowsel[row]; | |
| 764 | + } | |
| 765 | + | |
| 766 | + // If there is a column compression the show scheme | |
| 767 | + if (m.m_colsel != NULL) { | |
| 768 | + os << endl << " Column selection:"; | |
| 769 | + for (int col = 0; col < m.m_num_colsel; ++col) | |
| 770 | + os << " " << m.m_colsel[col]; | |
| 771 | + } | |
| 733 | 772 | |
| 734 | 773 | // Return output stream |
| 735 | 774 | return os; | ... | ... |
src/GMatrix.hpp
| ... | ... | @@ -142,7 +142,8 @@ protected: |
| 142 | 142 | // Private data area |
| 143 | 143 | int m_rows; // Number of rows |
| 144 | 144 | int m_cols; // Number of columns |
| 145 | - int m_elements; // Number of (physical) elements in matrix | |
| 145 | + int m_elements; // Number of elements stored in matrix | |
| 146 | + int m_alloc; // Size of allocated matrix memory | |
| 146 | 147 | int m_num_rowsel; // Number of selected rows (for compressed decomposition) |
| 147 | 148 | int m_num_colsel; // Number of selected columns (for compressed decomposition) |
| 148 | 149 | int* m_colstart; // Column start indices (m_cols+1) | ... | ... |
src/GSparseMatrix.cpp
| ... | ... | @@ -31,7 +31,8 @@ using namespace std; |
| 31 | 31 | //#define G_DEBUG_SPARSE_PENDING // Analyse pending values |
| 32 | 32 | //#define G_DEBUG_SPARSE_INSERTION // Analyse value insertion |
| 33 | 33 | //#define G_DEBUG_SPARSE_COMPRESSION // Analyse zero row/column compression |
| 34 | - | |
| 34 | +//#define G_DEBUG_SPARSE_MALLOC // Analyse memory management | |
| 35 | +#define G_USE_MEMCPY | |
| 35 | 36 | |
| 36 | 37 | /*========================================================================== |
| 37 | 38 | = = |
| ... | ... | @@ -45,18 +46,20 @@ using namespace std; |
| 45 | 46 | GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix() |
| 46 | 47 | { |
| 47 | 48 | // Initialise private members for clean destruction |
| 48 | - m_rows = 0; | |
| 49 | - m_cols = 0; | |
| 50 | - m_elements = 0; | |
| 51 | - m_data = NULL; | |
| 52 | - m_colstart = NULL; | |
| 53 | - m_rowinx = NULL; | |
| 54 | - m_zero = 0.0; | |
| 55 | - m_fill_val = 0.0; | |
| 56 | - m_fill_row = 0; | |
| 57 | - m_fill_col = 0; | |
| 58 | - m_symbolic = NULL; | |
| 59 | - m_numeric = NULL; | |
| 49 | + m_rows = 0; | |
| 50 | + m_cols = 0; | |
| 51 | + m_elements = 0; | |
| 52 | + m_alloc = 0; | |
| 53 | + m_data = NULL; | |
| 54 | + m_colstart = NULL; | |
| 55 | + m_rowinx = NULL; | |
| 56 | + m_mem_block = G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK; | |
| 57 | + m_zero = 0.0; | |
| 58 | + m_fill_val = 0.0; | |
| 59 | + m_fill_row = 0; | |
| 60 | + m_fill_col = 0; | |
| 61 | + m_symbolic = NULL; | |
| 62 | + m_numeric = NULL; | |
| 60 | 63 | |
| 61 | 64 | // Allocate column start array. This is the only array that we can |
| 62 | 65 | // allocate at this time. The other arrays can only be allocated during |
| ... | ... | @@ -98,16 +101,17 @@ GSparseMatrix::GSparseMatrix(const GSparseMatrix& m) : GMatrix(m) |
| 98 | 101 | m_numeric = NULL; |
| 99 | 102 | |
| 100 | 103 | // Copy data members |
| 101 | - m_zero = m.m_zero; | |
| 102 | - m_fill_val = m.m_fill_val; | |
| 103 | - m_fill_row = m.m_fill_row; | |
| 104 | - m_fill_col = m.m_fill_col; | |
| 104 | + m_mem_block = m.m_mem_block; | |
| 105 | + m_zero = m.m_zero; | |
| 106 | + m_fill_val = m.m_fill_val; | |
| 107 | + m_fill_row = m.m_fill_row; | |
| 108 | + m_fill_col = m.m_fill_col; | |
| 105 | 109 | |
| 106 | 110 | // Allocate memory for row indices and copy them (only if there are elements) |
| 107 | - if (m_elements > 0) { | |
| 108 | - m_rowinx = new int[m_elements]; | |
| 111 | + if (m_alloc > 0) { | |
| 112 | + m_rowinx = new int[m_alloc]; | |
| 109 | 113 | if (m_rowinx == NULL) |
| 110 | - throw mem_alloc("GSparseMatrix copy constructor", m_elements); | |
| 114 | + throw mem_alloc("GSparseMatrix copy constructor", m_alloc); | |
| 111 | 115 | for (int i = 0; i < m_elements; ++i) |
| 112 | 116 | m_rowinx[i] = m.m_rowinx[i]; |
| 113 | 117 | } |
| ... | ... | @@ -181,17 +185,18 @@ GSparseMatrix& GSparseMatrix::operator= (const GSparseMatrix& m) |
| 181 | 185 | m_numeric = NULL; |
| 182 | 186 | |
| 183 | 187 | // Copy data members |
| 184 | - m_zero = m.m_zero; | |
| 185 | - m_fill_val = m.m_fill_val; | |
| 186 | - m_fill_row = m.m_fill_row; | |
| 187 | - m_fill_col = m.m_fill_col; | |
| 188 | + m_mem_block = m.m_mem_block; | |
| 189 | + m_zero = m.m_zero; | |
| 190 | + m_fill_val = m.m_fill_val; | |
| 191 | + m_fill_row = m.m_fill_row; | |
| 192 | + m_fill_col = m.m_fill_col; | |
| 188 | 193 | |
| 189 | 194 | // Allocate memory for row indices and copy them (only if there are elements) |
| 190 | - if (m_elements > 0) { | |
| 191 | - m_rowinx = new int[m_elements]; | |
| 195 | + if (m_alloc > 0) { | |
| 196 | + m_rowinx = new int[m_alloc]; | |
| 192 | 197 | if (m_rowinx == NULL) |
| 193 | 198 | throw mem_alloc("GSparseMatrix::operator= (const GSparseMatrix&)", |
| 194 | - m_elements); | |
| 199 | + m_alloc); | |
| 195 | 200 | for (int i = 0; i < m_elements; ++i) |
| 196 | 201 | m_rowinx[i] = m.m_rowinx[i]; |
| 197 | 202 | } |
| ... | ... | @@ -444,6 +449,23 @@ GSparseMatrix& GSparseMatrix::operator*= (const GSparseMatrix& m) |
| 444 | 449 | ==========================================================================*/ |
| 445 | 450 | |
| 446 | 451 | /*************************************************************************** |
| 452 | + * Set all matrix elements to 0 * | |
| 453 | + ***************************************************************************/ | |
| 454 | +void GSparseMatrix::clear() | |
| 455 | +{ | |
| 456 | + // Free memory | |
| 457 | + free_elements(0, m_elements); | |
| 458 | + | |
| 459 | + // Initialise column start indices to 0 | |
| 460 | + for (int col = 0; col <= m_cols; ++col) | |
| 461 | + m_colstart[col] = 0; | |
| 462 | + | |
| 463 | + // Return | |
| 464 | + return; | |
| 465 | +} | |
| 466 | + | |
| 467 | + | |
| 468 | +/*************************************************************************** | |
| 447 | 469 | * Get minimum matrix element * |
| 448 | 470 | ***************************************************************************/ |
| 449 | 471 | double GSparseMatrix::min() const |
| ... | ... | @@ -593,7 +615,6 @@ GVector GSparseMatrix::extract_col(int col) const |
| 593 | 615 | |
| 594 | 616 | // Return vector |
| 595 | 617 | return result; |
| 596 | - | |
| 597 | 618 | } |
| 598 | 619 | |
| 599 | 620 | |
| ... | ... | @@ -645,7 +666,7 @@ void GSparseMatrix::insert_col(const GVector& v, int col) |
| 645 | 666 | // Determine the number of non-zero elements in the vector |
| 646 | 667 | int n_vector = 0; |
| 647 | 668 | for (int row = 0; row < m_rows; ++row) { |
| 648 | - if (v(row) != 0.0) | |
| 669 | + if (v.m_data[row] != 0.0) | |
| 649 | 670 | n_vector++; |
| 650 | 671 | } |
| 651 | 672 | |
| ... | ... | @@ -678,8 +699,8 @@ void GSparseMatrix::insert_col(const GVector& v, int col) |
| 678 | 699 | // Insert the vector elements in the matrix |
| 679 | 700 | if (n_vector > 0) { |
| 680 | 701 | for (int row = 0, i = i_start; row < m_rows; ++row) { |
| 681 | - if (v(row) != 0.0) { | |
| 682 | - m_data[i] = v(row); | |
| 702 | + if (v.m_data[row] != 0.0) { | |
| 703 | + m_data[i] = v.m_data[row]; | |
| 683 | 704 | m_rowinx[i] = row; |
| 684 | 705 | i++; |
| 685 | 706 | } |
| ... | ... | @@ -726,11 +747,26 @@ void GSparseMatrix::add_col(const GVector& v, int col) |
| 726 | 747 | throw matrix_vector_mismatch("GSparseMatrix::add_col(const GVector&, int)", |
| 727 | 748 | v.m_num, m_rows, m_cols); |
| 728 | 749 | |
| 729 | - // Extract vector for column, add elements, and re-insert vector | |
| 730 | - GVector column = extract_col(col); | |
| 731 | - column += v; | |
| 732 | - insert_col(column, col); | |
| 750 | + // Extract vector for column, add elements, and re-insert vector (only if | |
| 751 | + // vector to insert has non-zeros) | |
| 752 | + if (v.non_zeros() > 0) { | |
| 733 | 753 | |
| 754 | + // Copy input vector | |
| 755 | + GVector column = v; | |
| 756 | + | |
| 757 | + // Add elements to vector | |
| 758 | + for (int i = m_colstart[col]; i < m_colstart[col+1]; ++i) | |
| 759 | + column.m_data[m_rowinx[i]] += m_data[i]; | |
| 760 | + | |
| 761 | + // If there is a pending element then put it in the vector | |
| 762 | + if (m_fill_val != 0.0 && m_fill_col == col) | |
| 763 | + column.m_data[m_fill_row] += m_fill_val; | |
| 764 | + | |
| 765 | + // Insert vector into matrix | |
| 766 | + insert_col(column, col); | |
| 767 | + | |
| 768 | + } | |
| 769 | + | |
| 734 | 770 | // Return |
| 735 | 771 | return; |
| 736 | 772 | } |
| ... | ... | @@ -1225,49 +1261,115 @@ void GSparseMatrix::fill_pending(void) |
| 1225 | 1261 | ***************************************************************************/ |
| 1226 | 1262 | void GSparseMatrix::alloc_elements(int start, int num) |
| 1227 | 1263 | { |
| 1264 | + // Dump header | |
| 1265 | + #if defined(G_DEBUG_SPARSE_MALLOC) | |
| 1266 | + cout << "GSparseMatrix::alloc_elements(start=" << start << ", num=" << | |
| 1267 | + num << ")" << endl; | |
| 1268 | + cout << " Before allocation : " << m_elements << " " << m_alloc << endl; | |
| 1269 | + #endif | |
| 1270 | + | |
| 1228 | 1271 | // Continue only if we need memory |
| 1229 | 1272 | if (num > 0) { |
| 1230 | 1273 | |
| 1231 | 1274 | // If start is after the end the append memory |
| 1232 | 1275 | if (start > m_elements) |
| 1233 | 1276 | start = m_elements; |
| 1277 | + | |
| 1278 | + // Determine the requested new logical size of the matrix | |
| 1279 | + int new_size = m_elements + num; | |
| 1280 | + | |
| 1281 | + // Case A: the requested memory is already available, so just move the | |
| 1282 | + // data to make space for new elements and initialise the new cells | |
| 1283 | + if (new_size <= m_alloc) { | |
| 1284 | + | |
| 1285 | + // Move up all elements after index to insert | |
| 1286 | + #if defined(G_USE_MEMCPY) | |
| 1287 | + int n_copy = m_elements - start; | |
| 1288 | + memmove(&(m_data[start+num]), &(m_data[start]), sizeof(double)*n_copy); | |
| 1289 | + memmove(&(m_rowinx[start+num]), &(m_rowinx[start]), sizeof(long)*n_copy); | |
| 1290 | + #else | |
| 1291 | + for (int i = m_elements - 1; i >= start; --i) { | |
| 1292 | + m_data[i+num] = m_data[i]; | |
| 1293 | + m_rowinx[i+num] = m_rowinx[i]; | |
| 1294 | + } | |
| 1295 | + #endif | |
| 1296 | + | |
| 1297 | + // Clear new elements (zero content for row 0) | |
| 1298 | + for (int i = start; i < start+num; ++i) { | |
| 1299 | + m_data[i] = 0.0; | |
| 1300 | + m_rowinx[i] = 0; | |
| 1301 | + } | |
| 1302 | + | |
| 1303 | + // Update element counter | |
| 1304 | + m_elements += num; | |
| 1305 | + | |
| 1306 | + } // endif: Case A: memory already existed | |
| 1307 | + | |
| 1308 | + // Case B: more memory is needed, so allocate it, copy the existing | |
| 1309 | + // content, and initialise new cells | |
| 1310 | + else { | |
| 1311 | + | |
| 1312 | + // Make sure that enough memory is allocated | |
| 1313 | + int new_propose = m_alloc + m_mem_block; | |
| 1314 | + m_alloc = (new_size > new_propose) ? new_size : new_propose; | |
| 1234 | 1315 | |
| 1235 | - // Allocate memory for new elements | |
| 1236 | - double* new_data = new double[m_elements+num]; | |
| 1237 | - int* new_rowinx = new int[m_elements+num]; | |
| 1238 | - if (new_data == NULL || new_rowinx == NULL) | |
| 1239 | - throw mem_alloc("GSparseMatrix::alloc_elements(int, int)", | |
| 1240 | - m_elements+num); | |
| 1241 | - | |
| 1242 | - // Copy all elements before index to insert | |
| 1243 | - for (int i = 0; i < start; ++i) { | |
| 1244 | - new_data[i] = m_data[i]; | |
| 1245 | - new_rowinx[i] = m_rowinx[i]; | |
| 1246 | - } | |
| 1316 | + // Allocate memory for new elements | |
| 1317 | + double* new_data = new double[m_alloc]; | |
| 1318 | + int* new_rowinx = new int[m_alloc]; | |
| 1319 | + if (new_data == NULL || new_rowinx == NULL) | |
| 1320 | + throw mem_alloc("GSparseMatrix::alloc_elements(int, int)", | |
| 1321 | + m_alloc); | |
| 1322 | + | |
| 1323 | + // Copy all elements before index to insert | |
| 1324 | + #if defined(G_USE_MEMCPY) | |
| 1325 | + int n_copy = start; | |
| 1326 | + memcpy(new_data, m_data, sizeof(double)*n_copy); | |
| 1327 | + memcpy(new_rowinx, m_rowinx, sizeof(long)*n_copy); | |
| 1328 | + #else | |
| 1329 | + for (int i = 0; i < start; ++i) { | |
| 1330 | + new_data[i] = m_data[i]; | |
| 1331 | + new_rowinx[i] = m_rowinx[i]; | |
| 1332 | + } | |
| 1333 | + #endif | |
| 1247 | 1334 | |
| 1248 | - // Clear new elements (zero content for row 0) | |
| 1249 | - for (int i = start; i < start+num; ++i) { | |
| 1250 | - new_data[i] = 0.0; | |
| 1251 | - new_rowinx[i] = 0; | |
| 1252 | - } | |
| 1335 | + // Clear new elements (zero content for row 0) | |
| 1336 | + for (int i = start; i < start+num; ++i) { | |
| 1337 | + new_data[i] = 0.0; | |
| 1338 | + new_rowinx[i] = 0; | |
| 1339 | + } | |
| 1253 | 1340 | |
| 1254 | - // Copy all elements after index to insert | |
| 1255 | - for (int i = start; i < m_elements; ++i) { | |
| 1256 | - new_data[i+num] = m_data[i]; | |
| 1257 | - new_rowinx[i+num] = m_rowinx[i]; | |
| 1258 | - } | |
| 1341 | + // Copy all elements after index to insert | |
| 1342 | + #if defined(G_USE_MEMCPY) | |
| 1343 | + n_copy = m_elements - start; | |
| 1344 | + memcpy(&(new_data[start+num]), &(m_data[start]), sizeof(double)*n_copy); | |
| 1345 | + memcpy(&(new_rowinx[start+num]), &(m_rowinx[start]), sizeof(long)*n_copy); | |
| 1346 | + #else | |
| 1347 | + for (int i = start; i < m_elements; ++i) { | |
| 1348 | + new_data[i+num] = m_data[i]; | |
| 1349 | + new_rowinx[i+num] = m_rowinx[i]; | |
| 1350 | + } | |
| 1351 | + #endif | |
| 1259 | 1352 | |
| 1260 | - // Delete old memory | |
| 1261 | - if (m_data != NULL) delete [] m_data; | |
| 1262 | - if (m_rowinx != NULL) delete [] m_rowinx; | |
| 1353 | + // Delete old memory | |
| 1354 | + if (m_data != NULL) delete [] m_data; | |
| 1355 | + if (m_rowinx != NULL) delete [] m_rowinx; | |
| 1263 | 1356 | |
| 1264 | - // Update pointers to new memory and update element counter | |
| 1265 | - m_data = new_data; | |
| 1266 | - m_rowinx = new_rowinx; | |
| 1267 | - m_elements += num; | |
| 1357 | + // Update pointers to new memory and update element counter | |
| 1358 | + m_data = new_data; | |
| 1359 | + m_rowinx = new_rowinx; | |
| 1360 | + m_elements += num; | |
| 1361 | + | |
| 1362 | + } // endelse: Case B: more memory was needed | |
| 1268 | 1363 | |
| 1269 | 1364 | } // endif: needed new memory |
| 1270 | 1365 | |
| 1366 | + // Dump new memory size | |
| 1367 | + #if defined(G_DEBUG_SPARSE_MALLOC) | |
| 1368 | + cout << " After allocation .: " << m_elements << " " << m_alloc << endl; | |
| 1369 | + #endif | |
| 1370 | + | |
| 1371 | + // Return | |
| 1372 | + return; | |
| 1271 | 1373 | } |
| 1272 | 1374 | |
| 1273 | 1375 | |
| ... | ... | @@ -1280,55 +1382,105 @@ void GSparseMatrix::alloc_elements(int start, int num) |
| 1280 | 1382 | ***************************************************************************/ |
| 1281 | 1383 | void GSparseMatrix::free_elements(int start, int num) |
| 1282 | 1384 | { |
| 1385 | + // Dump header | |
| 1386 | + #if defined(G_DEBUG_SPARSE_MALLOC) | |
| 1387 | + cout << "GSparseMatrix::free_elements(start=" << start << ", num=" << | |
| 1388 | + num << ")" << endl; | |
| 1389 | + #endif | |
| 1390 | + | |
| 1283 | 1391 | // Continue only if we need to free memory and if start is within the |
| 1284 | 1392 | // range |
| 1285 | 1393 | if (num > 0 && start < m_elements) { |
| 1286 | 1394 | |
| 1287 | - // Determine the new size of the matrix. If there are no elements then | |
| 1288 | - // simply delete all matrix elements ... | |
| 1395 | + // Determine the requested new logical size of the matrix | |
| 1289 | 1396 | int new_size = m_elements - num; |
| 1397 | + | |
| 1398 | + // If there are no elements then simply delete all matrix elements ... | |
| 1290 | 1399 | if (new_size < 1) { |
| 1291 | 1400 | if (m_data != NULL) delete [] m_data; |
| 1292 | 1401 | if (m_rowinx != NULL) delete [] m_rowinx; |
| 1293 | 1402 | m_data = NULL; |
| 1294 | 1403 | m_rowinx = NULL; |
| 1295 | 1404 | m_elements = 0; |
| 1405 | + m_alloc = 0; | |
| 1296 | 1406 | } |
| 1297 | 1407 | |
| 1298 | 1408 | // ... otherwise shrink the array |
| 1299 | 1409 | else { |
| 1300 | 1410 | |
| 1301 | - // Allocate new memory | |
| 1302 | - double* new_data = new double[new_size]; | |
| 1303 | - int* new_rowinx = new int[new_size]; | |
| 1304 | - if (new_data == NULL || new_rowinx == NULL) | |
| 1305 | - throw mem_alloc("GSparseMatrix::free_elements(int, int)", | |
| 1306 | - new_size); | |
| 1411 | + // Case A: If at least one entire memory block has been liberated then | |
| 1412 | + // physically shrink the matrix array | |
| 1413 | + if (m_alloc - new_size > m_mem_block) { | |
| 1414 | + | |
| 1415 | + // Shrink, but leave a memory block for possible future filling | |
| 1416 | + m_alloc = new_size + m_mem_block; | |
| 1417 | + | |
| 1418 | + // Allocate new memory | |
| 1419 | + double* new_data = new double[m_alloc]; | |
| 1420 | + int* new_rowinx = new int[m_alloc]; | |
| 1421 | + if (new_data == NULL || new_rowinx == NULL) | |
| 1422 | + throw mem_alloc("GSparseMatrix::free_elements(int, int)", m_alloc); | |
| 1423 | + | |
| 1424 | + // Copy all elements before the starting index | |
| 1425 | + #if defined(G_USE_MEMCPY) | |
| 1426 | + int n_copy = start; | |
| 1427 | + memcpy(new_data, m_data, sizeof(double)*n_copy); | |
| 1428 | + memcpy(new_rowinx, m_rowinx, sizeof(long)*n_copy); | |
| 1429 | + #else | |
| 1430 | + for (int i = 0; i < start; ++i) { | |
| 1431 | + new_data[i] = m_data[i]; | |
| 1432 | + new_rowinx[i] = m_rowinx[i]; | |
| 1433 | + } | |
| 1434 | + #endif | |
| 1435 | + | |
| 1436 | + // Copy all elements after the starting index | |
| 1437 | + #if defined(G_USE_MEMCPY) | |
| 1438 | + n_copy = new_size - start; | |
| 1439 | + memcpy(&(new_data[start]), &(m_data[start+num]), sizeof(double)*n_copy); | |
| 1440 | + memcpy(&(new_rowinx[start]), &(m_rowinx[start+num]), sizeof(long)*n_copy); | |
| 1441 | + #else | |
| 1442 | + for (int i = start; i < new_size; ++i) { | |
| 1443 | + new_data[i] = m_data[i+num]; | |
| 1444 | + new_rowinx[i] = m_rowinx[i+num]; | |
| 1445 | + } | |
| 1446 | + #endif | |
| 1447 | + | |
| 1448 | + // Delete old memory | |
| 1449 | + if (m_data != NULL) delete [] m_data; | |
| 1450 | + if (m_rowinx != NULL) delete [] m_rowinx; | |
| 1451 | + | |
| 1452 | + // Update pointers to new memory and update element counter | |
| 1453 | + m_data = new_data; | |
| 1454 | + m_rowinx = new_rowinx; | |
| 1455 | + m_elements = new_size; | |
| 1456 | + | |
| 1457 | + } // endif: Case A: memory shrinkage performed | |
| 1458 | + | |
| 1459 | + // Case B: we keep the memory and just move the elements | |
| 1460 | + else { | |
| 1461 | + | |
| 1462 | + // Move all elements after the starting index | |
| 1463 | + #if defined(G_USE_MEMCPY) | |
| 1464 | + int n_copy = new_size - start; | |
| 1465 | + memmove(&(m_data[start]), &(m_data[start+num]), sizeof(double)*n_copy); | |
| 1466 | + memmove(&(m_rowinx[start]), &(m_rowinx[start+num]), sizeof(long)*n_copy); | |
| 1467 | + #else | |
| 1468 | + for (int i = start; i < new_size; ++i) { | |
| 1469 | + m_data[i] = m_data[i+num]; | |
| 1470 | + m_rowinx[i] = m_rowinx[i+num]; | |
| 1471 | + } | |
| 1472 | + #endif | |
| 1307 | 1473 | |
| 1308 | - // Copy all elements before the starting index | |
| 1309 | - for (int i = 0; i < start; ++i) { | |
| 1310 | - new_data[i] = m_data[i]; | |
| 1311 | - new_rowinx[i] = m_rowinx[i]; | |
| 1312 | - } | |
| 1474 | + // Update element counter | |
| 1475 | + m_elements = new_size; | |
| 1313 | 1476 | |
| 1314 | - // Copy all elements after the starting index | |
| 1315 | - for (int i = start; i < new_size; ++i) { | |
| 1316 | - new_data[i] = m_data[i+num]; | |
| 1317 | - new_rowinx[i] = m_rowinx[i+num]; | |
| 1318 | - } | |
| 1319 | - | |
| 1320 | - // Delete old memory | |
| 1321 | - if (m_data != NULL) delete [] m_data; | |
| 1322 | - if (m_rowinx != NULL) delete [] m_rowinx; | |
| 1323 | - | |
| 1324 | - // Update pointers to new memory and update element counter | |
| 1325 | - m_data = new_data; | |
| 1326 | - m_rowinx = new_rowinx; | |
| 1327 | - m_elements = new_size; | |
| 1477 | + } // endelse: Case B | |
| 1328 | 1478 | |
| 1329 | 1479 | } // endif: array shrinkage needed |
| 1330 | 1480 | } // endif: needed new memory |
| 1331 | 1481 | |
| 1482 | + // Return | |
| 1483 | + return; | |
| 1332 | 1484 | } |
| 1333 | 1485 | |
| 1334 | 1486 | |
| ... | ... | @@ -1374,8 +1526,8 @@ void GSparseMatrix::remove_zero_row_col(void) |
| 1374 | 1526 | row_map[m_rowsel[c_row]] = c_row; |
| 1375 | 1527 | |
| 1376 | 1528 | // Initialise pointers to compressed array |
| 1377 | - double* d_data = m_data; | |
| 1378 | - int* d_rowinx = m_rowinx; | |
| 1529 | + double* d_data = m_data; | |
| 1530 | + int* d_rowinx = m_rowinx; | |
| 1379 | 1531 | |
| 1380 | 1532 | // Initialise column start of first column to zero |
| 1381 | 1533 | m_colstart[0] = 0; |
| ... | ... | @@ -1581,32 +1733,41 @@ ostream& operator<< (ostream& os, const GSparseMatrix& m) |
| 1581 | 1733 | else |
| 1582 | 1734 | os << " Number of columns .........: " << m.m_cols << endl; |
| 1583 | 1735 | os << " Number of non-zero elements: " << m.m_elements << endl; |
| 1736 | + os << " Number of allocated cells .: " << m.m_alloc << endl; | |
| 1737 | + os << " Memory block size .........: " << m.m_mem_block << endl; | |
| 1584 | 1738 | os << " Sparse matrix fill ........: " << m.fill() << endl; |
| 1585 | 1739 | |
| 1586 | - // Loop over all matrix elements and put them into the stream | |
| 1587 | - for (int row = 0; row < m.m_rows; ++row) { | |
| 1588 | - os << " "; | |
| 1589 | - for (int col = 0; col < m.m_cols; ++col) { | |
| 1590 | - os << m(row,col); | |
| 1591 | - if (col != m.m_cols-1) | |
| 1592 | - os << ", "; | |
| 1593 | - } | |
| 1594 | - if (row != m.m_rows-1) | |
| 1595 | - os << endl; | |
| 1740 | + // Loop over all matrix elements and put them into the stream (only if | |
| 1741 | + // their number is not too large) | |
| 1742 | + if (m.m_rows < 20 && m.m_cols < 20) { | |
| 1743 | + for (int row = 0; row < m.m_rows; ++row) { | |
| 1744 | + os << " "; | |
| 1745 | + for (int col = 0; col < m.m_cols; ++col) { | |
| 1746 | + os << m(row,col); | |
| 1747 | + if (col != m.m_cols-1) | |
| 1748 | + os << ", "; | |
| 1749 | + } | |
| 1750 | + if (row != m.m_rows-1) | |
| 1751 | + os << endl; | |
| 1752 | + } | |
| 1596 | 1753 | } |
| 1597 | 1754 | |
| 1598 | 1755 | // If there is a row compression the show scheme |
| 1599 | 1756 | if (m.m_rowsel != NULL) { |
| 1600 | 1757 | os << endl << " Row selection ..:"; |
| 1601 | - for (int row = 0; row < m.m_num_rowsel; ++row) | |
| 1602 | - os << " " << m.m_rowsel[row]; | |
| 1758 | + if (m.m_num_rowsel < 20) { | |
| 1759 | + for (int row = 0; row < m.m_num_rowsel; ++row) | |
| 1760 | + os << " " << m.m_rowsel[row]; | |
| 1761 | + } | |
| 1603 | 1762 | } |
| 1604 | 1763 | |
| 1605 | 1764 | // If there is a column compression the show scheme |
| 1606 | 1765 | if (m.m_colsel != NULL) { |
| 1607 | 1766 | os << endl << " Column selection:"; |
| 1608 | - for (int col = 0; col < m.m_num_colsel; ++col) | |
| 1609 | - os << " " << m.m_colsel[col]; | |
| 1767 | + if (m.m_num_colsel < 20) { | |
| 1768 | + for (int col = 0; col < m.m_num_colsel; ++col) | |
| 1769 | + os << " " << m.m_colsel[col]; | |
| 1770 | + } | |
| 1610 | 1771 | } |
| 1611 | 1772 | |
| 1612 | 1773 | // If there is a symbolic decomposition then put it also in the stream | ... | ... |
src/GSparseMatrix.hpp
| ... | ... | @@ -22,6 +22,9 @@ |
| 22 | 22 | /* __ Namespaces _________________________________________________________ */ |
| 23 | 23 | using namespace std; |
| 24 | 24 | |
| 25 | +/* __ Definitions ________________________________________________________ */ | |
| 26 | +#define G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK 512 // Default Memory block size | |
| 27 | + | |
| 25 | 28 | /* __ Enumerators ________________________________________________________ */ |
| 26 | 29 | |
| 27 | 30 | /* __ Structures _________________________________________________________ */ |
| ... | ... | @@ -94,6 +97,7 @@ public: |
| 94 | 97 | virtual GVector extract_col(int col) const; |
| 95 | 98 | virtual void insert_col(const GVector& v, int col); |
| 96 | 99 | virtual void add_col(const GVector& v, int col); |
| 100 | + virtual void set_mem_block(int block); | |
| 97 | 101 | virtual GMatrix convert_to_full() const; |
| 98 | 102 | //TBD virtual GMatrix extract_lower_triangle() const; |
| 99 | 103 | //TBD virtual GMatrix extract_upper_triangle() const; |
| ... | ... | @@ -112,13 +116,14 @@ private: |
| 112 | 116 | GSparseMatrix cs_transpose(GSparseMatrix *m, int values); |
| 113 | 117 | |
| 114 | 118 | // Private data members |
| 115 | - int* m_rowinx; // Row-indices of all elements | |
| 116 | - double m_zero; // The zero element (needed for data access) | |
| 117 | - double m_fill_val; // Element to be filled | |
| 118 | - int m_fill_row; // Row into which element needs to be filled | |
| 119 | - int m_fill_col; // Column into which element needs to be filled | |
| 120 | - void* m_symbolic; // Holds GSparseSymbolic object after decomposition | |
| 121 | - void* m_numeric; // Holds GSparseNumeric object after decomposition | |
| 119 | + int* m_rowinx; // Row-indices of all elements | |
| 120 | + int m_mem_block; // Memory block to be allocated at once | |
| 121 | + double m_zero; // The zero element (needed for data access) | |
| 122 | + double m_fill_val; // Element to be filled | |
| 123 | + int m_fill_row; // Row into which element needs to be filled | |
| 124 | + int m_fill_col; // Column into which element needs to be filled | |
| 125 | + void* m_symbolic; // Holds GSparseSymbolic object after decomposition | |
| 126 | + void* m_numeric; // Holds GSparseNumeric object after decomposition | |
| 122 | 127 | }; |
| 123 | 128 | |
| 124 | 129 | |
| ... | ... | @@ -245,14 +250,6 @@ GSparseMatrix operator/ (const GSparseMatrix& a, const double& b) |
| 245 | 250 | return result; |
| 246 | 251 | } |
| 247 | 252 | |
| 248 | -// Matrix clear function | |
| 249 | -inline | |
| 250 | -void GSparseMatrix::clear() | |
| 251 | -{ | |
| 252 | - free_elements(0, m_elements); | |
| 253 | - return; | |
| 254 | -} | |
| 255 | - | |
| 256 | 253 | // Matrix fill function |
| 257 | 254 | inline |
| 258 | 255 | double GSparseMatrix::fill() const |
| ... | ... | @@ -269,6 +266,14 @@ GSparseMatrix transpose(const GSparseMatrix& m) |
| 269 | 266 | return result; |
| 270 | 267 | } |
| 271 | 268 | |
| 269 | +// Set memory block size | |
| 270 | +inline | |
| 271 | +void GSparseMatrix::set_mem_block(int block) | |
| 272 | +{ | |
| 273 | + m_mem_block = (block > 0) ? block : 1; | |
| 274 | + return; | |
| 275 | +} | |
| 276 | + | |
| 272 | 277 | // Cholesky decomposition |
| 273 | 278 | inline |
| 274 | 279 | GSparseMatrix cholesky_decompose(const GSparseMatrix& m, int compress) | ... | ... |
src/GSymMatrix.cpp
| ... | ... | @@ -33,6 +33,7 @@ GSymMatrix::GSymMatrix(int rows, int cols) : GMatrix() |
| 33 | 33 | m_rows = 0; |
| 34 | 34 | m_cols = 0; |
| 35 | 35 | m_elements = 0; |
| 36 | + m_alloc = 0; | |
| 36 | 37 | m_num_rowsel = 0; |
| 37 | 38 | m_num_colsel = 0; |
| 38 | 39 | m_data = NULL; |
| ... | ... | @@ -63,6 +64,7 @@ GSymMatrix::GSymMatrix(int rows, int cols) : GMatrix() |
| 63 | 64 | m_rows = rows; |
| 64 | 65 | m_cols = cols; |
| 65 | 66 | m_elements = elements; |
| 67 | + m_alloc = elements; | |
| 66 | 68 | |
| 67 | 69 | // Set-up column start indices |
| 68 | 70 | m_colstart[0] = 0; | ... | ... |
src/GVector.cpp
| ... | ... | @@ -73,6 +73,25 @@ GVector::~GVector() |
| 73 | 73 | = = |
| 74 | 74 | ==========================================================================*/ |
| 75 | 75 | |
| 76 | +/*************************************************************************** | |
| 77 | + * Returns number of non-zeros in vector * | |
| 78 | + ***************************************************************************/ | |
| 79 | +int GVector::non_zeros() const | |
| 80 | +{ | |
| 81 | + // Initialise number of non-zeros | |
| 82 | + int non_zeros = 0; | |
| 83 | + | |
| 84 | + // Gather all non-zero elements | |
| 85 | + for (int i = 0; i < m_num; ++i) { | |
| 86 | + if (m_data[i] != 0.0) | |
| 87 | + non_zeros++; | |
| 88 | + } | |
| 89 | + | |
| 90 | + // Return number of non-zero elements | |
| 91 | + return non_zeros; | |
| 92 | +} | |
| 93 | + | |
| 94 | + | |
| 76 | 95 | /*========================================================================== |
| 77 | 96 | = = |
| 78 | 97 | = GVector private functions = | ... | ... |
src/GVector.hpp
| ... | ... | @@ -104,7 +104,8 @@ public: |
| 104 | 104 | GVector operator- () const; |
| 105 | 105 | |
| 106 | 106 | // Vector functions |
| 107 | - int size() const; // Return dimension of vector | |
| 107 | + int size() const; // Return dimension of vector | |
| 108 | + int non_zeros() const; // Returns # of non zeros in vector | |
| 108 | 109 | |
| 109 | 110 | // Exception: Vector index out of range |
| 110 | 111 | class out_of_range : public GException { | ... | ... |
src/Makefile.am
| 1 | 1 | ## Process this file with automake to produce Makefile.in |
| 2 | 2 | |
| 3 | -files = GException.hpp GException.cpp \ | |
| 4 | - GVector.hpp GVector.cpp \ | |
| 5 | - GMatrix.hpp GMatrix.cpp \ | |
| 6 | - GSymMatrix.hpp GSymMatrix.cpp \ | |
| 7 | - GSparseMatrix.hpp GSparseMatrix.cpp \ | |
| 8 | - GSparseSymbolic.hpp GSparseSymbolic.cpp \ | |
| 9 | - GSparseNumeric.hpp GSparseNumeric.cpp | |
| 3 | +SUBDIRS = src test | |
| 10 | 4 | |
| 11 | -lib_LTLIBRARIES = libgamma.la | |
| 12 | -libgamma_la_SOURCES = $(files) | ... | ... |
test/Makefile.am
| 1 | 1 | ## Process this file with automake to produce Makefile.in |
| 2 | 2 | |
| 3 | -check_PROGRAMS = test_GVector \ | |
| 4 | - test_GMatrix \ | |
| 5 | - test_GSymMatrix \ | |
| 6 | - test_GSparseMatrix | |
| 7 | -TESTS = test_GVector \ | |
| 8 | - test_GMatrix \ | |
| 9 | - test_GSymMatrix \ | |
| 10 | - test_GSparseMatrix | |
| 11 | -test_GVector_SOURCES = test_GVector.cpp | |
| 12 | -test_GVector_LDADD = ../src/libgamma.la | |
| 13 | -test_GMatrix_SOURCES = test_GMatrix.cpp | |
| 14 | -test_GMatrix_LDADD = ../src/libgamma.la | |
| 15 | -test_GSymMatrix_SOURCES = test_GSymMatrix.cpp | |
| 16 | -test_GSymMatrix_LDADD = ../src/libgamma.la | |
| 17 | -test_GSparseMatrix_SOURCES = test_GSparseMatrix.cpp | |
| 18 | -test_GSparseMatrix_LDADD = ../src/libgamma.la | |
| 3 | +SUBDIRS = src test | |
| 4 | + | ... | ... |
test/test_GMatrix.cpp
| ... | ... | @@ -265,6 +265,23 @@ int check_matrix_sum(const double sum) |
| 265 | 265 | |
| 266 | 266 | |
| 267 | 267 | /*************************************************************************** |
| 268 | + * Test: Output * | |
| 269 | + ***************************************************************************/ | |
| 270 | +void test_output(const GMatrix& m_test) | |
| 271 | +{ | |
| 272 | + cout << "Test GMatrix: Output test matrix: " << endl; | |
| 273 | + try { | |
| 274 | + cout << m_test << endl; | |
| 275 | + } | |
| 276 | + catch (exception &e) { | |
| 277 | + cout << endl << "TEST ERROR: Unable to output matrix." << endl; | |
| 278 | + cout << e.what() << endl; | |
| 279 | + throw; | |
| 280 | + } | |
| 281 | +} | |
| 282 | + | |
| 283 | + | |
| 284 | +/*************************************************************************** | |
| 268 | 285 | * Main test function * |
| 269 | 286 | ***************************************************************************/ |
| 270 | 287 | int main(void) |
| ... | ... | @@ -285,6 +302,9 @@ int main(void) |
| 285 | 302 | // Prepare result matrix |
| 286 | 303 | GMatrix result = m_test; |
| 287 | 304 | |
| 305 | + // Execute the tests | |
| 306 | + test_output(m_test); | |
| 307 | + | |
| 288 | 308 | // Test 1: Allocate zero matrix |
| 289 | 309 | try { |
| 290 | 310 | cout << "GMatrix - Test 1: Allocate zero matrix: "; | ... | ... |
test/test_GSparseMatrix.cpp
| ... | ... | @@ -1340,7 +1340,7 @@ void test_cholesky(void) |
| 1340 | 1340 | /*************************************************************************** |
| 1341 | 1341 | * Test: Heavy calculus * |
| 1342 | 1342 | ***************************************************************************/ |
| 1343 | -void test_heavy() | |
| 1343 | +void test_heavy(int block = 512) | |
| 1344 | 1344 | { |
| 1345 | 1345 | // Allocate some variables |
| 1346 | 1346 | clock_t t_start; |
| ... | ... | @@ -1353,14 +1353,15 @@ void test_heavy() |
| 1353 | 1353 | // |
| 1354 | 1354 | // Fill 10000 x 10000 matrix with 10000 values |
| 1355 | 1355 | number = 10000; |
| 1356 | - t_start = clock(); | |
| 1357 | 1356 | GSparseMatrix large(number,number); |
| 1357 | + large.set_mem_block(block); | |
| 1358 | + t_start = clock(); | |
| 1358 | 1359 | for (int i = 0; i < number; ++i) |
| 1359 | 1360 | large(i,i) = (i+1)*3.14; |
| 1360 | 1361 | t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC); |
| 1361 | 1362 | #if defined(DUMP_TIMING) |
| 1362 | 1363 | cout << endl << " - Fill of 10000 values needed " << t_elapse << |
| 1363 | - " sec (reference ~ 1.9 sec)"; | |
| 1364 | + " sec (reference ~ 0.2 sec)"; | |
| 1364 | 1365 | #endif |
| 1365 | 1366 | // |
| 1366 | 1367 | // Modify 10000 x 10000 matrix with 10000 (exisiting) values |
| ... | ... | @@ -1373,12 +1374,33 @@ void test_heavy() |
| 1373 | 1374 | " sec (reference ~ 0 sec)"; |
| 1374 | 1375 | #endif |
| 1375 | 1376 | // |
| 1377 | + // Insert columns into 10000 x 10000 matrix | |
| 1378 | + number = 10000; | |
| 1379 | + large.clear(); | |
| 1380 | + large.set_mem_block(block); | |
| 1381 | + GVector column(number); | |
| 1382 | + t_start = clock(); | |
| 1383 | + for (int j = 0; j < 100; ++j) { | |
| 1384 | + column = 0.0; | |
| 1385 | + for (int i = j; i < number; ++i) | |
| 1386 | + column(i) = (i+1)*3.14; | |
| 1387 | + large.add_col(column, j); | |
| 1388 | + } | |
| 1389 | + t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC); | |
| 1390 | + #if defined(DUMP_TIMING) | |
| 1391 | + cout << endl << " - 100 columns adding needed " << t_elapse << | |
| 1392 | + " sec (reference ~ 2.6 sec)"; | |
| 1393 | + #endif | |
| 1394 | + // | |
| 1376 | 1395 | // Subsequent addition and subtractions |
| 1377 | 1396 | number = 300; |
| 1378 | - t_start = clock(); | |
| 1379 | 1397 | GSparseMatrix sum(number,number); |
| 1380 | 1398 | GSparseMatrix add(number,number); |
| 1381 | 1399 | GSparseMatrix sub(number,number); |
| 1400 | + sum.set_mem_block(block); | |
| 1401 | + add.set_mem_block(block); | |
| 1402 | + sub.set_mem_block(block); | |
| 1403 | + t_start = clock(); | |
| 1382 | 1404 | for (int i = 0; i < number; ++i) { |
| 1383 | 1405 | add(i,number-i-1) = (i*i+1)*0.01; |
| 1384 | 1406 | sum += add; |
| ... | ... | @@ -1392,8 +1414,9 @@ void test_heavy() |
| 1392 | 1414 | #endif |
| 1393 | 1415 | // |
| 1394 | 1416 | // Subsequent multiplications |
| 1395 | - t_start = clock(); | |
| 1396 | 1417 | GSparseMatrix fac(number,number); |
| 1418 | + fac.set_mem_block(block); | |
| 1419 | + t_start = clock(); | |
| 1397 | 1420 | for (int i = 0; i < 1; ++i) { |
| 1398 | 1421 | for (int j = 0; j < number; ++j) |
| 1399 | 1422 | fac(j,j) = (i+1)*1.0; | ... | ... |
test/test_GSymMatrix.cpp
| ... | ... | @@ -290,6 +290,23 @@ int check_matrix_sum(const double sum) |
| 290 | 290 | |
| 291 | 291 | |
| 292 | 292 | /*************************************************************************** |
| 293 | + * Test: Output * | |
| 294 | + ***************************************************************************/ | |
| 295 | +void test_output(const GSymMatrix& m_test) | |
| 296 | +{ | |
| 297 | + cout << "Test GSymMatrix: Output test matrix: " << endl; | |
| 298 | + try { | |
| 299 | + cout << m_test << endl; | |
| 300 | + } | |
| 301 | + catch (exception &e) { | |
| 302 | + cout << endl << "TEST ERROR: Unable to output matrix." << endl; | |
| 303 | + cout << e.what() << endl; | |
| 304 | + throw; | |
| 305 | + } | |
| 306 | +} | |
| 307 | + | |
| 308 | + | |
| 309 | +/*************************************************************************** | |
| 293 | 310 | * Main test function * |
| 294 | 311 | ***************************************************************************/ |
| 295 | 312 | int main(void) |
| ... | ... | @@ -310,6 +327,9 @@ int main(void) |
| 310 | 327 | // Prepare result matrix |
| 311 | 328 | GSymMatrix result = m_test; |
| 312 | 329 | |
| 330 | + // Execute the tests | |
| 331 | + test_output(m_test); | |
| 332 | + | |
| 313 | 333 | // Test 1: Allocate zero matrix |
| 314 | 334 | try { |
| 315 | 335 | cout << "GSymMatrix - Test 1: Allocate zero matrix: "; | ... | ... |