Commit 9dc936391813e06d7d806068caa97326a993cf03

Authored by knodlseder
1 parent 53893431

Implement block memory allocating scheme

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&amp; 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&amp; GMatrix::operator= (const GMatrix&amp; 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&amp; GMatrix::operator= (const GMatrix&amp; 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&amp; GMatrix::operator= (const GMatrix&amp; 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&amp; operator&lt;&lt; (ostream&amp; os, const GMatrix&amp; 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&amp; 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&amp; GSparseMatrix::operator= (const GSparseMatrix&amp; 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&amp; GSparseMatrix::operator*= (const GSparseMatrix&amp; 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&amp; 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&amp; 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&amp; 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&amp; operator&lt;&lt; (ostream&amp; os, const GSparseMatrix&amp; 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&amp; a, const double&amp; 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&amp; 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: ";
... ...