Commit 150a17e86e4433e8cdbc4614c51a2e754b450673

Authored by knodlseder
1 parent 14f661df

start conform to coding conventions

Showing 1 changed file with 670 additions and 688 deletions
src/linalg/GSparseMatrix.cpp
1 1 /***************************************************************************
2 2 * GSparseMatrix.cpp - sparse matrix class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2006-2009 by Jurgen Knodlseder *
  4 + * copyright (C) 2006-2010 by Jurgen Knodlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software; you can redistribute it and/or modify *
... ... @@ -18,42 +18,41 @@
18 18 * Column 'col' covers therefore [m_colstart[j], ..., m_colstart[j+1]-1] *
19 19 * Note that 'm_colstart' has m_cols+1 elements. *
20 20 ***************************************************************************/
  21 +/**
  22 + * @file GSparseMatrix.cpp
  23 + * @brief GSparseMatrix class implementation
  24 + * @author J. Knodlseder
  25 + */
21 26  
22 27 /* __ Includes ___________________________________________________________ */
23   -#include "GException.hpp"
24 28 #include "GVector.hpp"
25   -#include "GMatrix.hpp"
26   -#include "GSymMatrix.hpp"
27 29 #include "GSparseMatrix.hpp"
28 30 #include "GSparseSymbolic.hpp"
29 31 #include "GSparseNumeric.hpp"
30 32  
31   -/* __ Namespaces _________________________________________________________ */
32   -using namespace std;
33   -
34 33 /* __ Method name definitions ____________________________________________ */
35   -#define G_OP_MUL_VEC "GSparseMatrix::operator* (const GVector&) const"
36   -#define G_OP_ADD "GSparseMatrix::operator+= (const GSparseMatrix&)"
37   -#define G_OP_SUB "GSparseMatrix::operator-= (const GSparseMatrix&)"
38   -#define G_OP_MAT_MUL "GSparseMatrix::operator*= (const GSparseMatrix&)"
39   -#define G_ADD_COL "GSparseMatrix::add_col(const GVector&, int)"
40   -#define G_ADD_COL2 "GSparseMatrix::add_col(const double*, const int*, int, int)"
41   -#define G_CHOL_DECOMP "GSparseMatrix::cholesky_decompose(int)"
42   -#define G_CHOL_SOLVE "GSparseMatrix::cholesky_solver(const GVector&, int)"
43   -#define G_EXTRACT_ROW "GSparseMatrix::extract_row(int) const"
44   -#define G_EXTRACT_COL "GSparseMatrix::extract_col(int) const"
45   -#define G_INSERT_COL "GSparseMatrix::insert_col(const GVector&, int)"
46   -#define G_INSERT_COL2 "GSparseMatrix::insert_col(const double*, const int*, int, int)"
47   -#define G_STACK_INIT "GSparseMatrix::stack_init(int, int)"
48   -#define G_STACK_PUSH "GSparseMatrix::stack_push_column(const double*, const int*, int, int)"
49   -#define G_STACK_FLUSH "GSparseMatrix::stack_flush()"
50   -#define G_CONSTRUCTOR "GSparseMatrix::constructor(int, int, int)"
51   -#define G_COPY_MEMBERS "GSparseMatrix::copy_members(const GSparseMatrix&)"
52   -#define G_ALLOC "GSparseMatrix::alloc_elements(int, int)"
53   -#define G_FREE "GSparseMatrix::free_elements(int, int)"
54   -#define G_REMOVE_ZERO "GSparseMatrix::remove_zero_row_col()"
55   -#define G_SYMPERM "cs_symperm(GSparseMatrix*, const int*, int)"
56   -#define G_TRANSPOSE "cs_transpose(GSparseMatrix*, int)"
  34 +#define G_OP_MUL_VEC "GSparseMatrix::operator* (GVector)"
  35 +#define G_OP_ADD "GSparseMatrix::operator+= (GSparseMatrix)"
  36 +#define G_OP_SUB "GSparseMatrix::operator-= (GSparseMatrix)"
  37 +#define G_OP_MAT_MUL "GSparseMatrix::operator*= (GSparseMatrix)"
  38 +#define G_ADD_COL "GSparseMatrix::add_col(GVector,int)"
  39 +#define G_ADD_COL2 "GSparseMatrix::add_col(double*,int*int,int)"
  40 +#define G_CHOL_DECOMP "GSparseMatrix::cholesky_decompose(int)"
  41 +#define G_CHOL_SOLVE "GSparseMatrix::cholesky_solver(GVector,int)"
  42 +#define G_EXTRACT_ROW "GSparseMatrix::extract_row(int)"
  43 +#define G_EXTRACT_COL "GSparseMatrix::extract_col(int)"
  44 +#define G_INSERT_COL "GSparseMatrix::insert_col(GVector,int)"
  45 +#define G_INSERT_COL2 "GSparseMatrix::insert_col(double*,int*,int,int)"
  46 +#define G_STACK_INIT "GSparseMatrix::stack_init(int,int)"
  47 +#define G_STACK_PUSH "GSparseMatrix::stack_push_column(double*,int*,int,int)"
  48 +#define G_STACK_FLUSH "GSparseMatrix::stack_flush(void)"
  49 +#define G_CONSTRUCTOR "GSparseMatrix::constructor(int,int,int)"
  50 +#define G_COPY_MEMBERS "GSparseMatrix::copy_members(GSparseMatrix)"
  51 +#define G_ALLOC "GSparseMatrix::alloc_elements(int,int)"
  52 +#define G_FREE "GSparseMatrix::free_elements(int,int)"
  53 +#define G_REMOVE_ZERO "GSparseMatrix::remove_zero_row_col(void)"
  54 +#define G_SYMPERM "cs_symperm(GSparseMatrix*,int*,int)"
  55 +#define G_TRANSPOSE "cs_transpose(GSparseMatrix*,int)"
