GammaLib 2.0.0
Loading...
Searching...
No Matches
GMatrix.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GMatrix.cpp - General matrix class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2006-2021 by Juergen Knoedlseder *
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 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GMatrix.cpp
23 * @brief General matrix class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <cmath>
32#include "GException.hpp"
33#include "GTools.hpp"
34#include "GMath.hpp"
35#include "GVector.hpp"
36#include "GMatrix.hpp"
37#include "GMatrixSparse.hpp"
38#include "GMatrixSymmetric.hpp"
39
40/* __ Method name definitions ____________________________________________ */
41#define G_CONSTRUCTOR "GMatrix::GMatrix(int&, int&)"
42#define G_OP_MUL_VEC "GMatrix::operator*(GVector&)"
43#define G_OP_ADD "GMatrix::operator+=(GMatrix&)"
44#define G_OP_SUB "GMatrix::operator-=(GMatrix&)"
45#define G_OP_MAT_MUL "GMatrix::operator*=(GMatrix&)"
46#define G_AT "GMatrix::at(int&, int&)"
47#define G_EXTRACT_ROW "GMatrix::row(int&)"
48#define G_SET_ROW "GMatrix::row(int&, GVector&)"
49#define G_EXTRACT_COLUMN "GMatrix::column(int&)"
50#define G_SET_COLUMN "GMatrix::column(int&, GVector&)"
51#define G_ADD_TO_ROW "GMatrix::add_to_row(int&, GVector&)"
52#define G_ADD_TO_COLUMN "GMatrix::add_to_column(int&, GVector&)"
53#define G_INVERT "GMatrix::invert()"
54#define G_SOLVE "GMatrix::solve(GVector&)"
55#define G_EXTRACT_LOWER "GMatrix::extract_lower_triangle()"
56#define G_EXTRACT_UPPER "GMatrix::extract_upper_triangle()"
57
58
59/*==========================================================================
60 = =
61 = Constructors/destructors =
62 = =
63 ==========================================================================*/
64
65/***********************************************************************//**
66 * @brief Void matrix constructor
67 *
68 * Constructs an empty matrix. An empty matrix has zero rows and columns.
69 ***************************************************************************/
71{
72 // Initialise class members
74
75 // Return
76 return;
77}
78
79
80/***********************************************************************//**
81 * @brief Matrix constructor
82 *
83 * @param[in] rows Number of rows [>=0].
84 * @param[in] columns Number of columns [>=0].
85 *
86 * @exception GException::invalid_argument
87 * Number of rows or columns is negative.
88 *
89 * Constructs a matrix with the specified number of @p rows and @p columns.
90 * The memory for all matrix elements will be allocated and all matrix
91 * elements will be initialized to 0.
92 ***************************************************************************/
93GMatrix::GMatrix(const int& rows, const int& columns) : GMatrixBase()
94{
95 // Throw exception if number of rows or columns is negative
96 #if defined(G_RANGE_CHECK)
97 if (rows < 0) {
98 std::string msg = "Number of rows "+gammalib::str(rows)+" is negative. "
99 "Please specify a non-negative number of rows.";
101 }
102 if (columns < 0) {
103 std::string msg = "Number of columns "+gammalib::str(columns)+" is "
104 "negative. Please specify a non-negative number of "
105 "columns.";
107 }
108 #endif
109
110 // Initialise class members for clean destruction
111 init_members();
112
113 // Allocate matrix memory
115
116 // Return
117 return;
118}
119
120
121/***********************************************************************//**
122 * @brief Copy constructor
123 *
124 * @param[in] matrix Matrix.
125 ***************************************************************************/
126GMatrix::GMatrix(const GMatrix& matrix) : GMatrixBase(matrix)
127{
128 // Initialise class members for clean destruction
129 init_members();
130
131 // Copy members
132 copy_members(matrix);
133
134 // Return
135 return;
136}
137
138
139/***********************************************************************//**
140 * @brief GMatrixSymmetric to GMatrix storage class convertor
141 *
142 * @param[in] matrix Symmetric matrix (GMatrixSymmetric).
143 *
144 * Constructs a GMatrix object from a symmetric matrix object of type
145 * GMatrixSymmetric. Since the result is a generic matrix, the constructor
146 * will succeed in all cases.
147 ***************************************************************************/
149{
150 // Initialise class members for clean destruction
151 init_members();
152
153 // Allocate matrix memory
154 alloc_members(matrix.rows(), matrix.columns());
155
156 // Fill matrix. We benefit here from the symmetry of the matrix and
157 // loop only over the lower triangle of the symmetric matrix to perform
158 // the fill.
159 for (int col = 0; col < m_cols; ++col) {
160 for (int row = col; row < m_rows; ++row) {
161 double value = matrix(row, col);
162 (*this)(row, col) = value;
163 (*this)(col, row) = value;
164 }
165 }
166
167 // Return
168 return;
169}
170
171
172/***********************************************************************//**
173 * @brief GMatrixSparse to GMatrix storage class convertor
174 *
175 * @param[in] matrix Sparse matrix (GMatrixSparse).
176 *
177 * Constructs a GMatrix object from a sparse matrix object of type
178 * GMatrixSparse. Since the result is a generic matrix, the constructor
179 * will succeed in all cases.
180 ***************************************************************************/
182{
183 // Initialise class members for clean destruction
184 init_members();
185
186 // Construct matrix
187 alloc_members(matrix.rows(), matrix.columns());
188
189 // Fill matrix
190 for (int col = 0; col < m_cols; ++col) {
191 for (int row = 0; row < m_rows; ++row) {
192 (*this)(row, col) = matrix(row, col);
193 }
194 }
195
196 // Return
197 return;
198}
199
200
201/***********************************************************************//**
202 * @brief Destructor
203 ***************************************************************************/
205{
206 // Free members
207 free_members();
208
209 // Return
210 return;
211}
212
213
214/*==========================================================================
215 = =
216 = Operators =
217 = =
218 ==========================================================================*/
219
220/***********************************************************************//**
221 * @brief Matrix assignment operator
222 *
223 * @param[in] matrix Matrix.
224 * @return Matrix.
225 *
226 * Assigns the content of another matrix to the actual matrix instance.
227 ***************************************************************************/
229{
230 // Execute only if object is not identical
231 if (this != &matrix) {
232
233 // Assign base class members. Note that this method will also perform
234 // the allocation of the matrix memory and the copy of the matrix
235 // attributes.
236 this->GMatrixBase::operator=(matrix);
237
238 // Free derived class members
239 free_members();
240
241 // Initialise derived class members
242 init_members();
243
244 // Copy derived class members
245 copy_members(matrix);
246
247 } // endif: object was not identical
248
249 // Return this object
250 return *this;
251}
252
253
254/***********************************************************************//**
255 * @brief Value assignment operator
256 *
257 * @param[in] value Value.
258 * @return Matrix.
259 *
260 * Assigns the specified @p value to all elements of the matrix.
261 ***************************************************************************/
262GMatrix& GMatrix::operator=(const double& value)
263{
264 // Assign value
265 double* ptr = m_data;
266 for (int i = 0; i < m_elements; ++i) {
267 *ptr++ = value;
268 }
269
270 // Return this object
271 return *this;
272}
273
274
275/***********************************************************************//**
276 * @brief Vector multiplication
277 *
278 * @param[in] vector Vector.
279 *
280 * @exception GException::invalid_argument
281 * Vector size differs from number of columns in matrix.
282 *
283 * This method performs a vector multiplication of a matrix. The vector
284 * multiplication will produce a vector. The multiplication can only be
285 * performed when the number of matrix columns is identical to the size
286 * of the vector. If the size of the vector differs an exception will be
287 * thrown.
288 ***************************************************************************/
290{
291 // Raise an exception if the matrix and vector dimensions are not compatible
292 if (m_cols != vector.size()) {
293 std::string msg = "Vector size "+gammalib::str(vector.size())+" does "
294 "not match "+gammalib::str(m_cols)+" matrix columns. "
295 "Please specify a vector of size "+
298 }
299
300 // Perform vector multiplication
301 GVector result(m_rows);
302 for (int row = 0; row < m_rows; ++row) {
303 double sum = 0.0;
304 const double* src = m_data + row;
305 for (int col = 0; col < m_cols; ++col, src += m_rows) {
306 sum += *src * vector[col];
307 }
308 result[row] = sum;
309 }
310
311 // Return result
312 return result;
313}
314
315
316/***********************************************************************//**
317 * @brief Negate matrix elements
318 *
319 * @return Matrix with negated elements.
320 *
321 * Returns a matrix where each element has been replaced by its negative
322 * element.
323 ***************************************************************************/
325{
326 // Copy matrix
327 GMatrix matrix = *this;
328
329 // Take the absolute value of all matrix elements
330 double* ptr = matrix.m_data;
331 for (int i = 0; i < matrix.m_elements; ++i, ++ptr) {
332 *ptr = -(*ptr);
333 }
334
335 // Return matrix
336 return matrix;
337}
338
339
340/***********************************************************************//**
341 * @brief Unary matrix addition operator
342 *
343 * @param[in] matrix Matrix.
344 *
345 * @exception GException::invalid_argument
346 * Incompatible number of matrix rows or columns.
347 *
348 * This method performs a matrix addition. The method throws an exception if
349 * the number of matrix rows or columns are not identical.
350 ***************************************************************************/
352{
353 // Throw an exception if the matrix dimensions are not compatible
354 if (m_rows != matrix.m_rows) {
355 std::string msg = "Number of matrix rows "+gammalib::str(matrix.m_rows)+
356 " differs from the expected number of "+
357 gammalib::str(m_rows)+" rows. Please specify a "
358 "matrix with "+gammalib::str(m_rows)+" rows.";
360 }
361 if (m_cols != matrix.m_cols) {
362 std::string msg = "Number of matrix columns "+gammalib::str(matrix.m_cols)+
363 " differs from the expected number of "+
364 gammalib::str(m_cols)+" columns. Please specify a "
365 "matrix with "+gammalib::str(m_cols)+" columns.";
367 }
368
369 // Add all matrix elements
370 const double* src = matrix.m_data;
371 double* dst = m_data;
372 for (int i = 0; i < m_elements; ++i) {
373 *dst++ += *src++;
374 }
375
376 // Return result
377 return *this;
378}
379
380
381/***********************************************************************//**
382 * @brief Unary matrix scalar addition operator
383 *
384 * @param[in] scalar Scalar.
385 *
386 * Adds a @p scalar to each matrix element.
387 ***************************************************************************/
388GMatrix& GMatrix::operator+=(const double& scalar)
389{
390 // Add all matrix elements
391 double* dst = m_data;
392 for (int i = 0; i < m_elements; ++i) {
393 *dst++ += scalar;
394 }
395
396 // Return result
397 return *this;
398}
399
400
401/***********************************************************************//**
402 * @brief Unary matrix subtraction operator
403 *
404 * @param[in] matrix Matrix.
405 *
406 * @exception GException::invalid_argument
407 * Incompatible number of matrix rows or columns.
408 *
409 * This method performs a matrix addition. The method throws an exception if
410 * the number of matrix rows or columns are not identical.
411 ***************************************************************************/
413{
414 // Throw an exception if the matrix dimensions are not compatible
415 if (m_rows != matrix.m_rows) {
416 std::string msg = "Number of matrix rows "+gammalib::str(matrix.m_rows)+
417 " differs from the expected number of "+
418 gammalib::str(m_rows)+" rows. Please specify a "
419 "matrix with "+gammalib::str(m_rows)+" rows.";
421 }
422 if (m_cols != matrix.m_cols) {
423 std::string msg = "Number of matrix columns "+gammalib::str(matrix.m_cols)+
424 " differs from the expected number of "+
425 gammalib::str(m_cols)+" columns. Please specify a "
426 "matrix with "+gammalib::str(m_cols)+" columns.";
428 }
429
430 // Subtract all matrix elements
431 const double* src = matrix.m_data;
432 double* dst = m_data;
433 for (int i = 0; i < m_elements; ++i) {
434 *dst++ -= *src++;
435 }
436
437 // Return result
438 return *this;
439}
440
441
442/***********************************************************************//**
443 * @brief Unary matrix scalar subtraction operator
444 *
445 * @param[in] scalar Scalar.
446 *
447 * Subtracts a @p scalar from each matrix element.
448 ***************************************************************************/
449GMatrix& GMatrix::operator-=(const double& scalar)
450{
451 // Add all matrix elements
452 double* dst = m_data;
453 for (int i = 0; i < m_elements; ++i) {
454 *dst++ -= scalar;
455 }
456
457 // Return result
458 return *this;
459}
460
461
462/***********************************************************************//**
463 * @brief Unary matrix multiplication operator
464 *
465 * @param[in] matrix Matrix.
466 *
467 * @exception GException::invalid_argument
468 * Number of rows in @p matrix is different from number of
469 * matrix columns.
470 *
471 * This method performs a matrix multiplication. The operation can only
472 * succeed when the dimensions of both matrices are compatible.
473 *
474 * In case of rectangular matrices the result matrix does not change and
475 * the operation is performed inplace. For the general case the result
476 * matrix changes in size and for simplicity a new matrix is allocated to
477 * hold the result.
478 ***************************************************************************/
480{
481 // Throw exception if the matrix dimensions are not compatible
482 if (m_cols != matrix.m_rows) {
483 std::string msg = "Number of "+gammalib::str(m_cols)+" columns in "
484 "the first matrix differs from number of "+
485 gammalib::str(matrix.m_rows)+" rows in the second "
486 "matrix. Please specify a second matrix with "+
487 gammalib::str(m_cols)+" rows.";
489 }
490
491 // Case A: Matrices are rectangular, so perform 'inplace' multiplication
492 if (m_rows == m_cols) {
493 for (int row = 0; row < m_rows; ++row) {
494 GVector v_row = this->row(row);
495 for (int col = 0; col < m_cols; ++col) {
496 double sum = 0.0;
497 for (int i = 0; i < m_cols; ++i) {
498 sum += v_row[i] * matrix(i,col);
499 }
500 (*this)(row,col) = sum;
501 }
502 }
503 }
504
505 // Case B: Matrices are not rectangular, so we cannot work inplace
506 else {
507
508 // Allocate result matrix
509 GMatrix result(m_rows, matrix.m_cols);
510
511 // Loop over all elements of result matrix
512 for (int row = 0; row < m_rows; ++row) {
513 for (int col = 0; col < matrix.m_cols; ++col) {
514 double sum = 0.0;
515 for (int i = 0; i < m_cols; ++i) {
516 sum += (*this)(row,i) * matrix(i,col);
517 }
518 result(row,col) = sum;
519 }
520 }
521
522 // Assign result
523 *this = result;
524
525 } // endelse: matrices were not rectangular
526
527 // Return result
528 return *this;
529}
530
531
532/*==========================================================================
533 = =
534 = Public methods =
535 = =
536 ==========================================================================*/
537
538/***********************************************************************//**
539 * @brief Clear matrix
540 ***************************************************************************/
542{
543 // Free members
544 free_members();
545
546 // Initialise private members
547 init_members();
548
549 // Return
550 return;
551}
552
553
554/***********************************************************************//**
555 * @brief Clone matrix
556 *
557 * @return Pointer to deep copy of matrix.
558 ***************************************************************************/
560{
561 // Clone matrix
562 return new GMatrix(*this);
563}
564
565
566/***********************************************************************//**
567 * @brief Return reference to matrix element
568 *
569 * @param[in] row Matrix row [0,...,rows()[.
570 * @param[in] column Matrix column [0,...,columns()[.
571 * @return Reference to matrix element.
572 *
573 * @exception GException::out_of_range
574 * Matrix row or column out of range.
575 *
576 * Returns a reference to the matrix element at @p row and @p column.
577 *
578 * This method verifies the validity of the @p row and @p column argument.
579 ***************************************************************************/
580double& GMatrix::at(const int& row, const int& column)
581{
582 // Throw exception if row or column is out of range
584 throw GException::out_of_range(G_AT, "Matrix row", row, m_rows);
585 }
587 throw GException::out_of_range(G_AT, "Matrix column", column, m_cols);
588 }
589
590 // Return element
591 return (m_data[m_colstart[column]+row]);
592}
593
594
595/***********************************************************************//**
596 * @brief Return reference to matrix element (const version)
597 *
598 * @param[in] row Matrix row [0,...,rows()[.
599 * @param[in] column Matrix column [0,...,columns()[.
600 * @return Const reference to matrix element.
601 *
602 * @exception GException::out_of_range
603 * Matrix row or column out of range.
604 *
605 * Returns a const reference to the matrix element at @p row and @p column.
606 *
607 * This method verifies the validity of the @p row and @p column argument.
608 ***************************************************************************/
609const double& GMatrix::at(const int& row, const int& column) const
610{
611 // Throw exception if row or column is out of range
613 throw GException::out_of_range(G_AT, "Matrix row", row, m_rows);
614 }
616 throw GException::out_of_range(G_AT, "Matrix column", column, m_cols);
617 }
618
619 // Return element
620 return (m_data[m_colstart[column]+row]);
621}
622
623
624
625/***********************************************************************//**
626 * @brief Extract row as vector from matrix
627 *
628 * @param[in] row Matrix row [0,...,rows()[.
629 * @return Vector of matrix row elements (columns() elements).
630 *
631 * @exception GException::out_of_range
632 * Invalid matrix row specified.
633 *
634 * Extracts one @p row of the matrix into a vector. The vector will contain
635 * columns() elements.
636 ***************************************************************************/
637GVector GMatrix::row(const int& row) const
638{
639 // Throw exception if the row is invalid
640 #if defined(G_RANGE_CHECK)
642 throw GException::out_of_range(G_EXTRACT_ROW, "Matrix row", row, m_rows);
643 }
644 #endif
645
646 // Create result vector
647 GVector result(m_cols);
648
649 // Extract row into vector. Recall that the matrix elements are stored
650 // column wise, hence we have to increment the element counter i by
651 // the number of rows to go into the next matrix column.
652 for (int col = 0, i = row; col < m_cols; ++col, i += m_rows) {
653 result[col] = m_data[i];
654 }
655
656 // Return vector
657 return result;
658}
659
660
661/***********************************************************************//**
662 * @brief Set row in matrix
663 *
664 * @param[in] row Matrix row [0,...,rows()[.
665 * @param[in] vector Vector of matrix row elements (columns() elements).
666 *
667 * @exception GException::out_of_range
668 * Invalid matrix row specified.
669 * @exception GException::invalid_argument
670 * Vector size does not match number of matrix columns.
671 *
672 * Sets the elements from a vector as the elements of a matrix row. The
673 * size of the vector must be identical to the number of columns in the
674 * matrix.
675 ***************************************************************************/
676void GMatrix::row(const int& row, const GVector& vector)
677{
678 // Throw an exception if the row is invalid
679 #if defined(G_RANGE_CHECK)
681 throw GException::out_of_range(G_SET_ROW, "Matrix row", row, m_rows);
682 }
683 #endif
684
685 // Throw an exception if the matrix and vector dimensions are not
686 // compatible
687 if (m_cols != vector.size()) {
688 std::string msg = "Vector size "+gammalib::str(vector.size())+
689 " does not match "+gammalib::str(m_cols)+" matrix "
690 "columns. Please specify a vector of size "+
693 }
694
695 // Set row from vector. Recall that the matrix elements are stored
696 // column wise, hence we have to increment the element counter i by
697 // the number of rows to go into the next matrix column.
698 for (int col = 0, i = row; col < m_cols; ++col, i += m_rows) {
699 m_data[i] = vector[col];
700 }
701
702 // Return
703 return;
704}
705
706
707/***********************************************************************//**
708 * @brief Extract column as vector from matrix
709 *
710 * @param[in] column Matrix column [0,...,columns()[.
711 * @return Vector of matrix column elements (rows() elements).
712 *
713 * @exception GException::out_of_range
714 * Invalid matrix column specified.
715 *
716 * This method extracts a matrix column into a vector.
717 ***************************************************************************/
718GVector GMatrix::column(const int& column) const
719{
720 // Throw exception if the column is invalid
721 #if defined(G_RANGE_CHECK)
723 throw GException::out_of_range(G_EXTRACT_COLUMN, "Matrix column",
724 column, m_cols);
725 }
726 #endif
727
728 // Create result vector
729 GVector result(m_rows);
730
731 // Continue only if we have elements
732 if (m_elements > 0) {
733
734 // Get start of data in matrix
735 int i = m_colstart[column];
736
737 // Extract column into vector
738 for (int row = 0; row < m_rows; ++row) {
739 result[row] = m_data[i++];
740 }
741
742 } // endif: matrix had elements
743
744 // Return vector
745 return result;
746}
747
748
749/***********************************************************************//**
750 * @brief Set matrix column from vector
751 *
752 * @param[in] column Matrix column [0,...,columns()[.
753 * @param[in] vector Vector.
754 *
755 * @exception GException::out_of_range
756 * Invalid matrix column specified.
757 * @exception GException::invalid_argument
758 * Vector size does not match number of matrix rows.
759 *
760 * Inserts the content of a vector into a matrix column. Any previous
761 * content in the matrix column will be overwritted.
762 ***************************************************************************/
763void GMatrix::column(const int& column, const GVector& vector)
764{
765 // Throw exception if the column is invalid
766 #if defined(G_RANGE_CHECK)
768 throw GException::out_of_range(G_SET_COLUMN, "Matrix column",
769 column, m_cols);
770 }
771 #endif
772
773 // Throw exception if the vector size does not match the number of rows
774 // in the matrix
775 if (m_rows != vector.size()) {
776 std::string msg = "Vector size "+gammalib::str(vector.size())+
777 " does not match "+gammalib::str(m_rows)+" matrix "
778 "rows. Please specify a vector of size "+
781 }
782
783 // Continue only if we have elements
784 if (m_elements > 0) {
785
786 // Get start index of data in matrix
787 int i = m_colstart[column];
788
789 // Insert column into vector
790 for (int row = 0; row < m_rows; ++row) {
791 m_data[i++] = vector[row];
792 }
793
794 } // endif: matrix had elements
795
796 // Return
797 return;
798}
799
800
801/***********************************************************************//**
802 * @brief Add row to matrix elements
803 *
804 * @param[in] row Matrix row [0,...,rows()[.
805 * @param[in] vector Vector of matrix row elements (columns() elements).
806 *
807 * @exception GException::out_of_range
808 * Invalid matrix row specified.
809 * @exception GException::matrix_vector_mismatch
810 * Vector does not match the matrix dimensions.
811 ***************************************************************************/
812void GMatrix::add_to_row(const int& row, const GVector& vector)
813{
814 // Throw exception if the row is invalid
815 #if defined(G_RANGE_CHECK)
817 throw GException::out_of_range(G_ADD_TO_ROW, "Matrix row", row, m_rows);
818
819 }
820 #endif
821
822 // Throw exception if the matrix and vector dimensions are not
823 // compatible
824 if (m_cols != vector.size()) {
825 std::string msg = "Vector size "+gammalib::str(vector.size())+
826 " does not match "+gammalib::str(m_cols)+" matrix "
827 "columns. Please specify a vector of size "+
830 }
831
832 // Add row from vector. Recall that the matrix elements are stored
833 // column wise, hence we have to increment the element counter i by
834 // the number of rows to go into the next matrix column.
835 for (int col = 0, i = row; col < m_cols; ++col, i += m_rows) {
836 m_data[i] += vector[col];
837 }
838
839 // Return
840 return;
841}
842
843
844/***********************************************************************//**
845 * @brief Add vector column into matrix
846 *
847 * @param[in] column Matrix column [0,...,columns()[.
848 * @param[in] vector Vector.
849 *
850 * @exception GException::out_of_range
851 * Invalid matrix column specified.
852 * @exception GException::matrix_vector_mismatch
853 * Vector size does not match number of matrix rows.
854 *
855 * Adds the content of a vector to a matrix column.
856 ***************************************************************************/
857void GMatrix::add_to_column(const int& column, const GVector& vector)
858{
859 // Raise an exception if the column is invalid
860 #if defined(G_RANGE_CHECK)
862 throw GException::out_of_range(G_ADD_TO_COLUMN, "Matrix column",
863 column, m_cols);
864
865 }
866 #endif
867
868 // Raise an exception if the matrix and vector dimensions are not
869 // compatible
870 if (m_rows != vector.size()) {
871 std::string msg = "Vector size "+gammalib::str(vector.size())+
872 " does not match "+gammalib::str(m_rows)+" matrix "
873 "rows. Please specify a vector of size "+
876 }
877
878 // Continue only if we have elements
879 if (m_elements > 0) {
880
881 // Get start index of data in matrix
882 int i = m_colstart[column];
883
884 // Add column into vector
885 for (int row = 0; row < m_rows; ++row) {
886 m_data[i++] += vector[row];
887 }
888
889 } // endif: matrix had elements
890
891 // Return
892 return;
893}
894
895
896/***********************************************************************//**
897 * @brief Return transposed matrix
898 *
899 * @return Transposed matrix.
900 *
901 * Returns transposed matrix of the matrix.
902 ***************************************************************************/
904{
905 // Allocate result matrix
906 GMatrix matrix(m_cols, m_rows);
907
908 // Transpose matrix
909 for (int row = 0; row < m_rows; ++row) {
910 for (int col = 0; col < m_cols; ++col) {
911 matrix(col, row) = (*this)(row, col);
912 }
913 }
914
915 // Return matrix
916 return matrix;
917}
918
919
920/***********************************************************************//**
921 * @brief Return inverted matrix
922 *
923 * @return Inverted matrix.
924 *
925 * @exception GException::feature_not_implemented
926 * Feature not yet implemented.
927 *
928 * Returns inverse of matrix.
929 *
930 * @todo Needs to be implemented.
931 ***************************************************************************/
933{
934 // Allocate result matrix
935 GMatrix matrix(m_cols, m_rows);
936
937 // Throw exception
939
940 // Return matrix
941 return matrix;
942}
943
944
945/***********************************************************************//**
946 * @brief Solves linear matrix equation
947 *
948 * @param[in] vector Solution vector.
949 *
950 * @exception GException::feature_not_implemented
951 * Feature not yet implemented.
952 *
953 * Solves the linear equation
954 *
955 * \f[M \times {\tt solution} = {\tt vector} \f]
956 *
957 * where \f$M\f$ is the matrix, \f${\tt vector}\f$ is the result, and
958 * \f${\tt solution}\f$ is the solution.
959 *
960 * @todo Needs to be implemented.
961 ***************************************************************************/
962GVector GMatrix::solve(const GVector& vector) const
963{
964 // Allocate result vector
965 GVector result;
966
967 // Throw exception
969
970 // Return vector
971 return result;
972}
973
974
975/***********************************************************************//**
976 * @brief Return absolute of matrix
977 *
978 * @return Absolute of matrix
979 *
980 * Returns matrix where all elements of the matrix have been replaced by
981 * their absolute values.
982 ***************************************************************************/
984{
985 // Allocate result matrix
986 GMatrix matrix(m_rows, m_cols);
987
988 // Take the absolute value of all matrix elements
989 double* src = m_data;
990 double* dst = matrix.m_data;
991 for (int i = 0; i < m_elements; ++i) {
992 *dst++ = std::abs(*src++);
993 }
994
995 // Return matrix
996 return matrix;
997}
998
999
1000/***********************************************************************//**
1001 * @brief Return fill of matrix
1002 *
1003 * @return Matrix fill (between 0 and 1).
1004 *
1005 * Returns the fill of the matrix. The fill of a matrix is defined as the
1006 * number non-zero elements devided by the number of total elements. By
1007 * definition, the fill is comprised in the interval [0,..,1].
1008 *
1009 * The fill of a matrix with zero elements will be set to 0.
1010 ***************************************************************************/
1011double GMatrix::fill(void) const
1012{
1013 // Initialise result
1014 double result = 0.0;
1015
1016 // Continue only if matrix has elements
1017 if (m_elements > 0) {
1018
1019 // Determine the number of zero elements
1020 int zero = 0;
1021 for (int i = 0; i < m_elements; ++i) {
1022 if (m_data[i] == 0.0) {
1023 zero++;
1024 }
1025 }
1026
1027 // Compute fill
1028 result = 1.0-double(zero)/double(m_elements);
1029
1030 } // endif: there were elements in the matrix
1031
1032 // Return result
1033 return result;
1034}
1035
1036
1037/***********************************************************************//**
1038 * @brief Extract lower triangle of matrix
1039 *
1040 * @exception GException::invalid_argument
1041 * Matrix is not a square matrix.
1042 *
1043 * This method extracts the lower triangle of a matrix into another matrix.
1044 * (including the diagonal elements).
1045 * All remaining matrix elements will be zero.
1046 *
1047 * Triangular extraction only works for square matrixes.
1048 ***************************************************************************/
1050{
1051 // Throw exception if matrix is not square
1052 if (m_rows != m_cols) {
1053 std::string msg = "Number of matrix rows "+gammalib::str(m_rows)+
1054 " differs from number of matrix columns "+
1055 gammalib::str(m_cols)+". This method only works "
1056 "on square matrices.";
1058 }
1059
1060 // Define result matrix
1061 GMatrix result(m_rows, m_cols);
1062
1063 // Extract all elements
1064 for (int col = 0; col < m_cols; ++col) {
1065 int i = m_colstart[col] + col;
1066 for (int row = col; row < m_rows; ++row, ++i) {
1067 result.m_data[i] = m_data[i];
1068 }
1069 }
1070
1071 // Return result
1072 return result;
1073}
1074
1075
1076/***********************************************************************//**
1077 * @brief Extract upper triangle of matrix
1078 *
1079 * @exception GException::invalid_argument
1080 * Matrix is not a square matrix.
1081 *
1082 * This method extracts the upper triangle of a matrix into another matrix.
1083 * (including the diagonal elements).
1084 * All remaining matrix elements will be zero.
1085 *
1086 * Triangular extraction only works for square matrixes.
1087 ***************************************************************************/
1089{
1090 // Throw exception if matrix is not squared
1091 if (m_rows != m_cols) {
1092 std::string msg = "Number of matrix rows "+gammalib::str(m_rows)+
1093 " differs from number of matrix columns "+
1094 gammalib::str(m_cols)+". This method only works "
1095 "on square matrices.";
1097 }
1098
1099 // Define result matrix
1100 GMatrix result(m_rows, m_cols);
1101
1102 // Extract all elements
1103 for (int col = 0; col < m_cols; ++col) {
1104 int i = m_colstart[col];
1105 for (int row = 0; row <= col; ++row, ++i) {
1106 result.m_data[i] = m_data[i];
1107 }
1108 }
1109
1110 // Return result
1111 return result;
1112}
1113
1114
1115/***********************************************************************//**
1116 * @brief Set Euler rotation matrix around x axis
1117 *
1118 * @param[in] angle Rotation angle (degrees)
1119 ***************************************************************************/
1120void GMatrix::eulerx(const double& angle)
1121{
1122 // Free members
1124
1125 // Initialise members
1127
1128 // Construct 3*3 matrix
1129 alloc_members(3,3);
1130
1131 // Compute angles
1132 double arg = angle * gammalib::deg2rad;
1133 double cosangle = std::cos(arg);
1134 double sinangle = std::sin(arg);
1135
1136 // Set matrix elements
1137 (*this)(0,0) = 1.0;
1138 (*this)(0,1) = 0.0;
1139 (*this)(0,2) = 0.0;
1140 (*this)(1,0) = 0.0;
1141 (*this)(1,1) = cosangle;
1142 (*this)(1,2) = -sinangle;
1143 (*this)(2,0) = 0.0;
1144 (*this)(2,1) = sinangle;
1145 (*this)(2,2) = cosangle;
1146
1147 // Return
1148 return;
1149}
1150
1151
1152/***********************************************************************//**
1153 * @brief Set Euler rotation matrix around y axis
1154 *
1155 * @param[in] angle Rotation angle (degrees)
1156 ***************************************************************************/
1157void GMatrix::eulery(const double& angle)
1158{
1159 // Free members
1161
1162 // Initialise members
1164
1165 // Construct 3*3 matrix
1166 alloc_members(3,3);
1167
1168 // Compute angles
1169 double arg = angle * gammalib::deg2rad;
1170 double cosangle = std::cos(arg);
1171 double sinangle = std::sin(arg);
1172
1173 // Set matrix elements
1174 (*this)(0,0) = cosangle;
1175 (*this)(0,1) = 0.0;
1176 (*this)(0,2) = sinangle;
1177 (*this)(1,0) = 0.0;
1178 (*this)(1,1) = 1.0;
1179 (*this)(1,2) = 0.0;
1180 (*this)(2,0) = -sinangle;
1181 (*this)(2,1) = 0.0;
1182 (*this)(2,2) = cosangle;
1183
1184 // Return
1185 return;
1186}
1187
1188
1189/***********************************************************************//**
1190 * @brief Set Euler rotation matrix around z axis
1191 *
1192 * @param[in] angle Rotation angle (degrees)
1193 ***************************************************************************/
1194void GMatrix::eulerz(const double& angle)
1195{
1196 // Free members
1198
1199 // Initialise members
1201
1202 // Construct 3*3 matrix
1203 alloc_members(3,3);
1204
1205 // Compute angles
1206 double arg = angle * gammalib::deg2rad;
1207 double cosangle = std::cos(arg);
1208 double sinangle = std::sin(arg);
1209
1210 // Set matrix elements
1211 (*this)(0,0) = cosangle;
1212 (*this)(0,1) = -sinangle;
1213 (*this)(0,2) = 0.0;
1214 (*this)(1,0) = sinangle;
1215 (*this)(1,1) = cosangle;
1216 (*this)(1,2) = 0.0;
1217 (*this)(2,0) = 0.0;
1218 (*this)(2,1) = 0.0;
1219 (*this)(2,2) = 1.0;
1220
1221 // Return
1222 return;
1223}
1224
1225
1226/***********************************************************************//**
1227 * @brief Print matrix
1228 *
1229 * @param[in] chatter Chattiness.
1230 * @return String containing matrix information.
1231 ***************************************************************************/
1232std::string GMatrix::print(const GChatter& chatter) const
1233{
1234 // Initialise result string
1235 std::string result;
1236
1237 // Continue only if chatter is not silent
1238 if (chatter != SILENT) {
1239
1240 // Append header
1241 result.append("=== GMatrix ===");
1242
1243 // Append information
1244 result.append("\n"+gammalib::parformat("Number of rows"));
1245 result.append(gammalib::str(m_rows));
1246 if (m_rowsel != NULL) {
1247 result.append(" (compressed "+gammalib::str(m_num_rowsel)+")");
1248 }
1249 result.append("\n"+gammalib::parformat("Number of columns"));
1250 result.append(gammalib::str(m_cols));
1251 if (m_colsel != NULL) {
1252 result.append(" (compressed "+gammalib::str(m_num_colsel)+")");
1253 }
1254 result.append("\n"+gammalib::parformat("Number of elements"));
1255 result.append(gammalib::str(m_elements));
1256 result.append("\n"+gammalib::parformat("Number of allocated cells"));
1257 result.append(gammalib::str(m_alloc));
1258
1259 // Append elements and compression schemes
1260 result.append(print_elements(chatter));
1261 result.append(print_row_compression(chatter));
1262 result.append(print_col_compression(chatter));
1263
1264 } // endif: chatter was not silent
1265
1266 // Return result
1267 return result;
1268}
1269
1270
1271/*==========================================================================
1272 = =
1273 = Private methods =
1274 = =
1275 ==========================================================================*/
1276
1277/***********************************************************************//**
1278 * @brief Initialise class members
1279 ***************************************************************************/
1281{
1282 // Return
1283 return;
1284}
1285
1286
1287/***********************************************************************//**
1288 * @brief Copy class members
1289 *
1290 * @param[in] matrix Matrix.
1291 ***************************************************************************/
1293{
1294 // Return
1295 return;
1296}
1297
1298
1299/***********************************************************************//**
1300 * @brief Delete class members
1301 ***************************************************************************/
1303{
1304 // Return
1305 return;
1306}
1307
1308
1309/***********************************************************************//**
1310 * @brief Allocate matrix memory
1311 *
1312 * @param[in] rows Number of matrix rows.
1313 * @param[in] columns Number of matrix columns.
1314 *
1315 * Allocates memory for the matrix elements. The method assumes that no
1316 * memory has been allocated for the matrix elements and the column start
1317 * index array. The method allocates the memory for matrix elements and the
1318 * column start indices, sets all matrix elements to 0, and sets the column
1319 * start indices.
1320 *
1321 * If either the number of rows or the number of columns is non-positive, the
1322 * method does nothing.
1323 ***************************************************************************/
1324void GMatrix::alloc_members(const int& rows, const int& columns)
1325{
1326 // Determine number of elements to store in matrix
1327 int elements = rows * columns;
1328
1329 // Continue only if number of elements is positive
1330 if (elements > 0) {
1331
1332 // Free any existing memory
1333 if (m_data != NULL) delete [] m_data;
1334 if (m_colstart != NULL) delete [] m_colstart;
1335
1336 // Allocate matrix array and column start index array.
1337 m_data = new double[elements];
1338 m_colstart = new int[columns+1];
1339
1340 // Store matrix size (logical, storage, allocated)
1341 m_rows = rows;
1342 m_cols = columns;
1343 m_elements = elements;
1344 m_alloc = elements;
1345
1346 // Set-up column start indices
1347 m_colstart[0] = 0;
1348 for (int col = 1; col <= m_cols; ++col) {
1349 m_colstart[col] = m_colstart[col-1] + m_rows;
1350 }
1351
1352 // Initialise matrix elements to 0
1353 for (int i = 0; i < m_elements; ++i) {
1354 m_data[i] = 0.0;
1355 }
1356
1357 } // endif: number of elements was positive
1358
1359 // Return
1360 return;
1361}
#define G_AT
Exception handler interface definition.
Mathematical function definitions.
Sparse matrix class definition.
Symmetric matrix class definition.
#define G_CONSTRUCTOR
Definition GMatrix.cpp:41
#define G_OP_ADD
Definition GMatrix.cpp:43
#define G_EXTRACT_ROW
Definition GMatrix.cpp:47
#define G_EXTRACT_COLUMN
Definition GMatrix.cpp:49
#define G_OP_MUL_VEC
Definition GMatrix.cpp:42
#define G_OP_MAT_MUL
Definition GMatrix.cpp:45
#define G_EXTRACT_LOWER
Definition GMatrix.cpp:55
#define G_SET_ROW
Definition GMatrix.cpp:48
#define G_EXTRACT_UPPER
Definition GMatrix.cpp:56
#define G_INVERT
Definition GMatrix.cpp:53
#define G_SET_COLUMN
Definition GMatrix.cpp:50
#define G_SOLVE
Definition GMatrix.cpp:54
#define G_ADD_TO_COLUMN
Definition GMatrix.cpp:52
#define G_ADD_TO_ROW
Definition GMatrix.cpp:51
#define G_OP_SUB
Definition GMatrix.cpp:44
Generic matrix class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
double angle(const GVector &a, const GVector &b)
Computes angle between vectors.
Definition GVector.cpp:974
Vector class interface definition.
Abstract matrix base class interface definition.
const int & rows(void) const
Return number of matrix rows.
int m_num_rowsel
Number of selected rows (for compressed decomposition)
void init_members(void)
Initialise class members.
std::string print_col_compression(const GChatter &chatter=NORMAL) const
Print column compression scheme if it exists.
int m_cols
Number of columns.
int m_rows
Number of rows.
const int & columns(void) const
Return number of matrix columns.
virtual GMatrixBase & operator=(const GMatrixBase &matrix)
Assignment operator.
int * m_colsel
Column selection (for compressed decomposition)
double * m_data
Matrix data.
int m_num_colsel
Number of selected columns (for compressed decomposition)
void free_members(void)
Delete class members.
std::string print_row_compression(const GChatter &chatter=NORMAL) const
Print row compression scheme if it exists.
std::string print_elements(const GChatter &chatter=NORMAL, const int &num=15) const
Print all matrix elements.
int m_alloc
Size of allocated matrix memory.
int * m_colstart
Column start indices (m_cols+1)
int * m_rowsel
Row selection (for compressed decomposition)
int m_elements
Number of elements stored in matrix.
Sparse matrix class interface definition.
Symmetric matrix class interface definition.
Generic matrix class definition.
Definition GMatrix.hpp:79
void init_members(void)
Initialise class members.
Definition GMatrix.cpp:1280
void copy_members(const GMatrix &matrix)
Copy class members.
Definition GMatrix.cpp:1292
virtual double sum(void) const
Return matrix element sum.
Definition GMatrix.hpp:353
virtual ~GMatrix(void)
Destructor.
Definition GMatrix.cpp:204
GMatrix(void)
Void matrix constructor.
Definition GMatrix.cpp:70
virtual double & at(const int &row, const int &column)
Return reference to matrix element.
Definition GMatrix.cpp:580
GMatrix extract_lower_triangle(void) const
Extract lower triangle of matrix.
Definition GMatrix.cpp:1049
virtual std::string print(const GChatter &chatter=NORMAL) const
Print matrix.
Definition GMatrix.cpp:1232
virtual GMatrix & operator*=(const GMatrix &matrix)
Unary matrix multiplication operator.
Definition GMatrix.cpp:479
virtual double fill(void) const
Return fill of matrix.
Definition GMatrix.cpp:1011
GVector solve(const GVector &vector) const
Solves linear matrix equation.
Definition GMatrix.cpp:962
void eulerx(const double &angle)
Set Euler rotation matrix around x axis.
Definition GMatrix.cpp:1120
virtual GVector row(const int &row) const
Extract row as vector from matrix.
Definition GMatrix.cpp:637
GMatrix transpose(void) const
Return transposed matrix.
Definition GMatrix.cpp:903
GMatrix invert(void) const
Return inverted matrix.
Definition GMatrix.cpp:932
virtual void add_to_row(const int &row, const GVector &vector)
Add row to matrix elements.
Definition GMatrix.cpp:812
virtual GMatrix operator-(void) const
Negate matrix elements.
Definition GMatrix.cpp:324
virtual void add_to_column(const int &column, const GVector &vector)
Add vector column into matrix.
Definition GMatrix.cpp:857
virtual GMatrix * clone(void) const
Clone matrix.
Definition GMatrix.cpp:559
virtual GMatrix & operator=(const GMatrix &matrix)
Matrix assignment operator.
Definition GMatrix.cpp:228
virtual GMatrix & operator+=(const GMatrix &matrix)
Unary matrix addition operator.
Definition GMatrix.cpp:351
virtual GMatrix & operator-=(const GMatrix &matrix)
Unary matrix subtraction operator.
Definition GMatrix.cpp:412
GMatrix abs(void) const
Return absolute of matrix.
Definition GMatrix.cpp:983
GMatrix extract_upper_triangle(void) const
Extract upper triangle of matrix.
Definition GMatrix.cpp:1088
void eulerz(const double &angle)
Set Euler rotation matrix around z axis.
Definition GMatrix.cpp:1194
void eulery(const double &angle)
Set Euler rotation matrix around y axis.
Definition GMatrix.cpp:1157
virtual GVector column(const int &column) const
Extract column as vector from matrix.
Definition GMatrix.cpp:718
void alloc_members(const int &rows, const int &columns)
Allocate matrix memory.
Definition GMatrix.cpp:1324
void free_members(void)
Delete class members.
Definition GMatrix.cpp:1302
virtual GVector operator*(const GVector &vector) const
Vector multiplication.
Definition GMatrix.cpp:289
virtual void clear(void)
Clear matrix.
Definition GMatrix.cpp:541
Vector class.
Definition GVector.hpp:46
const int & size(void) const
Return size of vector.
Definition GVector.hpp:178
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
const double deg2rad
Definition GMath.hpp:43