Commit dbd56b4e30bf24d4c5a4e99b52dc1a6e3754fff8

Authored by knodlseder
1 parent 4f37bc98

Implement fill-stack

doc/gammalib_um.tex
1 -%---------------------------------------------------------------------------- % GammaLib User Manual % % Version .........: 0.0.0 % Last modification: 26 October 2006 %---------------------------------------------------------------------------- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Definitions for manual package %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\task}{\mbox{GammaLib}} \newcommand{\this}{\mbox{\tt \task}} \newcommand{\version}{\mbox{0.0.0}} \newcommand{\calendar}{\mbox{26 October 2006}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Document definition %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \documentclass{article}[12pt,a4] \usepackage{epsfig} \usepackage{manual} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Begin of document body %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} \frontpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Introduction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Introduction} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Motivation} Again another library? Indeed, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Philisophy} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Implementation} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % GammaLib objects %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{\this\ objects} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Vectors and matrices} %---------------------------------------------------------------------------- \subsubsection{General} Most of the calculations that are needed in data analysis can be expressed as vector and matrix operations. For this reason, \this\ provides a vector and matrix package that is implemeted as the {\tt GVector} and the {\tt GMatrix} classes. %---------------------------------------------------------------------------- \subsubsection{Matrix types} The matrix base class is {\tt GMatrix} which stores all elements of the matrix (including zeros) in a full array. The full array has the dimensions {\tt rows} $\times$ {\tt cols}, matrix elements are stored in column major format. {\tt GSymMatrix} symmetric matrix. {\tt GSparseMatrix} sparse matrix. {\tt GSymSparseMatrix} symmetric sparse matrix. %---------------------------------------------------------------------------- \subsubsection{Matrix arithmetics} {\tt GMatrix} and its derived objects can be added, subtracted, scaled and negated, very much as other data types. The following code fragment illustrates the usage: \begin{verbatim} // Matrix allocation GMatrix a(2,3); GMatrix b(3,2); GMatrix c(2,2); GMatrix d(2,2); // Element assignment a(0,0) = a(1,1) = a(1,2) = 1.0; b(0,0) = b(1,1) = b(2,1) = 1.0; d(0,0) = d(1,1) = 1.0; // Arithmetics c = a * b; // Matrix multiplication d = c; // Assignment c = c * 2.0; // Multiplication of all matrix elements by 2.0 a = a + 1.0; // Addition of 1.0 to all matrix elements d = d + d - c; // Matrix addition and subtraction c = -d; // Negation of all matrix elements a *= 5.0; // Multiplication of all matrix elements by 5.0 \end{verbatim} Matrix allocation requires {\bf always} the specification of the number of rows and columns of the matrix. This means that there is no such thing as a matrix object with zero rows or columns. All matrix elements are initialised to 0.0 by the matrix allocation. Matrix elements are accessed by the {\tt matrix(row,col)} function, where {\tt row} and {\tt col} start from 0 for the first row or column and run up to the number of rows or columns minus 1. Matrix arithmetics comprise binary operators {\tt C = A operator B} and unary operators {\tt C operator A}. {\tt A} and {\tt B} may be either {\tt GMatrix} (or derived) objects or {\tt double} values. In case of {\tt double} values the operation is performed on each matrix element, i.e. \begin{verbatim} c = c * 2.0; d = d / 3.0; \end{verbatim} multiply each matrix element of {\tt c} by 2.0 and divide each matrix element of {\tt d} by 3.0. These operations can be writted also more compactly using unary operators: \begin{verbatim} c *= 2.0; d /= 3.0; \end{verbatim} While the addition, multiplication %---------------------------------------------------------------------------- \subsubsection{Matrix functions} %---------------------------------------------------------------------------- \subsubsection{Matrix compression} The {\tt GSymMatrix} Cholesky decomposition, solver and inversion routines may also be applied to matrices that contain rows or columns that are filled by zeros. In this case the functions provide the option to (logically) compress the matrices by skipping the zero rows and columns during the calculation. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Code reference %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \clearpage \section{Code reference} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{{\tt GVector}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{{\tt GMatrix}} \end{document}  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +%---------------------------------------------------------------------------- % GammaLib User Manual % % Version .........: 0.0.0 % Last modification: 26 October 2006 %---------------------------------------------------------------------------- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Definitions for manual package %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\task}{\mbox{GammaLib}} \newcommand{\this}{\mbox{\tt \task}} \newcommand{\version}{\mbox{0.0.0}} \newcommand{\calendar}{\mbox{26 October 2006}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Document definition %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \documentclass{article}[12pt,a4] \usepackage{epsfig} \usepackage{manual} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Begin of document body %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} \frontpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Introduction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Introduction} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Motivation} Again another library? Indeed, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Philisophy} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Implementation} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % GammaLib objects %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{\this\ objects} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Vectors and matrices} %---------------------------------------------------------------------------- \subsubsection{General} Most of the calculations that are needed in data analysis can be expressed as vector and matrix operations. For this reason, \this\ provides a vector and matrix package that is implemeted as the {\tt GVector} and the {\tt GMatrix} classes. %---------------------------------------------------------------------------- \subsubsection{Matrix storage classes} The matrix base class is {\tt GMatrix} which stores all elements of the matrix (including zeros) in a full array. The full array has the dimensions {\tt rows} $\times$ {\tt cols}, matrix elements are stored in column major format. Derived matrix classes exist for more compact storage modes, reducing the memory requirements for handling and storing the information. {\tt GSymMatrix} symmetric matrix. {\tt GSparseMatrix} sparse matrix. The following description of the matrix class properties apply to all matrix storage classes, if not stated otherwise. %---------------------------------------------------------------------------- \subsubsection{Matrix arithmetics} {\tt GMatrix} and its derived objects can be added, subtracted, scaled and negated, very much as other data types. The following code fragment illustrates the usage: \begin{verbatim} // Matrix allocation GMatrix A(2,3); GMatrix B(3,2); GMatrix C(2,2); GMatrix D(2,2); // Element assignment A(0,0) = A(1,1) = A(1,2) = 1.0; B(0,0) = B(1,1) = B(2,1) = 1.0; D(0,0) = D(1,1) = 1.0; // Arithmetics C = A * B; // Matrix multiplication D = C; // Assignment C = C * 2.0; // Multiplication of all matrix elements by 2.0 D = D + D - C; // Matrix addition and subtraction C = -D; // Negation of all matrix elements A *= 5.0; // Multiplication of all matrix elements by 5.0 \end{verbatim} Matrix allocation requires {\bf always} the specification of the number of rows and columns of the matrix. This means that there is no such thing as a matrix object with zero rows or columns. All matrix elements are initialised to 0.0 by the matrix allocation. Matrix elements are accessed by the {\tt matrix(row,col)} function, where {\tt row} and {\tt col} start from 0 for the first row or column and run up to the number of rows or columns minus 1. Matrix arithmetics comprise binary operators {\tt C = A operator B} and unary operators {\tt C operator A}. {\tt A} and {\tt B} may be either {\tt GMatrix} (or derived) objects or {\tt double} values. The following fundamental operations exist for all matrices: \begin{verbatim} C = A + B; // Matrix addition C = A - B; // Matrix subtraction C = A * B; // Matrix multiplication C = A * v; // Matrix vector multiplication C = A * s; // Matrix scalar multiplication C = s * A; // Matrix scalar multiplication (left sided) C = A * s; // Matrix scalar multiplication (right sided) C = A / s; // Matrix scalar division C = -A; // Negation A += B; // Matrix inplace addition A -= B; // Matrix inplace subtraction A *= B; // Matrix inplace multiplications A *= s; // Matrix inplace scalar multiplication A /= s; // Matrix inplace scalar division \end{verbatim} Note that all {\bf inplace operations}, such as the {\tt +=}, {\tt -=}, {\tt *=}, and {\tt /=} operators do not require the allocation of additional memory to hold the matrix result elements, hence inplace operations may be preferable if memory requirements are an issue. Matrices may be compared to each other using \begin{verbatim} int identical = (A == B); // True if all matrix elements are identical // and if the matrices have identical dimensions int different = (A != B); // True if at least one matrix element differs // or if the matrices have different dimensions \end{verbatim} %---------------------------------------------------------------------------- \subsubsection{Matrix functions} Matrix attributes: \begin{verbatim} unsigned rows = M.rows(); // Returns number of rows in matrix unsigned cols = M.cols(); // Returns number of columns in matrix \end{verbatim} Matrix information: \begin{verbatim} double sum = M.sum(); // Sum of all elements in matrix double min = M.min(); // Returns minimum element of matrix double max = M.max(); // Returns maximum element of matrix \end{verbatim} %---------------------------------------------------------------------------- \subsubsection{Matrix factorisations} A general tool of numeric matrix calculs is factorisation. Solve linear equation {\tt Ax = b}. Inverse a matrix (by solving successively {\tt Ax = e}, where {\tt e} are the unit vectors for all dimensions). % \paragraph{Matrix factorisations} For symmetric and positive definite matrices the most efficient factorisation is the Cholesky decomposition. The following code fragment illustrates the usage: \begin{verbatim} GMatrix A(n_rows, n_cols}; GVector x(n_rows}; GVector b(n_rows}; ... A.cholesky_decompose(); // Perform Cholesky factorisation x = A.cholesky_solver(b); // Solve Ax=b for x \end{verbatim} Note that once the function {\tt A.cholesky\_decompose()} has been applied, the original matrix content has been replaced by its Cholesky decomposition. Since the Cholesky decomposition can be performed inplace (i.e. without the allocation of additional memory to hold the result), the matrix replacement is most memory economic. In case that the original matrix should be kept, one may either copy it before into another {\tt GMatrix} object or use the function \begin{verbatim} GMatrix L = cholesky_decompose(A); x = L.cholesky_solver(b); \end{verbatim} A symmetric and positif definite matrix can be inverted using the Cholesky decomposition using \begin{verbatim} A.cholesky_invert(); // Inverse matrix using Cholesky factorisation \end{verbatim} Alternatively, the function \begin{verbatim} GMatrix A_inv = cholesky_invert(A); \end{verbatim} may be used. The Cholesky decomposition, solver and inversion routines may also be applied to matrices that contain rows or columns that are filled by zeros. In this case the functions provide the option to (logically) compress the matrices by skipping the zero rows and columns during the calculation. For compressed matrix Cholesky factorisation, only the non-zero rows and columns have to be symmetric and positive definite. In particular, the full matrix may even be non-symmetric. %---------------------------------------------------------------------------- \subsubsection{Sparse matrix} %%%%% \paragraph{General} \this\ provides a sparse matrix storage type that can save considerable amounts of memory for calculations. Assigment possible. The only exception that does not work is \begin{verbatim} GSparseMatrix A; A(0,0) = A(1,1) = A(2,2) = 1.0; \end{verbatim} In this case the value {\tt 1.0} is only assigned to the last element, i.e. {\tt A(2,2)}. Inverting a sparse matrix produces in general a full matrix, so the inversion function should be used with caution. Note that a full matrix that is stored in sparse format takes roughly twice the memory than a normal {\tt GMatrix} object. If nevertheless the inverse of a sparse matrix should be examined, it is recommended to perform the analysis column-wise: \begin{verbatim} GSparseMatrix A(rows,cols); // Allocate sparse matrix GVector unit(rows); // Allocate vector ... A.cholesky_decompose(); // Factorise matrix // Column-wise solving the matrix equation for (int col = 0; col < m_cols; ++col) { unit(col) = 1.0; // Set unit vector GVector x = cholesky_solver(unit); // Get column x of inverse ... unit(col) = 0.0; // Clear unit vector for next round } \end{verbatim} %%%%% \paragraph{Filling of a sparse matrix} The filling of a sparse matrix is a tricky issue since the storage of the elements depends on their distribution in the matrix. If one would know beforehand this distribution, sparse matrix filling would be easy and fast. In general, however, the distribution is not known a priori, and matrix filling may become a quite time consuming task. If a matrix has to be filled element by element, the access through the operator \begin{verbatim} m(row,col) = value; \end{verbatim} may be mandatory. In principle, if a new element is inserted into a matrix a new memory cell has to be allocated for this element, and other elements may be moved. Memory allocation is quite time consuming, and to reduce the overhead, {\tt GSparseMatrix} can be configured to allocate memory in bunches. By default, each time more matrix memory is needed, {\tt GSparseMatrix} allocates 512 cells at once (or 6144 Bytes since each element requires a {\tt double} and a {\tt int} storage location). If this amount of memory is not adequat one may change this value by using \begin{verbatim} m.set_mem_block(size); \end{verbatim} where {\tt size} is the number of matrix elements that should be allocated at once (corresponding to a total memory of $12 \times {\tt size}$ Bytes). Alternatively, a matrix may be filled column-wise using the functions \begin{verbatim} m.insert_col(vector,col); // Insert a vector in column m.add_col(vector,col); // Add content of a vector to column \end{verbatim} While {\tt insert\_col} sets the values of column {\tt col} (deleting thus any previously existing entries), {\tt add\_col} adds the content of {\tt vector} to all elements of column {\tt col}. Using these functions is considerably more rapid than filling individual values. Still, if the matrix is big (i.e. severeal thousands of rows and columns), filling individual columns may still be slow. To speed-up dynamical matrix filling, an internal fill-stack has been implemented in {\tt GSparseMatrix}. Instead of inserting values column-by-column, the columns are stored in a stack and filled into the matrix once the stack is full. This reduces the number of dynamic memory allocations to let the matrix grow as it is built. By default, the internal stack is disabled. The stack can be enabled and used as follows: \begin{verbatim} m.stack_init(size, entries); // Initialise stack ... m.add_col(vector,col); // Add columns ... m.stack_destroy(); // Flush and destory stack \end{verbatim} The method {\tt stack\_init} initialises a stack with a number of {\tt size} elements and a maximum of {\tt entries} columns. The larger the values {\tt size} and {\tt entries} are chosen, the more efficient the stack works. The total amount of memory of the stack can be estimated as $12 \times {\tt size} + 8 \times {\tt entries}$ Bytes. If a rough estimate of the total number of non-zero elements is available it is recommended to set {\tt size} to this value. As a rule of thumb, {\tt size} should be at least of the dimension of either the number of rows or the number of columns of the matrix (take the maximum of both). {\tt entries} is best set to the number of columns of the matrix. If memory limits are an issue smaller values may be set, but if the values are too small, the speed increase may become negligible (or even, stack-filling may become slower than normal filling). Stack-filling only works with the method {\tt add\_col}. Note also that filling sub-sequently the same row leads to stack flushing, so if the same column is filled in a loop, i.e. \begin{verbatim} for (int col = 0; col < 100; ++col) { column = 0.0; // Reset column column(i) = i; // Set column m.add_col(column,col); // Add column } \end{verbatim} it is better to fill the column before adding, i.e. \begin{verbatim} column = 0.0; // Reset column for (int col = 0; col < 100; ++col) column(i) = i; // Set column \end{verbatim} The method {\tt add\_col} calls the method {\tt stack\_push\_column} for stack filling. {\tt add\_col} is more general than {\tt stack\_push\_column} in that it decides which of stack- or direct filling is more adequate. In particular, {\tt stack\_push\_column} may refuse pushing a column onto the stack if there is not enough space. In that case, {\tt stack\_push\_column} returns a non-zero value that corresponds to the number of non-zero elements in the vector that should be added. However, it is recommended to not use {\tt stack\_push\_column} and call instead {\tt add\_col}. The method {\tt stack\_destroy} is used to flush and destroy the stack. After this call the stack memory is liberated. If the stack should be flushed without destroying it, the method {\tt stack\_flush} may be used: \begin{verbatim} m.stack_init(size, entries); // Initialise stack ... m.add_col(vector,col); // Add columns ... m.stack_flush(); // Simply flush stack \end{verbatim} Once flushed, the stack can be filled anew. Note that stack flushing is not automatic! This means, if one trys to use a matrix for calculs without flushing, the calculs may be work. {\bf If a stack is used for filling, always flush the stack before using the matrix.} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Code reference %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \clearpage \section{Code reference} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{{\tt GVector}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{{\tt GMatrix}} \end{document}
3 \ No newline at end of file 3 \ No newline at end of file
src/GMatrix.cpp
@@ -20,6 +20,96 @@ using namespace std; @@ -20,6 +20,96 @@ using namespace std;
20 20
21 /*========================================================================== 21 /*==========================================================================
22 = = 22 = =
  23 + = Private functions =
  24 + = =
  25 + ==========================================================================*/
  26 +void GMatrix::init_members(void)
  27 +{
  28 + // Initialise GMatrix members
  29 + m_rows = 0; // Number of rows
  30 + m_cols = 0; // Number of columns
  31 + m_elements = 0; // Logically used number of elements
  32 + m_alloc = 0; // Allocated # of elements (>= m_elements)
  33 + m_num_rowsel = 0; // Number of selected rows (for comp. decomp.)
  34 + m_num_colsel = 0; // Number of selected columns (for comp. decomp.)
  35 + m_data = NULL; // Matrix data
  36 + m_colstart = NULL; // Column start indices (m_cols+1)
  37 + m_rowsel = NULL; // Row selection (for compressed decomposition)
  38 + m_colsel = NULL; // Column selection (for compressed decomposition)
  39 +
  40 + // Return
  41 + return;
  42 +}
  43 +/***************************************************************************/
  44 +void GMatrix::copy_members(const GMatrix& m)
  45 +{
  46 + // Copy matrix attributes
  47 + m_rows = m.m_rows;
  48 + m_cols = m.m_cols;
  49 + m_elements = m.m_elements;
  50 + m_alloc = m.m_alloc;
  51 + m_num_rowsel = m.m_num_rowsel;
  52 + m_num_colsel = m.m_num_colsel;
  53 +
  54 + // Allocate memory for column start array and copy content
  55 + m_colstart = new int[m_cols+1];
  56 + if (m_colstart == NULL)
  57 + throw mem_alloc("GMatrix::copy_members(const Matrix&)", m_cols+1);
  58 + for (int i = 0; i <= m_cols; ++i)
  59 + m_colstart[i] = m.m_colstart[i];
  60 +
  61 + // Allocate memory for elements and copy them (only if there are elements)
  62 + if (m.m_data != NULL && m_alloc > 0) {
  63 + m_data = new double[m_alloc];
  64 + if (m_data == NULL)
  65 + throw mem_alloc("GMatrix::copy_members(const Matrix&)", m_alloc);
  66 + for (int i = 0; i < m_elements; ++i)
  67 + m_data[i] = m.m_data[i];
  68 + }
  69 +
  70 + // If there is a row selection then copy it
  71 + if (m.m_rowsel != NULL && m_num_rowsel > 0) {
  72 + m_rowsel = new int[m_num_rowsel];
  73 + if (m_rowsel == NULL)
  74 + throw mem_alloc("GMatrix::copy_members(const Matrix&)", m_num_rowsel);
  75 + for (int i = 0; i < m_num_rowsel; ++i)
  76 + m_rowsel[i] = m.m_rowsel[i];
  77 + }
  78 +
  79 + // If there is a column selection then copy it
  80 + if (m.m_colsel != NULL && m_num_colsel > 0) {
  81 + m_colsel = new int[m_num_colsel];
  82 + if (m_colsel == NULL)
  83 + throw mem_alloc("GMatrix::copy_members(const Matrix&)", m_num_colsel);
  84 + for (int i = 0; i < m_num_colsel; ++i)
  85 + m_colsel[i] = m.m_colsel[i];
  86 + }
  87 +
  88 + // Return
  89 + return;
  90 +}
  91 +/***************************************************************************/
  92 +void GMatrix::free_members(void)
  93 +{
  94 + // De-allocate only if memory has indeed been allocated
  95 + if (m_colsel != NULL) delete [] m_colsel;
  96 + if (m_rowsel != NULL) delete [] m_rowsel;
  97 + if (m_data != NULL) delete [] m_data;
  98 + if (m_colstart != NULL) delete [] m_colstart;
  99 +
  100 + // Properly mark members as free
  101 + m_colstart = NULL;
  102 + m_data = NULL;
  103 + m_rowsel = NULL;
  104 + m_colsel = NULL;
  105 +
  106 + // Return
  107 + return;
  108 +}
  109 +
  110 +
  111 +/*==========================================================================
  112 + = =
23 = GMatrix constructors/destructors = 113 = GMatrix constructors/destructors =
24 = = 114 = =
25 ==========================================================================*/ 115 ==========================================================================*/
@@ -30,17 +120,8 @@ using namespace std; @@ -30,17 +120,8 @@ using namespace std;
30 GMatrix::GMatrix(void) 120 GMatrix::GMatrix(void)
31 { 121 {
32 // Initialise private members for clean destruction 122 // Initialise private members for clean destruction
33 - m_rows = 0;  
34 - m_cols = 0;  
35 - m_elements = 0;  
36 - m_alloc = 0;  
37 - m_num_rowsel = 0;  
38 - m_num_colsel = 0;  
39 - m_data = NULL;  
40 - m_colstart = NULL;  
41 - m_rowsel = NULL;  
42 - m_colsel = NULL;  
43 - 123 + init_members();
  124 +
44 // Return 125 // Return
45 return; 126 return;
46 } 127 }
@@ -52,16 +133,7 @@ GMatrix::GMatrix(void) @@ -52,16 +133,7 @@ GMatrix::GMatrix(void)
52 GMatrix::GMatrix(int rows, int cols) 133 GMatrix::GMatrix(int rows, int cols)
53 { 134 {
54 // Initialise private members for clean destruction 135 // Initialise private members for clean destruction
55 - m_rows = 0;  
56 - m_cols = 0;  
57 - m_elements = 0;  
58 - m_alloc = 0;  
59 - m_num_rowsel = 0;  
60 - m_num_colsel = 0;  
61 - m_data = NULL;  
62 - m_colstart = NULL;  
63 - m_rowsel = NULL;  
64 - m_colsel = NULL; 136 + init_members();
65 137
66 // Determine number of elements to store in matrix 138 // Determine number of elements to store in matrix
67 int elements = rows*cols; 139 int elements = rows*cols;
@@ -106,59 +178,11 @@ GMatrix::GMatrix(int rows, int cols) @@ -106,59 +178,11 @@ GMatrix::GMatrix(int rows, int cols)
106 GMatrix::GMatrix(const GMatrix& m) 178 GMatrix::GMatrix(const GMatrix& m)
107 { 179 {
108 // Initialise private members for clean destruction 180 // Initialise private members for clean destruction
109 - m_rows = 0;  
110 - m_cols = 0;  
111 - m_elements = 0;  
112 - m_alloc = 0;  
113 - m_num_rowsel = 0;  
114 - m_num_colsel = 0;  
115 - m_data = NULL;  
116 - m_colstart = NULL;  
117 - m_rowsel = NULL;  
118 - m_colsel = NULL;  
119 -  
120 - // Allocate memory for column start array and copy content  
121 - m_colstart = new int[m.m_cols+1];  
122 - if (m_colstart == NULL)  
123 - throw mem_alloc("GMatrix copy constructor", m.m_cols+1);  
124 - for (int i = 0; i <= m.m_cols; ++i)  
125 - m_colstart[i] = m.m_colstart[i];  
126 -  
127 - // Allocate memory for elements and copy them (only if there are elements)  
128 - if (m.m_alloc > 0) {  
129 - m_data = new double[m.m_alloc];  
130 - if (m_data == NULL)  
131 - throw mem_alloc("GMatrix copy constructor", m.m_alloc);  
132 - for (int i = 0; i < m.m_elements; ++i)  
133 - m_data[i] = m.m_data[i];  
134 - }  
135 -  
136 - // If there is a row selection then copy it  
137 - if (m.m_rowsel != NULL && m.m_num_rowsel > 0) {  
138 - m_rowsel = new int[m.m_num_rowsel];  
139 - if (m_rowsel == NULL)  
140 - throw mem_alloc("GMatrix copy constructor", m.m_num_rowsel);  
141 - for (int i = 0; i < m.m_num_rowsel; ++i)  
142 - m_rowsel[i] = m.m_rowsel[i];  
143 - m_num_rowsel = m.m_num_rowsel;  
144 - } 181 + init_members();
145 182
146 - // If there is a column selection then copy it  
147 - if (m.m_colsel != NULL && m.m_num_colsel > 0) {  
148 - m_colsel = new int[m.m_num_colsel];  
149 - if (m_colsel == NULL)  
150 - throw mem_alloc("GMatrix copy constructor", m.m_num_colsel);  
151 - for (int i = 0; i < m.m_num_colsel; ++i)  
152 - m_colsel[i] = m.m_colsel[i];  
153 - m_num_colsel = m.m_num_colsel;  
154 - } 183 + // Copy members
  184 + copy_members(m);
155 185
156 - // Copy matrix attributes  
157 - m_rows = m.m_rows;  
158 - m_cols = m.m_cols;  
159 - m_elements = m.m_elements;  
160 - m_alloc = m.m_alloc;  
161 -  
162 // Return 186 // Return
163 return; 187 return;
164 } 188 }
@@ -169,11 +193,8 @@ GMatrix::GMatrix(const GMatrix&amp; m) @@ -169,11 +193,8 @@ GMatrix::GMatrix(const GMatrix&amp; m)
169 ***************************************************************************/ 193 ***************************************************************************/
170 GMatrix::~GMatrix() 194 GMatrix::~GMatrix()
171 { 195 {
172 - // De-allocate only if memory has indeed been allocated  
173 - if (m_rowsel != NULL) delete [] m_rowsel;  
174 - if (m_colsel != NULL) delete [] m_colsel;  
175 - if (m_colstart != NULL) delete [] m_colstart;  
176 - if (m_data != NULL) delete [] m_data; 196 + // Free members
  197 + free_members();
177 198
178 // Return 199 // Return
179 return; 200 return;
@@ -193,66 +214,15 @@ GMatrix&amp; GMatrix::operator= (const GMatrix&amp; m) @@ -193,66 +214,15 @@ GMatrix&amp; GMatrix::operator= (const GMatrix&amp; m)
193 { 214 {
194 // Execute only if object is not identical 215 // Execute only if object is not identical
195 if (this != &m) { 216 if (this != &m) {
196 -  
197 - // De-allocate memory if it has indeed been allocated  
198 - if (m_colstart != NULL) delete [] m_colstart;  
199 - if (m_rowsel != NULL) delete [] m_rowsel;  
200 - if (m_colsel != NULL) delete [] m_colsel;  
201 - if (m_data != NULL) delete [] m_data;  
202 217
  218 + // Free members
  219 + free_members();
  220 +
203 // Initialise private members for clean destruction 221 // Initialise private members for clean destruction
204 - m_rows = 0;  
205 - m_cols = 0;  
206 - m_elements = 0;  
207 - m_alloc = 0;  
208 - m_num_rowsel = 0;  
209 - m_num_colsel = 0;  
210 - m_data = NULL;  
211 - m_colstart = NULL;  
212 - m_rowsel = NULL;  
213 - m_colsel = NULL;  
214 -  
215 - // Allocate memory for column start array and copy content  
216 - m_colstart = new int[m.m_cols+1];  
217 - if (m_colstart == NULL)  
218 - throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_cols+1);  
219 - for (int i = 0; i <= m.m_cols; ++i)  
220 - m_colstart[i] = m.m_colstart[i];  
221 -  
222 - // Allocate memory for elements and copy them (only if there are elements)  
223 - if (m.m_alloc > 0) {  
224 - m_data = new double[m.m_alloc];  
225 - if (m_data == NULL)  
226 - throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_alloc);  
227 - for (int i = 0; i < m.m_elements; ++i)  
228 - m_data[i] = m.m_data[i];  
229 - }  
230 -  
231 - // If there is a row selection then copy it  
232 - if (m.m_rowsel != NULL && m.m_num_rowsel > 0) {  
233 - m_rowsel = new int[m.m_num_rowsel];  
234 - if (m_rowsel == NULL)  
235 - throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_num_rowsel);  
236 - for (int i = 0; i < m.m_num_rowsel; ++i)  
237 - m_rowsel[i] = m.m_rowsel[i];  
238 - m_num_rowsel = m.m_num_rowsel;  
239 - }  
240 -  
241 - // If there is a column selection then copy it  
242 - if (m.m_colsel != NULL && m.m_num_colsel > 0) {  
243 - m_colsel = new int[m.m_num_colsel];  
244 - if (m_colsel == NULL)  
245 - throw mem_alloc("GMatrix::operator= (const GMatrix&)", m.m_num_colsel);  
246 - for (int i = 0; i < m.m_num_colsel; ++i)  
247 - m_colsel[i] = m.m_colsel[i];  
248 - m_num_colsel = m.m_num_colsel;  
249 - } 222 + init_members();
250 223
251 - // Copy matrix attributes  
252 - m_rows = m.m_rows;  
253 - m_cols = m.m_cols;  
254 - m_elements = m.m_elements;  
255 - m_alloc = m.m_alloc; 224 + // Copy members
  225 + copy_members(m);
256 226
257 } // endif: object was not identical 227 } // endif: object was not identical
258 228
src/GMatrix.hpp
@@ -137,6 +137,9 @@ protected: @@ -137,6 +137,9 @@ protected:
137 GMatrix(); 137 GMatrix();
138 138
139 // Private member functions 139 // Private member functions
  140 + void init_members(void);
  141 + void copy_members(const GMatrix& m);
  142 + void free_members(void);
140 void select_non_zero(void); 143 void select_non_zero(void);
141 144
142 // Private data area 145 // Private data area
src/GSparseMatrix.cpp
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 * m_rowinx : holds the row indices for all elements (Ai) * 17 * m_rowinx : holds the row indices for all elements (Ai) *
18 * Column 'col' covers therefore [m_colstart[j], ..., m_colstart[j+1]-1] * 18 * Column 'col' covers therefore [m_colstart[j], ..., m_colstart[j+1]-1] *
19 * Note that 'm_colstart' has m_cols+1 elements. * 19 * Note that 'm_colstart' has m_cols+1 elements. *
20 -/*************************************************************************** 20 + ***************************************************************************/
21 21
22 /* __ Includes ___________________________________________________________ */ 22 /* __ Includes ___________________________________________________________ */
23 #include "GSparseMatrix.hpp" 23 #include "GSparseMatrix.hpp"
@@ -27,31 +27,26 @@ @@ -27,31 +27,26 @@
27 /* __ Namespaces _________________________________________________________ */ 27 /* __ Namespaces _________________________________________________________ */
28 using namespace std; 28 using namespace std;
29 29
30 -/* __ Definitions ________________________________________________________ */ 30 +/* __ Debug definitions __________________________________________________ */
31 //#define G_DEBUG_SPARSE_PENDING // Analyse pending values 31 //#define G_DEBUG_SPARSE_PENDING // Analyse pending values
32 //#define G_DEBUG_SPARSE_INSERTION // Analyse value insertion 32 //#define G_DEBUG_SPARSE_INSERTION // Analyse value insertion
33 //#define G_DEBUG_SPARSE_COMPRESSION // Analyse zero row/column compression 33 //#define G_DEBUG_SPARSE_COMPRESSION // Analyse zero row/column compression
34 //#define G_DEBUG_SPARSE_MALLOC // Analyse memory management 34 //#define G_DEBUG_SPARSE_MALLOC // Analyse memory management
  35 +//#define G_DEBUG_SPARSE_STACK_PUSH // Analyse stack column pushing
  36 +//#define G_DEBUG_SPARSE_STACK_FLUSH // Analyse stack column flushing
  37 +
  38 +/* __ Definitions ________________________________________________________ */
35 #define G_USE_MEMCPY 39 #define G_USE_MEMCPY
36 40
  41 +
37 /*========================================================================== 42 /*==========================================================================
38 = = 43 = =
39 - = GSparseMatrix constructors/destructors = 44 + = Private functions =
40 = = 45 = =
41 ==========================================================================*/ 46 ==========================================================================*/
42 -  
43 -/***************************************************************************  
44 - * GSparseMatrix constructor *  
45 - ***************************************************************************/  
46 -GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix() 47 +void GSparseMatrix::init_members(void)
47 { 48 {
48 - // Initialise private members for clean destruction  
49 - m_rows = 0;  
50 - m_cols = 0;  
51 - m_elements = 0; // Logically used # of elements  
52 - m_alloc = 0; // Allocated # of elements (>= m_elements)  
53 - m_data = NULL;  
54 - m_colstart = NULL; 49 + // Initialise sparse matrix members
55 m_rowinx = NULL; 50 m_rowinx = NULL;
56 m_mem_block = G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK; 51 m_mem_block = G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK;
57 m_zero = 0.0; 52 m_zero = 0.0;
@@ -60,7 +55,106 @@ GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix() @@ -60,7 +55,106 @@ GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix()
60 m_fill_col = 0; 55 m_fill_col = 0;
61 m_symbolic = NULL; 56 m_symbolic = NULL;
62 m_numeric = NULL; 57 m_numeric = NULL;
63 - 58 +
  59 + // Initialise stack members
  60 + m_stack_max_entries = 0;
  61 + m_stack_size = 0;
  62 + m_stack_entries = 0;
  63 + m_stack_colinx = NULL;
  64 + m_stack_start = NULL;
  65 + m_stack_data = NULL;
  66 + m_stack_rowinx = NULL;
  67 +
  68 + // Return
  69 + return;
  70 +}
  71 +/***************************************************************************/
  72 +void GSparseMatrix::copy_members(const GSparseMatrix& m)
  73 +{
  74 + // Copy data members
  75 + m_mem_block = m.m_mem_block;
  76 + m_zero = m.m_zero;
  77 + m_fill_val = m.m_fill_val;
  78 + m_fill_row = m.m_fill_row;
  79 + m_fill_col = m.m_fill_col;
  80 +
  81 + // Copy row indices
  82 + if (m.m_rowinx != NULL && m.m_alloc > 0) {
  83 + m_rowinx = new int[m.m_alloc];
  84 + if (m_rowinx == NULL)
  85 + throw mem_alloc("GSparseMatrix::copy_members(const GSparseMatrix&)", m.m_alloc);
  86 + for (int i = 0; i < m.m_elements; ++i)
  87 + m_rowinx[i] = m.m_rowinx[i];
  88 + }
  89 +
  90 + // Copy symbolic decomposition
  91 + if (m.m_symbolic != NULL) {
  92 + GSparseSymbolic* symbolic = new GSparseSymbolic();
  93 + if (symbolic == NULL)
  94 + throw mem_alloc("GSparseMatrix::copy_members(const GSparseMatrix&)", 1);
  95 + *symbolic = *((GSparseSymbolic*)m.m_symbolic);
  96 + m_symbolic = (void*)symbolic;
  97 + }
  98 +
  99 + // Copy numeric decomposition
  100 + if (m.m_numeric != NULL) {
  101 + GSparseNumeric* numeric = new GSparseNumeric();
  102 + if (numeric == NULL)
  103 + throw mem_alloc("GSparseMatrix::copy_members(const GSparseMatrix&)", 1);
  104 + *numeric = *((GSparseNumeric*)m.m_numeric);
  105 + m_numeric = (void*)numeric;
  106 + }
  107 +
  108 + // Return
  109 + return;
  110 +}
  111 +/***************************************************************************/
  112 +void GSparseMatrix::free_members(void)
  113 +{
  114 + // De-allocate only if memory has indeed been allocated
  115 + if (m_numeric != NULL) delete (GSparseNumeric*)m_numeric;
  116 + if (m_symbolic != NULL) delete (GSparseSymbolic*)m_symbolic;
  117 + if (m_rowinx != NULL) delete [] m_rowinx;
  118 +
  119 + // Properly mark members as free
  120 + m_rowinx = NULL;
  121 + m_symbolic = NULL;
  122 + m_numeric = NULL;
  123 +
  124 + // Free stack members
  125 + if (m_stack_colinx != NULL) delete [] m_stack_colinx;
  126 + if (m_stack_start != NULL) delete [] m_stack_start;
  127 + if (m_stack_data != NULL) delete [] m_stack_data;
  128 + if (m_stack_rowinx != NULL) delete [] m_stack_rowinx;
  129 +
  130 + // Properly mark members as free
  131 + m_stack_colinx = NULL;
  132 + m_stack_start = NULL;
  133 + m_stack_data = NULL;
  134 + m_stack_rowinx = NULL;
  135 +
  136 + // Return
  137 + return;
  138 +}
  139 +
  140 +
  141 +/*==========================================================================
  142 + = =
  143 + = GSparseMatrix constructors/destructors =
  144 + = =
  145 + ==========================================================================*/
  146 +
  147 +/***************************************************************************
  148 + * GSparseMatrix constructor *
  149 + * ----------------------------------------------------------------------- *
  150 + * First invoques GMatrix void constructor which initialises all GMatrix *
  151 + * members but which does not allocate memory or assign any value. *
  152 + ***************************************************************************/
  153 +GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix()
  154 +{
  155 + // Initialise private members for clean destruction
  156 + init_members();
  157 +
64 // Allocate column start array. This is the only array that we can 158 // Allocate column start array. This is the only array that we can
65 // allocate at this time. The other arrays can only be allocated during 159 // allocate at this time. The other arrays can only be allocated during
66 // filling of the matrix 160 // filling of the matrix
@@ -96,44 +190,11 @@ GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix() @@ -96,44 +190,11 @@ GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix()
96 GSparseMatrix::GSparseMatrix(const GSparseMatrix& m) : GMatrix(m) 190 GSparseMatrix::GSparseMatrix(const GSparseMatrix& m) : GMatrix(m)
97 { 191 {
98 // Initialise private members for clean destruction 192 // Initialise private members for clean destruction
99 - m_rowinx = NULL;  
100 - m_symbolic = NULL;  
101 - m_numeric = NULL;  
102 -  
103 - // Copy data members  
104 - m_mem_block = m.m_mem_block;  
105 - m_zero = m.m_zero;  
106 - m_fill_val = m.m_fill_val;  
107 - m_fill_row = m.m_fill_row;  
108 - m_fill_col = m.m_fill_col;  
109 -  
110 - // Allocate memory for row indices and copy them (only if there are elements)  
111 - if (m_alloc > 0) {  
112 - m_rowinx = new int[m_alloc];  
113 - if (m_rowinx == NULL)  
114 - throw mem_alloc("GSparseMatrix copy constructor", m_alloc);  
115 - for (int i = 0; i < m_elements; ++i)  
116 - m_rowinx[i] = m.m_rowinx[i];  
117 - } 193 + init_members();
118 194
119 - // If there is a symbolic decomposition then copy it  
120 - if (m.m_symbolic != NULL) {  
121 - GSparseSymbolic* symbolic = new GSparseSymbolic();  
122 - if (symbolic == NULL)  
123 - throw mem_alloc("GSparseMatrix copy constructor", 1);  
124 - *symbolic = *((GSparseSymbolic*)m.m_symbolic);  
125 - m_symbolic = (void*)symbolic;  
126 - } 195 + // Copy members
  196 + copy_members(m);
127 197
128 - // If there is a numeric decomposition then copy it  
129 - if (m.m_numeric != NULL) {  
130 - GSparseNumeric* numeric = new GSparseNumeric();  
131 - if (numeric == NULL)  
132 - throw mem_alloc("GSparseMatrix copy constructor", 1);  
133 - *numeric = *((GSparseNumeric*)m.m_numeric);  
134 - m_numeric = (void*)numeric;  
135 - }  
136 -  
137 // Return 198 // Return
138 return; 199 return;
139 } 200 }
@@ -147,10 +208,8 @@ GSparseMatrix::GSparseMatrix(const GSparseMatrix&amp; m) : GMatrix(m) @@ -147,10 +208,8 @@ GSparseMatrix::GSparseMatrix(const GSparseMatrix&amp; m) : GMatrix(m)
147 ***************************************************************************/ 208 ***************************************************************************/
148 GSparseMatrix::~GSparseMatrix() 209 GSparseMatrix::~GSparseMatrix()
149 { 210 {
150 - // De-allocate only if memory has indeed been allocated by derived class  
151 - if (m_rowinx != NULL) delete [] m_rowinx;  
152 - if (m_symbolic != NULL) delete (GSparseSymbolic*)m_symbolic;  
153 - if (m_numeric != NULL) delete (GSparseNumeric*)m_numeric; 211 + // Free members
  212 + free_members();
154 213
155 // Return 214 // Return
156 return; 215 return;
@@ -174,50 +233,14 @@ GSparseMatrix&amp; GSparseMatrix::operator= (const GSparseMatrix&amp; m) @@ -174,50 +233,14 @@ GSparseMatrix&amp; GSparseMatrix::operator= (const GSparseMatrix&amp; m)
174 // Invoque base class assignment operator 233 // Invoque base class assignment operator
175 this->GMatrix::operator=(m); 234 this->GMatrix::operator=(m);
176 235
177 - // De-allocate memory if it has indeed been allocated  
178 - if (m_rowinx != NULL) delete [] m_rowinx;  
179 - if (m_symbolic != NULL) delete (GSparseSymbolic*)m_symbolic;  
180 - if (m_numeric != NULL) delete (GSparseNumeric*)m_numeric; 236 + // Free members
  237 + free_members();
181 238
182 // Initialise private members for clean destruction 239 // Initialise private members for clean destruction
183 - m_rowinx = NULL;  
184 - m_symbolic = NULL;  
185 - m_numeric = NULL;  
186 -  
187 - // Copy data members  
188 - m_mem_block = m.m_mem_block;  
189 - m_zero = m.m_zero;  
190 - m_fill_val = m.m_fill_val;  
191 - m_fill_row = m.m_fill_row;  
192 - m_fill_col = m.m_fill_col;  
193 -  
194 - // Allocate memory for row indices and copy them (only if there are elements)  
195 - if (m_alloc > 0) {  
196 - m_rowinx = new int[m_alloc];  
197 - if (m_rowinx == NULL)  
198 - throw mem_alloc("GSparseMatrix::operator= (const GSparseMatrix&)",  
199 - m_alloc);  
200 - for (int i = 0; i < m_elements; ++i)  
201 - m_rowinx[i] = m.m_rowinx[i];  
202 - } 240 + init_members();
203 241
204 - // If there is a symbolic decomposition then copy it  
205 - if (m.m_symbolic != NULL) {  
206 - GSparseSymbolic* symbolic = new GSparseSymbolic();  
207 - if (symbolic == NULL)  
208 - throw mem_alloc("GSparseMatrix copy constructor", 1);  
209 - *symbolic = *((GSparseSymbolic*)m.m_symbolic);  
210 - m_symbolic = (void*)symbolic;  
211 - }  
212 -  
213 - // If there is a numeric decomposition then copy it  
214 - if (m.m_numeric != NULL) {  
215 - GSparseNumeric* numeric = new GSparseNumeric();  
216 - if (numeric == NULL)  
217 - throw mem_alloc("GSparseMatrix copy constructor", 1);  
218 - *numeric = *((GSparseNumeric*)m.m_numeric);  
219 - m_numeric = (void*)numeric;  
220 - } 242 + // Copy members
  243 + copy_members(m);
221 244
222 } // endif: object was not identical 245 } // endif: object was not identical
223 246
@@ -742,22 +765,40 @@ void GSparseMatrix::insert_col(const GVector&amp; v, int col) @@ -742,22 +765,40 @@ void GSparseMatrix::insert_col(const GVector&amp; v, int col)
742 ***************************************************************************/ 765 ***************************************************************************/
743 void GSparseMatrix::add_col(const GVector& v, int col) 766 void GSparseMatrix::add_col(const GVector& v, int col)
744 { 767 {
745 - // Raise an exception if the column index is invalid  
746 - #if defined(G_RANGE_CHECK)  
747 - if (col >= m_cols)  
748 - throw out_of_range("GSparseMatrix::add_col(const GVector&, int)",  
749 - 0, col, m_rows, m_cols);  
750 - #endif 768 + // Initialise number of non-zero elements to 0
  769 + int non_zero = 0;
  770 +
  771 + // If we have a stack then try to push elements on stack first ...
  772 + if (m_stack_data != NULL) {
  773 + non_zero = stack_push_column(v, col);
  774 + if (non_zero == 0)
  775 + return;
  776 + }
  777 +
  778 + // ... otherwise check first the arguments and determine the number of
  779 + // non-zero elements in vector
  780 + else {
751 781
752 - // Raise an exception if the matrix and vector dimensions are incompatible  
753 - if (m_rows != v.m_num)  
754 - throw matrix_vector_mismatch("GSparseMatrix::add_col(const GVector&, int)",  
755 - v.m_num, m_rows, m_cols); 782 + // Raise an exception if the column index is invalid
  783 + #if defined(G_RANGE_CHECK)
  784 + if (col >= m_cols)
  785 + throw out_of_range("GSparseMatrix::add_col(const GVector&, int)",
  786 + 0, col, m_rows, m_cols);
  787 + #endif
  788 +
  789 + // Raise an exception if the matrix and vector dimensions are incompatible
  790 + if (m_rows != v.m_num)
  791 + throw matrix_vector_mismatch("GSparseMatrix::add_col(const GVector&, int)",
  792 + v.m_num, m_rows, m_cols);
  793 +
  794 + // Determine number of non-zero elements in vector
  795 + non_zero = v.non_zeros();
  796 + }
756 797
757 // Extract vector for column, add elements, and re-insert vector (only if 798 // Extract vector for column, add elements, and re-insert vector (only if
758 // vector to insert has non-zeros) 799 // vector to insert has non-zeros)
759 - if (v.non_zeros() > 0) {  
760 - 800 + if (non_zero > 0) {
  801 +
761 // Copy input vector 802 // Copy input vector
762 GVector column = v; 803 GVector column = v;
763 804
@@ -771,9 +812,10 @@ void GSparseMatrix::add_col(const GVector&amp; v, int col) @@ -771,9 +812,10 @@ void GSparseMatrix::add_col(const GVector&amp; v, int col)
771 812
772 // Insert vector into matrix 813 // Insert vector into matrix
773 insert_col(column, col); 814 insert_col(column, col);
  815 +
774 816
775 } 817 }
776 - 818 +
777 // Return 819 // Return
778 return; 820 return;
779 } 821 }
@@ -1119,6 +1161,405 @@ void GSparseMatrix::cholesky_invert(int compress) @@ -1119,6 +1161,405 @@ void GSparseMatrix::cholesky_invert(int compress)
1119 } 1161 }
1120 1162
1121 1163
  1164 +/***************************************************************************
  1165 + * Initialises matrix filling stack *
  1166 + * ----------------------------------------------------------------------- *
  1167 + * The matrix filling stack is used to allow for a fast column-wise *
  1168 + * filling of a sparse matrix. Columns are successively appended to a *
  1169 + * stack which is regularily flushed when it is full. This reduces memory *
  1170 + * copies and movements and increases filling speed. *
  1171 + ***************************************************************************/
  1172 +void GSparseMatrix::stack_init(int size, int entries)
  1173 +{
  1174 + // If there is an existing stack the delete it now
  1175 + if (m_stack_colinx != NULL) delete [] m_stack_colinx;
  1176 + if (m_stack_start != NULL) delete [] m_stack_start;
  1177 + if (m_stack_data != NULL) delete [] m_stack_data;
  1178 + if (m_stack_rowinx != NULL) delete [] m_stack_rowinx;
  1179 +
  1180 + // Initialise stack members
  1181 + m_stack_max_entries = (entries > 0) ? entries : G_SPARSE_MATRIX_DEFAULT_STACK_ENTRIES;
  1182 + m_stack_size = (size > 0) ? size : G_SPARSE_MATRIX_DEFAULT_STACK_SIZE;
  1183 + m_stack_entries = 0;
  1184 + m_stack_colinx = NULL;
  1185 + m_stack_start = NULL;
  1186 + m_stack_data = NULL;
  1187 + m_stack_rowinx = NULL;
  1188 +
  1189 + // Allocate stack memory. Raise an exception if allocation fails
  1190 + m_stack_colinx = new int[m_stack_max_entries];
  1191 + m_stack_start = new int[m_stack_max_entries+1];
  1192 + m_stack_data = new double[m_stack_size];
  1193 + m_stack_rowinx = new int[m_stack_size];
  1194 + if (m_stack_colinx == NULL)
  1195 + throw mem_alloc("GSparseMatrix::stack_init", m_stack_max_entries);
  1196 + if (m_stack_start == NULL)
  1197 + throw mem_alloc("GSparseMatrix::stack_init", m_stack_max_entries+1);
  1198 + if (m_stack_data == NULL || m_stack_rowinx == NULL)
  1199 + throw mem_alloc("GSparseMatrix::stack_init", m_stack_size);
  1200 +
  1201 + // Initialise next free stack location to the first stack element
  1202 + m_stack_start[0] = 0;
  1203 +
  1204 + // Return
  1205 + return;
  1206 +}
  1207 +
  1208 +
  1209 +/***************************************************************************
  1210 + * Push a column on the matrix stack *
  1211 + * ----------------------------------------------------------------------- *
  1212 + * The return value indicates if the vector was successfully pushed onto *
  1213 + * the stack (=0) or if the elements need to be added directly (in this *
  1214 + * case the return value equals to the number of non-zero elements in the *
  1215 + * vector. *
  1216 + ***************************************************************************/
  1217 +int GSparseMatrix::stack_push_column(const GVector& v, int col)
  1218 +{
  1219 + // Raise an exception if the column index is invalid
  1220 + #if defined(G_RANGE_CHECK)
  1221 + if (col >= m_cols)
  1222 + throw out_of_range("GSparseMatrix::stack_push_column(const GVector&, int)",
  1223 + 0, col, m_rows, m_cols);
  1224 + #endif
  1225 +
  1226 + // Raise an exception if the matrix and vector dimensions are incompatible
  1227 + if (m_rows != v.m_num)
  1228 + throw matrix_vector_mismatch("GSparseMatrix::stack_push_column(const GVector&, int)",
  1229 + v.m_num, m_rows, m_cols);
  1230 +
  1231 + // Determines how many elements should be stored in stack
  1232 + int elements = 0;
  1233 + for (int i = 0; i < v.m_num; ++i) {
  1234 + if (v.m_data[i] != 0.0)
  1235 + elements++;
  1236 + }
  1237 +
  1238 + // If the vector is empty there is nothing to do
  1239 + if (elements == 0)
  1240 + return 0;
  1241 +
  1242 + // If there is no stack or the stack can not hold the requested number of
  1243 + // elements then report number of vector elements to the caller
  1244 + if (m_stack_data == NULL || elements > m_stack_size)
  1245 + return elements;
  1246 +
  1247 + // If the specified column is already in the stack then flush stack (we don't
  1248 + // allow the same column twice)
  1249 + for (int i = 0; i < m_stack_entries; ++i) {
  1250 + if (col == m_stack_colinx[i]) {
  1251 + stack_flush();
  1252 + break;
  1253 + }
  1254 + }
  1255 +
  1256 + // If the stack is full then flush it before pushing the vector onto it
  1257 + if ((m_stack_entries >= m_stack_max_entries) ||
  1258 + (elements >= (m_stack_size - m_stack_start[m_stack_entries])))
  1259 + stack_flush();
  1260 +
  1261 + // Push the vector on the stack
  1262 + int inx = m_stack_start[m_stack_entries];
  1263 + for (int i = 0; i < v.m_num; ++i) {
  1264 + if (v.m_data[i] != 0.0) {
  1265 + m_stack_data[inx] = v.m_data[i];
  1266 + m_stack_rowinx[inx] = i;
  1267 + inx++;
  1268 + }
  1269 + }
  1270 +
  1271 + // Store entry information and initialise start of next entry
  1272 + m_stack_colinx[m_stack_entries] = col; // Store column index for entry
  1273 + m_stack_entries++; // Increase the # of entries
  1274 + m_stack_start[m_stack_entries] = inx; // Set start pointer for next entry
  1275 +
  1276 + // Debug: show stack information
  1277 + #if defined(G_DEBUG_SPARSE_STACK_PUSH)
  1278 + cout << "GSparseMatrix::stack_push_column(v, col=" << col << ")" << endl;
  1279 + cout << " Number of entries: " << m_stack_entries << endl;
  1280 + cout << " Entry columns ...:";
  1281 + for (int i = 0; i < m_stack_entries; ++i)
  1282 + cout << " " << m_stack_colinx[i];
  1283 + cout << endl;
  1284 + cout << " Entry starts ....:";
  1285 + for (int i = 0; i < m_stack_entries; ++i)
  1286 + cout << " " << m_stack_start[i];
  1287 + cout << " (next at " << m_stack_start[m_stack_entries] << ")" << endl;
  1288 + cout << " Stack data ......:";
  1289 + for (int i = 0; i < m_stack_start[m_stack_entries]; ++i)
  1290 + cout << " " << m_stack_data[i];
  1291 + cout << endl;
  1292 + cout << " Stack rows ......:";
  1293 + for (int i = 0; i < m_stack_start[m_stack_entries]; ++i)
  1294 + cout << " " << m_stack_rowinx[i];
  1295 + cout << endl;
  1296 + #endif
  1297 +
  1298 + // Return success
  1299 + return 0;
  1300 +}
  1301 +
  1302 +
  1303 +/***************************************************************************
  1304 + * Flush matrix stack *
  1305 + * ----------------------------------------------------------------------- *
  1306 + * Adds the stack to the actual matrix. First, the total number of matrix *
  1307 + * elements is determined. The new memory is allocated to hold all *
  1308 + * elements. Finally, all elements are filled into a working array that is *
  1309 + * then compressed into the matrix. *
  1310 + * ----------------------------------------------------------------------- *
  1311 + * NOTE: The present algorithm assumes that each column occurs only once *
  1312 + * in the stack! *
  1313 + ***************************************************************************/
  1314 +void GSparseMatrix::stack_flush(void)
  1315 +{
  1316 + // Do nothing if there is no stack
  1317 + if (m_stack_data == NULL)
  1318 + return;
  1319 +
  1320 + // Fill pending value
  1321 + fill_pending();
  1322 +
  1323 + // Debug header
  1324 + #if defined(G_DEBUG_SPARSE_STACK_FLUSH)
  1325 + cout << "GSparseMatrix::stack_flush" << endl;
  1326 + cout << " Stack entries ...: " << m_stack_entries << endl;
  1327 + cout << " Stack elements ..: " << m_stack_start[m_stack_entries] << endl;
  1328 + cout << " Matrix elements .: " << m_elements << endl;
  1329 + #endif
  1330 +
  1331 + // Allocate workspace for column flags
  1332 + int* wrk_int = new int[m_cols];
  1333 + if (wrk_int == NULL)
  1334 + throw mem_alloc("GSparseMatrix::stack_flush", m_cols);
  1335 +
  1336 + // First gather all columns from existing matrix and flag all existing
  1337 + // columns by 1 and all non-existing by 0
  1338 + for (int col = 0; col < m_cols; ++col) {
  1339 + if (m_colstart[col] < m_colstart[col+1])
  1340 + wrk_int[col] = 1;
  1341 + else
  1342 + wrk_int[col] = 0;
  1343 + }
  1344 +
  1345 + // Loop over all stack entries and set column flags. They have the
  1346 + // following definition:
  1347 + // -(entry+2): Column exists and is also found in stack=entry
  1348 + // +(entry+2): Column exists in stack=entry only
  1349 + // 1: Column exists in matrix only
  1350 + // 0: Column does neither exist in matrix or stack
  1351 + int new_elements = 0;
  1352 + for (int entry = 0; entry < m_stack_entries; ++entry) {
  1353 +
  1354 + // Get column for actual entry
  1355 + int col = m_stack_colinx[entry];
  1356 +
  1357 + // If column exists already in matrix then determine total number
  1358 + // of elements
  1359 + if (wrk_int[col] == 1) {
  1360 + int i_start = m_colstart[col];
  1361 + int i_stop = m_colstart[col+1];
  1362 + int k_start = m_stack_start[entry];
  1363 + int k_stop = m_stack_start[entry+1];
  1364 + int row_m = m_rowinx[i_start];
  1365 + int row_s = m_stack_rowinx[k_start];
  1366 + if (k_start < k_stop && i_start < i_stop) {
  1367 + wrk_int[col] = -(entry+2); // Flag that we have to mix
  1368 + while (i_start < i_stop || k_start < k_stop) {
  1369 + if (row_m == row_s) { // Case A: element in matrix and stack
  1370 + i_start++;
  1371 + k_start++;
  1372 + row_m = (i_start < i_stop) ? m_rowinx[i_start] : m_rows+1;
  1373 + row_s = (k_start < k_stop) ? m_stack_rowinx[k_start] : m_rows+1;
  1374 + }
  1375 + else if (row_m < row_s) { // Case B: element in matrix only
  1376 + i_start++;
  1377 + row_m = (i_start < i_stop) ? m_rowinx[i_start] : m_rows+1;
  1378 + }
  1379 + else { // Case C: element in stack only
  1380 + k_start++;
  1381 + row_s = (k_start < k_stop) ? m_stack_rowinx[k_start] : m_rows+1;
  1382 + new_elements++;
  1383 + }
  1384 + } // endwhile: mixing
  1385 + } // endif: there were elements in stack
  1386 + } // endif: column existed in the matrix
  1387 +
  1388 + // Column did not exists in the matrix, so it's newand we add all elements
  1389 + else {
  1390 + wrk_int[col] = (entry+2);
  1391 + new_elements += (m_stack_start[entry+1] - m_stack_start[entry]);
  1392 + }
  1393 + }
  1394 + int elements = m_elements + new_elements;
  1395 +
  1396 + // Dump number of elements in new matrix
  1397 + #if defined(G_DEBUG_SPARSE_STACK_FLUSH)
  1398 + cout << " New elements ....: " << new_elements << endl;
  1399 + #endif
  1400 +
  1401 + // Allocate memory for new matrix (always keep some elbow room)
  1402 + m_alloc = elements + m_mem_block;
  1403 + double* new_data = new double[m_alloc];
  1404 + int* new_rowinx = new int[m_alloc];
  1405 + if (new_data == NULL || new_rowinx == NULL)
  1406 + throw mem_alloc("GSparseMatrix::stack_flush", m_alloc);
  1407 +
  1408 + // Fill new matrix. For this purpose we loop over all matrix columns
  1409 + // and perform the operation that was identified in the previous scan
  1410 + int index = 0;
  1411 + #if defined(G_DEBUG_SPARSE_STACK_FLUSH)
  1412 + int num_orig = 0;
  1413 + int num_stack = 0;
  1414 + int num_mix = 0;
  1415 + #endif
  1416 + for (int col = 0; col < m_cols; ++col) {
  1417 +
  1418 + // If column does not exist then skip
  1419 + if (wrk_int[col] == 0) {
  1420 + m_colstart[col] = index;
  1421 + continue;
  1422 + }
  1423 +
  1424 + // If column exists in the matrix but not in the stack we copy the
  1425 + // existing column into the new matrix
  1426 + if (wrk_int[col] == 1) {
  1427 + for (int i = m_colstart[col]; i < m_colstart[col+1]; ++i) {
  1428 + new_data[index] = m_data[i];
  1429 + new_rowinx[index] = m_rowinx[i];
  1430 + index++;
  1431 + #if defined(G_DEBUG_SPARSE_STACK_FLUSH)
  1432 + num_orig++;
  1433 + #endif
  1434 + }
  1435 + }
  1436 +
  1437 + // If column is new (i.e. it did not exist in the matrix before) we
  1438 + // copy the stack into the new matrix
  1439 + else if (wrk_int[col] > 1) {
  1440 + int entry = wrk_int[col] - 2;
  1441 + for (int i = m_stack_start[entry]; i < m_stack_start[entry+1]; ++i) {
  1442 + new_data[index] = m_stack_data[i];
  1443 + new_rowinx[index] = m_stack_rowinx[i];
  1444 + index++;
  1445 + #if defined(G_DEBUG_SPARSE_STACK_FLUSH)
  1446 + num_stack++;
  1447 + #endif
  1448 + }
  1449 + }
  1450 +
  1451 + // If column exists in the matrix and in the stack then we have the
  1452 + // most tricky case since we have to mix both ...
  1453 + else {
  1454 + int entry = -(wrk_int[col] + 2);
  1455 + int i_start = m_colstart[col];
  1456 + int i_stop = m_colstart[col+1];
  1457 + int k_start = m_stack_start[entry];
  1458 + int k_stop = m_stack_start[entry+1];
  1459 + int row_m = m_rowinx[i_start];
  1460 + int row_s = m_stack_rowinx[k_start];
  1461 + if (k_start < k_stop && i_start < i_stop) {
  1462 + while (i_start < i_stop || k_start < k_stop) {
  1463 + if (row_m == row_s) { // Case A: element in matrix and stack
  1464 + new_data[index] = m_data[i_start] + m_stack_data[k_start];
  1465 + new_rowinx[index] = row_m;
  1466 + i_start++;
  1467 + k_start++;
  1468 + row_m = (i_start < i_stop) ? m_rowinx[i_start] : m_rows+1;
  1469 + row_s = (k_start < k_stop) ? m_stack_rowinx[k_start] : m_rows+1;
  1470 + }
  1471 + else if (row_m < row_s) { // Case B: element in matrix only
  1472 + new_data[index] = m_data[i_start];
  1473 + new_rowinx[index] = row_m;
  1474 + i_start++;
  1475 + row_m = (i_start < i_stop) ? m_rowinx[i_start] : m_rows+1;
  1476 + }
  1477 + else { // Case C: element in stack only
  1478 + new_data[index] = m_stack_data[k_start];
  1479 + new_rowinx[index] = row_s;
  1480 + k_start++;
  1481 + row_s = (k_start < k_stop) ? m_stack_rowinx[k_start] : m_rows+1;
  1482 + }
  1483 + index++;
  1484 + #if defined(G_DEBUG_SPARSE_STACK_FLUSH)
  1485 + num_mix++;
  1486 + #endif
  1487 + } // endwhile: mixing
  1488 + } // endif: there were elements in stack
  1489 +
  1490 + } // endelse: we had to mix the entries
  1491 +
  1492 + // Store actual index in column start array
  1493 + m_colstart[col] = index;
  1494 +
  1495 + } // endfor: looped over all columns
  1496 +
  1497 + // Dump number of elements in new matrix after addition
  1498 + #if defined(G_DEBUG_SPARSE_STACK_FLUSH)
  1499 + cout << " Added elements ..: " << index << " (sould be " << elements << ")" << endl;
  1500 + cout << " - Matrix only ...: " << num_orig << endl;
  1501 + cout << " - Stack only ....: " << num_stack << endl;
  1502 + cout << " - Matrix & Stack : " << num_mix << endl;
  1503 + #endif
  1504 +
  1505 + // Correct columns start array
  1506 + for (int col = m_cols; col > 0; --col)
  1507 + m_colstart[col] = m_colstart[col-1];
  1508 + m_colstart[0] = 0;
  1509 +
  1510 + // Delete old matrix memory
  1511 + if (m_data != NULL) delete [] m_data;
  1512 + if (m_rowinx != NULL) delete [] m_rowinx;
  1513 +
  1514 + // Update pointers to new memory and update element counter
  1515 + m_data = new_data;
  1516 + m_rowinx = new_rowinx;
  1517 + m_elements = elements;
  1518 +
  1519 + // Stack is empty now, so reset stack counters
  1520 + m_stack_entries = 0;
  1521 + m_stack_start[0] = 0;
  1522 +
  1523 + // Free workspace
  1524 + delete [] wrk_int;
  1525 +
  1526 + // Return
  1527 + return;
  1528 +}
  1529 +
  1530 +
  1531 +/***************************************************************************
  1532 + * Destroy matrix stack *
  1533 + * ----------------------------------------------------------------------- *
  1534 + * Flush and destroy matrix stack *
  1535 + ***************************************************************************/
  1536 +void GSparseMatrix::stack_destroy(void)
  1537 +{
  1538 + // Flush stack first
  1539 + stack_flush();
  1540 +
  1541 + // Free stack members
  1542 + if (m_stack_colinx != NULL) delete [] m_stack_colinx;
  1543 + if (m_stack_start != NULL) delete [] m_stack_start;
  1544 + if (m_stack_data != NULL) delete [] m_stack_data;
  1545 + if (m_stack_rowinx != NULL) delete [] m_stack_rowinx;
  1546 +
  1547 + // Properly mark members as free
  1548 + m_stack_colinx = NULL;
  1549 + m_stack_start = NULL;
  1550 + m_stack_data = NULL;
  1551 + m_stack_rowinx = NULL;
  1552 +
  1553 + // Initialise stack members
  1554 + m_stack_max_entries = 0;
  1555 + m_stack_size = 0;
  1556 + m_stack_entries = 0;
  1557 +
  1558 + // Return
  1559 + return;
  1560 +}
  1561 +
  1562 +
1122 /*========================================================================== 1563 /*==========================================================================
1123 = = 1564 = =
1124 = GSparseMatrix private functions = 1565 = GSparseMatrix private functions =
src/GSparseMatrix.hpp
@@ -24,6 +24,8 @@ using namespace std; @@ -24,6 +24,8 @@ using namespace std;
24 24
25 /* __ Definitions ________________________________________________________ */ 25 /* __ Definitions ________________________________________________________ */
26 #define G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK 512 // Default Memory block size 26 #define G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK 512 // Default Memory block size
  27 +#define G_SPARSE_MATRIX_DEFAULT_STACK_ENTRIES 100 // Max # of stack entries
  28 +#define G_SPARSE_MATRIX_DEFAULT_STACK_SIZE 512 // Max # of stack elements
27 29
28 /* __ Macros (to be moved to GammaLib general header) ____________________ */ 30 /* __ Macros (to be moved to GammaLib general header) ____________________ */
29 #define G_MIN(a,b) (((a) < (b)) ? (a) : (b)) 31 #define G_MIN(a,b) (((a) < (b)) ? (a) : (b))
@@ -104,25 +106,43 @@ public: @@ -104,25 +106,43 @@ public:
104 virtual void cholesky_decompose(int compress = 1); 106 virtual void cholesky_decompose(int compress = 1);
105 virtual GVector cholesky_solver(const GVector& v, int compress = 1); 107 virtual GVector cholesky_solver(const GVector& v, int compress = 1);
106 virtual void cholesky_invert(int compress = 1); 108 virtual void cholesky_invert(int compress = 1);
  109 +
  110 + // Stack functions
  111 + virtual void stack_init(int size = 0, int entries = 0);
  112 + virtual int stack_push_column(const GVector& v, int col);
  113 + virtual void stack_flush(void);
  114 + virtual void stack_destroy(void);
107 115
108 private: 116 private:
109 // Private functions 117 // Private functions
110 - int get_index(int row, int col) const;  
111 - void fill_pending(void);  
112 - void alloc_elements(int start, int num);  
113 - void free_elements(int start, int num);  
114 - void remove_zero_row_col(void);  
115 - void insert_zero_row_col(int rows, int cols); 118 + void init_members(void);
  119 + void copy_members(const GSparseMatrix& m);
  120 + void free_members(void);
  121 + int get_index(int row, int col) const;
  122 + void fill_pending(void);
  123 + void alloc_elements(int start, int num);
  124 + void free_elements(int start, int num);
  125 + void remove_zero_row_col(void);
  126 + void insert_zero_row_col(int rows, int cols);
116 127
117 // Private data members 128 // Private data members
118 - int* m_rowinx; // Row-indices of all elements  
119 - int m_mem_block; // Memory block to be allocated at once  
120 - double m_zero; // The zero element (needed for data access)  
121 - double m_fill_val; // Element to be filled  
122 - int m_fill_row; // Row into which element needs to be filled  
123 - int m_fill_col; // Column into which element needs to be filled  
124 - void* m_symbolic; // Holds GSparseSymbolic object after decomposition  
125 - void* m_numeric; // Holds GSparseNumeric object after decomposition 129 + int* m_rowinx; // Row-indices of all elements
  130 + int m_mem_block; // Memory block to be allocated at once
  131 + double m_zero; // The zero element (needed for data access)
  132 + double m_fill_val; // Element to be filled
  133 + int m_fill_row; // Row into which element needs to be filled
  134 + int m_fill_col; // Column into which element needs to be filled
  135 + void* m_symbolic; // Holds GSparseSymbolic object after decomposition
  136 + void* m_numeric; // Holds GSparseNumeric object after decomposition
  137 +
  138 + // Fill-stack
  139 + int m_stack_max_entries; // Maximum number of entries in the stack
  140 + int m_stack_size; // Maximum number of elements in the stack
  141 + int m_stack_entries; // Number of entries in the stack
  142 + int* m_stack_colinx; // Column index for each entry [m_stack_entries]
  143 + int* m_stack_start; // Start in stack for each entry [m_stack_entries+1]
  144 + double* m_stack_data; // Stack data [m_stack_size]
  145 + int* m_stack_rowinx; // Srack row indices [m_stack_size]
126 }; 146 };
127 147
128 148
@@ -205,6 +225,7 @@ GSparseMatrix&amp; GSparseMatrix::operator*= (const double&amp; d) @@ -205,6 +225,7 @@ GSparseMatrix&amp; GSparseMatrix::operator*= (const double&amp; d)
205 { 225 {
206 fill_pending(); 226 fill_pending();
207 this->GMatrix::operator*=(d); 227 this->GMatrix::operator*=(d);
  228 + return *this;
208 } 229 }
209 230
210 // Unary scalar division 231 // Unary scalar division
@@ -213,6 +234,7 @@ GSparseMatrix&amp; GSparseMatrix::operator/= (const double&amp; d) @@ -213,6 +234,7 @@ GSparseMatrix&amp; GSparseMatrix::operator/= (const double&amp; d)
213 { 234 {
214 fill_pending(); 235 fill_pending();
215 this->GMatrix::operator/=(d); 236 this->GMatrix::operator/=(d);
  237 + return *this;
216 } 238 }
217 239
218 240
src/GSparseSymbolic.cpp
@@ -488,7 +488,7 @@ int* GSparseSymbolic::cs_amd(int order, const GSparseMatrix* A) @@ -488,7 +488,7 @@ int* GSparseSymbolic::cs_amd(int order, const GSparseMatrix* A)
488 #endif 488 #endif
489 489
490 // Drop diagonal entries from C 490 // Drop diagonal entries from C
491 - int cnz_diag = cs_fkeep(&C, &cs_diag, NULL); 491 + cs_fkeep(&C, &cs_diag, NULL);
492 492
493 // Debug 493 // Debug
494 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING) 494 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
src/GSymMatrix.cpp
@@ -389,6 +389,7 @@ void GSymMatrix::cholesky_decompose(int compress) @@ -389,6 +389,7 @@ void GSymMatrix::cholesky_decompose(int compress)
389 if (no_zeros) { 389 if (no_zeros) {
390 390
391 // Loop over upper triangle (col >= row) 391 // Loop over upper triangle (col >= row)
  392 + double diag = 0.0;
392 for (int row = 0; row < m_rows; ++row) { 393 for (int row = 0; row < m_rows; ++row) {
393 double* ptr = m_data + m_colstart[row]; 394 double* ptr = m_data + m_colstart[row];
394 for (int col = row; col < m_cols; ++col, ++ptr) { 395 for (int col = row; col < m_cols; ++col, ++ptr) {
@@ -397,7 +398,6 @@ void GSymMatrix::cholesky_decompose(int compress) @@ -397,7 +398,6 @@ void GSymMatrix::cholesky_decompose(int compress)
397 int offset = m_colstart[k] - k; // is always positive 398 int offset = m_colstart[k] - k; // is always positive
398 sum -= m_data[offset+row] * m_data[offset+col]; // sum -= M(row,k)*M(col,k) 399 sum -= m_data[offset+row] * m_data[offset+col]; // sum -= M(row,k)*M(col,k)
399 } 400 }
400 - double diag;  
401 if (row == col) { 401 if (row == col) {
402 if (sum <= 0.0) 402 if (sum <= 0.0)
403 throw matrix_not_pos_definite("GSymMatrix::cholesky_decompose(int)", 403 throw matrix_not_pos_definite("GSymMatrix::cholesky_decompose(int)",
@@ -423,6 +423,7 @@ void GSymMatrix::cholesky_decompose(int compress) @@ -423,6 +423,7 @@ void GSymMatrix::cholesky_decompose(int compress)
423 int* k_ptr; 423 int* k_ptr;
424 424
425 // Loop over upper triangle (col >= row) 425 // Loop over upper triangle (col >= row)
  426 + double diag = 0.0;
426 for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) { 427 for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) {
427 double* ptr_0 = m_data + m_colstart[*row_ptr] - *row_ptr; 428 double* ptr_0 = m_data + m_colstart[*row_ptr] - *row_ptr;
428 for (col = row, col_ptr = m_inx + row; col < m_num_inx; ++col, ++col_ptr) { 429 for (col = row, col_ptr = m_inx + row; col < m_num_inx; ++col, ++col_ptr) {
@@ -432,7 +433,6 @@ void GSymMatrix::cholesky_decompose(int compress) @@ -432,7 +433,6 @@ void GSymMatrix::cholesky_decompose(int compress)
432 int offset = m_colstart[*k_ptr] - *k_ptr; // is always positive 433 int offset = m_colstart[*k_ptr] - *k_ptr; // is always positive
433 sum -= m_data[offset+*row_ptr] * m_data[offset+*col_ptr]; // sum -= M(row,k)*M(col,k) 434 sum -= m_data[offset+*row_ptr] * m_data[offset+*col_ptr]; // sum -= M(row,k)*M(col,k)
434 } 435 }
435 - double diag;  
436 if (*row_ptr == *col_ptr) { 436 if (*row_ptr == *col_ptr) {
437 if (sum <= 0.0) 437 if (sum <= 0.0)
438 throw matrix_not_pos_definite("GSymMatrix::cholesky_decompose(int)", 438 throw matrix_not_pos_definite("GSymMatrix::cholesky_decompose(int)",
src/GSymMatrix.hpp
@@ -159,6 +159,7 @@ inline @@ -159,6 +159,7 @@ inline
159 GSymMatrix& GSymMatrix::operator*= (const double& d) 159 GSymMatrix& GSymMatrix::operator*= (const double& d)
160 { 160 {
161 this->GMatrix::operator*=(d); 161 this->GMatrix::operator*=(d);
  162 + return *this;
162 } 163 }
163 164
164 // Unary scalar division 165 // Unary scalar division
@@ -166,6 +167,7 @@ inline @@ -166,6 +167,7 @@ inline
166 GSymMatrix& GSymMatrix::operator/= (const double& d) 167 GSymMatrix& GSymMatrix::operator/= (const double& d)
167 { 168 {
168 this->GMatrix::operator/=(d); 169 this->GMatrix::operator/=(d);
  170 + return *this;
169 } 171 }
170 172
171 173
src/GammaLib.hpp 0 โ†’ 100644
  1 +/***************************************************************************
  2 + * GammaLib.hpp - Gamma-Ray Astronomy Library Header file *
  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 GAMMALIB_HPP
  15 +#define GAMMALIB_HPP
  16 +
  17 +/* __ Includes ___________________________________________________________ */
  18 +#ifdef HAVE_CONFIG_H
  19 +#include <config.h>
  20 +#endif
  21 +#include "GException.hpp"
  22 +#include "GVector.hpp"
  23 +#include "GMatrix.hpp"
  24 +#include "GSymMatrix.hpp"
  25 +#include "GSparseMatrix.hpp"
  26 +#include "GSparseSymbolic.hpp"
  27 +#include "GSparseNumeric.hpp"
  28 +
  29 +/* __ Globals ____________________________________________________________ */
  30 +
  31 +/* __ Prototypes _________________________________________________________ */
  32 +
  33 +#endif /* GAMMALIB_HPP */
src/Makefile.am
1 ## Process this file with automake to produce Makefile.in 1 ## Process this file with automake to produce Makefile.in
2 2
3 -files = GException.hpp GException.cpp \  
4 - GVector.hpp GVector.cpp \  
5 - GMatrix.hpp GMatrix.cpp \  
6 - GSymMatrix.hpp GSymMatrix.cpp \  
7 - GSparseMatrix.hpp GSparseMatrix.cpp \  
8 - GSparseSymbolic.hpp GSparseSymbolic.cpp \  
9 - GSparseNumeric.hpp GSparseNumeric.cpp 3 +SUBDIRS = src test
10 4
11 -# Build dynamic library  
12 -#lib_LTLIBRARIES = libgamma.la  
13 -#libgamma_la_SOURCES = $(files)  
14 -#libgamma_la_LDFLAGS =  
15 -  
16 -# Build static library  
17 -noinst_LIBRARIES = libgamma.a  
18 -libgamma_a_SOURCES = $(files)  
19 -#libgamma_a_LDFLAGS =  
test/Makefile.am
1 ## Process this file with automake to produce Makefile.in 1 ## Process this file with automake to produce Makefile.in
2 2
3 -check_PROGRAMS = test_GVector \  
4 - test_GMatrix \  
5 - test_GSymMatrix \  
6 - test_GSparseMatrix  
7 -TESTS = test_GVector \  
8 - test_GMatrix \  
9 - test_GSymMatrix \  
10 - test_GSparseMatrix  
11 -test_GVector_SOURCES = test_GVector.cpp  
12 -#test_GVector_LDADD = ../src/libgamma.la  
13 -test_GVector_LDADD = ../src/libgamma.a  
14 -test_GMatrix_SOURCES = test_GMatrix.cpp  
15 -#test_GMatrix_LDADD = ../src/libgamma.la  
16 -test_GMatrix_LDADD = ../src/libgamma.a  
17 -test_GSymMatrix_SOURCES = test_GSymMatrix.cpp  
18 -#test_GSymMatrix_LDADD = ../src/libgamma.la  
19 -test_GSymMatrix_LDADD = ../src/libgamma.a  
20 -test_GSparseMatrix_SOURCES = test_GSparseMatrix.cpp  
21 -#test_GSparseMatrix_LDADD = ../src/libgamma.la  
22 -test_GSparseMatrix_LDADD = ../src/libgamma.a 3 +SUBDIRS = src test
  4 +
test/Makefile.in
@@ -183,7 +183,7 @@ test_GSymMatrix_SOURCES = test_GSymMatrix.cpp @@ -183,7 +183,7 @@ test_GSymMatrix_SOURCES = test_GSymMatrix.cpp
183 test_GSymMatrix_LDADD = ../src/libgamma.a 183 test_GSymMatrix_LDADD = ../src/libgamma.a
184 test_GSparseMatrix_SOURCES = test_GSparseMatrix.cpp 184 test_GSparseMatrix_SOURCES = test_GSparseMatrix.cpp
185 #test_GSparseMatrix_LDADD = ../src/libgamma.la 185 #test_GSparseMatrix_LDADD = ../src/libgamma.la
186 -test_GSparseMatrix_LDADD = ../src/libgamma.a 186 +test_GSparseMatrix_LDADD = ../src/libgamma.a -lc_p
187 all: all-am 187 all: all-am
188 188
189 .SUFFIXES: 189 .SUFFIXES:
test/test_GMatrix.cpp
@@ -22,8 +22,8 @@ double g_matrix[] = {1.0, 2.0, 3.0, 4.0, @@ -22,8 +22,8 @@ double g_matrix[] = {1.0, 2.0, 3.0, 4.0,
22 5.0, 6.0, 7.0, 8.0, 22 5.0, 6.0, 7.0, 8.0,
23 9.0, 10., 11., 12.}; 23 9.0, 10., 11., 12.};
24 double g_vector[] = {1.0, 2.0, 3.0, 4.0}; 24 double g_vector[] = {1.0, 2.0, 3.0, 4.0};
25 -unsigned g_rows = 3;  
26 -unsigned g_cols = 4; 25 +int g_rows = 3;
  26 +int g_cols = 4;
27 27
28 28
29 /*************************************************************************** 29 /***************************************************************************
@@ -33,8 +33,8 @@ GMatrix set_matrix(void) @@ -33,8 +33,8 @@ GMatrix set_matrix(void)
33 { 33 {
34 try { 34 try {
35 GMatrix matrix(g_rows,g_cols); 35 GMatrix matrix(g_rows,g_cols);
36 - for (unsigned row = 0; row < g_rows; ++row) {  
37 - for (unsigned col = 0; col < g_cols; ++col) 36 + for (int row = 0; row < g_rows; ++row) {
  37 + for (int col = 0; col < g_cols; ++col)
38 matrix(row,col) = g_matrix[col+row*g_cols]; 38 matrix(row,col) = g_matrix[col+row*g_cols];
39 } 39 }
40 return matrix; 40 return matrix;
@@ -53,7 +53,7 @@ GVector set_vector(void) @@ -53,7 +53,7 @@ GVector set_vector(void)
53 { 53 {
54 try { 54 try {
55 GVector vector(g_cols); 55 GVector vector(g_cols);
56 - for (unsigned col = 0; col < g_cols; ++col) 56 + for (int col = 0; col < g_cols; ++col)
57 vector(col) = g_vector[col]; 57 vector(col) = g_vector[col];
58 return vector; 58 return vector;
59 } 59 }
@@ -71,8 +71,8 @@ int check_matrix(const GMatrix&amp; m, const double scale, const double add) @@ -71,8 +71,8 @@ int check_matrix(const GMatrix&amp; m, const double scale, const double add)
71 { 71 {
72 int result = 1; 72 int result = 1;
73 try { 73 try {
74 - for (unsigned row = 0; row < g_rows; ++row) {  
75 - for (unsigned col = 0; col < g_cols; ++col) { 74 + for (int row = 0; row < g_rows; ++row) {
  75 + for (int col = 0; col < g_cols; ++col) {
76 double value = g_matrix[col+row*g_cols] * scale + add; 76 double value = g_matrix[col+row*g_cols] * scale + add;
77 if (fabs(m(row,col)-value) > 1.0e-15) { 77 if (fabs(m(row,col)-value) > 1.0e-15) {
78 result = 0; 78 result = 0;
@@ -96,8 +96,8 @@ int check_transpose_matrix(const GMatrix&amp; m, const double scale, const double ad @@ -96,8 +96,8 @@ int check_transpose_matrix(const GMatrix&amp; m, const double scale, const double ad
96 { 96 {
97 int result = 1; 97 int result = 1;
98 try { 98 try {
99 - for (unsigned row = 0; row < g_rows; ++row) {  
100 - for (unsigned col = 0; col < g_cols; ++col) { 99 + for (int row = 0; row < g_rows; ++row) {
  100 + for (int col = 0; col < g_cols; ++col) {
101 double value = g_matrix[col+row*g_cols] * scale + add; 101 double value = g_matrix[col+row*g_cols] * scale + add;
102 if (m(col,row) != value) { 102 if (m(col,row) != value) {
103 result = 0; 103 result = 0;
@@ -121,8 +121,8 @@ int check_matrix_lt(const GMatrix&amp; m, const double scale, const double add) @@ -121,8 +121,8 @@ int check_matrix_lt(const GMatrix&amp; m, const double scale, const double add)
121 { 121 {
122 int result = 1; 122 int result = 1;
123 try { 123 try {
124 - for (unsigned row = 0; row < g_rows; ++row) {  
125 - for (unsigned col = 0; col < g_cols; ++col) { 124 + for (int row = 0; row < g_rows; ++row) {
  125 + for (int col = 0; col < g_cols; ++col) {
126 double value = (col <= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0; 126 double value = (col <= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0;
127 if (m(row,col) != value) { 127 if (m(row,col) != value) {
128 result = 0; 128 result = 0;
@@ -146,8 +146,8 @@ int check_matrix_ut(const GMatrix&amp; m, const double scale, const double add) @@ -146,8 +146,8 @@ int check_matrix_ut(const GMatrix&amp; m, const double scale, const double add)
146 { 146 {
147 int result = 1; 147 int result = 1;
148 try { 148 try {
149 - for (unsigned row = 0; row < g_rows; ++row) {  
150 - for (unsigned col = 0; col < g_cols; ++col) { 149 + for (int row = 0; row < g_rows; ++row) {
  150 + for (int col = 0; col < g_cols; ++col) {
151 double value = (col >= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0; 151 double value = (col >= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0;
152 if (m(row,col) != value) { 152 if (m(row,col) != value) {
153 result = 0; 153 result = 0;
@@ -171,9 +171,9 @@ int check_matrix_vector(const GVector&amp; v) @@ -171,9 +171,9 @@ int check_matrix_vector(const GVector&amp; v)
171 { 171 {
172 int result = 1; 172 int result = 1;
173 try { 173 try {
174 - for (unsigned row = 0; row < v.size(); ++row) { 174 + for (int row = 0; row < v.size(); ++row) {
175 double value = 0.0; 175 double value = 0.0;
176 - for (unsigned col = 0; col < g_cols; ++col) 176 + for (int col = 0; col < g_cols; ++col)
177 value += g_matrix[col+row*g_cols] * g_vector[col]; 177 value += g_matrix[col+row*g_cols] * g_vector[col];
178 if (v(row) != value) { 178 if (v(row) != value) {
179 result = 0; 179 result = 0;
@@ -198,10 +198,10 @@ int check_matrix_matrix(const GMatrix&amp; m) @@ -198,10 +198,10 @@ int check_matrix_matrix(const GMatrix&amp; m)
198 return 0; 198 return 0;
199 int result = 1; 199 int result = 1;
200 try { 200 try {
201 - for (unsigned row = 0; row < m.rows(); ++row) {  
202 - for (unsigned col = 0; col < m.cols(); ++col) { 201 + for (int row = 0; row < m.rows(); ++row) {
  202 + for (int col = 0; col < m.cols(); ++col) {
203 double value = 0.0; 203 double value = 0.0;
204 - for (unsigned i = 0; i < g_cols; ++i) 204 + for (int i = 0; i < g_cols; ++i)
205 value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols]; 205 value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols];
206 if (m(row,col) != value) { 206 if (m(row,col) != value) {
207 result = 0; 207 result = 0;
@@ -224,8 +224,8 @@ int check_matrix_matrix(const GMatrix&amp; m) @@ -224,8 +224,8 @@ int check_matrix_matrix(const GMatrix&amp; m)
224 int check_matrix_min(const double min) 224 int check_matrix_min(const double min)
225 { 225 {
226 double value = g_matrix[0]; 226 double value = g_matrix[0];
227 - for (unsigned row = 0; row < g_rows; ++row) {  
228 - for (unsigned col = 0; col < g_cols; ++col) { 227 + for (int row = 0; row < g_rows; ++row) {
  228 + for (int col = 0; col < g_cols; ++col) {
229 if (g_matrix[col+row*g_cols] < value) 229 if (g_matrix[col+row*g_cols] < value)
230 value = g_matrix[col+row*g_cols]; 230 value = g_matrix[col+row*g_cols];
231 } 231 }
@@ -240,8 +240,8 @@ int check_matrix_min(const double min) @@ -240,8 +240,8 @@ int check_matrix_min(const double min)
240 int check_matrix_max(const double max) 240 int check_matrix_max(const double max)
241 { 241 {
242 double value = g_matrix[0]; 242 double value = g_matrix[0];
243 - for (unsigned row = 0; row < g_rows; ++row) {  
244 - for (unsigned col = 0; col < g_cols; ++col) { 243 + for (int row = 0; row < g_rows; ++row) {
  244 + for (int col = 0; col < g_cols; ++col) {
245 if (g_matrix[col+row*g_cols] > value) 245 if (g_matrix[col+row*g_cols] > value)
246 value = g_matrix[col+row*g_cols]; 246 value = g_matrix[col+row*g_cols];
247 } 247 }
@@ -256,8 +256,8 @@ int check_matrix_max(const double max) @@ -256,8 +256,8 @@ int check_matrix_max(const double max)
256 int check_matrix_sum(const double sum) 256 int check_matrix_sum(const double sum)
257 { 257 {
258 double value = 0.0; 258 double value = 0.0;
259 - for (unsigned row = 0; row < g_rows; ++row) {  
260 - for (unsigned col = 0; col < g_cols; ++col) 259 + for (int row = 0; row < g_rows; ++row) {
  260 + for (int col = 0; col < g_cols; ++col)
261 value += g_matrix[col+row*g_cols]; 261 value += g_matrix[col+row*g_cols];
262 } 262 }
263 return (sum == value); 263 return (sum == value);
@@ -674,4 +674,6 @@ int main(void) @@ -674,4 +674,6 @@ int main(void)
674 } 674 }
675 cout << "ok." << endl; 675 cout << "ok." << endl;
676 676
  677 + // Return
  678 + return 0;
677 } 679 }
test/test_GSparseMatrix.cpp
@@ -23,12 +23,12 @@ using namespace std; @@ -23,12 +23,12 @@ using namespace std;
23 23
24 /* __ Globals ____________________________________________________________ */ 24 /* __ Globals ____________________________________________________________ */
25 double g_matrix[] = {1.0, 7.0, 3.0, 2.0, 4.0, 8.0, 5.0, 6.0, 9.0}; 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}; 26 +int g_row[] = { 0, 0, 1, 2, 2, 2, 3, 3, 3};
  27 +int 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}; 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; 29 +int g_elements = 9;
  30 +int g_rows = 4;
  31 +int g_cols = 5;
32 32
33 33
34 /*************************************************************************** 34 /***************************************************************************
@@ -38,7 +38,7 @@ GSparseMatrix set_matrix(void) @@ -38,7 +38,7 @@ GSparseMatrix set_matrix(void)
38 { 38 {
39 try { 39 try {
40 GSparseMatrix matrix(g_rows,g_cols); 40 GSparseMatrix matrix(g_rows,g_cols);
41 - for (unsigned i = 0; i < g_elements; ++i) 41 + for (int i = 0; i < g_elements; ++i)
42 matrix(g_row[i],g_col[i]) = g_matrix[i]; 42 matrix(g_row[i],g_col[i]) = g_matrix[i];
43 return matrix; 43 return matrix;
44 } 44 }
@@ -56,7 +56,7 @@ GVector set_vector(void) @@ -56,7 +56,7 @@ GVector set_vector(void)
56 { 56 {
57 try { 57 try {
58 GVector vector(g_cols); 58 GVector vector(g_cols);
59 - for (unsigned col = 0; col < g_cols; ++col) 59 + for (int col = 0; col < g_cols; ++col)
60 vector(col) = g_vector[col]; 60 vector(col) = g_vector[col];
61 return vector; 61 return vector;
62 } 62 }
@@ -74,9 +74,9 @@ int check_matrix(const GSparseMatrix&amp; m, const double scale, const double add) @@ -74,9 +74,9 @@ int check_matrix(const GSparseMatrix&amp; m, const double scale, const double add)
74 { 74 {
75 int result = 1; 75 int result = 1;
76 try { 76 try {
77 - for (unsigned row = 0; row < g_rows; ++row) {  
78 - for (unsigned col = 0; col < g_cols; ++col) {  
79 - unsigned i; 77 + for (int row = 0; row < g_rows; ++row) {
  78 + for (int col = 0; col < g_cols; ++col) {
  79 + int i;
80 double ref_value = add; 80 double ref_value = add;
81 for (i = 0; i < g_elements; ++i) { 81 for (i = 0; i < g_elements; ++i) {
82 if (g_row[i] == row && g_col[i] == col) { 82 if (g_row[i] == row && g_col[i] == col) {
@@ -107,10 +107,10 @@ int check_matrix_vector(const GVector&amp; v) @@ -107,10 +107,10 @@ int check_matrix_vector(const GVector&amp; v)
107 { 107 {
108 int result = 1; 108 int result = 1;
109 try { 109 try {
110 - for (unsigned row = 0; row < v.size(); ++row) { 110 + for (int row = 0; row < v.size(); ++row) {
111 double value = 0.0; 111 double value = 0.0;
112 - for (unsigned col = 0; col < g_cols; ++col) {  
113 - unsigned i; 112 + for (int col = 0; col < g_cols; ++col) {
  113 + int i;
114 double ref_value = 0.0; 114 double ref_value = 0.0;
115 for (i = 0; i < g_elements; ++i) { 115 for (i = 0; i < g_elements; ++i) {
116 if (g_row[i] == row && g_col[i] == col) { 116 if (g_row[i] == row && g_col[i] == col) {
@@ -143,11 +143,11 @@ int check_matrix_matrix(const GSparseMatrix&amp; m) @@ -143,11 +143,11 @@ int check_matrix_matrix(const GSparseMatrix&amp; m)
143 return 0; 143 return 0;
144 int result = 1; 144 int result = 1;
145 try { 145 try {
146 - for (unsigned row = 0; row < m.rows(); ++row) {  
147 - for (unsigned col = 0; col < m.cols(); ++col) { 146 + for (int row = 0; row < m.rows(); ++row) {
  147 + for (int col = 0; col < m.cols(); ++col) {
148 double value = 0.0; 148 double value = 0.0;
149 - for (unsigned i = 0; i < g_cols; ++i) {  
150 - unsigned k; 149 + for (int i = 0; i < g_cols; ++i) {
  150 + int k;
151 double ref_value_1 = 0.0; 151 double ref_value_1 = 0.0;
152 double ref_value_2 = 0.0; 152 double ref_value_2 = 0.0;
153 for (k = 0; k < g_elements; ++k) { 153 for (k = 0; k < g_elements; ++k) {
@@ -187,9 +187,9 @@ int check_transpose_matrix(const GSparseMatrix&amp; m, const double scale, const dou @@ -187,9 +187,9 @@ int check_transpose_matrix(const GSparseMatrix&amp; m, const double scale, const dou
187 { 187 {
188 int result = 1; 188 int result = 1;
189 try { 189 try {
190 - for (unsigned row = 0; row < g_rows; ++row) {  
191 - for (unsigned col = 0; col < g_cols; ++col) {  
192 - unsigned i; 190 + for (int row = 0; row < g_rows; ++row) {
  191 + for (int col = 0; col < g_cols; ++col) {
  192 + int i;
193 double ref_value = 0.0; 193 double ref_value = 0.0;
194 for (i = 0; i < g_elements; ++i) { 194 for (i = 0; i < g_elements; ++i) {
195 if (g_row[i] == row && g_col[i] == col) { 195 if (g_row[i] == row && g_col[i] == col) {
@@ -218,7 +218,7 @@ int check_transpose_matrix(const GSparseMatrix&amp; m, const double scale, const dou @@ -218,7 +218,7 @@ int check_transpose_matrix(const GSparseMatrix&amp; m, const double scale, const dou
218 int check_matrix_min(const double min) 218 int check_matrix_min(const double min)
219 { 219 {
220 double value = g_matrix[0]; 220 double value = g_matrix[0];
221 - for (unsigned i = 0; i < g_elements; ++i) { 221 + for (int i = 0; i < g_elements; ++i) {
222 if (g_matrix[i] < value) 222 if (g_matrix[i] < value)
223 value = g_matrix[i]; 223 value = g_matrix[i];
224 } 224 }
@@ -233,7 +233,7 @@ int check_matrix_min(const double min) @@ -233,7 +233,7 @@ int check_matrix_min(const double min)
233 int check_matrix_max(const double max) 233 int check_matrix_max(const double max)
234 { 234 {
235 double value = g_matrix[0]; 235 double value = g_matrix[0];
236 - for (unsigned i = 0; i < g_elements; ++i) { 236 + for (int i = 0; i < g_elements; ++i) {
237 if (g_matrix[i] > value) 237 if (g_matrix[i] > value)
238 value = g_matrix[i]; 238 value = g_matrix[i];
239 } 239 }
@@ -247,7 +247,7 @@ int check_matrix_max(const double max) @@ -247,7 +247,7 @@ int check_matrix_max(const double max)
247 int check_matrix_sum(const double sum) 247 int check_matrix_sum(const double sum)
248 { 248 {
249 double value = 0.0; 249 double value = 0.0;
250 - for (unsigned i = 0; i < g_elements; ++i) 250 + for (int i = 0; i < g_elements; ++i)
251 value += g_matrix[i]; 251 value += g_matrix[i];
252 return (sum == value); 252 return (sum == value);
253 } 253 }
@@ -375,7 +375,31 @@ void test_assign_values(const GSparseMatrix&amp; m_test) @@ -375,7 +375,31 @@ void test_assign_values(const GSparseMatrix&amp; m_test)
375 throw; 375 throw;
376 } 376 }
377 cout << "."; 377 cout << ".";
378 - #endif 378 + #endif
  379 + //
  380 + // Insert column into 10 x 10 matrix using matrix stack
  381 + try {
  382 + GSparseMatrix stack(10,10);
  383 + stack.clear();
  384 + for (int i = 3; i < 5; ++i)
  385 + stack(i,i) = 5.0;
  386 + GVector column(10);
  387 + stack.stack_init(100,50);
  388 + for (int j = 0; j < 10; ++j) {
  389 + int i_min = (j < 2) ? 0 : j-2;
  390 + int i_max = (j > 8) ? 10 : j+2;
  391 + column = 0.0;
  392 + for (int i = i_min; i < i_max; ++i)
  393 + column(i) = (i+1)*1;
  394 + stack.add_col(column, j);
  395 + }
  396 + stack.stack_destroy();
  397 +// cout << stack << endl;
  398 + }
  399 + catch (exception &e) {
  400 + cout << e.what() << endl;
  401 + throw;
  402 + }
379 cout << " ok." << endl; 403 cout << " ok." << endl;
380 } 404 }
381 405
@@ -1346,16 +1370,18 @@ void test_heavy(int block = 512) @@ -1346,16 +1370,18 @@ void test_heavy(int block = 512)
1346 clock_t t_start; 1370 clock_t t_start;
1347 double t_elapse; 1371 double t_elapse;
1348 int number; 1372 int number;
  1373 + int num_cols;
  1374 + int i_min, i_max;
1349 1375
1350 // Perform test 1376 // Perform test
1351 cout << "Test GSparseMatrix: Heavy calculus: "; 1377 cout << "Test GSparseMatrix: Heavy calculus: ";
1352 try { 1378 try {
1353 // 1379 //
1354 // Fill 10000 x 10000 matrix with 10000 values 1380 // Fill 10000 x 10000 matrix with 10000 values
  1381 + t_start = clock();
1355 number = 10000; 1382 number = 10000;
1356 GSparseMatrix large(number,number); 1383 GSparseMatrix large(number,number);
1357 large.set_mem_block(block); 1384 large.set_mem_block(block);
1358 - t_start = clock();  
1359 for (int i = 0; i < number; ++i) 1385 for (int i = 0; i < number; ++i)
1360 large(i,i) = (i+1)*3.14; 1386 large(i,i) = (i+1)*3.14;
1361 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC); 1387 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
@@ -1375,32 +1401,67 @@ void test_heavy(int block = 512) @@ -1375,32 +1401,67 @@ void test_heavy(int block = 512)
1375 #endif 1401 #endif
1376 // 1402 //
1377 // Insert columns into 10000 x 10000 matrix 1403 // Insert columns into 10000 x 10000 matrix
1378 - number = 10000; 1404 + number = 10000;
  1405 + num_cols = 1000;
1379 large.clear(); 1406 large.clear();
1380 large.set_mem_block(block); 1407 large.set_mem_block(block);
  1408 + for (int j = 200; j < 400; ++j)
  1409 + large(j,j) = 3.14;
1381 GVector column(number); 1410 GVector column(number);
1382 t_start = clock(); 1411 t_start = clock();
1383 - for (int j = 0; j < 100; ++j) { 1412 + for (int j = 0; j < num_cols; ++j) {
  1413 + i_min = (j < 2) ? 0 : j-2;
  1414 + i_max = (j > num_cols-2) ? num_cols : j+2;
1384 column = 0.0; 1415 column = 0.0;
1385 - for (int i = j; i < number; ++i)  
1386 - column(i) = (i+1)*3.14; 1416 + for (int i = i_min; i < i_max; ++i)
  1417 + column(i) = (i+1)*0.01;
1387 large.add_col(column, j); 1418 large.add_col(column, j);
1388 } 1419 }
1389 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC); 1420 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
1390 #if defined(DUMP_TIMING) 1421 #if defined(DUMP_TIMING)
1391 - cout << endl << " - 100 columns adding needed " << t_elapse <<  
1392 - " sec (reference ~ 2.6 sec)"; 1422 + cout << endl << " - " << num_cols << " columns adding needed " << t_elapse <<
  1423 + " sec (reference ~ 0.4 sec)";
1393 #endif 1424 #endif
1394 // 1425 //
  1426 + // Insert columns into 10000 x 10000 matrix using matrix stack
  1427 + GSparseMatrix stack(number,number);
  1428 + stack.clear();
  1429 + stack.set_mem_block(block);
  1430 + for (int j = 200; j < 400; ++j)
  1431 + stack(j,j) = 3.14;
  1432 + t_start = clock();
  1433 + column = GVector(number);
  1434 + stack.stack_init(20000,100);
  1435 + for (int j = 0; j < num_cols; ++j) {
  1436 + i_min = (j < 2) ? 0 : j-2;
  1437 + i_max = (j > num_cols-2) ? num_cols : j+2;
  1438 + column = 0.0;
  1439 + for (int i = i_min; i < i_max; ++i)
  1440 + column(i) = (i+1)*0.01;
  1441 + stack.add_col(column, j);
  1442 + }
  1443 + stack.stack_destroy();
  1444 + t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
  1445 + #if defined(DUMP_TIMING)
  1446 + cout << endl << " - " << num_cols << " columns stack-adding needed " << t_elapse <<
  1447 + " sec (reference ~ 0.1 sec)";
  1448 + #endif
  1449 + //
  1450 + // Check that both are identical
  1451 + if (large != stack) {
  1452 + cout << endl << "TEST ERROR: Stack-based insertion corrupted." << endl;
  1453 + throw;
  1454 + }
  1455 + //
1395 // Subsequent addition and subtractions 1456 // Subsequent addition and subtractions
1396 number = 300; 1457 number = 300;
  1458 + t_start = clock();
1397 GSparseMatrix sum(number,number); 1459 GSparseMatrix sum(number,number);
1398 GSparseMatrix add(number,number); 1460 GSparseMatrix add(number,number);
1399 GSparseMatrix sub(number,number); 1461 GSparseMatrix sub(number,number);
1400 sum.set_mem_block(block); 1462 sum.set_mem_block(block);
1401 add.set_mem_block(block); 1463 add.set_mem_block(block);
1402 sub.set_mem_block(block); 1464 sub.set_mem_block(block);
1403 - t_start = clock();  
1404 for (int i = 0; i < number; ++i) { 1465 for (int i = 0; i < number; ++i) {
1405 add(i,number-i-1) = (i*i+1)*0.01; 1466 add(i,number-i-1) = (i*i+1)*0.01;
1406 sum += add; 1467 sum += add;
@@ -1425,7 +1486,7 @@ void test_heavy(int block = 512) @@ -1425,7 +1486,7 @@ void test_heavy(int block = 512)
1425 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC); 1486 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
1426 #if defined(DUMP_TIMING) 1487 #if defined(DUMP_TIMING)
1427 cout << endl << " - Matrix multiplication 1 times " << t_elapse << 1488 cout << endl << " - Matrix multiplication 1 times " << t_elapse <<
1428 - " sec (reference ~ 3.5 sec)"; 1489 + " sec (reference ~ 3.1 sec)";
1429 #endif 1490 #endif
1430 } 1491 }
1431 catch (exception &e) { 1492 catch (exception &e) {
test/test_GSymMatrix.cpp
@@ -18,10 +18,10 @@ @@ -18,10 +18,10 @@
18 using namespace std; 18 using namespace std;
19 19
20 /* __ Globals ____________________________________________________________ */ 20 /* __ Globals ____________________________________________________________ */
21 -double g_matrix[] = {4.0, 1.0, 2.0, 1.0, 5.0, 3.0, 2.0, 3.0, 6.0};  
22 -double g_vector[] = {1.0, 2.0, 3.0};  
23 -unsigned g_rows = 3;  
24 -unsigned g_cols = 3; 21 +double g_matrix[] = {4.0, 1.0, 2.0, 1.0, 5.0, 3.0, 2.0, 3.0, 6.0};
  22 +double g_vector[] = {1.0, 2.0, 3.0};
  23 +int g_rows = 3;
  24 +int g_cols = 3;
25 25
26 26
27 /*************************************************************************** 27 /***************************************************************************
@@ -31,8 +31,8 @@ GSymMatrix set_matrix(void) @@ -31,8 +31,8 @@ GSymMatrix set_matrix(void)
31 { 31 {
32 try { 32 try {
33 GSymMatrix matrix(g_rows,g_cols); 33 GSymMatrix matrix(g_rows,g_cols);
34 - for (unsigned row = 0; row < g_rows; ++row) {  
35 - for (unsigned col = 0; col < g_cols; ++col) 34 + for (int row = 0; row < g_rows; ++row) {
  35 + for (int col = 0; col < g_cols; ++col)
36 matrix(row,col) = g_matrix[col+row*g_cols]; 36 matrix(row,col) = g_matrix[col+row*g_cols];
37 } 37 }
38 return matrix; 38 return matrix;
@@ -51,11 +51,11 @@ GSymMatrix set_matrix_zero(void) @@ -51,11 +51,11 @@ GSymMatrix set_matrix_zero(void)
51 { 51 {
52 try { 52 try {
53 GSymMatrix matrix(g_rows+1,g_cols+1); 53 GSymMatrix matrix(g_rows+1,g_cols+1);
54 - unsigned i = 0;  
55 - for (unsigned row = 0; row < g_rows+1; ++row) { 54 + int i = 0;
  55 + for (int row = 0; row < g_rows+1; ++row) {
56 if (row == 2) continue; 56 if (row == 2) continue;
57 - unsigned j = 0;  
58 - for (unsigned col = 0; col < g_cols+1; ++col) { 57 + int j = 0;
  58 + for (int col = 0; col < g_cols+1; ++col) {
59 if (col == 2) continue; 59 if (col == 2) continue;
60 matrix(row,col) = g_matrix[j+i*g_cols]; 60 matrix(row,col) = g_matrix[j+i*g_cols];
61 j++; 61 j++;
@@ -78,7 +78,7 @@ GVector set_vector(void) @@ -78,7 +78,7 @@ GVector set_vector(void)
78 { 78 {
79 try { 79 try {
80 GVector vector(g_cols); 80 GVector vector(g_cols);
81 - for (unsigned col = 0; col < g_cols; ++col) 81 + for (int col = 0; col < g_cols; ++col)
82 vector(col) = g_vector[col]; 82 vector(col) = g_vector[col];
83 return vector; 83 return vector;
84 } 84 }
@@ -96,8 +96,8 @@ int check_matrix(const GSymMatrix&amp; m, const double scale, const double add) @@ -96,8 +96,8 @@ int check_matrix(const GSymMatrix&amp; m, const double scale, const double add)
96 { 96 {
97 int result = 1; 97 int result = 1;
98 try { 98 try {
99 - for (unsigned row = 0; row < g_rows; ++row) {  
100 - for (unsigned col = 0; col < g_cols; ++col) { 99 + for (int row = 0; row < g_rows; ++row) {
  100 + for (int col = 0; col < g_cols; ++col) {
101 double value = g_matrix[col+row*g_cols] * scale + add; 101 double value = g_matrix[col+row*g_cols] * scale + add;
102 if (fabs(m(row,col)-value) > 1.0e-15) { 102 if (fabs(m(row,col)-value) > 1.0e-15) {
103 result = 0; 103 result = 0;
@@ -121,8 +121,8 @@ int check_matrix(const GMatrix&amp; m, const double scale, const double add) @@ -121,8 +121,8 @@ int check_matrix(const GMatrix&amp; m, const double scale, const double add)
121 { 121 {
122 int result = 1; 122 int result = 1;
123 try { 123 try {
124 - for (unsigned row = 0; row < g_rows; ++row) {  
125 - for (unsigned col = 0; col < g_cols; ++col) { 124 + for (int row = 0; row < g_rows; ++row) {
  125 + for (int col = 0; col < g_cols; ++col) {
126 double value = g_matrix[col+row*g_cols] * scale + add; 126 double value = g_matrix[col+row*g_cols] * scale + add;
127 if (m(row,col) != value) { 127 if (m(row,col) != value) {
128 result = 0; 128 result = 0;
@@ -146,8 +146,8 @@ int check_matrix_lt(const GMatrix&amp; m, const double scale, const double add) @@ -146,8 +146,8 @@ int check_matrix_lt(const GMatrix&amp; m, const double scale, const double add)
146 { 146 {
147 int result = 1; 147 int result = 1;
148 try { 148 try {
149 - for (unsigned row = 0; row < g_rows; ++row) {  
150 - for (unsigned col = 0; col < g_cols; ++col) { 149 + for (int row = 0; row < g_rows; ++row) {
  150 + for (int col = 0; col < g_cols; ++col) {
151 double value = (col <= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0; 151 double value = (col <= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0;
152 if (m(row,col) != value) { 152 if (m(row,col) != value) {
153 result = 0; 153 result = 0;
@@ -171,8 +171,8 @@ int check_matrix_ut(const GMatrix&amp; m, const double scale, const double add) @@ -171,8 +171,8 @@ int check_matrix_ut(const GMatrix&amp; m, const double scale, const double add)
171 { 171 {
172 int result = 1; 172 int result = 1;
173 try { 173 try {
174 - for (unsigned row = 0; row < g_rows; ++row) {  
175 - for (unsigned col = 0; col < g_cols; ++col) { 174 + for (int row = 0; row < g_rows; ++row) {
  175 + for (int col = 0; col < g_cols; ++col) {
176 double value = (col >= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0; 176 double value = (col >= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0;
177 if (m(row,col) != value) { 177 if (m(row,col) != value) {
178 result = 0; 178 result = 0;
@@ -196,9 +196,9 @@ int check_matrix_vector(const GVector&amp; v) @@ -196,9 +196,9 @@ int check_matrix_vector(const GVector&amp; v)
196 { 196 {
197 int result = 1; 197 int result = 1;
198 try { 198 try {
199 - for (unsigned row = 0; row < v.size(); ++row) { 199 + for (int row = 0; row < v.size(); ++row) {
200 double value = 0.0; 200 double value = 0.0;
201 - for (unsigned col = 0; col < g_cols; ++col) 201 + for (int col = 0; col < g_cols; ++col)
202 value += g_matrix[col+row*g_cols] * g_vector[col]; 202 value += g_matrix[col+row*g_cols] * g_vector[col];
203 if (v(row) != value) { 203 if (v(row) != value) {
204 result = 0; 204 result = 0;
@@ -223,10 +223,10 @@ int check_matrix_matrix(const GSymMatrix&amp; m) @@ -223,10 +223,10 @@ int check_matrix_matrix(const GSymMatrix&amp; m)
223 return 0; 223 return 0;
224 int result = 1; 224 int result = 1;
225 try { 225 try {
226 - for (unsigned row = 0; row < m.rows(); ++row) {  
227 - for (unsigned col = 0; col < m.cols(); ++col) { 226 + for (int row = 0; row < m.rows(); ++row) {
  227 + for (int col = 0; col < m.cols(); ++col) {
228 double value = 0.0; 228 double value = 0.0;
229 - for (unsigned i = 0; i < g_cols; ++i) 229 + for (int i = 0; i < g_cols; ++i)
230 value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols]; 230 value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols];
231 if (m(row,col) != value) { 231 if (m(row,col) != value) {
232 result = 0; 232 result = 0;
@@ -249,8 +249,8 @@ int check_matrix_matrix(const GSymMatrix&amp; m) @@ -249,8 +249,8 @@ int check_matrix_matrix(const GSymMatrix&amp; m)
249 int check_matrix_min(const double min) 249 int check_matrix_min(const double min)
250 { 250 {
251 double value = g_matrix[0]; 251 double value = g_matrix[0];
252 - for (unsigned row = 0; row < g_rows; ++row) {  
253 - for (unsigned col = 0; col < g_cols; ++col) { 252 + for (int row = 0; row < g_rows; ++row) {
  253 + for (int col = 0; col < g_cols; ++col) {
254 if (g_matrix[col+row*g_cols] < value) 254 if (g_matrix[col+row*g_cols] < value)
255 value = g_matrix[col+row*g_cols]; 255 value = g_matrix[col+row*g_cols];
256 } 256 }
@@ -265,8 +265,8 @@ int check_matrix_min(const double min) @@ -265,8 +265,8 @@ int check_matrix_min(const double min)
265 int check_matrix_max(const double max) 265 int check_matrix_max(const double max)
266 { 266 {
267 double value = g_matrix[0]; 267 double value = g_matrix[0];
268 - for (unsigned row = 0; row < g_rows; ++row) {  
269 - for (unsigned col = 0; col < g_cols; ++col) { 268 + for (int row = 0; row < g_rows; ++row) {
  269 + for (int col = 0; col < g_cols; ++col) {
270 if (g_matrix[col+row*g_cols] > value) 270 if (g_matrix[col+row*g_cols] > value)
271 value = g_matrix[col+row*g_cols]; 271 value = g_matrix[col+row*g_cols];
272 } 272 }
@@ -281,8 +281,8 @@ int check_matrix_max(const double max) @@ -281,8 +281,8 @@ int check_matrix_max(const double max)
281 int check_matrix_sum(const double sum) 281 int check_matrix_sum(const double sum)
282 { 282 {
283 double value = 0.0; 283 double value = 0.0;
284 - for (unsigned row = 0; row < g_rows; ++row) {  
285 - for (unsigned col = 0; col < g_cols; ++col) 284 + for (int row = 0; row < g_rows; ++row) {
  285 + for (int col = 0; col < g_cols; ++col)
286 value += g_matrix[col+row*g_cols]; 286 value += g_matrix[col+row*g_cols];
287 } 287 }
288 return (sum == value); 288 return (sum == value);
@@ -928,4 +928,7 @@ int main(void) @@ -928,4 +928,7 @@ int main(void)
928 } 928 }
929 cout << "ok." << endl; 929 cout << "ok." << endl;
930 930
  931 + // Return
  932 + return 0;
  933 +
931 } 934 }
test/test_GVector.cpp
@@ -25,18 +25,18 @@ int main(void) @@ -25,18 +25,18 @@ int main(void)
25 cout << "*************************" << endl; 25 cout << "*************************" << endl;
26 26
27 // Set parameters 27 // Set parameters
28 - unsigned num = 5; 28 + int num = 5;
29 29
30 // Define vectors 30 // Define vectors
31 GVector test(num); 31 GVector test(num);
32 GVector result(num); 32 GVector result(num);
33 GVector smaller(num+1); 33 GVector smaller(num+1);
34 GVector bigger(num+1); 34 GVector bigger(num+1);
35 - for (unsigned i = 0; i < num; ++i) 35 + for (int i = 0; i < num; ++i)
36 test(i) = (i+1) * 1.1; 36 test(i) = (i+1) * 1.1;
37 - for (unsigned i = 0; i < num-1; ++i) 37 + for (int i = 0; i < num-1; ++i)
38 smaller(i) = (i+1) * 1.1; 38 smaller(i) = (i+1) * 1.1;
39 - for (unsigned i = 0; i < num+1; ++i) 39 + for (int i = 0; i < num+1; ++i)
40 bigger(i) = (i+1) * 1.1; 40 bigger(i) = (i+1) * 1.1;
41 41
42 // Test 1: Allocate zero vector 42 // Test 1: Allocate zero vector
@@ -329,4 +329,7 @@ int main(void) @@ -329,4 +329,7 @@ int main(void)
329 cout << e.what() << endl; 329 cout << e.what() << endl;
330 } 330 }
331 331
  332 +
  333 + // Return
  334 + return 0;
332 } 335 }