57 56  
58 57 /* __ Macros _____________________________________________________________ */
59 58 #define G_MIN(a,b) (((a) < (b)) ? (a) : (b))
... ... @@ -80,126 +79,62 @@ using namespace std;
80 79 = =
81 80 ==========================================================================*/
82 81  
83   -/***************************************************************************
84   - * Constructor *
85   - * ----------------------------------------------------------------------- *
86   - * First calls the void base class constructor that initialises all base *
87   - * class members, then call the GSparseMatrix initialisation method and *
88   - * finally construct the object. *
  82 +/***********************************************************************//**
  83 + * @brief Matrix constructor
  84 + *
  85 + * @param[in] rows Number of rows in matrix.
  86 + * @param[in] cols Number of columns in matrix.
  87 + * @param[in] elements Number of elements for which memory should be allocated.
  88 + *
  89 + * First calls the void base class constructor that initialises all base
  90 + * class members, then call the GSparseMatrix initialisation method and
  91 + * finally construct the object.
89 92 ***************************************************************************/
90 93 GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrixBase()
91 94 {
92   - // Initialise private members for clean destruction
93   - init_members();
  95 + // Initialise private members for clean destruction
  96 + init_members();
94 97  
95   - // Construct sparse matrix
96   - constructor(rows, cols, elements);
  98 + // Construct sparse matrix
  99 + constructor(rows, cols, elements);
97 100  
98   - // Return
99   - return;
  101 + // Return
  102 + return;
100 103 }
101 104  
102 105  
103   -/***************************************************************************
104   - * Copy constructor *
105   - * ----------------------------------------------------------------------- *
106   - * First calls the void base class copy constructor that copys all base *
107   - * class members, then call the GSparseMatrix member copy method. *
108   - * NOTE: The copy constructor does NOT fill a pending element. *
  106 +/***********************************************************************//**
  107 + * @brief Copy constructor
  108 + *
  109 + * @param[in] m Matrix from which class should be instantiated.
  110 + *
  111 + * First calls the void base class copy constructor that copys all base
  112 + * class members, then call the GSparseMatrix member copy method.
  113 + * NOTE: The copy constructor does NOT fill a pending element.
109 114 ***************************************************************************/
110 115 GSparseMatrix::GSparseMatrix(const GSparseMatrix& m) : GMatrixBase(m)
111 116 {
112   - // Initialise private members for clean destruction
113   - init_members();
  117 + // Initialise private members for clean destruction
  118 + init_members();
114 119  
115   - // Copy members
116   - copy_members(m);
  120 + // Copy members
  121 + copy_members(m);
117 122  
118   - // Return
119   - return;
  123 + // Return
  124 + return;
120 125 }
121 126  
122 127  
123   -/***************************************************************************
124   - * GMatrix -> GSparseMatrix storage class conversion *
125   - * ----------------------------------------------------------------------- *
126   - * First calls the void base class constructor that initialises all base *
127   - * class members, then call the GSparseMatrix initialisation method and *
128   - * finally construct the object and fill it with the GMatrix data. *
  128 +/***********************************************************************//**
  129 + * @brief Destructor
129 130 ***************************************************************************/
130   -/*
131   -GSparseMatrix::GSparseMatrix(const GMatrix& m) : GMatrixBase()
132   -{
133   - // Initialise private members for clean destruction
134   - init_members();
135   -
136   - // Construct sparse matrix
137   - constructor(m.rows(), m.cols());
138   -
139   - // Use a fill-stack for better performance
140   - stack_init(m_cols, G_SPARSE_MATRIX_DEFAULT_STACK_ENTRIES);
141   -
142   - // Loop over all columns
143   - GVector column(m_cols);
144   - for (int col = 0; col < m_cols; ++col) {
145   - column = m.extract_col(col);
146   - insert_col(column, col);
147   - }
148   -
149   - // Destroy fill stack
150   - stack_destroy();
151   -
152   - // Return result
153   - return;
154   -}
155   -*/
156   -
157   -/***************************************************************************
158   - * GSymMatrix -> GSparseMatrix storage class conversion *
159   - * ----------------------------------------------------------------------- *
160   - * First calls the void base class constructor that initialises all base *
161   - * class members, then call the GSparseMatrix initialisation method and *
162   - * finally construct the object and fill it with the GSymMatrix data. *
163   - ***************************************************************************/
164   -/*
165   -GSparseMatrix::GSparseMatrix(const GSymMatrix& m) : GMatrixBase()
166   -{
167   - // Initialise private members for clean destruction
168   - init_members();
169   -
170   - // Construct sparse matrix
171   - constructor(m.rows(), m.cols());
172   -
173   - // Use a fill-stack for better performance
174   - stack_init(m_cols, G_SPARSE_MATRIX_DEFAULT_STACK_ENTRIES);
175   -
176   - // Loop over all columns
177   - GVector column(m_cols);
178   - for (int col = 0; col < m_cols; ++col) {
179   - column = m.extract_col(col);
180   - insert_col(column, col);
181   - }
182   -
183   - // Destroy fill stack
184   - stack_destroy();
185   -
186   - // Return result
187   - return;
188   -}
189   -*/
190   -
191   -/***************************************************************************
192   - * Destructor *
193   - * ----------------------------------------------------------------------- *
194   - * First destroys class members, then destroy base class members. *
195   - ***************************************************************************/
196   -GSparseMatrix::~GSparseMatrix()
  131 +GSparseMatrix::~GSparseMatrix(void)
