/*************************************************************************** * GMatrix.cpp - General matrix class * * ----------------------------------------------------------------------- * * copyright (C) 2006-2017 by Juergen Knoedlseder * * ----------------------------------------------------------------------- * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ***************************************************************************/ /** * @file GMatrix.cpp * @brief General matrix class implementation * @author Juergen Knoedlseder */ /* __ Includes ___________________________________________________________ */ #ifdef HAVE_CONFIG_H #include #endif #include #include "GException.hpp" #include "GTools.hpp" #include "GMath.hpp" #include "GVector.hpp" #include "GMatrix.hpp" #include "GMatrixSparse.hpp" #include "GMatrixSymmetric.hpp" /* __ Method name definitions ____________________________________________ */ #define G_CONSTRUCTOR "GMatrix::GMatrix(int&, int&)" #define G_OP_MUL_VEC "GMatrix::operator*(GVector&)" #define G_OP_ADD "GMatrix::operator+=(GMatrix&)" #define G_OP_SUB "GMatrix::operator-=(GMatrix&)" #define G_OP_MAT_MUL "GMatrix::operator*=(GMatrix&)" #define G_AT "GMatrix::at(int&, int&)" #define G_EXTRACT_ROW "GMatrix::row(int&)" #define G_SET_ROW "GMatrix::row(int&, GVector&)" #define G_EXTRACT_COLUMN "GMatrix::column(int&)" #define G_SET_COLUMN "GMatrix::column(int&, GVector&)" #define G_ADD_TO_ROW "GMatrix::add_to_row(int&, GVector&)" #define G_ADD_TO_COLUMN "GMatrix::add_to_column(int&, GVector&)" #define G_INVERT "GMatrix::invert()" #define G_SOLVE "GMatrix::solve(GVector&)" #define G_EXTRACT_LOWER "GMatrix::extract_lower_triangle()" #define G_EXTRACT_UPPER "GMatrix::extract_upper_triangle()" /*========================================================================== = = = Constructors/destructors = = = ==========================================================================*/ /***********************************************************************//** * @brief Void matrix constructor * * Constructs an empty matrix (i.e. a matrix without any elements; the number * of rows and columns of the matrix will be zero). * * @todo Verify that the class is save against empty matrix objects. ***************************************************************************/ GMatrix::GMatrix(void) : GMatrixBase() { // Initialise class members init_members(); // Return return; } /***********************************************************************//** * @brief Matrix constructor * * @param[in] rows Number of rows [>0]. * @param[in] columns Number of columns [>0]. * * @exception GException::empty * Specified number of rows or columns is not valid. * * Constructs a matrix with the specified number of @p rows and @p columns. * The memory for all matrix elements will be allocated and all matrix * elements will be initialized to 0. ***************************************************************************/ GMatrix::GMatrix(const int& rows, const int& columns) : GMatrixBase() { // Continue only if matrix is valid if (rows > 0 && columns > 0) { // Initialise class members for clean destruction init_members(); // Allocate matrix memory alloc_members(rows, columns); } else { throw GException::empty(G_CONSTRUCTOR); } // Return return; } /***********************************************************************//** * @brief Copy constructor * * @param[in] matrix Matrix. ***************************************************************************/ GMatrix::GMatrix(const GMatrix& matrix) : GMatrixBase(matrix) { // Initialise class members for clean destruction init_members(); // Copy members copy_members(matrix); // Return return; } /***********************************************************************//** * @brief GMatrixSymmetric to GMatrix storage class convertor * * @param[in] matrix Symmetric matrix (GMatrixSymmetric). * * Constructs a GMatrix object from a symmetric matrix object of type * GMatrixSymmetric. Since the result is a generic matrix, the constructor * will succeed in all cases. ***************************************************************************/ GMatrix::GMatrix(const GMatrixSymmetric& matrix) : GMatrixBase(matrix) { // Initialise class members for clean destruction init_members(); // Allocate matrix memory alloc_members(matrix.rows(), matrix.columns()); // Fill matrix. We benefit here from the symmetry of the matrix and // loop only over the lower triangle of the symmetric matrix to perform // the fill. for (int col = 0; col < m_cols; ++col) { for (int row = col; row < m_rows; ++row) { double value = matrix(row, col); (*this)(row, col) = value; (*this)(col, row) = value; } } // Return return; } /***********************************************************************//** * @brief GMatrixSparse to GMatrix storage class convertor * * @param[in] matrix Sparse matrix (GMatrixSparse). * * Constructs a GMatrix object from a sparse matrix object of type * GMatrixSparse. Since the result is a generic matrix, the constructor * will succeed in all cases. ***************************************************************************/ GMatrix::GMatrix(const GMatrixSparse& matrix) : GMatrixBase(matrix) { // Initialise class members for clean destruction init_members(); // Construct matrix alloc_members(matrix.rows(), matrix.columns()); // Fill matrix for (int col = 0; col < m_cols; ++col) { for (int row = 0; row < m_rows; ++row) { (*this)(row, col) = matrix(row, col); } } // Return return; } /***********************************************************************//** * @brief Destructor ***************************************************************************/ GMatrix::~GMatrix(void) { // Free members free_members(); // Return return; } /*========================================================================== = = = Operators = = = ==========================================================================*/ /***********************************************************************//** * @brief Matrix assignment operator * * @param[in] matrix Matrix. * @return Matrix. * * Assigns the content of another matrix to the actual matrix instance. ***************************************************************************/ GMatrix& GMatrix::operator=(const GMatrix& matrix) { // Execute only if object is not identical if (this != &matrix) { // Assign base class members. Note that this method will also perform // the allocation of the matrix memory and the copy of the matrix // attributes. this->GMatrixBase::operator=(matrix); // Free derived class members free_members(); // Initialise derived class members init_members(); // Copy derived class members copy_members(matrix); } // endif: object was not identical // Return this object return *this; } /***********************************************************************//** * @brief Value assignment operator * * @param[in] value Value. * @return Matrix. * * Assigns the specified @p value to all elements of the matrix. ***************************************************************************/ GMatrix& GMatrix::operator=(const double& value) { // Assign value double* ptr = m_data; for (int i = 0; i < m_elements; ++i) { *ptr++ = value; } // Return this object return *this; } /***********************************************************************//** * @brief Vector multiplication * * @param[in] vector Vector. * * @exception GException::matrix_vector_mismatch * Vector length differs from number of columns in matrix. * * This method performs a vector multiplication of a matrix. The vector * multiplication will produce a vector. The matrix multiplication can only * be performed when the number of matrix columns is identical to the length * of the vector. ***************************************************************************/ GVector GMatrix::operator*(const GVector& vector) const { // Raise an exception if the matrix and vector dimensions are not compatible if (m_cols != vector.size()) { throw GException::matrix_vector_mismatch(G_OP_MUL_VEC, vector.size(), m_rows, m_cols); } // Perform vector multiplication GVector result(m_rows); for (int row = 0; row < m_rows; ++row) { double sum = 0.0; const double* src = m_data + row; for (int col = 0; col < m_cols; ++col, src += m_rows) { sum += *src * vector[col]; } result[row] = sum; } // Return result return result; } /***********************************************************************//** * @brief Negate matrix elements * * @return Matrix with negated elements. * * Returns a matrix where each element has been replaced by its negative * element. ***************************************************************************/ GMatrix GMatrix::operator-(void) const { // Copy matrix GMatrix matrix = *this; // Take the absolute value of all matrix elements double* ptr = matrix.m_data; for (int i = 0; i < matrix.m_elements; ++i, ++ptr) { *ptr = -(*ptr); } // Return matrix return matrix; } /***********************************************************************//** * @brief Unary matrix addition operator * * @param[in] matrix Matrix. * * @exception GException::matrix_mismatch * Incompatible matrix size. * * This method performs a matrix addition. The operation can only succeed * when the dimensions of both matrices are identical. ***************************************************************************/ GMatrix& GMatrix::operator+=(const GMatrix& matrix) { // Raise an exception if the matrix dimensions are not compatible if (m_rows != matrix.m_rows || m_cols != matrix.m_cols) { throw GException::matrix_mismatch(G_OP_ADD, m_rows, m_cols, matrix.m_rows, matrix.m_cols); } // Add all matrix elements const double* src = matrix.m_data; double* dst = m_data; for (int i = 0; i < m_elements; ++i) { *dst++ += *src++; } // Return result return *this; } /***********************************************************************//** * @brief Unary matrix scalar addition operator * * @param[in] scalar Scalar. * * Adds a @p scalar to each matrix element. ***************************************************************************/ GMatrix& GMatrix::operator+=(const double& scalar) { // Add all matrix elements double* dst = m_data; for (int i = 0; i < m_elements; ++i) { *dst++ += scalar; } // Return result return *this; } /***********************************************************************//** * @brief Unary matrix subtraction operator * * @param[in] matrix Matrix. * * @exception GException::matrix_mismatch * Incompatible matrix size. * * This method performs a matrix addition. The operation can only succeed * when the dimensions of both matrices are identical. ***************************************************************************/ GMatrix& GMatrix::operator-=(const GMatrix& matrix) { // Raise an exception if the matrix dimensions are not compatible if (m_rows != matrix.m_rows || m_cols != matrix.m_cols) { throw GException::matrix_mismatch(G_OP_SUB, m_rows, m_cols, matrix.m_rows, matrix.m_cols); } // Subtract all matrix elements const double* src = matrix.m_data; double* dst = m_data; for (int i = 0; i < m_elements; ++i) { *dst++ -= *src++; } // Return result return *this; } /***********************************************************************//** * @brief Unary matrix scalar subtraction operator * * @param[in] scalar Scalar. * * Subtracts a @p scalar from each matrix element. ***************************************************************************/ GMatrix& GMatrix::operator-=(const double& scalar) { // Add all matrix elements double* dst = m_data; for (int i = 0; i < m_elements; ++i) { *dst++ -= scalar; } // Return result return *this; } /***********************************************************************//** * @brief Unary matrix multiplication operator * * @param[in] matrix Matrix. * * @exception GException::matrix_mismatch * Incompatible matrix size. * * This method performs a matrix multiplication. The operation can only * succeed when the dimensions of both matrices are compatible. * * In case of rectangular matrices the result matrix does not change and * the operation is performed inplace. For the general case the result * matrix changes in size and for simplicity a new matrix is allocated to * hold the result. ***************************************************************************/ GMatrix& GMatrix::operator*=(const GMatrix& matrix) { // Raise an exception if the matrix dimensions are not compatible if (m_cols != matrix.m_rows) { throw GException::matrix_mismatch(G_OP_MAT_MUL, m_rows, m_cols, matrix.m_rows, matrix.m_cols); } // Case A: Matrices are rectangular, so perform 'inplace' multiplication if (m_rows == m_cols) { for (int row = 0; row < m_rows; ++row) { GVector v_row = this->row(row); for (int col = 0; col < m_cols; ++col) { double sum = 0.0; for (int i = 0; i < m_cols; ++i) { sum += v_row[i] * matrix(i,col); } (*this)(row,col) = sum; } } } // Case B: Matrices are not rectangular, so we cannot work inplace else { // Allocate result matrix GMatrix result(m_rows, matrix.m_cols); // Loop over all elements of result matrix for (int row = 0; row < m_rows; ++row) { for (int col = 0; col < matrix.m_cols; ++col) { double sum = 0.0; for (int i = 0; i < m_cols; ++i) { sum += (*this)(row,i) * matrix(i,col); } result(row,col) = sum; } } // Assign result *this = result; } // endelse: matrices were not rectangular // Return result return *this; } /*========================================================================== = = = Public methods = = = ==========================================================================*/ /***********************************************************************//** * @brief Clear matrix ***************************************************************************/ void GMatrix::clear(void) { // Free members free_members(); // Initialise private members init_members(); // Return return; } /***********************************************************************//** * @brief Clone matrix * * @return Pointer to deep copy of matrix. ***************************************************************************/ GMatrix* GMatrix::clone(void) const { // Clone matrix return new GMatrix(*this); } /***********************************************************************//** * @brief Return reference to matrix element * * @param[in] row Matrix row [0,...,rows()-1]. * @param[in] column Matrix column [0,...,columns()-1]. * @return Reference to matrix element. * * @exception GException::out_of_range * Row or column index out of range. * * Returns a reference to the matrix element at @p row and @p column. * Verifies the validity of the @p row and @p column argument. ***************************************************************************/ double& GMatrix::at(const int& row, const int& column) { // Raise exception if row or column index is out of range if (row < 0 || row >= m_rows || column < 0 || column >= m_cols) { throw GException::out_of_range(G_AT, row, column, m_rows, m_cols); } // Return element return (m_data[m_colstart[column]+row]); } /***********************************************************************//** * @brief Return reference to matrix element (const version) * * @param[in] row Matrix row [0,...,rows()-1]. * @param[in] column Matrix column [0,...,columns()-1]. * @return Const reference to matrix element. * * @exception GException::out_of_range * Row or column index out of range. * * Returns a const reference to the matrix element at @p row and @p column. * Verifies the validity of the @p row and @p column argument. ***************************************************************************/ const double& GMatrix::at(const int& row, const int& column) const { // Raise exception if row or column index is out of range if (row < 0 || row >= m_rows || column < 0 || column >= m_cols) { throw GException::out_of_range(G_AT, row, column, m_rows, m_cols); } // Return element return (m_data[m_colstart[column]+row]); } /***********************************************************************//** * @brief Extract row as vector from matrix * * @param[in] row Matrix row [0,...,rows()-1]. * @return Vector of matrix row elements (columns() elements). * * @exception GException::out_of_range * Invalid row index specified. * * Extracts one @p row of the matrix into a vector. The vector will contain * columns() elements. ***************************************************************************/ GVector GMatrix::row(const int& row) const { // Raise an exception if the row index is invalid #if defined(G_RANGE_CHECK) if (row < 0 || row >= m_rows) { throw GException::out_of_range(G_EXTRACT_ROW, row, 0, m_rows-1); } #endif // Create result vector GVector result(m_cols); // Extract row into vector. Recall that the matrix elements are stored // column wise, hence we have to increment the element counter i by // the number of rows to go into the next matrix column. for (int col = 0, i = row; col < m_cols; ++col, i += m_rows) { result[col] = m_data[i]; } // Return vector return result; } /***********************************************************************//** * @brief Set row in matrix * * @param[in] row Matrix row [0,...,rows()-1]. * @param[in] vector Vector of matrix row elements (columns() elements). * * @exception GException::out_of_range * Invalid row index specified. * @exception GException::matrix_vector_mismatch * Vector does not match the matrix dimensions. * * Sets the elements from a vector as the elements of a matrix row. The * length of the vector must be identical to the number of columns in the * matrix. ***************************************************************************/ void GMatrix::row(const int& row, const GVector& vector) { // Raise an exception if the row index is invalid #if defined(G_RANGE_CHECK) if (row < 0 || row >= m_rows) { throw GException::out_of_range(G_SET_ROW, row, 0, m_rows-1); } #endif // Raise an exception if the matrix and vector dimensions are not // compatible if (m_cols != vector.size()) { throw GException::matrix_vector_mismatch(G_SET_ROW, vector.size(), m_rows, m_cols); } // Set row from vector. Recall that the matrix elements are stored // column wise, hence we have to increment the element counter i by // the number of rows to go into the next matrix column. for (int col = 0, i = row; col < m_cols; ++col, i += m_rows) { m_data[i] = vector[col]; } // Return return; } /***********************************************************************//** * @brief Extract column as vector from matrix * * @param[in] column Column index [0,...,columns()-1]. * * @exception GException::out_of_range * Invalid row index specified. * * This method extracts a matrix column into a vector. ***************************************************************************/ GVector GMatrix::column(const int& column) const { // Raise an exception if the column index is invalid #if defined(G_RANGE_CHECK) if (column < 0 || column >= m_cols) { throw GException::out_of_range(G_EXTRACT_COLUMN, column, 0, m_cols-1); } #endif // Create result vector GVector result(m_rows); // Continue only if we have elements if (m_elements > 0) { // Get start of data in matrix int i = m_colstart[column]; // Extract column into vector for (int row = 0; row < m_rows; ++row) { result[row] = m_data[i++]; } } // endif: matrix had elements // Return vector return result; } /***********************************************************************//** * @brief Set matrix column from vector * * @param[in] column Column index [0,...,columns()-1]. * @param[in] vector Vector. * * @exception GException::out_of_range * Invalid column index specified. * @exception GException::matrix_vector_mismatch * Matrix dimension mismatches the vector size. * * Inserts the content of a vector into a matrix column. Any previous * content in the matrix column will be overwritted. ***************************************************************************/ void GMatrix::column(const int& column, const GVector& vector) { // Raise an exception if the column index is invalid #if defined(G_RANGE_CHECK) if (column < 0 || column >= m_cols) { throw GException::out_of_range(G_SET_COLUMN, column, 0, m_cols-1); } #endif // Raise an exception if the matrix and vector dimensions are not // compatible if (m_rows != vector.size()) { throw GException::matrix_vector_mismatch(G_SET_COLUMN, vector.size(), m_rows, m_cols); } // Continue only if we have elements if (m_elements > 0) { // Get start index of data in matrix int i = m_colstart[column]; // Insert column into vector for (int row = 0; row < m_rows; ++row) { m_data[i++] = vector[row]; } } // endif: matrix had elements // Return return; } /***********************************************************************//** * @brief Add row to matrix elements * * @param[in] row Matrix row [0,...,rows()-1]. * @param[in] vector Vector of matrix row elements (columns() elements). * * @exception GException::out_of_range * Invalid row index specified. * @exception GException::matrix_vector_mismatch * Vector does not match the matrix dimensions. ***************************************************************************/ void GMatrix::add_to_row(const int& row, const GVector& vector) { // Raise an exception if the row index is invalid #if defined(G_RANGE_CHECK) if (row < 0 || row >= m_rows) { throw GException::out_of_range(G_ADD_TO_ROW, row, 0, m_rows-1); } #endif // Raise an exception if the matrix and vector dimensions are not // compatible if (m_cols != vector.size()) { throw GException::matrix_vector_mismatch(G_ADD_TO_ROW, vector.size(), m_rows, m_cols); } // Add row from vector. Recall that the matrix elements are stored // column wise, hence we have to increment the element counter i by // the number of rows to go into the next matrix column. for (int col = 0, i = row; col < m_cols; ++col, i += m_rows) { m_data[i] += vector[col]; } // Return return; } /***********************************************************************//** * @brief Add vector column into matrix * * @param[in] column Column index [0,...,columns()-1]. * @param[in] vector Vector. * * @exception GException::out_of_range * Invalid column index specified. * @exception GException::matrix_vector_mismatch * Matrix dimension mismatches the vector size. * * Adds the content of a vector to a matrix column. ***************************************************************************/ void GMatrix::add_to_column(const int& column, const GVector& vector) { // Raise an exception if the column index is invalid #if defined(G_RANGE_CHECK) if (column < 0 || column >= m_cols) { throw GException::out_of_range(G_ADD_TO_COLUMN, column, 0, m_cols-1); } #endif // Raise an exception if the matrix and vector dimensions are not // compatible if (m_rows != vector.size()) { throw GException::matrix_vector_mismatch(G_ADD_TO_COLUMN, vector.size(), m_rows, m_cols); } // Continue only if we have elements if (m_elements > 0) { // Get start index of data in matrix int i = m_colstart[column]; // Add column into vector for (int row = 0; row < m_rows; ++row) { m_data[i++] += vector[row]; } } // endif: matrix had elements // Return return; } /***********************************************************************//** * @brief Return transposed matrix * * @return Transposed matrix. * * Returns transposed matrix of the matrix. ***************************************************************************/ GMatrix GMatrix::transpose(void) const { // Allocate result matrix GMatrix matrix(m_cols, m_rows); // Transpose matrix for (int row = 0; row < m_rows; ++row) { for (int col = 0; col < m_cols; ++col) { matrix(col, row) = (*this)(row, col); } } // Return matrix return matrix; } /***********************************************************************//** * @brief Return inverted matrix * * @return Inverted matrix. * * @exception GException::feature_not_implemented * Feature not yet implemented. * * Returns inverse of matrix. * * @todo Needs to be implemented. ***************************************************************************/ GMatrix GMatrix::invert(void) const { // Allocate result matrix GMatrix matrix(m_cols, m_rows); // Throw exception throw GException::feature_not_implemented(G_INVERT); // Return matrix return matrix; } /***********************************************************************//** * @brief Solves linear matrix equation * * @param[in] vector Solution vector. * * @exception GException::feature_not_implemented * Feature not yet implemented. * * Solves the linear equation * * \f[M \times {\tt solution} = {\tt vector} \f] * * where \f$M\f$ is the matrix, \f${\tt vector}\f$ is the result, and * \f${\tt solution}\f$ is the solution. * * @todo Needs to be implemented. ***************************************************************************/ GVector GMatrix::solve(const GVector& vector) const { // Allocate result vector GVector result; // Throw exception throw GException::feature_not_implemented(G_SOLVE); // Return vector return result; } /***********************************************************************//** * @brief Return absolute of matrix * * @return Absolute of matrix * * Returns matrix where all elements of the matrix have been replaced by * their absolute values. ***************************************************************************/ GMatrix GMatrix::abs(void) const { // Allocate result matrix GMatrix matrix(m_rows, m_cols); // Take the absolute value of all matrix elements double* src = m_data; double* dst = matrix.m_data; for (int i = 0; i < m_elements; ++i) { *dst++ = std::abs(*src++); } // Return matrix return matrix; } /***********************************************************************//** * @brief Return fill of matrix * * @return Matrix fill (between 0 and 1). * * Returns the fill of the matrix. The fill of a matrix is defined as the * number non-zero elements devided by the number of total elements. By * definition, the fill is comprised in the interval [0,..,1]. * * The fill of a matrix with zero elements will be set to 0. ***************************************************************************/ double GMatrix::fill(void) const { // Initialise result double result = 0.0; // Continue only if matrix has elements if (m_elements > 0) { // Determine the number of zero elements int zero = 0; for (int i = 0; i < m_elements; ++i) { if (m_data[i] == 0.0) { zero++; } } // Compute fill result = 1.0-double(zero)/double(m_elements); } // endif: there were elements in the matrix // Return result return result; } /***********************************************************************//** * @brief Extract lower triangle of matrix * * @exception GException::matrix_not_square * Matrix is not a square matrix. * * This method extracts the lower triangle of a matrix into another matrix. * (including the diagonal elements). * All remaining matrix elements will be zero. * * Triangular extraction only works for square matrixes. ***************************************************************************/ GMatrix GMatrix::extract_lower_triangle(void) const { // Raise an exception if matrix is not square if (m_rows != m_cols) { throw GException::matrix_not_square(G_EXTRACT_LOWER, m_rows, m_cols); } // Define result matrix GMatrix result(m_rows, m_cols); // Extract all elements for (int col = 0; col < m_cols; ++col) { int i = m_colstart[col] + col; for (int row = col; row < m_rows; ++row, ++i) { result.m_data[i] = m_data[i]; } } // Return result return result; } /***********************************************************************//** * @brief Extract upper triangle of matrix * * @exception GException::matrix_not_square * Matrix is not a square matrix. * * This method extracts the upper triangle of a matrix into another matrix. * (including the diagonal elements). * All remaining matrix elements will be zero. * * Triangular extraction only works for square matrixes. ***************************************************************************/ GMatrix GMatrix::extract_upper_triangle(void) const { // Raise an exception if matrix is not squared if (m_rows != m_cols) { throw GException::matrix_not_square(G_EXTRACT_UPPER, m_rows, m_cols); } // Define result matrix GMatrix result(m_rows, m_cols); // Extract all elements for (int col = 0; col < m_cols; ++col) { int i = m_colstart[col]; for (int row = 0; row <= col; ++row, ++i) { result.m_data[i] = m_data[i]; } } // Return result return result; } /***********************************************************************//** * @brief Set Euler rotation matrix around x axis * * @param[in] angle Rotation angle (degrees) ***************************************************************************/ void GMatrix::eulerx(const double& angle) { // Free members GMatrixBase::free_members(); // Initialise members GMatrixBase::init_members(); // Construct 3*3 matrix alloc_members(3,3); // Compute angles double arg = angle * gammalib::deg2rad; double cosangle = std::cos(arg); double sinangle = std::sin(arg); // Set matrix elements (*this)(0,0) = 1.0; (*this)(0,1) = 0.0; (*this)(0,2) = 0.0; (*this)(1,0) = 0.0; (*this)(1,1) = cosangle; (*this)(1,2) = -sinangle; (*this)(2,0) = 0.0; (*this)(2,1) = sinangle; (*this)(2,2) = cosangle; // Return return; } /***********************************************************************//** * @brief Set Euler rotation matrix around y axis * * @param[in] angle Rotation angle (degrees) ***************************************************************************/ void GMatrix::eulery(const double& angle) { // Free members GMatrixBase::free_members(); // Initialise members GMatrixBase::init_members(); // Construct 3*3 matrix alloc_members(3,3); // Compute angles double arg = angle * gammalib::deg2rad; double cosangle = std::cos(arg); double sinangle = std::sin(arg); // Set matrix elements (*this)(0,0) = cosangle; (*this)(0,1) = 0.0; (*this)(0,2) = sinangle; (*this)(1,0) = 0.0; (*this)(1,1) = 1.0; (*this)(1,2) = 0.0; (*this)(2,0) = -sinangle; (*this)(2,1) = 0.0; (*this)(2,2) = cosangle; // Return return; } /***********************************************************************//** * @brief Set Euler rotation matrix around z axis * * @param[in] angle Rotation angle (degrees) ***************************************************************************/ void GMatrix::eulerz(const double& angle) { // Free members GMatrixBase::free_members(); // Initialise members GMatrixBase::init_members(); // Construct 3*3 matrix alloc_members(3,3); // Compute angles double arg = angle * gammalib::deg2rad; double cosangle = std::cos(arg); double sinangle = std::sin(arg); // Set matrix elements (*this)(0,0) = cosangle; (*this)(0,1) = -sinangle; (*this)(0,2) = 0.0; (*this)(1,0) = sinangle; (*this)(1,1) = cosangle; (*this)(1,2) = 0.0; (*this)(2,0) = 0.0; (*this)(2,1) = 0.0; (*this)(2,2) = 1.0; // Return return; } /***********************************************************************//** * @brief Print matrix * * @return String containing matrix information. ***************************************************************************/ std::string GMatrix::print(const GChatter& chatter) const { // Initialise result string std::string result; // Continue only if chatter is not silent if (chatter != SILENT) { // Append header result.append("=== GMatrix ==="); // Append information result.append("\n"+gammalib::parformat("Number of rows")); result.append(gammalib::str(m_rows)); if (m_rowsel != NULL) { result.append(" (compressed "+gammalib::str(m_num_rowsel)+")"); } result.append("\n"+gammalib::parformat("Number of columns")); result.append(gammalib::str(m_cols)); if (m_colsel != NULL) { result.append(" (compressed "+gammalib::str(m_num_colsel)+")"); } result.append("\n"+gammalib::parformat("Number of elements")); result.append(gammalib::str(m_elements)); result.append("\n"+gammalib::parformat("Number of allocated cells")); result.append(gammalib::str(m_alloc)); // Append elements and compression schemes result.append(print_elements(chatter)); result.append(print_row_compression(chatter)); result.append(print_col_compression(chatter)); } // endif: chatter was not silent // Return result return result; } /*========================================================================== = = = Private methods = = = ==========================================================================*/ /***********************************************************************//** * @brief Initialise class members ***************************************************************************/ void GMatrix::init_members(void) { // Return return; } /***********************************************************************//** * @brief Copy class members * * @param[in] matrix Matrix. ***************************************************************************/ void GMatrix::copy_members(const GMatrix& matrix) { // Return return; } /***********************************************************************//** * @brief Delete class members ***************************************************************************/ void GMatrix::free_members(void) { // Return return; } /***********************************************************************//** * @brief Allocate matrix memory * * @param[in] rows Number of matrix rows. * @param[in] columns Number of matrix columns. * * Allocates memory for the matrix elements. The method assumes that no * memory has been allocated for the matrix elements and the column start * index array. The method allocates the memory for matrix elements and the * column start indices, sets all matrix elements to 0, and sets the column * start indices. * * If either the number of rows or the number of columns is non-positive, the * method does nothing. ***************************************************************************/ void GMatrix::alloc_members(const int& rows, const int& columns) { // Determine number of elements to store in matrix int elements = rows * columns; // Continue only if number of elements is positive if (elements > 0) { // Free any existing memory if (m_data != NULL) delete [] m_data; if (m_colstart != NULL) delete [] m_colstart; // Allocate matrix array and column start index array. m_data = new double[elements]; m_colstart = new int[columns+1]; // Store matrix size (logical, storage, allocated) m_rows = rows; m_cols = columns; m_elements = elements; m_alloc = elements; // Set-up column start indices m_colstart[0] = 0; for (int col = 1; col <= m_cols; ++col) { m_colstart[col] = m_colstart[col-1] + m_rows; } // Initialise matrix elements to 0 for (int i = 0; i < m_elements; ++i) { m_data[i] = 0.0; } } // endif: number of elements was positive // Return return; }