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