197 132 {
198   - // Free members
199   - free_members();
  133 + // Free members
  134 + free_members();
200 135  
201   - // Return
202   - return;
  136 + // Return
  137 + return;
203 138 }
204 139  
205 140  
... ... @@ -209,237 +144,255 @@ GSparseMatrix::~GSparseMatrix()
209 144 = =
210 145 ==========================================================================*/
211 146  
212   -/***************************************************************************
213   - * Assignment operator *
214   - * ----------------------------------------------------------------------- *
  147 +/***********************************************************************//**
  148 + * @brief Assignment operator
  149 + *
  150 + * @param[in] m GSparseMatrix instance to be assigned
215 151 ***************************************************************************/
216 152 GSparseMatrix& GSparseMatrix::operator= (const GSparseMatrix& m)
217 153 {
218   - // Execute only if object is not identical
219   - if (this != &m) {
  154 + // Execute only if object is not identical
  155 + if (this != &m) {
220 156  
221   - // Copy base class members
222   - this->GMatrixBase::operator=(m);
  157 + // Copy base class members
  158 + this->GMatrixBase::operator=(m);
223 159  
224   - // Free members
225   - free_members();
  160 + // Free members
  161 + free_members();
226 162  
227   - // Initialise private members for clean destruction
228   - init_members();
  163 + // Initialise private members for clean destruction
  164 + init_members();
229 165  
230   - // Copy members
231   - copy_members(m);
  166 + // Copy members
  167 + copy_members(m);
232 168  
233   - } // endif: object was not identical
  169 + } // endif: object was not identical
234 170  
235   - // Return
236   - return *this;
  171 + // Return
  172 + return *this;
237 173 }
238 174  
239 175  
240   -/***************************************************************************
241   - * Vector multiplication *
242   - * ----------------------------------------------------------------------- *
243   - * Performs sparse matrix*vector multiplication including an eventually *
244   - * pending fill. *
  176 +/***********************************************************************//**
  177 + * @brief Vector multiplication
  178 + *
  179 + * @param[in] v GVector with which matrix is to be multiplied
  180 + *
  181 + * Performs sparse matrix*vector multiplication including any pending fill.
245 182 ***************************************************************************/
246 183 GVector GSparseMatrix::operator* (const GVector& v) const
247 184 {
248   - // Raise an exception if the matrix and vector dimensions are not compatible
249   - if (m_cols != v.m_num)
250   - throw GException::matrix_vector_mismatch(G_OP_MUL_VEC, v.m_num, m_rows, m_cols);
251   -
252   - // Initialise result vector
253   - GVector result(m_rows);
254   -
255   - // Multiply only if there are elements in matrix
256   - if (m_elements > 0) {
257   -
258   - // Perform vector multiplication
259   - for (int col = 0; col < m_cols; ++col) {
260   - int i_start = m_colstart[col];
261   - int i_stop = m_colstart[col+1];
262   - double* ptr_data = m_data + i_start;
263   - int* ptr_rowinx = m_rowinx + i_start;
264   - for (int i = i_start; i < i_stop; ++i)
265   - result(*ptr_rowinx++) += *ptr_data++ * v(col);
266   - }
  185 + // Raise an exception if the matrix and vector dimensions are not compatible
  186 + if (m_cols != v.m_num)
  187 + throw GException::matrix_vector_mismatch(G_OP_MUL_VEC, v.m_num,
  188 + m_rows, m_cols);
  189 +
  190 + // Initialise result vector
  191 + GVector result(m_rows);
  192 +
  193 + // Multiply only if there are elements in matrix
  194 + if (m_elements > 0) {
  195 +
  196 + // Perform vector multiplication
  197 + for (int col = 0; col < m_cols; ++col) {
  198 + int i_start = m_colstart[col];
  199 + int i_stop = m_colstart[col+1];
  200 + double* ptr_data = m_data + i_start;
  201 + int* ptr_rowinx = m_rowinx + i_start;
  202 + for (int i = i_start; i < i_stop; ++i)
  203 + result(*ptr_rowinx++) += *ptr_data++ * v(col);
  204 + }
267 205  
268   - // If fill is pending then add-in also this element into the product
269   - if (m_fill_val != 0.0) {
270   - result(m_fill_row) += m_fill_val * v(m_fill_col);
271   - #if defined(G_DEBUG_SPARSE_PENDING)
272   - cout << G_OP_MUL_VEC << ": pending value " << m_fill_val <<
273   - " for location (" << m_fill_row << "," << m_fill_col <<
274   - ") has been used." << endl;
275   - #endif
276   - }
  206 + // If fill is pending then add-in also this element into the product
  207 + if (m_fill_val != 0.0) {
  208 + result(m_fill_row) += m_fill_val * v(m_fill_col);
  209 + #if defined(G_DEBUG_SPARSE_PENDING)
  210 + std::cout << G_OP_MUL_VEC << ": pending value " << m_fill_val
  211 + << " for location (" << m_fill_row << "," << m_fill_col
  212 + << ") has been used." << std::endl;
  213 + #endif
  214 + }
277 215  
278   - } // endif: there were elements in matrix
  216 + } // endif: there were elements in matrix
279 217  
280   - // Return result
281   - return result;
  218 + // Return result
  219 + return result;
282 220 }
283 221  
284 222  
285   -/***************************************************************************
286   - * Equalty operator *
287   - * ----------------------------------------------------------------------- *
288   - * Two matrixes are considered equal if they have the same dimensions and *
289   - * identicial elements. *
290   - * !!! NOT YET IN NATIVE CODING !!! *
  223 +/***********************************************************************//**
  224 + * @brief Equalty operator
  225 + *
  226 + * @param[in] m Matrix to compare with.
  227 + *
  228 + * Two matrixes are considered equal if they have the same dimensions and
  229 + * identicial elements. The return value is 1 if the matrices are identical,
  230 + * 0 otherwise.
  231 + * TODO: Implement native sparse code
291 232 ***************************************************************************/
292 233 int GSparseMatrix::operator== (const GSparseMatrix &m) const
293 234 {
294   - // Initalise the result to 'equal matrices'
295   - int result = 1;
296   -
297   - // Perform comparison (only if matrix dimensions are identical)
298   - if (m_rows == m.m_rows && m_cols == m.m_cols) {
299   -
300   - // Loop over all matrix elements
301   - for (int row = 0; row < m_rows; ++row) {
302   - for (int col = 0; col < m_cols; ++col) {
303   - if ((*this)(row,col) != m(row,col)) {
304   - result = 0;
305   - break;
  235 + // Initalise the result to 'equal matrices'
  236 + int result = 1;
  237 +
  238 + // Perform comparison (only if matrix dimensions are identical)
  239 + if (m_rows == m.m_rows && m_cols == m.m_cols) {
  240 +
  241 + // Loop over all matrix elements
  242 + for (int row = 0; row < m_rows; ++row) {
  243 + for (int col = 0; col < m_cols; ++col) {
  244 + if ((*this)(row,col) != m(row,col)) {
  245 + result = 0;
  246 + break;
  247 + }
  248 + }
  249 + if (!result)
  250 + break;
306 251 }
307   - }
308   - if (!result)
309   - break;
310 252 }
311   - }
312   - else
313   - result = 0;
  253 + else
  254 + result = 0;
314 255  
315   - // Return result
316   - return result;
  256 + // Return result
  257 + return result;
317 258 }
318 259  
319 260  
320   -/***************************************************************************
321   - * Equalty operator *
322   - * ----------------------------------------------------------------------- *
323   - * Two matrixes are considered equal if they have the same dimensions and *
324   - * identicial elements. *
325   - * !!! NOT YET IN NATIVE CODING !!! *
  261 +/***********************************************************************//**
  262 + * @brief Unequalty operator
  263 + *
  264 + * @param[in] m Matrix to compare with.
  265 + *
  266 + * Two matrixes are considered unequal if they have different dimensions or
  267 + * differing elements. The return value is 1 if the matrices are not
  268 + * identical and 0 if they are identical.
  269 + * TODO: Implement native sparse code
326 270 ***************************************************************************/
327 271 int GSparseMatrix::operator!= (const GSparseMatrix &m) const
328 272 {
329   - // Initalise the result to 'equal matrices'
330   - int result = 0;
331   -
332   - // Perform comparison (only if matrix dimensions are identical)
333   - if (m_rows == m.m_rows && m_cols == m.m_cols) {
334   -
335   - // Loop over all matrix elements
336   - for (int row = 0; row < m_rows; ++row) {
337   - for (int col = 0; col < m_cols; ++col) {
338   - if ((*this)(row,col) != m(row,col)) {
339   - result = 1;
340   - break;
  273 + // Initalise the result to 'equal matrices'
  274 + int result = 0;
  275 +
  276 + // Perform comparison (only if matrix dimensions are identical)
  277 + if (m_rows == m.m_rows && m_cols == m.m_cols) {
  278 +
  279 + // Loop over all matrix elements
  280 + for (int row = 0; row < m_rows; ++row) {
  281 + for (int col = 0; col < m_cols; ++col) {
  282 + if ((*this)(row,col) != m(row,col)) {
  283 + result = 1;
  284 + break;
  285 + }
  286 + }
  287 + if (!result)
  288 + break;
341 289 }
342   - }
343   - if (!result)
344   - break;
345 290 }
346   - }
347   - else
348   - result = 1;
  291 + else
  292 + result = 1;
349 293  
350   - // Return result
351   - return result;
  294 + // Return result
  295 + return result;
352 296 }
353 297  
354 298  
355   -/***************************************************************************
356   - * Unary matrix addition operator *
357   - * ----------------------------------------------------------------------- *
358   - * !!! NOT YET IN NATIVE CODING !!! *
  299 +/***********************************************************************//**
  300 + * @brief Unary matrix addition operator
  301 + *
  302 + * @param[in] m Matrix to be added.
  303 + *
  304 + * TODO: Implement native sparse code
359 305 ***************************************************************************/
360 306 GSparseMatrix& GSparseMatrix::operator+= (const GSparseMatrix& m)
361 307 {
362   - // Raise an exception if the matrix dimensions are not compatible
363   - if (m_rows != m.m_rows || m_cols != m.m_cols)
364   - throw GException::matrix_mismatch(G_OP_ADD, m_rows, m_cols, m.m_rows, m.m_cols);
  308 + // Raise an exception if the matrix dimensions are not compatible
  309 + if (m_rows != m.m_rows || m_cols != m.m_cols)
  310 + throw GException::matrix_mismatch(G_OP_ADD, m_rows, m_cols,
  311 + m.m_rows, m.m_cols);
365 312  
366   - // Perform inplace matrix addition
367   - for (int col = 0; col < m_cols; ++col) {
368   - GVector v_result = extract_col(col);
369   - GVector v_operand = m.extract_col(col);
370   - v_result += v_operand;
371   - insert_col(v_result, col);
372   - }
  313 + // Perform inplace matrix addition using vectors
  314 + for (int col = 0; col < m_cols; ++col) {
  315 + GVector v_result = extract_col(col);
  316 + GVector v_operand = m.extract_col(col);
  317 + v_result += v_operand;
  318 + insert_col(v_result, col);
  319 + }
373 320  
374   - // Return result
375   - return *this;
  321 + // Return result
  322 + return *this;
376 323 }
377 324  
378 325  
379   -/***************************************************************************
380   - * Unary matrix subtraction operator *
381   - * ----------------------------------------------------------------------- *
382   - * !!! NOT YET IN NATIVE CODING !!! *
  326 +/***********************************************************************//**
  327 + * @brief Unary matrix subtraction operator
  328 + *
  329 + * @param[in] m Matrix to be subtracted.
  330 + *
  331 + * TODO: Implement native sparse code
383 332 ***************************************************************************/
384 333 GSparseMatrix& GSparseMatrix::operator-= (const GSparseMatrix& m)
385 334 {
386   - // Raise an exception if the matrix dimensions are not compatible
387   - if (m_rows != m.m_rows || m_cols != m.m_cols)
388   - throw GException::matrix_mismatch(G_OP_SUB, m_rows, m_cols, m.m_rows, m.m_cols);
  335 + // Raise an exception if the matrix dimensions are not compatible
  336 + if (m_rows != m.m_rows || m_cols != m.m_cols)
  337 + throw GException::matrix_mismatch(G_OP_SUB, m_rows, m_cols,
  338 + m.m_rows, m.m_cols);
389 339  
390   - // Perform inplace matrix subtraction
391   - for (int col = 0; col < m_cols; ++col) {
392   - GVector v_result = extract_col(col);
393   - GVector v_operand = m.extract_col(col);
394   - v_result -= v_operand;
395   - insert_col(v_result, col);
396   - }
  340 + // Perform inplace matrix subtraction
  341 + for (int col = 0; col < m_cols; ++col) {
  342 + GVector v_result = extract_col(col);
  343 + GVector v_operand = m.extract_col(col);
  344 + v_result -= v_operand;
  345 + insert_col(v_result, col);
  346 + }
397 347  
398   - // Return result
399   - return *this;
  348 + // Return result
  349 + return *this;
400 350 }
401 351  
402 352  
403   -/***************************************************************************
404   - * Matrix multiplication (unary multiplication operator) *
405   - * ----------------------------------------------------------------------- *
406   - * !!! NOT YET IN NATIVE CODING !!! *
  353 +/***********************************************************************//**
  354 + * @brief Unary matrix multiplication operator
  355 + *
  356 + * @param[in] m Matrix to be multiplied.
  357 + *
  358 + * TODO: Implement native sparse code
407 359 ***************************************************************************/
408 360 GSparseMatrix& GSparseMatrix::operator*= (const GSparseMatrix& m)
409 361 {
410   - // Raise an exception if the matrix dimensions are not compatible
411   - if (m_cols != m.m_rows || m_rows != m.m_cols)
412   - throw GException::matrix_mismatch(G_OP_MAT_MUL, m_rows, m_cols, m.m_rows, m.m_cols);
413   -
414   - // Allocate result matrix
415   - GSparseMatrix result(m_rows, m.m_cols);
416   -
417   - // Multiply only if there are elements in both matrices
418   - if (m_elements > 0 && m.m_elements > 0) {
  362 + // Raise an exception if the matrix dimensions are not compatible
  363 + if (m_cols != m.m_rows || m_rows != m.m_cols)
  364 + throw GException::matrix_mismatch(G_OP_MAT_MUL, m_rows, m_cols,
  365 + m.m_rows, m.m_cols);
  366 +
  367 + // Allocate result matrix
  368 + GSparseMatrix result(m_rows, m.m_cols);
  369 +
  370 + // Multiply only if there are elements in both matrices
  371 + if (m_elements > 0 && m.m_elements > 0) {
  372 +
  373 + // Loop over all elements of result matrix
  374 + for (int row = 0; row < m_rows; ++row) {
  375 + for (int col = 0; col < m.m_cols; ++col) {
  376 + double sum = 0.0;
  377 + for (int i = 0; i < m_cols; ++i)
  378 + sum += (*this)(row,i) * m(i,col);
  379 + result(row,col) = sum;
  380 + }
  381 + }
419 382  
420   - // Loop over all elements of result matrix
421   - for (int row = 0; row < m_rows; ++row) {
422   - for (int col = 0; col < m.m_cols; ++col) {
423   - double sum = 0.0;
424   - for (int i = 0; i < m_cols; ++i)
425   - sum += (*this)(row,i) * m(i,col);
426   - result(row,col) = sum;
427   - }
428 383 }
429 384  
430   - }
431   -
432   - // Assign result
433   - *this = result;
  385 + // Assign result
  386 + *this = result;
434 387  
435   - // Return result
436   - return *this;
  388 + // Return result
  389 + return *this;
437 390 }
438 391  
439 392  
440 393 /*==========================================================================
441 394 = =
442   - = GSparseMatrix methods =
  395 + = GSparseMatrix public methods =
443 396 = =
444 397 ==========================================================================*/
445 398  
... ... @@ -714,214 +667,215 @@ void GSparseMatrix::cholesky_decompose(int compress)
714 667 }
715 668  
716 669  
717   -/***************************************************************************
718   - * GSparseMatrix Cholesky solver *
719   - * ----------------------------------------------------------------------- *
720   - * Solves the linear equation A*x=b using a Cholesky decomposition of A. *
721   - * This function is to be applied on a GSparseMatrix matrix for which a *
722   - * Choleksy factorization has been produced using 'cholesky_decompose'. *
  670 +/***********************************************************************//**
  671 + * @brief Cholesky solver
  672 + *
  673 + * @param[in] v Solution vector.
  674 + * @param[in] compress Request matrix compression.
  675 + *
  676 + * Solves the linear equation A*x=b using a Cholesky decomposition of A.
  677 + * This function is to be applied on a GSparseMatrix matrix for which a
  678 + * Choleksy factorization has been produced using 'cholesky_decompose'.
723 679 ***************************************************************************/
724 680 GVector GSparseMatrix::cholesky_solver(const GVector& v, int compress)
725 681 {
726   - // Declare loop variables
727   - int row;
728   - int col;
729   - int c_row;
730   - int c_col;
731   -
732   - // Dump header
733   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
734   - cout << "GSparseMatrix::cholesky_solver" << endl;
735   - cout << " Input vector .....: " << v << endl;
736   - #endif
737   -
738   - // Raise an exception if the matrix and vector dimensions are incompatible
739   - if (m_rows != v.m_num)
740   - throw GException::matrix_vector_mismatch(G_CHOL_SOLVE, v.m_num, m_rows, m_cols);
741   -
742   - // Raise an exception if there is no symbolic pointer
743   - if (!m_symbolic)
744   - throw GException::matrix_not_factorised(G_CHOL_SOLVE, "Cholesky decomposition");
745   -
746   - // Get symbolic pointer
747   - GSparseSymbolic* symbolic = (GSparseSymbolic*)m_symbolic;
748   -
749   - // Raise an exception if there is no permutation
750   - if (!symbolic->m_pinv)
751   - throw GException::matrix_not_factorised(G_CHOL_SOLVE, "Cholesky decomposition");
752   -
753   - // Flag row and column compression
754   - int row_compressed = (m_rowsel != NULL && m_num_rowsel < m_rows);
755   - int col_compressed = (m_colsel != NULL && m_num_colsel < m_cols);
756   -
757   - // Decide if we need a compression algorithm or not
758   - int no_zero = !(compress && (row_compressed || col_compressed));
759   -
760   - // Allocate vector for permutation and result vector
761   - GVector result(m_cols);
762   -
763   - // Setup pointers to L matrix and x vector
764   - int* Lp = m_colstart;
765   - int* Li = m_rowinx;
766   - double* Lx = m_data;
767   -
768   - // Case A: no zero-row/col compression needed
769   - if (no_zero) {
770   -
771   - // Declare working vector
772   - GVector x(m_rows);
773   -
774   - // Perform inverse vector permutation
775   - for (int i = 0; i < v.m_num; ++i)
776   - x.m_data[symbolic->m_pinv[i]] = v.m_data[i];
  682 + // Declare loop variables
  683 + int row;
  684 + int col;
  685 + int c_row;
  686 + int c_col;
777 687  
778   - // Inplace solve L\x=x
779   - for (col = 0; col < m_cols; ++col) { // loop over columns
780   - x.m_data[col] /= Lx[Lp[col]]; // divide by diag.
781   - for (int p = Lp[col]+1; p < Lp[col+1]; p++) // loop over elements
782   - x.m_data[Li[p]] -= Lx[p] * x.m_data[col];
783   - }
  688 + // Dump header
  689 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  690 + std::cout << "GSparseMatrix::cholesky_solver" << std::endl;
  691 + std::cout << " Input vector .....: " << v << std::endl;
  692 + #endif
784 693  
785   - // Inplace solve L'\x=x
786   - for (col = m_cols-1; col >= 0; --col) { // loop over columns
787   - for (int p = Lp[col]+1; p < Lp[col+1]; p++) // loop over elements
788   - x.m_data[col] -= Lx[p] * x.m_data[Li[p]];
789   - x.m_data[col] /= Lx[Lp[col]];
790   - }
  694 + // Raise an exception if the matrix and vector dimensions are incompatible
  695 + if (m_rows != v.m_num)
  696 + throw GException::matrix_vector_mismatch(G_CHOL_SOLVE, v.m_num,
  697 + m_rows, m_cols);
  698 + // Raise an exception if there is no symbolic pointer
  699 + if (!m_symbolic)
  700 + throw GException::matrix_not_factorised(G_CHOL_SOLVE,
  701 + "Cholesky decomposition");
  702 +
  703 + // Get symbolic pointer
  704 + GSparseSymbolic* symbolic = (GSparseSymbolic*)m_symbolic;
  705 +
  706 + // Raise an exception if there is no permutation
  707 + if (!symbolic->m_pinv)
  708 + throw GException::matrix_not_factorised(G_CHOL_SOLVE,
  709 + "Cholesky decomposition");
  710 +
  711 + // Flag row and column compression
  712 + int row_compressed = (m_rowsel != NULL && m_num_rowsel < m_rows);
  713 + int col_compressed = (m_colsel != NULL && m_num_colsel < m_cols);
  714 +
  715 + // Decide if we need a compression algorithm or not
  716 + int no_zero = !(compress && (row_compressed || col_compressed));
  717 +
  718 + // Allocate vector for permutation and result vector
  719 + GVector result(m_cols);
  720 +
  721 + // Setup pointers to L matrix and x vector
  722 + int* Lp = m_colstart;
  723 + int* Li = m_rowinx;
  724 + double* Lx = m_data;
  725 +
  726 + // Case A: no zero-row/col compression needed
  727 + if (no_zero) {
  728 +
  729 + // Declare working vector
  730 + GVector x(m_rows);
  731 +
  732 + // Perform inverse vector permutation
  733 + for (int i = 0; i < v.m_num; ++i)
  734 + x.m_data[symbolic->m_pinv[i]] = v.m_data[i];
  735 +
  736 + // Inplace solve L\x=x
  737 + for (col = 0; col < m_cols; ++col) { // loop over columns
  738 + x.m_data[col] /= Lx[Lp[col]]; // divide by diag.
  739 + for (int p = Lp[col]+1; p < Lp[col+1]; p++) // loop over elements
  740 + x.m_data[Li[p]] -= Lx[p] * x.m_data[col];
  741 + }
791 742  
792   - // Perform vector permutation
793   - for (int i = 0; i < m_cols; ++i)
794   - result.m_data[i] = x.m_data[symbolic->m_pinv[i]];
  743 + // Inplace solve L'\x=x
  744 + for (col = m_cols-1; col >= 0; --col) { // loop over columns
  745 + for (int p = Lp[col]+1; p < Lp[col+1]; p++) // loop over elements
  746 + x.m_data[col] -= Lx[p] * x.m_data[Li[p]];
  747 + x.m_data[col] /= Lx[Lp[col]];
  748 + }
795 749  
796   - } // endif: Case A
  750 + // Perform vector permutation
  751 + for (int i = 0; i < m_cols; ++i)
  752 + result.m_data[i] = x.m_data[symbolic->m_pinv[i]];
797 753  
798   - // Case B: zero-row/column compression requested
799   - else {
  754 + } // endif: Case A
800 755  
801   - // Allocate row and column mapping arrays
802   - int* row_map = new int[m_rows];
803   - if (row_map == NULL)
804   - throw GException::mem_alloc(G_CHOL_SOLVE, m_rows);
805   - int* col_map = new int[m_cols];
806   - if (col_map == NULL)
807   - throw GException::mem_alloc(G_CHOL_SOLVE, m_cols);
808   -
809   - // Setup row mapping array that maps original matrix rows into compressed
810   - // matrix rows. An entry of -1 indicates that the row should be dropped.
811   - // If no selection exists then setup an identity map.
812   - if (row_compressed) {
813   - for (row = 0; row < m_rows; ++row)
814   - row_map[row] = -1;
815   - for (c_row = 0; c_row < m_num_rowsel; ++c_row)
816   - row_map[m_rowsel[c_row]] = c_row;
817   - }
  756 + // Case B: zero-row/column compression requested
818 757 else {
819   - for (row = 0; row < m_rows; ++row)
820   - row_map[row] = row;
821   - }
822   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
823   - cout << " Row mapping ......:";
824   - for (row = 0; row < m_rows; ++row)
825   - cout << " " << row_map[row];
826   - cout << endl;
827   - #endif
828 758  
829   - // Setup column mapping array that maps original matrix column into compressed
830   - // matrix columns. An entry of -1 indicates that the column should be dropped
831   - // If no selection exists then setup an identity map.
832   - if (col_compressed) {
833   - for (col = 0; col < m_cols; ++col)
834   - col_map[col] = -1;
835   - for (c_col = 0; c_col < m_num_colsel; ++c_col)
836   - col_map[m_colsel[c_col]] = c_col;
837   - }
838   - else {
839   - for (col = 0; col < m_cols; ++col)
840   - col_map[col] = col;
841   - }
842   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
843   - cout << " Column mapping ...:";
844   - for (col = 0; col < m_cols; ++col)
845   - cout << " " << col_map[col];
846   - cout << endl;
847   - #endif
  759 + // Allocate row and column mapping arrays
  760 + int* row_map = new int[m_rows];
  761 + int* col_map = new int[m_cols];
  762 +
  763 + // Setup row mapping array that maps original matrix rows into compressed
  764 + // matrix rows. An entry of -1 indicates that the row should be dropped.
  765 + // If no selection exists then setup an identity map.
  766 + if (row_compressed) {
  767 + for (row = 0; row < m_rows; ++row)
  768 + row_map[row] = -1;
  769 + for (c_row = 0; c_row < m_num_rowsel; ++c_row)
  770 + row_map[m_rowsel[c_row]] = c_row;
  771 + }
  772 + else {
  773 + for (row = 0; row < m_rows; ++row)
  774 + row_map[row] = row;
  775 + }
  776 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  777 + std::cout << " Row mapping ......:";
  778 + for (row = 0; row < m_rows; ++row)
  779 + std::cout << " " << row_map[row];
  780 + std::cout << std::endl;
  781 + #endif
848 782  
849   - // Declare working vector
850   - GVector x(row_compressed ? m_num_rowsel : m_rows);
  783 + // Setup column mapping array that maps original matrix column into compressed
  784 + // matrix columns. An entry of -1 indicates that the column should be dropped
  785 + // If no selection exists then setup an identity map.
  786 + if (col_compressed) {
  787 + for (col = 0; col < m_cols; ++col)
  788 + col_map[col] = -1;
  789 + for (c_col = 0; c_col < m_num_colsel; ++c_col)
  790 + col_map[m_colsel[c_col]] = c_col;
  791 + }
  792 + else {
  793 + for (col = 0; col < m_cols; ++col)
  794 + col_map[col] = col;
  795 + }
  796 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  797 + std::cout << " Column mapping ...:";
  798 + for (col = 0; col < m_cols; ++col)
  799 + std::cout << " " << col_map[col];
  800 + std::cout << std::endl;
  801 + #endif
851 802  
852   - // Compress input vector v -> c_v if required
853   - if (m_rowsel != NULL && m_num_rowsel < m_rows) {
854   - for (c_row = 0; c_row < m_num_rowsel; ++c_row)
855   - x.m_data[c_row] = v.m_data[m_rowsel[c_row]];
856   - }
857   - else
858   - x = v;
859   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
860   - cout << " Compressed vector : " << x << endl;
861   - #endif
  803 + // Declare working vector
  804 + GVector x(row_compressed ? m_num_rowsel : m_rows);
862 805  
863   - // Perform inverse permutation
864   - x = iperm(x, symbolic->m_pinv);
865   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
866   - cout << " Permutated vector : " << x << endl;
867   - #endif
  806 + // Compress input vector v -> c_v if required
  807 + if (m_rowsel != NULL && m_num_rowsel < m_rows) {
  808 + for (c_row = 0; c_row < m_num_rowsel; ++c_row)
  809 + x.m_data[c_row] = v.m_data[m_rowsel[c_row]];
  810 + }
  811 + else
  812 + x = v;
  813 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  814 + std::cout << " Compressed vector : " << x << std::endl;
  815 + #endif
868 816  
869   - // Inplace solve L\x=x. The column and row maps are just use to see which
870   - // columns or rows should be skipped in the calculations.
871   - for (col = 0; col < m_cols; ++col) { // loop over columns
872   - if ((c_col = col_map[col]) >= 0) { // use only non-zero cols
873   - x.m_data[c_col] /= Lx[Lp[col]]; // divide by diag.
874   - for (int p = Lp[col]+1; p < Lp[col+1]; p++) { // loop over elements
875   - if ((c_row = row_map[Li[p]]) >= 0) // use only non-zero rows
876   - x.m_data[c_row] -= Lx[p] * x.m_data[c_col];
  817 + // Perform inverse permutation
  818 + x = iperm(x, symbolic->m_pinv);
  819 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  820 + std::cout << " Permutated vector : " << x << std::endl;
  821 + #endif
  822 +
  823 + // Inplace solve L\x=x. The column and row maps are just use to see which
  824 + // columns or rows should be skipped in the calculations.
  825 + for (col = 0; col < m_cols; ++col) { // loop over columns
  826 + if ((c_col = col_map[col]) >= 0) { // use only non-zero cols
  827 + x.m_data[c_col] /= Lx[Lp[col]]; // divide by diag.
  828 + for (int p = Lp[col]+1; p < Lp[col+1]; p++) { // loop over elements
  829 + if ((c_row = row_map[Li[p]]) >= 0) // use only non-zero rows
  830 + x.m_data[c_row] -= Lx[p] * x.m_data[c_col];
  831 + }
  832 + }
877 833 }
878   - }
879   - }
880   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
881   - cout << " Solve Lx=x .......: " << x << endl;
882   - #endif
  834 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  835 + std::cout << " Solve Lx=x .......: " << x << std::endl;
  836 + #endif
883 837  
884   - // Inplace solve L'\x=x. The column and row maps are just use to see which
885   - // columns or rows should be skipped in the calculations.
886   - for (col = m_cols-1; col >= 0; --col) { // loop over columns
887   - if ((c_col = col_map[col]) >= 0) { // use only non-zero cols
888   - for (int p = Lp[col]+1; p < Lp[col+1]; p++) { // loop over elements
889   - if ((c_row = row_map[Li[p]]) >= 0) // use only non-zero rows
890   - x.m_data[c_col] -= Lx[p] * x.m_data[c_row];
  838 + // Inplace solve L'\x=x. The column and row maps are just use to see which
  839 + // columns or rows should be skipped in the calculations.
  840 + for (col = m_cols-1; col >= 0; --col) { // loop over columns
  841 + if ((c_col = col_map[col]) >= 0) { // use only non-zero cols
  842 + for (int p = Lp[col]+1; p < Lp[col+1]; p++) { // loop over elements
  843 + if ((c_row = row_map[Li[p]]) >= 0) // use only non-zero rows
  844 + x.m_data[c_col] -= Lx[p] * x.m_data[c_row];
  845 + }
  846 + x.m_data[c_col] /= Lx[Lp[col]];
  847 + }
891 848 }
892   - x.m_data[c_col] /= Lx[Lp[col]];
893   - }
894   - }
895   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
896   - cout << " Solve L'x=x ......: " << x << endl;
897   - #endif
  849 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  850 + std::cout << " Solve L'x=x ......: " << x << std::endl;
  851 + #endif
898 852  
899   - // Perform vector permutation
900   - x = perm(x, symbolic->m_pinv);
901   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
902   - cout << " Permutated vector : " << x << endl;
903   - #endif
  853 + // Perform vector permutation
  854 + x = perm(x, symbolic->m_pinv);
  855 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  856 + std::cout << " Permutated vector : " << x << std::endl;
  857 + #endif
904 858  
905   - // If column compression has been performed the expand the result vector
906   - // accordingly
907   - if (m_colsel != NULL && m_num_colsel < m_cols) {
908   - for (c_col = 0; c_col < m_num_colsel; ++c_col)
909   - result.m_data[m_colsel[c_col]] = x.m_data[c_col];
910   - }
911   - else
912   - result = x;
913   - #if defined(G_DEBUG_SPARSE_COMPRESSION)
914   - cout << " Restored vector ..: " << result << endl;
915   - #endif
  859 + // If column compression has been performed the expand the result vector
  860 + // accordingly
  861 + if (m_colsel != NULL && m_num_colsel < m_cols) {
  862 + for (c_col = 0; c_col < m_num_colsel; ++c_col)
  863 + result.m_data[m_colsel[c_col]] = x.m_data[c_col];
  864 + }
  865 + else
  866 + result = x;
  867 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  868 + std::cout << " Restored vector ..: " << result << std::endl;
  869 + #endif
916 870  
917   - // Free mapping arrays
918   - delete [] row_map;
919   - delete [] col_map;
  871 + // Free mapping arrays
  872 + delete [] row_map;
  873 + delete [] col_map;
920 874  
921   - } // endelse: Case B
  875 + } // endelse: Case B
922 876  
923   - // Return result vector
924   - return result;
  877 + // Return result vector
  878 + return result;
925 879 }
926 880  
927 881  
... ... @@ -963,21 +917,20 @@ void GSparseMatrix::cholesky_invert(int compress)
963 917 }
964 918  
965 919  
966   -/***************************************************************************
967   - * Set all matrix elements to 0 *
968   - * ----------------------------------------------------------------------- *
  920 +/***********************************************************************//**
  921 + * @brief Set all matrix elements to 0
969 922 ***************************************************************************/
970   -void GSparseMatrix::clear()
  923 +void GSparseMatrix::clear(void)
971 924 {
972   - // Free memory
973   - free_elements(0, m_elements);
  925 + // Free memory
  926 + free_elements(0, m_elements);
974 927  
975   - // Initialise column start indices to 0
976   - for (int col = 0; col <= m_cols; ++col)
977   - m_colstart[col] = 0;
  928 + // Initialise column start indices to 0
  929 + for (int col = 0; col <= m_cols; ++col)
  930 + m_colstart[col] = 0;
978 931  
979   - // Return
980   - return;
  932 + // Return
  933 + return;
981 934 }
982 935  
983 936  
... ... @@ -1057,17 +1010,35 @@ GVector GSparseMatrix::extract_col(int col) const
1057 1010 }
1058 1011  
1059 1012  
1060   -/***************************************************************************
1061   - * Get matrix fill *
1062   - * ----------------------------------------------------------------------- *
  1013 +/***********************************************************************//**
  1014 + * @brief Returns fill of matrix
  1015 + *
  1016 + * The fill of a matrix is defined as the number non-zero elements devided
  1017 + * by the number of total elements. By definiton, the fill is comprised
  1018 + * in the interval [0,..,1]. The fill of an undefined matrix is defined to
  1019 + * be 0.
1063 1020 ***************************************************************************/
1064 1021 double GSparseMatrix::fill() const
1065 1022 {
1066   - // Determine number of elements in matrix
1067   - int num = (m_fill_val == 0.0) ? m_elements : m_elements + 1;
  1023 + // Initialise result
  1024 + double result = 0.0;
  1025 +
  1026 + // Compute matrix size
  1027 + int size = m_rows*m_cols;
1068 1028  
1069   - // Return fill
1070   - return (double(num) / double(m_rows*m_cols));
  1029 + // Continue only if matrix has elements
  1030 + if (size > 0) {
  1031 +
  1032 + // Determine number of elements in matrix
  1033 + int num = (m_fill_val == 0.0) ? m_elements : m_elements + 1;
  1034 +
  1035 + // Compute fill
  1036 + result = double(num) / double(size);
  1037 +
  1038 + } // endif: there were elements in matrix
  1039 +
  1040 + // Return fill
  1041 + return result;
1071 1042 }
1072 1043  
1073 1044  
... ... @@ -1842,182 +1813,187 @@ double GSparseMatrix::sum() const
1842 1813  
1843 1814 /*==========================================================================
1844 1815 = =
1845   - = GSparseMatrix private functions =
  1816 + = GSparseMatrix private methods =
1846 1817 = =
1847 1818 ==========================================================================*/
1848 1819  
1849   -/***************************************************************************
1850   - * Constructor method *
1851   - * ----------------------------------------------------------------------- *
1852   - * This is the main constructor code, without any initialisation in it. *
1853   - * It is used as service function to a number of different constructors of *
1854   - * the GSparseMatrix class. *
  1820 +/***********************************************************************//**
  1821 + * @brief Allocate matrix
  1822 + *
  1823 + * @param[in] rows Number of rows to be allocated.
  1824 + * @param[in] cols Number of columns to be allocated.
  1825 + * @param[in] elements Number of matrix elements to be physically allocated.
  1826 + *
  1827 + * This is the main constructor code that allocates and initialises memory
  1828 + * for matrix elements.
1855 1829 ***************************************************************************/
1856 1830 void GSparseMatrix::constructor(int rows, int cols, int elements)
1857 1831 {
1858   - // Allocate column start array. This is the only array that we can
1859   - // allocate at this time. The other arrays can only be allocated during
1860   - // filling of the matrix
1861   - m_colstart = new int[cols+1];
1862   - if (m_colstart == NULL)
1863   - throw GException::mem_alloc(G_CONSTRUCTOR, cols+1);
1864   -
1865   - // Store (logical) matrix size
1866   - m_rows = rows;
1867   - m_cols = cols;
  1832 + // Continue only if matrix is not empty
  1833 + if (rows > 0 && cols > 0) {
1868 1834  
1869   - // Initialise column start indices to 0
1870   - for (int col = 0; col <= m_cols; ++col)
1871   - m_colstart[col] = 0;
  1835 + // Allocate column start array. This is the only array that we can
  1836 + // allocate at this time. The other arrays can only be allocated during
  1837 + // filling of the matrix
  1838 + m_colstart = new int[cols+1];
1872 1839  
1873   - // Optionally allocate elements
1874   - if (elements > 0)
1875   - alloc_elements(0, elements);
  1840 + // Store (logical) matrix size
  1841 + m_rows = rows;
  1842 + m_cols = cols;
1876 1843  
1877   - // Return
1878   - return;
1879   -}
  1844 + // Initialise column start indices to 0
  1845 + for (int col = 0; col <= m_cols; ++col)
  1846 + m_colstart[col] = 0;
1880 1847  
  1848 + // Optionally allocate memory for matrix elements
  1849 + if (elements > 0)
  1850 + alloc_elements(0, elements);
1881 1851  
1882   -/***************************************************************************
1883   - * Initialise class members *
1884   - * ----------------------------------------------------------------------- *
1885   - ***************************************************************************/
1886   -void GSparseMatrix::init_members(void)
1887   -{
1888   - // Initialise sparse matrix members
1889   - m_rowinx = NULL;
1890   - m_mem_block = G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK;
1891   - m_zero = 0.0;
1892   - m_fill_val = 0.0;
1893   - m_fill_row = 0;
1894   - m_fill_col = 0;
1895   - m_symbolic = NULL;
1896   - m_numeric = NULL;
1897   -
1898   - // Initialise stack members
1899   - init_stack_members();
  1852 + } // endif: matrix was not empty
1900 1853  
1901   - // Return
1902   - return;
  1854 + // Return
  1855 + return;
1903 1856 }
1904 1857  
1905 1858  
1906   -/***************************************************************************
1907   - * Initialise fill-stack *
1908   - * ----------------------------------------------------------------------- *
  1859 +/***********************************************************************//**
  1860 + * @brief Initialise class mambers
1909 1861 ***************************************************************************/
1910   -void GSparseMatrix::init_stack_members(void)
  1862 +void GSparseMatrix::init_members(void)
1911 1863 {
1912   - // Initialise stack members
1913   - m_stack_max_entries = 0;
1914   - m_stack_size = 0;
1915   - m_stack_entries = 0;
1916   - m_stack_colinx = NULL;
1917   - m_stack_start = NULL;
1918   - m_stack_data = NULL;
1919   - m_stack_rowinx = NULL;
1920   - m_stack_work = NULL;
1921   - m_stack_buffer = NULL;
1922   -
1923   - // Return
1924   - return;
  1864 + // Initialise sparse matrix members
  1865 + m_rowinx = NULL;
  1866 + m_mem_block = G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK;
  1867 + m_zero = 0.0;
  1868 + m_fill_val = 0.0;
  1869 + m_fill_row = 0;
  1870 + m_fill_col = 0;
  1871 + m_symbolic = NULL;
  1872 + m_numeric = NULL;
  1873 +
  1874 + // Initialise stack members
  1875 + init_stack_members();
  1876 +
  1877 + // Return
  1878 + return;
1925 1879 }
1926 1880  
1927 1881  
1928   -/***************************************************************************
1929   - * Copy class members *
1930   - * ----------------------------------------------------------------------- *
  1882 +/***********************************************************************//**
  1883 + * @brief Allocate matrix
  1884 + *
  1885 + * @param[in] m Matrix to be copied.
1931 1886 ***************************************************************************/
1932 1887 void GSparseMatrix::copy_members(const GSparseMatrix& m)
1933 1888 {
1934   - // Copy GSparseMatrix members
1935   - m_mem_block = m.m_mem_block;
1936   - m_zero = m.m_zero;
1937   - m_fill_val = m.m_fill_val;
1938   - m_fill_row = m.m_fill_row;
1939   - m_fill_col = m.m_fill_col;
1940   -
1941   - // Copy row indices
1942   - if (m.m_rowinx != NULL && m.m_alloc > 0) {
1943   - m_rowinx = new int[m.m_alloc];
1944   - if (m_rowinx == NULL)
1945   - throw GException::mem_alloc(G_COPY_MEMBERS, m.m_alloc);
1946   - for (int i = 0; i < m.m_elements; ++i)
1947   - m_rowinx[i] = m.m_rowinx[i];
1948   - }
  1889 + // Copy GSparseMatrix members
  1890 + m_mem_block = m.m_mem_block;
  1891 + m_zero = m.m_zero;
  1892 + m_fill_val = m.m_fill_val;
  1893 + m_fill_row = m.m_fill_row;
  1894 + m_fill_col = m.m_fill_col;
  1895 +
  1896 + // Copy row indices if they exist
  1897 + if (m.m_rowinx != NULL && m.m_alloc > 0) {
  1898 + m_rowinx = new int[m.m_alloc];
  1899 + for (int i = 0; i < m.m_elements; ++i)
  1900 + m_rowinx[i] = m.m_rowinx[i];
  1901 + }
1949 1902  
1950   - // Copy symbolic decomposition
1951   - if (m.m_symbolic != NULL) {
1952   - GSparseSymbolic* symbolic = new GSparseSymbolic();
1953   - if (symbolic == NULL)
1954   - throw GException::mem_alloc(G_COPY_MEMBERS, 1);
1955   - *symbolic = *((GSparseSymbolic*)m.m_symbolic);
1956   - m_symbolic = (void*)symbolic;
1957   - }
  1903 + // Copy symbolic decomposition if it exists
  1904 + if (m.m_symbolic != NULL) {
  1905 + GSparseSymbolic* symbolic = new GSparseSymbolic();
  1906 + *symbolic = *((GSparseSymbolic*)m.m_symbolic);
  1907 + m_symbolic = (void*)symbolic;
  1908 + }
1958 1909  
1959   - // Copy numeric decomposition
1960   - if (m.m_numeric != NULL) {
1961   - GSparseNumeric* numeric = new GSparseNumeric();
1962   - if (numeric == NULL)
1963   - throw GException::mem_alloc(G_COPY_MEMBERS, 1);
1964   - *numeric = *((GSparseNumeric*)m.m_numeric);
1965   - m_numeric = (void*)numeric;
1966   - }
  1910 + // Copy numeric decomposition if it exists
  1911 + if (m.m_numeric != NULL) {
  1912 + GSparseNumeric* numeric = new GSparseNumeric();
  1913 + *numeric = *((GSparseNumeric*)m.m_numeric);
  1914 + m_numeric = (void*)numeric;
  1915 + }
1967 1916  
1968   - // Return
1969   - return;
  1917 + // Return
  1918 + return;
1970 1919 }
1971 1920  
1972 1921  
1973   -/***************************************************************************
1974   - * Delete class members *
1975   - * ----------------------------------------------------------------------- *
  1922 +/***********************************************************************//**
  1923 + * @brief Delete class members
1976 1924 ***************************************************************************/
1977 1925 void GSparseMatrix::free_members(void)
1978 1926 {
1979   - // De-allocate only if memory has indeed been allocated
1980   - if (m_numeric != NULL) delete (GSparseNumeric*)m_numeric;
1981   - if (m_symbolic != NULL) delete (GSparseSymbolic*)m_symbolic;
1982   - if (m_rowinx != NULL) delete [] m_rowinx;
  1927 + // De-allocate only if memory has indeed been allocated
  1928 + if (m_numeric != NULL) delete (GSparseNumeric*)m_numeric;
  1929 + if (m_symbolic != NULL) delete (GSparseSymbolic*)m_symbolic;
  1930 + if (m_rowinx != NULL) delete [] m_rowinx;
1983 1931  
1984   - // Properly mark members as free
1985   - m_rowinx = NULL;
1986   - m_symbolic = NULL;
1987   - m_numeric = NULL;
  1932 + // Properly mark members as free
  1933 + m_rowinx = NULL;
  1934 + m_symbolic = NULL;
  1935 + m_numeric = NULL;
1988 1936  
1989   - // Free stack members
1990   - free_stack_members();
  1937 + // Free stack members
  1938 + free_stack_members();
1991 1939  
1992   - // Return
1993   - return;
  1940 + // Return
  1941 + return;
1994 1942 }
1995 1943  
1996 1944  
1997   -/***************************************************************************
1998   - * Delete fill-stack class members *
1999   - * ----------------------------------------------------------------------- *
  1945 +/***********************************************************************//**
  1946 + * @brief Initialise fill stack
  1947 + *
  1948 + * The fill stack is used to fill the sparse matrix without any prior know-
  1949 + * ledge about the number of location of the non-zero matrix elements.
  1950 + * Values are first filled into the stack and flushed into the sparse
  1951 + * matrix once the stack is full.
2000 1952 ***************************************************************************/
2001   -void GSparseMatrix::free_stack_members(void)
  1953 +void GSparseMatrix::init_stack_members(void)
2002 1954 {
2003   - // Free stack members
2004   - if (m_stack_colinx != NULL) delete [] m_stack_colinx;
2005   - if (m_stack_start != NULL) delete [] m_stack_start;
2006   - if (m_stack_data != NULL) delete [] m_stack_data;
2007   - if (m_stack_rowinx != NULL) delete [] m_stack_rowinx;
2008   - if (m_stack_work != NULL) delete [] m_stack_work;
2009   - if (m_stack_buffer != NULL) delete [] m_stack_buffer;
2010   -
2011   - // Properly mark members as free
2012   - m_stack_colinx = NULL;
2013   - m_stack_start = NULL;
2014   - m_stack_data = NULL;
2015   - m_stack_rowinx = NULL;
2016   - m_stack_work = NULL;
2017   - m_stack_buffer = NULL;
  1955 + // Initialise stack members
  1956 + m_stack_max_entries = 0;
  1957 + m_stack_size = 0;
  1958 + m_stack_entries = 0;
  1959 + m_stack_colinx = NULL;
  1960 + m_stack_start = NULL;
  1961 + m_stack_data = NULL;
  1962 + m_stack_rowinx = NULL;
  1963 + m_stack_work = NULL;
  1964 + m_stack_buffer = NULL;
  1965 +
  1966 + // Return
  1967 + return;
  1968 +}
2018 1969  
2019   - // Return
2020   - return;
  1970 +
  1971 +/***********************************************************************//**
  1972 + * @brief Delete fill-stack class members
  1973 + *
  1974 + * Deletes all memory that has been allocated using the init_stack_members()
  1975 + * method.
  1976 + ***************************************************************************/
  1977 +void GSparseMatrix::free_stack_members(void)
  1978 +{
  1979 + // Free stack members
  1980 + if (m_stack_colinx != NULL) delete [] m_stack_colinx;
  1981 + if (m_stack_start != NULL) delete [] m_stack_start;
  1982 + if (m_stack_data != NULL) delete [] m_stack_data;
  1983 + if (m_stack_rowinx != NULL) delete [] m_stack_rowinx;
  1984 + if (m_stack_work != NULL) delete [] m_stack_work;
  1985 + if (m_stack_buffer != NULL) delete [] m_stack_buffer;
  1986 +
  1987 + // Properly mark members as free
  1988 + m_stack_colinx = NULL;
  1989 + m_stack_start = NULL;
  1990 + m_stack_data = NULL;
  1991 + m_stack_rowinx = NULL;
  1992 + m_stack_work = NULL;
  1993 + m_stack_buffer = NULL;
  1994 +
  1995 + // Return
  1996 + return;
2021 1997 }
2022 1998  
2023 1999  
... ... @@ -2704,75 +2680,81 @@ void GSparseMatrix::mix_column(const double* src1_data, const int* src1_row,
2704 2680 = =
2705 2681 ==========================================================================*/
2706 2682  
2707   -/***************************************************************************
2708   - * Output operator *
2709   - * ----------------------------------------------------------------------- *
  2683 +/***********************************************************************//**
  2684 + * @brief Output operator
  2685 + *
  2686 + * @param[in] os Output stream.
  2687 + * @param[in] m Matrix to put in output stream.
2710 2688 ***************************************************************************/
2711   -ostream& operator<< (ostream& os, const GSparseMatrix& m)
  2689 +std::ostream& operator<< (std::ostream& os, const GSparseMatrix& m)
2712 2690 {
2713   - // Put header in stream
2714   - os << "=== GSparseMatrix ===" << endl;
2715   - if (m.m_rowsel != NULL)
2716   - os << " Number of rows ............: " << m.m_rows << " (compressed " <<
2717   - m.m_num_rowsel << ")" << endl;
2718   - else
2719   - os << " Number of rows ............: " << m.m_rows << endl;
2720   - if (m.m_colsel != NULL)
2721   - os << " Number of columns .........: " << m.m_cols << " (compressed " <<
2722   - m.m_num_colsel << ")" << endl;
2723   - else
2724   - os << " Number of columns .........: " << m.m_cols << endl;
2725   - if (m.m_fill_val == 0.0)
2726   - os << " Number of non-zero elements: " << m.m_colstart[m.m_cols] << " (" <<
2727   - m.m_elements << ")" << endl;
2728   - else {
2729   - os << " Number of non-zero elements: " << m.m_colstart[m.m_cols]+1 << " (" <<
2730   - m.m_elements+1 << ")" << endl;
2731   - os << " Pending element ...........: (" << m.m_fill_row << "," << m.m_fill_col <<
2732   - ")=" << m.m_fill_val << endl;
2733   - }
2734   - os << " Number of allocated cells .: " << m.m_alloc << endl;
2735   - os << " Memory block size .........: " << m.m_mem_block << endl;
2736   - os << " Sparse matrix fill ........: " << m.fill() << endl;
2737   -
2738   - // Dump elements and compression schemes
2739   - m.dump_elements(os);
2740   - m.dump_row_comp(os);
2741   - m.dump_col_comp(os);
2742   -
2743   - // If there is a symbolic decomposition then put it also in the stream
2744   - if (m.m_symbolic != NULL) {
2745   - os << endl << *((GSparseSymbolic*)m.m_symbolic);
2746   - }
  2691 + // Determine number of elements
  2692 + int nonzero;
  2693 + int elements = m.m_elements;
  2694 + if (m.m_fill_val == 0.0) {
  2695 + nonzero = (m.m_colstart != NULL) ? m.m_colstart[m.m_cols] : 0;
  2696 + }
  2697 + else {
  2698 + nonzero = (m.m_colstart != NULL) ? m.m_colstart[m.m_cols]+1 : 0;
  2699 + elements++;
  2700 + }
2747 2701  
2748   - // If there is a numeric decomposition then put it also in the stream
2749   - if (m.m_numeric != NULL) {
2750   - os << endl << *((GSparseNumeric*)m.m_numeric);
2751   - }
  2702 + // Put header in stream
  2703 + os << "=== GSparseMatrix ===" << std::endl;
  2704 + if (m.m_rowsel != NULL) {
  2705 + os << " Number of rows ............: " << m.m_rows
  2706 + << " (compressed " << m.m_num_rowsel << ")" << std::endl;
  2707 + }
  2708 + else
  2709 + os << " Number of rows ............: " << m.m_rows << std::endl;
  2710 + if (m.m_colsel != NULL) {
  2711 + os << " Number of columns .........: " << m.m_cols
  2712 + << " (compressed " << m.m_num_colsel << ")" << std::endl;
  2713 + }
  2714 + else
  2715 + os << " Number of columns .........: " << m.m_cols << std::endl;
  2716 + os << " Number of non-zero elements: " << nonzero
  2717 + << " (" << elements << ")" << std::endl;
  2718 + if (m.m_fill_val != 0.0) {
  2719 + os << " Pending element ...........: (" << m.m_fill_row << ","
  2720 + << m.m_fill_col << ")=" << m.m_fill_val << std::endl;
  2721 + }
  2722 + os << " Number of allocated cells .: " << m.m_alloc << std::endl;
  2723 + os << " Memory block size .........: " << m.m_mem_block << std::endl;
  2724 + os << " Sparse matrix fill ........: " << m.fill() << std::endl;
  2725 +
  2726 + // If there is a symbolic decomposition then put it also in the stream
  2727 + if (m.m_symbolic != NULL)
  2728 + os << std::endl << *((GSparseSymbolic*)m.m_symbolic);
  2729 +
  2730 + // If there is a numeric decomposition then put it also in the stream
  2731 + if (m.m_numeric != NULL)
  2732 + os << std::endl << *((GSparseNumeric*)m.m_numeric);
2752 2733  
2753   - // Return output stream
2754   - return os;
  2734 + // Return output stream
  2735 + return os;
2755 2736 }
2756 2737  
2757 2738  
2758   -/***************************************************************************
2759   - * Matrix absolute values *
2760   - * ----------------------------------------------------------------------- *
  2739 +/***********************************************************************//**
  2740 + * @brief Return matrix with absolute values of all elements
  2741 + *
  2742 + * @param[in] m Matrix for which absolute values are to be returned.
2761 2743 ***************************************************************************/
2762 2744 GSparseMatrix fabs(const GSparseMatrix& m)
2763 2745 {
2764   - // Define result matrix
2765   - GSparseMatrix result = m;
  2746 + // Define result matrix
  2747 + GSparseMatrix result = m;
2766 2748  
2767   - // Fill pending element
2768   - result.fill_pending();
  2749 + // Fill pending element
  2750 + result.fill_pending();
2769 2751  
2770   - // Convert all elements to absolute values
2771   - for (int i = 0; i < result.m_elements; ++i)
2772   - result.m_data[i] = fabs(result.m_data[i]);
  2752 + // Convert all elements to absolute values
  2753 + for (int i = 0; i < result.m_elements; ++i)
  2754 + result.m_data[i] = fabs(result.m_data[i]);
2773 2755  
2774   - // Return result
2775   - return result;
  2756 + // Return result
  2757 + return result;
2776 2758 }
2777 2759  
2778 2760  
... ...