Commit 0796cf5e4c40ac03ad29f7d4cc5bfd6ae6f3a0e6

Authored by knodlseder
1 parent c6e119fa

First implementation of sparse matrix class.

src/GMatrix.cpp
... ... @@ -18,20 +18,51 @@
18 18 using namespace std;
19 19  
20 20  
  21 +/*==========================================================================
  22 + = =
  23 + = GMatrix constructors/destructors =
  24 + = =
  25 + ==========================================================================*/
  26 +
  27 +/***************************************************************************
  28 + * GMatrix private constructor (used for derived class initialization) *
  29 + ***************************************************************************/
  30 +GMatrix::GMatrix(void)
  31 +{
  32 + // Initialise private members for clean destruction
  33 + m_rows = 0;
  34 + m_cols = 0;
  35 + m_elements = 0;
  36 + m_num_rowsel = 0;
  37 + m_num_colsel = 0;
  38 + m_data = NULL;
  39 + m_colstart = NULL;
  40 + m_rowsel = NULL;
  41 + m_colsel = NULL;
  42 +
  43 + // Return
  44 + return;
  45 +}
  46 +
  47 +
21 48 /***************************************************************************
22 49 * GMatrix constructor *
23 50 ***************************************************************************/
24   -GMatrix::GMatrix(unsigned rows, unsigned cols)
  51 +GMatrix::GMatrix(int rows, int cols)
25 52 {
26 53 // Initialise private members for clean destruction
27   - m_rows = 0;
28   - m_cols = 0;
29   - m_elements = 0;
30   - m_data = NULL;
31   - m_colstart = NULL;
  54 + m_rows = 0;
  55 + m_cols = 0;
  56 + m_elements = 0;
  57 + m_num_rowsel = 0;
  58 + m_num_colsel = 0;
  59 + m_data = NULL;
  60 + m_colstart = NULL;
  61 + m_rowsel = NULL;
  62 + m_colsel = NULL;
32 63  
33 64 // Determine number of physical elements in matrix
34   - unsigned elements = rows*cols;
  65 + int elements = rows*cols;
35 66  
36 67 // Throw exception if requested matrix size is zero
37 68 if (elements == 0)
... ... @@ -40,7 +71,7 @@ GMatrix::GMatrix(unsigned rows, unsigned cols)
40 71 // Allocate matrix array and column start index array. Throw an exception
41 72 // if allocation failed
42 73 m_data = new double[elements];
43   - m_colstart = new unsigned[cols+1];
  74 + m_colstart = new int[cols+1];
44 75 if (m_data == NULL || m_colstart == NULL)
45 76 throw mem_alloc("GMatrix constructor", elements);
46 77  
... ... @@ -51,36 +82,80 @@ GMatrix::GMatrix(unsigned rows, unsigned cols)
51 82  
52 83 // Set-up column start indices
53 84 m_colstart[0] = 0;
54   - for (unsigned col = 1; col <= m_cols; ++col)
  85 + for (int col = 1; col <= m_cols; ++col)
55 86 m_colstart[col] = m_colstart[col-1] + m_rows;
56 87  
57 88 // Initialise matrix elements to 0.0
58   - for (unsigned i = 0; i < m_elements; ++i)
  89 + for (int i = 0; i < m_elements; ++i)
59 90 m_data[i] = 0.0;
  91 +
  92 + // Return
  93 + return;
60 94 }
61 95  
62 96  
63 97 /***************************************************************************
64   - * GMatrix copy constructor *
  98 + * GMatrix copy constructor *
  99 + * ----------------------------------------------------------------------- *
  100 + * The copy constructor is sufficiently general to provide the base *
  101 + * constructor for all derived classes, including sparse matrices. *
65 102 ***************************************************************************/
66 103 GMatrix::GMatrix(const GMatrix& m)
67 104 {
68   - m_rows = 0;
69   - m_cols = 0;
70   - m_elements = 0;
71   - m_data = NULL;
72   - m_colstart = NULL;
73   - m_data = new double[m.m_elements];
74   - m_colstart = new unsigned[m.m_cols+1];
75   - if (m_data == NULL || m_colstart == NULL)
76   - throw mem_alloc("GMatrix copy constructor", m.m_elements);
  105 + // Initialise private members for clean destruction
  106 + m_rows = 0;
  107 + m_cols = 0;
  108 + m_elements = 0;
  109 + m_num_rowsel = 0;
  110 + m_num_colsel = 0;
  111 + m_data = NULL;
  112 + m_colstart = NULL;
  113 + m_rowsel = NULL;
  114 + m_colsel = NULL;
  115 +
  116 + // Allocate memory for column start array and copy content
  117 + m_colstart = new int[m.m_cols+1];
  118 + if (m_colstart == NULL)
  119 + throw mem_alloc("GMatrix copy constructor", m.m_cols+1);
  120 + for (int i = 0; i <= m.m_cols; ++i)
  121 + m_colstart[i] = m.m_colstart[i];
  122 +
  123 + // 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];
  126 + if (m_data == NULL)
  127 + throw mem_alloc("GMatrix copy constructor", m.m_elements);
  128 + for (int i = 0; i < m.m_elements; ++i)
  129 + m_data[i] = m.m_data[i];
  130 + }
  131 +
  132 + // If there is a row selection then copy it
  133 + if (m.m_rowsel != NULL && m.m_num_rowsel > 0) {
  134 + m_rowsel = new int[m.m_num_rowsel];
  135 + if (m_rowsel == NULL)
  136 + throw mem_alloc("GMatrix copy constructor", m.m_num_rowsel);
  137 + for (int i = 0; i < m.m_num_rowsel; ++i)
  138 + m_rowsel[i] = m.m_rowsel[i];
  139 + m_num_rowsel = m.m_num_rowsel;
  140 + }
  141 +
  142 + // If there is a column selection then copy it
  143 + if (m.m_colsel != NULL && m.m_num_colsel > 0) {
  144 + m_colsel = new int[m.m_num_colsel];
  145 + if (m_colsel == NULL)
  146 + throw mem_alloc("GMatrix copy constructor", m.m_num_colsel);
  147 + for (int i = 0; i < m.m_num_colsel; ++i)
  148 + m_colsel[i] = m.m_colsel[i];
  149 + m_num_colsel = m.m_num_colsel;
  150 + }
  151 +
  152 + // Copy matrix attributes
77 153 m_rows = m.m_rows;
78 154 m_cols = m.m_cols;
79 155 m_elements = m.m_elements;
80   - for (unsigned i = 0; i <= m_cols; ++i)
81   - m_colstart[i] = m.m_colstart[i];
82   - for (unsigned i = 0; i < m_elements; ++i)
83   - m_data[i] = m.m_data[i];
  156 +
  157 + // Return
  158 + return;
84 159 }
85 160  
86 161  
... ... @@ -90,104 +165,591 @@ GMatrix::GMatrix(const GMatrix&amp; m)
90 165 GMatrix::~GMatrix()
91 166 {
92 167 // De-allocate only if memory has indeed been allocated
93   - if (m_colstart != NULL) delete[] m_colstart;
94   - if (m_data != NULL) delete[] m_data;
  168 + if (m_colstart != NULL) delete [] m_colstart;
  169 + if (m_rowsel != NULL) delete [] m_rowsel;
  170 + if (m_colsel != NULL) delete [] m_colsel;
  171 + if (m_data != NULL) delete [] m_data;
  172 +
  173 + // Return
  174 + return;
95 175 }
96 176  
97 177  
  178 +/*==========================================================================
  179 + = =
  180 + = GMatrix operators =
  181 + = =
  182 + ==========================================================================*/
  183 +
98 184 /***************************************************************************
99 185 * GMatrix assignment operator *
100 186 ***************************************************************************/
101 187 GMatrix& GMatrix::operator= (const GMatrix& m)
102 188 {
103   - m_rows = 0;
104   - m_cols = 0;
105   - m_elements = 0;
106   - m_data = NULL;
107   - m_colstart = NULL;
108   - m_data = new double[m.m_elements];
109   - m_colstart = new unsigned[m.m_cols+1];
110   - if (m_data == NULL || m_colstart == NULL)
111   - throw mem_alloc("GMatrix assignment operator", m.m_elements);
112   - m_rows = m.m_rows;
113   - m_cols = m.m_cols;
114   - m_elements = m.m_elements;
115   - for (unsigned i = 0; i <= m_cols; ++i)
116   - m_colstart[i] = m.m_colstart[i];
117   - for (unsigned i = 0; i < m_elements; ++i)
118   - m_data[i] = m.m_data[i];
119   - return *this;
120   -}
  189 + // Execute only if object is not identical
  190 + if (this != &m) {
  191 +
  192 + // De-allocate memory if it has indeed been allocated
  193 + if (m_colstart != NULL) delete [] m_colstart;
  194 + if (m_rowsel != NULL) delete [] m_rowsel;
  195 + if (m_colsel != NULL) delete [] m_colsel;
  196 + if (m_data != NULL) delete [] m_data;
  197 +
  198 + // Initialise private members for clean destruction
  199 + m_rows = 0;
  200 + m_cols = 0;
  201 + m_elements = 0;
  202 + m_num_rowsel = 0;
  203 + m_num_colsel = 0;
  204 + m_data = NULL;
  205 + m_colstart = NULL;
  206 + m_rowsel = NULL;
  207 + m_colsel = NULL;
  208 +
  209 + // Allocate memory for column start array and copy content
  210 + m_colstart = new int[m.m_cols+1];
  211 + if (m_colstart == NULL)
  212 + throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_cols+1);
  213 + for (int i = 0; i <= m.m_cols; ++i)
  214 + m_colstart[i] = m.m_colstart[i];
  215 +
  216 + // 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];
  219 + if (m_data == NULL)
  220 + throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_elements);
  221 + for (int i = 0; i < m.m_elements; ++i)
  222 + m_data[i] = m.m_data[i];
  223 + }
121 224  
  225 + // If there is a row selection then copy it
  226 + if (m.m_rowsel != NULL && m.m_num_rowsel > 0) {
  227 + m_rowsel = new int[m.m_num_rowsel];
  228 + if (m_rowsel == NULL)
  229 + throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_num_rowsel);
  230 + for (int i = 0; i < m.m_num_rowsel; ++i)
  231 + m_rowsel[i] = m.m_rowsel[i];
  232 + m_num_rowsel = m.m_num_rowsel;
  233 + }
122 234  
123   -/***************************************************************************
124   - * GMatrix output operator *
125   - ***************************************************************************/
126   -ostream& operator<< (ostream& os, const GMatrix& m)
127   -{
128   - for (unsigned row = 0; row < m.m_rows; ++row) {
129   - for (unsigned col = 0; col < m.m_cols; ++col) {
130   - os << m(row,col);
131   - if (col != m.m_cols-1)
132   - os << ", ";
133   - }
134   - if (row != m.m_rows-1)
135   - os << endl;
136   - }
137   - return os;
  235 + // If there is a column selection then copy it
  236 + if (m.m_colsel != NULL && m.m_num_colsel > 0) {
  237 + m_colsel = new int[m.m_num_colsel];
  238 + if (m_colsel == NULL)
  239 + throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_num_colsel);
  240 + for (int i = 0; i < m.m_num_colsel; ++i)
  241 + m_colsel[i] = m.m_colsel[i];
  242 + m_num_colsel = m.m_num_colsel;
  243 + }
  244 +
  245 + // Copy matrix attributes
  246 + m_rows = m.m_rows;
  247 + m_cols = m.m_cols;
  248 + m_elements = m.m_elements;
  249 + } // endif: object was not identical
  250 +
  251 + // Return this object
  252 + return *this;
138 253 }
139 254  
140 255  
141 256 /***************************************************************************
142   - * GMatrix * Gvector multiplication *
  257 + * Vector multiplication *
143 258 ***************************************************************************/
144 259 GVector GMatrix::operator* (const GVector& v) const
145 260 {
146 261 // Raise an exception if the matrix and vector dimensions are not compatible
147 262 if (m_cols != v.m_num)
148   - throw vec_mat_mismatch("GMatrix*GVector operator", v.m_num, m_rows, m_cols);
  263 + throw matrix_vector_mismatch("GMatrix::operator* (const GVector&)",
  264 + v.m_num, m_rows, m_cols);
149 265  
150 266 // Perform vector multiplication
151 267 GVector result(m_rows);
152   - for (unsigned row = 0; row < m_rows; ++row) {
  268 + for (int row = 0; row < m_rows; ++row) {
153 269 double sum = 0.0;
154   - for (unsigned col = 0; col < m_cols; ++col)
  270 + for (int col = 0; col < m_cols; ++col)
155 271 sum += (*this)(row,col) * v(col);
156 272 result(row) = sum;
157 273 }
  274 +
  275 + // Return result
  276 + return result;
  277 +}
  278 +
  279 +
  280 +/***************************************************************************
  281 + * GMatrix comparison (equality operator) *
  282 + ***************************************************************************/
  283 +int GMatrix::operator== (const GMatrix &m) const
  284 +{
  285 + // Initalise the result to 'equal matrices'
  286 + int result = 1;
  287 +
  288 + // Perform comparison (only if matrix dimensions and number of physical
  289 + // elements are identical; otherwise set result to 'false')
  290 + if (m_rows == m.m_rows && m_cols == m.m_cols && m_elements == m.m_elements) {
  291 + for (int i = 0; i < m_elements; ++i) {
  292 + if (m_data[i] != m.m_data[i]) {
  293 + result = 0;
  294 + break;
  295 + }
  296 + }
  297 + }
  298 + else
  299 + result = 0;
  300 +
  301 + // Return result
  302 + return result;
  303 +}
  304 +
  305 +
  306 +/***************************************************************************
  307 + * GMatrix comparison (non-equality operator) *
  308 + ***************************************************************************/
  309 +int GMatrix::operator!= (const GMatrix &m) const
  310 +{
  311 + // Initalise the result to 'equal matrices'
  312 + int result = 0;
  313 +
  314 + // Perform comparison (only if matrix dimensions and number of physical
  315 + // elements are identical; otherwise set result to 'true')
  316 + if (m_rows == m.m_rows && m_cols == m.m_cols && m_elements == m.m_elements) {
  317 + for (int i = 0; i < m_elements; ++i) {
  318 + if (m_data[i] != m.m_data[i]) {
  319 + result = 1;
  320 + break;
  321 + }
  322 + }
  323 + }
  324 + else
  325 + result = 1;
  326 +
  327 + // Return result
158 328 return result;
159 329 }
160 330  
161 331  
162 332 /***************************************************************************
163   - * GMatrix * GMatrix multiplication *
  333 + * GMatrix negation (unary minus operator) *
164 334 ***************************************************************************/
165   -GMatrix GMatrix::operator* (const GMatrix& m) const
  335 +GMatrix GMatrix::operator- ( ) const
  336 +{
  337 + // Copy argument into result
  338 + GMatrix result = *this;
  339 +
  340 + // Negate result
  341 + for (int i = 0; i < m_elements; ++i)
  342 + result.m_data[i] = -result.m_data[i];
  343 +
  344 + // Return result
  345 + return result;
  346 +}
  347 +
  348 +
  349 +/***************************************************************************
  350 + * GMatrix addition (unary addition operator) *
  351 + ***************************************************************************/
  352 +GMatrix& GMatrix::operator+= (const GMatrix& m)
  353 +{
  354 + // Raise an exception if the matrix dimensions are not compatible
  355 + if (m_rows != m.m_rows || m_cols != m.m_cols)
  356 + throw matrix_mismatch("GMatrix::operator+= (const GMatrix&)",
  357 + m_rows, m_cols, m.m_rows, m.m_cols);
  358 +
  359 + // Add matrices
  360 + for (int i = 0; i < m_elements; ++i)
  361 + m_data[i] += m.m_data[i];
  362 +
  363 + // Return result
  364 + return *this;
  365 +}
  366 +
  367 +
  368 +/***************************************************************************
  369 + * GMatrix subtraction (unary subtraction operator) *
  370 + ***************************************************************************/
  371 +GMatrix& GMatrix::operator-= (const GMatrix& m)
  372 +{
  373 + // Raise an exception if the matrix dimensions are not compatible
  374 + if (m_rows != m.m_rows || m_cols != m.m_cols)
  375 + throw matrix_mismatch("GMatrix::operator-= (const GMatrix&)",
  376 + m_rows, m_cols, m.m_rows, m.m_cols);
  377 +
  378 + // Subtract matrices
  379 + for (int i = 0; i < m_elements; ++i)
  380 + m_data[i] -= m.m_data[i];
  381 +
  382 + // Return result
  383 + return *this;
  384 +}
  385 +
  386 +
  387 +/***************************************************************************
  388 + * Matrix multiplication (unary multiplication operator) *
  389 + * ----------------------------------------------------------------------- *
  390 + * In case of rectangular matrices the result matrix does not change and *
  391 + * the operations can be performed 'quasi' inplace (except of a vector). *
  392 + * For the general case the result matrix changes the size so for *
  393 + * simplicity a new matrix is allocated to hold the results. *
  394 + ***************************************************************************/
  395 +GMatrix& GMatrix::operator*= (const GMatrix& m)
166 396 {
167 397 // Raise an exception if the matrix dimensions are not compatible
168 398 if (m_cols != m.m_rows)
169   - throw GMatrix::dim_mult_mismatch("GMatrix multiplication", m_cols, m.m_rows);
170   -
171   - // Perform matrix multiplication
172   - GMatrix result(m_rows,m.m_cols);
173   - for (unsigned row = 0; row < m_rows; ++row) {
174   - for (unsigned col = 0; col < m.m_cols; ++col) {
175   - double sum = 0.0;
176   - for (unsigned i = 0; i < m_cols; ++i)
177   - sum += (*this)(row,i)*m(i,col);
178   - result(row,col) = sum;
  399 + throw matrix_mismatch("GMatrix::operator*= (const GMatrix&)",
  400 + m_rows, m_cols, m.m_rows, m.m_cols);
  401 +
  402 + // Case A: Matrices are rectangular, so perform 'inplace' multiplication
  403 + if (m_rows == m_cols) {
  404 + for (int row = 0; row < m_rows; ++row) {
  405 + GVector v_row = extract_row(row);
  406 + for (int col = 0; col < m_cols; ++col) {
  407 + double sum = 0.0;
  408 + for (int i = 0; i < m_cols; ++i)
  409 + sum += v_row(i) * m(i,col);
  410 + (*this)(row,col) = sum;
  411 + }
179 412 }
180 413 }
  414 +
  415 + // Case B: Matrices are not rectangular, so we cannot work inplace
  416 + else {
  417 +
  418 + // Allocate result matrix
  419 + GMatrix result(m_rows, m.m_cols);
  420 +
  421 + // Loop over all elements of result matrix
  422 + for (int row = 0; row < m_rows; ++row) {
  423 + for (int col = 0; col < m.m_cols; ++col) {
  424 + double sum = 0.0;
  425 + for (int i = 0; i < m_cols; ++i)
  426 + sum += (*this)(row,i) * m(i,col);
  427 + result(row,col) = sum;
  428 + }
  429 + }
  430 +
  431 + // Assign result
  432 + *this = result;
  433 +
  434 + } // endelse: matrices were not rectangular
  435 +
  436 + // Return result
  437 + return *this;
  438 +}
  439 +
  440 +
  441 +/***************************************************************************
  442 + * GMatrix scalar multiplication (unary scalar multiplication operator) *
  443 + ***************************************************************************/
  444 +GMatrix& GMatrix::operator*= (const double& d)
  445 +{
  446 + // Case A: If multiplicator is 0.0 then set entire matrix to 0.0
  447 + if (d == 0.0) {
  448 + for (int i = 0; i < m_elements; ++i)
  449 + m_data[i] = 0.0;
  450 + }
  451 +
  452 + // Case B: If multiplicator is not +/- 1.0 then perform multiplication
  453 + else if (fabs(d) != 1.0) {
  454 + for (int i = 0; i < m_elements; ++i)
  455 + m_data[i] *= d;
  456 + }
  457 +
  458 + // Case C: If multiplication is -1.0 then negate
  459 + else if (d == -1.0) {
  460 + for (int i = 0; i < m_elements; ++i)
  461 + m_data[i] = -m_data[i];
  462 + }
  463 +
  464 + // Return result
  465 + return *this;
  466 +}
  467 +
  468 +
  469 +/***************************************************************************
  470 + * Matrix scalar division (unary scalar division operator) *
  471 + ***************************************************************************/
  472 +GMatrix& GMatrix::operator/= (const double& d)
  473 +{
  474 + // Case A: If divider is not +/- 1.0 then perform division
  475 + if (fabs(d) != 1.0) {
  476 + for (int i = 0; i < m_elements; ++i)
  477 + m_data[i] /= d;
  478 + }
  479 +
  480 + // Case B: If divider is -1.0 then negate
  481 + else if (d == -1.0) {
  482 + for (int i = 0; i < m_elements; ++i)
  483 + m_data[i] = -m_data[i];
  484 + }
  485 +
  486 + // Return result
  487 + return *this;
  488 +}
  489 +
  490 +
  491 +/*==========================================================================
  492 + = =
  493 + = GMatrix member functions =
  494 + = =
  495 + ==========================================================================*/
  496 +
  497 +/***************************************************************************
  498 + * Get minimum physical matrix element *
  499 + ***************************************************************************/
  500 +double GMatrix::min() const
  501 +{
  502 + // Initialise minimum with first element
  503 + double result = m_data[0];
  504 +
  505 + // Search all elements for the smallest one
  506 + for (int i = 1; i < m_elements; ++i) {
  507 + if (m_data[i] < result)
  508 + result = m_data[i];
  509 + }
  510 +
  511 + // Return result
  512 + return result;
  513 +}
  514 +
  515 +
  516 +/***************************************************************************
  517 + * Get maximum physical matrix element *
  518 + ***************************************************************************/
  519 +double GMatrix::max() const
  520 +{
  521 + // Initialise minimum with first element
  522 + double result = m_data[0];
  523 +
  524 + // Search all elements for the largest one
  525 + for (int i = 1; i < m_elements; ++i) {
  526 + if (m_data[i] > result)
  527 + result = m_data[i];
  528 + }
  529 +
  530 + // Return result
  531 + return result;
  532 +}
  533 +
  534 +
  535 +/***************************************************************************
  536 + * Get matrix sum *
  537 + ***************************************************************************/
  538 +double GMatrix::sum() const
  539 +{
  540 + // Initialise matrix sum
  541 + double result = 0.0;
  542 +
  543 + // Add all elements
  544 + for (int i = 0; i < m_elements; ++i)
  545 + result += m_data[i];
  546 +
  547 + // Return result
  548 + return result;
  549 +}
  550 +
  551 +
  552 +/***************************************************************************
  553 + * Inplace transpose of matrix *
  554 + * ----------------------------------------------------------------------- *
  555 + * The transpose operation exchanges the number of rows against the number *
  556 + * of columns. The element transformation is done inplace. *
  557 + ***************************************************************************/
  558 +void GMatrix::transpose()
  559 +{
  560 + // Case A: matrix is rectangular then simply swap the elements
  561 + if (m_rows == m_cols) {
  562 + double swap;
  563 + double* ptr_dst;
  564 + double* ptr_src;
  565 + for (int row = 0; row < m_rows; ++row) {
  566 + for (int col = row; col < m_cols; ++col) {
  567 + ptr_dst = m_data + m_cols*row + col;
  568 + ptr_src = m_data + m_rows*col + row;
  569 + swap = *ptr_dst;
  570 + *ptr_dst = *ptr_src;
  571 + *ptr_src = swap;
  572 + }
  573 + }
  574 + }
  575 +
  576 + // Case B: Dummy for non-rectangular transpose
  577 + else {
  578 + GMatrix result(m_cols, m_rows);
  579 + for (int row = 0; row < m_rows; ++row) {
  580 + for (int col = 0; col < m_cols; ++col)
  581 + result(col, row) = (*this)(row, col);
  582 + }
  583 + *this = result;
  584 + }
  585 +
  586 +}
  587 +
  588 +
  589 +/***************************************************************************
  590 + * Extract row from matrix into vector *
  591 + ***************************************************************************/
  592 +GVector GMatrix::extract_row(int row) const
  593 +{
  594 + // Raise an exception if the row index is invalid
  595 + #if defined(G_RANGE_CHECK)
  596 + if (row >= m_rows)
  597 + throw out_of_range("GMatrix::extract_row(int)",
  598 + row, 0, m_rows, m_cols);
  599 + #endif
  600 +
  601 + // Create result vector
  602 + GVector result(m_cols);
  603 +
  604 + // Extract row into vector
  605 + for (int col = 0; col < m_cols; ++col)
  606 + result(col) = (*this)(row,col);
  607 +
  608 + // Return vector
181 609 return result;
  610 +
182 611 }
183 612  
184 613  
185 614 /***************************************************************************
186   - * Class exception handlers *
  615 + * Extract column from matrix into vector *
187 616 ***************************************************************************/
188   -// Matrix row or column out of range
189   -GMatrix::out_of_range::out_of_range(string origin, unsigned row, unsigned col,
190   - unsigned rows, unsigned cols)
  617 +GVector GMatrix::extract_col(int col) const
  618 +{
  619 + // Raise an exception if the column index is invalid
  620 + #if defined(G_RANGE_CHECK)
  621 + if (col >= m_cols)
  622 + throw out_of_range("GMatrix::extract_col(int)",
  623 + 0, col, m_rows, m_cols);
  624 + #endif
  625 +
  626 + // Create result vector
  627 + GVector result(m_rows);
  628 +
  629 + // Extract column into vector
  630 + for (int row = 0; row < m_rows; ++row)
  631 + result(row) = (*this)(row,col);
  632 +
  633 + // Return vector
  634 + return result;
  635 +
  636 +}
  637 +
  638 +
  639 +/*==========================================================================
  640 + = =
  641 + = GMatrix private member functions =
  642 + = =
  643 + ==========================================================================*/
  644 +
  645 +/***************************************************************************
  646 + * select_non_zero *
  647 + * ----------------------------------------------------------------------- *
  648 + * Determines the non-zero rows and columns in matrix and set up index *
  649 + * arrays that points to these rows/columns. These arraya are used for *
  650 + * compressed matrix factorisations. *
  651 + ***************************************************************************/
  652 +void GMatrix::select_non_zero(void)
  653 +{
  654 + // Free existing selection arrays
  655 + if (m_rowsel != NULL) delete [] m_rowsel;
  656 + if (m_colsel != NULL) delete [] m_colsel;
  657 +
  658 + // Allocate selection arrays
  659 + m_rowsel = new int[m_rows];
  660 + if (m_rowsel == NULL)
  661 + throw mem_alloc("GMatrix::select_non_zero()", m_rows);
  662 + m_colsel = new int[m_cols];
  663 + if (m_colsel == NULL)
  664 + throw mem_alloc("GMatrix::select_non_zero()", m_cols);
  665 +
  666 + // Initialise non-zero row and column counters
  667 + m_num_rowsel = 0;
  668 + m_num_colsel = 0;
  669 +
  670 + // Declare loop variables
  671 + int row;
  672 + int col;
  673 +
  674 + // Find all non-zero rows
  675 + for (row = 0; row < m_rows; ++row) {
  676 + for (col = 0; col < m_cols; ++col) {
  677 + if ((*this)(row,col) != 0.0)
  678 + break;
  679 + }
  680 + if (col < m_cols) // found a non-zero element in row
  681 + m_rowsel[m_num_rowsel++] = row;
  682 + }
  683 +
  684 + // Find all non-zero columns
  685 + for (col = 0; col < m_cols; ++col) {
  686 + for (row = 0; row < m_rows; ++row) {
  687 + if ((*this)(row,col) != 0.0)
  688 + break;
  689 + }
  690 + if (row < m_rows) // found a non-zero element in column
  691 + m_colsel[m_num_colsel++] = col;
  692 + }
  693 +
  694 + // Return
  695 + return;
  696 +}
  697 +
  698 +/*==========================================================================
  699 + = =
  700 + = GMatrix friends =
  701 + = =
  702 + ==========================================================================*/
  703 +
  704 +/***************************************************************************
  705 + * Output operator *
  706 + ***************************************************************************/
  707 +ostream& operator<< (ostream& os, const GMatrix& m)
  708 +{
  709 + // Loop over all matrix elements
  710 + for (int row = 0; row < m.m_rows; ++row) {
  711 + for (int col = 0; col < m.m_cols; ++col) {
  712 + os << m(row,col);
  713 + if (col != m.m_cols-1)
  714 + os << ", ";
  715 + }
  716 + if (row != m.m_rows-1)
  717 + os << endl;
  718 + }
  719 +
  720 + // Return output stream
  721 + return os;
  722 +}
  723 +
  724 +
  725 +/***************************************************************************
  726 + * Matrix absolute values *
  727 + ***************************************************************************/
  728 +GMatrix fabs(const GMatrix& m)
  729 +{
  730 + // Define result matrix
  731 + GMatrix result = m;
  732 +
  733 + // Convert all elements to absolute values
  734 + for (int i = 0; i < result.m_elements; ++i)
  735 + result.m_data[i] = fabs(result.m_data[i]);
  736 +
  737 + // Return result
  738 + return result;
  739 +}
  740 +
  741 +
  742 +/*==========================================================================
  743 + = =
  744 + = GMatrix exception classes =
  745 + = =
  746 + ==========================================================================*/
  747 +
  748 +/***************************************************************************
  749 + * Matrix row or column out of range *
  750 + ***************************************************************************/
  751 +GMatrix::out_of_range::out_of_range(string origin, int row, int col,
  752 + int rows, int cols)
191 753 {
192 754 m_origin = origin;
193 755 ostringstream s_row;
... ... @@ -203,9 +765,12 @@ GMatrix::out_of_range::out_of_range(string origin, unsigned row, unsigned col,
203 765 s_cols.str() + "])";
204 766 }
205 767  
206   -// Matrix - Vector mismatch
207   -GMatrix::vec_mat_mismatch::vec_mat_mismatch(string origin, unsigned num,
208   - unsigned rows, unsigned cols)
  768 +
  769 +/***************************************************************************
  770 + * Mismatch between matrix and vector *
  771 + ***************************************************************************/
  772 +GMatrix::matrix_vector_mismatch::matrix_vector_mismatch(string origin,
  773 + int num, int rows, int cols)
209 774 {
210 775 m_origin = origin;
211 776 ostringstream s_num;
... ... @@ -219,9 +784,12 @@ GMatrix::vec_mat_mismatch::vec_mat_mismatch(string origin, unsigned num,
219 784 s_rows.str() + "," + s_cols.str() + "]";
220 785 }
221 786  
222   -// Matrix mismatch (additional etc.)
223   -GMatrix::dim_add_mismatch::dim_add_mismatch(string origin, unsigned rows1, unsigned rows2,
224   - unsigned cols1, unsigned cols2)
  787 +
  788 +/***************************************************************************
  789 + * Matrix mismatch in operation *
  790 + ***************************************************************************/
  791 +GMatrix::matrix_mismatch::matrix_mismatch(string origin, int rows1,
  792 + int cols1, int rows2, int cols2)
225 793 {
226 794 m_origin = origin;
227 795 ostringstream s_rows1;
... ... @@ -229,24 +797,84 @@ GMatrix::dim_add_mismatch::dim_add_mismatch(string origin, unsigned rows1, unsig
229 797 ostringstream s_cols1;
230 798 ostringstream s_cols2;
231 799 s_rows1 << rows1;
  800 + s_cols1 << cols1;
232 801 s_rows2 << rows2;
  802 + s_cols2 << cols2;
  803 + m_message = "Matrix mismatch: M1(" + s_rows1.str() + "," + s_cols1.str() +
  804 + ") incompatible with M2(" + s_rows2.str() + "," +
  805 + s_cols2.str() + ")";
  806 +}
  807 +
  808 +
  809 +/***************************************************************************
  810 + * Matrix not rectangular *
  811 + ***************************************************************************/
  812 +GMatrix::matrix_not_rect::matrix_not_rect(string origin, int rows1,
  813 + int cols1, int rows2, int cols2)
  814 +{
  815 + m_origin = origin;
  816 + ostringstream s_rows1;
  817 + ostringstream s_rows2;
  818 + ostringstream s_cols1;
  819 + ostringstream s_cols2;
  820 + s_rows1 << rows1;
233 821 s_cols1 << cols1;
  822 + s_rows2 << rows2;
234 823 s_cols2 << cols2;
235   - m_message = "Size [" + s_rows1.str() + "," + s_cols1.str() +
236   - "] of first matrix is incompatible with size [" +
237   - s_rows2.str() + "," + s_cols2.str() +
238   - "] of second matrix";
  824 + m_message = "Operation only valid for rectangular matrices: M[" +
  825 + s_rows1.str() + "," + s_cols1.str() +
  826 + "] *= M[" + s_rows2.str() + "," + s_cols2.str() +
  827 + "] not allowed";
  828 +}
  829 +
  830 +
  831 +/***************************************************************************
  832 + * Matrix is not positive definite *
  833 + ***************************************************************************/
  834 +GMatrix::matrix_not_pos_definite::matrix_not_pos_definite(string origin,
  835 + int row, double sum)
  836 +{
  837 + m_origin = origin;
  838 + ostringstream s_rows;
  839 + ostringstream s_sum;
  840 + s_rows << row;
  841 + s_sum << scientific << sum;
  842 + m_message = "Matrix is not positive definite (sum " + s_sum.str() +
  843 + " occured in row/column " + s_rows.str() + ")";
239 844 }
240 845  
241   -// Matrix mismatch (multiplication)
242   -GMatrix::dim_mult_mismatch::dim_mult_mismatch(string origin, unsigned cols, unsigned rows)
  846 +
  847 +/***************************************************************************
  848 + * Matrix is not symmetric *
  849 + ***************************************************************************/
  850 +GMatrix::matrix_not_symmetric::matrix_not_symmetric(string origin, int cols,
  851 + int rows)
243 852 {
244 853 m_origin = origin;
245 854 ostringstream s_rows;
246 855 ostringstream s_cols;
247 856 s_rows << rows;
248 857 s_cols << cols;
249   - m_message = "Number of columns [" + s_cols.str() +
250   - "] in first matrix is incompatible with number of rows [" +
251   - s_rows.str() + "] in second matrix";
  858 + m_message = "Matrix is not symmetric [" + s_rows.str() + "," +
  859 + s_cols.str() + "]";
  860 +}
  861 +
  862 +
  863 +/***************************************************************************
  864 + * Matrix has not been factorised *
  865 + ***************************************************************************/
  866 +GMatrix::matrix_not_factorised::matrix_not_factorised(string origin, string type)
  867 +{
  868 + m_origin = origin;
  869 + m_message = "Matrix has not been factorised using " + type;
  870 +}
  871 +
  872 +
  873 +/***************************************************************************
  874 + * All matrix elements are zero *
  875 + ***************************************************************************/
  876 +GMatrix::matrix_zero::matrix_zero(string origin)
  877 +{
  878 + m_origin = origin;
  879 + m_message = "All matrix elements are zero";
252 880 }
... ...
src/GMatrix.hpp
... ... @@ -32,264 +32,131 @@ using namespace std;
32 32 * GMatrix class definition *
33 33 ***************************************************************************/
34 34 class GMatrix {
35   - // Operator friends
36   - friend GMatrix operator+ (const double& a, const GMatrix& b);
37   - friend GMatrix operator- (const double& a, const GMatrix& b);
38   - friend GMatrix operator* (const double& a, const GMatrix& b);
  35 + // Binary operator friends
  36 + friend GMatrix operator* (const double& a, const GMatrix& b);
  37 + friend GMatrix operator* (const GMatrix& a, const double& b);
  38 + friend GMatrix operator/ (const GMatrix& a, const double& b);
39 39  
40 40 // I/O friends
41   - friend ostream& operator<< (ostream& os, const GMatrix& m);
  41 + friend ostream& operator<< (ostream& os, const GMatrix& m);
42 42  
43 43 // Friend functions
44 44 friend GMatrix transpose(const GMatrix& m);
45 45 friend GMatrix fabs(const GMatrix& m);
  46 +
46 47 public:
47 48 // Constructors and destructors
48   - GMatrix(unsigned rows, unsigned cols);
  49 + GMatrix(int rows, int cols);
49 50 GMatrix(const GMatrix& m);
50 51 virtual ~GMatrix();
51 52  
52 53 // Matrix element access operators
53   - virtual double& operator() (unsigned row, unsigned col);
54   - virtual const double& operator() (unsigned row, unsigned col) const;
  54 + virtual double& operator() (int row, int col);
  55 + virtual const double& operator() (int row, int col) const;
55 56  
56 57 // Matrix assignment operators
57   - GMatrix& operator= (const GMatrix& m);
58   - GMatrix& operator= (const double& d);
  58 + virtual GMatrix& operator= (const GMatrix& m);
  59 +
  60 + // Binary operators
  61 + virtual GMatrix operator+ (const GMatrix& m) const;
  62 + virtual GMatrix operator- (const GMatrix& m) const;
  63 + virtual GMatrix operator* (const GMatrix& m) const;
  64 + virtual GVector operator* (const GVector& v) const;
  65 + virtual int operator== (const GMatrix& m) const;
  66 + virtual int operator!= (const GMatrix& m) const;
59 67  
60   - // Generic matrix operators (structure independent)
  68 + // Unary operators
  69 + GMatrix operator- () const;
61 70 virtual GMatrix& operator+= (const GMatrix& m);
62 71 virtual GMatrix& operator-= (const GMatrix& m);
63   - virtual GMatrix& operator+= (const double& d);
64   - virtual GMatrix& operator-= (const double& d);
  72 + virtual GMatrix& operator*= (const GMatrix& m);
65 73 virtual GMatrix& operator*= (const double& d);
66 74 virtual GMatrix& operator/= (const double& d);
67   - virtual int operator== (const GMatrix& m) const;
68   - virtual int operator!= (const GMatrix& m) const;
69   -
70   - // Specific matrix operators (structure dependent)
71   - GMatrix operator+ (const GMatrix& m) const;
72   - GMatrix operator- (const GMatrix& m) const;
73   - GMatrix operator* (const GMatrix& m) const;
74   - virtual GVector operator* (const GVector& v) const;
75   - GMatrix operator+ (const double& d) const;
76   - GMatrix operator- (const double& d) const;
77   - GMatrix operator* (const double& d) const;
78   - GMatrix operator/ (const double& d) const;
79   - GMatrix operator- () const;
80   -
81   - // Generic matrix functions (structure independent)
82   - virtual double min() const; // Minimum physical element
83   - virtual double max() const; // Maximum physical element
84   - virtual double sum() const; // Sum of matrix elements
85   - virtual unsigned rows() const; // Return number of rows
86   - virtual unsigned cols() const; // Return number of columns
87 75  
88   - // Specific matrix functions (structure dependent)
89   - virtual void transpose(); // Inplace transpose of matrix
  76 + // Matrix functions
  77 + virtual int rows() const { return m_rows; }
  78 + virtual int cols() const { return m_cols; }
  79 + virtual double min() const;
  80 + virtual double max() const;
  81 + virtual double sum() const;
  82 + virtual void transpose();
  83 + virtual GVector extract_row(int row) const;
  84 + virtual GVector extract_col(int col) const;
90 85  
91 86 // Exception: Matrix indices out of range
92 87 class out_of_range : public GException {
93 88 public:
94   - out_of_range(string origin, unsigned row, unsigned col,
95   - unsigned rows, unsigned cols);
  89 + out_of_range(string origin, int row, int col, int rows, int cols);
96 90 };
97 91  
98 92 // Exception: Vector - Matrix mismatch
99   - class vec_mat_mismatch : public GException {
  93 + class matrix_vector_mismatch : public GException {
100 94 public:
101   - vec_mat_mismatch(string origin, unsigned num, unsigned rows, unsigned cols);
  95 + matrix_vector_mismatch(string origin, int num, int rows, int cols);
102 96 };
103 97  
104   - // Exception: Matrix dimensions mismatch (addition, etc.)
105   - class dim_add_mismatch : public GException {
  98 + // Exception: Matrix dimensions mismatch
  99 + class matrix_mismatch : public GException {
106 100 public:
107   - dim_add_mismatch(string origin, unsigned rows1, unsigned rows2,
108   - unsigned cols1, unsigned cols2);
  101 + matrix_mismatch(string origin, int rows1, int cols1, int cols1, int cols2);
109 102 };
110 103  
111   - // Exception: Matrix dimensions mismatch (multiplication)
112   - class dim_mult_mismatch : public GException {
  104 + // Exception: Matrix not rectangular
  105 + class matrix_not_rect : public GException {
113 106 public:
114   - dim_mult_mismatch(string origin, unsigned cols, unsigned rows);
  107 + matrix_not_rect(string origin, int rows1, int cols1, int cols1, int cols2);
115 108 };
116 109  
117   -protected:
118   - // Void constructor to be used by derived classes which have own constructor
119   - GMatrix() { }
120   -
121   - // Private data area
122   - unsigned m_rows; // Number of rows
123   - unsigned m_cols; // Number of columns
124   - unsigned m_elements; // Number of (physical) elements in matrix
125   - unsigned* m_colstart; // Column start indices (m_cols+1)
126   - double* m_data; // Matrix data
127   -};
128   -
129   -
130   -/***************************************************************************
131   - * Generic inline members (to be inherited) *
132   - ***************************************************************************/
133   -// Matrix unary addition operator: GMatrix += GMatrix
134   -inline
135   -GMatrix& GMatrix::operator+= (const GMatrix& m)
136   -{
137   - if (m_rows != m.m_rows || m_cols != m.m_cols)
138   - throw dim_add_mismatch("GMatrix += operator", m_rows, m.m_rows, m_cols, m.m_cols);
139   - for (unsigned i = 0; i < m_elements; ++i)
140   - m_data[i] += m.m_data[i];
141   - return *this;
142   -}
143   -
144   -// Matrix unary subtraction operator: GMatrix -= GMatrix
145   -inline
146   -GMatrix& GMatrix::operator-= (const GMatrix& m)
147   -{
148   - if (m_rows != m.m_rows || m_cols != m.m_cols)
149   - throw dim_add_mismatch("GMatrix -= operator", m_rows, m.m_rows, m_cols, m.m_cols);
150   - for (unsigned i = 0; i < m_elements; ++i)
151   - m_data[i] -= m.m_data[i];
152   - return *this;
153   -}
154   -
155   -// Scalar unary addition operator: GMatrix += double
156   -inline
157   -GMatrix& GMatrix::operator+= (const double& d)
158   -{
159   - for (unsigned i = 0; i < m_elements; ++i)
160   - m_data[i] += d;
161   - return *this;
162   -}
163   -
164   -// Scalar unary subtraction operator: GMatrix -= double
165   -inline
166   -GMatrix& GMatrix::operator-= (const double& d)
167   -{
168   - for (unsigned i = 0; i < m_elements; ++i)
169   - m_data[i] -= d;
170   - return *this;
171   -}
172   -
173   -// Scalar unary multiplication operator: GMatrix *= double
174   -inline
175   -GMatrix& GMatrix::operator*= (const double& d)
176   -{
177   - for (unsigned i = 0; i < m_elements; ++i)
178   - m_data[i] *= d;
179   - return *this;
180   -}
181   -
182   -// Scalar unary division operator: GMatrix /= double
183   -inline
184   -GMatrix& GMatrix::operator/= (const double& d)
185   -{
186   - for (unsigned i = 0; i < m_elements; ++i)
187   - m_data[i] /= d;
188   - return *this;
189   -}
190   -
191   -// Equality operator: GMatrix == GMatrix
192   -inline
193   -int GMatrix::operator== (const GMatrix &m) const
194   -{
195   - int result = 1;
196   - if (m_rows == m.m_rows && m_cols == m.m_cols && m_elements == m.m_elements) {
197   - for (unsigned i = 0; i < m_elements; ++i) {
198   - if (m_data[i] != m.m_data[i]) {
199   - result = 0;
200   - break;
201   - }
202   - }
203   - }
204   - else
205   - result = 0;
206   - return result;
207   -}
  110 + // Exception: Matrix not positive definite
  111 + class matrix_not_pos_definite : public GException {
  112 + public:
  113 + matrix_not_pos_definite(string origin, int row, double sum);
  114 + };
208 115  
209   -// Non equality operator: GMatrix != GMatrix
210   -inline
211   -int GMatrix::operator!= (const GMatrix &m) const
212   -{
213   - int result = 0;
214   - if (m_rows == m.m_rows && m_cols == m.m_cols && m_elements == m.m_elements) {
215   - for (unsigned i = 0; i < m_elements; ++i) {
216   - if (m_data[i] != m.m_data[i]) {
217   - result = 1;
218   - break;
219   - }
220   - }
221   - }
222   - else
223   - result = 1;
224   - return result;
225   -}
  116 + // Exception: Matrix not symmetric
  117 + class matrix_not_symmetric : public GException {
  118 + public:
  119 + matrix_not_symmetric(string origin, int cols, int rows);
  120 + };
226 121  
227   -// Matrix minimum: GMatrix.min()
228   -inline
229   -double GMatrix::min() const
230   -{
231   - double result = m_data[0];
232   - for (unsigned i = 1; i < m_elements; ++i) {
233   - if (m_data[i] < result)
234   - result = m_data[i];
235   - }
236   - return result;
237   -}
  122 + // Exception: Matrix not factorised
  123 + class matrix_not_factorised : public GException {
  124 + public:
  125 + matrix_not_factorised(string origin, string type);
  126 + };
238 127  
239   -// Matrix maximum: GMatrix.max()
240   -inline
241   -double GMatrix::max() const
242   -{
243   - double result = m_data[0];
244   - for (unsigned i = 1; i < m_elements; ++i) {
245   - if (m_data[i] > result)
246   - result = m_data[i];
247   - }
248   - return result;
249   -}
  128 + // Exception: All matrix elements are zero
  129 + class matrix_zero : public GException {
  130 + public:
  131 + matrix_zero(string origin);
  132 + };
250 133  
251   -// Matrix sum: GMatrix.sum()
252   -inline
253   -double GMatrix::sum() const
254   -{
255   - double result = 0.0;
256   - for (unsigned row = 0; row < m_rows; ++row) {
257   - for (unsigned col = 0; col < m_cols; ++col)
258   - result += (*this)(row,col);
259   - }
260   - return result;
261   -}
  134 +protected:
  135 + // Void constructor to be used by derived classes which have own constructor
  136 + GMatrix();
262 137  
263   -// Return number of rows: GMatrix.rows()
264   -inline
265   -unsigned GMatrix::rows() const
266   -{
267   - return m_rows;
268   -}
  138 + // Private member functions
  139 + void select_non_zero(void);
269 140  
270   -// Return number of columns: GMatrix.cols()
271   -inline
272   -unsigned GMatrix::cols() const
273   -{
274   - return m_cols;
275   -}
  141 + // Private data area
  142 + int m_rows; // Number of rows
  143 + int m_cols; // Number of columns
  144 + int m_elements; // Number of (physical) elements in matrix
  145 + int m_num_rowsel; // Number of selected rows (for compressed decomposition)
  146 + int m_num_colsel; // Number of selected columns (for compressed decomposition)
  147 + int* m_colstart; // Column start indices (m_cols+1)
  148 + int* m_rowsel; // Row selection (for compressed decomposition)
  149 + int* m_colsel; // Column selection (for compressed decomposition)
  150 + double* m_data; // Matrix data
  151 +};
276 152  
277 153  
278 154 /***************************************************************************
279   - * Specific inline members (may need specific function for derived class) *
  155 + * Inline member functions *
280 156 ***************************************************************************/
281   -// Scalar assignment operator: GMatrix = double
282   -inline
283   -GMatrix& GMatrix::operator= (const double& d)
284   -{
285   - for (unsigned i = 0; i < m_elements; ++i)
286   - m_data[i] = d;
287   - return *this;
288   -}
289   -
290   -// Matrix element access operator: GMatrix(row,col)
  157 +// Matrix element access operator
291 158 inline
292   -double& GMatrix::operator() (unsigned row, unsigned col)
  159 +double& GMatrix::operator() (int row, int col)
293 160 {
294 161 #if defined(G_RANGE_CHECK)
295 162 if (row >= m_rows || col >= m_cols)
... ... @@ -298,9 +165,9 @@ double&amp; GMatrix::operator() (unsigned row, unsigned col)
298 165 return m_data[m_colstart[col]+row];
299 166 }
300 167  
301   -// Matrix element access operator (const version): GMatrix(row,col)
  168 +// Matrix element access operator (const version)
302 169 inline
303   -const double& GMatrix::operator() (unsigned row, unsigned col) const
  170 +const double& GMatrix::operator() (int row, int col) const
304 171 {
305 172 #if defined(G_RANGE_CHECK)
306 173 if (row >= m_rows || col >= m_cols)
... ... @@ -309,7 +176,7 @@ const double&amp; GMatrix::operator() (unsigned row, unsigned col) const
309 176 return m_data[m_colstart[col]+row];
310 177 }
311 178  
312   -// Matrix addition: GMatrix + GMatrix
  179 +// Binary matrix addition
313 180 inline
314 181 GMatrix GMatrix::operator+ (const GMatrix& m) const
315 182 {
... ... @@ -318,7 +185,7 @@ GMatrix GMatrix::operator+ (const GMatrix&amp; m) const
318 185 return result;
319 186 }
320 187  
321   -// Matrix subtraction: GMatrix - GMatrix
  188 +// Binary matrix subtraction
322 189 inline
323 190 GMatrix GMatrix::operator- (const GMatrix& m) const
324 191 {
... ... @@ -327,91 +194,29 @@ GMatrix GMatrix::operator- (const GMatrix&amp; m) const
327 194 return result;
328 195 }
329 196  
330   -// Matrix scaling: GMatrix + double
331   -inline
332   -GMatrix GMatrix::operator+ (const double& d) const
333   -{
334   - GMatrix result = (*this);
335   - result += d;
336   - return result;
337   -}
338   -
339   -// Matrix scaling: GMatrix - double
340   -inline
341   -GMatrix GMatrix::operator- (const double& d) const
342   -{
343   - GMatrix result = (*this);
344   - result -= d;
345   - return result;
346   -}
347   -
348   -// Matrix scaling: GMatrix * double
349   -inline
350   -GMatrix GMatrix::operator* (const double& d) const
351   -{
352   - GMatrix result = (*this);
353   - result *= d;
354   - return result;
355   -}
356   -
357   -// Matrix inverse scaling: GMatrix * double
358   -inline
359   -GMatrix GMatrix::operator/ (const double& d) const
360   -{
361   - GMatrix result = (*this);
362   - result /= d;
363   - return result;
364   -}
365   -
366   -// Unary minus operator: -GMatrix
  197 +// Binary matrix multiplication
367 198 inline
368   -GMatrix GMatrix::operator- ( ) const
  199 +GMatrix GMatrix::operator* (const GMatrix& m) const
369 200 {
370 201 GMatrix result = *this;
371   - for (unsigned i = 0; i < m_elements; ++i)
372   - result.m_data[i] = -result.m_data[i];
  202 + result *= m;
373 203 return result;
374 204 }
375 205  
376   -// Matrix transpose: GMatrix.transpose()
377   -inline
378   -void GMatrix::transpose()
379   -{
380   - for (unsigned row = 0; row < m_rows; ++row) {
381   - double* ptr0 = m_data + row;
382   - double* ptr2 = m_data + m_colstart[row]+row+1;
383   - for (unsigned col = row+1; col < m_cols; ++col) {
384   - double* ptr1 = ptr0 + m_colstart[col];
385   - double swap = *ptr1;
386   - *ptr1 = *ptr2;
387   - *ptr2++ = swap;
388   - }
389   - }
390   -}
391   -
392 206  
393 207 /***************************************************************************
394 208 * Inline friends *
395 209 ***************************************************************************/
396   -// Matrix addition: double + GMatrix
397   -inline
398   -GMatrix operator+ (const double& a, const GMatrix& b)
399   -{
400   - GMatrix result = b;
401   - result += a;
402   - return result;
403   -}
404   -
405   -// Matrix subtraction: double - GMatrix
406   -inline
407   -GMatrix operator- (const double& a, const GMatrix& b)
  210 +// Binary matrix scaling (matrix is left operand)
  211 +inline
  212 +GMatrix operator* (const GMatrix& a, const double& b)
408 213 {
409   - GMatrix result = b;
410   - result -= a;
  214 + GMatrix result = a;
  215 + result *= b;
411 216 return result;
412 217 }
413 218  
414   -// Matrix scaling: double * GMatrix
  219 +// Binary matrix scaling (matrix is right operand)
415 220 inline
416 221 GMatrix operator* (const double& a, const GMatrix& b)
417 222 {
... ... @@ -420,22 +225,21 @@ GMatrix operator* (const double&amp; a, const GMatrix&amp; b)
420 225 return result;
421 226 }
422 227  
423   -// Matrix transpose: transpose(GMatrix)
424   -inline
425   -GMatrix transpose(const GMatrix& m)
  228 +// Binary matrix division (matrix is left operand)
  229 +inline
  230 +GMatrix operator/ (const GMatrix& a, const double& b)
426 231 {
427   - GMatrix result = m;
428   - result.transpose();
  232 + GMatrix result = a;
  233 + result /= b;
429 234 return result;
430 235 }
431 236  
432   -// Matrix absolute: fabs(GMatrix)
  237 +// Matrix transpose function
433 238 inline
434   -GMatrix fabs(const GMatrix& m)
  239 +GMatrix transpose(const GMatrix& m)
435 240 {
436 241 GMatrix result = m;
437   - for (unsigned i = 0; i < result.m_elements; ++i)
438   - result.m_data[i] = fabs(result.m_data[i]);
  242 + result.transpose();
439 243 return result;
440 244 }
441 245  
... ...
src/GSparseMatrix.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * GSparseMatrix.cpp - sparse matrix class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright : (C) 2006 by Jurgen Knodlseder *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software; you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation; either version 2 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + * ----------------------------------------------------------------------- *
  13 + * This class implements the compressed sparse column format. The *
  14 + * following arrays are allocated: *
  15 + * m_data : holds all 'elements' non-zero values, in column order (Ax) *
  16 + * m_colstart : holds the index of the first element of each column (Ap) *
  17 + * m_rowinx : holds the row indices for all elements (Ai) *
  18 + * Column 'col' covers therefore [m_colstart[j], ..., m_colstart[j+1]-1] *
  19 + * Note that 'm_colstart' has m_cols+1 elements. *
  20 +/***************************************************************************
  21 +
  22 +/* __ Includes ___________________________________________________________ */
  23 +#include "GSparseMatrix.hpp"
  24 +#include "GSparseSymbolic.hpp"
  25 +#include "GSparseNumeric.hpp"
  26 +
  27 +/* __ Namespaces _________________________________________________________ */
  28 +using namespace std;
  29 +
  30 +/* __ Definitions ________________________________________________________ */
  31 +//#define G_DEBUG_SPARSE_PENDING // Analyse pending values
  32 +//#define G_DEBUG_SPARSE_INSERTION // Analyse value insertion
  33 +//#define G_DEBUG_SPARSE_COMPRESSION // Analyse zero row/column compression
  34 +
  35 +
  36 +/*==========================================================================
  37 + = =
  38 + = GSparseMatrix constructors/destructors =
  39 + = =
  40 + ==========================================================================*/
  41 +
  42 +/***************************************************************************
  43 + * GSparseMatrix constructor *
  44 + ***************************************************************************/
  45 +GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix()
  46 +{
  47 + // 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;
  60 +
  61 + // Allocate column start array. This is the only array that we can
  62 + // allocate at this time. The other arrays can only be allocated during
  63 + // filling of the matrix
  64 + m_colstart = new int[cols+1];
  65 + if (m_colstart == NULL)
  66 + throw mem_alloc("GSparseMatrix constructor", cols+1);
  67 +
  68 + // Store (logical) matrix size
  69 + m_rows = rows;
  70 + m_cols = cols;
  71 +
  72 + // Initialise column start indices to 0
  73 + for (int col = 0; col <= m_cols; ++col)
  74 + m_colstart[col] = 0;
  75 +
  76 + // Optionally allocate elements
  77 + if (elements > 0)
  78 + alloc_elements(0, elements);
  79 +
  80 + // Return
  81 + return;
  82 +}
  83 +
  84 +
  85 +/***************************************************************************
  86 + * GSparseMatrix copy constructor *
  87 + * ----------------------------------------------------------------------- *
  88 + * First invoques GMatrix copy constructor (which sets the logical matrix *
  89 + * dimensions and copies the elements and the column start array). It *
  90 + * remains then to this constructor to copy the row indices. *
  91 + * NOTE: The copy constructor does NOT fill a pending element. *
  92 + ***************************************************************************/
  93 +GSparseMatrix::GSparseMatrix(const GSparseMatrix& m) : GMatrix(m)
  94 +{
  95 + // Initialise private members for clean destruction
  96 + m_rowinx = NULL;
  97 + m_symbolic = NULL;
  98 + m_numeric = NULL;
  99 +
  100 + // 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;
  105 +
  106 + // 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];
  109 + if (m_rowinx == NULL)
  110 + throw mem_alloc("GSparseMatrix copy constructor", m_elements);
  111 + for (int i = 0; i < m_elements; ++i)
  112 + m_rowinx[i] = m.m_rowinx[i];
  113 + }
  114 +
  115 + // If there is a symbolic decomposition then copy it
  116 + if (m.m_symbolic != NULL) {
  117 + GSparseSymbolic* symbolic = new GSparseSymbolic();
  118 + if (symbolic == NULL)
  119 + throw mem_alloc("GSparseMatrix copy constructor", 1);
  120 + *symbolic = *((GSparseSymbolic*)m.m_symbolic);
  121 + m_symbolic = (void*)symbolic;
  122 + }
  123 +
  124 + // If there is a numeric decomposition then copy it
  125 + if (m.m_numeric != NULL) {
  126 + GSparseNumeric* numeric = new GSparseNumeric();
  127 + if (numeric == NULL)
  128 + throw mem_alloc("GSparseMatrix copy constructor", 1);
  129 + *numeric = *((GSparseNumeric*)m.m_numeric);
  130 + m_numeric = (void*)numeric;
  131 + }
  132 +
  133 + // Return
  134 + return;
  135 +}
  136 +
  137 +
  138 +/***************************************************************************
  139 + * GSparseMatrix destructor *
  140 + * ----------------------------------------------------------------------- *
  141 + * First invoques this destructor to de-allocate row indices, then invoque *
  142 + * ~GMatrix destructor to de-allocate the other arrays. *
  143 + ***************************************************************************/
  144 +GSparseMatrix::~GSparseMatrix()
  145 +{
  146 + // De-allocate only if memory has indeed been allocated by derived class
  147 + if (m_rowinx != NULL) delete [] m_rowinx;
  148 + if (m_symbolic != NULL) delete (GSparseSymbolic*)m_symbolic;
  149 + if (m_numeric != NULL) delete (GSparseNumeric*)m_numeric;
  150 +
  151 + // Return
  152 + return;
  153 +}
  154 +
  155 +
  156 +/*==========================================================================
  157 + = =
  158 + = GSparseMatrix operators =
  159 + = =
  160 + ==========================================================================*/
  161 +
  162 +/***************************************************************************
  163 + * GSparseMatrix assignment operator *
  164 + ***************************************************************************/
  165 +GSparseMatrix& GSparseMatrix::operator= (const GSparseMatrix& m)
  166 +{
  167 + // Execute only if object is not identical
  168 + if (this != &m) {
  169 +
  170 + // Invoque base class assignment operator
  171 + this->GMatrix::operator=(m);
  172 +
  173 + // De-allocate memory if it has indeed been allocated
  174 + if (m_rowinx != NULL) delete [] m_rowinx;
  175 + if (m_symbolic != NULL) delete (GSparseSymbolic*)m_symbolic;
  176 + if (m_numeric != NULL) delete (GSparseNumeric*)m_numeric;
  177 +
  178 + // Initialise private members for clean destruction
  179 + m_rowinx = NULL;
  180 + m_symbolic = NULL;
  181 + m_numeric = NULL;
  182 +
  183 + // 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 +
  189 + // 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];
  192 + if (m_rowinx == NULL)
  193 + throw mem_alloc("GSparseMatrix::operator= (const GSparseMatrix&)",
  194 + m_elements);
  195 + for (int i = 0; i < m_elements; ++i)
  196 + m_rowinx[i] = m.m_rowinx[i];
  197 + }
  198 +
  199 + // If there is a symbolic decomposition then copy it
  200 + if (m.m_symbolic != NULL) {
  201 + GSparseSymbolic* symbolic = new GSparseSymbolic();
  202 + if (symbolic == NULL)
  203 + throw mem_alloc("GSparseMatrix copy constructor", 1);
  204 + *symbolic = *((GSparseSymbolic*)m.m_symbolic);
  205 + m_symbolic = (void*)symbolic;
  206 + }
  207 +
  208 + // If there is a numeric decomposition then copy it
  209 + if (m.m_numeric != NULL) {
  210 + GSparseNumeric* numeric = new GSparseNumeric();
  211 + if (numeric == NULL)
  212 + throw mem_alloc("GSparseMatrix copy constructor", 1);
  213 + *numeric = *((GSparseNumeric*)m.m_numeric);
  214 + m_numeric = (void*)numeric;
  215 + }
  216 +
  217 + } // endif: object was not identical
  218 +
  219 + // Return
  220 + return *this;
  221 +}
  222 +
  223 +
  224 +/***************************************************************************
  225 + * Vector multiplication *
  226 + * ----------------------------------------------------------------------- *
  227 + * Performs sparse matrix*vector multiplication including an eventually *
  228 + * pending fill. *
  229 + ***************************************************************************/
  230 +GVector GSparseMatrix::operator* (const GVector& v) const
  231 +{
  232 + // Raise an exception if the matrix and vector dimensions are not compatible
  233 + if (m_cols != v.m_num)
  234 + throw matrix_vector_mismatch("GSparseMatrix::operator* (const GVector&)",
  235 + v.m_num, m_rows, m_cols);
  236 +
  237 + // Initialise result vector
  238 + GVector result(m_rows);
  239 +
  240 + // Multiply only if there are elements in matrix
  241 + if (m_elements > 0) {
  242 +
  243 + // Perform vector multiplication
  244 + for (int col = 0; col < m_cols; ++col) {
  245 + int i_start = m_colstart[col];
  246 + int i_stop = m_colstart[col+1];
  247 + double* ptr_data = m_data + i_start;
  248 + int* ptr_rowinx = m_rowinx + i_start;
  249 + for (int i = i_start; i < i_stop; ++i)
  250 + result(*ptr_rowinx++) += *ptr_data++ * v(col);
  251 + }
  252 +
  253 + // If fill is pending then add-in also this element into the product
  254 + if (m_fill_val != 0.0) {
  255 + result(m_fill_row) += m_fill_val * v(m_fill_col);
  256 + #if defined(G_DEBUG_SPARSE_PENDING)
  257 + cout << "GSparseMatrix::operator* (const GVector&) const: pending value " <<
  258 + m_fill_val << " for location (" << m_fill_row << "," << m_fill_col <<
  259 + ") has been used." << endl;
  260 + #endif
  261 + }
  262 +
  263 + } // endif: there were elements in matrix
  264 +
  265 + // Return result
  266 + return result;
  267 +}
  268 +
  269 +
  270 +/***************************************************************************
  271 + * GSparseMatrix comparison (equality operator) *
  272 + ***************************************************************************/
  273 +int GSparseMatrix::operator== (const GSparseMatrix &m) const
  274 +{
  275 + // Initalise the result to 'equal matrices'
  276 + int result = 1;
  277 +
  278 + // Perform comparison (only if matrix dimensions are identical)
  279 + if (m_rows == m.m_rows && m_cols == m.m_cols) {
  280 +
  281 + // Loop over all matrix elements
  282 + for (int row = 0; row < m_rows; ++row) {
  283 + for (int col = 0; col < m_cols; ++col) {
  284 + if ((*this)(row,col) != m(row,col)) {
  285 + result = 0;
  286 + break;
  287 + }
  288 + }
  289 + if (!result)
  290 + break;
  291 + }
  292 + }
  293 + else
  294 + result = 0;
  295 +
  296 + // Return result
  297 + return result;
  298 +}
  299 +
  300 +
  301 +/***************************************************************************
  302 + * GSparseMatrix comparison (non-equality operator) *
  303 + ***************************************************************************/
  304 +int GSparseMatrix::operator!= (const GSparseMatrix &m) const
  305 +{
  306 + // Initalise the result to 'equal matrices'
  307 + int result = 0;
  308 +
  309 + // Perform comparison (only if matrix dimensions are identical)
  310 + if (m_rows == m.m_rows && m_cols == m.m_cols) {
  311 +
  312 + // Loop over all matrix elements
  313 + for (int row = 0; row < m_rows; ++row) {
  314 + for (int col = 0; col < m_cols; ++col) {
  315 + if ((*this)(row,col) != m(row,col)) {
  316 + result = 1;
  317 + break;
  318 + }
  319 + }
  320 + if (!result)
  321 + break;
  322 + }
  323 + }
  324 + else
  325 + result = 1;
  326 +
  327 + // Return result
  328 + return result;
  329 +}
  330 +
  331 +
  332 +/***************************************************************************
  333 + * GSparseMatrix negation (unary minus operator) *
  334 + ***************************************************************************/
  335 +GSparseMatrix GSparseMatrix::operator- ( ) const
  336 +{
  337 + // Copy argument into result
  338 + GSparseMatrix result = *this;
  339 +
  340 + // Fill pending matrix element
  341 + result.fill_pending();
  342 +
  343 + // Negate result
  344 + for (int i = 0; i < result.m_elements; ++i)
  345 + result.m_data[i] = -result.m_data[i];
  346 +
  347 + // Return result
  348 + return result;
  349 +}
  350 +
  351 +
  352 +/***************************************************************************
  353 + * GSparseMatrix addition (unary addition operator) *
  354 + * ----------------------------------------------------------------------- *
  355 + * NOT YET IN PURE NATIVE CODE !!!!!! *
  356 + ***************************************************************************/
  357 +GSparseMatrix& GSparseMatrix::operator+= (const GSparseMatrix& m)
  358 +{
  359 + // Raise an exception if the matrix dimensions are not compatible
  360 + if (m_rows != m.m_rows || m_cols != m.m_cols)
  361 + throw matrix_mismatch("GSparseMatrix::operator+= (const GSparseMatrix&)",
  362 + m_rows, m_cols, m.m_rows, m.m_cols);
  363 +
  364 + // Perform inplace matrix addition
  365 + for (int col = 0; col < m_cols; ++col) {
  366 + GVector v_result = extract_col(col);
  367 + GVector v_operand = m.extract_col(col);
  368 + v_result += v_operand;
  369 + insert_col(v_result, col);
  370 + }
  371 +
  372 + // Return result
  373 + return *this;
  374 +}
  375 +
  376 +
  377 +/***************************************************************************
  378 + * GSparseMatrix subtraction (unary addition operator) *
  379 + * ----------------------------------------------------------------------- *
  380 + * NOT YET IN PURE NATIVE CODE !!!!!! *
  381 + ***************************************************************************/
  382 +GSparseMatrix& GSparseMatrix::operator-= (const GSparseMatrix& m)
  383 +{
  384 + // Raise an exception if the matrix dimensions are not compatible
  385 + if (m_rows != m.m_rows || m_cols != m.m_cols)
  386 + throw matrix_mismatch("GSparseMatrix::operator-= (const GSparseMatrix&)",
  387 + m_rows, m_cols, m.m_rows, m.m_cols);
  388 +
  389 + // Perform inplace matrix subtraction
  390 + for (int col = 0; col < m_cols; ++col) {
  391 + GVector v_result = extract_col(col);
  392 + GVector v_operand = m.extract_col(col);
  393 + v_result -= v_operand;
  394 + insert_col(v_result, col);
  395 + }
  396 +
  397 + // Return result
  398 + return *this;
  399 +}
  400 +
  401 +
  402 +/***************************************************************************
  403 + * Matrix multiplication (unary multiplication operator) *
  404 + * ----------------------------------------------------------------------- *
  405 + * NOT YET IN PURE NATIVE CODE !!!!!! *
  406 + ***************************************************************************/
  407 +GSparseMatrix& GSparseMatrix::operator*= (const GSparseMatrix& m)
  408 +{
  409 + // Raise an exception if the matrix dimensions are not compatible
  410 + if (m_cols != m.m_rows || m_rows != m.m_cols)
  411 + throw matrix_mismatch("GSparseMatrix::operator*= (const GSparseMatrix&)",
  412 + 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) {
  419 +
  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 + }
  429 +
  430 + }
  431 +
  432 + // Assign result
  433 + *this = result;
  434 +
  435 + // Return result
  436 + return *this;
  437 +}
  438 +
  439 +
  440 +/*==========================================================================
  441 + = =
  442 + = GSparseMatrix member functions =
  443 + = =
  444 + ==========================================================================*/
  445 +
  446 +/***************************************************************************
  447 + * Get minimum matrix element *
  448 + ***************************************************************************/
  449 +double GSparseMatrix::min() const
  450 +{
  451 + // Initialise minimum with fill value
  452 + double result = m_fill_val;
  453 +
  454 + // Search all elements for the smallest one
  455 + for (int i = 0; i < m_elements; ++i) {
  456 + if (m_data[i] < result)
  457 + result = m_data[i];
  458 + }
  459 +
  460 + // If minimum is > 0.0 and there are zero elements then set the minimum
  461 + // to 0.0
  462 + if ((result > 0.0) && (m_elements < (m_rows*m_cols)))
  463 + result = 0.0;
  464 +
  465 + // Return result
  466 + return result;
  467 +}
  468 +
  469 +
  470 +/***************************************************************************
  471 + * Get maximum matrix element *
  472 + ***************************************************************************/
  473 +double GSparseMatrix::max() const
  474 +{
  475 + // Initialise maximum with fill value
  476 + double result = m_fill_val;
  477 +
  478 + // Search all elements for the largest one
  479 + for (int i = 0; i < m_elements; ++i) {
  480 + if (m_data[i] > result)
  481 + result = m_data[i];
  482 + }
  483 +
  484 + // If maximum is < 0.0 and there are zero elements then set the maximum
  485 + // to 0.0
  486 + if ((result < 0.0) && (m_elements < (m_rows*m_cols)))
  487 + result = 0.0;
  488 +
  489 + // Return result
  490 + return result;
  491 +}
  492 +
  493 +
  494 +/***************************************************************************
  495 + * Compute sum of non-zero elements *
  496 + ***************************************************************************/
  497 +double GSparseMatrix::sum() const
  498 +{
  499 + // Initialise matrix sum with fill value
  500 + double result = m_fill_val;
  501 +
  502 + // Add all elements
  503 + for (int i = 0; i < m_elements; ++i)
  504 + result += m_data[i];
  505 +
  506 + // Return result
  507 + return result;
  508 +}
  509 +
  510 +
  511 +/***************************************************************************
  512 + * Inplace transpose of matrix *
  513 + * ----------------------------------------------------------------------- *
  514 + * Call cs function *
  515 + ***************************************************************************/
  516 +void GSparseMatrix::transpose()
  517 +{
  518 + *this = cs_transpose(this, 1);
  519 +}
  520 +
  521 +
  522 +/***************************************************************************
  523 + * Extract row from matrix into vector *
  524 + ***************************************************************************/
  525 +GVector GSparseMatrix::extract_row(int row) const
  526 +{
  527 + // Raise an exception if the row index is invalid
  528 + #if defined(G_RANGE_CHECK)
  529 + if (row >= m_rows)
  530 + throw out_of_range("GSparseMatrix::extract_row(int)",
  531 + row, 0, m_rows, m_cols);
  532 + #endif
  533 +
  534 + // Create result vector
  535 + GVector result(m_cols);
  536 +
  537 + // Loop over all columns to extract data
  538 + for (int col = 0; col < m_cols; ++col) {
  539 +
  540 + // Get the start and stop of the elements
  541 + int i_start = m_colstart[col];
  542 + int i_stop = m_colstart[col+1];
  543 +
  544 + // Search requested row in elements
  545 + int i;
  546 + for (i = i_start; i < i_stop; ++i) {
  547 + if (m_rowinx[i] == row)
  548 + break;
  549 + }
  550 +
  551 + // Copy element if we found one
  552 + if (i < i_stop)
  553 + result(col) = m_data[i];
  554 +
  555 + } // endfor: looped over all columns
  556 +
  557 + // If there is a pending element then put it in the vector
  558 + if (m_fill_val != 0.0 && m_fill_row == row)
  559 + result(m_fill_col) = m_fill_val;
  560 +
  561 + // Return vector
  562 + return result;
  563 +
  564 +}
  565 +
  566 +
  567 +/***************************************************************************
  568 + * Extract column from matrix into vector *
  569 + ***************************************************************************/
  570 +GVector GSparseMatrix::extract_col(int col) const
  571 +{
  572 + // Raise an exception if the column index is invalid
  573 + #if defined(G_RANGE_CHECK)
  574 + if (col >= m_cols)
  575 + throw out_of_range("GSparseMatrix::extract_col(int)",
  576 + 0, col, m_rows, m_cols);
  577 + #endif
  578 +
  579 + // Create result vector
  580 + GVector result(m_rows);
  581 +
  582 + // Get the start and stop of the elements
  583 + int i_start = m_colstart[col];
  584 + int i_stop = m_colstart[col+1];
  585 +
  586 + // Extract elements into vector
  587 + for (int i = i_start; i < i_stop; ++i)
  588 + result(m_rowinx[i]) = m_data[i];
  589 +
  590 + // If there is a pending element then put it in the vector
  591 + if (m_fill_val != 0.0 && m_fill_col == col)
  592 + result(m_fill_row) = m_fill_val;
  593 +
  594 + // Return vector
  595 + return result;
  596 +
  597 +}
  598 +
  599 +
  600 +/***************************************************************************
  601 + * Insert vector column into matrix *
  602 + ***************************************************************************/
  603 +void GSparseMatrix::insert_col(const GVector& v, int col)
  604 +{
  605 + // Debug header
  606 + #if defined(G_DEBUG_SPARSE_INSERTION)
  607 + cout << "GSparseMatrix::insert_col([" << v << "], " << col << "):" << endl;
  608 + cout << " In Data : ";
  609 + for (int i = 0; i < m_elements; ++i)
  610 + cout << m_data[i] << " ";
  611 + cout << endl << " In Row .: ";
  612 + for (int i = 0; i < m_elements; ++i)
  613 + cout << m_rowinx[i] << " ";
  614 + cout << endl << " In Col .: ";
  615 + for (int i = 0; i < m_cols+1; ++i)
  616 + cout << m_colstart[i] << " ";
  617 + cout << endl;
  618 + #endif
  619 +
  620 + // Raise an exception if the column index is invalid
  621 + #if defined(G_RANGE_CHECK)
  622 + if (col >= m_cols)
  623 + throw out_of_range("GSparseMatrix::insert_col(const GVector&, int)",
  624 + 0, col, m_rows, m_cols);
  625 + #endif
  626 +
  627 + // Raise an exception if the matrix and vector dimensions are not compatible
  628 + if (m_rows != v.m_num)
  629 + throw matrix_vector_mismatch("GSparseMatrix::insert_col(const GVector&, int)",
  630 + v.m_num, m_rows, m_cols);
  631 +
  632 + // If there is a pending element for this column then delete it since
  633 + // the vector overwrites this element
  634 + if (m_fill_val != 0.0 && m_fill_col == col) {
  635 + #if defined(G_DEBUG_SPARSE_PENDING)
  636 + cout << "GSparseMatrix::insert_col(const GVector, int): pending value " <<
  637 + m_fill_val << " for location (" << m_fill_row << "," << m_fill_col <<
  638 + ") became obsolete" << endl;
  639 + #endif
  640 + m_fill_val = 0.0;
  641 + m_fill_row = 0;
  642 + m_fill_col = 0;
  643 + }
  644 +
  645 + // Determine the number of non-zero elements in the vector
  646 + int n_vector = 0;
  647 + for (int row = 0; row < m_rows; ++row) {
  648 + if (v(row) != 0.0)
  649 + n_vector++;
  650 + }
  651 +
  652 + // Get the start and stop indices of the actual column and compute
  653 + // the number of exisiting elements in the column
  654 + int i_start = m_colstart[col];
  655 + int i_stop = m_colstart[col+1];
  656 + int n_exist = i_stop - i_start;
  657 +
  658 + // Compute the size difference for the new matrix. It is positive if
  659 + // the number of non-zero entries in the vector is larger than the
  660 + // number of non-zero entries in the matrix (in this case we have to
  661 + // increase the matrix size).
  662 + int n_diff = n_vector - n_exist;
  663 +
  664 + // If we need space then allocate it, if we have to much space the free it
  665 + if (n_diff > 0) {
  666 + alloc_elements(i_start, n_diff);
  667 + #if defined(G_DEBUG_SPARSE_INSERTION)
  668 + cout << " Insert .: " << n_diff << " elements at index " << i_start << endl;
  669 + #endif
  670 + }
  671 + else if (n_diff < 0) {
  672 + free_elements(i_start, -n_diff);
  673 + #if defined(G_DEBUG_SPARSE_INSERTION)
  674 + cout << " Remove .: " << -n_diff << " elements at index " << i_start << endl;
  675 + #endif
  676 + }
  677 +
  678 + // Insert the vector elements in the matrix
  679 + if (n_vector > 0) {
  680 + for (int row = 0, i = i_start; row < m_rows; ++row) {
  681 + if (v(row) != 0.0) {
  682 + m_data[i] = v(row);
  683 + m_rowinx[i] = row;
  684 + i++;
  685 + }
  686 + }
  687 + }
  688 +
  689 + // Update column start indices
  690 + for (int i = col+1; i <= m_cols; ++i)
  691 + m_colstart[i] += n_diff;
  692 +
  693 + // Debugging: show sparse matrix after insertion
  694 + #if defined(G_DEBUG_SPARSE_INSERTION)
  695 + cout << " Out Data: ";
  696 + for (int i = 0; i < m_elements; ++i)
  697 + cout << m_data[i] << " ";
  698 + cout << endl << " Out Row : ";
  699 + for (int i = 0; i < m_elements; ++i)
  700 + cout << m_rowinx[i] << " ";
  701 + cout << endl << " Out Col : ";
  702 + for (int i = 0; i < m_cols+1; ++i)
  703 + cout << m_colstart[i] << " ";
  704 + cout << endl;
  705 + #endif
  706 +
  707 + // Return
  708 + return;
  709 +}
  710 +
  711 +
  712 +/***************************************************************************
  713 + * Add vector to matrix column *
  714 + ***************************************************************************/
  715 +void GSparseMatrix::add_col(const GVector& v, int col)
  716 +{
  717 + // Raise an exception if the column index is invalid
  718 + #if defined(G_RANGE_CHECK)
  719 + if (col >= m_cols)
  720 + throw out_of_range("GSparseMatrix::add_col(const GVector&, int)",
  721 + 0, col, m_rows, m_cols);
  722 + #endif
  723 +
  724 + // Raise an exception if the matrix and vector dimensions are incompatible
  725 + if (m_rows != v.m_num)
  726 + throw matrix_vector_mismatch("GSparseMatrix::add_col(const GVector&, int)",
  727 + v.m_num, m_rows, m_cols);
  728 +
  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);
  733 +
  734 + // Return
  735 + return;
  736 +}
  737 +
  738 +
  739 +/***************************************************************************
  740 + * Convert matrix into full matrix *
  741 + ***************************************************************************/
  742 +GMatrix GSparseMatrix::convert_to_full() const
  743 +{
  744 + // Define result matrix
  745 + GMatrix result(m_rows, m_cols);
  746 +
  747 + // Extract all elements
  748 + for (int row = 0; row < m_rows; ++row) {
  749 + for (int col = 0; col < m_cols; ++col)
  750 + result(row,col) = (*this)(row,col);
  751 + }
  752 +
  753 + // Return result
  754 + return result;
  755 +}
  756 +
  757 +
  758 +/***************************************************************************
  759 + * GSparseMatrix Cholesky decomposition *
  760 + * ----------------------------------------------------------------------- *
  761 + * Cholesky decomposition of a sparse matrix. The decomposition is stored *
  762 + * within the GSparseMatrix without destroying the original matrix. *
  763 +***************************************************************************/
  764 +void GSparseMatrix::cholesky_decompose(int compress)
  765 +{
  766 + // Save original matrix size
  767 + int matrix_rows = m_rows;
  768 + int matrix_cols = m_cols;
  769 +
  770 + // Delete any existing symbolic analysis object
  771 + if (m_symbolic != NULL) delete (GSparseSymbolic*)m_symbolic;
  772 +
  773 + // Allocate symbolic analysis object
  774 + GSparseSymbolic* symbolic = new GSparseSymbolic();
  775 + if (symbolic == NULL)
  776 + throw mem_alloc("GSparseMatrix::cholesky_decompose(int)", 1);
  777 +
  778 + // Declare numeric analysis object. We don't allocate one since we'll
  779 + // throw it away at the end of the function (the L matrix will be copied
  780 + // in this object)
  781 + GSparseNumeric numeric;
  782 +
  783 + // Fill pending element into matrix
  784 + fill_pending();
  785 +
  786 + // Remove rows and columns containing only zeros if matrix compression
  787 + // has been selected
  788 + if (compress)
  789 + remove_zero_row_col();
  790 +
  791 + // Ordering an symbolic analysis of matrix. This sets up an array 'pinv'
  792 + // which contains the fill-in reducing permutations
  793 + symbolic->cholesky_symbolic_analysis(1, *this);
  794 +
  795 + // Perform numeric Cholesky decomposition
  796 + numeric.cholesky_numeric_analysis(*this, *symbolic);
  797 +
  798 + // Insert zero rows and columns if they have been removed previously.
  799 + // Since no selection information is present in numeric.m_L we have to
  800 + // copy it from this in order to allow for insertion.
  801 + if (compress) {
  802 +
  803 + // If there is a row selection then copy it
  804 + if (m_rowsel != NULL && m_num_rowsel > 0) {
  805 + numeric.m_L->m_rowsel = new int[m_num_rowsel];
  806 + if (numeric.m_L->m_rowsel == NULL)
  807 + throw mem_alloc("GSparseMatrix::cholesky_decompose(int)", m_num_rowsel);
  808 + for (int i = 0; i < m_num_rowsel; ++i)
  809 + numeric.m_L->m_rowsel[i] = m_rowsel[i];
  810 + numeric.m_L->m_num_rowsel = m_num_rowsel;
  811 + }
  812 +
  813 + // If there is a column selection then copy it
  814 + if (m_colsel != NULL && m_num_colsel > 0) {
  815 + numeric.m_L->m_colsel = new int[m_num_colsel];
  816 + if (numeric.m_L->m_colsel == NULL)
  817 + throw mem_alloc("GSparseMatrix::cholesky_decompose(int)", m_num_colsel);
  818 + for (int i = 0; i < m_num_colsel; ++i)
  819 + numeric.m_L->m_colsel[i] = m_colsel[i];
  820 + numeric.m_L->m_num_colsel = m_num_colsel;
  821 + }
  822 +
  823 + // Now we can insert zero rows and columns
  824 + numeric.m_L->insert_zero_row_col(matrix_rows, matrix_cols);
  825 + }
  826 +
  827 + // Store Cholesky decomposition in matrix
  828 + *this = *(numeric.m_L);
  829 +
  830 + // Store symbolic pointer in sparse matrix object
  831 + m_symbolic = (void*)symbolic;
  832 +
  833 + // Return
  834 + return;
  835 +}
  836 +
  837 +
  838 +/***************************************************************************
  839 + * GSparseMatrix Cholesky solver *
  840 + * ----------------------------------------------------------------------- *
  841 + * Solves the linear equation A*x=b using a Cholesky decomposition of A. *
  842 + * This function is to be applied on a GSparseMatrix matrix for which a *
  843 + * Choleksy factorization has been produced using 'cholesky_decompose'. *
  844 + ***************************************************************************/
  845 +GVector GSparseMatrix::cholesky_solver(const GVector& v, int compress)
  846 +{
  847 + // Declare loop variables
  848 + int row;
  849 + int col;
  850 + int c_row;
  851 + int c_col;
  852 +
  853 + // Dump header
  854 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  855 + cout << "GSparseMatrix::cholesky_solver" << endl;
  856 + cout << " Input vector .....: " << v << endl;
  857 + #endif
  858 +
  859 + // Raise an exception if the matrix and vector dimensions are incompatible
  860 + if (m_rows != v.m_num)
  861 + throw matrix_vector_mismatch(
  862 + "GSparseMatrix::cholesky_solver(const GVector&, int)",
  863 + v.m_num, m_rows, m_cols);
  864 +
  865 + // Raise an exception if there is no symbolic pointer
  866 + if (!m_symbolic)
  867 + throw matrix_not_factorised(
  868 + "GSparseMatrix::cholesky_solver(const GVector&, int)",
  869 + "Cholesky decomposition");
  870 +
  871 + // Get symbolic pointer
  872 + GSparseSymbolic* symbolic = (GSparseSymbolic*)m_symbolic;
  873 +
  874 + // Raise an exception if there is no permutation
  875 + if (!symbolic->m_pinv)
  876 + throw matrix_not_factorised(
  877 + "GSparseMatrix::cholesky_solver(const GVector&, int)",
  878 + "Cholesky decomposition");
  879 +
  880 + // Flag row and column compression
  881 + int row_compressed = (m_rowsel != NULL && m_num_rowsel < m_rows);
  882 + int col_compressed = (m_colsel != NULL && m_num_colsel < m_cols);
  883 +
  884 + // Decide if we need a compression algorithm or not
  885 + int no_zero = !(compress && (row_compressed || col_compressed));
  886 +
  887 + // Allocate vector for permutation and result vector
  888 + GVector result(m_cols);
  889 +
  890 + // Setup pointers to L matrix and x vector
  891 + int* Lp = m_colstart;
  892 + int* Li = m_rowinx;
  893 + double* Lx = m_data;
  894 +
  895 + // Case A: no zero-row/col compression needed
  896 + if (no_zero) {
  897 +
  898 + // Declare working vector
  899 + GVector x(m_rows);
  900 +
  901 + // Perform inverse vector permutation
  902 + for (int i = 0; i < v.m_num; ++i)
  903 + x.m_data[symbolic->m_pinv[i]] = v.m_data[i];
  904 +
  905 + // Inplace solve L\x=x
  906 + for (col = 0; col < m_cols; ++col) { // loop over columns
  907 + x.m_data[col] /= Lx[Lp[col]]; // divide by diag.
  908 + for (int p = Lp[col]+1; p < Lp[col+1]; p++) // loop over elements
  909 + x.m_data[Li[p]] -= Lx[p] * x.m_data[col];
  910 + }
  911 +
  912 + // Inplace solve L'\x=x
  913 + for (col = m_cols-1; col >= 0; --col) { // loop over columns
  914 + for (int p = Lp[col]+1; p < Lp[col+1]; p++) // loop over elements
  915 + x.m_data[col] -= Lx[p] * x.m_data[Li[p]];
  916 + x.m_data[col] /= Lx[Lp[col]];
  917 + }
  918 +
  919 + // Perform vector permutation
  920 + for (int i = 0; i < m_cols; ++i)
  921 + result.m_data[i] = x.m_data[symbolic->m_pinv[i]];
  922 +
  923 + } // endif: Case A
  924 +
  925 + // Case B: zero-row/column compression requested
  926 + else {
  927 +
  928 + // Allocate row and column mapping arrays
  929 + int* row_map = new int[m_rows];
  930 + if (row_map == NULL)
  931 + throw mem_alloc("GSparseMatrix::cholesky_solver(const GVector&, int)", m_rows);
  932 + int* col_map = new int[m_cols];
  933 + if (col_map == NULL)
  934 + throw mem_alloc("GSparseMatrix::cholesky_solver(const GVector&, int)", m_cols);
  935 +
  936 + // Setup row mapping array that maps original matrix rows into compressed
  937 + // matrix rows. An entry of -1 indicates that the row should be dropped.
  938 + // If no selection exists then setup an identity map.
  939 + if (row_compressed) {
  940 + for (row = 0; row < m_rows; ++row)
  941 + row_map[row] = -1;
  942 + for (c_row = 0; c_row < m_num_rowsel; ++c_row)
  943 + row_map[m_rowsel[c_row]] = c_row;
  944 + }
  945 + else {
  946 + for (row = 0; row < m_rows; ++row)
  947 + row_map[row] = row;
  948 + }
  949 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  950 + cout << " Row mapping ......:";
  951 + for (row = 0; row < m_rows; ++row)
  952 + cout << " " << row_map[row];
  953 + cout << endl;
  954 + #endif
  955 +
  956 + // Setup column mapping array that maps original matrix column into compressed
  957 + // matrix columns. An entry of -1 indicates that the column should be dropped
  958 + // If no selection exists then setup an identity map.
  959 + if (col_compressed) {
  960 + for (col = 0; col < m_cols; ++col)
  961 + col_map[col] = -1;
  962 + for (c_col = 0; c_col < m_num_colsel; ++c_col)
  963 + col_map[m_colsel[c_col]] = c_col;
  964 + }
  965 + else {
  966 + for (col = 0; col < m_cols; ++col)
  967 + col_map[col] = col;
  968 + }
  969 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  970 + cout << " Column mapping ...:";
  971 + for (col = 0; col < m_cols; ++col)
  972 + cout << " " << col_map[col];
  973 + cout << endl;
  974 + #endif
  975 +
  976 + // Declare working vector
  977 + GVector x(row_compressed ? m_num_rowsel : m_rows);
  978 +
  979 + // Compress input vector v -> c_v if required
  980 + if (m_rowsel != NULL && m_num_rowsel < m_rows) {
  981 + for (c_row = 0; c_row < m_num_rowsel; ++c_row)
  982 + x.m_data[c_row] = v.m_data[m_rowsel[c_row]];
  983 + }
  984 + else
  985 + x = v;
  986 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  987 + cout << " Compressed vector : " << x << endl;
  988 + #endif
  989 +
  990 + // Perform inverse permutation
  991 + x = iperm(x, symbolic->m_pinv);
  992 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  993 + cout << " Permutated vector : " << x << endl;
  994 + #endif
  995 +
  996 + // Inplace solve L\x=x. The column and row maps are just use to see which
  997 + // columns or rows should be skipped in the calculations.
  998 + for (col = 0; col < m_cols; ++col) { // loop over columns
  999 + if ((c_col = col_map[col]) >= 0) { // use only non-zero cols
  1000 + x.m_data[c_col] /= Lx[Lp[col]]; // divide by diag.
  1001 + for (int p = Lp[col]+1; p < Lp[col+1]; p++) { // loop over elements
  1002 + if ((c_row = row_map[Li[p]]) >= 0) // use only non-zero rows
  1003 + x.m_data[c_row] -= Lx[p] * x.m_data[c_col];
  1004 + }
  1005 + }
  1006 + }
  1007 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1008 + cout << " Solve Lx=x .......: " << x << endl;
  1009 + #endif
  1010 +
  1011 + // Inplace solve L'\x=x. The column and row maps are just use to see which
  1012 + // columns or rows should be skipped in the calculations.
  1013 + for (col = m_cols-1; col >= 0; --col) { // loop over columns
  1014 + if ((c_col = col_map[col]) >= 0) { // use only non-zero cols
  1015 + for (int p = Lp[col]+1; p < Lp[col+1]; p++) { // loop over elements
  1016 + if ((c_row = row_map[Li[p]]) >= 0) // use only non-zero rows
  1017 + x.m_data[c_col] -= Lx[p] * x.m_data[c_row];
  1018 + }
  1019 + x.m_data[c_col] /= Lx[Lp[col]];
  1020 + }
  1021 + }
  1022 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1023 + cout << " Solve L'x=x ......: " << x << endl;
  1024 + #endif
  1025 +
  1026 + // Perform vector permutation
  1027 + x = perm(x, symbolic->m_pinv);
  1028 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1029 + cout << " Permutated vector : " << x << endl;
  1030 + #endif
  1031 +
  1032 + // If column compression has been performed the expand the result vector
  1033 + // accordingly
  1034 + if (m_colsel != NULL && m_num_colsel < m_cols) {
  1035 + for (c_col = 0; c_col < m_num_colsel; ++c_col)
  1036 + result.m_data[m_colsel[c_col]] = x.m_data[c_col];
  1037 + }
  1038 + else
  1039 + result = x;
  1040 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1041 + cout << " Restored vector ..: " << result << endl;
  1042 + #endif
  1043 +
  1044 + // Free mapping arrays
  1045 + delete [] row_map;
  1046 + delete [] col_map;
  1047 +
  1048 + } // endelse: Case B
  1049 +
  1050 + // Return result vector
  1051 + return result;
  1052 +}
  1053 +
  1054 +
  1055 +/***************************************************************************
  1056 + * GSparseMatrix Cholesky invert *
  1057 + * ----------------------------------------------------------------------- *
  1058 + * Inplace matrix inversion using the Cholesky decomposition. *
  1059 + ***************************************************************************/
  1060 +void GSparseMatrix::cholesky_invert(int compress)
  1061 +{
  1062 + // Generate Cholesky decomposition of matrix
  1063 + cholesky_decompose(compress);
  1064 +
  1065 + // Allocate result matrix and unit vector
  1066 + GSparseMatrix result(m_rows, m_cols);
  1067 + GVector unit(m_rows);
  1068 +
  1069 + // Column-wise solving of the problem
  1070 + for (int col = 0; col < m_cols; ++col) {
  1071 +
  1072 + // Set unit vector
  1073 + unit.m_data[col] = 1.0;
  1074 +
  1075 + // Solve for column
  1076 + GVector x = cholesky_solver(unit, compress);
  1077 +
  1078 + // Insert column in matrix
  1079 + result.insert_col(x, col);
  1080 +
  1081 + // Clear unit vector for next round
  1082 + unit.m_data[col] = 0.0;
  1083 +
  1084 + }
  1085 +
  1086 + *this = result;
  1087 +
  1088 + // Return
  1089 + return;
  1090 +}
  1091 +
  1092 +
  1093 +/*==========================================================================
  1094 + = =
  1095 + = GSparseMatrix private functions =
  1096 + = =
  1097 + ==========================================================================*/
  1098 +
  1099 +/***************************************************************************
  1100 + * Determines element index for (row,col) *
  1101 + * ----------------------------------------------------------------------- *
  1102 + * Returns the index in the compressed array for (row,col). The following *
  1103 + * special results exist: *
  1104 + * -1: Requested index does not exist in the matrix *
  1105 + * m_elements: Requested index is the pending element *
  1106 + ***************************************************************************/
  1107 +int GSparseMatrix::get_index(int row, int col) const
  1108 +{
  1109 + // Initialise element to 'not found'
  1110 + int index = -1;
  1111 +
  1112 + // If we have a pending element then check if this element is requested
  1113 + if (m_fill_val != 0.0) {
  1114 + if (row == m_fill_row && col == m_fill_col)
  1115 + return m_elements;
  1116 + }
  1117 +
  1118 + // If requested element is not the pending element then check if it exists
  1119 + // in the matrix. Only if it is found its index is returned. Otherwise
  1120 + // the default index is -1, signalling that the element is absent.
  1121 + if (m_elements > 0) {
  1122 + int* ptr_colstart = m_colstart + col;
  1123 + int i_start = *ptr_colstart++;
  1124 + int i_stop = *ptr_colstart;
  1125 + int* ptr_rowinx = m_rowinx + i_start;
  1126 + for (int i = i_start; i < i_stop; ++i) {
  1127 + int row_test = *ptr_rowinx++;
  1128 + if (row_test == row) {
  1129 + index = i;
  1130 + break;
  1131 + }
  1132 + }
  1133 + }
  1134 +
  1135 + // Return index
  1136 + return index;
  1137 +}
  1138 +
  1139 +
  1140 +/***************************************************************************
  1141 + * Fills pending matrix element *
  1142 + * ----------------------------------------------------------------------- *
  1143 + * If 'm_fill_val' is non-zero a pending matrix element exists that should *
  1144 + * be filled into (row,col)=(m_fill_row,m_fill_col). This routine performs *
  1145 + * the filling of the matrix with this element and resets 'm_fill_val' to *
  1146 + * zero. This routine allows for element-by-element filling of a sparse *
  1147 + * matrix. This is, of course, very time consuming and should in general *
  1148 + * be avoided. However, it allows to design a sparse matrix class that *
  1149 + * hides the matrix sparsity completely to the user. *
  1150 + ***************************************************************************/
  1151 +void GSparseMatrix::fill_pending(void)
  1152 +{
  1153 + // If we have a pending element then fill it into the matrix
  1154 + if (m_fill_val != 0.0) {
  1155 +
  1156 + // Debugging
  1157 + #if defined(G_DEBUG_SPARSE_PENDING) || defined(G_DEBUG_SPARSE_INSERTION)
  1158 + cout << "GSparseMatrix::fill_pending(): pending value " <<
  1159 + m_fill_val << " will be filled in location (" <<
  1160 + m_fill_row << "," << m_fill_col << ")" << endl;
  1161 + #endif
  1162 +
  1163 + // If there are so far no elements in the matrix then append element ...
  1164 + int inx_insert;
  1165 + if (m_elements == 0)
  1166 + inx_insert = 0;
  1167 +
  1168 + // ... otherwise search for index to insert
  1169 + else {
  1170 + int* ptr_colstart = m_colstart + m_fill_col;
  1171 + int i_start = *ptr_colstart++;
  1172 + int i_stop = *ptr_colstart;
  1173 + int* ptr_rowinx = m_rowinx + i_start;
  1174 + for (inx_insert = i_start; inx_insert < i_stop; ++inx_insert) {
  1175 + int row_test = *ptr_rowinx++;
  1176 + if (row_test > m_fill_row) {
  1177 + break;
  1178 + }
  1179 + }
  1180 + }
  1181 +
  1182 + // Allocate memory for new element
  1183 + alloc_elements(inx_insert, 1);
  1184 +
  1185 + // Insert element
  1186 + m_data[inx_insert] = m_fill_val;
  1187 + m_rowinx[inx_insert] = m_fill_row;
  1188 +
  1189 + // Update column start indices
  1190 + for (int col = m_fill_col+1; col <= m_cols; ++col)
  1191 + m_colstart[col] += 1;
  1192 +
  1193 + // Reset fill value
  1194 + m_fill_val = 0.0;
  1195 + m_fill_row = 0;
  1196 + m_fill_col = 0;
  1197 +
  1198 + // Debugging: show sparse matrix after filling
  1199 + #if defined(G_DEBUG_SPARSE_PENDING) || defined(G_DEBUG_SPARSE_INSERTION)
  1200 + cout << " Data: ";
  1201 + for (int i = 0; i < m_elements; ++i)
  1202 + cout << m_data[i] << " ";
  1203 + cout << endl << " Row.: ";
  1204 + for (int i = 0; i < m_elements; ++i)
  1205 + cout << m_rowinx[i] << " ";
  1206 + cout << endl << " Col.: ";
  1207 + for (int i = 0; i < m_cols+1; ++i)
  1208 + cout << m_colstart[i] << " ";
  1209 + cout << endl;
  1210 + #endif
  1211 +
  1212 + } // endif: a pending matrix element was found
  1213 +
  1214 +}
  1215 +
  1216 +
  1217 +/***************************************************************************
  1218 + * Allocate memory for new matrix elements *
  1219 + * ----------------------------------------------------------------------- *
  1220 + * Inserts a memory allocation for 'num' elements at the index 'start'. *
  1221 + * The new elements are filled with 0.0 and the corresponding row indices *
  1222 + * are set to 0. *
  1223 + * NOTE: This routine does not take care of updating 'm_colstart'. This *
  1224 + * has to be done by the client. *
  1225 + ***************************************************************************/
  1226 +void GSparseMatrix::alloc_elements(int start, int num)
  1227 +{
  1228 + // Continue only if we need memory
  1229 + if (num > 0) {
  1230 +
  1231 + // If start is after the end the append memory
  1232 + if (start > m_elements)
  1233 + start = m_elements;
  1234 +
  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 + }
  1247 +
  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 + }
  1253 +
  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 + }
  1259 +
  1260 + // Delete old memory
  1261 + if (m_data != NULL) delete [] m_data;
  1262 + if (m_rowinx != NULL) delete [] m_rowinx;
  1263 +
  1264 + // Update pointers to new memory and update element counter
  1265 + m_data = new_data;
  1266 + m_rowinx = new_rowinx;
  1267 + m_elements += num;
  1268 +
  1269 + } // endif: needed new memory
  1270 +
  1271 +}
  1272 +
  1273 +
  1274 +/***************************************************************************
  1275 + * Free memory for obsolete matrix elements *
  1276 + * ----------------------------------------------------------------------- *
  1277 + * Free memory for 'num' elements starting from index 'start'. *
  1278 + * NOTE: This routine does not take care of updating 'm_colstart'. This *
  1279 + * has to be done by the client. *
  1280 + ***************************************************************************/
  1281 +void GSparseMatrix::free_elements(int start, int num)
  1282 +{
  1283 + // Continue only if we need to free memory and if start is within the
  1284 + // range
  1285 + if (num > 0 && start < m_elements) {
  1286 +
  1287 + // Determine the new size of the matrix. If there are no elements then
  1288 + // simply delete all matrix elements ...
  1289 + int new_size = m_elements - num;
  1290 + if (new_size < 1) {
  1291 + if (m_data != NULL) delete [] m_data;
  1292 + if (m_rowinx != NULL) delete [] m_rowinx;
  1293 + m_data = NULL;
  1294 + m_rowinx = NULL;
  1295 + m_elements = 0;
  1296 + }
  1297 +
  1298 + // ... otherwise shrink the array
  1299 + else {
  1300 +
  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);
  1307 +
  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 + }
  1313 +
  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;
  1328 +
  1329 + } // endif: array shrinkage needed
  1330 + } // endif: needed new memory
  1331 +
  1332 +}
  1333 +
  1334 +
  1335 +/***************************************************************************
  1336 + * remove_zero_row_col *
  1337 + * ----------------------------------------------------------------------- *
  1338 + * Remove all rows and columns that contain only zeros from matrix. This *
  1339 + * function is needed for compressed matrix factorisation. The resulting *
  1340 + * matrix has reduced size (# of rows and columns) and dimensions (# of *
  1341 + * elements). Note that the physical memory is not reduced by the routine. *
  1342 + ***************************************************************************/
  1343 +void GSparseMatrix::remove_zero_row_col(void)
  1344 +{
  1345 + // Dump header
  1346 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1347 + cout << "GSparseMatrix::remove_zero_row_col" << endl;
  1348 + #endif
  1349 +
  1350 + // Fill pending value in matrix
  1351 + fill_pending();
  1352 +
  1353 + // Select non-zero rows and columns of matrix
  1354 + select_non_zero();
  1355 +
  1356 + // Stop if there is no compression
  1357 + if (m_rows == m_num_rowsel && m_cols == m_num_colsel)
  1358 + return;
  1359 +
  1360 + // Raise exception if all matrix elements are zero
  1361 + if (m_num_rowsel < 1 || m_num_colsel < 1)
  1362 + throw matrix_zero("GSparseMatrix::remove_zero_row_col()");
  1363 +
  1364 + // Allocate row mapping array
  1365 + int* row_map = new int[m_rows];
  1366 + if (row_map == NULL)
  1367 + throw mem_alloc("GSparseMatrix::remove_zero_row_col()", m_rows);
  1368 +
  1369 + // Setup row mapping array that maps original matrix rows into compressed
  1370 + // matrix rows. An entry of -1 indicates that the row should be dropped
  1371 + for (int row = 0; row < m_rows; ++row)
  1372 + row_map[row] = -1;
  1373 + for (int c_row = 0; c_row < m_num_rowsel; ++c_row)
  1374 + row_map[m_rowsel[c_row]] = c_row;
  1375 +
  1376 + // Initialise pointers to compressed array
  1377 + double* d_data = m_data;
  1378 + int* d_rowinx = m_rowinx;
  1379 +
  1380 + // Initialise column start of first column to zero
  1381 + m_colstart[0] = 0;
  1382 +
  1383 + // Dump column start array
  1384 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1385 + cout << " before compression:";
  1386 + for (int col = 0; col <= m_cols; ++col)
  1387 + cout << " " << m_colstart[col];
  1388 + cout << endl;
  1389 + #endif
  1390 +
  1391 + // Loop over all columns of compressed matrix
  1392 + for (int c_col = 0; c_col < m_num_colsel; ++c_col) {
  1393 +
  1394 + // Get index range for elements in original matrix
  1395 + int i_start = m_colstart[m_colsel[c_col]];
  1396 + int i_stop = m_colstart[m_colsel[c_col]+1];
  1397 +
  1398 + // Initialise number of element counter for the compressed column
  1399 + int num = 0;
  1400 +
  1401 + // Loop over all elements in original column
  1402 + int c_row;
  1403 + for (int i = i_start; i < i_stop; ++i) {
  1404 + if ((c_row = row_map[m_rowinx[i]]) >= 0) {
  1405 + *d_data++ = m_data[i];
  1406 + *d_rowinx++ = c_row;
  1407 + num++;
  1408 + }
  1409 + }
  1410 +
  1411 + // Update column stop
  1412 + m_colstart[c_col+1] = m_colstart[c_col] + num;
  1413 +
  1414 + } // endfor: looped over all columns of compressed matrix
  1415 +
  1416 + // Dump column start array
  1417 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1418 + cout << " after compression :";
  1419 + for (int c_col = 0; c_col <= m_num_colsel; ++c_col)
  1420 + cout << " " << m_colstart[c_col];
  1421 + cout << endl;
  1422 + #endif
  1423 +
  1424 + // Free row mapping array
  1425 + delete [] row_map;
  1426 +
  1427 + // Update matrix attributes
  1428 + m_rows = m_num_rowsel;
  1429 + m_cols = m_num_colsel;
  1430 + m_elements = m_colstart[m_num_colsel];
  1431 +
  1432 + // Return
  1433 + return;
  1434 +}
  1435 +
  1436 +
  1437 +/***************************************************************************
  1438 + * insert_zero_row_col *
  1439 + * ----------------------------------------------------------------------- *
  1440 + * Insert zero rows and columns into matrix. Since for a sparse matrix *
  1441 + * this does not require any allocation of additional memory, the data are *
  1442 + * not moved by this function, but the pointers are re-arranged. *
  1443 + ***************************************************************************/
  1444 +void GSparseMatrix::insert_zero_row_col(int rows, int cols)
  1445 +{
  1446 + // Dump header
  1447 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1448 + cout << "GSparseMatrix::insert_zero_row_col(" << rows << "," << cols <<
  1449 + ")" << endl;
  1450 + #endif
  1451 +
  1452 + // Fill pending value in matrix
  1453 + fill_pending();
  1454 +
  1455 + // Stop if there is no insertion
  1456 + if (m_rows == rows && m_cols == cols)
  1457 + return;
  1458 +
  1459 + // If row selection exists then restore row indices
  1460 + if (m_rowsel != NULL) {
  1461 + for (int i = 0; i < m_elements; ++i)
  1462 + m_rowinx[i] = m_rowsel[m_rowinx[i]];
  1463 + }
  1464 +
  1465 + // Dump column start array
  1466 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1467 + cout << " before restoration:";
  1468 + for (int c_col = 0; c_col <= m_num_colsel; ++c_col)
  1469 + cout << " " << m_colstart[c_col];
  1470 + cout << endl;
  1471 + #endif
  1472 +
  1473 + // If column selection exists then restore column counters
  1474 + if (m_colsel != NULL) {
  1475 + int col_stop = cols - 1;
  1476 + for (int c_col = m_num_colsel-1; c_col > 0; --c_col) {
  1477 + int col_start = m_colsel[c_col-1] + 1;
  1478 + int col_value = m_colstart[c_col];
  1479 + for (int col = col_start; col <= col_stop; ++col)
  1480 + m_colstart[col] = col_value;
  1481 + col_stop = col_start - 1;
  1482 + }
  1483 + m_colstart[cols] = m_elements;
  1484 + }
  1485 +
  1486 + // Dump column start array
  1487 + #if defined(G_DEBUG_SPARSE_COMPRESSION)
  1488 + cout << " after restoration :";
  1489 + for (int col = 0; col <= cols; ++col)
  1490 + cout << " " << m_colstart[col];
  1491 + cout << endl;
  1492 + #endif
  1493 +
  1494 + // Update matrix attributes
  1495 + m_rows = rows;
  1496 + m_cols = cols;
  1497 +
  1498 + // Return
  1499 + return;
  1500 +}
  1501 +
  1502 +
  1503 +/***************************************************************************
  1504 + * cs_transpose *
  1505 + * ----------------------------------------------------------------------- *
  1506 + * Transpose matrix. The flag 'values' allows to avoid copying the actual *
  1507 + * data values. This allows to perform a logical matrix transposition, as *
  1508 + * needed by the symbolic matrix analysis class. *
  1509 + ***************************************************************************/
  1510 +GSparseMatrix GSparseMatrix::cs_transpose(GSparseMatrix* m, int values)
  1511 +{
  1512 + // Fill pending value in input matrix
  1513 + m->fill_pending();
  1514 +
  1515 + // Declare and allocate result matrix
  1516 + GSparseMatrix result(m->m_cols, m->m_rows, m->m_elements);
  1517 +
  1518 + // Allocate and initialise workspace
  1519 + int wrk_size = m->m_rows;
  1520 + int* wrk_int = new int[wrk_size];
  1521 + if (wrk_int == NULL)
  1522 + throw mem_alloc("GSparseMatrix::cs_transpose(GSparseMatrix*, int)",
  1523 + wrk_size);
  1524 + for (int i = 0; i < wrk_size; i++)
  1525 + wrk_int[i] = 0;
  1526 +
  1527 + // Setup the number of non-zero elements in each row
  1528 + for (int p = 0; p < m->m_elements; p++)
  1529 + wrk_int[m->m_rowinx[p]]++;
  1530 +
  1531 + // Set row pointers. To use a GSparseSymbolic function we have to
  1532 + // allocate and object (but this does not take memory)
  1533 + cs_cumsum(result.m_colstart, wrk_int, m->m_rows);
  1534 +
  1535 + // Case A: Normal transponse, including assignment of values
  1536 + if (values) {
  1537 + for (int col = 0; col < m->m_cols; col++) {
  1538 + for (int p = m->m_colstart[col] ; p < m->m_colstart[col+1] ; p++) {
  1539 + int i = wrk_int[m->m_rowinx[p]]++;
  1540 + result.m_rowinx[i] = col;
  1541 + result.m_data[i] = m->m_data[p] ;
  1542 + }
  1543 + }
  1544 + }
  1545 +
  1546 + // Case B: Logical transponse, no assignment of values is performed
  1547 + else {
  1548 + for (int col = 0; col < m->m_cols; col++) {
  1549 + for (int p = m->m_colstart[col] ; p < m->m_colstart[col+1] ; p++)
  1550 + result.m_rowinx[wrk_int[m->m_rowinx[p]]++] = col;
  1551 + }
  1552 + }
  1553 +
  1554 + // Return transponse matrix
  1555 + return result;
  1556 +
  1557 +}
  1558 +
  1559 +
  1560 +/*==========================================================================
  1561 + = =
  1562 + = GSparseMatrix friends =
  1563 + = =
  1564 + ==========================================================================*/
  1565 +
  1566 +/***************************************************************************
  1567 + * Output operator *
  1568 + ***************************************************************************/
  1569 +ostream& operator<< (ostream& os, const GSparseMatrix& m)
  1570 +{
  1571 + // Put header in stream
  1572 + os << "=== GSparseMatrix ===" << endl;
  1573 + if (m.m_rowsel != NULL)
  1574 + os << " Number of rows ............: " << m.m_rows << " (compressed " <<
  1575 + m.m_num_rowsel << ")" << endl;
  1576 + else
  1577 + os << " Number of rows ............: " << m.m_rows << endl;
  1578 + if (m.m_colsel != NULL)
  1579 + os << " Number of columns .........: " << m.m_cols << " (compressed " <<
  1580 + m.m_num_colsel << ")" << endl;
  1581 + else
  1582 + os << " Number of columns .........: " << m.m_cols << endl;
  1583 + os << " Number of non-zero elements: " << m.m_elements << endl;
  1584 + os << " Sparse matrix fill ........: " << m.fill() << endl;
  1585 +
  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;
  1596 + }
  1597 +
  1598 + // If there is a row compression the show scheme
  1599 + if (m.m_rowsel != NULL) {
  1600 + os << endl << " Row selection ..:";
  1601 + for (int row = 0; row < m.m_num_rowsel; ++row)
  1602 + os << " " << m.m_rowsel[row];
  1603 + }
  1604 +
  1605 + // If there is a column compression the show scheme
  1606 + if (m.m_colsel != NULL) {
  1607 + os << endl << " Column selection:";
  1608 + for (int col = 0; col < m.m_num_colsel; ++col)
  1609 + os << " " << m.m_colsel[col];
  1610 + }
  1611 +
  1612 + // If there is a symbolic decomposition then put it also in the stream
  1613 + if (m.m_symbolic != NULL) {
  1614 + os << endl << *((GSparseSymbolic*)m.m_symbolic);
  1615 + }
  1616 +
  1617 + // If there is a numeric decomposition then put it also in the stream
  1618 + if (m.m_numeric != NULL) {
  1619 + os << endl << *((GSparseNumeric*)m.m_numeric);
  1620 + }
  1621 +
  1622 + // Return output stream
  1623 + return os;
  1624 +}
  1625 +
  1626 +
  1627 +/***************************************************************************
  1628 + * Matrix absolute values *
  1629 + ***************************************************************************/
  1630 +GSparseMatrix fabs(const GSparseMatrix& m)
  1631 +{
  1632 + // Define result matrix
  1633 + GSparseMatrix result = m;
  1634 +
  1635 + // Fill pending element
  1636 + result.fill_pending();
  1637 +
  1638 + // Convert all elements to absolute values
  1639 + for (int i = 0; i < result.m_elements; ++i)
  1640 + result.m_data[i] = fabs(result.m_data[i]);
  1641 +
  1642 + // Return result
  1643 + return result;
  1644 +}
  1645 +
  1646 +
  1647 +/*==========================================================================
  1648 + = =
  1649 + = GSparseMatrix exception classes =
  1650 + = =
  1651 + ==========================================================================*/
  1652 +
  1653 +
  1654 +/*==========================================================================
  1655 + = =
  1656 + = Other functions used by GSparseMatrix =
  1657 + = =
  1658 + ==========================================================================*/
  1659 +
  1660 +/***************************************************************************
  1661 + * cs_cumsum *
  1662 + * ----------------------------------------------------------------------- *
  1663 + * Evaluate p[0..n] = cumulative sum of c[0..n-1] *
  1664 + * ----------------------------------------------------------------------- *
  1665 + * Input: c[0..n-1] integer array of n elements *
  1666 + * Output: nz2 cumulative sum of c[0..n-1] *
  1667 + * p[0..n] integer array of n+1 elements *
  1668 + * c[0..n-1] holds p[0..n-1] on output *
  1669 + ***************************************************************************/
  1670 +double cs_cumsum(int* p, int* c, int n)
  1671 +{
  1672 + // Signal error if one of the input pointers is NULL
  1673 + if (!p || !c) return (-1);
  1674 +
  1675 + // Initialise sums (integer and double)
  1676 + int nz = 0;
  1677 + double nz2 = 0.0;
  1678 +
  1679 + // Evaluate p[0..n] = cumulative sum of c[0..n-1]
  1680 + for (int i = 0; i < n; ++i) {
  1681 + p[i] = nz ;
  1682 + nz += c[i];
  1683 + nz2 += c[i]; // also in double to avoid int overflow
  1684 + c[i] = p[i]; // also copy p[0..n-1] back into c[0..n-1]
  1685 + }
  1686 + p[n] = nz ;
  1687 +
  1688 + // Return cumulative sum of c[0..n-1]
  1689 + return nz2;
  1690 +}
  1691 +
... ...
src/GSparseMatrix.hpp
1 1 /***************************************************************************
2   - * GSymMatrix.hpp - symmetric matrix class *
  2 + * GSparseMatrix.hpp - sparse matrix class *
3 3 * ----------------------------------------------------------------------- *
4 4 * copyright : (C) 2006 by Jurgen Knodlseder *
5 5 * ----------------------------------------------------------------------- *
... ... @@ -11,8 +11,8 @@
11 11 * *
12 12 ***************************************************************************/
13 13  
14   -#ifndef GSYMMATRIX_HPP
15   -#define GSYMMATRIX_HPP
  14 +#ifndef GSPARSEMATRIX_HPP
  15 +#define GSPARSEMATRIX_HPP
16 16  
17 17 /* __ Includes ___________________________________________________________ */
18 18 #include "GException.hpp"
... ... @@ -27,251 +27,248 @@ using namespace std;
27 27 /* __ Structures _________________________________________________________ */
28 28  
29 29 /* __ Prototypes _________________________________________________________ */
  30 +double cs_cumsum(int* p, int* c, int n);
30 31  
31 32  
32 33 /***************************************************************************
33   - * GSymMatrix class definition *
  34 + * GSparseMatrix class definition *
34 35 ***************************************************************************/
35   -class GSymMatrix : public GMatrix {
36   - // Operator friends
37   - friend GSymMatrix operator* (const double &a, const GSymMatrix &b);
  36 +class GSparseMatrix : public GMatrix {
  37 + // Friend classes
  38 + friend class GSparseSymbolic;
  39 + friend class GSparseNumeric;
  40 +
  41 + // Binary operator friends
  42 + friend GSparseMatrix operator* (const double& a, const GSparseMatrix& b);
  43 + friend GSparseMatrix operator* (const GSparseMatrix& a, const double& b);
  44 + friend GSparseMatrix operator/ (const GSparseMatrix& a, const double& b);
38 45  
39 46 // I/O friends
40   - // ...
41   -
  47 + friend ostream& operator<< (ostream& os, const GSparseMatrix& m);
  48 +
42 49 // Friend functions
43   - friend GSymMatrix transpose(const GSymMatrix &m);
44   - friend GSymMatrix cholesky_decompose(const GSymMatrix &m);
45   - friend GMatrix full(const GSymMatrix &m);
46   - friend GMatrix lower_triangle(const GSymMatrix &m);
47   - friend GMatrix upper_triangle(const GSymMatrix &m);
  50 + friend GSparseMatrix transpose(const GSparseMatrix& m);
  51 + friend GSparseMatrix fabs(const GSparseMatrix& m);
  52 + friend GSparseMatrix cholesky_decompose(const GSparseMatrix& m, int compress = 1);
  53 + friend GSparseMatrix cholesky_invert(const GSparseMatrix& m, int compress = 1);
  54 +
48 55 public:
49 56 // Constructors and destructors (not inherited)
50   - GSymMatrix(unsigned rows, unsigned cols);
51   - ~GSymMatrix() { }
  57 + GSparseMatrix(int rows, int cols, int elements = 0);
  58 + GSparseMatrix(const GSparseMatrix& m);
  59 + virtual ~GSparseMatrix();
52 60  
53 61 // Matrix element access operators
54   - double& operator() (unsigned row, unsigned col);
55   - const double& operator() (unsigned row, unsigned col) const;
  62 + virtual double& operator() (int row, int col);
  63 + virtual const double& operator() (int row, int col) const;
56 64  
57 65 // Matrix assignment operators (not inherited)
58   - GSymMatrix& operator= (const GSymMatrix& m);
59   - GSymMatrix& operator= (const double& d);
60   -
61   - // Specific matrix operators (structure dependent)
62   - GSymMatrix operator+ (const GSymMatrix& m) const;
63   - GSymMatrix operator- (const GSymMatrix& m) const;
64   - GSymMatrix operator* (const GSymMatrix& m) const;
65   - GVector operator* (const GVector& v) const;
66   - GSymMatrix operator* (const double& d) const;
67   - GSymMatrix operator/ (const double& d) const;
68   - GSymMatrix operator- () const;
69   -
70   - // Specific matrix functions
71   - void transpose(); // Inplace transpose of matrix
72   - void cholesky_decompose(); // Inplace Cholesky decomposition
73   -
74   - // Exception: Matrix not symmetric
75   - class not_sym : public GException {
76   - public:
77   - not_sym(string origin, unsigned cols, unsigned rows);
78   - };
79   -
80   - // Exception: Matrix not positive definite
81   - class not_pos_definite : public GException {
82   - public:
83   - not_pos_definite(string origin, unsigned row, double sum);
84   - };
  66 + virtual GSparseMatrix& operator= (const GSparseMatrix& m);
  67 +
  68 + // Binary operators
  69 + virtual GSparseMatrix operator+ (const GSparseMatrix& m) const;
  70 + virtual GSparseMatrix operator- (const GSparseMatrix& m) const;
  71 + virtual GSparseMatrix operator* (const GSparseMatrix& m) const;
  72 + virtual GVector operator* (const GVector& v) const;
  73 + virtual int operator== (const GSparseMatrix& m) const;
  74 + virtual int operator!= (const GSparseMatrix& m) const;
  75 +
  76 + // Unary operators
  77 + GSparseMatrix operator- () const;
  78 + virtual GSparseMatrix& operator+= (const GSparseMatrix& m);
  79 + virtual GSparseMatrix& operator-= (const GSparseMatrix& m);
  80 + virtual GSparseMatrix& operator*= (const GSparseMatrix& m);
  81 + virtual GSparseMatrix& operator*= (const double& d);
  82 + virtual GSparseMatrix& operator/= (const double& d);
  83 +
  84 + // Matrix functions
  85 + // USE_BASE: virtual int rows() const { return m_rows; }
  86 + // USE_BASE: virtual int cols() const { return m_cols; }
  87 + virtual double fill() const { return (double(m_elements)/double(m_rows*m_cols)); }
  88 + virtual double min() const;
  89 + virtual double max() const;
  90 + virtual double sum() const;
  91 + virtual void transpose();
  92 + virtual GVector extract_row(int row) const;
  93 + virtual GVector extract_col(int col) const;
  94 + virtual void insert_col(const GVector& v, int col);
  95 + virtual void add_col(const GVector& v, int col);
  96 + virtual GMatrix convert_to_full() const;
  97 + //TBD virtual GMatrix extract_lower_triangle() const;
  98 + //TBD virtual GMatrix extract_upper_triangle() const;
  99 + virtual void cholesky_decompose(int compress = 1);
  100 + virtual GVector cholesky_solver(const GVector& v, int compress = 1);
  101 + virtual void cholesky_invert(int compress = 1);
  102 +
85 103 private:
  104 + // Private functions
  105 + int get_index(int row, int col) const;
  106 + void fill_pending(void);
  107 + void alloc_elements(int start, int num);
  108 + void free_elements(int start, int num);
  109 + void remove_zero_row_col(void);
  110 + void insert_zero_row_col(int rows, int cols);
  111 + GSparseMatrix cs_transpose(GSparseMatrix *m, int values);
  112 +
  113 + // Private data members
  114 + int* m_rowinx; // Row-indices of all elements
  115 + double m_zero; // The zero element (needed for data access)
  116 + double m_fill_val; // Element to be filled
  117 + int m_fill_row; // Row into which element needs to be filled
  118 + int m_fill_col; // Column into which element needs to be filled
  119 + void* m_symbolic; // Holds GSparseSymbolic object after decomposition
  120 + void* m_numeric; // Holds GSparseNumeric object after decomposition
86 121 };
87 122  
88 123  
89 124 /***************************************************************************
90 125 * Inline members that override base class members *
91 126 ***************************************************************************/
92   -// Matrix assignment operator: GSymMatrix = GSymMatrix
93   -inline
94   -GSymMatrix& GSymMatrix::operator= (const GSymMatrix& m)
95   -{
96   - if (this != &m)
97   - this->GMatrix::operator=(m);
98   -}
99   -
100   -// Scalar assignment operator: GSymMatrix = double
  127 +// Matrix element access operator
101 128 inline
102   -GSymMatrix& GSymMatrix::operator= (const double& d)
103   -{
104   - this->GMatrix::operator=(d);
105   -}
106   -
107   -// Matrix element access operator: GSymMatrix(row,col)
108   -inline
109   -double& GSymMatrix::operator() (unsigned row, unsigned col)
  129 +double& GSparseMatrix::operator() (int row, int col)
110 130 {
111   - #if G_RANGE_CHECK
  131 + #if defined(G_RANGE_CHECK)
112 132 if (row >= m_rows || col >= m_cols)
113   - throw out_of_range("GSymMatrix access", row, col, m_rows, m_cols);
  133 + throw out_of_range("GSparseMatrix access", row, col, m_rows, m_cols);
114 134 #endif
115   - unsigned inx = (row >= col) ? m_colstart[col]+(row-col) : m_colstart[row]+(col-row);
116   - return m_data[inx];
  135 + fill_pending();
  136 + int inx = get_index(row,col);
  137 + double* value;
  138 + if (inx < 0) {
  139 + value = &m_fill_val;
  140 + m_fill_row = row;
  141 + m_fill_col = col;
  142 + }
  143 + else
  144 + value = &(m_data[inx]);
  145 + return *value;
117 146 }
118 147  
119   -// Matrix element access operator (const version): GSymMatrix(row,col)
  148 +// Matrix element access operator (const version)
  149 +// We need here the zero element to return also a pointer for 0.0 entry that is
  150 +// not stored. Since we have the const version we don't have to care about
  151 +// modification of this zero value.
120 152 inline
121   -const double& GSymMatrix::operator() (unsigned row, unsigned col) const
  153 +const double& GSparseMatrix::operator() (int row, int col) const
122 154 {
123   - #if G_RANGE_CHECK
  155 + #if defined(G_RANGE_CHECK)
124 156 if (row >= m_rows || col >= m_cols)
125   - throw out_of_range("GSymMatrix access", row, col, m_rows, m_cols);
  157 + throw out_of_range("GSparseMatrix access", row, col, m_rows, m_cols);
126 158 #endif
127   - unsigned inx = (row >= col) ? m_colstart[col]+(row-col) : m_colstart[row]+(col-row);
128   - return m_data[inx];
  159 + int inx = get_index(row,col);
  160 + double* value;
  161 + if (inx < 0)
  162 + value = (double*)&m_zero;
  163 + else if (inx == m_elements)
  164 + value = (double*)&m_fill_val;
  165 + else
  166 + value = (double*)&(m_data[inx]);
  167 + return *value;
129 168 }
130 169  
131   -// Matrix addition: GSymMatrix + GSymMatrix
  170 +// Binary matrix addition
132 171 inline
133   -GSymMatrix GSymMatrix::operator+ (const GSymMatrix& m) const
  172 +GSparseMatrix GSparseMatrix::operator+ (const GSparseMatrix& m) const
134 173 {
135   - GSymMatrix result = *this;
  174 + GSparseMatrix result = *this;
136 175 result += m;
137 176 return result;
138 177 }
139 178  
140   -// Matrix subtraction: GSymMatrix - GSymMatrix
  179 +// Binary matrix subtraction
141 180 inline
142   -GSymMatrix GSymMatrix::operator- (const GSymMatrix& m) const
  181 +GSparseMatrix GSparseMatrix::operator- (const GSparseMatrix& m) const
143 182 {
144   - GSymMatrix result = *this;
  183 + GSparseMatrix result = *this;
145 184 result -= m;
146 185 return result;
147 186 }
148 187  
149   -// Matrix multiplication: GSymMatrix * GSymMatrix
150   -inline
151   -GSymMatrix GSymMatrix::operator* (const GSymMatrix& m) const
152   -{
153   - #if G_RANGE_CHECK
154   - if (m_cols != m.m_rows)
155   - throw GMatrix::dim_mult_mismatch("GSymMatrix multiplication", m_cols, m.m_rows);
156   - #endif
157   - GSymMatrix result(m_rows,m.m_cols);
158   - for (unsigned row = 0; row < m_rows; ++row) {
159   - for (unsigned col = 0; col < m.m_cols; ++col) {
160   - double sum = 0.0;
161   - for (unsigned i = 0; i < m_cols; ++i)
162   - sum += (*this)(row,i)*m(i,col);
163   - result(row,col) = sum;
164   - }
165   - }
166   - return result;
167   -}
168   -
169   -// Matrix/Vector multiplication: GSymMatrix * GVector
  188 +// Binary matrix multiplication
170 189 inline
171   -GVector GSymMatrix::operator* (const GVector& v) const
172   -{
173   - return (this->GMatrix::operator*(v));
174   -}
175   -
176   -// Matrix scaling: GSymMatrix * double
177   -inline
178   -GSymMatrix GSymMatrix::operator* (const double &d) const
179   -{
180   - GSymMatrix result = (*this);
181   - result *= d;
182   - return result;
183   -}
184   -
185   -// Matrix inverse scaling: GSymMatrix * double
186   -inline
187   -GSymMatrix GSymMatrix::operator/ (const double &d) const
  190 +GSparseMatrix GSparseMatrix::operator* (const GSparseMatrix& m) const
188 191 {
189   - GSymMatrix result = (*this);
190   - result /= d;
  192 + GSparseMatrix result = *this;
  193 + result *= m;
191 194 return result;
192 195 }
193 196  
194   -// Unary minus operator
  197 +// Unary scalar multiplication
195 198 inline
196   -GSymMatrix GSymMatrix::operator- ( ) const
  199 +GSparseMatrix& GSparseMatrix::operator*= (const double& d)
197 200 {
198   - GSymMatrix result = *this;
199   - for (unsigned i = 0; i < m_elements; ++i)
200   - result.m_data[i] = -result.m_data[i];
201   - return result;
  201 + fill_pending();
  202 + this->GMatrix::operator*=(d);
202 203 }
203 204  
204   -// Matrix transpose
  205 +// Unary scalar division
205 206 inline
206   -void GSymMatrix::transpose()
  207 +GSparseMatrix& GSparseMatrix::operator/= (const double& d)
207 208 {
208   - return;
  209 + fill_pending();
  210 + this->GMatrix::operator/=(d);
209 211 }
210 212  
211 213  
212   -
213 214 /***************************************************************************
214 215 * Inline friends *
215 216 ***************************************************************************/
216   -// Matrix scaling: double * GSymMatrix
  217 +// Binary matrix scaling (matrix is left operand)
217 218 inline
218   -GSymMatrix operator* (const double& a, const GSymMatrix& b)
  219 +GSparseMatrix operator* (const GSparseMatrix& a, const double& b)
219 220 {
220   - GSymMatrix result = b;
221   - result *= a;
  221 + GSparseMatrix result = a;
  222 + result.fill_pending();
  223 + result *= b;
222 224 return result;
223 225 }
224 226  
225   -// Matrix transpose: transpose(GSymMatrix)
  227 +// Binary matrix scaling (matrix is right operand)
226 228 inline
227   -GSymMatrix transpose(const GSymMatrix &m)
  229 +GSparseMatrix operator* (const double& a, const GSparseMatrix& b)
228 230 {
229   - return m;
  231 + GSparseMatrix result = b;
  232 + result.fill_pending();
  233 + result *= a;
  234 + return result;
230 235 }
231 236  
232   -// Cholesky decomposition: cholesky_decompose(GSymMatrix)
  237 +// Binary matrix division (matrix is left operand)
233 238 inline
234   -GSymMatrix cholesky_decompose(const GSymMatrix &m)
  239 +GSparseMatrix operator/ (const GSparseMatrix& a, const double& b)
235 240 {
236   - GSymMatrix result = m;
237   - result.cholesky_decompose();
  241 + GSparseMatrix result = a;
  242 + result.fill_pending();
  243 + result /= b;
238 244 return result;
239 245 }
240 246  
241   -// Convert symmetric matrix into full matrix: full(GSymMatrix)
  247 +// Matrix transpose function
242 248 inline
243   -GMatrix full(const GSymMatrix& m)
  249 +GSparseMatrix transpose(const GSparseMatrix& m)
244 250 {
245   - GMatrix result(m.m_rows,m.m_cols);
246   - for (unsigned row = 0; row < m.m_rows; ++row) {
247   - for (unsigned col = 0; col < m.m_cols; ++col)
248   - result(row,col) = m(row,col);
249   - }
  251 + GSparseMatrix result = m;
  252 + result.transpose();
250 253 return result;
251 254 }
252 255  
253   -// Convert symmetric matrix into lower triangle full matrix: lower_triangle(GSymMatrix)
  256 +// Cholesky decomposition
254 257 inline
255   -GMatrix lower_triangle(const GSymMatrix &m)
  258 +GSparseMatrix cholesky_decompose(const GSparseMatrix& m, int compress)
256 259 {
257   - GMatrix result(m.m_rows,m.m_cols);
258   - for (unsigned row = 0; row < m.m_rows; ++row) {
259   - for (unsigned col = 0; col <= row; ++col)
260   - result(row,col) = m.m_data[m.m_colstart[col]+(row-col)];
261   - }
  260 + GSparseMatrix result = m;
  261 + result.cholesky_decompose(compress);
262 262 return result;
263 263 }
264 264  
265   -// Convert symmetric matrix into upper triangle full matrix: lower_triangle(GSymMatrix)
  265 +// Matrix inversion using Cholesky decomposition
266 266 inline
267   -GMatrix upper_triangle(const GSymMatrix &m)
  267 +GSparseMatrix cholesky_invert(const GSparseMatrix& m, int compress)
268 268 {
269   - GMatrix result(m.m_rows,m.m_cols);
270   - for (unsigned row = 0; row < m.m_rows; ++row) {
271   - for (unsigned col = row; col < m.m_cols; ++col)
272   - result(row,col) = m.m_data[m.m_colstart[row]+(col-row)];
273   - }
  269 + GSparseMatrix result = m;
  270 + result.cholesky_invert(compress);
274 271 return result;
275 272 }
276 273  
277   -#endif /* GSYMMATRIX_HPP */
  274 +#endif /* GSPARSEMATRIX_HPP */
... ...
src/GSparseNumeric.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * GSparseNumeric.cpp - sparse matrix numeric analysis class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright : (C) 2006 by Jurgen Knodlseder *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software; you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation; either version 2 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + ***************************************************************************/
  13 +
  14 +/* __ Includes ___________________________________________________________ */
  15 +#include "GSparseSymbolic.hpp"
  16 +#include "GSparseNumeric.hpp"
  17 +
  18 +/* __ Namespaces _________________________________________________________ */
  19 +using namespace std;
  20 +
  21 +/* __ Macros _____________________________________________________________ */
  22 +#define CS_FLIP(i) (-(i)-2)
  23 +#define CS_MARK(w,j) { w [j] = CS_FLIP (w [j]) ; }
  24 +#define CS_MARKED(w,j) (w [j] < 0)
  25 +
  26 +
  27 +/*==========================================================================
  28 + = =
  29 + = GSparseNumeric constructors/destructors =
  30 + = =
  31 + ==========================================================================*/
  32 +
  33 +/***************************************************************************
  34 + * GSparseNumeric constructor *
  35 + ***************************************************************************/
  36 +GSparseNumeric::GSparseNumeric()
  37 +{
  38 + // Initialise private members for clean destruction
  39 + m_L = NULL;
  40 + m_U = NULL;
  41 + m_pinv = NULL;
  42 + m_B = NULL;
  43 + m_n_pinv = 0;
  44 + m_n_B = 0;
  45 +
  46 + // Return
  47 + return;
  48 +}
  49 +
  50 +
  51 +/***************************************************************************
  52 + * GSparseNumeric destructor *
  53 + ***************************************************************************/
  54 +GSparseNumeric::~GSparseNumeric()
  55 +{
  56 + // De-allocate only if memory has indeed been allocated
  57 + if (m_L != NULL) delete m_L;
  58 + if (m_U != NULL) delete m_U;
  59 + if (m_pinv != NULL) delete [] m_pinv;
  60 + if (m_B != NULL) delete [] m_B;
  61 +
  62 + // Return
  63 + return;
  64 +}
  65 +
  66 +
  67 +/*==========================================================================
  68 + = =
  69 + = GSparseNumeric operators =
  70 + = =
  71 + ==========================================================================*/
  72 +
  73 +/***************************************************************************
  74 + * GSparseNumeric assignment operator *
  75 + ***************************************************************************/
  76 +GSparseNumeric& GSparseNumeric::operator= (const GSparseNumeric& n)
  77 +{
  78 + // Execute only if object is not identical
  79 + if (this != &n) {
  80 +
  81 + // Initialise private members for clean destruction
  82 + m_L = NULL;
  83 + m_U = NULL;
  84 + m_pinv = NULL;
  85 + m_B = NULL;
  86 + m_n_pinv = 0;
  87 + m_n_B = 0;
  88 +
  89 + // Copy m_L if it exists
  90 + if (n.m_L != NULL)
  91 + m_L = new GSparseMatrix(*n.m_L);
  92 +
  93 + // Copy m_U if it exists
  94 + if (n.m_U != NULL)
  95 + m_U = new GSparseMatrix(*n.m_U);
  96 +
  97 + // Copy m_pinv array if it exists
  98 + if (n.m_pinv != NULL) {
  99 + m_pinv = new int[n.m_n_pinv];
  100 + if (m_pinv == NULL)
  101 + throw mem_alloc("GSparseNumeric::operator= (const GSparseNumeric&)",
  102 + n.m_n_pinv);
  103 + for (int i = 0; i < n.m_n_pinv; ++i)
  104 + m_pinv[i] = n.m_pinv[i];
  105 + m_n_pinv = n.m_n_pinv;
  106 + }
  107 +
  108 + // Copy m_B array if it exists
  109 + if (n.m_B != NULL) {
  110 + m_B = new double[n.m_n_B];
  111 + if (m_B == NULL)
  112 + throw mem_alloc("GSparseNumeric::operator= (const GSparseNumeric&)",
  113 + n.m_n_B);
  114 + for (int i = 0; i < n.m_n_B; ++i)
  115 + m_B[i] = n.m_B[i];
  116 + m_n_B = n.m_n_B;
  117 + }
  118 +
  119 + } // endif: object was not identical
  120 +
  121 + // Return
  122 + return *this;
  123 +}
  124 +
  125 +
  126 +/*==========================================================================
  127 + = =
  128 + = GSparseNumeric member functions =
  129 + = =
  130 + ==========================================================================*/
  131 +
  132 +/***************************************************************************
  133 + * cholesky_numeric_analysis *
  134 + * ----------------------------------------------------------------------- *
  135 + * L = chol (A, [pinv parent cp]), pinv is optional. This function *
  136 + * allocates the memory to hold the information. *
  137 + * ----------------------------------------------------------------------- *
  138 + * Input: A Sparse matrix *
  139 + * S Symbolic analysis of sparse matrix *
  140 + ***************************************************************************/
  141 +void GSparseNumeric::cholesky_numeric_analysis(GSparseMatrix& A,
  142 + const GSparseSymbolic& S)
  143 +{
  144 + // Return if arrays in the symbolic analysis have not been allocated
  145 + if (!S.m_cp || !S.m_parent) return;
  146 +
  147 + // Declare
  148 + double lki;
  149 + int top, i, p, k;
  150 +
  151 + // Assign input matrix attributes
  152 + int n = A.m_cols;
  153 +
  154 + // Allocate int workspace
  155 + int wrk_size = 2*n;
  156 + int* wrk_int = new int[wrk_size];
  157 + if (wrk_int == NULL)
  158 + throw mem_alloc(
  159 + "GSparseNumeric::cholesky_numeric_analysis(GSparseMatrix&, const GSparseSymbolic&)",
  160 + wrk_size);
  161 +
  162 + // Allocate double workspace
  163 + wrk_size = n;
  164 + double* wrk_double = new double[wrk_size];
  165 + if (wrk_double == NULL)
  166 + throw mem_alloc(
  167 + "GSparseNumeric::cholesky_numeric_analysis(GSparseMatrix&, const GSparseSymbolic&)",
  168 + wrk_size);
  169 +
  170 + // Assign pointers
  171 + int* cp = S.m_cp;
  172 + int* pinv = S.m_pinv;
  173 + int* parent = S.m_parent;
  174 +
  175 + // Assign C = A(p,p) where A and C are symmetric and the upper part stored
  176 + GSparseMatrix C = (pinv) ? S.cs_symperm(&A, pinv, 1) : (A);
  177 +
  178 + // Assign workspace pointer
  179 + int* c = wrk_int;
  180 + int* s = wrk_int + n;
  181 + double* x = wrk_double;
  182 +
  183 + // Assign C matrix pointers
  184 + int* Cp = C.m_colstart;
  185 + int* Ci = C.m_rowinx;
  186 + double* Cx = C.m_data;
  187 +
  188 + // Allocate L matrix
  189 + m_L = new GSparseMatrix(n,n,cp[n]);
  190 + if (m_L == NULL)
  191 + throw mem_alloc(
  192 + "GSparseNumeric::cholesky_numeric_analysis(GSparseMatrix&, const GSparseSymbolic&)",
  193 + 1);
  194 +
  195 + // Assign L matrix pointers
  196 + int* Lp = m_L->m_colstart;
  197 + int* Li = m_L->m_rowinx;
  198 + double* Lx = m_L->m_data;
  199 +
  200 + // Initialise column pointers of L and c
  201 + for (k = 0; k < n; ++k)
  202 + Lp[k] = c[k] = cp[k];
  203 +
  204 + // Compute L(:,k) for L*L' = C
  205 + for (k = 0; k < n; k++) {
  206 +
  207 + // Nonzero pattern of L(k,:)
  208 + top = cs_ereach(&C, k, parent, s, c); // find pattern of L(k,:)
  209 + x[k] = 0; // x (0:k) is now zero
  210 +
  211 + // x = full(triu(C(:,k)))
  212 + for (p = Cp[k]; p < Cp[k+1]; p++) {
  213 + if (Ci[p] <= k)
  214 + x[Ci[p]] = Cx[p];
  215 + }
  216 +
  217 + // d = C(k,k)
  218 + double d = x[k];
  219 +
  220 + // Clear x for k+1st iteration
  221 + x[k] = 0;
  222 +
  223 + // Triangular solve: Solve L(0:k-1,0:k-1) * x = C(:,k)
  224 + for ( ; top < n; top++) {
  225 + i = s[top]; // s [top..n-1] is pattern of L(k,:)
  226 + lki = x[i]/Lx[Lp[i]]; // L(k,i) = x (i) / L(i,i)
  227 + x[i] = 0; // clear x for k+1st iteration
  228 + for (p = Lp[i]+1; p < c[i]; p++)
  229 + x[Li[p]] -= Lx[p] * lki;
  230 + d -= lki * lki; // d = d - L(k,i)*L(k,i)
  231 + p = c [i]++ ;
  232 + Li[p] = k; // store L(k,i) in column i
  233 + Lx[p] = lki;
  234 + }
  235 +
  236 + // Compute L(k,k)
  237 + if (d <= 0)
  238 + throw GSparseMatrix::matrix_not_pos_definite(
  239 + "GSparseNumeric::cholesky_numeric_analysis(GSparseMatrix&, const GSparseSymbolic&)",
  240 + k, d);
  241 +
  242 + // Store L(k,k) = sqrt (d) in column k
  243 + p = c[k]++;
  244 + Li[p] = k;
  245 + Lx[p] = sqrt(d);
  246 + }
  247 +
  248 + // Finalize L
  249 + Lp[n] = cp[n];
  250 +
  251 + // Free workspace
  252 + delete [] wrk_int;
  253 + delete [] wrk_double;
  254 +
  255 + // Return void
  256 + return;
  257 +}
  258 +
  259 +
  260 +/*==========================================================================
  261 + = =
  262 + = GSparseNumeric private functions =
  263 + = =
  264 + ==========================================================================*/
  265 +
  266 +/***************************************************************************
  267 + * cs_ereach *
  268 + * ----------------------------------------------------------------------- *
  269 + * Find nonzero pattern of Cholesky L(k,1:k-1) using etree and *
  270 + * triu(A(:,k)) *
  271 + * ----------------------------------------------------------------------- *
  272 + * Input: A Sparse matrix *
  273 + * k Node *
  274 + * parent ... *
  275 + * s ... *
  276 + * w ... *
  277 + * Input: top Index, where s[top..n-1] contains pattern *
  278 + * of L(k,:); -1 if arrays have not been *
  279 + * allocated *
  280 + ***************************************************************************/
  281 +int GSparseNumeric::cs_ereach(const GSparseMatrix* A, int k,
  282 + const int* parent, int* s, int* w)
  283 +{
  284 + // Return -1 if arrays have not been allocated
  285 + if (!parent || !s || !w) return (-1);
  286 +
  287 + // Assign A matrix attributes and pointers
  288 + int n = A->m_cols;
  289 + int top = n;
  290 + int* Ap = A->m_colstart;
  291 + int* Ai = A->m_rowinx;
  292 +
  293 + // Mark node k as visited
  294 + CS_MARK(w, k);
  295 +
  296 + // Loop over elements of node
  297 + int i;
  298 + for (int p = Ap[k]; p < Ap[k+1]; ++p) {
  299 + i = Ai[p]; // A(i,k) is nonzero
  300 + if (i > k) continue; // only use upper triangular part of A
  301 +
  302 + // Traverse up etree
  303 + int len;
  304 + for (len = 0; !CS_MARKED(w,i); i = parent[i]) {
  305 + s[len++] = i; // L(k,i) is nonzero
  306 + CS_MARK(w, i); // mark i as visited
  307 + }
  308 +
  309 + // Push path onto stack
  310 + while (len > 0)
  311 + s[--top] = s[--len];
  312 + }
  313 +
  314 + // Unmark all nodes
  315 + for (int p = top; p < n; ++p)
  316 + CS_MARK(w, s[p]);
  317 +
  318 + // Unmark node k
  319 + CS_MARK(w, k);
  320 +
  321 + // Return index top, where s[top..n-1] contains pattern of L(k,:)
  322 + return (top);
  323 +}
  324 +
  325 +
  326 +/*==========================================================================
  327 + = =
  328 + = GSparseNumeric static member functions =
  329 + = =
  330 + ==========================================================================*/
  331 +
  332 +/*==========================================================================
  333 + = =
  334 + = GSparseNumeric friends =
  335 + = =
  336 + ==========================================================================*/
  337 +
  338 +/***************************************************************************
  339 + * Output operator *
  340 + ***************************************************************************/
  341 +ostream& operator<< (ostream& os, const GSparseNumeric& n)
  342 +{
  343 + // Put header is stream
  344 + os << "=== GSparseNumeric ===";
  345 +
  346 + // Show L or V matrix
  347 + if (n.m_L != NULL) {
  348 + os << endl <<
  349 + " === L or V ";
  350 + os << *n.m_L << endl;
  351 + }
  352 +
  353 + // Show U or R matrix
  354 + if (n.m_U != NULL) {
  355 + os << endl <<
  356 + " === U or R matrix ";
  357 + os << *n.m_U << endl;
  358 + }
  359 +
  360 + // Show inverse permutation if it exists
  361 + if (n.m_pinv != NULL) {
  362 + os << endl << " Inverse permutation (of " << n.m_n_pinv << " elements)" << endl;
  363 + for (int i = 0; i < n.m_n_pinv; ++i)
  364 + os << " " << n.m_pinv[i];
  365 + }
  366 +
  367 + // Show beta array if it exists
  368 + if (n.m_B != NULL) {
  369 + os << endl << " Beta[0.." << n.m_n_B << "]" << endl;
  370 + for (int i = 0; i < n.m_n_B; ++i)
  371 + os << " " << n.m_B[i];
  372 + }
  373 +
  374 + // Return output stream
  375 + return os;
  376 +}
  377 +
  378 +/*==========================================================================
  379 + = =
  380 + = GSparseNumeric exception classes =
  381 + = =
  382 + ==========================================================================*/
... ...
src/GSparseNumeric.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * GSparseNumeric.hpp - sparse matrix numeric analysis class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright : (C) 2006 by Jurgen Knodlseder *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software; you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation; either version 2 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + ***************************************************************************/
  13 +
  14 +#ifndef GSPARSENUMERIC_HPP
  15 +#define GSPARSENUMERIC_HPP
  16 +
  17 +/* __ Includes ___________________________________________________________ */
  18 +#include "GException.hpp"
  19 +#include "GVector.hpp"
  20 +#include "GMatrix.hpp"
  21 +#include "GSparseMatrix.hpp"
  22 +
  23 +/* __ Namespaces _________________________________________________________ */
  24 +using namespace std;
  25 +
  26 +/* __ Definitions ________________________________________________________ */
  27 +
  28 +/* __ Enumerators ________________________________________________________ */
  29 +
  30 +/* __ Structures _________________________________________________________ */
  31 +
  32 +/* __ Prototypes _________________________________________________________ */
  33 +
  34 +
  35 +/***************************************************************************
  36 + * GSparseNumeric class definition *
  37 + ***************************************************************************/
  38 +class GSparseNumeric {
  39 + // Friend classes
  40 + friend class GSparseMatrix;
  41 +
  42 + // I/O friends
  43 + friend ostream& operator<< (ostream& os, const GSparseNumeric& n);
  44 +
  45 +public:
  46 + // Constructors and destructors
  47 + GSparseNumeric();
  48 + ~GSparseNumeric();
  49 +
  50 + // Assignment operator
  51 + GSparseNumeric& operator= (const GSparseNumeric& n);
  52 +
  53 + // Functions
  54 + void cholesky_numeric_analysis(GSparseMatrix& m, const GSparseSymbolic& s);
  55 +
  56 +private:
  57 + // Functions
  58 + int cs_ereach(const GSparseMatrix* A, int k, const int* parent, int* s, int* w);
  59 +
  60 + // Data
  61 + GSparseMatrix* m_L; // L for LU and Cholesky, V for QR
  62 + GSparseMatrix* m_U; // U for LU, R for QR, not used for Cholesky
  63 + int* m_pinv; // partial pivoting for LU
  64 + double* m_B; // beta [0..n-1] for QR
  65 + int m_n_pinv; // Number of elements in m_pinv
  66 + int m_n_B; // Number of elements in m_B
  67 +};
  68 +
  69 +
  70 +/***************************************************************************
  71 + * Inline members *
  72 + ***************************************************************************/
  73 +
  74 +
  75 +/***************************************************************************
  76 + * Inline friends *
  77 + ***************************************************************************/
  78 +
  79 +#endif /* GSPARSENUMERIC_HPP */
... ...
src/GSparseSymbolic.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * GSparseSymbolic.cpp - sparse matrix symbolic analysis class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright : (C) 2006 by Jurgen Knodlseder *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software; you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation; either version 2 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + ***************************************************************************/
  13 +
  14 +/* __ Includes ___________________________________________________________ */
  15 +#include "GSparseSymbolic.hpp"
  16 +
  17 +/* __ Namespaces _________________________________________________________ */
  18 +using namespace std;
  19 +
  20 +/* __ Macros _____________________________________________________________ */
  21 +#define CS_MIN(a,b) (((a) < (b)) ? (a) : (b))
  22 +#define CS_MAX(a,b) (((a) > (b)) ? (a) : (b))
  23 +#define CS_FLIP(i) (-(i)-2)
  24 +
  25 +/* __ Definitions ________________________________________________________ */
  26 +//#define G_DEBUG_SPARSE_SYM_AMD_ORDERING // Debug AMD ordering
  27 +
  28 +
  29 +/*==========================================================================
  30 + = =
  31 + = GSparseSymbolic constructors/destructors =
  32 + = =
  33 + ==========================================================================*/
  34 +
  35 +/***************************************************************************
  36 + * GSparseSymbolic constructor *
  37 + ***************************************************************************/
  38 +GSparseSymbolic::GSparseSymbolic()
  39 +{
  40 + // Initialise private members for clean destruction
  41 + m_n_pinv = 0;
  42 + m_n_q = 0;
  43 + m_n_parent = 0;
  44 + m_n_cp = 0;
  45 + m_n_leftmost = 0;
  46 + m_pinv = NULL;
  47 + m_q = NULL;
  48 + m_parent = NULL;
  49 + m_cp = NULL;
  50 + m_leftmost = NULL;
  51 + m_m2 = 0;
  52 + m_lnz = 0.0;
  53 + m_unz = 0.0;
  54 +
  55 + // Return
  56 + return;
  57 +}
  58 +
  59 +
  60 +/***************************************************************************
  61 + * GSparseSymbolic destructor *
  62 + ***************************************************************************/
  63 +GSparseSymbolic::~GSparseSymbolic()
  64 +{
  65 + // De-allocate only if memory has indeed been allocated
  66 + if (m_pinv != NULL) delete[] m_pinv;
  67 + if (m_q != NULL) delete[] m_q;
  68 + if (m_parent != NULL) delete[] m_parent;
  69 + if (m_cp != NULL) delete[] m_cp;
  70 + if (m_leftmost != NULL) delete[] m_leftmost;
  71 +
  72 + // Return
  73 + return;
  74 +}
  75 +
  76 +
  77 +/*==========================================================================
  78 + = =
  79 + = GSparseSymbolic operators =
  80 + = =
  81 + ==========================================================================*/
  82 +
  83 +/***************************************************************************
  84 + * GSparseSymbolic assignment operator *
  85 + ***************************************************************************/
  86 +GSparseSymbolic& GSparseSymbolic::operator= (const GSparseSymbolic& s)
  87 +{
  88 + // Execute only if object is not identical
  89 + if (this != &s) {
  90 +
  91 + // Initialise private members for clean destruction
  92 + m_n_pinv = 0;
  93 + m_n_q = 0;
  94 + m_n_parent = 0;
  95 + m_n_cp = 0;
  96 + m_n_leftmost = 0;
  97 + m_pinv = NULL;
  98 + m_q = NULL;
  99 + m_parent = NULL;
  100 + m_cp = NULL;
  101 + m_leftmost = NULL;
  102 + m_m2 = 0;
  103 + m_lnz = 0.0;
  104 + m_unz = 0.0;
  105 +
  106 + // Copy data members
  107 + m_m2 = s.m_m2;
  108 + m_lnz = s.m_lnz;
  109 + m_unz = s.m_unz;
  110 +
  111 + // Copy m_pinv array if it exists
  112 + if (s.m_pinv != NULL) {
  113 + m_pinv = new int[s.m_n_pinv];
  114 + if (m_pinv == NULL)
  115 + throw mem_alloc("GSparseSymbolic::operator= (const GSparseSymbolic&)",
  116 + s.m_n_pinv);
  117 + for (int i = 0; i < s.m_n_pinv; ++i)
  118 + m_pinv[i] = s.m_pinv[i];
  119 + m_n_pinv = s.m_n_pinv;
  120 + }
  121 +
  122 + // Copy m_q array if it exists
  123 + if (s.m_q != NULL) {
  124 + m_q = new int[s.m_n_q];
  125 + if (m_q == NULL)
  126 + throw mem_alloc("GSparseSymbolic::operator= (const GSparseSymbolic&)",
  127 + s.m_n_q);
  128 + for (int i = 0; i < s.m_n_q; ++i)
  129 + m_q[i] = s.m_q[i];
  130 + m_n_q = s.m_n_q;
  131 + }
  132 +
  133 + // Copy m_parent array if it exists
  134 + if (s.m_parent != NULL) {
  135 + m_parent = new int[s.m_n_parent];
  136 + if (m_parent == NULL)
  137 + throw mem_alloc("GSparseSymbolic::operator= (const GSparseSymbolic&)",
  138 + s.m_n_parent);
  139 + for (int i = 0; i < s.m_n_parent; ++i)
  140 + m_parent[i] = s.m_parent[i];
  141 + m_n_parent = s.m_n_parent;
  142 + }
  143 +
  144 + // Copy m_cp array if it exists
  145 + if (s.m_cp != NULL) {
  146 + m_cp = new int[s.m_n_cp];
  147 + if (m_cp == NULL)
  148 + throw mem_alloc("GSparseSymbolic::operator= (const GSparseSymbolic&)",
  149 + s.m_n_cp);
  150 + for (int i = 0; i < s.m_n_cp; ++i)
  151 + m_cp[i] = s.m_cp[i];
  152 + m_n_cp = s.m_n_cp;
  153 + }
  154 +
  155 + // Copy m_leftmost array if it exists
  156 + if (s.m_leftmost != NULL) {
  157 + m_leftmost = new int[s.m_n_leftmost];
  158 + if (m_leftmost == NULL)
  159 + throw mem_alloc("GSparseSymbolic::operator= (const GSparseSymbolic&)",
  160 + s.m_n_leftmost);
  161 + for (int i = 0; i < s.m_n_leftmost; ++i)
  162 + m_leftmost[i] = s.m_leftmost[i];
  163 + m_leftmost = s.m_leftmost;
  164 + }
  165 +
  166 + } // endif: object was not identical
  167 +
  168 + // Return
  169 + return (*this);
  170 +}
  171 +
  172 +
  173 +/*==========================================================================
  174 + = =
  175 + = GSparseSymbolic member functions =
  176 + = =
  177 + ==========================================================================*/
  178 +
  179 +/***************************************************************************
  180 + * cholesky_symbolic_analysis *
  181 + * ----------------------------------------------------------------------- *
  182 + * Ordering and symbolic analysis for a Cholesky factorization. This *
  183 + * function allocates the memory to hold the information. *
  184 + * ----------------------------------------------------------------------- *
  185 + * Input: order 0: natural *
  186 + * 1: Cholesky decomposition *
  187 + * m Sparse matrix *
  188 + ***************************************************************************/
  189 +void GSparseSymbolic::cholesky_symbolic_analysis(int order, GSparseMatrix& m)
  190 +{
  191 + // Check if order type is valid
  192 + if (order < 0 || order > 1)
  193 + throw invalid_order("GSparseSymbolic::cholesky_symbolic_analysis(int, GSparseMatrix*)",
  194 + order, 0, 1);
  195 +
  196 + // Fill pending element
  197 + m.fill_pending();
  198 +
  199 + // Assign input matrix attributes
  200 + int n = m.m_cols;
  201 +
  202 + // P = amd(A+A'), or natural
  203 + int* P = cs_amd(order, &m);
  204 +
  205 + // Find inverse permutation and store it in class member 'm_pinv'
  206 + m_pinv = cs_pinv(P, n);
  207 + m_n_pinv = n;
  208 +
  209 + // Delete workspace
  210 + delete [] P;
  211 +
  212 + // C = spones(triu(A(P,P)))
  213 + GSparseMatrix C = cs_symperm(&m, m_pinv, 0);
  214 +
  215 + // Find etree of C and store it in class member 'm_parent'
  216 + m_parent = cs_etree(&C, 0);
  217 + m_n_parent = n;
  218 +
  219 + // Post order the etree
  220 + int* post = cs_post(m_parent, n);
  221 +
  222 + // Find column counts of chol(C)
  223 + int* c = cs_counts(&C, m_parent, post, 0);
  224 +
  225 + // Delete workspace
  226 + delete [] post;
  227 +
  228 + // Allocate column pointers for Cholesky decomposition
  229 + m_n_cp = n+1;
  230 + m_cp = new int[m_n_cp];
  231 + if (m_cp == NULL)
  232 + throw mem_alloc("GSparseSymbolic::cs_schol(int, GSparseMatrix*)", m_n_cp);
  233 +
  234 + // Find column pointers for L
  235 + m_unz = m_lnz = cs_cumsum(m_cp, c, n);
  236 +
  237 + // Delete workspace
  238 + delete [] c;
  239 +
  240 +// return ((S->lnz >= 0) ? S : cs_sfree (S)) ;
  241 +}
  242 +
  243 +
  244 +/*==========================================================================
  245 + = =
  246 + = GSparseSymbolic private functions =
  247 + = =
  248 + ==========================================================================*/
  249 +
  250 +/***************************************************************************
  251 + * cs_amd *
  252 + * ----------------------------------------------------------------------- *
  253 + * Applies an approximate minimum degree ordering algorithm to derive the *
  254 + * permutations that minimise the fill-in. *
  255 + * p = amd(A+A') if symmetric is true, or amd(A'A) otherwise *
  256 + * ----------------------------------------------------------------------- *
  257 + * Input: order 0: natural *
  258 + * 1: Cholesky decomposition *
  259 + * 2: LU decomposition *
  260 + * 3: QR decomposition *
  261 + * A Sparse matrix *
  262 + * Output: p[0..n] integer array of n+1 elements *
  263 + ***************************************************************************/
  264 +int* GSparseSymbolic::cs_amd(int order, GSparseMatrix* A)
  265 +{
  266 + // Throw exception if order is not a decomposition
  267 + if (order < 0 || order > 3)
  268 + throw invalid_order("GSparseSymbolic::cs_amd(int, GSparseMatrix*)",
  269 + order, 0, 3);
  270 +
  271 + // Debug
  272 + #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
  273 + cout << endl << "GSparseSymbolic::cs_amd entered" << endl;
  274 + cout << " order ......................: " << order << endl;
  275 + cout << " number of rows .............: " << A->m_rows << endl;
  276 + cout << " number of columns ..........: " << A->m_cols << endl;
  277 + cout << " number of non-zero elements : " << A->m_elements << endl;
  278 + #endif
  279 +
  280 + // Declare
  281 + int dense;
  282 + int d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1,
  283 + k2, k3, jlast, ln, mindeg = 0, nvi, nvj, nvk, mark, wnvi,
  284 + ok, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q;
  285 + unsigned int h ;
  286 +
  287 + // Assign input matrix attributes
  288 + int m = A->m_rows;
  289 + int n = A->m_cols;
  290 +
  291 +
  292 + // ======================================================================
  293 + // Step 1: Construct matrix C
  294 + // ======================================================================
  295 +
  296 + // Debug
  297 + #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
  298 + cout << " Step 1: Construct matrix C" << endl;
  299 + #endif
  300 +
  301 + // Initialise matrix C. We do not care at this point about the actual
  302 + // dimension since we attribute the matrix later anyways. It's just
  303 + // that there is no empty constructor of a matrix, so we have to put
  304 + // something by default ...
  305 + GSparseMatrix C(m,n);
  306 +
  307 + // Get (logical) transpose of A: AT = A'
  308 + GSparseMatrix AT = A->cs_transpose(A,0);
  309 +
  310 + // Find dense threshold
  311 + dense = (int)CS_MAX(16, 10 * sqrt((double)n));
  312 + dense = CS_MIN(n-2, dense);
  313 +
  314 + // Case A: Cholesky decomposition of a symmetric matrix: C = A + A'
  315 + if (order == 1 && n == m) {
  316 +// C = cs_add (A, AT, 0, 0);
  317 + C = *A + AT;
  318 + }
  319 +
  320 + // Case B: LU decomposition: C = A' * A with no dense rows
  321 + else if (order == 2) {
  322 +
  323 + // Assign A' matrix attributes
  324 + int* ATp = AT.m_colstart;
  325 + int* ATi = AT.m_rowinx;
  326 +
  327 + // Drop dense columns from AT
  328 + for (p2 = 0, j = 0; j < m; j++) {
  329 + p = ATp[j]; // column j of AT starts here
  330 + ATp[j] = p2; // new column j starts here
  331 + if (ATp[j+1] - p > dense) continue; // skip dense col j
  332 + for ( ; p < ATp[j+1]; p++)
  333 + ATi[p2++] = ATi[p] ;
  334 + }
  335 +
  336 + // Finalise AT
  337 + ATp[m] = p2;
  338 +
  339 + // Get (logical) transpose of AT: A2 = AT'
  340 + GSparseMatrix A2 = AT.cs_transpose(&AT,0);
  341 +
  342 + // C = A' * A with no dense rows
  343 +// C = A2 ? cs_multiply(AT, A2) : NULL;
  344 + C = AT * A2;
  345 + }
  346 +
  347 + // Case C: QR decomposition: C = A' * A
  348 + else {
  349 +// C = cs_multiply(AT, A);
  350 + C = AT * *A;
  351 + }
  352 +
  353 + // Stop in case of an error
  354 +// if (!C) return (NULL) ;
  355 +
  356 + // Drop diagonal entries from C
  357 + cs_fkeep(&C, &cs_diag, NULL);
  358 +
  359 + // Assign C matrix attributes
  360 + int* Cp = C.m_colstart;
  361 + int cnz = Cp[n];
  362 +
  363 + // Allocate result array
  364 + int* P = new int[n+1];
  365 + if (P == NULL)
  366 + throw mem_alloc("GSparseSymbolic::cs_amd (int, GSparseMatrix*)", n+1);
  367 +
  368 + // Allocate workspace
  369 + int wrk_size = 8*(n+1);
  370 + int* wrk_int = new int[wrk_size];
  371 + if (wrk_int == NULL)
  372 + throw mem_alloc("GSparseSymbolic::cs_amd (int, GSparseMatrix*)", wrk_size);
  373 +
  374 + // Add elbow room to C
  375 +// t = cnz + cnz/5 + 2*n;
  376 +// if (!P || !W || !cs_sprealloc (C, t)) return (cs_idone (P, C, W, 0)) ;
  377 + int t = cnz/5 + 2*n;
  378 + C.alloc_elements(cnz, t);
  379 +
  380 + // Set workspace pointers
  381 + int* len = wrk_int;
  382 + int* nv = wrk_int + (n+1);
  383 + int* next = wrk_int + 2*(n+1);
  384 + int* head = wrk_int + 3*(n+1);
  385 + int* elen = wrk_int + 4*(n+1);
  386 + int* degree = wrk_int + 5*(n+1);
  387 + int* w = wrk_int + 6*(n+1);
  388 + int* hhead = wrk_int + 7*(n+1);
  389 + int* last = P; // use P as workspace for last
  390 +
  391 +
  392 + // ======================================================================
  393 + // Step 2: Initialize quotient graph
  394 + // ======================================================================
  395 +
  396 + // Debug
  397 + #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
  398 + cout << " Step 2: Initialize quotient graph" << endl;
  399 + #endif
  400 +
  401 + // (Re-)assign C matrix attributes
  402 + int nzmax = C.m_elements; // Maximum number of entries
  403 + Cp = C.m_colstart;
  404 + int* Ci = C.m_rowinx;
  405 +
  406 + // Setup array that contains for each column the number of non-zero elements
  407 + for (k = 0 ; k < n ; k++)
  408 + len[k] = Cp[k+1] - Cp[k];
  409 + len[n] = 0;
  410 +
  411 + // Loop over all columns
  412 + for (i = 0 ; i <= n ; i++) {
  413 + head[i] = -1; // degree list i is empty
  414 + last[i] = -1;
  415 + next[i] = -1;
  416 + hhead[i] = -1; // hash list i is empty
  417 + nv[i] = 1; // node i is just one node
  418 + w[i] = 1; // node i is alive
  419 + elen[i] = 0; // Ek of node i is empty
  420 + degree[i] = len[i]; // degree of node i
  421 + }
  422 +
  423 + // Clear w
  424 + mark = cs_wclear(0, 0, w, n);
  425 +
  426 + // End-point initialisations
  427 + elen[n] = -2; // n is a dead element
  428 + Cp[n] = -1; // n is a root of assembly tree
  429 + w[n] = 0; // n is a dead element
  430 +
  431 +
  432 + // ======================================================================
  433 + // Step 3: Initialize degree lists
  434 + // ======================================================================
  435 +
  436 + // Debug
  437 + #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
  438 + cout << " Step 3: Initialize degree lists" << endl;
  439 + #endif
  440 +
  441 + // Loop over all columns
  442 + for (i = 0 ; i < n ; i++) {
  443 +
  444 + // Get degree of node
  445 + d = degree[i];
  446 +
  447 + // Case A: Node i is empty
  448 + if (d == 0) {
  449 + elen[i] = -2; // element i is dead
  450 + nel++ ;
  451 + Cp[i] = -1; // i is a root of assembly tree
  452 + w[i] = 0; // i is a dead element
  453 + }
  454 +
  455 + // Case B: Node is dense
  456 + else if (d > dense) {
  457 + nv[i] = 0; // absorb i into element n
  458 + elen[i] = -1; // node i is dead
  459 + nel++ ;
  460 + Cp[i] = CS_FLIP(n);
  461 + nv[n]++ ;
  462 + }
  463 +
  464 + // Case C: Node is sparse
  465 + else {
  466 + if (head[d] != -1) last[head[d]] = i;
  467 + next[i] = head[d]; // put node i in degree list d
  468 + head[d] = i;
  469 + }
  470 + } // endfor: looped over all columns
  471 +
  472 +
  473 + // ======================================================================
  474 + // Step 4: Build permutations
  475 + // ======================================================================
  476 +
  477 + // Debug
  478 + #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
  479 + cout << " Step 4: Build permutations" << endl;
  480 + #endif
  481 +
  482 + // While (selecting pivots) do
  483 + while (nel < n) {
  484 +
  485 + // Select node of minimum approximate degree
  486 + for (k = -1; mindeg < n && (k = head [mindeg]) == -1; mindeg++) ;
  487 + if (next[k] != -1) last [next[k]] = -1;
  488 + head[mindeg] = next[k]; // remove k from degree list
  489 + elenk = elen[k]; // elenk = |Ek|
  490 + nvk = nv[k]; // # of nodes k represents
  491 + nel += nvk; // nv[k] nodes of A eliminated
  492 +
  493 + // Garbage collection
  494 + if (elenk > 0 && cnz + mindeg >= nzmax) {
  495 +
  496 + // Loop over all columns
  497 + for (j = 0 ; j < n ; j++) {
  498 + // If j is a live node or element, then ...
  499 + if ((p = Cp[j]) >= 0) {
  500 + Cp[j] = Ci[p]; // save first entry of object
  501 + Ci[p] = CS_FLIP(j); // first entry is now CS_FLIP(j)
  502 + }
  503 + }
  504 +
  505 + // Scan all memory
  506 + for (q = 0, p = 0; p < cnz ; ) {
  507 + // If we found object j, then ...
  508 + if ((j = CS_FLIP(Ci[p++])) >= 0) {
  509 + Ci[q] = Cp[j]; // restore first entry of object
  510 + Cp[j] = q++; // new pointer to object j
  511 + for (k3 = 0; k3 < len [j]-1; k3++)
  512 + Ci[q++] = Ci[p++];
  513 + }
  514 + }
  515 + cnz = q; // Ci[cnz...nzmax-1] now free
  516 +
  517 + } // endif: garbage collection done
  518 +
  519 + // Construct new element ---------------------------------------- */
  520 + dk = 0;
  521 + nv[k] = -nvk; // flag k as in Lk
  522 + p = Cp[k];
  523 + pk1 = (elenk == 0) ? p : cnz; // do in place if elen[k] == 0
  524 + pk2 = pk1;
  525 + for (k1 = 1; k1 <= elenk + 1; k1++) {
  526 +
  527 + // ...
  528 + if (k1 > elenk) {
  529 + e = k; // search the nodes in k
  530 + pj = p; // list of nodes starts at Ci[pj]
  531 + ln = len [k] - elenk; // length of list of nodes in k
  532 + }
  533 + else {
  534 + e = Ci[p++]; // search the nodes in e
  535 + pj = Cp[e];
  536 + ln = len[e]; // length of list of nodes in e
  537 + }
  538 +
  539 + // ...
  540 + for (k2 = 1 ; k2 <= ln ; k2++) {
  541 + i = Ci[pj++];
  542 + if ((nvi = nv [i]) <= 0) // Skip of node i is dead or seen
  543 + continue;
  544 + dk += nvi; // degree[Lk] += size of node i
  545 + nv[i] = -nvi; // negate nv[i] to denote i in Lk
  546 + Ci[pk2++] = i; // place i in Lk
  547 + if (next[i] != -1)
  548 + last[next[i]] = last[i];
  549 +
  550 + // remove i from degree list
  551 + if (last[i] != -1)
  552 + next[last[i]] = next[i];
  553 + else
  554 + head[degree[i]] = next[i];
  555 + } // endfor: k2
  556 +
  557 + // ...
  558 + if (e != k) {
  559 + Cp[e] = CS_FLIP (k); // absorb e into k
  560 + w[e] = 0; // e is now a dead element
  561 + }
  562 + } // endfor: k1
  563 +
  564 + if (elenk != 0) cnz = pk2; // Ci [cnz...nzmax] is free
  565 + degree[k] = dk; // external degree of k - |Lk\i|
  566 + Cp[k] = pk1; // element k is in Ci[pk1..pk2-1]
  567 + len[k] = pk2 - pk1;
  568 + elen[k] = -2; // k is now an element
  569 +
  570 + // Clear w if necessary
  571 + mark = cs_wclear(mark, lemax, w, n);
  572 +
  573 + // Scan 1: Find set differences |Le\Lk|
  574 + for (pk = pk1 ; pk < pk2 ; pk++) {
  575 + i = Ci [pk];
  576 + if ((eln = elen [i]) <= 0) // skip if elen[i] empty
  577 + continue;
  578 + nvi = -nv[i]; // nv [i] was negated
  579 + wnvi = mark - nvi;
  580 +
  581 + // Scan Ei
  582 + for (p = Cp[i]; p <= Cp[i] + eln - 1; p++) {
  583 + e = Ci [p] ;
  584 + if (w[e] >= mark)
  585 + w[e] -= nvi; // decrement |Le\Lk|
  586 + else if (w[e] != 0) // ensure e is a live element
  587 + w[e] = degree[e] + wnvi; // 1st time e seen in scan 1
  588 + }
  589 + } // endfor: scan 1 finished
  590 +
  591 + // Scan 2: Degree update
  592 + for (pk = pk1; pk < pk2; pk++) {
  593 + i = Ci [pk] ; /* consider node i in Lk */
  594 + p1 = Cp [i] ;
  595 + p2 = p1 + elen [i] - 1 ;
  596 + pn = p1 ;
  597 +
  598 + // Scan Ei
  599 + for (h = 0, d = 0, p = p1 ; p <= p2 ; p++) {
  600 + e = Ci [p] ;
  601 + // If e is an unabsorbed element, then ...
  602 + if (w [e] != 0) {
  603 + dext = w [e] - mark ; /* dext = |Le\Lk| */
  604 + if (dext > 0) {
  605 + d += dext ; /* sum up the set differences */
  606 + Ci [pn++] = e ; /* keep e in Ei */
  607 + h += e ; /* compute the hash of node i */
  608 + }
  609 + else {
  610 + Cp [e] = CS_FLIP (k) ; /* aggressive absorb. e->k */
  611 + w [e] = 0 ; /* e is a dead element */
  612 + }
  613 + }
  614 + } // endfor: scanned Ei
  615 +
  616 + // elen[i] = |Ei|
  617 + elen [i] = pn - p1 + 1 ;
  618 + p3 = pn ;
  619 + p4 = p1 + len [i] ;
  620 +
  621 + // Prune edges in Ai
  622 + for (p = p2 + 1 ; p < p4 ; p++) {
  623 + j = Ci [p] ;
  624 + if ((nvj = nv [j]) <= 0) continue ; /* node j dead or in Lk */
  625 + d += nvj ; /* degree(i) += |j| */
  626 + Ci [pn++] = j ; /* place j in node list of i */
  627 + h += j ; /* compute hash for node i */
  628 + }
  629 +
  630 + // Check for mass elimination
  631 + if (d == 0) {
  632 + Cp [i] = CS_FLIP (k) ; /* absorb i into k */
  633 + nvi = -nv [i] ;
  634 + dk -= nvi ; /* |Lk| -= |i| */
  635 + nvk += nvi ; /* |k| += nv[i] */
  636 + nel += nvi ;
  637 + nv [i] = 0 ;
  638 + elen [i] = -1 ; /* node i is dead */
  639 + }
  640 + else {
  641 + degree [i] = CS_MIN (degree [i], d) ; /* update degree(i) */
  642 + Ci [pn] = Ci [p3] ; /* move first node to end */
  643 + Ci [p3] = Ci [p1] ; /* move 1st el. to end of Ei */
  644 + Ci [p1] = k ; /* add k as 1st element in of Ei */
  645 + len [i] = pn - p1 + 1 ; /* new len of adj. list of node i */
  646 + h %= n ; /* finalize hash of i */
  647 + next [i] = hhead [h] ; /* place i in hash bucket */
  648 + hhead [h] = i ;
  649 + last [i] = h ; /* save hash of i in last[i] */
  650 + }
  651 + } // endfor: scan 2 is done
  652 +
  653 + // finalize |Lk|
  654 + degree[k] = dk ;
  655 + lemax = CS_MAX(lemax, dk);
  656 +
  657 + // Clear w
  658 + mark = cs_wclear(mark+lemax, lemax, w, n);
  659 +
  660 + // Supernode detection
  661 + for (pk = pk1 ; pk < pk2 ; pk++) {
  662 + i = Ci [pk] ;
  663 + if (nv [i] >= 0) continue ; /* skip if i is dead */
  664 + h = last [i] ; /* scan hash bucket of node i */
  665 + i = hhead [h] ;
  666 + hhead [h] = -1 ; /* hash bucket will be empty */
  667 +
  668 + // ...
  669 + for ( ; i != -1 && next [i] != -1 ; i = next [i], mark++) {
  670 + ln = len [i] ;
  671 + eln = elen [i] ;
  672 + for (p = Cp [i]+1 ; p <= Cp [i] + ln-1 ; p++) w [Ci [p]] = mark;
  673 + jlast = i ;
  674 +
  675 + // Compare i with all j
  676 + for (j = next [i] ; j != -1 ; ) {
  677 + ok = (len [j] == ln) && (elen [j] == eln) ;
  678 + for (p = Cp [j] + 1 ; ok && p <= Cp [j] + ln - 1 ; p++) {
  679 + if (w [Ci [p]] != mark) ok = 0 ; /* compare i and j*/
  680 + }
  681 +
  682 + // i and j are identical
  683 + if (ok) {
  684 + Cp[j] = CS_FLIP(i); /* absorb j into i */
  685 + nv[i] += nv[j];
  686 + nv[j] = 0;
  687 + elen[j] = -1; /* node j is dead */
  688 + j = next[j]; /* delete j from hash bucket */
  689 + next[jlast] = j;
  690 + }
  691 + // j and i are different
  692 + else {
  693 + jlast = j;
  694 + j = next[j];
  695 + }
  696 + } // endfor: comparison of i with all j
  697 + } //
  698 + } // endfor: supernode detection
  699 +
  700 + // Finalize new element
  701 + for (p = pk1, pk = pk1 ; pk < pk2 ; pk++) /* finalize Lk */
  702 + {
  703 + i = Ci [pk] ;
  704 + if ((nvi = -nv [i]) <= 0) continue ;/* skip if i is dead */
  705 + nv [i] = nvi ; /* restore nv[i] */
  706 + d = degree [i] + dk - nvi ; /* compute external degree(i) */
  707 + d = CS_MIN (d, n - nel - nvi) ;
  708 + if (head [d] != -1) last [head [d]] = i ;
  709 + next [i] = head [d] ; /* put i back in degree list */
  710 + last [i] = -1 ;
  711 + head [d] = i ;
  712 + mindeg = CS_MIN (mindeg, d) ; /* find new minimum degree */
  713 + degree [i] = d ;
  714 + Ci [p++] = i ; /* place i in Lk */
  715 + }
  716 + nv [k] = nvk ; /* # nodes absorbed into k */
  717 + if ((len [k] = p-pk1) == 0) /* length of adj list of element k*/
  718 + {
  719 + Cp [k] = -1 ; /* k is a root of the tree */
  720 + w [k] = 0 ; /* k is now a dead element */
  721 + }
  722 + if (elenk != 0) cnz = p ; /* free unused space in Lk */
  723 + }
  724 +
  725 + // Postordering
  726 + for (i = 0 ; i < n ; i++) Cp [i] = CS_FLIP (Cp [i]) ;/* fix assembly tree */
  727 + for (j = 0 ; j <= n ; j++) head [j] = -1 ;
  728 + for (j = n ; j >= 0 ; j--) /* place unordered nodes in lists */
  729 + {
  730 + if (nv [j] > 0) continue ; /* skip if j is an element */
  731 + next [j] = head [Cp [j]] ; /* place j in list of its parent */
  732 + head [Cp [j]] = j ;
  733 + }
  734 + for (e = n ; e >= 0 ; e--) /* place elements in lists */
  735 + {
  736 + if (nv [e] <= 0) continue ; /* skip unless e is an element */
  737 + if (Cp [e] != -1)
  738 + {
  739 + next [e] = head [Cp [e]] ; /* place e in list of its parent */
  740 + head [Cp [e]] = e ;
  741 + }
  742 + }
  743 +
  744 + // ======================================================================
  745 + // Step 5: Postorder the assembly tree
  746 + // ======================================================================
  747 +
  748 + // Debug
  749 + #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
  750 + cout << " Step 5: Postorder the assembly tree" << endl;
  751 + #endif
  752 +
  753 + // Postorder the assembly tree
  754 + for (k = 0, i = 0 ; i <= n ; i++) {
  755 + if (Cp [i] == -1)
  756 + k = cs_tdfs(i, k, head, next, P, w);
  757 + }
  758 +
  759 + // Free workspace
  760 + delete [] wrk_int;
  761 +
  762 + // Debug
  763 + #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
  764 + cout << " Permutation:" << endl;
  765 + for (i = 0; i < n; ++i)
  766 + cout << " " << P[i];
  767 + cout << endl;
  768 + cout << "GSparseSymbolic::cs_amd finished" << endl;
  769 + #endif
  770 +
  771 + // Return result
  772 + return (P);
  773 +}
  774 +
  775 +
  776 +/***************************************************************************
  777 + * cs_counts *
  778 + * ----------------------------------------------------------------------- *
  779 + * Column counts of LL'=A or LL'=A'A, given parent & post ordering *
  780 + * ----------------------------------------------------------------------- *
  781 + * Input: A Sparse matrix A *
  782 + * parent[0..n-1] parent array *
  783 + * post[0..n-1] post ordering array *
  784 + * ata 0: count LL'=A, 1: count LL'=A'A *
  785 + * Output: p[0..n] integer array of n+1 elements *
  786 + ***************************************************************************/
  787 +int* GSparseSymbolic::cs_counts(GSparseMatrix* A, const int* parent,
  788 + const int* post, int ata)
  789 +{
  790 + // Declare loop variables
  791 + int i, j, k, J, p, q, jleaf;
  792 +
  793 + // Return NULL pointer if input arrays are NULL or sparse matrix is
  794 + // empty
  795 + if (!parent || !post) return (NULL);
  796 +
  797 + // Assign input matrix attributes
  798 + int m = A->m_rows;
  799 + int n = A->m_cols;
  800 +
  801 + // Allocate result
  802 + int* colcount = new int[n];
  803 + if (colcount == NULL)
  804 + throw mem_alloc("GSparseSymbolic::cs_counts(GSparseMatrix*, const int*, const int*, int)",
  805 + n);
  806 + int* delta = colcount;
  807 +
  808 + // Allocate workspace
  809 + int wrk_size = 4*n + (ata ? (n+m+1) : 0);
  810 + int* wrk_int = new int[wrk_size];
  811 + if (wrk_int == NULL)
  812 + throw mem_alloc("GSparseSymbolic::cs_counts(GSparseMatrix*, const int*, const int*, int)",
  813 + wrk_size);
  814 +
  815 + // Get transpose of A: AT = A'
  816 + GSparseMatrix AT = A->cs_transpose(A,0);
  817 +
  818 + // Set-up pointers to workspace
  819 + int* ancestor = wrk_int;
  820 + int* maxfirst = wrk_int + n;
  821 + int* prevleaf = wrk_int + 2*n;
  822 + int* first = wrk_int + 3*n;
  823 +
  824 + // Clear workspace
  825 + for (k = 0; k < wrk_size; k++)
  826 + wrk_int[k] = -1;
  827 +
  828 + // Find first j
  829 + for (k = 0; k < n; k++) {
  830 + j = post[k];
  831 + delta[j] = (first[j] == -1) ? 1 : 0; // delta[j]=1 if j is a leaf
  832 + for ( ; j != -1 && first[j] == -1; j = parent[j]) first[j] = k;
  833 + }
  834 +
  835 + // Assign output matrix attributes
  836 + int* ATp = AT.m_colstart;
  837 + int* ATi = AT.m_rowinx;
  838 +
  839 + // Initialise
  840 + int* head = NULL;
  841 + int* next = NULL;
  842 + if (ata) init_ata(&AT, post, wrk_int, &head, &next);
  843 +
  844 + // Each node in its own set
  845 + for (i = 0; i < n; i++) ancestor[i] = i;
  846 +
  847 + // Loop over all columns of matrix A (or rows of matrix AT)
  848 + #define HEAD(k,j) (ata ? head [k] : j)
  849 + #define NEXT(J) (ata ? next [J] : -1)
  850 + for (k = 0; k < n; k++) {
  851 + j = post[k]; // j is the kth node in postordered etree
  852 + if (parent[j] != -1) delta[parent[j]]--; // j is not a root
  853 + for (J = HEAD(k,j); J != -1; J = NEXT(J)) { // J=j for LL'=A case
  854 +
  855 + // Loop over all non-zero elements in column J
  856 + for (p = ATp[J]; p < ATp[J+1]; p++) {
  857 + i = ATi [p] ;
  858 + q = cs_leaf(i, j, first, maxfirst, prevleaf, ancestor, &jleaf);
  859 + if (jleaf >= 1) delta [j]++ ; /* A(i,j) is in skeleton */
  860 + if (jleaf == 2) delta [q]-- ; /* account for overlap in q */
  861 + }
  862 + }
  863 + if (parent[j] != -1) ancestor[j] = parent[j];
  864 + }
  865 +
  866 + // Sum up delta's of each child
  867 + for (j = 0; j < n; j++) {
  868 + if (parent[j] != -1) colcount[parent[j]] += colcount[j];
  869 + }
  870 +
  871 + // Free workspace
  872 + delete [] wrk_int;
  873 +
  874 + // Return result
  875 + return (colcount);
  876 +}
  877 +
  878 +
  879 +/***************************************************************************
  880 + * cs_etree *
  881 + * ----------------------------------------------------------------------- *
  882 + * Compute the etree of A using triu(A), or A'A without forming A'A *
  883 + * ----------------------------------------------------------------------- *
  884 + * Input: A Sparse matrix A *
  885 + * ata flag *
  886 + * Output: etree(A) Evaluation tree of matrix A *
  887 + ***************************************************************************/
  888 +int* GSparseSymbolic::cs_etree(GSparseMatrix* A, int ata)
  889 +{
  890 + // Declare loop variables
  891 + int i, k, p;
  892 +
  893 + // Assign matrix attributes
  894 + int m = A->m_rows;
  895 + int n = A->m_cols;
  896 +
  897 + // Allocate result array
  898 + int* parent = new int[n];
  899 + if (parent == NULL)
  900 + throw mem_alloc("GSparseSymbolic::cs_etree(GSparseMatrix*, int)", n);
  901 +
  902 + // Allocate workspace
  903 + int wrk_size = n + (ata ? m : 0);
  904 + int* wrk_int = new int[wrk_size];
  905 + if (wrk_int == NULL)
  906 + throw mem_alloc("GSparseSymbolic::cs_etree(GSparseMatrix*, int)", wrk_size);
  907 +
  908 + // Set-up pointers to workspace. If 'ata=1' then we use also a prev array
  909 + int* ancestor = wrk_int;
  910 + int* prev = wrk_int + n;
  911 +
  912 + // If 'prev' is requested, initialise array with -1
  913 + if (ata) for (i = 0; i < m ; ++i) prev[i] = -1;
  914 +
  915 + // Loop over all nodes (columns)
  916 + for (k = 0; k < n; ++k) {
  917 +
  918 + // Initialise node k to having no parent and no ancestor
  919 + parent[k] = -1; // node k has no parent yet
  920 + ancestor[k] = -1; // nor does k have an ancestor
  921 +
  922 + // Loop over all elements in column k
  923 + for (p = A->m_colstart[k]; p < A->m_colstart[k+1]; ++p) {
  924 +
  925 + // Get element index
  926 + i = ata ? (prev[A->m_rowinx[p]]) : (A->m_rowinx[p]);
  927 +
  928 + // Traverse from i to k
  929 + int inext;
  930 + for ( ; i != -1 && i < k; i = inext) {
  931 + inext = ancestor[i]; // inext = ancestor of i
  932 + ancestor[i] = k; // path compression
  933 + if (inext == -1) parent[i] = k; // no ancestor, parent is k
  934 + }
  935 + if (ata) prev[A->m_rowinx[p]] = k;
  936 + }
  937 + }
  938 +
  939 + // Free workspace
  940 + delete [] wrk_int;
  941 +
  942 + // Return result
  943 + return (parent);
  944 +
  945 +}
  946 +
  947 +
  948 +/***************************************************************************
  949 + * cs_fkeep *
  950 + * ----------------------------------------------------------------------- *
  951 + * Drop entries for which fkeep(A(i,j)) is false. Return the number of *
  952 + * non-zero elements if ok, otherwise return -1. *
  953 + * ----------------------------------------------------------------------- *
  954 + * Input: A Sparse matrix *
  955 + * fkeep Screening function *
  956 + * other Other function *
  957 + * Output: result 0..n-1 if ok, -1 in case of error *
  958 + ***************************************************************************/
  959 +int GSparseSymbolic::cs_fkeep(GSparseMatrix* A, int(*fkeep)(int, int, double, void*),
  960 + void* other)
  961 +{
  962 + // Return error if some of the input pointers is invalid
  963 + if (!A || !fkeep) return (-1);
  964 +
  965 + // Declare
  966 + int j, p, nz = 0;
  967 +
  968 + // Assign matrix attributes
  969 + int n = A->m_cols;
  970 + int* Ap = A->m_colstart;
  971 + int* Ai = A->m_rowinx;
  972 + double* Ax = A->m_data;
  973 +
  974 + // Loop over all columns
  975 + for (j = 0; j < n; j++) {
  976 + p = Ap[j]; // get current location of col j
  977 + Ap[j] = nz; // record new location of col j
  978 + for ( ; p < Ap[j+1] ; p++) {
  979 + if (fkeep(Ai[p], j, Ax ? Ax[p] : 1, other)) {
  980 + if (Ax) Ax[nz] = Ax[p]; // keep A(i,j)
  981 + Ai[nz++] = Ai[p] ;
  982 + }
  983 + }
  984 + }
  985 +
  986 + // Finalise A
  987 + Ap[n] = nz;
  988 +
  989 + // Remove extra space from A
  990 +// cs_sprealloc (A, 0) ; /* remove extra space from A */
  991 +
  992 + // Return number of non-zero elements
  993 + return (nz) ;
  994 +}
  995 +
  996 +
  997 +/***************************************************************************
  998 + * cs_leaf *
  999 + * ----------------------------------------------------------------------- *
  1000 + * Consider A(i,j), node j in ith row subtree and return lca(jprev,j) *
  1001 + * ----------------------------------------------------------------------- *
  1002 + * Input: i row to consider *
  1003 + * j column to consider *
  1004 + * first[0..n-1] ... *
  1005 + * maxfirst[0..n-1] ... *
  1006 + * prevleaf[0..n-1] ... *
  1007 + * ancestor[0..n-1] ... *
  1008 + * Output: q ... *
  1009 + * jleaf ... *
  1010 + ***************************************************************************/
  1011 +int GSparseSymbolic::cs_leaf(int i, int j, const int *first, int *maxfirst,
  1012 + int *prevleaf, int *ancestor, int *jleaf)
  1013 +{
  1014 + // If one of the input pointers is invalid then return -1
  1015 + if (!first || !maxfirst || !prevleaf || !ancestor || !jleaf) return (-1);
  1016 +
  1017 + // Declare loop variables
  1018 + int q, s, sparent;
  1019 +
  1020 + // ...
  1021 + *jleaf = 0 ;
  1022 +
  1023 + // If j is not a leaf then return -1
  1024 + if (i <= j || first[j] <= maxfirst[i]) return (-1);
  1025 +
  1026 + // Update max first[j] seen so far
  1027 + maxfirst[i] = first[j];
  1028 +
  1029 + // jprev = previous leaf of ith subtree
  1030 + int jprev = prevleaf[i];
  1031 + prevleaf[i] = j;
  1032 +
  1033 + // j is first or subsequent leaf
  1034 + *jleaf = (jprev == -1) ? 1: 2;
  1035 +
  1036 + // If j is 1st leaf then q is the root of ith subtree
  1037 + if (*jleaf == 1) return (i);
  1038 +
  1039 + // ...
  1040 + for (q = jprev; q != ancestor[q]; q = ancestor[q]) ;
  1041 +
  1042 + // ...
  1043 + for (s = jprev; s != q; s = sparent) {
  1044 + sparent = ancestor[s]; // path compression
  1045 + ancestor[s] = q;
  1046 + }
  1047 +
  1048 + // Return least common ancester (jprev,j)
  1049 + return (q);
  1050 +}
  1051 +
  1052 +
  1053 +/***************************************************************************
  1054 + * cs_pinv *
  1055 + * ----------------------------------------------------------------------- *
  1056 + * Inverts the permutation p[0..n-1] *
  1057 + * ----------------------------------------------------------------------- *
  1058 + * Input: p[0..n-1] integer array of n elements (NULL denotres ID) *
  1059 + * Output: pinv[0..n-1] pinv[0..n-1] = p[n-1..0] *
  1060 + ***************************************************************************/
  1061 +int* GSparseSymbolic::cs_pinv(int const *p, int n)
  1062 +{
  1063 + // Return NULL pointer if input pointer is NULL. This denotes identity
  1064 + if (!p || n < 1) return (NULL);
  1065 +
  1066 + // Allocate result array
  1067 + int* pinv = new int[n];
  1068 + if (pinv == NULL)
  1069 + throw mem_alloc("GSparseSymbolic::cs_pinv", n);
  1070 +
  1071 + // Invert the permutation
  1072 + for (int k = 0; k < n; ++k)
  1073 + pinv[p[k]] = k;
  1074 +
  1075 + // Return result
  1076 + return (pinv);
  1077 +}
  1078 +
  1079 +
  1080 +/***************************************************************************
  1081 + * cs_post *
  1082 + * ----------------------------------------------------------------------- *
  1083 + * Post order a forest *
  1084 + * ----------------------------------------------------------------------- *
  1085 + * Input: parent[0..n-1] integer array of n elements *
  1086 + * Output: post[0..n-1] ... *
  1087 + ***************************************************************************/
  1088 +int* GSparseSymbolic::cs_post(const int* parent, int n)
  1089 +{
  1090 + // Return NULL pointer if input pointer is NULL
  1091 + if (!parent || n < 1) return (NULL);
  1092 +
  1093 + // Allocate result array
  1094 + int* post = new int[n];
  1095 + if (post == NULL)
  1096 + throw mem_alloc("GSparseSymbolic::cs_post(const int*, int)", n);
  1097 +
  1098 + // Allocate workspace
  1099 + int wrk_size = 3 * n;
  1100 + int* wrk_int = new int[wrk_size];
  1101 + if (wrk_int == NULL)
  1102 + throw mem_alloc("GSparseSymbolic::cs_post(const int*, int)", wrk_size);
  1103 +
  1104 + // Set-up pointers to workspace
  1105 + int* head = wrk_int;
  1106 + int* next = wrk_int + n;
  1107 + int* stack = wrk_int + 2*n; // Working array for 'cs_tdfs' function
  1108 +
  1109 + // Declare and initialise loop variables
  1110 + int j, k = 0;
  1111 +
  1112 + // Empty linked list
  1113 + for (j = 0 ; j < n ; j++) head[j] = -1;
  1114 +
  1115 + // Traverse nodes in reverse order to build a linked list 'head'
  1116 + for (j = n-1; j >= 0; j--) {
  1117 +
  1118 + // Skip if j is a root
  1119 + if (parent[j] == -1) continue;
  1120 +
  1121 + // Add j to list of its parent
  1122 + next[j] = head[parent[j]];
  1123 + head[parent[j]] = j;
  1124 + }
  1125 +
  1126 + // Traverse nodes
  1127 + for (j = 0 ; j < n ; j++) {
  1128 +
  1129 + // Skip if j is not a root
  1130 + if (parent[j] != -1) continue;
  1131 +
  1132 + // Depth-first search and postorder of a tree rooted at node j
  1133 + k = cs_tdfs(j, k, head, next, post, stack);
  1134 + }
  1135 +
  1136 + // Free workspace
  1137 + delete [] wrk_int;
  1138 +
  1139 + // Return result
  1140 + return (post);
  1141 +
  1142 +}
  1143 +
  1144 +
  1145 +/***************************************************************************
  1146 + * cs_symperm *
  1147 + * ----------------------------------------------------------------------- *
  1148 + * C = A(p,p) where A and C are symmetric the upper part stored. *
  1149 + * pinv not p *
  1150 + * ----------------------------------------------------------------------- *
  1151 + * Input: A Sparse matrix *
  1152 + * pinv pinv[0..n-1] *
  1153 + * values =1 allocate memory for values (NOT USED) *
  1154 + * Output: C Sparse matrix *
  1155 + ***************************************************************************/
  1156 +GSparseMatrix GSparseSymbolic::cs_symperm(GSparseMatrix* A, const int* pinv,
  1157 + int values) const
  1158 +{
  1159 + // Declare loop variables
  1160 + int i, j, p, q, i2, j2;
  1161 +
  1162 + // Assign matrix attributes
  1163 + int n = A->m_cols;
  1164 + int* Ap = A->m_colstart;
  1165 + int* Ai = A->m_rowinx;
  1166 + double* Ax = A->m_data;
  1167 +
  1168 + // Allocate result matrix
  1169 + GSparseMatrix C(n, n, Ap[n]);
  1170 +
  1171 + // Allocate and initialise workspace
  1172 + int wrk_size = n;
  1173 + int* wrk_int = new int[wrk_size];
  1174 + if (wrk_int == NULL)
  1175 + throw mem_alloc("GSparseSymbolic::cs_symperm(GSparseMatrix*, const int*, int",
  1176 + wrk_size);
  1177 + for (i = 0; i < wrk_size; ++i)
  1178 + wrk_int[i] = 0;
  1179 +
  1180 + // Assign result matriix attributes
  1181 + int* Cp = C.m_colstart;
  1182 + int* Ci = C.m_rowinx;
  1183 + double* Cx = C.m_data;
  1184 +
  1185 + // Count entries in each column of C
  1186 + for (j = 0; j < n; j++) {
  1187 +
  1188 + // Column j of A is column j2 of C
  1189 + j2 = pinv ? pinv[j] : j;
  1190 +
  1191 + // Loop over entries in column j
  1192 + for (p = Ap[j]; p < Ap[j+1]; p++) {
  1193 + i = Ai [p];
  1194 + if (i > j) continue; // skip lower triangular part of A
  1195 + i2 = pinv ? pinv[i] : i; // row i of A is row i2 of C
  1196 + wrk_int[CS_MAX(i2, j2)]++; // column count of C
  1197 + }
  1198 + }
  1199 +
  1200 + // Compute column pointers of C
  1201 + cs_cumsum(Cp, wrk_int, n);
  1202 +
  1203 + // Loop over all columns of A
  1204 + for (j = 0 ; j < n ; j++) {
  1205 +
  1206 + // Column j of A is column j2 of C
  1207 + j2 = pinv ? pinv[j] : j;
  1208 +
  1209 + // Loop over entries in column j
  1210 + for (p = Ap[j]; p < Ap[j+1]; p++) {
  1211 + i = Ai [p] ;
  1212 + if (i > j) continue; // skip lower triangular part of A
  1213 + i2 = pinv ? pinv[i] : i; // row i of A is row i2 of C
  1214 + Ci[q = wrk_int[CS_MAX(i2,j2)]++] = CS_MIN(i2,j2);
  1215 + Cx[q] = Ax[p];
  1216 + }
  1217 + }
  1218 +
  1219 + // Free workspace
  1220 + delete [] wrk_int;
  1221 +
  1222 + // Return result
  1223 + return (C);
  1224 +
  1225 +}
  1226 +
  1227 +
  1228 +/***************************************************************************
  1229 + * cs_tdfs *
  1230 + * ----------------------------------------------------------------------- *
  1231 + * Depth-first search and postorder of a tree rooted at node j *
  1232 + * ----------------------------------------------------------------------- *
  1233 + * Input: j Node of tree root *
  1234 + * k ... *
  1235 + * head head[0..n-1] linked list (updated) *
  1236 + * next next[0..n-1] linked list info *
  1237 + * post post[0..n-1] array (updated) *
  1238 + * stack stack[0..n-1] working array (updated) *
  1239 + * Output: k Update of k *
  1240 + ***************************************************************************/
  1241 +int GSparseSymbolic::cs_tdfs(int j, int k, int* head, const int* next,
  1242 + int* post, int* stack)
  1243 +{
  1244 + // Return -1 if one of the array pointers is NULL
  1245 + if (!head || !next || !post || !stack) return (-1);
  1246 +
  1247 + // Decrare
  1248 + int i, p;
  1249 +
  1250 + // Place j on the first position of the stack
  1251 + stack[0] = j;
  1252 +
  1253 + // Loop while stack is not empty
  1254 + int top = 0;
  1255 + while (top >= 0) {
  1256 + p = stack[top]; // p = top of stack
  1257 + i = head[p]; // i = youngest child of p
  1258 + if (i == -1) {
  1259 + top--; // p has no unordered children left
  1260 + post[k++] = p; // node p is the kth postordered node
  1261 + }
  1262 + else {
  1263 + head[p] = next[i]; // remove i from children of p
  1264 + stack[++top] = i; // start depth-first search on child node i
  1265 + }
  1266 + }
  1267 +
  1268 + // Return result
  1269 + return (k) ;
  1270 +}
  1271 +
  1272 +
  1273 +/*==========================================================================
  1274 + = =
  1275 + = GSparseSymbolic static member functions =
  1276 + = =
  1277 + ==========================================================================*/
  1278 +
  1279 +/***************************************************************************
  1280 + * init_ata *
  1281 + * ----------------------------------------------------------------------- *
  1282 + * Initialise A'A. *
  1283 + * Note that the returned pointers 'head' and 'info' point into the *
  1284 + * 'wrk_int' workspace array. *
  1285 + * ----------------------------------------------------------------------- *
  1286 + * Input: AT Sparse matrix A' *
  1287 + * post ... *
  1288 + * wrk_int Workspace *
  1289 + * head pointer to head[0..n-1] linked list *
  1290 + * next pointer to next[0..n-1] linked list info *
  1291 + * Output: - - *
  1292 + ***************************************************************************/
  1293 +void GSparseSymbolic::init_ata(GSparseMatrix* AT, const int* post,
  1294 + int* wrk_int, int** head, int** next)
  1295 +{
  1296 + // Declare loop variables
  1297 + int i, k, p;
  1298 +
  1299 + // Assign matrix attributes
  1300 + int m = AT->m_cols;
  1301 + int n = AT->m_rows;
  1302 + int* ATp = AT->m_colstart;
  1303 + int* ATi = AT->m_rowinx;
  1304 +
  1305 + // Set-up pointers to workspace
  1306 + *head = wrk_int + 4*n;
  1307 + *next = wrk_int + 5*n+1;
  1308 +
  1309 + // Invert post
  1310 + for (k = 0 ; k < n ; k++)
  1311 + wrk_int[post[k]] = k;
  1312 +
  1313 + // Loop over columns of AT matrix
  1314 + for (i = 0 ; i < m ; i++) {
  1315 +
  1316 + // Loop over elements in column i of AT matrix
  1317 + for (k = n, p = ATp[i]; p < ATp[i+1]; p++)
  1318 + k = CS_MIN(k,wrk_int[ATi[p]]);
  1319 +
  1320 + // Place row i in linked list k
  1321 + (*next)[i] = (*head)[k];
  1322 + (*head)[k] = i;
  1323 + }
  1324 +}
  1325 +
  1326 +
  1327 +/***************************************************************************
  1328 + * cs_diag *
  1329 + * ----------------------------------------------------------------------- *
  1330 + * Keep off-diagonal entries and drop diagonal entries. *
  1331 + * ----------------------------------------------------------------------- *
  1332 + * Input: i Row index *
  1333 + * j Column index *
  1334 + * aij NOT USED *
  1335 + * other NOT USED *
  1336 + * Output: diag 0: off-diagonal, 1: diagonal element *
  1337 + ***************************************************************************/
  1338 +int GSparseSymbolic::cs_diag(int i, int j, double aij, void* other)
  1339 +{
  1340 + return (i != j);
  1341 +}
  1342 +
  1343 +
  1344 +/***************************************************************************
  1345 + * cs_wclear *
  1346 + * ----------------------------------------------------------------------- *
  1347 + * Clear w array *
  1348 + * ----------------------------------------------------------------------- *
  1349 + * Input: mark ... *
  1350 + * lemax ... *
  1351 + * w w[0..n-1] working array *
  1352 + * n Size of the working array *
  1353 + * Output: mark Update of mark *
  1354 + * w Cleared w[0..n-1] working array *
  1355 + ***************************************************************************/
  1356 +int GSparseSymbolic::cs_wclear(int mark, int lemax, int* w, int n)
  1357 +{
  1358 + // Declare loop variables
  1359 + int k;
  1360 +
  1361 + // ...
  1362 + if (mark < 2 || (mark + lemax < 0)) {
  1363 + for (k = 0; k < n; k++) if (w[k] != 0) w[k] = 1;
  1364 + mark = 2;
  1365 + }
  1366 +
  1367 + // Return mark. At this point, w[0..n-1] < mark holds
  1368 + return (mark);
  1369 +}
  1370 +
  1371 +
  1372 +/*==========================================================================
  1373 + = =
  1374 + = GSparseSymbolic friends =
  1375 + = =
  1376 + ==========================================================================*/
  1377 +
  1378 +/***************************************************************************
  1379 + * Output operator *
  1380 + ***************************************************************************/
  1381 +ostream& operator<< (ostream& os, const GSparseSymbolic& s)
  1382 +{
  1383 + // Put header is stream
  1384 + os << "=== GSparseSymbolic ===";
  1385 +
  1386 + // Show inverse permutation if it exists
  1387 + if (s.m_pinv != NULL) {
  1388 + os << endl << " Inverse permutation (of " << s.m_n_pinv << " elements)" <<
  1389 + endl;
  1390 + for (int i = 0; i < s.m_n_pinv; ++i)
  1391 + os << " " << s.m_pinv[i];
  1392 + }
  1393 +
  1394 + // Show fill reducing column permutation if it exists
  1395 + if (s.m_q != NULL) {
  1396 + os << endl << " Fill reducing column permutation (" << s.m_n_cp <<
  1397 + " elements)" << endl;
  1398 + for (int i = 0; i < s.m_n_cp; ++i)
  1399 + os << " " << s.m_q[i];
  1400 + }
  1401 +
  1402 + // Show elimination tree for Cholesky and QR if it exists
  1403 + if (s.m_parent != NULL) {
  1404 + os << endl << " Elimination tree (" << s.m_n_parent << " elements)" <<
  1405 + endl;
  1406 + for (int i = 0; i < s.m_n_parent; ++i)
  1407 + os << " " << s.m_parent[i];
  1408 + }
  1409 +
  1410 + // Show column pointers for Cholesky row counts for QR if it exists
  1411 + if (s.m_cp != NULL) {
  1412 + os << endl << " Cholesky column pointers/QR row counts (" << s.m_n_cp <<
  1413 + " elements)" << endl;
  1414 + for (int i = 0; i < s.m_n_cp; ++i)
  1415 + os << " " << s.m_cp[i];
  1416 + }
  1417 +
  1418 + // Show leftmost[i] = min(find(A(i,:))) if it exists
  1419 + if (s.m_leftmost != NULL) {
  1420 + os << endl << " leftmost[i] = min(find(A(i,:))) (" << s.m_n_leftmost <<
  1421 + " elements)" << endl;
  1422 + for (int i = 0; i < s.m_n_leftmost; ++i)
  1423 + os << " " << s.m_leftmost[i];
  1424 + }
  1425 +
  1426 + // Return output stream
  1427 + return os;
  1428 +}
  1429 +
  1430 +
  1431 +/*==========================================================================
  1432 + = =
  1433 + = GSparseSymbolic exception classes =
  1434 + = =
  1435 + ==========================================================================*/
  1436 +
  1437 +/***************************************************************************
  1438 + * Invalid ordering scheme requested *
  1439 + ***************************************************************************/
  1440 +GSparseSymbolic::invalid_order::invalid_order(string origin, int order,
  1441 + int min_order, int max_order)
  1442 +{
  1443 + m_origin = origin;
  1444 + ostringstream s_order;
  1445 + ostringstream s_min_order;
  1446 + ostringstream s_max_order;
  1447 + s_order << order;
  1448 + s_min_order << min_order;
  1449 + s_max_order << max_order;
  1450 + m_message = "Invalid ordering type " + s_order.str() +
  1451 + "requested; must be comprised in [" + s_min_order.str() +
  1452 + "," + s_max_order.str() + "]";
  1453 +}
... ...
src/GSparseSymbolic.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * GSparseSymbolic.hpp - sparse matrix symbolic analysis class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright : (C) 2006 by Jurgen Knodlseder *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software; you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation; either version 2 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + ***************************************************************************/
  13 +
  14 +#ifndef GSPARSESYMBOLIC_HPP
  15 +#define GSPARSESYMBOLIC_HPP
  16 +
  17 +/* __ Includes ___________________________________________________________ */
  18 +#include "GException.hpp"
  19 +#include "GVector.hpp"
  20 +#include "GMatrix.hpp"
  21 +#include "GSparseMatrix.hpp"
  22 +
  23 +/* __ Namespaces _________________________________________________________ */
  24 +using namespace std;
  25 +
  26 +/* __ Definitions ________________________________________________________ */
  27 +
  28 +/* __ Enumerators ________________________________________________________ */
  29 +
  30 +/* __ Structures _________________________________________________________ */
  31 +
  32 +/* __ Prototypes _________________________________________________________ */
  33 +
  34 +
  35 +/***************************************************************************
  36 + * GSparseSymbolic class definition *
  37 + ***************************************************************************/
  38 +class GSparseSymbolic {
  39 + // Friend classes
  40 + friend class GSparseMatrix;
  41 + friend class GSparseNumeric;
  42 +
  43 + // Binary operator friends
  44 +
  45 + // I/O friends
  46 + friend ostream& operator<< (ostream& os, const GSparseSymbolic& s);
  47 +
  48 + // Friend functions
  49 +
  50 +public:
  51 + // Constructors and destructors
  52 + GSparseSymbolic();
  53 +// GSparseSymbolic(const GSparseSymbolic& s) { cout << "would sym to" << endl;}
  54 + ~GSparseSymbolic();
  55 +
  56 + // Assignment operator
  57 + GSparseSymbolic& operator= (const GSparseSymbolic& s);
  58 +
  59 + // Binary operators
  60 +
  61 + // Unary operators
  62 +
  63 + // Functions
  64 + void cholesky_symbolic_analysis(int order, GSparseMatrix& m);
  65 +
  66 + // Exception: Invalid ordering scheme
  67 + class invalid_order : public GException {
  68 + public:
  69 + invalid_order(string origin, int order, int min_order, int max_order);
  70 + };
  71 +
  72 +private:
  73 + // Functions
  74 + int* cs_amd (int order, GSparseMatrix* A);
  75 + int* cs_counts(GSparseMatrix* A, const int* parent, const int* post, int ata);
  76 + int* cs_etree(GSparseMatrix* A, int ata);
  77 + int cs_fkeep(GSparseMatrix* A, int(*fkeep)(int, int, double, void*), void* other);
  78 + int cs_leaf(int i, int j, const int* first, int* maxfirst, int* prevleaf, int* ancestor, int* jleaf);
  79 + int* cs_pinv(int const* p, int n);
  80 + int* cs_post(const int* parent, int n);
  81 + GSparseMatrix cs_symperm(GSparseMatrix* A, const int* pinv, int values) const;
  82 + int cs_tdfs(int j, int k, int* head, const int* next, int* post, int* stack);
  83 + static void init_ata(GSparseMatrix* AT, const int* post, int* wrk_int, int** head, int** next);
  84 + static int cs_diag(int i, int j, double aij, void* other);
  85 + static int cs_wclear(int mark, int lemax, int* w, int n);
  86 +
  87 + // Data
  88 + int* m_pinv; // Inverse row permutation for QR, fill reduce permutation for Cholesky
  89 + int* m_q; // Fill-reducing column permutation for LU and QR
  90 + int* m_parent; // elimination tree for Cholesky and QR
  91 + int* m_cp; // column pointers for Cholesky, row counts for QR
  92 + int* m_leftmost; // leftmost[i] = min(find(A(i,:))), for QR
  93 + int m_m2; // # of rows for QR, after adding fictitious rows
  94 + double m_lnz; // # entries in L for LU or Cholesky; in V for QR
  95 + double m_unz; // # entries in U for LU; in R for QR
  96 + int m_n_pinv; // Number of elements in m_pinv
  97 + int m_n_q; // Number of elements in m_q
  98 + int m_n_parent; // Number of elements in m_parent
  99 + int m_n_cp; // Number of elements in m_cp
  100 + int m_n_leftmost; // Number of elements in m_leftmost
  101 +};
  102 +
  103 +
  104 +/***************************************************************************
  105 + * Inline members *
  106 + ***************************************************************************/
  107 +
  108 +
  109 +/***************************************************************************
  110 + * Inline friends *
  111 + ***************************************************************************/
  112 +
  113 +#endif /* GSPARSESYMBOLIC_HPP */
... ...
src/GSymMatrix.cpp
... ... @@ -18,26 +18,34 @@
18 18 using namespace std;
19 19  
20 20  
  21 +/*==========================================================================
  22 + = =
  23 + = GSymMatrix constructors/destructors =
  24 + = =
  25 + ==========================================================================*/
  26 +
21 27 /***************************************************************************
22   - * GSymMatrix constructor *
  28 + * GSymMatrix constructor *
23 29 ***************************************************************************/
24   -GSymMatrix::GSymMatrix(unsigned rows, unsigned cols) : GMatrix()
  30 +GSymMatrix::GSymMatrix(int rows, int cols) : GMatrix()
25 31 {
26 32 // Initialise private members for clean destruction
27   - m_rows = 0;
28   - m_cols = 0;
29   - m_elements = 0;
30   - m_num_inx = 0;
31   - m_data = NULL;
32   - m_colstart = NULL;
33   - m_inx = NULL;
  33 + m_rows = 0;
  34 + m_cols = 0;
  35 + m_elements = 0;
  36 + m_num_rowsel = 0;
  37 + m_num_colsel = 0;
  38 + m_data = NULL;
  39 + m_colstart = NULL;
  40 + m_rowsel = NULL;
  41 + m_colsel = NULL;
34 42  
35 43 // Throw exception if number of rows and columns is not identical
36 44 if (rows != cols)
37   - throw not_sym("GSymMatrix constructor", rows, cols);
  45 + throw matrix_not_symmetric("GSymMatrix constructor", rows, cols);
38 46  
39 47 // Determine number of physical elements in matrix
40   - unsigned elements = rows*(rows+1)/2;
  48 + int elements = rows*(rows+1)/2;
41 49  
42 50 // Throw exception if requested matrix size is zero
43 51 if (elements == 0)
... ... @@ -46,8 +54,8 @@ GSymMatrix::GSymMatrix(unsigned rows, unsigned cols) : GMatrix()
46 54 // Allocate matrix array and column start index array. Throw an exception
47 55 // if allocation failed
48 56 m_data = new double[elements];
49   - m_colstart = new unsigned[cols+1];
50   - m_inx = new unsigned[cols];
  57 + m_colstart = new int[cols+1];
  58 + m_inx = new int[cols];
51 59 if (m_data == NULL || m_colstart == NULL || m_inx == NULL)
52 60 throw mem_alloc("GSymMatrix constructor", elements);
53 61  
... ... @@ -58,13 +66,16 @@ GSymMatrix::GSymMatrix(unsigned rows, unsigned cols) : GMatrix()
58 66  
59 67 // Set-up column start indices
60 68 m_colstart[0] = 0;
61   - unsigned offset = rows;
62   - for (unsigned col = 1; col <= m_cols; ++col)
  69 + int offset = rows;
  70 + for (int col = 1; col <= m_cols; ++col)
63 71 m_colstart[col] = m_colstart[col-1] + offset--;
64 72  
65 73 // Initialise matrix elements to 0.0
66   - for (unsigned i = 0; i < m_elements; ++i)
  74 + for (int i = 0; i < m_elements; ++i)
67 75 m_data[i] = 0.0;
  76 +
  77 + // Return
  78 + return;
68 79 }
69 80  
70 81  
... ... @@ -75,12 +86,16 @@ GSymMatrix::GSymMatrix(unsigned rows, unsigned cols) : GMatrix()
75 86 ***************************************************************************/
76 87 GSymMatrix::GSymMatrix(const GSymMatrix& m) : GMatrix(m)
77 88 {
  89 + // Copy members
78 90 m_num_inx = m.m_num_inx;
79   - m_inx = new unsigned[m_cols];
  91 + m_inx = new int[m_cols];
80 92 if (m_inx == NULL)
81 93 throw mem_alloc("GSymMatrix copy constructor", m_cols);
82   - for (unsigned i = 0; i < m_cols; ++i)
  94 + for (int i = 0; i < m_cols; ++i)
83 95 m_inx[i] = m.m_inx[i];
  96 +
  97 + // Return
  98 + return;
84 99 }
85 100  
86 101  
... ... @@ -92,46 +107,259 @@ GSymMatrix::GSymMatrix(const GSymMatrix&amp; m) : GMatrix(m)
92 107 GSymMatrix::~GSymMatrix()
93 108 {
94 109 // De-allocate only if memory has indeed been allocated by derived class
95   - if (m_inx != NULL) delete[] m_inx;
  110 + if (m_inx != NULL) delete [] m_inx;
  111 +
  112 + // Return
  113 + return;
96 114 }
97 115  
98 116  
  117 +/*==========================================================================
  118 + = =
  119 + = GSymMatrix operators =
  120 + = =
  121 + ==========================================================================*/
  122 +
99 123 /***************************************************************************
100 124 * GSymMatrix assignment operator *
101 125 ***************************************************************************/
102 126 GSymMatrix& GSymMatrix::operator= (const GSymMatrix& m)
103 127 {
  128 + // Execute only if object is not identical
104 129 if (this != &m) {
  130 +
  131 + // Invoque base class assignment operator
105 132 this->GMatrix::operator=(m);
  133 +
  134 + // De-allocate memory if it has indeed been allocated
  135 + if (m_inx != NULL) delete [] m_inx;
  136 +
  137 + // Copy data members
106 138 m_num_inx = m.m_num_inx;
107   - m_inx = new unsigned[m_cols];
  139 +
  140 + // Allocate memory for indices and copy them
  141 + m_inx = new int[m_cols];
108 142 if (m_inx == NULL)
109 143 throw mem_alloc("GSymMatrix assignment operator", m_cols);
110   - for (unsigned i = 0; i < m_cols; ++i)
  144 + for (int i = 0; i < m_cols; ++i)
111 145 m_inx[i] = m.m_inx[i];
112 146 }
  147 +
  148 + // Return this object
  149 + return *this;
113 150 }
114 151  
115 152  
116 153 /***************************************************************************
117   - * GSymMatrix * GSymMatrix multiplication *
  154 + * Vector multiplication *
118 155 ***************************************************************************/
119   -GSymMatrix GSymMatrix::operator* (const GSymMatrix& m) const
  156 +GVector GSymMatrix::operator* (const GVector& v) const
  157 +{
  158 + // Raise an exception if the matrix and vector dimensions are not compatible
  159 + if (m_cols != v.m_num)
  160 + throw matrix_vector_mismatch("GSymMatrix::operator* (const GVector&)",
  161 + v.m_num, m_rows, m_cols);
  162 +
  163 + // Perform vector multiplication
  164 + GVector result(m_rows);
  165 + for (int row = 0; row < m_rows; ++row) {
  166 + double sum = 0.0;
  167 + for (int col = 0; col < m_cols; ++col)
  168 + sum += (*this)(row,col) * v(col);
  169 + result(row) = sum;
  170 + }
  171 +
  172 + // Return result
  173 + return result;
  174 +}
  175 +
  176 +
  177 +/***************************************************************************
  178 + * GSymMatrix negation (unary minus operator) *
  179 + ***************************************************************************/
  180 +GSymMatrix GSymMatrix::operator- ( ) const
  181 +{
  182 + // Copy argument into result
  183 + GSymMatrix result = *this;
  184 +
  185 + // Negate result
  186 + for (int i = 0; i < m_elements; ++i)
  187 + result.m_data[i] = -result.m_data[i];
  188 +
  189 + // Return result
  190 + return result;
  191 +}
  192 +
  193 +
  194 +/***************************************************************************
  195 + * Matrix multiplication (unary multiplication operator) *
  196 + * ----------------------------------------------------------------------- *
  197 + * Symmetric matrices must have the same dimensions to be multiplied. *
  198 + ***************************************************************************/
  199 +GSymMatrix& GSymMatrix::operator*= (const GSymMatrix& m)
120 200 {
121 201 // Raise an exception if the matrix dimensions are not compatible
122   - if (m_cols != m.m_rows)
123   - throw GMatrix::dim_mult_mismatch("GSymMatrix multiplication", m_cols, m.m_rows);
  202 + if (m_cols != m.m_rows || m_rows != m.m_cols)
  203 + throw matrix_mismatch("GSymMatrix::operator*= (const GSymMatrix&)",
  204 + m_rows, m_cols, m.m_rows, m.m_cols);
124 205  
125   - // Perform matrix multiplication
126   - GSymMatrix result(m_rows,m.m_cols);
127   - for (unsigned row = 0; row < m_rows; ++row) {
128   - for (unsigned col = 0; col < m.m_cols; ++col) {
  206 + // Allocate result matrix
  207 + GSymMatrix result(m_rows, m.m_cols);
  208 +
  209 + // Loop over all elements of result matrix
  210 + for (int row = 0; row < m_rows; ++row) {
  211 + for (int col = 0; col < m.m_cols; ++col) {
129 212 double sum = 0.0;
130   - for (unsigned i = 0; i < m_cols; ++i)
131   - sum += (*this)(row,i)*m(i,col);
132   - result(row,col) = sum;
133   - }
  213 + for (int i = 0; i < m_cols; ++i)
  214 + sum += (*this)(row,i) * m(i,col);
  215 + result(row,col) = sum;
  216 + }
  217 + }
  218 +
  219 + // Assign result
  220 + *this = result;
  221 +
  222 + // Return result
  223 + return *this;
  224 +}
  225 +
  226 +
  227 +/*==========================================================================
  228 + = =
  229 + = GSymMatrix member functions =
  230 + = =
  231 + ==========================================================================*/
  232 +
  233 +/***************************************************************************
  234 + * Sum matrix elements *
  235 + ***************************************************************************/
  236 +double GSymMatrix::sum() const
  237 +{
  238 + // Initialise matrix sums (diagonal and off-diagonal)
  239 + double diag = 0.0;
  240 + double off_diag = 0.0;
  241 +
  242 + // Calulate sum over diagonal elements
  243 + for (int row = 0; row < m_rows; ++row)
  244 + diag += m_data[m_colstart[row]];
  245 +
  246 + // Calulate sum over off-diagonal elements
  247 + for (int row = 0; row < m_rows; ++row) {
  248 + for (int col = row+1; col < m_cols; ++col)
  249 + off_diag += m_data[m_colstart[row]+(col-row)];
  250 + }
  251 +
  252 + // Calculate total
  253 + double result = diag + 2.0 * off_diag;
  254 +
  255 + // Return result
  256 + return result;
  257 +}
  258 +
  259 +
  260 +/***************************************************************************
  261 + * Extract row from matrix into vector *
  262 + ***************************************************************************/
  263 +GVector GSymMatrix::extract_row(int row) const
  264 +{
  265 + // Raise an exception if the row index is invalid
  266 + #if defined(G_RANGE_CHECK)
  267 + if (row >= m_rows)
  268 + throw out_of_range("GSymMatrix::extract_row(int)",
  269 + row, 0, m_rows, m_cols);
  270 + #endif
  271 +
  272 + // Create result vector
  273 + GVector result(m_cols);
  274 +
  275 + // Extract row into vector
  276 + for (int col = 0; col < m_cols; ++col)
  277 + result(col) = (*this)(row,col);
  278 +
  279 + // Return vector
  280 + return result;
  281 +
  282 +}
  283 +
  284 +
  285 +/***************************************************************************
  286 + * Extract column from matrix into vector *
  287 + ***************************************************************************/
  288 +GVector GSymMatrix::extract_col(int col) const
  289 +{
  290 + // Raise an exception if the column index is invalid
  291 + #if defined(G_RANGE_CHECK)
  292 + if (col >= m_cols)
  293 + throw out_of_range("GSymMatrix::extract_col(int)",
  294 + 0, col, m_rows, m_cols);
  295 + #endif
  296 +
  297 + // Create result vector
  298 + GVector result(m_rows);
  299 +
  300 + // Extract column into vector
  301 + for (int row = 0; row < m_rows; ++row)
  302 + result(row) = (*this)(row,col);
  303 +
  304 + // Return vector
  305 + return result;
  306 +
  307 +}
  308 +
  309 +
  310 +/***************************************************************************
  311 + * Convert symmetric matrix into full matrix *
  312 + ***************************************************************************/
  313 +GMatrix GSymMatrix::convert_to_full() const
  314 +{
  315 + // Define result matrix
  316 + GMatrix result(m_rows, m_cols);
  317 +
  318 + // Extract all elements
  319 + for (int row = 0; row < m_rows; ++row) {
  320 + for (int col = 0; col < m_cols; ++col)
  321 + result(row,col) = (*this)(row,col);
134 322 }
  323 +
  324 + // Return result
  325 + return result;
  326 +}
  327 +
  328 +
  329 +/***************************************************************************
  330 + * Extract lower triangle of symmetric matrix into full matrix *
  331 + ***************************************************************************/
  332 +GMatrix GSymMatrix::extract_lower_triangle() const
  333 +{
  334 + // Define result matrix
  335 + GMatrix result(m_rows, m_cols);
  336 +
  337 + // Extract all elements
  338 + for (int row = 0; row < m_rows; ++row) {
  339 + for (int col = 0; col <= row; ++col)
  340 + result(row,col) = m_data[m_colstart[col]+(row-col)];
  341 + }
  342 +
  343 + // Return result
  344 + return result;
  345 +}
  346 +
  347 +
  348 +/***************************************************************************
  349 + * Extract upper triangle of symmetric matrix into full matrix *
  350 + ***************************************************************************/
  351 +GMatrix GSymMatrix::extract_upper_triangle() const
  352 +{
  353 + // Define result matrix
  354 + GMatrix result(m_rows, m_cols);
  355 +
  356 + // Extract all elements
  357 + for (int row = 0; row < m_rows; ++row) {
  358 + for (int col = row; col < m_cols; ++col)
  359 + result(row,col) = m_data[m_colstart[row]+(col-row)];
  360 + }
  361 +
  362 + // Return result
135 363 return result;
136 364 }
137 365  
... ... @@ -159,18 +387,19 @@ void GSymMatrix::cholesky_decompose(int compress)
159 387 if (no_zeros) {
160 388  
161 389 // Loop over upper triangle (col >= row)
162   - for (unsigned row = 0; row < m_rows; ++row) {
  390 + for (int row = 0; row < m_rows; ++row) {
163 391 double* ptr = m_data + m_colstart[row];
164   - for (unsigned col = row; col < m_cols; ++col, ++ptr) {
  392 + for (int col = row; col < m_cols; ++col, ++ptr) {
165 393 double sum = *ptr; // sum = M(row,col)
166   - for (unsigned k = 0; k < row; ++k) {
167   - unsigned offset = m_colstart[k] - k; // is always positive
  394 + for (int k = 0; k < row; ++k) {
  395 + int offset = m_colstart[k] - k; // is always positive
168 396 sum -= m_data[offset+row] * m_data[offset+col]; // sum -= M(row,k)*M(col,k)
169 397 }
170 398 double diag;
171 399 if (row == col) {
172 400 if (sum <= 0.0)
173   - throw not_pos_definite("GSymMatrix cholesky_decompose", row, sum);
  401 + throw matrix_not_pos_definite("GSymMatrix::cholesky_decompose(int)",
  402 + row, sum);
174 403 *ptr = sqrt(sum); // M(row,row) = sqrt(sum)
175 404 diag = 1.0/(*ptr);
176 405 }
... ... @@ -184,12 +413,12 @@ void GSymMatrix::cholesky_decompose(int compress)
184 413 else if (m_num_inx > 0) {
185 414  
186 415 // Allocate loop variables and pointers
187   - unsigned row;
188   - unsigned col;
189   - unsigned k;
190   - unsigned* row_ptr;
191   - unsigned* col_ptr;
192   - unsigned* k_ptr;
  416 + int row;
  417 + int col;
  418 + int k;
  419 + int* row_ptr;
  420 + int* col_ptr;
  421 + int* k_ptr;
193 422  
194 423 // Loop over upper triangle (col >= row)
195 424 for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) {
... ... @@ -198,13 +427,14 @@ void GSymMatrix::cholesky_decompose(int compress)
198 427 double* ptr = ptr_0 + *col_ptr;
199 428 double sum = *ptr; // sum = M(row,col)
200 429 for (k = 0, k_ptr = m_inx; k < row; ++k, ++k_ptr) {
201   - unsigned offset = m_colstart[*k_ptr] - *k_ptr; // is always positive
  430 + int offset = m_colstart[*k_ptr] - *k_ptr; // is always positive
202 431 sum -= m_data[offset+*row_ptr] * m_data[offset+*col_ptr]; // sum -= M(row,k)*M(col,k)
203 432 }
204 433 double diag;
205 434 if (*row_ptr == *col_ptr) {
206 435 if (sum <= 0.0)
207   - throw not_pos_definite("GSymMatrix cholesky_decompose", *row_ptr, sum);
  436 + throw matrix_not_pos_definite("GSymMatrix::cholesky_decompose(int)",
  437 + *row_ptr, sum);
208 438 *ptr = sqrt(sum); // M(row,row) = sqrt(sum)
209 439 diag = 1.0/(*ptr);
210 440 }
... ... @@ -216,7 +446,7 @@ void GSymMatrix::cholesky_decompose(int compress)
216 446  
217 447 // Case C: all matrix elements are zero
218 448 else
219   - throw all_zero("GSymMatrix cholesky_decompose");
  449 + throw matrix_zero("GSymMatrix::cholesky_decompose(int)");
220 450  
221 451 }
222 452  
... ... @@ -231,6 +461,12 @@ void GSymMatrix::cholesky_decompose(int compress)
231 461 ***************************************************************************/
232 462 GVector GSymMatrix::cholesky_solver(const GVector& v, int compress)
233 463 {
  464 + // Raise an exception if the matrix and vector dimensions are not compatible
  465 + if (m_rows != v.m_num)
  466 + throw matrix_vector_mismatch(
  467 + "GSymMatrix::cholesky_solver(const GVector&, int)",
  468 + v.m_num, m_rows, m_cols);
  469 +
234 470 // Allocate result vector
235 471 GVector x(m_rows);
236 472  
... ... @@ -241,9 +477,9 @@ GVector GSymMatrix::cholesky_solver(const GVector&amp; v, int compress)
241 477 if (no_zeros) {
242 478  
243 479 // Solve L*y=b, storing y in x (row>k)
244   - for (unsigned row = 0; row < m_rows; ++row) {
  480 + for (int row = 0; row < m_rows; ++row) {
245 481 double sum = v(row);
246   - for (unsigned k = 0; k < row; ++k)
  482 + for (int k = 0; k < row; ++k)
247 483 sum -= m_data[m_colstart[k]+(row-k)] * x(k); // sum -= M(row,k) * x(k)
248 484 x(row) = sum/m_data[m_colstart[row]]; // x(row) = sum/M(row,row)
249 485 }
... ... @@ -252,7 +488,7 @@ GVector GSymMatrix::cholesky_solver(const GVector&amp; v, int compress)
252 488 for (int row = m_rows-1; row >= 0; --row) {
253 489 double sum = x(row);
254 490 double* ptr = m_data + m_colstart[row] + 1;
255   - for (unsigned k = row+1; k < m_rows; ++k)
  491 + for (int k = row+1; k < m_rows; ++k)
256 492 sum -= *ptr++ * x(k); // sum -= M(k,row) * x(k)
257 493 x(row) = sum/m_data[m_colstart[row]]; // x(row) = sum/M(row,row)
258 494 }
... ... @@ -263,9 +499,9 @@ GVector GSymMatrix::cholesky_solver(const GVector&amp; v, int compress)
263 499  
264 500 // Allocate loop variables and pointers
265 501 int row;
266   - unsigned k;
267   - unsigned* row_ptr;
268   - unsigned* k_ptr;
  502 + int k;
  503 + int* row_ptr;
  504 + int* k_ptr;
269 505  
270 506 // Solve L*y=b, storing y in x (row>k)
271 507 for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) {
... ... @@ -289,7 +525,7 @@ GVector GSymMatrix::cholesky_solver(const GVector&amp; v, int compress)
289 525  
290 526 // Case C: all matrix elements are zero
291 527 else
292   - throw all_zero("GSymMatrix cholesky_solver");
  528 + throw matrix_zero("GSymMatrix::cholesky_solver(const GVector&, int)");
293 529  
294 530 // Return result vector
295 531 return x;
... ... @@ -315,27 +551,27 @@ void GSymMatrix::cholesky_invert(int compress)
315 551 if (no_zeros) {
316 552  
317 553 // Generate inverse of Cholesky decomposition (col>row)
318   - for (unsigned row = 0; row < m_rows; ++row) {
  554 + for (int row = 0; row < m_rows; ++row) {
319 555 double* ptr = m_data + m_colstart[row];
320 556 *ptr = 1.0/(*ptr); // M(row,row) = 1/M(row,row)
321   - for (unsigned col = row+1; col < m_cols; ++col) {
  557 + for (int col = row+1; col < m_cols; ++col) {
322 558 double sum = 0.0;
323 559 double* ptr1 = m_data + col - row;
324 560 double* ptr2 = ptr;
325   - for (unsigned k = row; k < col; ++k)
  561 + for (int k = row; k < col; ++k)
326 562 sum -= *(ptr1-- + m_colstart[k]) * *ptr2++; // sum -= M(col,k)*M(k,row)
327 563 *(ptr+col-row) = sum/m_data[m_colstart[col]]; // M(col,row) = sum/M(col,col)
328 564 }
329 565 }
330 566  
331 567 // Matrix multiplication (col>=row)
332   - for (unsigned row = 0; row < m_rows; ++row) {
  568 + for (int row = 0; row < m_rows; ++row) {
333 569 double* ptr = m_data + m_colstart[row];
334   - for (unsigned col = row; col < m_cols; ++col) {
  570 + for (int col = row; col < m_cols; ++col) {
335 571 double sum = 0.0;
336 572 double* ptr1 = ptr + col - row;
337 573 double* ptr2 = m_data + m_colstart[col];
338   - for (unsigned k = col; k < m_cols; ++k)
  574 + for (int k = col; k < m_cols; ++k)
339 575 sum += *ptr1++ * *ptr2++; // sum += M(row,k)*M(k,col)
340 576 *(ptr+col-row) = sum; // M(row,col) = sum
341 577 }
... ... @@ -346,12 +582,12 @@ void GSymMatrix::cholesky_invert(int compress)
346 582 else if (m_num_inx > 0) {
347 583  
348 584 // Allocate loop variables and pointers
349   - unsigned row;
350   - unsigned col;
351   - unsigned k;
352   - unsigned* row_ptr;
353   - unsigned* col_ptr;
354   - unsigned* k_ptr;
  585 + int row;
  586 + int col;
  587 + int k;
  588 + int* row_ptr;
  589 + int* col_ptr;
  590 + int* k_ptr;
355 591  
356 592 // Generate inverse of Cholesky decomposition (col>row)
357 593 for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) {
... ... @@ -384,11 +620,17 @@ void GSymMatrix::cholesky_invert(int compress)
384 620  
385 621 // Case C: all matrix elements are zero
386 622 else
387   - throw all_zero("GSymMatrix cholesky_invert");
  623 + throw matrix_zero("GSymMatrix::cholesky_invert(int)");
388 624  
389 625 }
390 626  
391 627  
  628 +/*==========================================================================
  629 + = =
  630 + = GSymMatrix private functions =
  631 + = =
  632 + ==========================================================================*/
  633 +
392 634 /***************************************************************************
393 635 * GSymMatrix set_inx *
394 636 * ----------------------------------------------------------------------- *
... ... @@ -399,8 +641,8 @@ void GSymMatrix::cholesky_invert(int compress)
399 641 void GSymMatrix::set_inx(void)
400 642 {
401 643 // Allocate loop variables and pointers
402   - unsigned row;
403   - unsigned col;
  644 + int row;
  645 + int col;
404 646  
405 647 // Find all nonzero rows/cols
406 648 m_num_inx = 0;
... ... @@ -430,37 +672,31 @@ void GSymMatrix::set_inx(void)
430 672 }
431 673  
432 674  
  675 +/*==========================================================================
  676 + = =
  677 + = GSymMatrix friends =
  678 + = =
  679 + ==========================================================================*/
  680 +
433 681 /***************************************************************************
434   - * Class exception handlers *
  682 + * Matrix absolute values *
435 683 ***************************************************************************/
436   -// Matrix not symmetric
437   -GSymMatrix::not_sym::not_sym(string origin, unsigned cols, unsigned rows)
  684 +GSymMatrix fabs(const GSymMatrix& m)
438 685 {
439   - m_origin = origin;
440   - ostringstream s_rows;
441   - ostringstream s_cols;
442   - s_rows << rows;
443   - s_cols << cols;
444   - m_message = "Matrix is not symmetric [" + s_rows.str() + "," +
445   - s_cols.str() + "]";
  686 + // Define result matrix
  687 + GSymMatrix result(m.m_rows,m.m_cols);
  688 +
  689 + // Convert all elements to absolute values
  690 + for (int i = 0; i < m.m_elements; ++i)
  691 + result.m_data[i] = fabs(m.m_data[i]);
  692 +
  693 + // Return result
  694 + return result;
446 695 }
447 696  
448   -// Matrix not positive definite
449   -GSymMatrix::not_pos_definite::not_pos_definite(string origin, unsigned row,
450   - double sum)
451   -{
452   - m_origin = origin;
453   - ostringstream s_rows;
454   - ostringstream s_sum;
455   - s_rows << row;
456   - s_sum << scientific << sum;
457   - m_message = "Matrix is not positive definite (sum " + s_sum.str() +
458   - " occured in row " + s_rows.str() + ")";
459   -}
460 697  
461   -// All matrix elements are zero
462   -GSymMatrix::all_zero::all_zero(string origin)
463   -{
464   - m_origin = origin;
465   - m_message = "All matrix elements are zero";
466   -}
  698 +/*==========================================================================
  699 + = =
  700 + = GSymMatrix exception classes =
  701 + = =
  702 + ==========================================================================*/
... ...
src/GSymMatrix.hpp
... ... @@ -33,113 +33,106 @@ using namespace std;
33 33 * GSymMatrix class definition *
34 34 ***************************************************************************/
35 35 class GSymMatrix : public GMatrix {
36   - // Operator friends
37   - friend GSymMatrix operator+ (const double& a, const GSymMatrix& b);
38   - friend GSymMatrix operator- (const double& a, const GSymMatrix& b);
39   - friend GSymMatrix operator* (const double& a, const GSymMatrix& b);
  36 + // Binary operator friends
  37 + friend GSymMatrix operator* (const double& a, const GSymMatrix& b);
  38 + friend GSymMatrix operator* (const GSymMatrix& a, const double& b);
  39 + friend GSymMatrix operator/ (const GSymMatrix& a, const double& b);
40 40  
41 41 // I/O friends
42   - // ...
43   -
  42 + // USE_BASE: friend ostream& operator<< (ostream& os, const GSymMatrix& m);
  43 +
44 44 // Friend functions
45 45 friend GSymMatrix transpose(const GSymMatrix& m);
46 46 friend GSymMatrix fabs(const GSymMatrix& m);
47 47 friend GSymMatrix cholesky_decompose(const GSymMatrix& m, int compress = 1);
48 48 friend GSymMatrix cholesky_invert(const GSymMatrix& m, int compress = 1);
49   - friend GMatrix full(const GSymMatrix& m);
50   - friend GMatrix lower_triangle(const GSymMatrix& m);
51   - friend GMatrix upper_triangle(const GSymMatrix& m);
  49 +
52 50 public:
53 51 // Constructors and destructors (not inherited)
54   - GSymMatrix(unsigned rows, unsigned cols);
  52 + GSymMatrix(int rows, int cols);
55 53 GSymMatrix(const GSymMatrix& m);
56   - ~GSymMatrix();
  54 + virtual ~GSymMatrix();
57 55  
58 56 // Matrix element access operators
59   - double& operator() (unsigned row, unsigned col);
60   - const double& operator() (unsigned row, unsigned col) const;
  57 + virtual double& operator() (int row, int col);
  58 + virtual const double& operator() (int row, int col) const;
61 59  
62 60 // Matrix assignment operators (not inherited)
63   - GSymMatrix& operator= (const GSymMatrix& m);
64   - GSymMatrix& operator= (const double& d);
65   -
66   - // Specific matrix operators (structure dependent)
67   - GSymMatrix operator+ (const GSymMatrix& m) const;
68   - GSymMatrix operator- (const GSymMatrix& m) const;
69   - GSymMatrix operator* (const GSymMatrix& m) const;
70   - GVector operator* (const GVector& v) const;
71   - GSymMatrix operator+ (const double& d) const;
72   - GSymMatrix operator- (const double& d) const;
73   - GSymMatrix operator* (const double& d) const;
74   - GSymMatrix operator/ (const double& d) const;
75   - GSymMatrix operator- () const;
76   -
77   - // Specific matrix functions
78   - void transpose(); // Inplace transpose of matrix
79   - void cholesky_decompose(int compress = 1); // Inplace Cholesky decomposition
80   - GVector cholesky_solver(const GVector& v, int compress = 1); // Cholesky solver
81   - void cholesky_invert(int compress = 1); // Inplace Cholesky matrix inverter
82   -
83   - // Exception: Matrix not symmetric
84   - class not_sym : public GException {
85   - public:
86   - not_sym(string origin, unsigned cols, unsigned rows);
87   - };
  61 + virtual GSymMatrix& operator= (const GSymMatrix& m);
88 62  
89   - // Exception: Matrix not positive definite
90   - class not_pos_definite : public GException {
91   - public:
92   - not_pos_definite(string origin, unsigned row, double sum);
93   - };
  63 + // Binary operators
  64 + virtual GSymMatrix operator+ (const GSymMatrix& m) const;
  65 + virtual GSymMatrix operator- (const GSymMatrix& m) const;
  66 + virtual GSymMatrix operator* (const GSymMatrix& m) const;
  67 + virtual GVector operator* (const GVector& v) const;
  68 + // USE_BASE: virtual int operator== (const GSymMatrix& m) const;
  69 + // USE_BASE: virtual int operator!= (const GSymMatrix& m) const;
94 70  
  71 + // Unary operators
  72 + GSymMatrix operator- () const;
  73 + // USE_BASE: virtual GSymMatrix& operator+= (const GSymMatrix& m);
  74 + // USE_BASE: virtual GSymMatrix& operator-= (const GSymMatrix& m);
  75 + virtual GSymMatrix& operator*= (const GSymMatrix& m);
  76 + virtual GSymMatrix& operator*= (const double& d);
  77 + virtual GSymMatrix& operator/= (const double& d);
  78 +
  79 + // Matrix functions
  80 + // USE_BASE: virtual int rows() const { return m_rows; }
  81 + // USE_BASE: virtual int cols() const { return m_cols; }
  82 + // USE_BASE: virtual double min() const;
  83 + // USE_BASE: virtual double max() const;
  84 + virtual double sum() const;
  85 + virtual void transpose() { return; }
  86 + virtual GVector extract_row(int row) const;
  87 + virtual GVector extract_col(int col) const;
  88 + virtual GMatrix convert_to_full() const;
  89 + virtual GMatrix extract_lower_triangle() const;
  90 + virtual GMatrix extract_upper_triangle() const;
  91 + virtual void cholesky_decompose(int compress = 1);
  92 + virtual GVector cholesky_solver(const GVector& v, int compress = 1);
  93 + virtual void cholesky_invert(int compress = 1);
  94 +
95 95 // Exception: All matrix elements are zero
96 96 class all_zero : public GException {
97 97 public:
98 98 all_zero(string origin);
99 99 };
  100 +
100 101 private:
101   - void set_inx(void); // Set indices of non-zero rows/columns
102   - unsigned m_num_inx; // Number of non-zero rows/columns
103   - unsigned* m_inx; // Indices of non-zero rows/columns
  102 + void set_inx(void); // Set indices of non-zero rows/columns
  103 + int m_num_inx; // Number of non-zero rows/columns
  104 + int* m_inx; // Indices of non-zero rows/columns
104 105 };
105 106  
106 107  
107 108 /***************************************************************************
108   - * Inline members that override base class members *
  109 + * Inline member functions *
109 110 ***************************************************************************/
110   -// Scalar assignment operator: GSymMatrix = double
  111 +// Matrix element access operator
111 112 inline
112   -GSymMatrix& GSymMatrix::operator= (const double& d)
113   -{
114   - this->GMatrix::operator=(d);
115   - return *this;
116   -}
117   -
118   -// Matrix element access operator: GSymMatrix(row,col)
119   -inline
120   -double& GSymMatrix::operator() (unsigned row, unsigned col)
  113 +double& GSymMatrix::operator() (int row, int col)
121 114 {
122 115 #if defined(G_RANGE_CHECK)
123 116 if (row >= m_rows || col >= m_cols)
124 117 throw out_of_range("GSymMatrix access", row, col, m_rows, m_cols);
125 118 #endif
126   - unsigned inx = (row >= col) ? m_colstart[col]+(row-col) : m_colstart[row]+(col-row);
  119 + int inx = (row >= col) ? m_colstart[col]+(row-col) : m_colstart[row]+(col-row);
127 120 return m_data[inx];
128 121 }
129 122  
130   -// Matrix element access operator (const version): GSymMatrix(row,col)
  123 +// Matrix element access operator (const version)
131 124 inline
132   -const double& GSymMatrix::operator() (unsigned row, unsigned col) const
  125 +const double& GSymMatrix::operator() (int row, int col) const
133 126 {
134 127 #if defined(G_RANGE_CHECK)
135 128 if (row >= m_rows || col >= m_cols)
136 129 throw out_of_range("GSymMatrix access", row, col, m_rows, m_cols);
137 130 #endif
138   - unsigned inx = (row >= col) ? m_colstart[col]+(row-col) : m_colstart[row]+(col-row);
  131 + int inx = (row >= col) ? m_colstart[col]+(row-col) : m_colstart[row]+(col-row);
139 132 return m_data[inx];
140 133 }
141 134  
142   -// Matrix addition: GSymMatrix + GSymMatrix
  135 +// Binary matrix addition
143 136 inline
144 137 GSymMatrix GSymMatrix::operator+ (const GSymMatrix& m) const
145 138 {
... ... @@ -148,7 +141,7 @@ GSymMatrix GSymMatrix::operator+ (const GSymMatrix&amp; m) const
148 141 return result;
149 142 }
150 143  
151   -// Matrix subtraction: GSymMatrix - GSymMatrix
  144 +// Binary matrix subtraction
152 145 inline
153 146 GSymMatrix GSymMatrix::operator- (const GSymMatrix& m) const
154 147 {
... ... @@ -157,116 +150,68 @@ GSymMatrix GSymMatrix::operator- (const GSymMatrix&amp; m) const
157 150 return result;
158 151 }
159 152  
160   -// Matrix/Vector multiplication: GSymMatrix * GVector
  153 +// Binary matrix multiplication
161 154 inline
162   -GVector GSymMatrix::operator* (const GVector& v) const
163   -{
164   - return (this->GMatrix::operator*(v));
165   -}
166   -
167   -// Matrix scaling: GSymMatrix + double
168   -inline
169   -GSymMatrix GSymMatrix::operator+ (const double& d) const
  155 +GSymMatrix GSymMatrix::operator* (const GSymMatrix& m) const
170 156 {
171   - GSymMatrix result = (*this);
172   - result += d;
173   - return result;
174   -}
175   -
176   -// Matrix scaling: GSymMatrix - double
177   -inline
178   -GSymMatrix GSymMatrix::operator- (const double& d) const
179   -{
180   - GSymMatrix result = (*this);
181   - result -= d;
182   - return result;
183   -}
184   -
185   -// Matrix scaling: GSymMatrix * double
186   -inline
187   -GSymMatrix GSymMatrix::operator* (const double& d) const
188   -{
189   - GSymMatrix result = (*this);
190   - result *= d;
191   - return result;
192   -}
193   -
194   -// Matrix inverse scaling: GSymMatrix * double
195   -inline
196   -GSymMatrix GSymMatrix::operator/ (const double& d) const
197   -{
198   - GSymMatrix result = (*this);
199   - result /= d;
  157 + GSymMatrix result = *this;
  158 + result *= m;
200 159 return result;
201 160 }
202 161  
203   -// Unary minus operator
  162 +// Unary scalar multiplication
204 163 inline
205   -GSymMatrix GSymMatrix::operator- ( ) const
  164 +GSymMatrix& GSymMatrix::operator*= (const double& d)
206 165 {
207   - GSymMatrix result = *this;
208   - for (unsigned i = 0; i < m_elements; ++i)
209   - result.m_data[i] = -result.m_data[i];
210   - return result;
  166 + this->GMatrix::operator*=(d);
211 167 }
212 168  
213   -// Matrix transpose
  169 +// Unary scalar division
214 170 inline
215   -void GSymMatrix::transpose()
  171 +GSymMatrix& GSymMatrix::operator/= (const double& d)
216 172 {
217   - return;
  173 + this->GMatrix::operator/=(d);
218 174 }
219 175  
220 176  
221   -
222 177 /***************************************************************************
223 178 * Inline friends *
224 179 ***************************************************************************/
225   -// Matrix addition: double + GSymMatrix
226   -inline
227   -GSymMatrix operator+ (const double& a, const GSymMatrix& b)
  180 +// Binary matrix scaling (matrix is left operand)
  181 +inline
  182 +GSymMatrix operator* (const GSymMatrix& a, const double& b)
228 183 {
229   - GSymMatrix result = b;
230   - result += a;
  184 + GSymMatrix result = a;
  185 + result *= b;
231 186 return result;
232 187 }
233 188  
234   -// Matrix subtracxtion: double * GSymMatrix
  189 +// Binary matrix scaling (matrix is right operand)
235 190 inline
236   -GSymMatrix operator- (const double& a, const GSymMatrix& b)
  191 +GSymMatrix operator* (const double& a, const GSymMatrix& b)
237 192 {
238 193 GSymMatrix result = b;
239   - result -= a;
  194 + result *= a;
240 195 return result;
241 196 }
242 197  
243   -// Matrix scaling: double * GSymMatrix
244   -inline
245   -GSymMatrix operator* (const double& a, const GSymMatrix& b)
  198 +// Binary matrix division (matrix is left operand)
  199 +inline
  200 +GSymMatrix operator/ (const GSymMatrix& a, const double& b)
246 201 {
247   - GSymMatrix result = b;
248   - result *= a;
  202 + GSymMatrix result = a;
  203 + result /= b;
249 204 return result;
250 205 }
251 206  
252   -// Matrix transpose: transpose(GSymMatrix)
  207 +// Matrix transpose function
253 208 inline
254 209 GSymMatrix transpose(const GSymMatrix& m)
255 210 {
256 211 return m;
257 212 }
258 213  
259   -// Matrix absolute: fabs(GSymMatrix)
260   -inline
261   -GSymMatrix fabs(const GSymMatrix& m)
262   -{
263   - GSymMatrix result = m;
264   - for (unsigned i = 0; i < result.m_elements; ++i)
265   - result.m_data[i] = fabs(result.m_data[i]);
266   - return result;
267   -}
268   -
269   -// Cholesky decomposition: cholesky_decompose(GSymMatrix)
  214 +// Cholesky decomposition
270 215 inline
271 216 GSymMatrix cholesky_decompose(const GSymMatrix& m, int compress)
272 217 {
... ... @@ -275,7 +220,7 @@ GSymMatrix cholesky_decompose(const GSymMatrix&amp; m, int compress)
275 220 return result;
276 221 }
277 222  
278   -// Inversion using Cholesky decomposition: cholesky_invert(GSymMatrix)
  223 +// Matrix inversion using Cholesky decomposition
279 224 inline
280 225 GSymMatrix cholesky_invert(const GSymMatrix& m, int compress)
281 226 {
... ... @@ -284,40 +229,4 @@ GSymMatrix cholesky_invert(const GSymMatrix&amp; m, int compress)
284 229 return result;
285 230 }
286 231  
287   -// Convert symmetric matrix into full matrix: full(GSymMatrix)
288   -inline
289   -GMatrix full(const GSymMatrix& m)
290   -{
291   - GMatrix result(m.m_rows,m.m_cols);
292   - for (unsigned row = 0; row < m.m_rows; ++row) {
293   - for (unsigned col = 0; col < m.m_cols; ++col)
294   - result(row,col) = m(row,col);
295   - }
296   - return result;
297   -}
298   -
299   -// Convert symmetric matrix into lower triangle full matrix: lower_triangle(GSymMatrix)
300   -inline
301   -GMatrix lower_triangle(const GSymMatrix& m)
302   -{
303   - GMatrix result(m.m_rows,m.m_cols);
304   - for (unsigned row = 0; row < m.m_rows; ++row) {
305   - for (unsigned col = 0; col <= row; ++col)
306   - result(row,col) = m.m_data[m.m_colstart[col]+(row-col)];
307   - }
308   - return result;
309   -}
310   -
311   -// Convert symmetric matrix into upper triangle full matrix: lower_triangle(GSymMatrix)
312   -inline
313   -GMatrix upper_triangle(const GSymMatrix& m)
314   -{
315   - GMatrix result(m.m_rows,m.m_cols);
316   - for (unsigned row = 0; row < m.m_rows; ++row) {
317   - for (unsigned col = row; col < m.m_cols; ++col)
318   - result(row,col) = m.m_data[m.m_colstart[row]+(col-row)];
319   - }
320   - return result;
321   -}
322   -
323 232 #endif /* GSYMMATRIX_HPP */
... ...
src/GVector.cpp
... ... @@ -15,10 +15,16 @@
15 15 #include "GVector.hpp"
16 16  
17 17  
  18 +/*==========================================================================
  19 + = =
  20 + = GVector constructors/destructors =
  21 + = =
  22 + ==========================================================================*/
  23 +
18 24 /***************************************************************************
19 25 * GVector constructor *
20 26 ***************************************************************************/
21   -GVector::GVector(unsigned num)
  27 +GVector::GVector(int num)
22 28 {
23 29 // Throw exception if requested vector length is zero
24 30 if (num == 0)
... ... @@ -31,8 +37,11 @@ GVector::GVector(unsigned num)
31 37  
32 38 // Store vector size and initialize elements to 0.0
33 39 m_num = num;
34   - for (unsigned i = 0; i < m_num; ++i)
  40 + for (int i = 0; i < m_num; ++i)
35 41 m_data[i] = 0.0;
  42 +
  43 + // Return
  44 + return;
36 45 }
37 46  
38 47  
... ... @@ -46,15 +55,42 @@ GVector::~GVector()
46 55 m_num = 0;
47 56 delete[] m_data;
48 57 }
  58 +
  59 + // Return
  60 + return;
49 61 }
50 62  
51 63  
  64 +/*==========================================================================
  65 + = =
  66 + = GVector operators =
  67 + = =
  68 + ==========================================================================*/
  69 +
  70 +/*==========================================================================
  71 + = =
  72 + = GVector member functions =
  73 + = =
  74 + ==========================================================================*/
  75 +
  76 +/*==========================================================================
  77 + = =
  78 + = GVector private functions =
  79 + = =
  80 + ==========================================================================*/
  81 +
  82 +/*==========================================================================
  83 + = =
  84 + = GVector friends =
  85 + = =
  86 + ==========================================================================*/
  87 +
52 88 /***************************************************************************
53 89 * GVector output operator *
54 90 ***************************************************************************/
55 91 ostream& operator<< (ostream& os, const GVector& v)
56 92 {
57   - for (unsigned i = 0; i < v.m_num; ++i) {
  93 + for (int i = 0; i < v.m_num; ++i) {
58 94 os << v(i);
59 95 if (i != v.m_num-1)
60 96 os << ", ";
... ... @@ -80,12 +116,17 @@ GVector cross(const GVector &amp;a, const GVector &amp;b)
80 116 }
81 117  
82 118  
  119 +/*==========================================================================
  120 + = =
  121 + = GSparseMatrix exception classes =
  122 + = =
  123 + ==========================================================================*/
  124 +
83 125 /***************************************************************************
84 126 * Class exception handlers *
85 127 ***************************************************************************/
86 128 // Vector index out of range
87   -GVector::out_of_range::out_of_range(string origin, unsigned inx,
88   - unsigned elements)
  129 +GVector::out_of_range::out_of_range(string origin, int inx, int elements)
89 130 {
90 131 m_origin = origin;
91 132 if (elements > 0) {
... ... @@ -102,8 +143,7 @@ GVector::out_of_range::out_of_range(string origin, unsigned inx,
102 143 }
103 144  
104 145 // Vector dimensions differ
105   -GVector::dim_mismatch::dim_mismatch(string origin, unsigned size1,
106   - unsigned size2)
  146 +GVector::dim_mismatch::dim_mismatch(string origin, int size1, int size2)
107 147 {
108 148 m_origin = origin;
109 149 ostringstream s_size1;
... ... @@ -115,7 +155,7 @@ GVector::dim_mismatch::dim_mismatch(string origin, unsigned size1,
115 155 }
116 156  
117 157 // Invalid vector dimension for cross product
118   -GVector::bad_cross_dim::bad_cross_dim(unsigned elements)
  158 +GVector::bad_cross_dim::bad_cross_dim(int elements)
119 159 {
120 160 ostringstream s_elements;
121 161 s_elements << elements;
... ...
src/GVector.hpp
... ... @@ -36,7 +36,8 @@ using namespace std;
36 36 class GVector {
37 37 // Friend classes
38 38 friend class GMatrix;
39   - friend class GMatrixSym;
  39 + friend class GSymMatrix;
  40 + friend class GSparseMatrix;
40 41  
41 42 // Operator friends
42 43 friend GVector operator+ (const GVector &a, const GVector &b);
... ... @@ -61,6 +62,8 @@ class GVector {
61 62 friend double min(const GVector &v);
62 63 friend double max(const GVector &v);
63 64 friend double sum(const GVector &v);
  65 + friend GVector perm(const GVector &v, const int *p);
  66 + friend GVector iperm(const GVector &v, const int *p);
64 67 friend GVector acos(const GVector &v);
65 68 friend GVector acosh(const GVector &v);
66 69 friend GVector asin(const GVector &v);
... ... @@ -81,13 +84,13 @@ class GVector {
81 84  
82 85 public:
83 86 // Constructors and destructors
84   - explicit GVector(unsigned num);
  87 + explicit GVector(int num);
85 88 GVector(const GVector& v);
86 89 ~GVector();
87 90  
88 91 // Vector element access operators
89   - double& operator() (unsigned inx);
90   - const double& operator() (unsigned inx) const;
  92 + double& operator() (int inx);
  93 + const double& operator() (int inx) const;
91 94  
92 95 // Vector operators
93 96 GVector& operator= (const GVector& v);
... ... @@ -101,28 +104,28 @@ public:
101 104 GVector operator- () const;
102 105  
103 106 // Vector functions
104   - unsigned size() const; // Return dimension of vector
  107 + int size() const; // Return dimension of vector
105 108  
106 109 // Exception: Vector index out of range
107 110 class out_of_range : public GException {
108 111 public:
109   - out_of_range(string origin, unsigned inx, unsigned elements);
  112 + out_of_range(string origin, int inx, int elements);
110 113 };
111 114  
112 115 // Exception: Vector dimensions mismatch
113 116 class dim_mismatch : public GException {
114 117 public:
115   - dim_mismatch(string origin, unsigned size1, unsigned size2);
  118 + dim_mismatch(string origin, int size1, int size2);
116 119 };
117 120  
118 121 // Exception: Invalid vector dimension for cross product
119 122 class bad_cross_dim : public GException {
120 123 public:
121   - bad_cross_dim(unsigned elements);
  124 + bad_cross_dim(int elements);
122 125 };
123 126 private:
124   - unsigned m_num;
125   - double* m_data;
  127 + int m_num;
  128 + double* m_data;
126 129 };
127 130  
128 131  
... ... @@ -138,13 +141,13 @@ GVector::GVector(const GVector&amp; v)
138 141 if (m_data == NULL)
139 142 throw mem_alloc("GVector copy constructor", v.m_num);
140 143 m_num = v.m_num;
141   - for (unsigned i = 0; i < m_num; ++i)
  144 + for (int i = 0; i < m_num; ++i)
142 145 m_data[i] = v.m_data[i];
143 146 }
144 147  
145 148 // Vector element access operator
146 149 inline
147   -double& GVector::operator() (unsigned inx)
  150 +double& GVector::operator() (int inx)
148 151 {
149 152 #if defined(G_RANGE_CHECK)
150 153 if (inx >= m_num)
... ... @@ -155,7 +158,7 @@ double&amp; GVector::operator() (unsigned inx)
155 158  
156 159 // Vector element access operator (const version)
157 160 inline
158   -const double& GVector::operator() (unsigned inx) const
  161 +const double& GVector::operator() (int inx) const
159 162 {
160 163 #if defined(G_RANGE_CHECK)
161 164 if (inx >= m_num)
... ... @@ -168,12 +171,15 @@ const double&amp; GVector::operator() (unsigned inx) const
168 171 inline
169 172 GVector& GVector::operator= (const GVector& v)
170 173 {
171   - m_data = new double[v.m_num];
172   - if (m_data == NULL)
173   - throw mem_alloc("GVector assignment operator", v.m_num);
174   - m_num = v.m_num;
175   - for (unsigned i = 0; i < m_num; ++i)
176   - m_data[i] = v.m_data[i];
  174 + if (this != &v) {
  175 + if (m_data != NULL) delete [] m_data;
  176 + m_data = new double[v.m_num];
  177 + if (m_data == NULL)
  178 + throw mem_alloc("GVector assignment operator", v.m_num);
  179 + m_num = v.m_num;
  180 + for (int i = 0; i < m_num; ++i)
  181 + m_data[i] = v.m_data[i];
  182 + }
177 183 return *this;
178 184 }
179 185  
... ... @@ -183,7 +189,7 @@ GVector&amp; GVector::operator+= (const GVector&amp; v)
183 189 {
184 190 if (m_num != v.m_num)
185 191 throw dim_mismatch("GVector += operator", m_num, v.m_num);
186   - for (unsigned i = 0; i < m_num; ++i)
  192 + for (int i = 0; i < m_num; ++i)
187 193 m_data[i] += v.m_data[i];
188 194 return *this;
189 195 }
... ... @@ -194,7 +200,7 @@ GVector&amp; GVector::operator-= (const GVector&amp; v)
194 200 {
195 201 if (m_num != v.m_num)
196 202 throw dim_mismatch("GVector -= operator", m_num, v.m_num);
197   - for (unsigned i = 0; i < m_num; ++i)
  203 + for (int i = 0; i < m_num; ++i)
198 204 m_data[i] -= v.m_data[i];
199 205 return *this;
200 206 }
... ... @@ -203,7 +209,7 @@ GVector&amp; GVector::operator-= (const GVector&amp; v)
203 209 inline
204 210 GVector& GVector::operator= (const double& v)
205 211 {
206   - for (unsigned i = 0; i < m_num; ++i)
  212 + for (int i = 0; i < m_num; ++i)
207 213 m_data[i] = v;
208 214 return *this;
209 215 }
... ... @@ -212,7 +218,7 @@ GVector&amp; GVector::operator= (const double&amp; v)
212 218 inline
213 219 GVector& GVector::operator+= (const double& v)
214 220 {
215   - for (unsigned i = 0; i < m_num; ++i)
  221 + for (int i = 0; i < m_num; ++i)
216 222 m_data[i] += v;
217 223 return *this;
218 224 }
... ... @@ -221,7 +227,7 @@ GVector&amp; GVector::operator+= (const double&amp; v)
221 227 inline
222 228 GVector& GVector::operator-= (const double& v)
223 229 {
224   - for (unsigned i = 0; i < m_num; ++i)
  230 + for (int i = 0; i < m_num; ++i)
225 231 m_data[i] -= v;
226 232 return *this;
227 233 }
... ... @@ -230,7 +236,7 @@ GVector&amp; GVector::operator-= (const double&amp; v)
230 236 inline
231 237 GVector& GVector::operator*= (const double& v)
232 238 {
233   - for (unsigned i = 0; i < m_num; ++i)
  239 + for (int i = 0; i < m_num; ++i)
234 240 m_data[i] *= v;
235 241 return *this;
236 242 }
... ... @@ -239,7 +245,7 @@ GVector&amp; GVector::operator*= (const double&amp; v)
239 245 inline
240 246 GVector& GVector::operator/= (const double& v)
241 247 {
242   - for (unsigned i = 0; i < m_num; ++i)
  248 + for (int i = 0; i < m_num; ++i)
243 249 m_data[i] /= v;
244 250 return *this;
245 251 }
... ... @@ -249,14 +255,14 @@ inline
249 255 GVector GVector::operator- ( ) const
250 256 {
251 257 GVector result = *this;
252   - for (unsigned i = 0; i < m_num; ++i)
  258 + for (int i = 0; i < m_num; ++i)
253 259 result.m_data[i] = -result.m_data[i];
254 260 return result;
255 261 }
256 262  
257 263 // Return size of vector
258 264 inline
259   -unsigned GVector::size() const
  265 +int GVector::size() const
260 266 {
261 267 return m_num;
262 268 }
... ... @@ -326,7 +332,7 @@ double operator* (const GVector&amp; a, const GVector&amp; b)
326 332 if (a.m_num != b.m_num)
327 333 throw GVector::dim_mismatch("GVector scalar product", a.m_num, b.m_num);
328 334 double result = 0.0;
329   - for (unsigned i = 0; i < a.m_num; ++i)
  335 + for (int i = 0; i < a.m_num; ++i)
330 336 result += (a.m_data[i] * b.m_data[i]);
331 337 return result;
332 338 }
... ... @@ -363,7 +369,7 @@ inline
363 369 double norm(const GVector &v)
364 370 {
365 371 double result = 0.0;
366   - for (unsigned i = 0; i < v.m_num; ++i)
  372 + for (int i = 0; i < v.m_num; ++i)
367 373 result += (v.m_data[i] * v.m_data[i]);
368 374 result = (result > 0.0) ? sqrt(result) : 0.0;
369 375 return result;
... ... @@ -374,7 +380,7 @@ inline
374 380 double min(const GVector &v)
375 381 {
376 382 double result = v.m_data[0];
377   - for (unsigned i = 1; i < v.m_num; ++i) {
  383 + for (int i = 1; i < v.m_num; ++i) {
378 384 if (v.m_data[i] < result)
379 385 result = v.m_data[i];
380 386 }
... ... @@ -386,7 +392,7 @@ inline
386 392 double max(const GVector &v)
387 393 {
388 394 double result = v.m_data[0];
389   - for (unsigned i = 1; i < v.m_num; ++i) {
  395 + for (int i = 1; i < v.m_num; ++i) {
390 396 if (v.m_data[i] > result)
391 397 result = v.m_data[i];
392 398 }
... ... @@ -398,17 +404,45 @@ inline
398 404 double sum(const GVector &v)
399 405 {
400 406 double result = 0.0;
401   - for (unsigned i = 0; i < v.m_num; ++i)
  407 + for (int i = 0; i < v.m_num; ++i)
402 408 result += v.m_data[i];
403 409 return result;
404 410 }
405 411  
  412 +// Vector permutation
  413 +inline
  414 +GVector perm(const GVector &v, const int *p)
  415 +{
  416 + GVector result(v.m_num);
  417 + if (p == NULL)
  418 + result = v;
  419 + else {
  420 + for (int i = 0; i < v.m_num; ++i)
  421 + result.m_data[i] = v.m_data[p[i]];
  422 + }
  423 + return result;
  424 +}
  425 +
  426 +// Inverse vector permutation
  427 +inline
  428 +GVector iperm(const GVector &v, const int *p)
  429 +{
  430 + GVector result(v.m_num);
  431 + if (p == NULL)
  432 + result = v;
  433 + else {
  434 + for (int i = 0; i < v.m_num; ++i)
  435 + result.m_data[p[i]] = v.m_data[i];
  436 + }
  437 + return result;
  438 +}
  439 +
406 440 // Vector acos
407 441 inline
408 442 GVector acos(const GVector &v)
409 443 {
410 444 GVector result(v.m_num);
411   - for (unsigned i = 0; i < v.m_num; ++i)
  445 + for (int i = 0; i < v.m_num; ++i)
412 446 result.m_data[i] = acos(v.m_data[i]);
413 447 return result;
414 448 }
... ... @@ -418,7 +452,7 @@ inline
418 452 GVector acosh(const GVector &v)
419 453 {
420 454 GVector result(v.m_num);
421   - for (unsigned i = 0; i < v.m_num; ++i)
  455 + for (int i = 0; i < v.m_num; ++i)
422 456 result.m_data[i] = acosh(v.m_data[i]);
423 457 return result;
424 458 }
... ... @@ -428,7 +462,7 @@ inline
428 462 GVector asin(const GVector &v)
429 463 {
430 464 GVector result(v.m_num);
431   - for (unsigned i = 0; i < v.m_num; ++i)
  465 + for (int i = 0; i < v.m_num; ++i)
432 466 result.m_data[i] = asin(v.m_data[i]);
433 467 return result;
434 468 }
... ... @@ -438,7 +472,7 @@ inline
438 472 GVector asinh(const GVector &v)
439 473 {
440 474 GVector result(v.m_num);
441   - for (unsigned i = 0; i < v.m_num; ++i)
  475 + for (int i = 0; i < v.m_num; ++i)
442 476 result.m_data[i] = asinh(v.m_data[i]);
443 477 return result;
444 478 }
... ... @@ -448,7 +482,7 @@ inline
448 482 GVector atan(const GVector &v)
449 483 {
450 484 GVector result(v.m_num);
451   - for (unsigned i = 0; i < v.m_num; ++i)
  485 + for (int i = 0; i < v.m_num; ++i)
452 486 result.m_data[i] = atan(v.m_data[i]);
453 487 return result;
454 488 }
... ... @@ -458,7 +492,7 @@ inline
458 492 GVector atanh(const GVector &v)
459 493 {
460 494 GVector result(v.m_num);
461   - for (unsigned i = 0; i < v.m_num; ++i)
  495 + for (int i = 0; i < v.m_num; ++i)
462 496 result.m_data[i] = atanh(v.m_data[i]);
463 497 return result;
464 498 }
... ... @@ -468,7 +502,7 @@ inline
468 502 GVector cos(const GVector &v)
469 503 {
470 504 GVector result(v.m_num);
471   - for (unsigned i = 0; i < v.m_num; ++i)
  505 + for (int i = 0; i < v.m_num; ++i)
472 506 result.m_data[i] = cos(v.m_data[i]);
473 507 return result;
474 508 }
... ... @@ -478,7 +512,7 @@ inline
478 512 GVector cosh(const GVector &v)
479 513 {
480 514 GVector result(v.m_num);
481   - for (unsigned i = 0; i < v.m_num; ++i)
  515 + for (int i = 0; i < v.m_num; ++i)
482 516 result.m_data[i] = cosh(v.m_data[i]);
483 517 return result;
484 518 }
... ... @@ -488,7 +522,7 @@ inline
488 522 GVector exp(const GVector &v)
489 523 {
490 524 GVector result(v.m_num);
491   - for (unsigned i = 0; i < v.m_num; ++i)
  525 + for (int i = 0; i < v.m_num; ++i)
492 526 result.m_data[i] = exp(v.m_data[i]);
493 527 return result;
494 528 }
... ... @@ -498,7 +532,7 @@ inline
498 532 GVector fabs(const GVector &v)
499 533 {
500 534 GVector result(v.m_num);
501   - for (unsigned i = 0; i < v.m_num; ++i)
  535 + for (int i = 0; i < v.m_num; ++i)
502 536 result.m_data[i] = fabs(v.m_data[i]);
503 537 return result;
504 538 }
... ... @@ -508,7 +542,7 @@ inline
508 542 GVector log(const GVector &v)
509 543 {
510 544 GVector result(v.m_num);
511   - for (unsigned i = 0; i < v.m_num; ++i)
  545 + for (int i = 0; i < v.m_num; ++i)
512 546 result.m_data[i] = log(v.m_data[i]);
513 547 return result;
514 548 }
... ... @@ -518,7 +552,7 @@ inline
518 552 GVector log10(const GVector &v)
519 553 {
520 554 GVector result(v.m_num);
521   - for (unsigned i = 0; i < v.m_num; ++i)
  555 + for (int i = 0; i < v.m_num; ++i)
522 556 result.m_data[i] = log10(v.m_data[i]);
523 557 return result;
524 558 }
... ... @@ -528,7 +562,7 @@ inline
528 562 GVector sin(const GVector &v)
529 563 {
530 564 GVector result(v.m_num);
531   - for (unsigned i = 0; i < v.m_num; ++i)
  565 + for (int i = 0; i < v.m_num; ++i)
532 566 result.m_data[i] = sin(v.m_data[i]);
533 567 return result;
534 568 }
... ... @@ -538,7 +572,7 @@ inline
538 572 GVector sinh(const GVector &v)
539 573 {
540 574 GVector result(v.m_num);
541   - for (unsigned i = 0; i < v.m_num; ++i)
  575 + for (int i = 0; i < v.m_num; ++i)
542 576 result.m_data[i] = sinh(v.m_data[i]);
543 577 return result;
544 578 }
... ... @@ -548,7 +582,7 @@ inline
548 582 GVector sqrt(const GVector &v)
549 583 {
550 584 GVector result(v.m_num);
551   - for (unsigned i = 0; i < v.m_num; ++i)
  585 + for (int i = 0; i < v.m_num; ++i)
552 586 result.m_data[i] = sqrt(v.m_data[i]);
553 587 return result;
554 588 }
... ... @@ -558,7 +592,7 @@ inline
558 592 GVector tan(const GVector &v)
559 593 {
560 594 GVector result(v.m_num);
561   - for (unsigned i = 0; i < v.m_num; ++i)
  595 + for (int i = 0; i < v.m_num; ++i)
562 596 result.m_data[i] = tan(v.m_data[i]);
563 597 return result;
564 598 }
... ... @@ -568,7 +602,7 @@ inline
568 602 GVector tanh(const GVector &v)
569 603 {
570 604 GVector result(v.m_num);
571   - for (unsigned i = 0; i < v.m_num; ++i)
  605 + for (int i = 0; i < v.m_num; ++i)
572 606 result.m_data[i] = tanh(v.m_data[i]);
573 607 return result;
574 608 }
... ... @@ -579,7 +613,7 @@ int operator== (const GVector &amp;a, const GVector &amp;b)
579 613 {
580 614 int result = 1;
581 615 if (a.m_num == b.m_num) {
582   - for (unsigned i = 0; i < a.m_num; ++i) {
  616 + for (int i = 0; i < a.m_num; ++i) {
583 617 if (a.m_data[i] != b.m_data[i]) {
584 618 result = 0;
585 619 break;
... ... @@ -597,7 +631,7 @@ int operator!= (const GVector &amp;a, const GVector &amp;b)
597 631 {
598 632 int result = 0;
599 633 if (a.m_num == b.m_num) {
600   - for (unsigned i = 0; i < a.m_num; ++i) {
  634 + for (int i = 0; i < a.m_num; ++i) {
601 635 if (a.m_data[i] != b.m_data[i]) {
602 636 result = 1;
603 637 break;
... ...
src/Makefile.am
... ... @@ -3,7 +3,10 @@
3 3 files = GException.hpp GException.cpp \
4 4 GVector.hpp GVector.cpp \
5 5 GMatrix.hpp GMatrix.cpp \
6   - GSymMatrix.hpp GSymMatrix.cpp
  6 + GSymMatrix.hpp GSymMatrix.cpp \
  7 + GSparseMatrix.hpp GSparseMatrix.cpp \
  8 + GSparseSymbolic.hpp GSparseSymbolic.cpp \
  9 + GSparseNumeric.hpp GSparseNumeric.cpp
7 10  
8 11 lib_LTLIBRARIES = libgamma.la
9 12 libgamma_la_SOURCES = $(files)
... ...
src/Makefile.in
1   -# Makefile.in generated by automake 1.6.3 from Makefile.am.
  1 +# Makefile.in generated by automake 1.9.2 from Makefile.am.
2 2 # @configure_input@
3 3  
4   -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
5   -# Free Software Foundation, Inc.
  4 +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
  5 +# 2003, 2004 Free Software Foundation, Inc.
6 6 # This Makefile.in is free software; the Free Software Foundation
7 7 # gives unlimited permission to copy and/or distribute it,
8 8 # with or without modifications, as long as this notice is preserved.
... ... @@ -13,168 +13,234 @@
13 13 # PARTICULAR PURPOSE.
14 14  
15 15 @SET_MAKE@
16   -SHELL = @SHELL@
  16 +
  17 +SOURCES = $(libgamma_la_SOURCES)
17 18  
18 19 srcdir = @srcdir@
19 20 top_srcdir = @top_srcdir@
20 21 VPATH = @srcdir@
21   -prefix = @prefix@
22   -exec_prefix = @exec_prefix@
23   -
24   -bindir = @bindir@
25   -sbindir = @sbindir@
26   -libexecdir = @libexecdir@
27   -datadir = @datadir@
28   -sysconfdir = @sysconfdir@
29   -sharedstatedir = @sharedstatedir@
30   -localstatedir = @localstatedir@
31   -libdir = @libdir@
32   -infodir = @infodir@
33   -mandir = @mandir@
34   -includedir = @includedir@
35   -oldincludedir = /usr/include
36 22 pkgdatadir = $(datadir)/@PACKAGE@
37 23 pkglibdir = $(libdir)/@PACKAGE@
38 24 pkgincludedir = $(includedir)/@PACKAGE@
39 25 top_builddir = ..
40   -
41   -ACLOCAL = @ACLOCAL@
42   -AUTOCONF = @AUTOCONF@
43   -AUTOMAKE = @AUTOMAKE@
44   -AUTOHEADER = @AUTOHEADER@
45   -
46 26 am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
47 27 INSTALL = @INSTALL@
48   -INSTALL_PROGRAM = @INSTALL_PROGRAM@
49   -INSTALL_DATA = @INSTALL_DATA@
50 28 install_sh_DATA = $(install_sh) -c -m 644
51 29 install_sh_PROGRAM = $(install_sh) -c
52 30 install_sh_SCRIPT = $(install_sh) -c
53   -INSTALL_SCRIPT = @INSTALL_SCRIPT@
54 31 INSTALL_HEADER = $(INSTALL_DATA)
55   -transform = @program_transform_name@
  32 +transform = $(program_transform_name)
56 33 NORMAL_INSTALL = :
57 34 PRE_INSTALL = :
58 35 POST_INSTALL = :
59 36 NORMAL_UNINSTALL = :
60 37 PRE_UNINSTALL = :
61 38 POST_UNINSTALL = :
62   -host_alias = @host_alias@
  39 +build_triplet = @build@
63 40 host_triplet = @host@
64   -
65   -EXEEXT = @EXEEXT@
66   -OBJEXT = @OBJEXT@
67   -PATH_SEPARATOR = @PATH_SEPARATOR@
  41 +subdir = src
  42 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
  43 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
  44 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac
  45 +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
  46 + $(ACLOCAL_M4)
  47 +mkinstalldirs = $(install_sh) -d
  48 +CONFIG_HEADER = $(top_builddir)/config.h
  49 +CONFIG_CLEAN_FILES =
  50 +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
  51 +am__vpath_adj = case $$p in \
  52 + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
  53 + *) f=$$p;; \
  54 + esac;
  55 +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
  56 +am__installdirs = "$(DESTDIR)$(libdir)"
  57 +libLTLIBRARIES_INSTALL = $(INSTALL)
  58 +LTLIBRARIES = $(lib_LTLIBRARIES)
  59 +libgamma_la_LIBADD =
  60 +am__objects_1 = GException.lo GVector.lo GMatrix.lo GSymMatrix.lo \
  61 + GSparseMatrix.lo GSparseSymbolic.lo GSparseNumeric.lo
  62 +am_libgamma_la_OBJECTS = $(am__objects_1)
  63 +libgamma_la_OBJECTS = $(am_libgamma_la_OBJECTS)
  64 +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
  65 +depcomp =
  66 +am__depfiles_maybe =
  67 +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
  68 + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
  69 +LTCXXCOMPILE = $(LIBTOOL) --mode=compile --tag=CXX $(CXX) $(DEFS) \
  70 + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
  71 + $(AM_CXXFLAGS) $(CXXFLAGS)
  72 +CXXLD = $(CXX)
  73 +CXXLINK = $(LIBTOOL) --mode=link --tag=CXX $(CXXLD) $(AM_CXXFLAGS) \
  74 + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
  75 +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
  76 + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
  77 +LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) \
  78 + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
  79 + $(AM_CFLAGS) $(CFLAGS)
  80 +CCLD = $(CC)
  81 +LINK = $(LIBTOOL) --mode=link --tag=CC $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
  82 + $(AM_LDFLAGS) $(LDFLAGS) -o $@
  83 +SOURCES = $(libgamma_la_SOURCES)
  84 +DIST_SOURCES = $(libgamma_la_SOURCES)
  85 +ETAGS = etags
  86 +CTAGS = ctags
  87 +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
  88 +ACLOCAL = @ACLOCAL@
68 89 AMTAR = @AMTAR@
69 90 AR = @AR@
70   -AS = @AS@
  91 +AUTOCONF = @AUTOCONF@
  92 +AUTOHEADER = @AUTOHEADER@
  93 +AUTOMAKE = @AUTOMAKE@
71 94 AWK = @AWK@
72 95 CC = @CC@
  96 +CFLAGS = @CFLAGS@
  97 +CPP = @CPP@
  98 +CPPFLAGS = @CPPFLAGS@
73 99 CXX = @CXX@
74 100 CXXCPP = @CXXCPP@
75   -DEPDIR = @DEPDIR@
76   -DLLTOOL = @DLLTOOL@
  101 +CXXFLAGS = @CXXFLAGS@
  102 +CYGPATH_W = @CYGPATH_W@
  103 +DEFS = @DEFS@
77 104 ECHO = @ECHO@
  105 +ECHO_C = @ECHO_C@
  106 +ECHO_N = @ECHO_N@
  107 +ECHO_T = @ECHO_T@
78 108 EGREP = @EGREP@
  109 +EXEEXT = @EXEEXT@
79 110 F77 = @F77@
80   -GCJ = @GCJ@
81   -GCJFLAGS = @GCJFLAGS@
  111 +FFLAGS = @FFLAGS@
  112 +INSTALL_DATA = @INSTALL_DATA@
  113 +INSTALL_PROGRAM = @INSTALL_PROGRAM@
  114 +INSTALL_SCRIPT = @INSTALL_SCRIPT@
82 115 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
  116 +LDFLAGS = @LDFLAGS@
  117 +LIBOBJS = @LIBOBJS@
  118 +LIBS = @LIBS@
83 119 LIBTOOL = @LIBTOOL@
  120 +LIBTOOL_DEPS = @LIBTOOL_DEPS@
84 121 LN_S = @LN_S@
  122 +LTLIBOBJS = @LTLIBOBJS@
85 123 MAINT = @MAINT@
86   -OBJDUMP = @OBJDUMP@
  124 +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
  125 +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
  126 +MAKEINFO = @MAKEINFO@
  127 +OBJEXT = @OBJEXT@
87 128 PACKAGE = @PACKAGE@
  129 +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
  130 +PACKAGE_NAME = @PACKAGE_NAME@
  131 +PACKAGE_STRING = @PACKAGE_STRING@
  132 +PACKAGE_TARNAME = @PACKAGE_TARNAME@
  133 +PACKAGE_VERSION = @PACKAGE_VERSION@
  134 +PATH_SEPARATOR = @PATH_SEPARATOR@
88 135 RANLIB = @RANLIB@
89   -RC = @RC@
  136 +SET_MAKE = @SET_MAKE@
  137 +SHELL = @SHELL@
90 138 STRIP = @STRIP@
91 139 VERSION = @VERSION@
92   -am__include = @am__include@
93   -am__quote = @am__quote@
  140 +ac_ct_AR = @ac_ct_AR@
  141 +ac_ct_CC = @ac_ct_CC@
  142 +ac_ct_CXX = @ac_ct_CXX@
  143 +ac_ct_F77 = @ac_ct_F77@
  144 +ac_ct_RANLIB = @ac_ct_RANLIB@
  145 +ac_ct_STRIP = @ac_ct_STRIP@
  146 +am__leading_dot = @am__leading_dot@
  147 +am__tar = @am__tar@
  148 +am__untar = @am__untar@
  149 +bindir = @bindir@
  150 +build = @build@
  151 +build_alias = @build_alias@
  152 +build_cpu = @build_cpu@
  153 +build_os = @build_os@
  154 +build_vendor = @build_vendor@
  155 +datadir = @datadir@
  156 +exec_prefix = @exec_prefix@
  157 +host = @host@
  158 +host_alias = @host_alias@
  159 +host_cpu = @host_cpu@
  160 +host_os = @host_os@
  161 +host_vendor = @host_vendor@
  162 +includedir = @includedir@
  163 +infodir = @infodir@
94 164 install_sh = @install_sh@
95   -
  165 +libdir = @libdir@
  166 +libexecdir = @libexecdir@
  167 +localstatedir = @localstatedir@
  168 +mandir = @mandir@
  169 +mkdir_p = @mkdir_p@
  170 +oldincludedir = @oldincludedir@
  171 +prefix = @prefix@
  172 +program_transform_name = @program_transform_name@
  173 +sbindir = @sbindir@
  174 +sharedstatedir = @sharedstatedir@
  175 +sysconfdir = @sysconfdir@
  176 +target_alias = @target_alias@
96 177 files = GException.hpp GException.cpp \
97 178 GVector.hpp GVector.cpp \
98 179 GMatrix.hpp GMatrix.cpp \
99   - GSymMatrix.hpp GSymMatrix.cpp
100   -
  180 + GSymMatrix.hpp GSymMatrix.cpp \
  181 + GSparseMatrix.hpp GSparseMatrix.cpp \
  182 + GSparseSymbolic.hpp GSparseSymbolic.cpp \
  183 + GSparseNumeric.hpp GSparseNumeric.cpp
101 184  
102 185 lib_LTLIBRARIES = libgamma.la
103 186 libgamma_la_SOURCES = $(files)
104   -subdir = src
105   -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
106   -CONFIG_HEADER = $(top_builddir)/config.h
107   -CONFIG_CLEAN_FILES =
108   -LTLIBRARIES = $(lib_LTLIBRARIES)
109   -
110   -libgamma_la_LDFLAGS =
111   -libgamma_la_LIBADD =
112   -am__objects_1 = GException.lo GVector.lo GMatrix.lo GSymMatrix.lo
113   -am_libgamma_la_OBJECTS = $(am__objects_1)
114   -libgamma_la_OBJECTS = $(am_libgamma_la_OBJECTS)
115   -
116   -DEFS = @DEFS@
117   -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
118   -CPPFLAGS = @CPPFLAGS@
119   -LDFLAGS = @LDFLAGS@
120   -LIBS = @LIBS@
121   -depcomp =
122   -am__depfiles_maybe =
123   -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
124   - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
125   -LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
126   - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
127   - $(AM_CXXFLAGS) $(CXXFLAGS)
128   -CXXLD = $(CXX)
129   -CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
130   - $(AM_LDFLAGS) $(LDFLAGS) -o $@
131   -CXXFLAGS = @CXXFLAGS@
132   -CFLAGS = @CFLAGS@
133   -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
134   - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
135   -LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
136   - $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
137   -CCLD = $(CC)
138   -LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
139   - $(AM_LDFLAGS) $(LDFLAGS) -o $@
140   -DIST_SOURCES = $(libgamma_la_SOURCES)
141   -DIST_COMMON = Makefile.am Makefile.in
142   -SOURCES = $(libgamma_la_SOURCES)
143   -
144 187 all: all-am
145 188  
146 189 .SUFFIXES:
147 190 .SUFFIXES: .cpp .lo .o .obj
148   -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
  191 +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
  192 + @for dep in $?; do \
  193 + case '$(am__configure_deps)' in \
  194 + *$$dep*) \
  195 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
  196 + && exit 0; \
  197 + exit 1;; \
  198 + esac; \
  199 + done; \
  200 + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps src/Makefile'; \
149 201 cd $(top_srcdir) && \
150   - $(AUTOMAKE) --gnu src/Makefile
151   -Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
152   - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
153   -libLTLIBRARIES_INSTALL = $(INSTALL)
  202 + $(AUTOMAKE) --gnu --ignore-deps src/Makefile
  203 +.PRECIOUS: Makefile
  204 +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
  205 + @case '$?' in \
  206 + *config.status*) \
  207 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
  208 + *) \
  209 + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
  210 + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
  211 + esac;
  212 +
  213 +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
  214 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
  215 +
  216 +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
  217 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
  218 +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
  219 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
154 220 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
155 221 @$(NORMAL_INSTALL)
156   - $(mkinstalldirs) $(DESTDIR)$(libdir)
  222 + test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
157 223 @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
158 224 if test -f $$p; then \
159   - f="`echo $$p | sed -e 's|^.*/||'`"; \
160   - echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f"; \
161   - $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f; \
  225 + f=$(am__strip_dir) \
  226 + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
  227 + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
162 228 else :; fi; \
163 229 done
164 230  
165 231 uninstall-libLTLIBRARIES:
166 232 @$(NORMAL_UNINSTALL)
167   - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
168   - p="`echo $$p | sed -e 's|^.*/||'`"; \
169   - echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \
170   - $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
  233 + @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
  234 + p=$(am__strip_dir) \
  235 + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
  236 + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
171 237 done
172 238  
173 239 clean-libLTLIBRARIES:
174 240 -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
175 241 @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
176 242 dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
177   - test -z "$dir" && dir=.; \
  243 + test "$$dir" != "$$p" || dir=.; \
178 244 echo "rm -f \"$${dir}/so_locations\""; \
179 245 rm -f "$${dir}/so_locations"; \
180 246 done
... ... @@ -182,19 +248,19 @@ libgamma.la: $(libgamma_la_OBJECTS) $(libgamma_la_DEPENDENCIES)
182 248 $(CXXLINK) -rpath $(libdir) $(libgamma_la_LDFLAGS) $(libgamma_la_OBJECTS) $(libgamma_la_LIBADD) $(LIBS)
183 249  
184 250 mostlyclean-compile:
185   - -rm -f *.$(OBJEXT) core *.core
  251 + -rm -f *.$(OBJEXT)
186 252  
187 253 distclean-compile:
188 254 -rm -f *.tab.c
189 255  
190 256 .cpp.o:
191   - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
  257 + $(CXXCOMPILE) -c -o $@ $<
192 258  
193 259 .cpp.obj:
194   - $(CXXCOMPILE) -c -o $@ `cygpath -w $<`
  260 + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
195 261  
196 262 .cpp.lo:
197   - $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
  263 + $(LTCXXCOMPILE) -c -o $@ $<
198 264  
199 265 mostlyclean-libtool:
200 266 -rm -f *.lo
... ... @@ -206,11 +272,6 @@ distclean-libtool:
206 272 -rm -f libtool
207 273 uninstall-info-am:
208 274  
209   -ETAGS = etags
210   -ETAGSFLAGS =
211   -
212   -tags: TAGS
213   -
214 275 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
215 276 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
216 277 unique=`for i in $$list; do \
... ... @@ -219,6 +280,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
219 280 $(AWK) ' { files[$$0] = 1; } \
220 281 END { for (i in files) print i; }'`; \
221 282 mkid -fID $$unique
  283 +tags: TAGS
222 284  
223 285 TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
224 286 $(TAGS_FILES) $(LISP)
... ... @@ -230,8 +292,24 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
230 292 done | \
231 293 $(AWK) ' { files[$$0] = 1; } \
232 294 END { for (i in files) print i; }'`; \
233   - test -z "$(ETAGS_ARGS)$$tags$$unique" \
234   - || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
  295 + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
  296 + test -n "$$unique" || unique=$$empty_fix; \
  297 + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
  298 + $$tags $$unique; \
  299 + fi
  300 +ctags: CTAGS
  301 +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
  302 + $(TAGS_FILES) $(LISP)
  303 + tags=; \
  304 + here=`pwd`; \
  305 + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
  306 + unique=`for i in $$list; do \
  307 + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  308 + done | \
  309 + $(AWK) ' { files[$$0] = 1; } \
  310 + END { for (i in files) print i; }'`; \
  311 + test -z "$(CTAGS_ARGS)$$tags$$unique" \
  312 + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
235 313 $$tags $$unique
236 314  
237 315 GTAGS:
... ... @@ -240,19 +318,21 @@ GTAGS:
240 318 && gtags -i $(GTAGS_ARGS) $$here
241 319  
242 320 distclean-tags:
243   - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
244   -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
245   -
246   -top_distdir = ..
247   -distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
  321 + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
248 322  
249 323 distdir: $(DISTFILES)
250   - @list='$(DISTFILES)'; for file in $$list; do \
  324 + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
  325 + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
  326 + list='$(DISTFILES)'; for file in $$list; do \
  327 + case $$file in \
  328 + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
  329 + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
  330 + esac; \
251 331 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
252 332 dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
253 333 if test "$$dir" != "$$file" && test "$$dir" != "."; then \
254 334 dir="/$$dir"; \
255   - $(mkinstalldirs) "$(distdir)$$dir"; \
  335 + $(mkdir_p) "$(distdir)$$dir"; \
256 336 else \
257 337 dir=''; \
258 338 fi; \
... ... @@ -270,10 +350,10 @@ distdir: $(DISTFILES)
270 350 check-am: all-am
271 351 check: check-am
272 352 all-am: Makefile $(LTLIBRARIES)
273   -
274 353 installdirs:
275   - $(mkinstalldirs) $(DESTDIR)$(libdir)
276   -
  354 + for dir in "$(DESTDIR)$(libdir)"; do \
  355 + test -z "$$dir" || $(mkdir_p) "$$dir"; \
  356 + done
277 357 install: install-am
278 358 install-exec: install-exec-am
279 359 install-data: install-data-am
... ... @@ -285,7 +365,7 @@ install-am: all-am
285 365 installcheck: installcheck-am
286 366 install-strip:
287 367 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
288   - INSTALL_STRIP_FLAG=-s \
  368 + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
289 369 `test -z '$(STRIP)' || \
290 370 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
291 371 mostlyclean-generic:
... ... @@ -293,7 +373,7 @@ mostlyclean-generic:
293 373 clean-generic:
294 374  
295 375 distclean-generic:
296   - -rm -f Makefile $(CONFIG_CLEAN_FILES)
  376 + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
297 377  
298 378 maintainer-clean-generic:
299 379 @echo "This command is intended for maintainers to use"
... ... @@ -304,7 +384,7 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
304 384 mostlyclean-am
305 385  
306 386 distclean: distclean-am
307   -
  387 + -rm -f Makefile
308 388 distclean-am: clean-am distclean-compile distclean-generic \
309 389 distclean-libtool distclean-tags
310 390  
... ... @@ -312,6 +392,8 @@ dvi: dvi-am
312 392  
313 393 dvi-am:
314 394  
  395 +html: html-am
  396 +
315 397 info: info-am
316 398  
317 399 info-am:
... ... @@ -327,7 +409,7 @@ install-man:
327 409 installcheck-am:
328 410  
329 411 maintainer-clean: maintainer-clean-am
330   -
  412 + -rm -f Makefile
331 413 maintainer-clean-am: distclean-am maintainer-clean-generic
332 414  
333 415 mostlyclean: mostlyclean-am
... ... @@ -335,17 +417,26 @@ mostlyclean: mostlyclean-am
335 417 mostlyclean-am: mostlyclean-compile mostlyclean-generic \
336 418 mostlyclean-libtool
337 419  
  420 +pdf: pdf-am
  421 +
  422 +pdf-am:
  423 +
  424 +ps: ps-am
  425 +
  426 +ps-am:
  427 +
338 428 uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES
339 429  
340   -.PHONY: GTAGS all all-am check check-am clean clean-generic \
341   - clean-libLTLIBRARIES clean-libtool distclean distclean-compile \
342   - distclean-generic distclean-libtool distclean-tags distdir dvi \
343   - dvi-am info info-am install install-am install-data \
344   - install-data-am install-exec install-exec-am install-info \
345   - install-info-am install-libLTLIBRARIES install-man \
346   - install-strip installcheck installcheck-am installdirs \
347   - maintainer-clean maintainer-clean-generic mostlyclean \
348   - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
  430 +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
  431 + clean-libLTLIBRARIES clean-libtool ctags distclean \
  432 + distclean-compile distclean-generic distclean-libtool \
  433 + distclean-tags distdir dvi dvi-am html html-am info info-am \
  434 + install install-am install-data install-data-am install-exec \
  435 + install-exec-am install-info install-info-am \
  436 + install-libLTLIBRARIES install-man install-strip installcheck \
  437 + installcheck-am installdirs maintainer-clean \
  438 + maintainer-clean-generic mostlyclean mostlyclean-compile \
  439 + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
349 440 tags uninstall uninstall-am uninstall-info-am \
350 441 uninstall-libLTLIBRARIES
351 442  
... ...
test/Makefile.am
1 1 ## Process this file with automake to produce Makefile.in
2 2  
3   -check_PROGRAMS = test_GVector test_GMatrix test_GSymMatrix
4   -TESTS = test_GVector test_GMatrix test_GSymMatrix
  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
5 11 test_GVector_SOURCES = test_GVector.cpp
6 12 test_GVector_LDADD = ../src/libgamma.la
7 13 test_GMatrix_SOURCES = test_GMatrix.cpp
8 14 test_GMatrix_LDADD = ../src/libgamma.la
9 15 test_GSymMatrix_SOURCES = test_GSymMatrix.cpp
10 16 test_GSymMatrix_LDADD = ../src/libgamma.la
  17 +test_GSparseMatrix_SOURCES = test_GSparseMatrix.cpp
  18 +test_GSparseMatrix_LDADD = ../src/libgamma.la
... ...
test/Makefile.in
1   -# Makefile.in generated by automake 1.6.3 from Makefile.am.
  1 +# Makefile.in generated by automake 1.9.2 from Makefile.am.
2 2 # @configure_input@
3 3  
4   -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
5   -# Free Software Foundation, Inc.
  4 +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
  5 +# 2003, 2004 Free Software Foundation, Inc.
6 6 # This Makefile.in is free software; the Free Software Foundation
7 7 # gives unlimited permission to copy and/or distribute it,
8 8 # with or without modifications, as long as this notice is preserved.
... ... @@ -13,143 +13,206 @@
13 13 # PARTICULAR PURPOSE.
14 14  
15 15 @SET_MAKE@
16   -SHELL = @SHELL@
  16 +SOURCES = $(test_GMatrix_SOURCES) $(test_GSparseMatrix_SOURCES) $(test_GSymMatrix_SOURCES) $(test_GVector_SOURCES)
17 17  
18 18 srcdir = @srcdir@
19 19 top_srcdir = @top_srcdir@
20 20 VPATH = @srcdir@
21   -prefix = @prefix@
22   -exec_prefix = @exec_prefix@
23   -
24   -bindir = @bindir@
25   -sbindir = @sbindir@
26   -libexecdir = @libexecdir@
27   -datadir = @datadir@
28   -sysconfdir = @sysconfdir@
29   -sharedstatedir = @sharedstatedir@
30   -localstatedir = @localstatedir@
31   -libdir = @libdir@
32   -infodir = @infodir@
33   -mandir = @mandir@
34   -includedir = @includedir@
35   -oldincludedir = /usr/include
36 21 pkgdatadir = $(datadir)/@PACKAGE@
37 22 pkglibdir = $(libdir)/@PACKAGE@
38 23 pkgincludedir = $(includedir)/@PACKAGE@
39 24 top_builddir = ..
40   -
41   -ACLOCAL = @ACLOCAL@
42   -AUTOCONF = @AUTOCONF@
43   -AUTOMAKE = @AUTOMAKE@
44   -AUTOHEADER = @AUTOHEADER@
45   -
46 25 am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
47 26 INSTALL = @INSTALL@
48   -INSTALL_PROGRAM = @INSTALL_PROGRAM@
49   -INSTALL_DATA = @INSTALL_DATA@
50 27 install_sh_DATA = $(install_sh) -c -m 644
51 28 install_sh_PROGRAM = $(install_sh) -c
52 29 install_sh_SCRIPT = $(install_sh) -c
53   -INSTALL_SCRIPT = @INSTALL_SCRIPT@
54 30 INSTALL_HEADER = $(INSTALL_DATA)
55   -transform = @program_transform_name@
  31 +transform = $(program_transform_name)
56 32 NORMAL_INSTALL = :
57 33 PRE_INSTALL = :
58 34 POST_INSTALL = :
59 35 NORMAL_UNINSTALL = :
60 36 PRE_UNINSTALL = :
61 37 POST_UNINSTALL = :
62   -host_alias = @host_alias@
  38 +build_triplet = @build@
63 39 host_triplet = @host@
64   -
65   -EXEEXT = @EXEEXT@
66   -OBJEXT = @OBJEXT@
67   -PATH_SEPARATOR = @PATH_SEPARATOR@
  40 +check_PROGRAMS = test_GVector$(EXEEXT) test_GMatrix$(EXEEXT) \
  41 + test_GSymMatrix$(EXEEXT) test_GSparseMatrix$(EXEEXT)
  42 +subdir = test
  43 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
  44 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
  45 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac
  46 +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
  47 + $(ACLOCAL_M4)
  48 +mkinstalldirs = $(install_sh) -d
  49 +CONFIG_HEADER = $(top_builddir)/config.h
  50 +CONFIG_CLEAN_FILES =
  51 +am_test_GMatrix_OBJECTS = test_GMatrix.$(OBJEXT)
  52 +test_GMatrix_OBJECTS = $(am_test_GMatrix_OBJECTS)
  53 +test_GMatrix_DEPENDENCIES = ../src/libgamma.la
  54 +am_test_GSparseMatrix_OBJECTS = test_GSparseMatrix.$(OBJEXT)
  55 +test_GSparseMatrix_OBJECTS = $(am_test_GSparseMatrix_OBJECTS)
  56 +test_GSparseMatrix_DEPENDENCIES = ../src/libgamma.la
  57 +am_test_GSymMatrix_OBJECTS = test_GSymMatrix.$(OBJEXT)
  58 +test_GSymMatrix_OBJECTS = $(am_test_GSymMatrix_OBJECTS)
  59 +test_GSymMatrix_DEPENDENCIES = ../src/libgamma.la
  60 +am_test_GVector_OBJECTS = test_GVector.$(OBJEXT)
  61 +test_GVector_OBJECTS = $(am_test_GVector_OBJECTS)
  62 +test_GVector_DEPENDENCIES = ../src/libgamma.la
  63 +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
  64 +depcomp =
  65 +am__depfiles_maybe =
  66 +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
  67 + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
  68 +LTCXXCOMPILE = $(LIBTOOL) --mode=compile --tag=CXX $(CXX) $(DEFS) \
  69 + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
  70 + $(AM_CXXFLAGS) $(CXXFLAGS)
  71 +CXXLD = $(CXX)
  72 +CXXLINK = $(LIBTOOL) --mode=link --tag=CXX $(CXXLD) $(AM_CXXFLAGS) \
  73 + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
  74 +SOURCES = $(test_GMatrix_SOURCES) $(test_GSparseMatrix_SOURCES) \
  75 + $(test_GSymMatrix_SOURCES) $(test_GVector_SOURCES)
  76 +DIST_SOURCES = $(test_GMatrix_SOURCES) $(test_GSparseMatrix_SOURCES) \
  77 + $(test_GSymMatrix_SOURCES) $(test_GVector_SOURCES)
  78 +ETAGS = etags
  79 +CTAGS = ctags
  80 +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
  81 +ACLOCAL = @ACLOCAL@
68 82 AMTAR = @AMTAR@
69 83 AR = @AR@
70   -AS = @AS@
  84 +AUTOCONF = @AUTOCONF@
  85 +AUTOHEADER = @AUTOHEADER@
  86 +AUTOMAKE = @AUTOMAKE@
71 87 AWK = @AWK@
72 88 CC = @CC@
  89 +CFLAGS = @CFLAGS@
  90 +CPP = @CPP@
  91 +CPPFLAGS = @CPPFLAGS@
73 92 CXX = @CXX@
74 93 CXXCPP = @CXXCPP@
75   -DEPDIR = @DEPDIR@
76   -DLLTOOL = @DLLTOOL@
  94 +CXXFLAGS = @CXXFLAGS@
  95 +CYGPATH_W = @CYGPATH_W@
  96 +DEFS = @DEFS@
77 97 ECHO = @ECHO@
  98 +ECHO_C = @ECHO_C@
  99 +ECHO_N = @ECHO_N@
  100 +ECHO_T = @ECHO_T@
78 101 EGREP = @EGREP@
  102 +EXEEXT = @EXEEXT@
79 103 F77 = @F77@
80   -GCJ = @GCJ@
81   -GCJFLAGS = @GCJFLAGS@
  104 +FFLAGS = @FFLAGS@
  105 +INSTALL_DATA = @INSTALL_DATA@
  106 +INSTALL_PROGRAM = @INSTALL_PROGRAM@
  107 +INSTALL_SCRIPT = @INSTALL_SCRIPT@
82 108 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
  109 +LDFLAGS = @LDFLAGS@
  110 +LIBOBJS = @LIBOBJS@
  111 +LIBS = @LIBS@
83 112 LIBTOOL = @LIBTOOL@
  113 +LIBTOOL_DEPS = @LIBTOOL_DEPS@
84 114 LN_S = @LN_S@
  115 +LTLIBOBJS = @LTLIBOBJS@
85 116 MAINT = @MAINT@
86   -OBJDUMP = @OBJDUMP@
  117 +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
  118 +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
  119 +MAKEINFO = @MAKEINFO@
  120 +OBJEXT = @OBJEXT@
87 121 PACKAGE = @PACKAGE@
  122 +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
  123 +PACKAGE_NAME = @PACKAGE_NAME@
  124 +PACKAGE_STRING = @PACKAGE_STRING@
  125 +PACKAGE_TARNAME = @PACKAGE_TARNAME@
  126 +PACKAGE_VERSION = @PACKAGE_VERSION@
  127 +PATH_SEPARATOR = @PATH_SEPARATOR@
88 128 RANLIB = @RANLIB@
89   -RC = @RC@
  129 +SET_MAKE = @SET_MAKE@
  130 +SHELL = @SHELL@
90 131 STRIP = @STRIP@
91 132 VERSION = @VERSION@
92   -am__include = @am__include@
93   -am__quote = @am__quote@
  133 +ac_ct_AR = @ac_ct_AR@
  134 +ac_ct_CC = @ac_ct_CC@
  135 +ac_ct_CXX = @ac_ct_CXX@
  136 +ac_ct_F77 = @ac_ct_F77@
  137 +ac_ct_RANLIB = @ac_ct_RANLIB@
  138 +ac_ct_STRIP = @ac_ct_STRIP@
  139 +am__leading_dot = @am__leading_dot@
  140 +am__tar = @am__tar@
  141 +am__untar = @am__untar@
  142 +bindir = @bindir@
  143 +build = @build@
  144 +build_alias = @build_alias@
  145 +build_cpu = @build_cpu@
  146 +build_os = @build_os@
  147 +build_vendor = @build_vendor@
  148 +datadir = @datadir@
  149 +exec_prefix = @exec_prefix@
  150 +host = @host@
  151 +host_alias = @host_alias@
  152 +host_cpu = @host_cpu@
  153 +host_os = @host_os@
  154 +host_vendor = @host_vendor@
  155 +includedir = @includedir@
  156 +infodir = @infodir@
94 157 install_sh = @install_sh@
  158 +libdir = @libdir@
  159 +libexecdir = @libexecdir@
  160 +localstatedir = @localstatedir@
  161 +mandir = @mandir@
  162 +mkdir_p = @mkdir_p@
  163 +oldincludedir = @oldincludedir@
  164 +prefix = @prefix@
  165 +program_transform_name = @program_transform_name@
  166 +sbindir = @sbindir@
  167 +sharedstatedir = @sharedstatedir@
  168 +sysconfdir = @sysconfdir@
  169 +target_alias = @target_alias@
  170 +TESTS = test_GVector \
  171 + test_GMatrix \
  172 + test_GSymMatrix \
  173 + test_GSparseMatrix
95 174  
96   -check_PROGRAMS = test_GVector test_GMatrix test_GSymMatrix
97   -TESTS = test_GVector test_GMatrix test_GSymMatrix
98 175 test_GVector_SOURCES = test_GVector.cpp
99 176 test_GVector_LDADD = ../src/libgamma.la
100 177 test_GMatrix_SOURCES = test_GMatrix.cpp
101 178 test_GMatrix_LDADD = ../src/libgamma.la
102 179 test_GSymMatrix_SOURCES = test_GSymMatrix.cpp
103 180 test_GSymMatrix_LDADD = ../src/libgamma.la
104   -subdir = test
105   -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
106   -CONFIG_HEADER = $(top_builddir)/config.h
107   -CONFIG_CLEAN_FILES =
108   -check_PROGRAMS = test_GVector$(EXEEXT) test_GMatrix$(EXEEXT) \
109   - test_GSymMatrix$(EXEEXT)
110   -am_test_GMatrix_OBJECTS = test_GMatrix.$(OBJEXT)
111   -test_GMatrix_OBJECTS = $(am_test_GMatrix_OBJECTS)
112   -test_GMatrix_DEPENDENCIES = ../src/libgamma.la
113   -test_GMatrix_LDFLAGS =
114   -am_test_GSymMatrix_OBJECTS = test_GSymMatrix.$(OBJEXT)
115   -test_GSymMatrix_OBJECTS = $(am_test_GSymMatrix_OBJECTS)
116   -test_GSymMatrix_DEPENDENCIES = ../src/libgamma.la
117   -test_GSymMatrix_LDFLAGS =
118   -am_test_GVector_OBJECTS = test_GVector.$(OBJEXT)
119   -test_GVector_OBJECTS = $(am_test_GVector_OBJECTS)
120   -test_GVector_DEPENDENCIES = ../src/libgamma.la
121   -test_GVector_LDFLAGS =
122   -
123   -DEFS = @DEFS@
124   -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
125   -CPPFLAGS = @CPPFLAGS@
126   -LDFLAGS = @LDFLAGS@
127   -LIBS = @LIBS@
128   -depcomp =
129   -am__depfiles_maybe =
130   -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
131   - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
132   -LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
133   - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
134   - $(AM_CXXFLAGS) $(CXXFLAGS)
135   -CXXLD = $(CXX)
136   -CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
137   - $(AM_LDFLAGS) $(LDFLAGS) -o $@
138   -CXXFLAGS = @CXXFLAGS@
139   -DIST_SOURCES = $(test_GMatrix_SOURCES) $(test_GSymMatrix_SOURCES) \
140   - $(test_GVector_SOURCES)
141   -DIST_COMMON = Makefile.am Makefile.in
142   -SOURCES = $(test_GMatrix_SOURCES) $(test_GSymMatrix_SOURCES) $(test_GVector_SOURCES)
143   -
  181 +test_GSparseMatrix_SOURCES = test_GSparseMatrix.cpp
  182 +test_GSparseMatrix_LDADD = ../src/libgamma.la
144 183 all: all-am
145 184  
146 185 .SUFFIXES:
147 186 .SUFFIXES: .cpp .lo .o .obj
148   -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
  187 +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
  188 + @for dep in $?; do \
  189 + case '$(am__configure_deps)' in \
  190 + *$$dep*) \
  191 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
  192 + && exit 0; \
  193 + exit 1;; \
  194 + esac; \
  195 + done; \
  196 + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps test/Makefile'; \
149 197 cd $(top_srcdir) && \
150   - $(AUTOMAKE) --gnu test/Makefile
151   -Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
152   - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
  198 + $(AUTOMAKE) --gnu --ignore-deps test/Makefile
  199 +.PRECIOUS: Makefile
  200 +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
  201 + @case '$?' in \
  202 + *config.status*) \
  203 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
  204 + *) \
  205 + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
  206 + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
  207 + esac;
  208 +
  209 +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
  210 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
  211 +
  212 +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
  213 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
  214 +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
  215 + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
153 216  
154 217 clean-checkPROGRAMS:
155 218 @list='$(check_PROGRAMS)'; for p in $$list; do \
... ... @@ -160,6 +223,9 @@ clean-checkPROGRAMS:
160 223 test_GMatrix$(EXEEXT): $(test_GMatrix_OBJECTS) $(test_GMatrix_DEPENDENCIES)
161 224 @rm -f test_GMatrix$(EXEEXT)
162 225 $(CXXLINK) $(test_GMatrix_LDFLAGS) $(test_GMatrix_OBJECTS) $(test_GMatrix_LDADD) $(LIBS)
  226 +test_GSparseMatrix$(EXEEXT): $(test_GSparseMatrix_OBJECTS) $(test_GSparseMatrix_DEPENDENCIES)
  227 + @rm -f test_GSparseMatrix$(EXEEXT)
  228 + $(CXXLINK) $(test_GSparseMatrix_LDFLAGS) $(test_GSparseMatrix_OBJECTS) $(test_GSparseMatrix_LDADD) $(LIBS)
163 229 test_GSymMatrix$(EXEEXT): $(test_GSymMatrix_OBJECTS) $(test_GSymMatrix_DEPENDENCIES)
164 230 @rm -f test_GSymMatrix$(EXEEXT)
165 231 $(CXXLINK) $(test_GSymMatrix_LDFLAGS) $(test_GSymMatrix_OBJECTS) $(test_GSymMatrix_LDADD) $(LIBS)
... ... @@ -168,19 +234,19 @@ test_GVector$(EXEEXT): $(test_GVector_OBJECTS) $(test_GVector_DEPENDENCIES)
168 234 $(CXXLINK) $(test_GVector_LDFLAGS) $(test_GVector_OBJECTS) $(test_GVector_LDADD) $(LIBS)
169 235  
170 236 mostlyclean-compile:
171   - -rm -f *.$(OBJEXT) core *.core
  237 + -rm -f *.$(OBJEXT)
172 238  
173 239 distclean-compile:
174 240 -rm -f *.tab.c
175 241  
176 242 .cpp.o:
177   - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
  243 + $(CXXCOMPILE) -c -o $@ $<
178 244  
179 245 .cpp.obj:
180   - $(CXXCOMPILE) -c -o $@ `cygpath -w $<`
  246 + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
181 247  
182 248 .cpp.lo:
183   - $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
  249 + $(LTCXXCOMPILE) -c -o $@ $<
184 250  
185 251 mostlyclean-libtool:
186 252 -rm -f *.lo
... ... @@ -192,11 +258,6 @@ distclean-libtool:
192 258 -rm -f libtool
193 259 uninstall-info-am:
194 260  
195   -ETAGS = etags
196   -ETAGSFLAGS =
197   -
198   -tags: TAGS
199   -
200 261 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
201 262 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
202 263 unique=`for i in $$list; do \
... ... @@ -205,6 +266,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
205 266 $(AWK) ' { files[$$0] = 1; } \
206 267 END { for (i in files) print i; }'`; \
207 268 mkid -fID $$unique
  269 +tags: TAGS
208 270  
209 271 TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
210 272 $(TAGS_FILES) $(LISP)
... ... @@ -216,8 +278,24 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
216 278 done | \
217 279 $(AWK) ' { files[$$0] = 1; } \
218 280 END { for (i in files) print i; }'`; \
219   - test -z "$(ETAGS_ARGS)$$tags$$unique" \
220   - || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
  281 + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
  282 + test -n "$$unique" || unique=$$empty_fix; \
  283 + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
  284 + $$tags $$unique; \
  285 + fi
  286 +ctags: CTAGS
  287 +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
  288 + $(TAGS_FILES) $(LISP)
  289 + tags=; \
  290 + here=`pwd`; \
  291 + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
  292 + unique=`for i in $$list; do \
  293 + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  294 + done | \
  295 + $(AWK) ' { files[$$0] = 1; } \
  296 + END { for (i in files) print i; }'`; \
  297 + test -z "$(CTAGS_ARGS)$$tags$$unique" \
  298 + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
221 299 $$tags $$unique
222 300  
223 301 GTAGS:
... ... @@ -226,10 +304,10 @@ GTAGS:
226 304 && gtags -i $(GTAGS_ARGS) $$here
227 305  
228 306 distclean-tags:
229   - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
  307 + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
230 308  
231 309 check-TESTS: $(TESTS)
232   - @failed=0; all=0; xfail=0; xpass=0; \
  310 + @failed=0; all=0; xfail=0; xpass=0; skip=0; \
233 311 srcdir=$(srcdir); export srcdir; \
234 312 list='$(TESTS)'; \
235 313 if test -n "$$list"; then \
... ... @@ -241,26 +319,29 @@ check-TESTS: $(TESTS)
241 319 all=`expr $$all + 1`; \
242 320 case " $(XFAIL_TESTS) " in \
243 321 *" $$tst "*) \
244   - xpass=`expr $$xpass + 1`; \
245   - failed=`expr $$failed + 1`; \
246   - echo "XPASS: $$tst"; \
  322 + xpass=`expr $$xpass + 1`; \
  323 + failed=`expr $$failed + 1`; \
  324 + echo "XPASS: $$tst"; \
247 325 ;; \
248 326 *) \
249   - echo "PASS: $$tst"; \
  327 + echo "PASS: $$tst"; \
250 328 ;; \
251 329 esac; \
252 330 elif test $$? -ne 77; then \
253 331 all=`expr $$all + 1`; \
254 332 case " $(XFAIL_TESTS) " in \
255 333 *" $$tst "*) \
256   - xfail=`expr $$xfail + 1`; \
257   - echo "XFAIL: $$tst"; \
  334 + xfail=`expr $$xfail + 1`; \
  335 + echo "XFAIL: $$tst"; \
258 336 ;; \
259 337 *) \
260   - failed=`expr $$failed + 1`; \
261   - echo "FAIL: $$tst"; \
  338 + failed=`expr $$failed + 1`; \
  339 + echo "FAIL: $$tst"; \
262 340 ;; \
263 341 esac; \
  342 + else \
  343 + skip=`expr $$skip + 1`; \
  344 + echo "SKIP: $$tst"; \
264 345 fi; \
265 346 done; \
266 347 if test "$$failed" -eq 0; then \
... ... @@ -276,24 +357,41 @@ check-TESTS: $(TESTS)
276 357 banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
277 358 fi; \
278 359 fi; \
279   - dashes=`echo "$$banner" | sed s/./=/g`; \
  360 + dashes="$$banner"; \
  361 + skipped=""; \
  362 + if test "$$skip" -ne 0; then \
  363 + skipped="($$skip tests were not run)"; \
  364 + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
  365 + dashes="$$skipped"; \
  366 + fi; \
  367 + report=""; \
  368 + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
  369 + report="Please report to $(PACKAGE_BUGREPORT)"; \
  370 + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
  371 + dashes="$$report"; \
  372 + fi; \
  373 + dashes=`echo "$$dashes" | sed s/./=/g`; \
280 374 echo "$$dashes"; \
281 375 echo "$$banner"; \
  376 + test -z "$$skipped" || echo "$$skipped"; \
  377 + test -z "$$report" || echo "$$report"; \
282 378 echo "$$dashes"; \
283 379 test "$$failed" -eq 0; \
284 380 else :; fi
285   -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
286   -
287   -top_distdir = ..
288   -distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
289 381  
290 382 distdir: $(DISTFILES)
291   - @list='$(DISTFILES)'; for file in $$list; do \
  383 + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
  384 + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
  385 + list='$(DISTFILES)'; for file in $$list; do \
  386 + case $$file in \
  387 + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
  388 + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
  389 + esac; \
292 390 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
293 391 dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
294 392 if test "$$dir" != "$$file" && test "$$dir" != "."; then \
295 393 dir="/$$dir"; \
296   - $(mkinstalldirs) "$(distdir)$$dir"; \
  394 + $(mkdir_p) "$(distdir)$$dir"; \
297 395 else \
298 396 dir=''; \
299 397 fi; \
... ... @@ -313,9 +411,7 @@ check-am: all-am
313 411 $(MAKE) $(AM_MAKEFLAGS) check-TESTS
314 412 check: check-am
315 413 all-am: Makefile
316   -
317 414 installdirs:
318   -
319 415 install: install-am
320 416 install-exec: install-exec-am
321 417 install-data: install-data-am
... ... @@ -327,7 +423,7 @@ install-am: all-am
327 423 installcheck: installcheck-am
328 424 install-strip:
329 425 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
330   - INSTALL_STRIP_FLAG=-s \
  426 + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
331 427 `test -z '$(STRIP)' || \
332 428 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
333 429 mostlyclean-generic:
... ... @@ -335,17 +431,18 @@ mostlyclean-generic:
335 431 clean-generic:
336 432  
337 433 distclean-generic:
338   - -rm -f Makefile $(CONFIG_CLEAN_FILES)
  434 + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
339 435  
340 436 maintainer-clean-generic:
341 437 @echo "This command is intended for maintainers to use"
342 438 @echo "it deletes files that may require special tools to rebuild."
343 439 clean: clean-am
344 440  
345   -clean-am: clean-checkPROGRAMS clean-generic clean-libtool mostlyclean-am
  441 +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
  442 + mostlyclean-am
346 443  
347 444 distclean: distclean-am
348   -
  445 + -rm -f Makefile
349 446 distclean-am: clean-am distclean-compile distclean-generic \
350 447 distclean-libtool distclean-tags
351 448  
... ... @@ -353,6 +450,8 @@ dvi: dvi-am
353 450  
354 451 dvi-am:
355 452  
  453 +html: html-am
  454 +
356 455 info: info-am
357 456  
358 457 info-am:
... ... @@ -368,7 +467,7 @@ install-man:
368 467 installcheck-am:
369 468  
370 469 maintainer-clean: maintainer-clean-am
371   -
  470 + -rm -f Makefile
372 471 maintainer-clean-am: distclean-am maintainer-clean-generic
373 472  
374 473 mostlyclean: mostlyclean-am
... ... @@ -376,17 +475,26 @@ mostlyclean: mostlyclean-am
376 475 mostlyclean-am: mostlyclean-compile mostlyclean-generic \
377 476 mostlyclean-libtool
378 477  
  478 +pdf: pdf-am
  479 +
  480 +pdf-am:
  481 +
  482 +ps: ps-am
  483 +
  484 +ps-am:
  485 +
379 486 uninstall-am: uninstall-info-am
380 487  
381   -.PHONY: GTAGS all all-am check check-TESTS check-am clean \
382   - clean-checkPROGRAMS clean-generic clean-libtool distclean \
383   - distclean-compile distclean-generic distclean-libtool \
384   - distclean-tags distdir dvi dvi-am info info-am install \
385   - install-am install-data install-data-am install-exec \
386   - install-exec-am install-info install-info-am install-man \
387   - install-strip installcheck installcheck-am installdirs \
388   - maintainer-clean maintainer-clean-generic mostlyclean \
389   - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
  488 +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
  489 + clean-checkPROGRAMS clean-generic clean-libtool ctags \
  490 + distclean distclean-compile distclean-generic \
  491 + distclean-libtool distclean-tags distdir dvi dvi-am html \
  492 + html-am info info-am install install-am install-data \
  493 + install-data-am install-exec install-exec-am install-info \
  494 + install-info-am install-man install-strip installcheck \
  495 + installcheck-am installdirs maintainer-clean \
  496 + maintainer-clean-generic mostlyclean mostlyclean-compile \
  497 + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
390 498 tags uninstall uninstall-am uninstall-info-am
391 499  
392 500 # Tell versions [3.59,3.63) of GNU make to not export all variables.
... ...
test/test_GMatrix.cpp
... ... @@ -18,10 +18,12 @@
18 18 using namespace std;
19 19  
20 20 /* __ Globals ____________________________________________________________ */
21   -double g_matrix[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0};
22   -double g_vector[] = {1.0, 2.0, 3.0};
  21 +double g_matrix[] = {1.0, 2.0, 3.0, 4.0,
  22 + 5.0, 6.0, 7.0, 8.0,
  23 + 9.0, 10., 11., 12.};
  24 +double g_vector[] = {1.0, 2.0, 3.0, 4.0};
23 25 unsigned g_rows = 3;
24   -unsigned g_cols = 3;
  26 +unsigned g_cols = 4;
25 27  
26 28  
27 29 /***************************************************************************
... ... @@ -72,7 +74,32 @@ int check_matrix(const GMatrix&amp; m, const double scale, const double add)
72 74 for (unsigned row = 0; row < g_rows; ++row) {
73 75 for (unsigned col = 0; col < g_cols; ++col) {
74 76 double value = g_matrix[col+row*g_cols] * scale + add;
75   - if (m(row,col) != value) {
  77 + if (fabs(m(row,col)-value) > 1.0e-15) {
  78 + result = 0;
  79 + break;
  80 + }
  81 + }
  82 + }
  83 + }
  84 + catch (exception &e) {
  85 + cout << "TEST ERROR: Unable to check test matrix." << endl;
  86 + throw;
  87 + }
  88 + return result;
  89 +}
  90 +
  91 +
  92 +/***************************************************************************
  93 + * Check transposed test matrix *
  94 + ***************************************************************************/
  95 +int check_transpose_matrix(const GMatrix& m, const double scale, const double add)
  96 +{
  97 + int result = 1;
  98 + try {
  99 + for (unsigned row = 0; row < g_rows; ++row) {
  100 + for (unsigned col = 0; col < g_cols; ++col) {
  101 + double value = g_matrix[col+row*g_cols] * scale + add;
  102 + if (m(col,row) != value) {
76 103 result = 0;
77 104 break;
78 105 }
... ... @@ -167,15 +194,15 @@ int check_matrix_vector(const GVector&amp; v)
167 194 ***************************************************************************/
168 195 int check_matrix_matrix(const GMatrix& m)
169 196 {
170   - if (m.rows() != g_rows || m.cols() != g_cols)
  197 + if (m.rows() != g_rows || m.cols() != g_rows)
171 198 return 0;
172 199 int result = 1;
173 200 try {
174   - for (unsigned row = 0; row < g_rows; ++row) {
175   - for (unsigned col = 0; col < g_cols; ++col) {
  201 + for (unsigned row = 0; row < m.rows(); ++row) {
  202 + for (unsigned col = 0; col < m.cols(); ++col) {
176 203 double value = 0.0;
177 204 for (unsigned i = 0; i < g_cols; ++i)
178   - value += g_matrix[i+row*g_cols] * g_matrix[row+i*g_cols];
  205 + value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols];
179 206 if (m(row,col) != value) {
180 207 result = 0;
181 208 break;
... ... @@ -323,7 +350,7 @@ int main(void)
323 350 cout << "GMatrix - Test 4: Define matrix using copy constructor: ";
324 351 //
325 352 GMatrix test4 = m_test;
326   - if (!check_matrix(test4, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  353 + if (!check_matrix(test4, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
327 354 cout << endl << "TEST ERROR: Corrupt copy constructor." << endl;
328 355 cout << test4 << endl;
329 356 throw;
... ... @@ -341,8 +368,8 @@ int main(void)
341 368 //
342 369 // GMatrix = GMatrix
343 370 result = m_test;
344   - if (!check_matrix(result, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
345   - cout << endl << "TEST ERROR: Corrupt copy constructor." << endl;
  371 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  372 + cout << endl << "TEST ERROR: Corrupt assignment." << endl;
346 373 cout << result << endl;
347 374 throw;
348 375 }
... ... @@ -356,14 +383,41 @@ int main(void)
356 383 }
357 384 cout << "ok." << endl;
358 385  
359   - // Test 6: Matrix*Vector multiplication
  386 + // Test 6: Transposition
360 387 try {
361   - cout << "GMatrix - Test 6: Matrix*Vector multiplication: ";
  388 + cout << "GMatrix - Test 6: Transposition: ";
362 389 //
363   - GVector v_test6 = m_test*v_test;
364   - if (!check_matrix_vector(v_test6) && !check_matrix(m_test, 1.0, 0.0)) {
  390 + // transpose(GMatrix)
  391 + result = transpose(m_test);
  392 + if (!check_transpose_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  393 + cout << endl << "TEST ERROR: Corrupt transpose(GMatrix) function." << endl;
  394 + cout << result << endl;
  395 + throw;
  396 + }
  397 + //
  398 + // GMatrix.transpose()
  399 + result = m_test;
  400 + result.transpose();
  401 + if (!check_transpose_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  402 + cout << endl << "TEST ERROR: Corrupt GMatrix.transpose() function." << endl;
  403 + cout << result << endl;
  404 + throw;
  405 + }
  406 + }
  407 + catch (exception &e) {
  408 + cout << e.what() << endl;
  409 + throw;
  410 + }
  411 + cout << "ok." << endl;
  412 +
  413 + // Test 7: Matrix*Vector multiplication
  414 + try {
  415 + cout << "GMatrix - Test 7: Matrix*Vector multiplication: ";
  416 + //
  417 + GVector v_test7 = m_test*v_test;
  418 + if (!check_matrix_vector(v_test7) || !check_matrix(m_test, 1.0, 0.0)) {
365 419 cout << endl << "TEST ERROR: Corrupt Matrix*Vector multiplication." << endl;
366   - cout << v_test6 << endl;
  420 + cout << v_test7 << endl;
367 421 throw;
368 422 }
369 423 }
... ... @@ -372,9 +426,9 @@ int main(void)
372 426 throw;
373 427 }
374 428 try {
375   - GVector v_test6 = bigger*v_test;
  429 + GVector v_test7 = bigger*v_test;
376 430 }
377   - catch (GMatrix::vec_mat_mismatch &e) {
  431 + catch (GMatrix::matrix_vector_mismatch &e) {
378 432 }
379 433 catch (exception &e) {
380 434 cout << e.what() << endl;
... ... @@ -382,14 +436,14 @@ int main(void)
382 436 }
383 437 cout << "ok." << endl;
384 438  
385   - // Test 7: Matrix*Matrix multiplication
  439 + // Test 8: Matrix*Matrix multiplication
386 440 try {
387   - cout << "GMatrix - Test 7: Matrix*Matrix multiplication: ";
  441 + cout << "GMatrix - Test 8: Matrix*Matrix multiplication: ";
388 442 //
389   - GMatrix m_test7 = m_test*m_test;
390   - if (!check_matrix_matrix(m_test7) && !check_matrix(m_test, 1.0, 0.0)) {
  443 + GMatrix m_test8 = m_test * transpose(m_test);
  444 + if (!check_matrix_matrix(m_test8) || !check_matrix(m_test, 1.0, 0.0)) {
391 445 cout << endl << "TEST ERROR: Corrupt Matrix*Matrix multiplication." << endl;
392   - cout << m_test7 << endl;
  446 + cout << m_test8 << endl;
393 447 throw;
394 448 }
395 449 }
... ... @@ -398,18 +452,18 @@ int main(void)
398 452 throw;
399 453 }
400 454 try {
401   - GMatrix m_test7 = m_test*bigger;
  455 + GMatrix m_test8 = m_test*bigger;
402 456 }
403   - catch (GMatrix::dim_mult_mismatch &e) {
  457 + catch (GMatrix::matrix_mismatch &e) {
404 458 }
405 459 catch (exception &e) {
406 460 cout << e.what() << endl;
407 461 throw;
408 462 }
409 463 try {
410   - GMatrix m_test7 = bigger*m_test;
  464 + GMatrix m_test8 = bigger*m_test;
411 465 }
412   - catch (GMatrix::dim_mult_mismatch &e) {
  466 + catch (GMatrix::matrix_mismatch &e) {
413 467 }
414 468 catch (exception &e) {
415 469 cout << e.what() << endl;
... ... @@ -417,67 +471,40 @@ int main(void)
417 471 }
418 472 cout << "ok." << endl;
419 473  
420   - // Test 8: Assignment and arithmetics
  474 + // Test 9: Assignment and arithmetics
421 475 try {
422   - cout << "GMatrix - Test 8: Assignment and arithmetics: ";
  476 + cout << "GMatrix - Test 9: Assignment and arithmetics: ";
423 477 //
424 478 // -GMatrix
425 479 result = -m_test;
426   - if (!check_matrix(result, -1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  480 + if (!check_matrix(result, -1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
427 481 cout << endl << "TEST ERROR: Corrupt -GMatrix operator." << endl;
428 482 cout << result << endl;
429 483 throw;
430 484 }
431 485 //
432   - // GMatrix = 3.0
433   - result = m_test;
434   - result = 3.0;
435   - if (!check_matrix(result, 0.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
436   - cout << endl << "TEST ERROR: Corrupt GMatrix = double operator." << endl;
437   - cout << result << endl;
438   - throw;
439   - }
440   - //
441 486 // GMatrix += GMatrix
442 487 result = m_test;
443 488 result += m_test;
444   - if (!check_matrix(result, 2.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  489 + if (!check_matrix(result, 2.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
445 490 cout << endl << "TEST ERROR: Corrupt GMatrix += GMatrix operator." << endl;
446 491 cout << result << endl;
447 492 throw;
448 493 }
449 494 //
450   - // GMatrix += 3.0
451   - result = m_test;
452   - result += 3.0;
453   - if (!check_matrix(result, 1.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
454   - cout << endl << "TEST ERROR: Corrupt GMatrix += double operator." << endl;
455   - cout << result << endl;
456   - throw;
457   - }
458   - //
459 495 // GMatrix -= GMatrix
460 496 result = m_test;
461 497 result -= m_test;
462   - if (!check_matrix(result, 0.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  498 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
463 499 cout << endl << "TEST ERROR: Corrupt GMatrix -= GMatrix operator." << endl;
464 500 cout << result << endl;
465 501 throw;
466 502 }
467 503 //
468   - // GMatrix -= 3.0
469   - result = m_test;
470   - result -= 3.0;
471   - if (!check_matrix(result, 1.0, -3.0) && !check_matrix(m_test, 1.0, 0.0)) {
472   - cout << endl << "TEST ERROR: Corrupt GMatrix -= double operator." << endl;
473   - cout << result << endl;
474   - throw;
475   - }
476   - //
477 504 // GMatrix *= 3.0
478 505 result = m_test;
479 506 result *= 3.0;
480   - if (!check_matrix(result, 3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  507 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
481 508 cout << endl << "TEST ERROR: Corrupt GMatrix *= double operator." << endl;
482 509 cout << result << endl;
483 510 throw;
... ... @@ -486,7 +513,7 @@ int main(void)
486 513 // GMatrix /= 3.0
487 514 result = m_test;
488 515 result /= 3.0;
489   - if (!check_matrix(result, 1.0/3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  516 + if (!check_matrix(result, 1.0/3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
490 517 cout << endl << "TEST ERROR: Corrupt GMatrix /= double operator." << endl;
491 518 cout << result << endl;
492 519 throw;
... ... @@ -494,7 +521,7 @@ int main(void)
494 521 //
495 522 // GMatrix + GMatrix
496 523 result = m_test + m_test;
497   - if (!check_matrix(result, 2.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  524 + if (!check_matrix(result, 2.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
498 525 cout << endl << "TEST ERROR: Corrupt GMatrix + GMatrix operator." << endl;
499 526 cout << result << endl;
500 527 throw;
... ... @@ -502,7 +529,7 @@ int main(void)
502 529 //
503 530 // GMatrix - GMatrix
504 531 result = m_test - m_test;
505   - if (!check_matrix(result, 0.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  532 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
506 533 cout << endl << "TEST ERROR: Corrupt GMatrix - GMatrix operator." << endl;
507 534 cout << result << endl;
508 535 throw;
... ... @@ -510,47 +537,15 @@ int main(void)
510 537 //
511 538 // GMatrix - GMatrix
512 539 result = m_test - m_test;
513   - if (!check_matrix(result, 0.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  540 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
514 541 cout << endl << "TEST ERROR: Corrupt GMatrix - GMatrix operator." << endl;
515 542 cout << result << endl;
516 543 throw;
517 544 }
518 545 //
519   - // GMatrix + 3.0
520   - result = m_test + 3.0;
521   - if (!check_matrix(result, 1.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
522   - cout << endl << "TEST ERROR: Corrupt GMatrix + double operator." << endl;
523   - cout << result << endl;
524   - throw;
525   - }
526   - //
527   - // 3.0 + GMatrix
528   - result = 3.0 + m_test;
529   - if (!check_matrix(result, 1.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
530   - cout << endl << "TEST ERROR: Corrupt double + GMatrix operator." << endl;
531   - cout << result << endl;
532   - throw;
533   - }
534   - //
535   - // GMatrix - 3.0
536   - result = m_test - 3.0;
537   - if (!check_matrix(result, 1.0, -3.0) && !check_matrix(m_test, 1.0, 0.0)) {
538   - cout << endl << "TEST ERROR: Corrupt GMatrix - double operator." << endl;
539   - cout << result << endl;
540   - throw;
541   - }
542   - //
543   - // 3.0 - GMatrix
544   - result = 3.0 - m_test;
545   - if (!check_matrix(result, -1.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
546   - cout << endl << "TEST ERROR: Corrupt double - GMatrix operator." << endl;
547   - cout << result << endl;
548   - throw;
549   - }
550   - //
551 546 // GMatrix * 3.0
552 547 result = m_test * 3.0;
553   - if (!check_matrix(result, 3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  548 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
554 549 cout << endl << "TEST ERROR: Corrupt GMatrix * double operator." << endl;
555 550 cout << result << endl;
556 551 throw;
... ... @@ -558,7 +553,7 @@ int main(void)
558 553 //
559 554 // 3.0 * GMatrix
560 555 result = 3.0 * m_test;
561   - if (!check_matrix(result, 3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  556 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
562 557 cout << endl << "TEST ERROR: Corrupt double * GMatrix operator." << endl;
563 558 cout << result << endl;
564 559 throw;
... ... @@ -566,7 +561,7 @@ int main(void)
566 561 //
567 562 // GMatrix / 3.0
568 563 result = m_test / 3.0;
569   - if (!check_matrix(result, 1.0/3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  564 + if (!check_matrix(result, 1.0/3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
570 565 cout << endl << "TEST ERROR: Corrupt GMatrix / double operator." << endl;
571 566 cout << result << endl;
572 567 throw;
... ... @@ -580,7 +575,7 @@ int main(void)
580 575 result = m_test;
581 576 result += bigger;
582 577 }
583   - catch (GMatrix::dim_add_mismatch) {
  578 + catch (GMatrix::matrix_mismatch) {
584 579 }
585 580 catch (exception &e) {
586 581 cout << e.what() << endl;
... ... @@ -588,9 +583,9 @@ int main(void)
588 583 }
589 584 cout << "ok." << endl;
590 585  
591   - // Test 9: Matrix functions
  586 + // Test 10: Matrix functions
592 587 try {
593   - cout << "GMatrix - Test 9: Matrix functions: ";
  588 + cout << "GMatrix - Test 10: Matrix functions: ";
594 589 //
595 590 double min = m_test.min();
596 591 if (!check_matrix_min(min)) {
... ... @@ -618,9 +613,9 @@ int main(void)
618 613 }
619 614 cout << "ok." << endl;
620 615  
621   - // Test 10: Matrix comparison
  616 + // Test 11: Matrix comparison
622 617 try {
623   - cout << "GMatrix - Test 10: Comparison: ";
  618 + cout << "GMatrix - Test 11: Comparison: ";
624 619 //
625 620 if ((m_test == m_test) != 1) {
626 621 cout << endl << "TEST ERROR: Corrupt GMatrix == GMatrix operator." << endl;
... ... @@ -659,49 +654,4 @@ int main(void)
659 654 }
660 655 cout << "ok." << endl;
661 656  
662   - // Test 11: Transformations
663   - try {
664   - cout << "GMatrix - Test 11: Transformations: ";
665   - //
666   - // transpose(GMatrix)
667   - result = transpose(m_test);
668   - if (!check_matrix(result, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
669   - cout << endl << "TEST ERROR: Corrupt transpose(GMatrix) function." << endl;
670   - cout << result << endl;
671   - throw;
672   - }
673   - //
674   - // GMatrix.transpose()
675   - result = m_test;
676   - result.transpose();
677   - if (!check_matrix(result, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
678   - cout << endl << "TEST ERROR: Corrupt GMatrix.transpose() function." << endl;
679   - cout << result << endl;
680   - throw;
681   - }
682   -/*
683   - //
684   - // lower_triangle(GMatrix)
685   - m_test11 = lower_triangle(m_test);
686   - if (!check_matrix_lt(m_test11, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
687   - cout << endl << "TEST ERROR: Corrupt lower_triangle(GMatrix) function." << endl;
688   - cout << m_test11 << endl;
689   - throw;
690   - }
691   - //
692   - // upper_triangle(GMatrix)
693   - m_test11 = upper_triangle(m_test);
694   - if (!check_matrix_ut(m_test11, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
695   - cout << endl << "TEST ERROR: Corrupt upper_triangle(GMatrix) function." << endl;
696   - cout << m_test11 << endl;
697   - throw;
698   - }
699   -*/
700   - }
701   - catch (exception &e) {
702   - cout << e.what() << endl;
703   - throw;
704   - }
705   - cout << "ok." << endl;
706   -
707   -}
708 657 \ No newline at end of file
  658 +}
... ...
test/test_GSparseMatrix.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * test_GSparseMatrix.cpp - test GSparseMatrix class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright : (C) 2006 by Jurgen Knodlseder *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software; you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation; either version 2 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + ***************************************************************************/
  13 +
  14 +/* __ Includes ___________________________________________________________ */
  15 +#include "test_GSparseMatrix.hpp"
  16 +
  17 +/* __ Namespaces _________________________________________________________ */
  18 +using namespace std;
  19 +
  20 +/* __ Definitions ________________________________________________________ */
  21 +//#define DUMP_RESIDUALS // Dump residuals
  22 +#define DUMP_TIMING // Dump timing
  23 +
  24 +/* __ Globals ____________________________________________________________ */
  25 +double g_matrix[] = {1.0, 7.0, 3.0, 2.0, 4.0, 8.0, 5.0, 6.0, 9.0};
  26 +unsigned g_row[] = { 0, 0, 1, 2, 2, 2, 3, 3, 3};
  27 +unsigned g_col[] = { 0, 4, 1, 0, 2, 4, 2, 3, 4};
  28 +double g_vector[] = {1.0, 2.0, 3.0, 4.0, 5.0};
  29 +unsigned g_elements = 9;
  30 +unsigned g_rows = 4;
  31 +unsigned g_cols = 5;
  32 +
  33 +
  34 +/***************************************************************************
  35 + * Set test matrix *
  36 + ***************************************************************************/
  37 +GSparseMatrix set_matrix(void)
  38 +{
  39 + try {
  40 + GSparseMatrix matrix(g_rows,g_cols);
  41 + for (unsigned i = 0; i < g_elements; ++i)
  42 + matrix(g_row[i],g_col[i]) = g_matrix[i];
  43 + return matrix;
  44 + }
  45 + catch (exception &e) {
  46 + cout << "TEST ERROR: Unable to set test matrix." << endl;
  47 + throw;
  48 + }
  49 +}
  50 +
  51 +
  52 +/***************************************************************************
  53 + * Set test vector *
  54 + ***************************************************************************/
  55 +GVector set_vector(void)
  56 +{
  57 + try {
  58 + GVector vector(g_cols);
  59 + for (unsigned col = 0; col < g_cols; ++col)
  60 + vector(col) = g_vector[col];
  61 + return vector;
  62 + }
  63 + catch (exception &e) {
  64 + cout << "TEST ERROR: Unable to set test vector." << endl;
  65 + throw;
  66 + }
  67 +}
  68 +
  69 +
  70 +/***************************************************************************
  71 + * Check test matrix *
  72 + ***************************************************************************/
  73 +int check_matrix(const GSparseMatrix& m, const double scale, const double add)
  74 +{
  75 + int result = 1;
  76 + try {
  77 + for (unsigned row = 0; row < g_rows; ++row) {
  78 + for (unsigned col = 0; col < g_cols; ++col) {
  79 + unsigned i;
  80 + double ref_value = add;
  81 + for (i = 0; i < g_elements; ++i) {
  82 + if (g_row[i] == row && g_col[i] == col) {
  83 + ref_value = g_matrix[i] * scale + add;
  84 + break;
  85 + }
  86 + }
  87 + if (fabs(m(row,col)-ref_value) > 1.0e-15) {
  88 +//cout << row << "," << col << ": " << fabs(m(row,col)-ref_value) << endl;
  89 + result = 0;
  90 + break;
  91 + }
  92 + }
  93 + }
  94 + }
  95 + catch (exception &e) {
  96 + cout << "TEST ERROR: Unable to check test matrix." << endl;
  97 + throw;
  98 + }
  99 + return result;
  100 +}
  101 +
  102 +
  103 +/***************************************************************************
  104 + * Check matrix*vector *
  105 + ***************************************************************************/
  106 +int check_matrix_vector(const GVector& v)
  107 +{
  108 + int result = 1;
  109 + try {
  110 + for (unsigned row = 0; row < v.size(); ++row) {
  111 + double value = 0.0;
  112 + for (unsigned col = 0; col < g_cols; ++col) {
  113 + unsigned i;
  114 + double ref_value = 0.0;
  115 + for (i = 0; i < g_elements; ++i) {
  116 + if (g_row[i] == row && g_col[i] == col) {
  117 + ref_value = g_matrix[i];
  118 + break;
  119 + }
  120 + }
  121 + value += ref_value * g_vector[col];
  122 + }
  123 + if (v(row) != value) {
  124 + result = 0;
  125 + break;
  126 + }
  127 + }
  128 + }
  129 + catch (exception &e) {
  130 + cout << "TEST ERROR: Unable to check matrix*vector product." << endl;
  131 + throw;
  132 + }
  133 + return result;
  134 +}
  135 +
  136 +
  137 +/***************************************************************************
  138 + * Check matrix*matrix *
  139 + ***************************************************************************/
  140 +int check_matrix_matrix(const GSparseMatrix& m)
  141 +{
  142 + if (m.rows() != g_rows || m.cols() != g_rows)
  143 + return 0;
  144 + int result = 1;
  145 + try {
  146 + for (unsigned row = 0; row < m.rows(); ++row) {
  147 + for (unsigned col = 0; col < m.cols(); ++col) {
  148 + double value = 0.0;
  149 + for (unsigned i = 0; i < g_cols; ++i) {
  150 + unsigned k;
  151 + double ref_value_1 = 0.0;
  152 + double ref_value_2 = 0.0;
  153 + for (k = 0; k < g_elements; ++k) {
  154 + if (g_row[k] == row && g_col[k] == i) {
  155 + ref_value_1 = g_matrix[k];
  156 + break;
  157 + }
  158 + }
  159 + for (k = 0; k < g_elements; ++k) {
  160 + if (g_row[k] == col && g_col[k] == i) {
  161 + ref_value_2 = g_matrix[k];
  162 + break;
  163 + }
  164 + }
  165 + value += ref_value_1 * ref_value_2;
  166 + }
  167 +//cout << row << "," << col << ": " << fabs(m(row,col)-value) << endl;
  168 + if (m(row,col) != value) {
  169 + result = 0;
  170 + break;
  171 + }
  172 + }
  173 + }
  174 + }
  175 + catch (exception &e) {
  176 + cout << "TEST ERROR: Unable to check matrix*matrix product." << endl;
  177 + throw;
  178 + }
  179 + return result;
  180 +}
  181 +
  182 +
  183 +/***************************************************************************
  184 + * Check transposed test matrix *
  185 + ***************************************************************************/
  186 +int check_transpose_matrix(const GSparseMatrix& m, const double scale, const double add)
  187 +{
  188 + int result = 1;
  189 + try {
  190 + for (unsigned row = 0; row < g_rows; ++row) {
  191 + for (unsigned col = 0; col < g_cols; ++col) {
  192 + unsigned i;
  193 + double ref_value = 0.0;
  194 + for (i = 0; i < g_elements; ++i) {
  195 + if (g_row[i] == row && g_col[i] == col) {
  196 + ref_value = g_matrix[i] * scale + add;
  197 + break;
  198 + }
  199 + }
  200 + if (fabs(m(col,row)-ref_value) > 1.0e-15) {
  201 + result = 0;
  202 + break;
  203 + }
  204 + }
  205 + }
  206 + }
  207 + catch (exception &e) {
  208 + cout << "TEST ERROR: Unable to check test matrix." << endl;
  209 + throw;
  210 + }
  211 + return result;
  212 +}
  213 +
  214 +
  215 +/***************************************************************************
  216 + * Check matrix min *
  217 + ***************************************************************************/
  218 +int check_matrix_min(const double min)
  219 +{
  220 + double value = g_matrix[0];
  221 + for (unsigned i = 0; i < g_elements; ++i) {
  222 + if (g_matrix[i] < value)
  223 + value = g_matrix[i];
  224 + }
  225 +// return (min == value);
  226 + return (min == 0.0);
  227 +}
  228 +
  229 +
  230 +/***************************************************************************
  231 + * Check matrix max *
  232 + ***************************************************************************/
  233 +int check_matrix_max(const double max)
  234 +{
  235 + double value = g_matrix[0];
  236 + for (unsigned i = 0; i < g_elements; ++i) {
  237 + if (g_matrix[i] > value)
  238 + value = g_matrix[i];
  239 + }
  240 + return (max == value);
  241 +}
  242 +
  243 +
  244 +/***************************************************************************
  245 + * Check matrix sum *
  246 + ***************************************************************************/
  247 +int check_matrix_sum(const double sum)
  248 +{
  249 + double value = 0.0;
  250 + for (unsigned i = 0; i < g_elements; ++i)
  251 + value += g_matrix[i];
  252 + return (sum == value);
  253 +}
  254 +
  255 +
  256 +/***************************************************************************
  257 + * Test: Output *
  258 + ***************************************************************************/
  259 +void test_output(const GSparseMatrix& m_test)
  260 +{
  261 + cout << "Test GSparseMatrix: Output test matrix: " << endl;
  262 + try {
  263 + cout << m_test << endl;
  264 + }
  265 + catch (exception &e) {
  266 + cout << endl << "TEST ERROR: Unable to output matrix." << endl;
  267 + cout << e.what() << endl;
  268 + throw;
  269 + }
  270 +}
  271 +
  272 +
  273 +/***************************************************************************
  274 + * Test: Allocate zero matrix *
  275 + ***************************************************************************/
  276 +void test_allocate(void)
  277 +{
  278 + cout << "Test GSparseMatrix: Allocate zero matrix: ";
  279 + try {
  280 + GSparseMatrix test(0,0);
  281 + }
  282 + catch (empty &e) {
  283 + cout << ". ok." << endl;
  284 + }
  285 + catch (exception &e) {
  286 + cout << endl << "TEST ERROR: Did not signal zero matrix allocation." << endl;
  287 + cout << e.what() << endl;
  288 + throw;
  289 + }
  290 + cout << ". ok." << endl;
  291 +}
  292 +
  293 +
  294 +/***************************************************************************
  295 + * Test: Assign values *
  296 + ***************************************************************************/
  297 +void test_assign_values(const GSparseMatrix& m_test)
  298 +{
  299 + cout << "Test GSparseMatrix: Assign matrix values: ";
  300 + try {
  301 + //
  302 + GSparseMatrix test(3,3);
  303 + test(1,1) = 1.0;
  304 + if (test(0,0) != 0.0 || test(1,0) != 0.0 || test(2,0) != 0.0 ||
  305 + test(0,1) != 0.0 || test(1,1) != 1.0 || test(2,1) != 0.0 ||
  306 + test(0,2) != 0.0 || test(1,2) != 0.0 || test(2,2) != 0.0) {
  307 + cout << endl << "TEST ERROR: Unable to set matrix values." << endl;
  308 + cout << test << endl;
  309 + throw;
  310 + }
  311 + cout << ".";
  312 + //
  313 + GSparseMatrix result = m_test;
  314 + result(0,0) = 0.0;
  315 + result(0,0) = 1.0;
  316 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  317 + cout << endl << "TEST ERROR: Bad M(row,col) assignment." << endl;
  318 + cout << "result:" << endl << result << endl;
  319 + cout << "m_test:" << endl << m_test << endl;
  320 + throw;
  321 + }
  322 + cout << ".";
  323 + //
  324 + result = m_test;
  325 + result(0,0) = 0.0;
  326 + result(0,4) = 0.0;
  327 + result(0,0) = 1.0;
  328 + result(0,4) = 0.0;
  329 + result(0,4) = 7.0;
  330 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  331 + cout << endl << "TEST ERROR: Bad M(row,col) assignment." << endl;
  332 + cout << "result:" << endl << result << endl;
  333 + cout << "m_test:" << endl << m_test << endl;
  334 + throw;
  335 + }
  336 + cout << ".";
  337 + //
  338 + result = m_test;
  339 + result(0,1) = 2.0;
  340 + result(0,2) = 2.0;
  341 + result(0,3) = 2.0;
  342 + result(0,1) = 0.0;
  343 + result(0,2) = 0.0;
  344 + result(0,3) = 0.0;
  345 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  346 + cout << endl << "TEST ERROR: Bad M(row,col) assignment." << endl;
  347 + cout << "result:" << endl << result << endl;
  348 + cout << "m_test:" << endl << m_test << endl;
  349 + throw;
  350 + }
  351 + cout << ".";
  352 + }
  353 + catch (exception &e) {
  354 + cout << e.what() << endl;
  355 + throw;
  356 + }
  357 + #if defined(G_RANGE_CHECK)
  358 + try {
  359 + GSparseMatrix test(3,3);
  360 + test(3,3) = 1.0;
  361 + }
  362 + catch (GMatrix::out_of_range &e) {
  363 + }
  364 + catch (exception &e) {
  365 + cout << e.what() << endl;
  366 + throw;
  367 + }
  368 + cout << ".";
  369 + #endif
  370 + cout << " ok." << endl;
  371 +}
  372 +
  373 +
  374 +/***************************************************************************
  375 + * Test: Matrix copy constructor *
  376 + ***************************************************************************/
  377 +void test_copy_constructor(const GSparseMatrix& m_test)
  378 +{
  379 + cout << "Test GSparseMatrix: Define matrix using copy constructor: ";
  380 + try {
  381 + //
  382 + GSparseMatrix test = m_test;
  383 + if (!check_matrix(test, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  384 + cout << endl << "TEST ERROR: Corrupt copy constructor." << endl;
  385 + cout << test << endl;
  386 + throw;
  387 + }
  388 + }
  389 + catch (exception &e) {
  390 + cout << e.what() << endl;
  391 + throw;
  392 + }
  393 + cout << ". ok." << endl;
  394 +}
  395 +
  396 +
  397 +/***************************************************************************
  398 + * Test: Matrix assignment *
  399 + ***************************************************************************/
  400 +void test_assign_matrix(const GSparseMatrix& m_test)
  401 +{
  402 + cout << "Test GSparseMatrix: Matrix assignment: ";
  403 + try {
  404 + //
  405 + // GSparseMatrix = GSparseMatrix
  406 + GSparseMatrix result(1,1);
  407 + result = m_test;
  408 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  409 + cout << endl << "TEST ERROR: Corrupt assignment." << endl;
  410 + cout << result << endl;
  411 + throw;
  412 + }
  413 + cout << ".";
  414 + //
  415 + // GSparseMatrix = GSparseMatrix (bigger matrix)
  416 + GSparseMatrix bigger(1000,1000);
  417 + for (int i = 0; i < 1000; ++i)
  418 + bigger(i,i) = (i+1)*1.1;
  419 + result = bigger;
  420 + cout << ".";
  421 + }
  422 + catch (exception &e) {
  423 + cout << e.what() << endl;
  424 + throw;
  425 + }
  426 + cout << " ok." << endl;
  427 +}
  428 +
  429 +
  430 +/***************************************************************************
  431 + * Test: Matrix transpose *
  432 + ***************************************************************************/
  433 +void test_transpose(const GSparseMatrix& m_test)
  434 +{
  435 + cout << "Test GSparseMatrix: Matrix transpose: ";
  436 + try {
  437 + //
  438 + // transpose(GSparseMatrix)
  439 + GSparseMatrix result(1,1);
  440 + result = transpose(m_test);
  441 + if (!check_transpose_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  442 + cout << endl << "TEST ERROR: Corrupt transpose(GSparseMatrix) function." << endl;
  443 + cout << result << endl;
  444 + throw;
  445 + }
  446 + cout << ".";
  447 + //
  448 + // GSparseMatrix.transpose()
  449 + result = m_test;
  450 + result.transpose();
  451 + if (!check_transpose_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  452 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix.transpose() function." << endl;
  453 + cout << result << endl;
  454 + throw;
  455 + }
  456 + cout << ".";
  457 + }
  458 + catch (exception &e) {
  459 + cout << e.what() << endl;
  460 + throw;
  461 + }
  462 + cout << " ok." << endl;
  463 +}
  464 +
  465 +
  466 +/***************************************************************************
  467 + * Test: Matrix*Vector multiplication *
  468 + ***************************************************************************/
  469 +void test_matrix_vector(const GSparseMatrix& m_test, const GVector& v_test)
  470 +{
  471 + cout << "Test GSparseMatrix: Matrix*Vector multiplication: ";
  472 + try {
  473 + //
  474 + GVector test = m_test*v_test;
  475 + if (!check_matrix_vector(test) || !check_matrix(m_test, 1.0, 0.0)) {
  476 + cout << endl << "TEST ERROR: Corrupt Matrix*Vector multiplication." << endl;
  477 + cout << test << endl;
  478 + throw;
  479 + }
  480 + }
  481 + catch (exception &e) {
  482 + cout << e.what() << endl;
  483 + throw;
  484 + }
  485 + cout << ".";
  486 + try {
  487 + GSparseMatrix bigger(1000,1000);
  488 + for (int i = 0; i < 1000; ++i)
  489 + bigger(i,i) = (i+1)*1.1;
  490 + GVector test = bigger*v_test;
  491 + }
  492 + catch (GMatrix::matrix_vector_mismatch &e) {
  493 + }
  494 + catch (exception &e) {
  495 + cout << e.what() << endl;
  496 + throw;
  497 + }
  498 + cout << ". ok." << endl;
  499 +}
  500 +
  501 +
  502 +/***************************************************************************
  503 + * Test: Matrix*Vector multiplication *
  504 + ***************************************************************************/
  505 +void test_matrix_matrix(const GSparseMatrix& m_test)
  506 +{
  507 + cout << "Test GSparseMatrix: Matrix*Matrix multiplication: ";
  508 + try {
  509 + //
  510 + GSparseMatrix test = m_test * transpose(m_test);
  511 + if (!check_matrix_matrix(test) || !check_matrix(m_test, 1.0, 0.0)) {
  512 + cout << endl << "TEST ERROR: Corrupt Matrix*Matrix multiplication." << endl;
  513 + cout << "test:" << endl << test << endl;
  514 + cout << "m_test:" << endl << m_test << endl;
  515 + throw;
  516 + }
  517 + cout << ".";
  518 + //
  519 + GSparseMatrix bigger(1000,1000);
  520 + for (int i = 0; i < 1000; ++i)
  521 + bigger(i,i) = (i+1)*1.1;
  522 + try {
  523 + GSparseMatrix test = m_test * bigger;
  524 + }
  525 + catch (GMatrix::matrix_mismatch &e) {
  526 + cout << ".";
  527 + }
  528 + catch (exception &e) {
  529 + cout << e.what() << endl;
  530 + throw;
  531 + }
  532 + //
  533 + try {
  534 + GSparseMatrix test7 = bigger * m_test;
  535 + }
  536 + catch (GMatrix::matrix_mismatch &e) {
  537 + cout << ".";
  538 + }
  539 + catch (exception &e) {
  540 + cout << e.what() << endl;
  541 + throw;
  542 + }
  543 + }
  544 + catch (exception &e) {
  545 + cout << e.what() << endl;
  546 + throw;
  547 + }
  548 + cout << " ok." << endl;
  549 +}
  550 +
  551 +
  552 +/***************************************************************************
  553 + * Test: Arithmetics *
  554 + ***************************************************************************/
  555 +void test_arithmetics(const GSparseMatrix& m_test)
  556 +{
  557 + cout << "Test GSparseMatrix: Arithmetics: ";
  558 + try {
  559 + //
  560 + // -GSparseMatrix
  561 + GSparseMatrix result(1,1);
  562 + result = -m_test;
  563 + if (!check_matrix(result, -1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  564 + cout << endl << "TEST ERROR: Corrupt -GSparseMatrix operator." << endl;
  565 + cout << "result " << result << endl;
  566 + cout << "m_test " << m_test << endl;
  567 + throw;
  568 + }
  569 + cout << ".";
  570 + //
  571 + // fabs(GSparseMatrix)
  572 + result = fabs(m_test);
  573 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  574 + cout << endl << "TEST ERROR: Corrupt fabs(GSparseMatrix) function." << endl;
  575 + cout << "result " << result << endl;
  576 + cout << "m_test " << m_test << endl;
  577 + throw;
  578 + }
  579 + cout << ".";
  580 + //
  581 + // GSparseMatrix += GSparseMatrix
  582 + result = m_test;
  583 + result += m_test;
  584 + if (!check_matrix(result, 2.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  585 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix += GSparseMatrix operator." << endl;
  586 + cout << "result " << result << endl;
  587 + cout << "m_test " << m_test << endl;
  588 + throw;
  589 + }
  590 + cout << ".";
  591 + //
  592 + // GSparseMatrix -= GSparseMatrix
  593 + result = m_test;
  594 + result -= m_test;
  595 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  596 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix -= GSparseMatrix operator." << endl;
  597 + cout << "result " << result << endl;
  598 + cout << "m_test " << m_test << endl;
  599 + throw;
  600 + }
  601 + cout << ".";
  602 + //
  603 + // GSparseMatrix *= 3.0
  604 + result = m_test;
  605 + result *= 3.0;
  606 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  607 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix *= double operator." << endl;
  608 + cout << "result " << result << endl;
  609 + cout << "m_test " << m_test << endl;
  610 + throw;
  611 + }
  612 + cout << ".";
  613 + //
  614 + // GSparseMatrix /= 3.0
  615 + result = m_test;
  616 + result /= 3.0;
  617 + if (!check_matrix(result, 1.0/3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  618 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix /= double operator." << endl;
  619 + cout << "result " << result << endl;
  620 + cout << "m_test " << m_test << endl;
  621 + throw;
  622 + }
  623 + cout << ".";
  624 + //
  625 + // GSparseMatrix + GSparseMatrix
  626 + result = m_test + m_test;
  627 + if (!check_matrix(result, 2.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  628 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix + GSparseMatrix operator." << endl;
  629 + cout << "result " << result << endl;
  630 + cout << "m_test " << m_test << endl;
  631 + throw;
  632 + }
  633 + cout << ".";
  634 + //
  635 + // GSparseMatrix - GSparseMatrix
  636 + result = m_test - m_test;
  637 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  638 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix - GSparseMatrix operator." << endl;
  639 + cout << "result " << result << endl;
  640 + cout << "m_test " << m_test << endl;
  641 + throw;
  642 + }
  643 + cout << ".";
  644 + //
  645 + // GSparseMatrix - GSparseMatrix
  646 + result = m_test - m_test;
  647 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  648 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix - GSparseMatrix operator." << endl;
  649 + cout << "result " << result << endl;
  650 + cout << "m_test " << m_test << endl;
  651 + throw;
  652 + }
  653 + cout << ".";
  654 + //
  655 + // GSparseMatrix * 3.0
  656 + result = m_test * 3.0;
  657 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  658 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix * double operator." << endl;
  659 + cout << "result " << result << endl;
  660 + cout << "m_test " << m_test << endl;
  661 + throw;
  662 + }
  663 + cout << ".";
  664 + //
  665 + // GSparseMatrix * -7.12
  666 + result = m_test * -7.12;
  667 + if (!check_matrix(result, -7.12, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  668 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix * double operator." << endl;
  669 + cout << "result " << result << endl;
  670 + cout << "m_test " << m_test << endl;
  671 + throw;
  672 + }
  673 + cout << ".";
  674 + //
  675 + // 3.0 * GSparseMatrix
  676 + result = 3.0 * m_test;
  677 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  678 + cout << endl << "TEST ERROR: Corrupt double * GSparseMatrix operator." << endl;
  679 + cout << "result " << result << endl;
  680 + cout << "m_test " << m_test << endl;
  681 + throw;
  682 + }
  683 + cout << ".";
  684 + //
  685 + // GSparseMatrix / 3.0
  686 + result = m_test / 3.0;
  687 + if (!check_matrix(result, 1.0/3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  688 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix / double operator." << endl;
  689 + cout << "result " << result << endl;
  690 + cout << "m_test " << m_test << endl;
  691 + throw;
  692 + }
  693 + cout << ".";
  694 + //
  695 + // GSparseMatrix / 0.0
  696 + double zero = 0.0;
  697 + result = m_test / zero;
  698 + if (!check_matrix(result, 1.0/zero, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  699 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix / 0.0." << endl;
  700 + cout << "result " << result << endl;
  701 + cout << "m_test " << m_test << endl;
  702 + throw;
  703 + cout << ".";
  704 + }
  705 + //
  706 + // GSparseMatrix.add_col()
  707 + result = m_test;
  708 + GVector v_add(g_rows);
  709 + for (int i = 0; i < g_rows; ++i)
  710 + v_add(i) = 7.0;
  711 + for (int col = 0; col < g_cols; ++col)
  712 + result.add_col(v_add, col);
  713 + if (!check_matrix(result, 1.0, 7.0) || !check_matrix(m_test, 1.0, 0.0)) {
  714 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix.add_col(+v)." << endl;
  715 + cout << "result " << result << endl;
  716 + cout << "m_test " << m_test << endl;
  717 + throw;
  718 + }
  719 + cout << ".";
  720 + //
  721 + // GSparseMatrix.add_col()
  722 + for (int col = 0; col < g_cols; ++col)
  723 + result.add_col(-v_add, col);
  724 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  725 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix.add_col(-v)." << endl;
  726 + cout << "result " << result << endl;
  727 + cout << "m_test " << m_test << endl;
  728 + throw;
  729 + }
  730 + cout << ".";
  731 + }
  732 + catch (exception &e) {
  733 + cout << e.what() << endl;
  734 + throw;
  735 + }
  736 + try {
  737 + GSparseMatrix bigger(1000,1000);
  738 + GSparseMatrix result(1,1);
  739 + for (int i = 0; i < 1000; ++i)
  740 + bigger(i,i) = (i+1)*1.1;
  741 + result = m_test;
  742 + result += bigger;
  743 + }
  744 + catch (GMatrix::matrix_mismatch) {
  745 + cout << ".";
  746 + }
  747 + catch (exception &e) {
  748 + cout << e.what() << endl;
  749 + throw;
  750 + }
  751 + cout << " ok." << endl;
  752 +}
  753 +
  754 +
  755 +/***************************************************************************
  756 + * Test: Matrix functions *
  757 + ***************************************************************************/
  758 +void test_functions(const GSparseMatrix& m_test)
  759 +{
  760 + cout << "Test GSparseMatrix: Matrix functions: ";
  761 + try {
  762 + //
  763 + double min = m_test.min();
  764 + if (!check_matrix_min(min)) {
  765 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix.min() function." << endl;
  766 + cout << "min:" << min << endl;
  767 + throw;
  768 + }
  769 + cout << ".";
  770 + //
  771 + double max = m_test.max();
  772 + if (!check_matrix_max(max)) {
  773 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix.max() function." << endl;
  774 + cout << "max:" << max << endl;
  775 + throw;
  776 + }
  777 + cout << ".";
  778 + //
  779 + double sum = m_test.sum();
  780 + if (!check_matrix_sum(sum)) {
  781 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix.sum() function." << endl;
  782 + cout << "sum:" << sum << endl;
  783 + throw;
  784 + }
  785 + cout << ".";
  786 + }
  787 + catch (exception &e) {
  788 + cout << e.what() << endl;
  789 + }
  790 + cout << " ok." << endl;
  791 +}
  792 +
  793 +
  794 +/***************************************************************************
  795 + * Test: Matrix comparison *
  796 + ***************************************************************************/
  797 +void test_comparison(const GSparseMatrix& m_test)
  798 +{
  799 + cout << "Test GSparseMatrix: Comparison: ";
  800 + try {
  801 + GSparseMatrix bigger(1000,1000);
  802 + for (int i = 0; i < 1000; ++i)
  803 + bigger(i,i) = (i+1)*1.1;
  804 + //
  805 + if ((m_test == m_test) != 1) {
  806 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix == GSparseMatrix operator." << endl;
  807 + throw;
  808 + }
  809 + cout << ".";
  810 + //
  811 + GSparseMatrix test(g_rows,g_cols);
  812 + if ((m_test == test) != 0) {
  813 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix == GSparseMatrix operator." << endl;
  814 + throw;
  815 + }
  816 + cout << ".";
  817 + //
  818 + if ((m_test == bigger) != 0) {
  819 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix == GSparseMatrix operator." << endl;
  820 + throw;
  821 + }
  822 + cout << ".";
  823 + //
  824 + if ((m_test != m_test) != 0) {
  825 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix != GSparseMatrix operator." << endl;
  826 + throw;
  827 + }
  828 + cout << ".";
  829 + //
  830 + if ((m_test != test) != 1) {
  831 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix != GSparseMatrix operator." << endl;
  832 + throw;
  833 + }
  834 + cout << ".";
  835 + //
  836 + if ((m_test != bigger) != 1) {
  837 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix != GSparseMatrix operator." << endl;
  838 + throw;
  839 + }
  840 + cout << ".";
  841 + }
  842 + catch (exception &e) {
  843 + cout << e.what() << endl;
  844 + throw;
  845 + }
  846 + cout << " ok." << endl;
  847 +}
  848 +
  849 +
  850 +/***************************************************************************
  851 + * Test: Matrix conversions *
  852 + ***************************************************************************/
  853 +void test_conversion(const GSparseMatrix& m_test)
  854 +{
  855 + cout << "Test GSparseMatrix: Conversions: ";
  856 + cout << " ok." << endl;
  857 +}
  858 +
  859 +
  860 +/***************************************************************************
  861 + * Test: Cholesky factorisation *
  862 + ***************************************************************************/
  863 +void test_cholesky(void)
  864 +{
  865 + cout << "Test GSparseMatrix: Cholesky decomposition, solver and inverter: ";
  866 + try {
  867 + //
  868 + // Setup matrix for Cholesky decomposition
  869 + GSparseMatrix m_chol_test(5,5);
  870 + m_chol_test(0,0) = 1.0;
  871 + m_chol_test(0,1) = 0.2;
  872 + m_chol_test(0,2) = 0.2;
  873 + m_chol_test(0,3) = 0.2;
  874 + m_chol_test(0,4) = 0.2;
  875 + m_chol_test(1,0) = 0.2;
  876 + m_chol_test(2,0) = 0.2;
  877 + m_chol_test(3,0) = 0.2;
  878 + m_chol_test(4,0) = 0.2;
  879 + m_chol_test(1,1) = 1.0;
  880 + m_chol_test(2,2) = 1.0;
  881 + m_chol_test(3,3) = 1.0;
  882 + m_chol_test(4,4) = 1.0;
  883 + //
  884 + // Try to solve now (should not work)
  885 + try {
  886 + GVector v_test12(5);
  887 + v_test12 = m_chol_test.cholesky_solver(v_test12);
  888 + }
  889 + catch (GMatrix::matrix_not_factorised) {
  890 + cout << ".";
  891 + }
  892 + catch (exception &e) {
  893 + cout << e.what() << endl;
  894 + throw;
  895 + }
  896 + //
  897 + // Test Cholesky decomposition
  898 + GSparseMatrix cd = cholesky_decompose(m_chol_test);
  899 + cout << ".";
  900 + //
  901 + // Test inplace Cholesky decomposition
  902 + cd = m_chol_test;
  903 + cd.cholesky_decompose();
  904 + cout << ".";
  905 + //
  906 + // Test Cholesky solver
  907 + GVector e0(5);
  908 + GVector a0(5);
  909 + e0(0) = 1.0;
  910 + a0(0) = 1.0;
  911 + a0(1) = 0.2;
  912 + a0(2) = 0.2;
  913 + a0(3) = 0.2;
  914 + a0(4) = 0.2;
  915 + GVector s0 = cd.cholesky_solver(a0);
  916 + double res = max(fabs(s0-e0));
  917 + if (res < 1.0e-15)
  918 + #if defined(DUMP_RESIDUALS)
  919 + cout << " Res(S0)=" << res << " ";
  920 + #else
  921 + cout << ".";
  922 + #endif
  923 + else {
  924 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  925 + cout << "Residual vector (all elements should be zero):" << endl;
  926 + cout << s0 << endl;
  927 + throw;
  928 + }
  929 + //
  930 + e0(0) = 0.0;
  931 + e0(1) = 1.0;
  932 + a0(0) = 0.2;
  933 + a0(1) = 1.0;
  934 + a0(2) = 0.0;
  935 + a0(3) = 0.0;
  936 + a0(4) = 0.0;
  937 + s0 = cd.cholesky_solver(a0);
  938 + res = max(fabs(s0-e0));
  939 + if (res < 1.0e-15)
  940 + #if defined(DUMP_RESIDUALS)
  941 + cout << "Res(S1)=" << res << " ";
  942 + #else
  943 + cout << ".";
  944 + #endif
  945 + else {
  946 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  947 + cout << "Residual vector (all elements should be zero):" << endl;
  948 + cout << s0 << endl;
  949 + throw;
  950 + }
  951 + //
  952 + e0(1) = 0.0;
  953 + e0(2) = 1.0;
  954 + a0(1) = 0.0;
  955 + a0(2) = 1.0;
  956 + s0 = cd.cholesky_solver(a0);
  957 + res = max(fabs(s0-e0));
  958 + if (res < 1.0e-15)
  959 + #if defined(DUMP_RESIDUALS)
  960 + cout << "Res(S2)=" << res << " ";
  961 + #else
  962 + cout << ".";
  963 + #endif
  964 + else {
  965 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  966 + cout << "Residual vector (all elements should be zero):" << endl;
  967 + cout << s0 << endl;
  968 + throw;
  969 + }
  970 + //
  971 + e0(2) = 0.0;
  972 + e0(3) = 1.0;
  973 + a0(2) = 0.0;
  974 + a0(3) = 1.0;
  975 + s0 = cd.cholesky_solver(a0);
  976 + res = max(fabs(s0-e0));
  977 + if (res < 1.0e-15)
  978 + #if defined(DUMP_RESIDUALS)
  979 + cout << "Res(S3)=" << res << " ";
  980 + #else
  981 + cout << ".";
  982 + #endif
  983 + else {
  984 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  985 + cout << "Residual vector (all elements should be zero):" << endl;
  986 + cout << s0 << endl;
  987 + throw;
  988 + }
  989 + //
  990 + e0(3) = 0.0;
  991 + e0(4) = 1.0;
  992 + a0(3) = 0.0;
  993 + a0(4) = 1.0;
  994 + s0 = cd.cholesky_solver(a0);
  995 + res = max(fabs(s0-e0));
  996 + if (res < 1.0e-15)
  997 + #if defined(DUMP_RESIDUALS)
  998 + cout << "Res(S4)=" << res << " ";
  999 + #else
  1000 + cout << ".";
  1001 + #endif
  1002 + else {
  1003 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1004 + cout << "Residual vector (all elements should be zero):" << endl;
  1005 + cout << s0 << endl;
  1006 + throw;
  1007 + }
  1008 + //
  1009 + // Setup matrix for Cholesky decomposition with zero row/col
  1010 + GSparseMatrix m_chol_test_zero(6,6);
  1011 + m_chol_test_zero(0,0) = 1.0;
  1012 + m_chol_test_zero(0,1) = 0.2;
  1013 + m_chol_test_zero(0,2) = 0.2;
  1014 + m_chol_test_zero(0,4) = 0.2;
  1015 + m_chol_test_zero(0,5) = 0.2;
  1016 + m_chol_test_zero(1,0) = 0.2;
  1017 + m_chol_test_zero(2,0) = 0.2;
  1018 + m_chol_test_zero(4,0) = 0.2;
  1019 + m_chol_test_zero(5,0) = 0.2;
  1020 + m_chol_test_zero(1,1) = 1.0;
  1021 + m_chol_test_zero(2,2) = 1.0;
  1022 + m_chol_test_zero(4,4) = 1.0;
  1023 + m_chol_test_zero(5,5) = 1.0;
  1024 + //
  1025 + // Test compressed Cholesky decomposition
  1026 + GSparseMatrix cd_zero = m_chol_test_zero;
  1027 + cd_zero.cholesky_decompose();
  1028 + //
  1029 + // Test compressed Cholesky solver
  1030 + e0 = GVector(6);
  1031 + a0 = GVector(6);
  1032 + e0(0) = 1.0;
  1033 + a0(0) = 1.0;
  1034 + a0(1) = 0.2;
  1035 + a0(2) = 0.2;
  1036 + a0(4) = 0.2;
  1037 + a0(5) = 0.2;
  1038 + s0 = cd_zero.cholesky_solver(a0);
  1039 + res = max(fabs(s0-e0));
  1040 + if (res < 1.0e-15)
  1041 + #if defined(DUMP_RESIDUALS)
  1042 + cout << "Res(S0Z)=" << res << " ";
  1043 + #else
  1044 + cout << ".";
  1045 + #endif
  1046 + else {
  1047 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1048 + cout << "Residual vector (all elements should be zero):" << endl;
  1049 + cout << s0 << endl;
  1050 + throw;
  1051 + }
  1052 + //
  1053 + e0(0) = 0.0;
  1054 + e0(1) = 1.0;
  1055 + a0(0) = 0.2;
  1056 + a0(1) = 1.0;
  1057 + a0(2) = 0.0;
  1058 + a0(4) = 0.0;
  1059 + a0(5) = 0.0;
  1060 + s0 = cd_zero.cholesky_solver(a0);
  1061 + res = max(fabs(s0-e0));
  1062 + if (res < 1.0e-15)
  1063 + #if defined(DUMP_RESIDUALS)
  1064 + cout << "Res(S1Z)=" << res << " ";
  1065 + #else
  1066 + cout << ".";
  1067 + #endif
  1068 + else {
  1069 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1070 + cout << "Residual vector (all elements should be zero):" << endl;
  1071 + cout << s0 << endl;
  1072 + throw;
  1073 + }
  1074 + //
  1075 + e0(1) = 0.0;
  1076 + e0(2) = 1.0;
  1077 + a0(1) = 0.0;
  1078 + a0(2) = 1.0;
  1079 + s0 = cd_zero.cholesky_solver(a0);
  1080 + res = max(fabs(s0-e0));
  1081 + if (res < 1.0e-15)
  1082 + #if defined(DUMP_RESIDUALS)
  1083 + cout << "Res(S2Z)=" << res << " ";
  1084 + #else
  1085 + cout << ".";
  1086 + #endif
  1087 + else {
  1088 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1089 + cout << "Residual vector (all elements should be zero):" << endl;
  1090 + cout << s0 << endl;
  1091 + throw;
  1092 + }
  1093 + //
  1094 + e0(2) = 0.0;
  1095 + e0(4) = 1.0;
  1096 + a0(2) = 0.0;
  1097 + a0(4) = 1.0;
  1098 + s0 = cd_zero.cholesky_solver(a0);
  1099 + res = max(fabs(s0-e0));
  1100 + if (res < 1.0e-15)
  1101 + #if defined(DUMP_RESIDUALS)
  1102 + cout << "Res(S3Z)=" << res << " ";
  1103 + #else
  1104 + cout << ".";
  1105 + #endif
  1106 + else {
  1107 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1108 + cout << "Residual vector (all elements should be zero):" << endl;
  1109 + cout << s0 << endl;
  1110 + throw;
  1111 + }
  1112 + //
  1113 + e0(4) = 0.0;
  1114 + e0(5) = 1.0;
  1115 + a0(4) = 0.0;
  1116 + a0(5) = 1.0;
  1117 + s0 = cd_zero.cholesky_solver(a0);
  1118 + res = max(fabs(s0-e0));
  1119 + if (res < 1.0e-15)
  1120 + #if defined(DUMP_RESIDUALS)
  1121 + cout << "Res(S4Z)=" << res << " ";
  1122 + #else
  1123 + cout << ".";
  1124 + #endif
  1125 + else {
  1126 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1127 + cout << "Residual vector (all elements should be zero):" << endl;
  1128 + cout << s0 << endl;
  1129 + throw;
  1130 + }
  1131 + //
  1132 + // Setup matrix for Cholesky decomposition with zero row/col (unsymmetric case)
  1133 + GSparseMatrix m_chol_test_zero2(6,5);
  1134 + m_chol_test_zero2(0,0) = 1.0;
  1135 + m_chol_test_zero2(0,1) = 0.2;
  1136 + m_chol_test_zero2(0,2) = 0.2;
  1137 + m_chol_test_zero2(0,3) = 0.2;
  1138 + m_chol_test_zero2(0,4) = 0.2;
  1139 + m_chol_test_zero2(1,0) = 0.2;
  1140 + m_chol_test_zero2(2,0) = 0.2;
  1141 + m_chol_test_zero2(4,0) = 0.2;
  1142 + m_chol_test_zero2(5,0) = 0.2;
  1143 + m_chol_test_zero2(1,1) = 1.0;
  1144 + m_chol_test_zero2(2,2) = 1.0;
  1145 + m_chol_test_zero2(4,3) = 1.0;
  1146 + m_chol_test_zero2(5,4) = 1.0;
  1147 + //
  1148 + // Test compressed Cholesky decomposition (unsymmetric case)
  1149 + GSparseMatrix cd_zero2 = m_chol_test_zero2;
  1150 + cd_zero2.cholesky_decompose();
  1151 + //
  1152 + // Test compressed Cholesky solver (unsymmetric case)
  1153 + e0 = GVector(5);
  1154 + a0 = GVector(6);
  1155 + e0(0) = 1.0;
  1156 + a0(0) = 1.0;
  1157 + a0(1) = 0.2;
  1158 + a0(2) = 0.2;
  1159 + a0(4) = 0.2;
  1160 + a0(5) = 0.2;
  1161 + s0 = cd_zero2.cholesky_solver(a0);
  1162 + res = max(fabs(s0-e0));
  1163 + if (res < 1.0e-15)
  1164 + #if defined(DUMP_RESIDUALS)
  1165 + cout << "Res(S0ZU)=" << res << " ";
  1166 + #else
  1167 + cout << ".";
  1168 + #endif
  1169 + else {
  1170 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1171 + cout << "Residual vector (all elements should be zero):" << endl;
  1172 + cout << s0 << endl;
  1173 + throw;
  1174 + }
  1175 + //
  1176 + e0(0) = 0.0;
  1177 + e0(1) = 1.0;
  1178 + a0(0) = 0.2;
  1179 + a0(1) = 1.0;
  1180 + a0(2) = 0.0;
  1181 + a0(4) = 0.0;
  1182 + a0(5) = 0.0;
  1183 + s0 = cd_zero2.cholesky_solver(a0);
  1184 + res = max(fabs(s0-e0));
  1185 + if (res < 1.0e-15)
  1186 + #if defined(DUMP_RESIDUALS)
  1187 + cout << "Res(S1ZU)=" << res << " ";
  1188 + #else
  1189 + cout << ".";
  1190 + #endif
  1191 + else {
  1192 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1193 + cout << "Residual vector (all elements should be zero):" << endl;
  1194 + cout << s0 << endl;
  1195 + throw;
  1196 + }
  1197 + //
  1198 + e0(1) = 0.0;
  1199 + e0(2) = 1.0;
  1200 + a0(1) = 0.0;
  1201 + a0(2) = 1.0;
  1202 + s0 = cd_zero2.cholesky_solver(a0);
  1203 + res = max(fabs(s0-e0));
  1204 + if (res < 1.0e-15)
  1205 + #if defined(DUMP_RESIDUALS)
  1206 + cout << "Res(S2ZU)=" << res << " ";
  1207 + #else
  1208 + cout << ".";
  1209 + #endif
  1210 + else {
  1211 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1212 + cout << "Residual vector (all elements should be zero):" << endl;
  1213 + cout << s0 << endl;
  1214 + throw;
  1215 + }
  1216 + //
  1217 + e0(2) = 0.0;
  1218 + e0(3) = 1.0;
  1219 + a0(2) = 0.0;
  1220 + a0(4) = 1.0;
  1221 + s0 = cd_zero2.cholesky_solver(a0);
  1222 + res = max(fabs(s0-e0));
  1223 + if (res < 1.0e-15)
  1224 + #if defined(DUMP_RESIDUALS)
  1225 + cout << "Res(S3ZU)=" << res << " ";
  1226 + #else
  1227 + cout << ".";
  1228 + #endif
  1229 + else {
  1230 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1231 + cout << "Residual vector (all elements should be zero):" << endl;
  1232 + cout << s0 << endl;
  1233 + throw;
  1234 + }
  1235 + //
  1236 + e0(3) = 0.0;
  1237 + e0(4) = 1.0;
  1238 + a0(4) = 0.0;
  1239 + a0(5) = 1.0;
  1240 + s0 = cd_zero2.cholesky_solver(a0);
  1241 + res = max(fabs(s0-e0));
  1242 + if (res < 1.0e-15)
  1243 + #if defined(DUMP_RESIDUALS)
  1244 + cout << "Res(S4ZU)=" << res << " ";
  1245 + #else
  1246 + cout << ".";
  1247 + #endif
  1248 + else {
  1249 + cout << endl << "TEST ERROR: Corrupt cholesky_solver(GVector) function." << endl;
  1250 + cout << "Residual vector (all elements should be zero):" << endl;
  1251 + cout << s0 << endl;
  1252 + throw;
  1253 + }
  1254 + //
  1255 + // Test Cholesky inverter (inplace)
  1256 + GSparseMatrix unit(5,5);
  1257 + unit(0,0) = 1.0;
  1258 + unit(1,1) = 1.0;
  1259 + unit(2,2) = 1.0;
  1260 + unit(3,3) = 1.0;
  1261 + unit(4,4) = 1.0;
  1262 + GSparseMatrix m_chol_test_inv = m_chol_test;
  1263 + m_chol_test_inv.cholesky_invert();
  1264 + GSparseMatrix ci_product = m_chol_test * m_chol_test_inv;
  1265 + GSparseMatrix ci_residuals = ci_product - unit;
  1266 + res = (fabs(ci_residuals)).max();
  1267 + if (res < 1.0e-15)
  1268 + #if defined(DUMP_RESIDUALS)
  1269 + cout << "Res(CI)=" << res << " ";
  1270 + #else
  1271 + cout << ".";
  1272 + #endif
  1273 + else {
  1274 + cout << endl << "TEST ERROR: Corrupt GSparseMatrix.cholesky_invert() function." << endl;
  1275 + cout << "Residual matrix (all elements should be zero):" << endl;
  1276 + cout << ci_residuals << endl;
  1277 + throw;
  1278 + }
  1279 + //
  1280 + // Test Cholesky inverter
  1281 + m_chol_test_inv = cholesky_invert(m_chol_test);
  1282 + ci_product = m_chol_test * m_chol_test_inv;
  1283 + ci_residuals = ci_product - unit;
  1284 + res = (fabs(ci_residuals)).max();
  1285 + if (res < 1.0e-15)
  1286 + #if defined(DUMP_RESIDUALS)
  1287 + cout << "Res(CI2)=" << res << " ";
  1288 + #else
  1289 + cout << ".";
  1290 + #endif
  1291 + else {
  1292 + cout << endl << "TEST ERROR: Corrupt cholesky_invert(GSparseMatrix) function." << endl;
  1293 + cout << "Residual matrix (all elements should be zero):" << endl;
  1294 + cout << ci_residuals << endl;
  1295 + throw;
  1296 + }
  1297 + //
  1298 + // Test Cholesky inverter for compressed matrix
  1299 + unit = GSparseMatrix(6,6);
  1300 + unit(0,0) = 1.0;
  1301 + unit(1,1) = 1.0;
  1302 + unit(2,2) = 1.0;
  1303 + unit(4,4) = 1.0;
  1304 + unit(5,5) = 1.0;
  1305 + GSparseMatrix m_chol_test_zero_inv = m_chol_test_zero;
  1306 + m_chol_test_zero_inv.cholesky_invert();
  1307 + GSparseMatrix ciz_product = m_chol_test_zero * m_chol_test_zero_inv;
  1308 + GSparseMatrix ciz_residuals = ciz_product - unit;
  1309 + res = (fabs(ciz_residuals)).max();
  1310 + if (res < 1.0e-15)
  1311 + #if defined(DUMP_RESIDUALS)
  1312 + cout << "Res(CIZ)=" << res << " ";
  1313 + #else
  1314 + cout << ".";
  1315 + #endif
  1316 + else {
  1317 + cout << endl << "TEST ERROR: Corrupt compressed GSparseMatrix.cholesky_invert() function." << endl;
  1318 + cout << "Residual matrix (all elements should be zero):" << endl;
  1319 + cout << ciz_residuals << endl;
  1320 + throw;
  1321 + }
  1322 + }
  1323 + catch (exception &e) {
  1324 + cout << e.what() << endl;
  1325 + throw;
  1326 + }
  1327 + cout << "ok." << endl;
  1328 +}
  1329 +
  1330 +
  1331 +/***************************************************************************
  1332 + * Test: Heavy calculus *
  1333 + ***************************************************************************/
  1334 +void test_heavy()
  1335 +{
  1336 + // Allocate some variables
  1337 + clock_t t_start;
  1338 + double t_elapse;
  1339 + int number;
  1340 +
  1341 + // Perform test
  1342 + cout << "Test GSparseMatrix: Heavy calculus: ";
  1343 + try {
  1344 + //
  1345 + // Fill 10000 x 10000 matrix with 10000 values
  1346 + number = 10000;
  1347 + t_start = clock();
  1348 + GSparseMatrix large(number,number);
  1349 + for (int i = 0; i < number; ++i)
  1350 + large(i,i) = (i+1)*3.14;
  1351 + t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
  1352 + #if defined(DUMP_TIMING)
  1353 + cout << endl << " - Fill of 10000 values needed " << t_elapse <<
  1354 + " sec (reference ~ 1.9 sec)";
  1355 + #endif
  1356 + //
  1357 + // Modify 10000 x 10000 matrix with 10000 (exisiting) values
  1358 + t_start = clock();
  1359 + for (int i = 0; i < number; ++i)
  1360 + large(i,i) = (i+1)*1.0;
  1361 + t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
  1362 + #if defined(DUMP_TIMING)
  1363 + cout << endl << " - Modification of 10000 values needed " << t_elapse <<
  1364 + " sec (reference ~ 0 sec)";
  1365 + #endif
  1366 + //
  1367 + // Subsequent addition and subtractions
  1368 + number = 300;
  1369 + t_start = clock();
  1370 + GSparseMatrix sum(number,number);
  1371 + GSparseMatrix add(number,number);
  1372 + GSparseMatrix sub(number,number);
  1373 + for (int i = 0; i < number; ++i) {
  1374 + add(i,number-i-1) = (i*i+1)*0.01;
  1375 + sum += add;
  1376 + sub(i,i) = (i+1)*1.0;
  1377 + sum -= sub;
  1378 + }
  1379 + t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
  1380 + #if defined(DUMP_TIMING)
  1381 + cout << endl << " - Matrix adding and subtraction 300 times " << t_elapse <<
  1382 + " sec (reference ~ 1.5 sec)";
  1383 + #endif
  1384 + //
  1385 + // Subsequent multiplications
  1386 + t_start = clock();
  1387 + GSparseMatrix fac(number,number);
  1388 + for (int i = 0; i < 1; ++i) {
  1389 + for (int j = 0; j < number; ++j)
  1390 + fac(j,j) = (i+1)*1.0;
  1391 + sum *= fac;
  1392 + }
  1393 + t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
  1394 + #if defined(DUMP_TIMING)
  1395 + cout << endl << " - Matrix multiplication 1 times " << t_elapse <<
  1396 + " sec (reference ~ 3.5 sec)";
  1397 + #endif
  1398 + }
  1399 + catch (exception &e) {
  1400 + cout << e.what() << endl;
  1401 + throw;
  1402 + }
  1403 + #if defined(DUMP_TIMING)
  1404 + cout << endl;
  1405 + #endif
  1406 + cout << "ok." << endl;
  1407 +}
  1408 +
  1409 +
  1410 +/***************************************************************************
  1411 + * Main test function *
  1412 + ***************************************************************************/
  1413 +int main(void)
  1414 +{
  1415 + // Dump header
  1416 + cout << endl;
  1417 + cout << "*******************************" << endl;
  1418 + cout << "* GSparseMatrix class testing *" << endl;
  1419 + cout << "*******************************" << endl;
  1420 +
  1421 + // Set test matrix and vector
  1422 + GSparseMatrix m_test = set_matrix();
  1423 + GVector v_test = set_vector();
  1424 +
  1425 + // Execute the tests
  1426 + test_output(m_test);
  1427 + test_allocate();
  1428 + test_assign_values(m_test);
  1429 + test_copy_constructor(m_test);
  1430 + test_assign_matrix(m_test);
  1431 + test_transpose(m_test);
  1432 + test_matrix_vector(m_test, v_test);
  1433 + test_matrix_matrix(m_test);
  1434 + test_arithmetics(m_test);
  1435 + test_functions(m_test);
  1436 + test_comparison(m_test);
  1437 + test_conversion(m_test);
  1438 + test_cholesky();
  1439 + test_heavy();
  1440 +
  1441 + // Return
  1442 + return 0;
  1443 +}
... ...
test/test_GSparseMatrix.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * test_GSparseMatrix.hpp - test GSparseMatrix class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright : (C) 2006 by Jurgen Knodlseder *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software; you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation; either version 2 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + ***************************************************************************/
  13 +
  14 +#ifndef TEST_GSPARSEMATRIX_HPP
  15 +#define TEST_GSPARSEMATRIX_HPP
  16 +
  17 +/* __ Includes ___________________________________________________________ */
  18 +#include "../src/GSparseMatrix.hpp"
  19 +#include <iostream> // cout, cerr
  20 +#include <stdexcept> // std::exception
  21 +#include <math.h>
  22 +
  23 +#endif /* TEST_GSPARSEMATRIX_HPP */
... ...
test/test_GSymMatrix.cpp
... ... @@ -99,7 +99,7 @@ int check_matrix(const GSymMatrix&amp; m, const double scale, const double add)
99 99 for (unsigned row = 0; row < g_rows; ++row) {
100 100 for (unsigned col = 0; col < g_cols; ++col) {
101 101 double value = g_matrix[col+row*g_cols] * scale + add;
102   - if (m(row,col) != value) {
  102 + if (fabs(m(row,col)-value) > 1.0e-15) {
103 103 result = 0;
104 104 break;
105 105 }
... ... @@ -219,15 +219,15 @@ int check_matrix_vector(const GVector&amp; v)
219 219 ***************************************************************************/
220 220 int check_matrix_matrix(const GSymMatrix& m)
221 221 {
222   - if (m.rows() != g_rows || m.cols() != g_cols)
  222 + if (m.rows() != g_rows || m.cols() != g_rows)
223 223 return 0;
224 224 int result = 1;
225 225 try {
226   - for (unsigned row = 0; row < g_rows; ++row) {
227   - for (unsigned col = 0; col < g_cols; ++col) {
  226 + for (unsigned row = 0; row < m.rows(); ++row) {
  227 + for (unsigned col = 0; col < m.cols(); ++col) {
228 228 double value = 0.0;
229 229 for (unsigned i = 0; i < g_cols; ++i)
230   - value += g_matrix[i+row*g_cols] * g_matrix[row+i*g_cols];
  230 + value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols];
231 231 if (m(row,col) != value) {
232 232 result = 0;
233 233 break;
... ... @@ -375,7 +375,7 @@ int main(void)
375 375 cout << "GSymMatrix - Test 4: Define matrix using copy constructor: ";
376 376 //
377 377 GSymMatrix test4 = m_test;
378   - if (!check_matrix(test4, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  378 + if (!check_matrix(test4, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
379 379 cout << endl << "TEST ERROR: Corrupt copy constructor." << endl;
380 380 cout << test4 << endl;
381 381 throw;
... ... @@ -393,8 +393,8 @@ int main(void)
393 393 //
394 394 // GSymMatrix = GSymMatrix
395 395 result = m_test;
396   - if (!check_matrix(result, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
397   - cout << endl << "TEST ERROR: Corrupt copy constructor." << endl;
  396 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  397 + cout << endl << "TEST ERROR: Corrupt assignment." << endl;
398 398 cout << result << endl;
399 399 throw;
400 400 }
... ... @@ -413,7 +413,7 @@ int main(void)
413 413 cout << "GSymMatrix - Test 6: Matrix*Vector multiplication: ";
414 414 //
415 415 GVector v_test6 = m_test*v_test;
416   - if (!check_matrix_vector(v_test6) && !check_matrix(m_test, 1.0, 0.0)) {
  416 + if (!check_matrix_vector(v_test6) || !check_matrix(m_test, 1.0, 0.0)) {
417 417 cout << endl << "TEST ERROR: Corrupt Matrix*Vector multiplication." << endl;
418 418 cout << v_test6 << endl;
419 419 throw;
... ... @@ -426,7 +426,7 @@ int main(void)
426 426 try {
427 427 GVector v_test6 = bigger*v_test;
428 428 }
429   - catch (GMatrix::vec_mat_mismatch &e) {
  429 + catch (GMatrix::matrix_vector_mismatch &e) {
430 430 }
431 431 catch (exception &e) {
432 432 cout << e.what() << endl;
... ... @@ -439,7 +439,7 @@ int main(void)
439 439 cout << "GSymMatrix - Test 7: Matrix*Matrix multiplication: ";
440 440 //
441 441 GSymMatrix m_test7 = m_test*m_test;
442   - if (!check_matrix_matrix(m_test7) && !check_matrix(m_test, 1.0, 0.0)) {
  442 + if (!check_matrix_matrix(m_test7) || !check_matrix(m_test, 1.0, 0.0)) {
443 443 cout << endl << "TEST ERROR: Corrupt Matrix*Matrix multiplication." << endl;
444 444 cout << m_test7 << endl;
445 445 throw;
... ... @@ -452,7 +452,7 @@ int main(void)
452 452 try {
453 453 GSymMatrix m_test7 = m_test*bigger;
454 454 }
455   - catch (GMatrix::dim_mult_mismatch &e) {
  455 + catch (GMatrix::matrix_mismatch &e) {
456 456 }
457 457 catch (exception &e) {
458 458 cout << e.what() << endl;
... ... @@ -461,7 +461,7 @@ int main(void)
461 461 try {
462 462 GSymMatrix m_test7 = bigger*m_test;
463 463 }
464   - catch (GMatrix::dim_mult_mismatch &e) {
  464 + catch (GMatrix::matrix_mismatch &e) {
465 465 }
466 466 catch (exception &e) {
467 467 cout << e.what() << endl;
... ... @@ -475,61 +475,34 @@ int main(void)
475 475 //
476 476 // -GSymMatrix
477 477 result = -m_test;
478   - if (!check_matrix(result, -1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  478 + if (!check_matrix(result, -1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
479 479 cout << endl << "TEST ERROR: Corrupt -GSymMatrix operator." << endl;
480 480 cout << result << endl;
481 481 throw;
482 482 }
483 483 //
484   - // GSymMatrix = 3.0
485   - result = m_test;
486   - result = 3.0;
487   - if (!check_matrix(result, 0.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
488   - cout << endl << "TEST ERROR: Corrupt GSymMatrix = double operator." << endl;
489   - cout << result << endl;
490   - throw;
491   - }
492   - //
493 484 // GSymMatrix += GSymMatrix
494 485 result = m_test;
495 486 result += m_test;
496   - if (!check_matrix(result, 2.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  487 + if (!check_matrix(result, 2.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
497 488 cout << endl << "TEST ERROR: Corrupt GSymMatrix += GSymMatrix operator." << endl;
498 489 cout << result << endl;
499 490 throw;
500 491 }
501 492 //
502   - // GSymMatrix += 3.0
503   - result = m_test;
504   - result += 3.0;
505   - if (!check_matrix(result, 1.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
506   - cout << endl << "TEST ERROR: Corrupt GSymMatrix += double operator." << endl;
507   - cout << result << endl;
508   - throw;
509   - }
510   - //
511 493 // GSymMatrix -= GSymMatrix
512 494 result = m_test;
513 495 result -= m_test;
514   - if (!check_matrix(result, 0.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  496 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
515 497 cout << endl << "TEST ERROR: Corrupt GSymMatrix -= GSymMatrix operator." << endl;
516 498 cout << result << endl;
517 499 throw;
518 500 }
519 501 //
520   - // GSymMatrix -= 3.0
521   - result = m_test;
522   - result -= 3.0;
523   - if (!check_matrix(result, 1.0, -3.0) && !check_matrix(m_test, 1.0, 0.0)) {
524   - cout << endl << "TEST ERROR: Corrupt GSymMatrix -= double operator." << endl;
525   - cout << result << endl;
526   - throw;
527   - }
528   - //
529 502 // GSymMatrix *= 3.0
530 503 result = m_test;
531 504 result *= 3.0;
532   - if (!check_matrix(result, 3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  505 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
533 506 cout << endl << "TEST ERROR: Corrupt GSymMatrix *= double operator." << endl;
534 507 cout << result << endl;
535 508 throw;
... ... @@ -538,7 +511,7 @@ int main(void)
538 511 // GSymMatrix /= 3.0
539 512 result = m_test;
540 513 result /= 3.0;
541   - if (!check_matrix(result, 1.0/3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  514 + if (!check_matrix(result, 1.0/3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
542 515 cout << endl << "TEST ERROR: Corrupt GSymMatrix /= double operator." << endl;
543 516 cout << result << endl;
544 517 throw;
... ... @@ -546,7 +519,7 @@ int main(void)
546 519 //
547 520 // GSymMatrix + GSymMatrix
548 521 result = m_test + m_test;
549   - if (!check_matrix(result, 2.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  522 + if (!check_matrix(result, 2.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
550 523 cout << endl << "TEST ERROR: Corrupt GSymMatrix + GSymMatrix operator." << endl;
551 524 cout << result << endl;
552 525 throw;
... ... @@ -554,7 +527,7 @@ int main(void)
554 527 //
555 528 // GSymMatrix - GSymMatrix
556 529 result = m_test - m_test;
557   - if (!check_matrix(result, 0.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  530 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
558 531 cout << endl << "TEST ERROR: Corrupt GSymMatrix - GSymMatrix operator." << endl;
559 532 cout << result << endl;
560 533 throw;
... ... @@ -562,47 +535,15 @@ int main(void)
562 535 //
563 536 // GSymMatrix - GSymMatrix
564 537 result = m_test - m_test;
565   - if (!check_matrix(result, 0.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  538 + if (!check_matrix(result, 0.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
566 539 cout << endl << "TEST ERROR: Corrupt GSymMatrix - GSymMatrix operator." << endl;
567 540 cout << result << endl;
568 541 throw;
569 542 }
570 543 //
571   - // GSymMatrix + 3.0
572   - result = m_test + 3.0;
573   - if (!check_matrix(result, 1.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
574   - cout << endl << "TEST ERROR: Corrupt GSymMatrix + double operator." << endl;
575   - cout << result << endl;
576   - throw;
577   - }
578   - //
579   - // 3.0 + GSymMatrix
580   - result = 3.0 + m_test;
581   - if (!check_matrix(result, 1.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
582   - cout << endl << "TEST ERROR: Corrupt double + GSymMatrix operator." << endl;
583   - cout << result << endl;
584   - throw;
585   - }
586   - //
587   - // GSymMatrix - 3.0
588   - result = m_test - 3.0;
589   - if (!check_matrix(result, 1.0, -3.0) && !check_matrix(m_test, 1.0, 0.0)) {
590   - cout << endl << "TEST ERROR: Corrupt GSymMatrix - double operator." << endl;
591   - cout << result << endl;
592   - throw;
593   - }
594   - //
595   - // 3.0 - GSymMatrix
596   - result = 3.0 - m_test;
597   - if (!check_matrix(result, -1.0, 3.0) && !check_matrix(m_test, 1.0, 0.0)) {
598   - cout << endl << "TEST ERROR: Corrupt double - GSymMatrix operator." << endl;
599   - cout << result << endl;
600   - throw;
601   - }
602   - //
603 544 // GSymMatrix * 3.0
604 545 result = m_test * 3.0;
605   - if (!check_matrix(result, 3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  546 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
606 547 cout << endl << "TEST ERROR: Corrupt GSymMatrix * double operator." << endl;
607 548 cout << result << endl;
608 549 throw;
... ... @@ -610,7 +551,7 @@ int main(void)
610 551 //
611 552 // 3.0 * GSymMatrix
612 553 result = 3.0 * m_test;
613   - if (!check_matrix(result, 3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  554 + if (!check_matrix(result, 3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
614 555 cout << endl << "TEST ERROR: Corrupt double * GSymMatrix operator." << endl;
615 556 cout << result << endl;
616 557 throw;
... ... @@ -618,7 +559,7 @@ int main(void)
618 559 //
619 560 // GSymMatrix / 3.0
620 561 result = m_test / 3.0;
621   - if (!check_matrix(result, 1.0/3.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  562 + if (!check_matrix(result, 1.0/3.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
622 563 cout << endl << "TEST ERROR: Corrupt GSymMatrix / double operator." << endl;
623 564 cout << result << endl;
624 565 throw;
... ... @@ -632,7 +573,7 @@ int main(void)
632 573 result = m_test;
633 574 result += bigger;
634 575 }
635   - catch (GMatrix::dim_add_mismatch) {
  576 + catch (GMatrix::matrix_mismatch) {
636 577 }
637 578 catch (exception &e) {
638 579 cout << e.what() << endl;
... ... @@ -717,7 +658,7 @@ int main(void)
717 658 //
718 659 // transpose(GSymMatrix)
719 660 result = transpose(m_test);
720   - if (!check_matrix(result, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  661 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
721 662 cout << endl << "TEST ERROR: Corrupt transpose(GSymMatrix) function." << endl;
722 663 cout << result << endl;
723 664 throw;
... ... @@ -726,32 +667,32 @@ int main(void)
726 667 // GSymMatrix.transpose()
727 668 result = m_test;
728 669 result.transpose();
729   - if (!check_matrix(result, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
  670 + if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
730 671 cout << endl << "TEST ERROR: Corrupt GSymMatrix.transpose() function." << endl;
731 672 cout << result << endl;
732 673 throw;
733 674 }
734 675 //
735   - // full(GSymMatrix)
736   - GMatrix m_test11 = full(m_test);
737   - if (!check_matrix(m_test11, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
738   - cout << endl << "TEST ERROR: Corrupt full(GSymMatrix) operator." << endl;
  676 + // convert_to_full()
  677 + GMatrix m_test11 = m_test.convert_to_full();
  678 + if (!check_matrix(m_test11, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  679 + cout << endl << "TEST ERROR: Corrupt convert_to_full() operator." << endl;
739 680 cout << m_test11 << endl;
740 681 throw;
741 682 }
742 683 //
743   - // lower_triangle(GSymMatrix)
744   - m_test11 = lower_triangle(m_test);
745   - if (!check_matrix_lt(m_test11, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
746   - cout << endl << "TEST ERROR: Corrupt lower_triangle(GSymMatrix) function." << endl;
  684 + // extract_lower_triangle()
  685 + m_test11 = m_test.extract_lower_triangle();
  686 + if (!check_matrix_lt(m_test11, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  687 + cout << endl << "TEST ERROR: Corrupt extract_lower_triangle() function." << endl;
747 688 cout << m_test11 << endl;
748 689 throw;
749 690 }
750 691 //
751   - // upper_triangle(GSymMatrix)
752   - m_test11 = upper_triangle(m_test);
753   - if (!check_matrix_ut(m_test11, 1.0, 0.0) && !check_matrix(m_test, 1.0, 0.0)) {
754   - cout << endl << "TEST ERROR: Corrupt upper_triangle(GSymMatrix) function." << endl;
  692 + // extract_upper_triangle()
  693 + m_test11 = m_test.extract_upper_triangle();
  694 + if (!check_matrix_ut(m_test11, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
  695 + cout << endl << "TEST ERROR: Corrupt extract_upper_triangle() function." << endl;
755 696 cout << m_test11 << endl;
756 697 throw;
757 698 }
... ... @@ -768,10 +709,10 @@ int main(void)
768 709 //
769 710 // Test Cholesky decomposition
770 711 GSymMatrix cd = cholesky_decompose(m_test);
771   - GMatrix cd_lower = lower_triangle(cd);
  712 + GMatrix cd_lower = cd.extract_lower_triangle();
772 713 GMatrix cd_upper = transpose(cd_lower);
773 714 GMatrix cd_product = cd_lower * cd_upper;
774   - GMatrix cd_residuals = full(m_test) - cd_product;
  715 + GMatrix cd_residuals = m_test.convert_to_full() - cd_product;
775 716 //
776 717 double res = (fabs(cd_residuals)).max();
777 718 if (res < 1.0e-15)
... ... @@ -786,10 +727,10 @@ int main(void)
786 727 // Test compressed Cholesky decomposition
787 728 GSymMatrix m_test_zero = set_matrix_zero();
788 729 GSymMatrix cd_zero = cholesky_decompose(m_test_zero);
789   - GMatrix cd_zero_lower = lower_triangle(cd_zero);
  730 + GMatrix cd_zero_lower = cd_zero.extract_lower_triangle();
790 731 GMatrix cd_zero_upper = transpose(cd_zero_lower);
791 732 GMatrix cd_zero_product = cd_zero_lower * cd_zero_upper;
792   - GMatrix cd_zero_residuals = full(m_test_zero) - cd_zero_product;
  733 + GMatrix cd_zero_residuals = m_test_zero.convert_to_full() - cd_zero_product;
793 734 //
794 735 res = (fabs(cd_zero_residuals)).max();
795 736 if (res < 1.0e-15)
... ... @@ -804,7 +745,7 @@ int main(void)
804 745 // Test Cholesky inplace decomposition
805 746 GSymMatrix m_test12 = m_test;
806 747 m_test12.cholesky_decompose();
807   - GMatrix cd_lower2 = lower_triangle(m_test12);
  748 + GMatrix cd_lower2 = m_test12.extract_lower_triangle();
808 749 if (cd_lower2 != cd_lower) {
809 750 cout << endl << "TEST ERROR: Corrupt GSymMatrix.cholesky_decompose() function." << endl;
810 751 cout << cd_lower2 << endl;
... ... @@ -967,4 +908,4 @@ int main(void)
967 908 }
968 909 cout << "ok." << endl;
969 910  
970   -}
971 911 \ No newline at end of file
  912 +}
... ...