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 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 3 \ No newline at end of file
... ...
src/GMatrix.cpp
... ... @@ -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 113 = GMatrix constructors/destructors =
24 114 = =
25 115 ==========================================================================*/
... ... @@ -30,17 +120,8 @@ using namespace std;
30 120 GMatrix::GMatrix(void)
31 121 {
32 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 125 // Return
45 126 return;
46 127 }
... ... @@ -52,16 +133,7 @@ GMatrix::GMatrix(void)
52 133 GMatrix::GMatrix(int rows, int cols)
53 134 {
54 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 138 // Determine number of elements to store in matrix
67 139 int elements = rows*cols;
... ... @@ -106,59 +178,11 @@ GMatrix::GMatrix(int rows, int cols)
106 178 GMatrix::GMatrix(const GMatrix& m)
107 179 {
108 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 186 // Return
163 187 return;
164 188 }
... ... @@ -169,11 +193,8 @@ GMatrix::GMatrix(const GMatrix&amp; m)
169 193 ***************************************************************************/
170 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 199 // Return
179 200 return;
... ... @@ -193,66 +214,15 @@ GMatrix&amp; GMatrix::operator= (const GMatrix&amp; m)
193 214 {
194 215 // Execute only if object is not identical
195 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 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 227 } // endif: object was not identical
258 228  
... ...
src/GMatrix.hpp
... ... @@ -137,6 +137,9 @@ protected:
137 137 GMatrix();
138 138  
139 139 // Private member functions
  140 + void init_members(void);
  141 + void copy_members(const GMatrix& m);
  142 + void free_members(void);
140 143 void select_non_zero(void);
141 144  
142 145 // Private data area
... ...
src/GSparseMatrix.cpp
... ... @@ -17,7 +17,7 @@
17 17 * m_rowinx : holds the row indices for all elements (Ai) *
18 18 * Column 'col' covers therefore [m_colstart[j], ..., m_colstart[j+1]-1] *
19 19 * Note that 'm_colstart' has m_cols+1 elements. *
20   -/***************************************************************************
  20 + ***************************************************************************/
21 21  
22 22 /* __ Includes ___________________________________________________________ */
23 23 #include "GSparseMatrix.hpp"
... ... @@ -27,31 +27,26 @@
27 27 /* __ Namespaces _________________________________________________________ */
28 28 using namespace std;
29 29  
30   -/* __ Definitions ________________________________________________________ */
  30 +/* __ Debug definitions __________________________________________________ */
31 31 //#define G_DEBUG_SPARSE_PENDING // Analyse pending values
32 32 //#define G_DEBUG_SPARSE_INSERTION // Analyse value insertion
33 33 //#define G_DEBUG_SPARSE_COMPRESSION // Analyse zero row/column compression
34 34 //#define G_DEBUG_SPARSE_MALLOC // Analyse memory management
  35 +//#define G_DEBUG_SPARSE_STACK_PUSH // Analyse stack column pushing
  36 +//#define G_DEBUG_SPARSE_STACK_FLUSH // Analyse stack column flushing
  37 +
  38 +/* __ Definitions ________________________________________________________ */
35 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 50 m_rowinx = NULL;
56 51 m_mem_block = G_SPARSE_MATRIX_DEFAULT_MEM_BLOCK;
57 52 m_zero = 0.0;
... ... @@ -60,7 +55,106 @@ GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix()
60 55 m_fill_col = 0;
61 56 m_symbolic = NULL;
62 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 158 // Allocate column start array. This is the only array that we can
65 159 // allocate at this time. The other arrays can only be allocated during
66 160 // filling of the matrix
... ... @@ -96,44 +190,11 @@ GSparseMatrix::GSparseMatrix(int rows, int cols, int elements) : GMatrix()
96 190 GSparseMatrix::GSparseMatrix(const GSparseMatrix& m) : GMatrix(m)
97 191 {
98 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 198 // Return
138 199 return;
139 200 }
... ... @@ -147,10 +208,8 @@ GSparseMatrix::GSparseMatrix(const GSparseMatrix&amp; m) : GMatrix(m)
147 208 ***************************************************************************/
148 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 214 // Return
156 215 return;
... ... @@ -174,50 +233,14 @@ GSparseMatrix&amp; GSparseMatrix::operator= (const GSparseMatrix&amp; m)
174 233 // Invoque base class assignment operator
175 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 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 245 } // endif: object was not identical
223 246  
... ... @@ -742,22 +765,40 @@ void GSparseMatrix::insert_col(const GVector&amp; v, int col)
742 765 ***************************************************************************/
743 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 798 // Extract vector for column, add elements, and re-insert vector (only if
758 799 // vector to insert has non-zeros)
759   - if (v.non_zeros() > 0) {
760   -
  800 + if (non_zero > 0) {
  801 +
761 802 // Copy input vector
762 803 GVector column = v;
763 804  
... ... @@ -771,9 +812,10 @@ void GSparseMatrix::add_col(const GVector&amp; v, int col)
771 812  
772 813 // Insert vector into matrix
773 814 insert_col(column, col);
  815 +
774 816  
775 817 }
776   -
  818 +
777 819 // Return
778 820 return;
779 821 }
... ... @@ -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 1565 = GSparseMatrix private functions =
... ...
src/GSparseMatrix.hpp
... ... @@ -24,6 +24,8 @@ using namespace std;
24 24  
25 25 /* __ Definitions ________________________________________________________ */
26 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 30 /* __ Macros (to be moved to GammaLib general header) ____________________ */
29 31 #define G_MIN(a,b) (((a) < (b)) ? (a) : (b))
... ... @@ -104,25 +106,43 @@ public:
104 106 virtual void cholesky_decompose(int compress = 1);
105 107 virtual GVector cholesky_solver(const GVector& v, int compress = 1);
106 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 116 private:
109 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 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 225 {
206 226 fill_pending();
207 227 this->GMatrix::operator*=(d);
  228 + return *this;
208 229 }
209 230  
210 231 // Unary scalar division
... ... @@ -213,6 +234,7 @@ GSparseMatrix&amp; GSparseMatrix::operator/= (const double&amp; d)
213 234 {
214 235 fill_pending();
215 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 488 #endif
489 489  
490 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 493 // Debug
494 494 #if defined(G_DEBUG_SPARSE_SYM_AMD_ORDERING)
... ...
src/GSymMatrix.cpp
... ... @@ -389,6 +389,7 @@ void GSymMatrix::cholesky_decompose(int compress)
389 389 if (no_zeros) {
390 390  
391 391 // Loop over upper triangle (col >= row)
  392 + double diag = 0.0;
392 393 for (int row = 0; row < m_rows; ++row) {
393 394 double* ptr = m_data + m_colstart[row];
394 395 for (int col = row; col < m_cols; ++col, ++ptr) {
... ... @@ -397,7 +398,6 @@ void GSymMatrix::cholesky_decompose(int compress)
397 398 int offset = m_colstart[k] - k; // is always positive
398 399 sum -= m_data[offset+row] * m_data[offset+col]; // sum -= M(row,k)*M(col,k)
399 400 }
400   - double diag;
401 401 if (row == col) {
402 402 if (sum <= 0.0)
403 403 throw matrix_not_pos_definite("GSymMatrix::cholesky_decompose(int)",
... ... @@ -423,6 +423,7 @@ void GSymMatrix::cholesky_decompose(int compress)
423 423 int* k_ptr;
424 424  
425 425 // Loop over upper triangle (col >= row)
  426 + double diag = 0.0;
426 427 for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) {
427 428 double* ptr_0 = m_data + m_colstart[*row_ptr] - *row_ptr;
428 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 433 int offset = m_colstart[*k_ptr] - *k_ptr; // is always positive
433 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 436 if (*row_ptr == *col_ptr) {
437 437 if (sum <= 0.0)
438 438 throw matrix_not_pos_definite("GSymMatrix::cholesky_decompose(int)",
... ...
src/GSymMatrix.hpp
... ... @@ -159,6 +159,7 @@ inline
159 159 GSymMatrix& GSymMatrix::operator*= (const double& d)
160 160 {
161 161 this->GMatrix::operator*=(d);
  162 + return *this;
162 163 }
163 164  
164 165 // Unary scalar division
... ... @@ -166,6 +167,7 @@ inline
166 167 GSymMatrix& GSymMatrix::operator/= (const double& d)
167 168 {
168 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 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 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 183 test_GSymMatrix_LDADD = ../src/libgamma.a
184 184 test_GSparseMatrix_SOURCES = test_GSparseMatrix.cpp
185 185 #test_GSparseMatrix_LDADD = ../src/libgamma.la
186   -test_GSparseMatrix_LDADD = ../src/libgamma.a
  186 +test_GSparseMatrix_LDADD = ../src/libgamma.a -lc_p
187 187 all: all-am
188 188  
189 189 .SUFFIXES:
... ...
test/test_GMatrix.cpp
... ... @@ -22,8 +22,8 @@ double g_matrix[] = {1.0, 2.0, 3.0, 4.0,
22 22 5.0, 6.0, 7.0, 8.0,
23 23 9.0, 10., 11., 12.};
24 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 33 {
34 34 try {
35 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 38 matrix(row,col) = g_matrix[col+row*g_cols];
39 39 }
40 40 return matrix;
... ... @@ -53,7 +53,7 @@ GVector set_vector(void)
53 53 {
54 54 try {
55 55 GVector vector(g_cols);
56   - for (unsigned col = 0; col < g_cols; ++col)
  56 + for (int col = 0; col < g_cols; ++col)
57 57 vector(col) = g_vector[col];
58 58 return vector;
59 59 }
... ... @@ -71,8 +71,8 @@ int check_matrix(const GMatrix&amp; m, const double scale, const double add)
71 71 {
72 72 int result = 1;
73 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 76 double value = g_matrix[col+row*g_cols] * scale + add;
77 77 if (fabs(m(row,col)-value) > 1.0e-15) {
78 78 result = 0;
... ... @@ -96,8 +96,8 @@ int check_transpose_matrix(const GMatrix&amp; m, const double scale, const double ad
96 96 {
97 97 int result = 1;
98 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 101 double value = g_matrix[col+row*g_cols] * scale + add;
102 102 if (m(col,row) != value) {
103 103 result = 0;
... ... @@ -121,8 +121,8 @@ int check_matrix_lt(const GMatrix&amp; m, const double scale, const double add)
121 121 {
122 122 int result = 1;
123 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 126 double value = (col <= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0;
127 127 if (m(row,col) != value) {
128 128 result = 0;
... ... @@ -146,8 +146,8 @@ int check_matrix_ut(const GMatrix&amp; m, const double scale, const double add)
146 146 {
147 147 int result = 1;
148 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 151 double value = (col >= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0;
152 152 if (m(row,col) != value) {
153 153 result = 0;
... ... @@ -171,9 +171,9 @@ int check_matrix_vector(const GVector&amp; v)
171 171 {
172 172 int result = 1;
173 173 try {
174   - for (unsigned row = 0; row < v.size(); ++row) {
  174 + for (int row = 0; row < v.size(); ++row) {
175 175 double value = 0.0;
176   - for (unsigned col = 0; col < g_cols; ++col)
  176 + for (int col = 0; col < g_cols; ++col)
177 177 value += g_matrix[col+row*g_cols] * g_vector[col];
178 178 if (v(row) != value) {
179 179 result = 0;
... ... @@ -198,10 +198,10 @@ int check_matrix_matrix(const GMatrix&amp; m)
198 198 return 0;
199 199 int result = 1;
200 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 203 double value = 0.0;
204   - for (unsigned i = 0; i < g_cols; ++i)
  204 + for (int i = 0; i < g_cols; ++i)
205 205 value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols];
206 206 if (m(row,col) != value) {
207 207 result = 0;
... ... @@ -224,8 +224,8 @@ int check_matrix_matrix(const GMatrix&amp; m)
224 224 int check_matrix_min(const double min)
225 225 {
226 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 229 if (g_matrix[col+row*g_cols] < value)
230 230 value = g_matrix[col+row*g_cols];
231 231 }
... ... @@ -240,8 +240,8 @@ int check_matrix_min(const double min)
240 240 int check_matrix_max(const double max)
241 241 {
242 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 245 if (g_matrix[col+row*g_cols] > value)
246 246 value = g_matrix[col+row*g_cols];
247 247 }
... ... @@ -256,8 +256,8 @@ int check_matrix_max(const double max)
256 256 int check_matrix_sum(const double sum)
257 257 {
258 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 261 value += g_matrix[col+row*g_cols];
262 262 }
263 263 return (sum == value);
... ... @@ -674,4 +674,6 @@ int main(void)
674 674 }
675 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 23  
24 24 /* __ Globals ____________________________________________________________ */
25 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 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 38 {
39 39 try {
40 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 42 matrix(g_row[i],g_col[i]) = g_matrix[i];
43 43 return matrix;
44 44 }
... ... @@ -56,7 +56,7 @@ GVector set_vector(void)
56 56 {
57 57 try {
58 58 GVector vector(g_cols);
59   - for (unsigned col = 0; col < g_cols; ++col)
  59 + for (int col = 0; col < g_cols; ++col)
60 60 vector(col) = g_vector[col];
61 61 return vector;
62 62 }
... ... @@ -74,9 +74,9 @@ int check_matrix(const GSparseMatrix&amp; m, const double scale, const double add)
74 74 {
75 75 int result = 1;
76 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 80 double ref_value = add;
81 81 for (i = 0; i < g_elements; ++i) {
82 82 if (g_row[i] == row && g_col[i] == col) {
... ... @@ -107,10 +107,10 @@ int check_matrix_vector(const GVector&amp; v)
107 107 {
108 108 int result = 1;
109 109 try {
110   - for (unsigned row = 0; row < v.size(); ++row) {
  110 + for (int row = 0; row < v.size(); ++row) {
111 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 114 double ref_value = 0.0;
115 115 for (i = 0; i < g_elements; ++i) {
116 116 if (g_row[i] == row && g_col[i] == col) {
... ... @@ -143,11 +143,11 @@ int check_matrix_matrix(const GSparseMatrix&amp; m)
143 143 return 0;
144 144 int result = 1;
145 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 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 151 double ref_value_1 = 0.0;
152 152 double ref_value_2 = 0.0;
153 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 187 {
188 188 int result = 1;
189 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 193 double ref_value = 0.0;
194 194 for (i = 0; i < g_elements; ++i) {
195 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 218 int check_matrix_min(const double min)
219 219 {
220 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 222 if (g_matrix[i] < value)
223 223 value = g_matrix[i];
224 224 }
... ... @@ -233,7 +233,7 @@ int check_matrix_min(const double min)
233 233 int check_matrix_max(const double max)
234 234 {
235 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 237 if (g_matrix[i] > value)
238 238 value = g_matrix[i];
239 239 }
... ... @@ -247,7 +247,7 @@ int check_matrix_max(const double max)
247 247 int check_matrix_sum(const double sum)
248 248 {
249 249 double value = 0.0;
250   - for (unsigned i = 0; i < g_elements; ++i)
  250 + for (int i = 0; i < g_elements; ++i)
251 251 value += g_matrix[i];
252 252 return (sum == value);
253 253 }
... ... @@ -375,7 +375,31 @@ void test_assign_values(const GSparseMatrix&amp; m_test)
375 375 throw;
376 376 }
377 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 403 cout << " ok." << endl;
380 404 }
381 405  
... ... @@ -1346,16 +1370,18 @@ void test_heavy(int block = 512)
1346 1370 clock_t t_start;
1347 1371 double t_elapse;
1348 1372 int number;
  1373 + int num_cols;
  1374 + int i_min, i_max;
1349 1375  
1350 1376 // Perform test
1351 1377 cout << "Test GSparseMatrix: Heavy calculus: ";
1352 1378 try {
1353 1379 //
1354 1380 // Fill 10000 x 10000 matrix with 10000 values
  1381 + t_start = clock();
1355 1382 number = 10000;
1356 1383 GSparseMatrix large(number,number);
1357 1384 large.set_mem_block(block);
1358   - t_start = clock();
1359 1385 for (int i = 0; i < number; ++i)
1360 1386 large(i,i) = (i+1)*3.14;
1361 1387 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
... ... @@ -1375,32 +1401,67 @@ void test_heavy(int block = 512)
1375 1401 #endif
1376 1402 //
1377 1403 // Insert columns into 10000 x 10000 matrix
1378   - number = 10000;
  1404 + number = 10000;
  1405 + num_cols = 1000;
1379 1406 large.clear();
1380 1407 large.set_mem_block(block);
  1408 + for (int j = 200; j < 400; ++j)
  1409 + large(j,j) = 3.14;
1381 1410 GVector column(number);
1382 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 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 1418 large.add_col(column, j);
1388 1419 }
1389 1420 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
1390 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 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 1456 // Subsequent addition and subtractions
1396 1457 number = 300;
  1458 + t_start = clock();
1397 1459 GSparseMatrix sum(number,number);
1398 1460 GSparseMatrix add(number,number);
1399 1461 GSparseMatrix sub(number,number);
1400 1462 sum.set_mem_block(block);
1401 1463 add.set_mem_block(block);
1402 1464 sub.set_mem_block(block);
1403   - t_start = clock();
1404 1465 for (int i = 0; i < number; ++i) {
1405 1466 add(i,number-i-1) = (i*i+1)*0.01;
1406 1467 sum += add;
... ... @@ -1425,7 +1486,7 @@ void test_heavy(int block = 512)
1425 1486 t_elapse = double(clock() - t_start)/double(CLOCKS_PER_SEC);
1426 1487 #if defined(DUMP_TIMING)
1427 1488 cout << endl << " - Matrix multiplication 1 times " << t_elapse <<
1428   - " sec (reference ~ 3.5 sec)";
  1489 + " sec (reference ~ 3.1 sec)";
1429 1490 #endif
1430 1491 }
1431 1492 catch (exception &e) {
... ...
test/test_GSymMatrix.cpp
... ... @@ -18,10 +18,10 @@
18 18 using namespace std;
19 19  
20 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 31 {
32 32 try {
33 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 36 matrix(row,col) = g_matrix[col+row*g_cols];
37 37 }
38 38 return matrix;
... ... @@ -51,11 +51,11 @@ GSymMatrix set_matrix_zero(void)
51 51 {
52 52 try {
53 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 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 59 if (col == 2) continue;
60 60 matrix(row,col) = g_matrix[j+i*g_cols];
61 61 j++;
... ... @@ -78,7 +78,7 @@ GVector set_vector(void)
78 78 {
79 79 try {
80 80 GVector vector(g_cols);
81   - for (unsigned col = 0; col < g_cols; ++col)
  81 + for (int col = 0; col < g_cols; ++col)
82 82 vector(col) = g_vector[col];
83 83 return vector;
84 84 }
... ... @@ -96,8 +96,8 @@ int check_matrix(const GSymMatrix&amp; m, const double scale, const double add)
96 96 {
97 97 int result = 1;
98 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 101 double value = g_matrix[col+row*g_cols] * scale + add;
102 102 if (fabs(m(row,col)-value) > 1.0e-15) {
103 103 result = 0;
... ... @@ -121,8 +121,8 @@ int check_matrix(const GMatrix&amp; m, const double scale, const double add)
121 121 {
122 122 int result = 1;
123 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 126 double value = g_matrix[col+row*g_cols] * scale + add;
127 127 if (m(row,col) != value) {
128 128 result = 0;
... ... @@ -146,8 +146,8 @@ int check_matrix_lt(const GMatrix&amp; m, const double scale, const double add)
146 146 {
147 147 int result = 1;
148 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 151 double value = (col <= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0;
152 152 if (m(row,col) != value) {
153 153 result = 0;
... ... @@ -171,8 +171,8 @@ int check_matrix_ut(const GMatrix&amp; m, const double scale, const double add)
171 171 {
172 172 int result = 1;
173 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 176 double value = (col >= row) ? g_matrix[col+row*g_cols] * scale + add : 0.0;
177 177 if (m(row,col) != value) {
178 178 result = 0;
... ... @@ -196,9 +196,9 @@ int check_matrix_vector(const GVector&amp; v)
196 196 {
197 197 int result = 1;
198 198 try {
199   - for (unsigned row = 0; row < v.size(); ++row) {
  199 + for (int row = 0; row < v.size(); ++row) {
200 200 double value = 0.0;
201   - for (unsigned col = 0; col < g_cols; ++col)
  201 + for (int col = 0; col < g_cols; ++col)
202 202 value += g_matrix[col+row*g_cols] * g_vector[col];
203 203 if (v(row) != value) {
204 204 result = 0;
... ... @@ -223,10 +223,10 @@ int check_matrix_matrix(const GSymMatrix&amp; m)
223 223 return 0;
224 224 int result = 1;
225 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 228 double value = 0.0;
229   - for (unsigned i = 0; i < g_cols; ++i)
  229 + for (int i = 0; i < g_cols; ++i)
230 230 value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols];
231 231 if (m(row,col) != value) {
232 232 result = 0;
... ... @@ -249,8 +249,8 @@ int check_matrix_matrix(const GSymMatrix&amp; m)
249 249 int check_matrix_min(const double min)
250 250 {
251 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 254 if (g_matrix[col+row*g_cols] < value)
255 255 value = g_matrix[col+row*g_cols];
256 256 }
... ... @@ -265,8 +265,8 @@ int check_matrix_min(const double min)
265 265 int check_matrix_max(const double max)
266 266 {
267 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 270 if (g_matrix[col+row*g_cols] > value)
271 271 value = g_matrix[col+row*g_cols];
272 272 }
... ... @@ -281,8 +281,8 @@ int check_matrix_max(const double max)
281 281 int check_matrix_sum(const double sum)
282 282 {
283 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 286 value += g_matrix[col+row*g_cols];
287 287 }
288 288 return (sum == value);
... ... @@ -928,4 +928,7 @@ int main(void)
928 928 }
929 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 25 cout << "*************************" << endl;
26 26  
27 27 // Set parameters
28   - unsigned num = 5;
  28 + int num = 5;
29 29  
30 30 // Define vectors
31 31 GVector test(num);
32 32 GVector result(num);
33 33 GVector smaller(num+1);
34 34 GVector bigger(num+1);
35   - for (unsigned i = 0; i < num; ++i)
  35 + for (int i = 0; i < num; ++i)
36 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 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 40 bigger(i) = (i+1) * 1.1;
41 41  
42 42 // Test 1: Allocate zero vector
... ... @@ -329,4 +329,7 @@ int main(void)
329 329 cout << e.what() << endl;
330 330 }
331 331  
  332 +
  333 + // Return
  334 + return 0;
332 335 }
... ...