Commit 381fb883a159164f722de042e4771b9fa6b4f08e

Authored by Jürgen Knödlseder
1 parent 2a7cdabb

Clean up of old vector and matrix documentation

doc/source/users/tutorial/index.rst
... ... @@ -4,6 +4,6 @@ Tutorials
4 4 .. toctree::
5 5 :maxdepth: 1
6 6  
  7 + intro
7 8 sky/index
8   - linalg
9 9 opt/index
... ...
doc/source/users/tutorial/intro.rst 0 → 100644
  1 +Introduction
  2 +============
  3 +
  4 +These tutorials provide some usage examples of the GammaLib C++ library and
  5 +its Python module.
  6 +
  7 +To test the C++ examples they need to be enclosed in the following code
  8 +structure
  9 +
  10 +.. code-block:: cpp
  11 + :linenos:
  12 +
  13 + #include "GammaLib.hpp"
  14 + int main(void) {
  15 + // example code goes here
  16 + return 0;
  17 + }
  18 +
  19 +For the Python examples the gammalib module needs to be imported
  20 +
  21 +.. code-block:: python
  22 + :linenos:
  23 +
  24 + import gammalib
  25 + # example code goes here
... ...
doc/source/users/tutorial/linalg.rst deleted
1   -Linear algebra
2   ---------------
3   -
4   -Vectors
5   -~~~~~~~
6   -
7   -General
8   -^^^^^^^
9   -
10   -The :doxy:`GVector` class implements a vector as a one-dimensional array of
11   -successive double precision floating point values. You may allocate
12   -an empty vector using
13   -
14   -.. code-block:: cpp
15   -
16   - GVector vector;
17   -
18   -and a vector of specific dimension using
19   -
20   -.. code-block:: cpp
21   -
22   - GVector vector(10); // Allocates a vector with 10 elements
23   -
24   -On allocation, all elements of a vector are set to 0.
25   -
26   -You may also allocate a vector by copying from another vector
27   -
28   -.. code-block:: cpp
29   -
30   - GVector vector(10); // Allocates a vector with 10 elements
31   - GVector another = vector; // Allocates vector by copying
32   -
33   -or by using
34   -
35   -.. code-block:: cpp
36   -
37   - GVector vector = GVector(10); // Allocates a vector with 10 elements
38   -
39   -Note that there are 3 special constructors which you can use to allocate
40   -vectors with 1, 2 or 3 elements:
41   -
42   -.. code-block:: cpp
43   -
44   - GVector vector(1.0); // Allocates vector [1.0]
45   - GVector vector(1.0, 2.0); // Allocates vector [1.0, 2.0]
46   - GVector vector(1.0, 2.0, 3.0); // Allocates vector [1.0, 2.0, 3.0]
47   -
48   -You can access vector elements using the :doxy:`GVector::operator[]` operator:
49   -
50   -.. code-block:: cpp
51   -
52   - GVector vector(10); // Allocates a vector with 10 elements
53   - for (int i = 0; i < 10; ++i) {
54   - vector[i] = (i+1)*10.0; // Set elements 10, 20, ..., 100
55   - }
56   - for (int i = 0; i < 10; ++i) {
57   - std::cout << vector[i] << std::endl; // Dump all elements, one by row
58   - }
59   -
60   -Note that the :doxy:`GVector::operator[]` operator does not check the validity of the element
61   -index. If index checking is needed, use the :doxy:`GVector::at` method:
62   -
63   -
64   -.. code-block:: cpp
65   -
66   - GVector vector(10); // Allocates a vector with 10 elements
67   - for (int i = 0; i < 10; ++i) {
68   - vector.at(i) = (i+1)*10.0; // Set elements 10, 20, ..., 100
69   - }
70   - for (int i = 0; i < 10; ++i) {
71   - std::cout << vector.at(i) << std::endl; // Dump all elements, one by row
72   - }
73   -
74   -The :doxy:`GVector::at` method will throw an :doxy:`GException::out_of_range` exception
75   -in case that the specified index is not valid.
76   -
77   -You may also dump the content of a vector using
78   -
79   -.. code-block:: cpp
80   -
81   - std::cout << vector << std::endl; // Dump entire vector
82   -
83   -which in the above example will put the sequence ::
84   -
85   - (10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
86   -
87   -on the screen.
88   -
89   -
90   -Vector arithmetics
91   -^^^^^^^^^^^^^^^^^^
92   -
93   -You can handle vectors pretty much the same way you handle floating point
94   -variables. :doxy:`GVector` supports various arithmetic operations:
95   -
96   -.. code-block:: cpp
97   -
98   - GVector a; // A vector
99   - GVector b; // Another vector
100   - GVector c; // Yet another vector
101   - double s; // A double precision value
102   - ...
103   - c = a + b; // Vector + Vector addition
104   - c = a + s; // Vector + Scalar addition
105   - c = s + b; // Scalar + Vector addition
106   - c = a - b; // Vector - Vector subtraction
107   - c = a - s; // Vector - Scalar subtraction
108   - c = s - b; // Scalar - Vector subtraction
109   - s = a * b; // Vector * Vector multiplication (dot product)
110   - c = a * s; // Vector * Scalar multiplication
111   - c = s * b; // Scalar * Vector multiplication
112   - c = a / s; // Vector * Scalar division
113   -
114   -Most of these operations operate element-wise. For example, scalar
115   -additions or subtractions add or subtract a given scalar value from every
116   -vector element. And scalar multiplications and divisions multiply or
117   -divide every vector element by a given value. The dot product implements
118   -the usual formula
119   -
120   -.. math::
121   - s = \sum_{i=0}^{N-1} a_i b_i
122   -
123   -(where :math:`N` is the number of vector elements).
124   -It is obvious that the dot product, as well as vector addition and
125   -subtraction, require vectors of identical dimensions. If vectors are not
126   -identical, an :doxy:`GException::vector_mismatch` exception will be thrown:
127   -
128   -.. code-block:: cpp
129   -
130   - try {
131   - GVector a(10);
132   - GVector b(11);
133   - GVector c = a + b; // WRONG: Vectors have incompatible dimensions
134   - }
135   - catch (GVector::vector_mismatch &e) {
136   - std::cout << e.what() << std::endl; // Dimension exception is catched here
137   - throw;
138   - }
139   -
140   -Further vector operations are
141   -
142   -.. code-block:: cpp
143   -
144   - c = a; // Vector assignment
145   - c = s; // Assigns scalar to all vector elements
146   - s = c[index]; // Vector element access
147   - c += a; // c = c + a;
148   - c -= a; // c = c - a;
149   - c += s; // c = c + s;
150   - c -= s; // c = c - s;
151   - c *= s; // c = c * s;
152   - c /= s; // c = c / s;
153   - c = -a; // Vector negation
154   -
155   -Finally, you can use the comparison operators
156   -
157   -.. code-block:: cpp
158   -
159   - int equal = (a == b); // True if all elements equal
160   - int unequal = (a != b); // True if at least one elements unequal
161   -
162   -to compare all elements of a vector. If all elements are
163   -identical, the :doxy:`GVector::operator==` operator returns ``true``, otherwise ``false``.
164   -If at least one element differs, the :doxy:`GVector::operator!=` operator returns ``true``,
165   -if all elements are identical it returns ``false``.
166   -
167   -In addition to the operators, you can apply the following mathematical
168   -functions to vectors::
169   -
170   - acos atan exp sin tanh
171   - acosh atanh abs sinh pow
172   - asin cos log sqrt
173   - asinh cosh log10 tan
174   -
175   -Again, these functions should be understood to be applied element-wise.
176   -They all take a vector as argument and produce a vector as result. For
177   -example
178   -
179   -.. code-block:: cpp
180   -
181   - c = sin(a);
182   -
183   -attributes the sine of each element of vector ``a`` to vector ``c``.
184   -Additional implemented functions are
185   -
186   -.. code-block:: cpp
187   -
188   - c = cross(a, b); // Vector cross product (for 3d only)
189   - s = norm(a); // Vector norm |a|
190   - s = min(a); // Minimum element of vector
191   - s = max(a); // Maximum element of vector
192   - s = sum(a); // Sum of vector elements
193   -
194   -Finally, the following methods exist:
195   -
196   -.. code-block:: cpp
197   -
198   - int n = a.size(); // Returns number of vector elements
199   - int n = a.non_zeros(); // Returns number of non-zero vector elements
200   -
201   -
202   -Matrixes
203   -~~~~~~~~
204   -
205   -General
206   -^^^^^^^
207   -
208   -A matrix is a two-dimensional array of double precision floating point
209   -values, arranged in rows and columns. Three matrix storage classes are
210   -implemented in GammaLib:
211   -
212   -- :doxy:`GMatrix` which explicitly stores all elements of a matrix
213   -
214   -- :doxy:`GMatrixSymmetric` which implements a symmetric matrix and only stores
215   - the lower-left triangle of matrix elements
216   -
217   -- :doxy:`GMatrixSparse` which implements a sparse matrix and only stores the
218   - non-zero elements of a matrix
219   -
220   -All matrix classes derive from the abstract :doxy:`GMatrixBase` class.
221   -
222   -
223   -.. _sec_matrix_storage:
224   -
225   -Matrix storage classes
226   -^^^^^^^^^^^^^^^^^^^^^^
227   -
228   -In the most general case, the rows and columns of a matrix are stored in
229   -a continuous array of :math:`{\tt rows} \times {\tt columns}` memory
230   -locations. This storage type is referred to as a *full matrix*, and is
231   -implemented by the class :doxy:`GMatrix`. Operations on full matrixes are in
232   -general relatively fast, but memory requirements may be important to
233   -hold all the elements. In general matrixes are stored column-wise
234   -(or in column-major format). For example, the matrix ::
235   -
236   - 1 2 3 4 5
237   - 6 7 8 9 10
238   - 11 12 13 14 15
239   -
240   -is stored in memory as ::
241   -
242   - | 1 6 11 | 2 7 12 | 3 8 13 | 4 9 14 | 5 10 15 |
243   -
244   -Many physical or mathematical problems treat with a subclass of matrixes
245   -that is symmetric, i.e. for which the element :math:`(row,col)` is identical to
246   -the element :math:`(col,row)`. In this case, the duplicated elements need not to
247   -be stored. The class :doxy:`GMatrixSymmetric` implements such a storage type.
248   -:doxy:`GMatrixSymmetric` stores the lower-left triangle of the matrix in
249   -column-major format. For illustration, the matrix ::
250   -
251   - 1 2 3 4
252   - 2 5 6 7
253   - 3 6 8 9
254   - 4 7 9 10
255   -
256   -is stored in memory as ::
257   -
258   - | 1 2 3 4 | 5 6 7 | 8 9 | 10 |
259   -
260   -This divides the storage requirements to hold the matrix elements by
261   -almost a factor of two.
262   -
263   -Finally, quite often one has to deal with matrixes that contain a large
264   -number of zeros. Such matrixes are called *sparse matrixes*. If only the
265   -non-zero elements of a sparse matrix are stored the memory requirements
266   -are considerably reduced. This goes however at the expense of matrix
267   -element access, which has become now more complex. In particular,
268   -filling efficiently a sparse matrix is a non-trivial problem (see
269   -:ref:`sec_matrix_filling`). Sparse matrix storage is implemented by
270   -the :doxy:`GMatrixSparse` class. A :doxy:`GMatrixSparse` object contains
271   -three one-dimensional arrays to store the matrix elements: a double type
272   -array that contains in continuous column-major order all non-zero
273   -elements, an int type array that contains for each non-zero element the
274   -row number of its location, and an int type array that contains the
275   -storage location of the first non-zero element for each matrix column.
276   -To illustrate this storage format, the matrix ::
277   -
278   - 1 0 0 7
279   - 2 5 0 0
280   - 3 0 6 0
281   - 4 0 0 8
282   -
283   -is stored in memory as ::
284   -
285   - | 1 2 3 4 | 5 | 6 | 7 8 | Matrix elements
286   - | 0 1 2 3 | 1 | 2 | 0 3 | Row indices for all elements
287   - | 0 | 4 | 5 | 6 | Storage location of first element of each column
288   -
289   -This example is of course not very economic, since the total number of
290   -Bytes used to store the matrix is
291   -:math:`8 \times 8 + (8 + 4) \times 4 = 112` Bytes, while a full
292   -:math:`4 \times 4` matrix is stored in
293   -:math:`(4 \times 4) \times 8 = 128` Bytes (recall: a double type values
294   -takes 8 Bytes, an int type value takes 4 Bytes). For realistic large
295   -systems, however, the gain in memory space can be dramatical.
296   -
297   -The usage of the :doxy:`GMatrix`, :doxy:`GMatrixSymmetric` and :doxy:`GMatrixSparse`
298   -classes is analoguous in that they implement basically all functions and
299   -methods in an identical way. So from the semantics the user has not to worry
300   -about the storage class. However, matrix element access speeds are not
301   -identical for all storage types, and if performance is an issue (as it
302   -certainly always will be), the user has to consider matrix access more
303   -carefully (see :ref:`sec_matrix_filling`).
304   -
305   -You allocate a matrix using the constructors:
306   -
307   -.. code-block:: cpp
308   -
309   - GMatrix A(10,20); // Full 10 x 20 matrix
310   - GMatrixSymmetric B(10,10); // Symmetric 10 x 10 matrix
311   - GMatrixSparse C(1000,10000); // Sparse 1000 x 10000 matrix
312   -
313   - GMatrix A(0,0); // WRONG: empty matrix not allowed
314   - GMatrixSymmetric B(20,22); // WRONG: symmetric matrix requested
315   -
316   -In the constructor, the first argument specifies the number of rows, the
317   -second the number of columns: ``A(row,column)``. A symmetric matrix needs of
318   -course an equal number of rows and columns. And an empty matrix is not
319   -allowed. All matrix elements are initialised to 0 by the matrix
320   -allocation.
321   -
322   -You can access matrix elements using the ``()`` operator, with the first
323   -argument specifying the row and the second argument the column to be
324   -accessed (row and column indices run from 0 to the number of elements
325   -minus one):
326   -
327   -.. code-block:: cpp
328   -
329   - for (int row = 0; row < n_rows; ++row) {
330   - for (int col = 0; col < n_cols; ++col) {
331   - A(row,col) = (row+col)/2.0; // Set value of matrix element
332   - }
333   - }
334   - ...
335   - double sum2 = 0.0;
336   - for (int row = 0; row < n_rows; ++row) {
337   - for (int col = 0; col < n_cols; ++col) {
338   - sum2 *= A(row,col) * A(row,col); // Get value of matrix element
339   - }
340   - }
341   -
342   -You can dump the content of a matrix to the console using
343   -
344   -.. code-block:: cpp
345   -
346   - std::cout << A << std::endl; // Dump matrix
347   -
348   -
349   -Matrix arithmetics
350   -^^^^^^^^^^^^^^^^^^
351   -
352   -The following description of matrix arithmetics applies to all storage
353   -classes (see :ref:`sec_matrix_storage`). The following matrix
354   -operators have been implemented:
355   -
356   -.. code-block:: cpp
357   -
358   - GMatrix A;
359   - GMatrix B;
360   - GMatrix C;
361   - ...
362   - C = A + B; // Matrix Matrix addition
363   - C = A - B; // Matrix Matrix subtraction
364   - C = A * B; // Matrix Matrix multiplication
365   - C = A * v; // Matrix Vector multiplication
366   - C = A * s; // Matrix Scalar multiplication
367   - C = s * A; // Scalar Matrix multiplication
368   - C = A / s; // Matrix Scalar division
369   - C = -A; // Negation
370   - A += B; // Matrix inplace addition
371   - A -= B; // Matrix inplace subtraction
372   - A *= B; // Matrix inplace multiplications
373   - A *= s; // Matrix inplace scalar multiplication
374   - A /= s; // Matrix inplace scalar division
375   -
376   -The comparison operators
377   -
378   -.. code-block:: cpp
379   -
380   - int equal = (A == B); // True if all elements equal
381   - int unequal = (A != B); // True if at least one elements unequal
382   -
383   -allow to compare all elements of a matrix. If all elements are
384   -identical, the ``==`` operator returns ``true``, otherwise ``false``.
385   -If at least one element differs, the ``!=`` operator returns true,
386   -if all elements are identical it returns false.
387   -
388   -
389   -General matrix methods and functions
390   -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
391   -
392   -A number of methods have been implemented to manipulate matrixes. The
393   -methods described in this section are available for all storage classes.
394   -
395   -The methods
396   -
397   -.. code-block:: cpp
398   -
399   - int rows = A.rows(); // Returns number of rows in matrix
400   - int cols = A.columns(); // Returns number of columns in matrix
401   - int rows = A.size(); // Returns number of elements in matrix
402   -
403   -provide access to the matrix dimensions, the methods
404   -
405   -.. code-block:: cpp
406   -
407   - double sum = A.sum(); // Sum of all elements in matrix
408   - double min = A.min(); // Returns minimum element of matrix
409   - double max = A.max(); // Returns maximum element of matrix
410   - double fill = A.fill(); // Returns fraction of non-zero elements
411   -
412   -inform about some matrix properties. The methods
413   -
414   -.. code-block:: cpp
415   -
416   - GVector row_vector = A.row(row); // Extract matrix row into vector
417   - GVector column_vector = A.col(column); // Extract matrix column into vector
418   -
419   -extract entire rows and columns from a matrix into a vector. Conversely,
420   -you may set entire rows or columns of a matrix using the methods
421   -
422   - A.row(row, row_vector); // Add vector to column
423   - A.column(column, column_vector); // Puts vector in column
424   -
425   -
426   -The methods
427   -
428   -.. code-block:: cpp
429   -
430   - A.insert_col(v_col,col); // Puts vector in column
431   - A.add_col(v_col,col); // Add vector to column
432   -
433   -inserts or adds the elements of a vector into a matrix column. Note that
434   -no row insertion routines have been implemented (so far) since they
435   -would be less efficient (recall that all matrix types are stored in
436   -column-major format).
437   -
438   -Conversion from one storage type to another is performed using
439   -
440   -.. code-block:: cpp
441   -
442   - B = A.convert_to_full(); // Converts A -> GMatrix
443   - B = A.convert_to_sym(); // Converts A -> GMatrixSymmetric
444   - B = A.convert_to_sparse(); // Converts A -> GMatrixSparse
445   -
446   -Note that ``convert_to_sym()`` can only be applied to a matrix that is
447   -indeed symmetric.
448   -
449   -The transpose of a matrix can be obtained by using one of
450   -
451   -.. code-block:: cpp
452   -
453   - A.transpose(); // Transpose method
454   - B = transpose(A); // Transpose function
455   -
456   -The absolute value of a matrix is provided by
457   -
458   -.. code-block:: cpp
459   -
460   - B = fabs(A); // B = |A|
461   -
462   -
463   -Specific matrix methods and functions
464   -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
465   -
466   -Some methods do only exist for specific matrix storage classes. Although
467   -these methods could in principle apply to all matrix classes, they have
468   -for practical reasons not yet been implemented for all storage classes.
469   -This may change in future versions of GammaLib.
470   -
471   -
472   -GMatrix methods
473   -~~~~~~~~~~~~~~~
474   -
475   -
476   -GMatrixSymmetric methods
477   -~~~~~~~~~~~~~~~~~~~~~~~~
478   -
479   -
480   -GMatrixSparse methods
481   -~~~~~~~~~~~~~~~~~~~~~
482   -
483   -Other methods
484   -~~~~~~~~~~~~~
485   -
486   -You can extract the lower or upper triangle of a matrix into another
487   -matrix using
488   -
489   -.. code-block:: cpp
490   -
491   - GMatrix B = A.extract_lower_triangle(); // B holds lower triangle
492   - GMatrix B = A.extract_upper_triangle(); // B holds upper triangle
493   -
494   -This method is implemented for storage classes :doxy:`GMatrix` and
495   -:doxy:`GMatrixSymmetric`.
496   -
497   -
498   -
499   -Matrix factorisations
500   -^^^^^^^^^^^^^^^^^^^^^
501   -
502   -A general tool of numeric matrix calculs is factorisation.
503   -
504   -Solve linear equation ``Ax = b``. Inverse a matrix (by solving successively
505   -``Ax = e``, where ``e`` are the unit vectors for all dimensions).
506   -
507   -For symmetric and positive definite matrices the most efficient
508   -factorisation is the Cholesky decomposition. The following code fragment
509   -illustrates the usage:
510   -
511   -.. code-block:: cpp
512   -
513   - GMatrix A(n_rows, n_cols};
514   - GVector x(n_rows};
515   - GVector b(n_rows};
516   - ...
517   - A.cholesky_decompose(); // Perform Cholesky factorisation
518   - x = A.cholesky_solver(b); // Solve Ax=b for x
519   -
520   -Note that once the function ``A.cholesky_decompose()`` has been applied,
521   -the original matrix content has been replaced by its Cholesky
522   -decomposition. Since the Cholesky decomposition can be performed inplace
523   -(i.e. without the allocation of additional memory to hold the result),
524   -the matrix replacement is most memory economic. In case that the
525   -original matrix should be kept, one may either copy it before into
526   -another :doxy:`GMatrix` object or use the function
527   -
528   -.. code-block:: cpp
529   -
530   - GMatrix L = cholesky_decompose(A);
531   - x = L.cholesky_solver(b);
532   -
533   -A symmetric and positive definite matrix can be inverted using the
534   -Cholesky decomposition using
535   -
536   -.. code-block:: cpp
537   -
538   - A.cholesky_invert(); // Inverse matrix using Cholesky fact.
539   -
540   -Alternatively, the function
541   -
542   -.. code-block:: cpp
543   -
544   - GMatrix A_inv = cholesky_invert(A);
545   -
546   -may be used.
547   -
548   -The Cholesky decomposition, solver and inversion routines may also be
549   -applied to matrices that contain rows or columns that are filled by
550   -zeros. In this case the functions provide the option to (logically)
551   -compress the matrices by skipping the zero rows and columns during the
552   -calculation.
553   -
554   -For compressed matrix Cholesky factorisation, only the non-zero rows and
555   -columns have to be symmetric and positive definite. In particular, the
556   -full matrix may even be non-symmetric.
557   -
558   -Sparse matrixes
559   -^^^^^^^^^^^^^^^
560   -
561   -The only exception that does not work is
562   -
563   -.. code-block:: cpp
564   -
565   - GMatrixSparse A(10,10);
566   - A(0,0) = A(1,1) = A(2,2) = 1.0; // WRONG: Cannot assign multiple at once
567   -
568   -In this case the value ``1.0`` is only assigned to the last element, i.e.
569   -``A(2,2)``, the other elements will remain ``0``. This feature has to do with
570   -the way how the compiler translates the code and how  implements sparse
571   -matrix filling. :doxy:`GMatrixSparse` provides a pointer for a new element to be
572   -filled. Since there is only one such *fill pointer*, only one element
573   -can be filled at once in a statement. **So it is strongly advised to
574   -avoid multiple matrix element assignment in a single row.** Better write
575   -the above code like
576   -
577   -.. code-block:: cpp
578   -
579   - GMatrixSparse A;
580   - A(0,0) = 1.0;
581   - A(1,1) = 1.0;
582   - A(2,2) = 1.0;
583   -
584   -This way, element assignment works fine.
585   -
586   -Inverting a sparse matrix produces in general a full matrix, so the
587   -inversion function should be used with caution. Note that a full matrix
588   -that is stored in sparse format takes roughly twice the memory than a
589   -normal :doxy:`GMatrix` object. If nevertheless the inverse of a sparse matrix
590   -should be examined, it is recommended to perform the analysis
591   -column-wise
592   -
593   -.. code-block:: cpp
594   -
595   - GMatrixSparse A(rows,cols); // Allocate sparse matrix
596   - GVector unit(rows); // Allocate vector
597   - ...
598   - A.cholesky_decompose(); // Factorise matrix
599   -
600   - // Column-wise solving the matrix equation
601   - for (int col = 0; col < cols; ++col) {
602   - unit(col) = 1.0; // Set unit vector
603   - GVector x = cholesky_solver(unit); // Get column x of inverse
604   - ...
605   - unit(col) = 0.0; // Clear unit vector for next round
606   - }
607   -
608   -.. _sec_matrix_filling:
609   -
610   -Filling sparse matrixes
611   -^^^^^^^^^^^^^^^^^^^^^^^
612   -
613   -The filling of a sparse matrix is a tricky issue since the storage of
614   -the elements depends on their distribution in the matrix. If one would
615   -know beforehand this distribution, sparse matrix filling would be easy
616   -and fast. In general, however, the distribution is not known a priori,
617   -and matrix filling may become a quite time consuming task.
618   -
619   -If a matrix has to be filled element by element, the access through the
620   -operator
621   -
622   -.. code-block:: cpp
623   -
624   - m(row,col) = value;
625   -
626   -may be mandatory. In principle, if a new element is inserted into a
627   -matrix a new memory cell has to be allocated for this element, and other
628   -elements may be moved. Memory allocation is quite time consuming, and to
629   -reduce the overhead, :doxy:`GMatrixSparse` can be configured to allocate memory
630   -in bunches. By default, each time more matrix memory is needed,
631   -:doxy:`GMatrixSparse` allocates 512 cells at once (or 6144 Bytes since each
632   -element requires a double and a int storage location). If this amount of
633   -memory is not adequat one may change this value by using
634   -
635   -.. code-block:: cpp
636   -
637   - m.set_mem_block(size);
638   -
639   -where size is the number of matrix elements that should be allocated at
640   -once (corresponding to a total memory of :math:`12 \times {\tt size}`
641   -Bytes).
642   -
643   -Alternatively, a matrix may be filled column-wise using the functions
644   -
645   -.. code-block:: cpp
646   -
647   - m.insert_col(vector,col); // Insert a vector in column
648   - m.add_col(vector,col); // Add content of a vector to column
649   -
650   -While ``insert_col`` sets the values of column ``col`` (deleting thus any
651   -previously existing entries), ``add_col`` adds the content of vector to all
652   -elements of column col. Using these functions is considerably more rapid
653   -than filling individual values.
654   -
655   -Still, if the matrix is big (i.e. several thousands of rows and
656   -columns), filling individual columns may still be slow. To speed-up
657   -dynamical matrix filling, an internal fill-stack has been implemented in
658   -:doxy:`GMatrixSparse`. Instead of inserting values column-by-column, the columns
659   -are stored in a stack and filled into the matrix once the stack is full.
660   -This reduces the number of dynamic memory allocations to let the matrix
661   -grow as it is built. By default, the internal stack is disabled. The
662   -stack can be enabled and used as follows:
663   -
664   -.. code-block:: cpp
665   -
666   - m.stack_init(size, entries); // Initialise stack
667   - ...
668   - m.add_col(vector,col); // Add columns
669   - ...
670   - m.stack_destroy(); // Flush and destory stack
671   -
672   -The method ``stack_init`` initialises a stack with a number of size
673   -elements and a maximum of entries columns. The larger the values size
674   -and entries are chosen, the more efficient the stack works. The total
675   -amount of memory of the stack can be estimated as
676   -:math:`12 \times {\tt size} + 8 \times {\tt entries}` Bytes. If a rough
677   -estimate of the total number of non-zero elements is available it is
678   -recommended to set size to this value. As a rule of thumb, size should
679   -be at least of the dimension of either the number of rows or the number
680   -of columns of the matrix (take the maximum of both). entries is best set
681   -to the number of columns of the matrix. If memory limits are an issue
682   -smaller values may be set, but if the values are too small, the speed
683   -increase may become negligible (or stack-filling may even become slower
684   -than normal filling).
685   -
686   -Stack-filling only works with the method ``add_col``. Note also that
687   -filling sub-sequently the same column leads to stack flushing. In the
688   -code
689   -
690   -.. code-block:: cpp
691   -
692   - for (int col = 0; col < 100; ++col) {
693   - column = 0.0; // Reset column
694   - column(col) = col; // Set column
695   - m.add_col(column,col); // Add column
696   - }
697   -
698   -stack flushing occurs in each loop, and consequently, the stack-filling
699   -approach will be not very efficient (it would probably be even slover
700   -than normal filling). If successive operations are to be performed on
701   -columns, it is better to perform them before adding. The code
702   -
703   -.. code-block:: cpp
704   -
705   - column = 0.0; // Reset column
706   - for (int col = 0; col < 100; ++col)
707   - column(col) = col; // Set column
708   - m.add_col(column,col); // Add column
709   -
710   -would be far more efficient.
711   -
712   -A avoidable overhead occurs for the case that the column to be added is
713   -sparse. The vector may contain many zeros, and :doxy:`GMatrixSparse` has to
714   -filter them out. If the sparsity of the column is known, this overhead
715   -can be avoided by directly passing a compressed array to ``add_col``:
716   -
717   -.. code-block:: cpp
718   -
719   - int number = 5; // 5 elements in array
720   - double* values = new double[number]; // Allocate values
721   - int* rows = new int[number]; // Allocate row index
722   - ...
723   - m.stack_init(size, entries); // Initialise stack
724   - ...
725   - for (int i = 0; i < number; ++i) { // Initialise array
726   - values[i] = ... // ... set values
727   - rows[i] = ... // ... set row indices
728   - }
729   - ...
730   - m.add_col(values,rows,number,col); // Add array
731   - ...
732   - m.stack_destroy(); // Flush and destory stack
733   - ...
734   - delete [] values; // Free array
735   - delete [] rows;
736   -
737   -The method ``add_col`` calls the method ``stack_push_column`` for stack
738   -filling. ``add_col`` is more general than ``stack_push_column`` in that it
739   -decides which of stack- or direct filling is more adequate. In
740   -particular, ``stack_push_column`` may refuse pushing a column onto the
741   -stack if there is not enough space. In that case, ``stack_push_column``
742   -returns a non-zero value that corresponds to the number of non-zero
743   -elements in the vector that should be added. However, it is recommended
744   -to not use ``stack_push_column`` and call instead ``add_col``.
745   -
746   -The method ``stack_destroy`` is used to flush and destroy the stack. After
747   -this call the stack memory is liberated. If the stack should be flushed
748   -without destroying it, the method ``stack_flush`` may be used:
749   -
750   -.. code-block:: cpp
751   -
752   - m.stack_init(size, entries); // Initialise stack
753   - ...
754   - m.add_col(vector,col); // Add columns
755   - ...
756   - m.stack_flush(); // Simply flush stack
757   -
758   -Once flushed, the stack can be filled anew.
759   -
760   -Note that stack flushing is not automatic! This means, if one trys to
761   -use a matrix for calculs without flushing, the calculs may be wrong.
762   -**If a stack is used for filling, always flush the stack before using
763   -the matrix.**
doc/source/users/tutorial/sky/convert_coordinates.rst
... ... @@ -5,27 +5,25 @@ To convert from celestial to Galactic coordinates you can set a sky
5 5 direction in celestial coordinates and read it back in Galactic
6 6 coordinates.
7 7  
  8 +**C++**
  9 +
  10 +.. code-block:: cpp
  11 + :linenos:
  12 +
  13 + GSkyDir dir;
  14 + dir.radec_deg(83.63,22.01);
  15 + double l = dir.l_deg();
  16 + double b = dir.b_deg();
  17 + std::cout << l << ", " << b << std::endl;
  18 +
8 19 **Python**
9 20  
10 21 .. code-block:: python
11 22 :linenos:
12 23  
13   - import gammalib
14 24 dir=gammalib.GSkyDir()
15 25 dir.radec_deg(83.63,22.01)
16 26 l=dir.l_deg()
17 27 b=dir.b_deg()
18 28 print(l,b)
19 29 (184.55973405309402, -5.7891829467816827)
20   -
21   -**C++**
22   -
23   -.. code-block:: cpp
24   - :linenos:
25   -
26   - #include "GammaLib.hpp"
27   - GSkyDir dir;
28   - dir.radec_deg(83.63,22.01);
29   - double l = dir.l_deg();
30   - double b = dir.b_deg();
31   - std::cout << l << ", " << b << std::endl;
... ...
doc/source/users/tutorial/sky/convert_projections.rst
... ... @@ -6,25 +6,22 @@ into a map in cartesian projection. Map conversion is performed using the
6 6 += operator that adds the bilinearly interpolated intensity values from one
7 7 map to another. The example code applies to any kind of map projections.
8 8  
9   -**Python**
10   -
11   -.. code-block:: python
12   - :linenos:
13   -
14   - import gammalib
15   - healpix = gammalib.GSkyMap("healpix.fits")
16   - map = gammalib.GSkyMap("CAR","GAL",0.0,0.0,0.5,0.5,100,100)
17   - map += healpix
18   - map.save("carmap.fits")
19   -
20 9 **C++**
21 10  
22 11 .. code-block:: cpp
23 12 :linenos:
24 13  
25   - #include "GammaLib.hpp"
26 14 GSkyMap healpix("healpix.fits");
27 15 GSkyMap map("CAR","GAL",0.0,0.0,0.5,0.5,100,100);
28 16 map += healpix;
29 17 map.save("carmap.fits");
30 18  
  19 +**Python**
  20 +
  21 +.. code-block:: python
  22 + :linenos:
  23 +
  24 + healpix = gammalib.GSkyMap('healpix.fits')
  25 + map = gammalib.GSkyMap('CAR','GAL',0.0,0.0,0.5,0.5,100,100)
  26 + map += healpix
  27 + map.save('carmap.fits')
... ...
doc/source/users/user_manual/modules/linalg/index.rst
... ... @@ -7,4 +7,6 @@ Linear algebra
7 7 :maxdepth: 1
8 8  
9 9 overview
10   - matrix
  10 + vector
  11 + matrix_storage
  12 + matrix_arithmetics
... ...
doc/source/users/user_manual/modules/linalg/matrix.rst deleted
1   -Matrix Storage classes
2   -======================
3   -
4   -Three matrix storage classes are implemented:
5   -
6   -* :doxy:`GMatrix` implements a plain matrix storage class which stores
7   - all elements of the matrix in memory;
8   -* :doxy:`GMatrixSymmetric` implements a symmetric matrix storage class
9   - which stores only a triangle of matrix elements, imposing thus
10   - strict matrix symmetry;
11   -* :doxy:`GMatrixSparse` implements a sparse matrix storage class which
12   - stores only non-zero matrix elements in a column-wise organisation.
13   -
14   -Storage class conversion constructors exist for all three classes
15   -to transform one storage class into another:
16   -
17   -**Python**
18   -
19   -.. code-block:: python
20   - :linenos:
21   -
22   - plain = gammalib.GMatrix(10,10)
23   - symmetric = gammalib.GMatrixSymmetric(plain)
24   - sparse = gammalib.GMatrixSparse(symmetric)
25   -
26   -**C++**
27   -
28   -.. code-block:: cpp
29   - :linenos:
30   -
31   - GMatrix plain(10,10);
32   - GMatrixSymmetric symmetric(plain);
33   - GMatrixSparse sparse(symmetric);
34   -
35   -In the above example, a plain matrix is instantiated in line 1, the
36   -plain matrix is converted into a symmetric matrix in line 2, and the
37   -symmetric matrix is converted into a sparse matrix in line 3.
38   -Additional complementary storage class conversion constructors exist,
39   -but conversion to a symmetric matrix is of course only possible if the
40   -matrix is indeed symmetric.
41   -
42   -Matrix elements are accessed using the ``operator()``. Filling of
43   -sparse matrix elements using this operator is possible, although this
44   -can be time consuming due to internal memory management. In general,
45   -each fill of a new non-zero element needs to shift all elements
46   -that are located after that element in memory.
47   -
48   -To reduce the memory management overhead in the filling of a sparse
49   -matrix, methods have been implemented that allow to fill a
50   -matrix column wise:
51   -
52   -**Python**
53   -
54   -.. code-block:: cpp
55   - :linenos:
56   -
57   - sparse = gammalib.GMatrixSparse(10,5)
58   - column = gammalib.GVector(10)
59   - column[0] = 1.0
60   - column[1] = 2.0
61   - column[5] = 8.0
62   - sparse.column(0, column)
63   - sparse.add_to_column(0, column)
64   -
65   -**C++**
66   -
67   -.. code-block:: cpp
68   - :linenos:
69   -
70   - GMatrixSparse sparse(10,5);
71   - GVector column(10);
72   - column[0] = 1.0;
73   - column[1] = 2.0;
74   - column[5] = 8.0;
75   - sparse.column(0, column);
76   - sparse.add_to_column(0, column);
77   -
78   -Line 1 allocates a sparse matrix with 10 rows and 5 columns, line 2
79   -instantiates a vector with 10 elements. In lines 3-5, 3 elements of
80   -the vector are set to specific values, all other elements will default
81   -to 0. In line 6, the elements of the vector are set as the elements
82   -of the first matrix column (column 0). Line 7 differs from line 6 in
83   -that the elements are now not set but added to the existing matrix
84   -elements.
85   -
86   -To further reduce the memory management overhead for the column-wise
87   -fill of a sparse matrix, a "fill-stack" has been implemented. The
88   -"fill-stack" is a buffer that implements a queue for columns that are
89   -to be set or added to the matrix. The columns will be stored in this
90   -"fill-stack" in the order they are provided, and only once the
91   -"fill-stack" is full, or upon request, the "fill-stack" will be flushed
92   -into memory. The "fill-stack" is used as follows:
93   -
94   -**C++**
95   -
96   -.. code-block:: cpp
97   - :linenos:
98   -
99   - sparse.stack_init(size, entries);
100   - ...
101   - sparse.column(0, column);
102   - ...
103   - sparse.stack_flush();
104   - ...
105   - sparse.stack_destroy();
106   -
107   -The ``stack_init(size, entries)`` method initialises the "fill-stack",
108   -where ``size`` is the size of the allocated memory buffer and ``entries``
109   -is the maximum number of columns that will be held by the buffer.
110   -If ``size`` is set to 0 (the default value), a default ``size`` value of
111   -512 is used. If ``entries`` is set to 0 (the default value), the number of
112   -matrix columns is taken as default ``entries`` value. Note that a too large
113   -number of elements will produce some overhead due to "fill-stack"
114   -management, hence ``entries`` should not exceeed a value of the order of
115   -10-100.
116   -
117   -The ``stack_flush()`` method flushes the stack, which is mandatory
118   -before any usage of the matrix. Note that the "fill-stack" **is not
119   -inserted automatically** before any matrix operation, hence manual stack
120   -flushing is needed to make all filled matrix elements available for usage.
121   -The ``stack_destroy()`` method will flush the stack and free all stack
122   -elements. This method should be called once no filling is required anymore.
123   -If ``stack_destroy()`` is called immediately after filling, no call to
124   -``stack_flush()`` is needed as the ``stack_destroy()`` method flushes the
125   -stack before destroying it. The matrix stack is also destroyed by the
126   -sparse matrix destructor, hence manual stack destruction is not
127   -mandatory.
doc/source/users/user_manual/modules/linalg/matrix_arithmetics.rst 0 → 100644
  1 +Matrix arithmetics
  2 +==================
  3 +
  4 +The following description of matrix arithmetics applies to all storage classes.
  5 +The following matrix operators have been implemented:
  6 +
  7 +**C++**
  8 +
  9 +.. code-block:: cpp
  10 + :linenos:
  11 +
  12 + GMatrix A(10,10); // A 10 x 10 matrix
  13 + GMatrix B(10,10); // Another 10 x 10 matrix
  14 + GMatrix C; // Result matrix
  15 + GVector v(10); // Vector with 10 elements
  16 + double s = 2.0; // Floating point value
  17 + C = A + B; // Matrix addition
  18 + C = A - B; // Matrix subtraction
  19 + C = A * B; // Matrix multiplication
  20 + C = A * v; // Vector multiplication
  21 + C = A * s; // Right-handed scalar multiplication
  22 + C = s * A; // Left-handed scalar Matrix multiplication (only C++)
  23 + C = A / s; // Scalar division
  24 + C = -A; // Negation
  25 + A += B; // Unary matrix addition
  26 + A -= B; // Unary matrix subtraction
  27 + A *= B; // Unary matrix multiplications
  28 + A *= s; // Unary matrix scalar multiplication
  29 + A /= s; // Unary matrix scalar division
  30 +
  31 +**Python**
  32 +
  33 +.. code-block:: python
  34 + :linenos:
  35 +
  36 + A = gammalib.GMatrix(10,10) # A 10 x 10 matrix
  37 + B = gammalib.GMatrix(10,10) # Another 10 x 10 matrix
  38 + v = gammalib.GVector(10) # Vector with 10 elements
  39 + s = 2.0 # Floating point value
  40 + C = A + B # Matrix addition
  41 + C = A - B # Matrix subtraction
  42 + C = A * B # Matrix multiplication
  43 + C = A * v # Vector multiplication
  44 + C = A * s # Scalar multiplication
  45 + C = A / s # Scalar division
  46 + C = -A # Negation
  47 + A += B # Unary matrix addition
  48 + A -= B # Unary matrix subtraction
  49 + A *= B # Unary matrix multiplications
  50 + A *= s # Unary matrix scalar multiplication
  51 + A /= s # Unary matrix scalar division
  52 +
  53 +You can use the comparison operators
  54 +
  55 +**C++**
  56 +
  57 +.. code-block:: cpp
  58 + :linenos:
  59 +
  60 + int equal = (A == B); // True if all elements equal
  61 + int unequal = (A != B); // True if at least one elements unequal
  62 +
  63 +**Python**
  64 +
  65 +.. code-block:: python
  66 + :linenos:
  67 +
  68 + equal = (A == B) # True if all elements equal
  69 + unequal = (A != B) # True if at least one elements unequal
  70 +
  71 +In addition to the operators, you can apply the following mathematical functions
  72 +to a matrix:
  73 +
  74 +**C++**
  75 +
  76 +.. code-block:: cpp
  77 + :linenos:
  78 +
  79 + C = A.abs(); // Matrix with absolute values of all matrix elements
  80 + C = A.transpose(); // Transpose matrix
  81 + C = A.invert(); // Invert matrix
  82 + v = A.solve(v); // Solve matrix equation x = M x v
  83 + s = A.min(); // Minimum element of matrix
  84 + s = A.max(); // Maximum element of matrix
  85 + s = A.sum(); // Sum of matrix elements
  86 +
  87 +**Python**
  88 +
  89 +.. code-block:: python
  90 + :linenos:
  91 +
  92 + C = A.abs() # Matrix with absolute values of all matrix elements
  93 + C = A.transpose() # Transpose matrix
  94 + C = A.invert() # Invert matrix
  95 + v = A.solve(v) # Solve matrix equation x = M x v
  96 + s = A.min() # Minimum element of matrix
  97 + s = A.max() # Maximum element of matrix
  98 + s = A.sum() # Sum of matrix elements
  99 +
  100 +.. warning::
  101 + The ``invert()`` and ``solve()`` methods are so far only implemented for
  102 + sparse matrices.
... ...
doc/source/users/user_manual/modules/linalg/matrix_storage.rst 0 → 100644
  1 +Matrix storage classes
  2 +======================
  3 +
  4 +A matrix is a two-dimensional array of double precision floating point
  5 +values, arranged in rows and columns. Three matrix storage classes are
  6 +implemented in GammaLib:
  7 +
  8 +- :doxy:`GMatrix` which explicitly stores all elements of a matrix
  9 +
  10 +- :doxy:`GMatrixSymmetric` which implements a symmetric matrix and only stores
  11 + the lower-left triangle of matrix elements
  12 +
  13 +- :doxy:`GMatrixSparse` which implements a sparse matrix and only stores the
  14 + non-zero elements of a matrix
  15 +
  16 +All matrix classes derive from the abstract :doxy:`GMatrixBase` class.
  17 +
  18 +In the most general case, the rows and columns of a matrix are stored in
  19 +a continuous array of :math:`{\tt rows} \times {\tt columns}` memory
  20 +locations. This storage type is referred to as a *full matrix*, and is
  21 +implemented by the class :doxy:`GMatrix`. Operations on full matrixes are in
  22 +general relatively fast, but memory requirements may be important to
  23 +hold all the elements. In general matrixes are stored column-wise
  24 +(or in column-major format). For example, the matrix ::
  25 +
  26 + 1 2 3 4 5
  27 + 6 7 8 9 10
  28 + 11 12 13 14 15
  29 +
  30 +is stored in memory as ::
  31 +
  32 + | 1 6 11 | 2 7 12 | 3 8 13 | 4 9 14 | 5 10 15 |
  33 +
  34 +Many physical or mathematical problems treat with a subclass of matrixes
  35 +that is symmetric, i.e. for which the element :math:`(row,col)` is identical to
  36 +the element :math:`(col,row)`. In this case, the duplicated elements need not to
  37 +be stored. The class :doxy:`GMatrixSymmetric` implements such a storage type.
  38 +:doxy:`GMatrixSymmetric` stores the lower-left triangle of the matrix in
  39 +column-major format. For illustration, the matrix ::
  40 +
  41 + 1 2 3 4
  42 + 2 5 6 7
  43 + 3 6 8 9
  44 + 4 7 9 10
  45 +
  46 +is stored in memory as ::
  47 +
  48 + | 1 2 3 4 | 5 6 7 | 8 9 | 10 |
  49 +
  50 +This divides the storage requirements to hold the matrix elements by
  51 +almost a factor of two.
  52 +
  53 +Finally, quite often one has to deal with matrixes that contain a large
  54 +number of zeros. Such matrixes are called *sparse matrixes*. If only the
  55 +non-zero elements of a sparse matrix are stored the memory requirements
  56 +are considerably reduced. This goes however at the expense of matrix
  57 +element access, which has become now more complex. In particular,
  58 +filling efficiently a sparse matrix is a non-trivial problem (see
  59 +:ref:`sec_matrix_filling`). Sparse matrix storage is implemented by
  60 +the :doxy:`GMatrixSparse` class. A :doxy:`GMatrixSparse` object contains
  61 +three one-dimensional arrays to store the matrix elements: a double type
  62 +array that contains in continuous column-major order all non-zero
  63 +elements, an int type array that contains for each non-zero element the
  64 +row number of its location, and an int type array that contains the
  65 +storage location of the first non-zero element for each matrix column.
  66 +To illustrate this storage format, the matrix ::
  67 +
  68 + 1 0 0 7
  69 + 2 5 0 0
  70 + 3 0 6 0
  71 + 4 0 0 8
  72 +
  73 +is stored in memory as ::
  74 +
  75 + | 1 2 3 4 | 5 | 6 | 7 8 | Matrix elements
  76 + | 0 1 2 3 | 1 | 2 | 0 3 | Row indices for all elements
  77 + | 0 | 4 | 5 | 6 | Storage location of first element of each column
  78 +
  79 +This example is of course not very economic, since the total number of
  80 +Bytes used to store the matrix is
  81 +:math:`8 \times 8 + (8 + 4) \times 4 = 112` Bytes, while a full
  82 +:math:`4 \times 4` matrix is stored in
  83 +:math:`(4 \times 4) \times 8 = 128` Bytes (recall: a double type values
  84 +takes 8 Bytes, an int type value takes 4 Bytes). For realistic large
  85 +systems, however, the gain in memory space can be dramatical.
  86 +
  87 +The usage of the :doxy:`GMatrix`, :doxy:`GMatrixSymmetric` and :doxy:`GMatrixSparse`
  88 +classes is analoguous in that they implement basically all functions and
  89 +methods in an identical way. So from the semantics the user has not to worry
  90 +about the storage class. However, matrix element access speeds are not
  91 +identical for all storage types, and if performance is an issue (as it
  92 +certainly always will be), the user has to consider matrix access more
  93 +carefully (see :ref:`sec_matrix_filling`).
  94 +
  95 +You allocate a matrix using the constructors
  96 +
  97 +**C++**
  98 +
  99 +.. code-block:: cpp
  100 + :linenos:
  101 +
  102 + GMatrix A(10,20); // Full 10 x 20 matrix
  103 + GMatrixSymmetric B(10,10); // Symmetric 10 x 10 matrix
  104 + GMatrixSparse C(1000,10000); // Sparse 1000 x 10000 matrix
  105 +
  106 + GMatrix D(0,0); // WRONG: empty matrix not allowed
  107 + GMatrixSymmetric E(20,22); // WRONG: symmetric matrix requested
  108 +
  109 +**Python**
  110 +
  111 +.. code-block:: python
  112 + :linenos:
  113 +
  114 + A = gammalib.GMatrix(10,20) # Full 10 x 20 matrix
  115 + B = gammalib.GMatrixSymmetric(10,10) # Symmetric 10 x 10 matrix
  116 + C = gammalib.GMatrixSparse(1000,10000) # Sparse 1000 x 10000 matrix
  117 +
  118 + D = gammalib.GMatrix(0,0) # WRONG: empty matrix not allowed
  119 + E = gammalib.GMatrixSymmetric(20,22) # WRONG: symmetric matrix requested
  120 +
  121 +
  122 +In the constructor, the first argument specifies the number of rows, the
  123 +second the number of columns: ``A(row,column)``. A symmetric matrix needs of
  124 +course an equal number of rows and columns. And an empty matrix is not
  125 +allowed. All matrix elements are initialised to 0 by the matrix
  126 +allocation.
  127 +
  128 +Storage class conversion constructors exist for all three classes
  129 +to transform one storage class into another:
  130 +
  131 +**C++**
  132 +
  133 +.. code-block:: cpp
  134 + :linenos:
  135 +
  136 + GMatrix full(10,10);
  137 + GMatrixSymmetric symmetric(plain);
  138 + GMatrixSparse sparse(symmetric);
  139 +
  140 +**Python**
  141 +
  142 +.. code-block:: python
  143 + :linenos:
  144 +
  145 + full = gammalib.GMatrix(10,10)
  146 + symmetric = gammalib.GMatrixSymmetric(full)
  147 + sparse = gammalib.GMatrixSparse(symmetric)
  148 +
  149 +Matrix elements are accessed using
  150 +
  151 +**C++**
  152 +
  153 +.. code-block:: cpp
  154 + :linenos:
  155 +
  156 + std::cout << B(5,7) << std::endl; // Matrix access in C++ through () operator
  157 +
  158 +**Python**
  159 +
  160 +.. code-block:: python
  161 + :linenos:
  162 +
  163 + print(B[5,7]) # Matrix access in Python through [] operator
  164 +
  165 +Filling of sparse matrix elements using this operator is possible, although
  166 +this can be time consuming due to internal memory management. In general,
  167 +each fill of a new non-zero element needs to shift all elements
  168 +that are located after that element in memory.
  169 +
  170 +To reduce the memory management overhead in the filling of a sparse matrix,
  171 +methods have been implemented that allow to fill a matrix column wise:
  172 +
  173 +**C++**
  174 +
  175 +.. code-block:: cpp
  176 + :linenos:
  177 +
  178 + GMatrixSparse sparse(10,5);
  179 + GVector column(10);
  180 + column[0] = 1.0;
  181 + column[1] = 2.0;
  182 + column[5] = 8.0;
  183 + sparse.column(0, column);
  184 + sparse.add_to_column(0, column);
  185 +
  186 +**Python**
  187 +
  188 +.. code-block:: cpp
  189 + :linenos:
  190 +
  191 + sparse = gammalib.GMatrixSparse(10,5)
  192 + column = gammalib.GVector(10)
  193 + column[0] = 1.0
  194 + column[1] = 2.0
  195 + column[5] = 8.0
  196 + sparse.column(0, column)
  197 + sparse.add_to_column(0, column)
  198 +
  199 +Line 1 allocates a sparse matrix with 10 rows and 5 columns, line 2
  200 +instantiates a vector with 10 elements. In lines 3-5, 3 elements of
  201 +the vector are set to specific values, all other elements will default
  202 +to 0. In line 6, the elements of the vector are set as the elements
  203 +of the first matrix column (column 0). Line 7 differs from line 6 in
  204 +that the elements are now not set but added to the existing matrix
  205 +elements.
  206 +
  207 +To further reduce the memory management overhead for the column-wise
  208 +fill of a sparse matrix, a "fill-stack" has been implemented. The
  209 +"fill-stack" is a buffer that implements a queue for columns that are
  210 +to be set or added to the matrix. The columns will be stored in this
  211 +"fill-stack" in the order they are provided, and only once the
  212 +"fill-stack" is full, or upon request, the "fill-stack" will be flushed
  213 +into memory. The "fill-stack" is used as follows:
  214 +
  215 +**C++**
  216 +
  217 +.. code-block:: cpp
  218 + :linenos:
  219 +
  220 + sparse.stack_init(size, entries);
  221 + ...
  222 + sparse.column(0, column);
  223 + ...
  224 + sparse.stack_flush();
  225 + ...
  226 + sparse.stack_destroy();
  227 +
  228 +The ``stack_init(size, entries)`` method initialises the "fill-stack",
  229 +where ``size`` is the size of the allocated memory buffer and ``entries``
  230 +is the maximum number of columns that will be held by the buffer.
  231 +If ``size`` is set to 0 (the default value), a default ``size`` value of
  232 +512 is used. If ``entries`` is set to 0 (the default value), the number of
  233 +matrix columns is taken as default ``entries`` value. Note that a too large
  234 +number of elements will produce some overhead due to "fill-stack"
  235 +management, hence ``entries`` should not exceeed a value of the order of
  236 +10-100.
  237 +
  238 +The ``stack_flush()`` method flushes the stack, which is mandatory
  239 +before any usage of the matrix. Note that the "fill-stack" **is not
  240 +inserted automatically** before any matrix operation, hence manual stack
  241 +flushing is needed to make all filled matrix elements available for usage.
  242 +The ``stack_destroy()`` method will flush the stack and free all stack
  243 +elements. This method should be called once no filling is required anymore.
  244 +If ``stack_destroy()`` is called immediately after filling, no call to
  245 +``stack_flush()`` is needed as the ``stack_destroy()`` method flushes the
  246 +stack before destroying it. The matrix stack is also destroyed by the
  247 +sparse matrix destructor, hence manual stack destruction is not
  248 +mandatory.
... ...
doc/source/users/user_manual/modules/linalg/vector.rst 0 → 100644
  1 +Vectors
  2 +=======
  3 +
  4 +The :doxy:`GVector` class implements a vector as a one-dimensional array of
  5 +successive double precision floating point values. You may allocate
  6 +an vectors as follows
  7 +
  8 +**C++**
  9 +
  10 +.. code-block:: cpp
  11 + :linenos:
  12 +
  13 + GVector vector1; // Allocates empty vector
  14 + GVector vector2(10); // Allocates vector with 10 elements
  15 + GVector vector3 = vector1; // Allocates vector by copying
  16 +
  17 +**Python**
  18 +
  19 +.. code-block:: python
  20 + :linenos:
  21 +
  22 + vector1 = gammalib.GVector() # Allocates empty vector
  23 + vector2 = gammalib.GVector(10) # Allocates vector with 10 elements
  24 + vector3 = vector1.copy() # Allocates vector by copying
  25 +
  26 +On allocation, all elements of a vector are set to 0.
  27 +
  28 +There are three special constructors which you can use to allocate vectors
  29 +with 1, 2 or 3 elements:
  30 +
  31 +**C++**
  32 +
  33 +.. code-block:: cpp
  34 + :linenos:
  35 +
  36 + GVector vector1(1.0); // Allocates vector [1.0]
  37 + GVector vector2(1.0, 2.0); // Allocates vector [1.0, 2.0]
  38 + GVector vector3(1.0, 2.0, 3.0); // Allocates vector [1.0, 2.0, 3.0]
  39 +
  40 +**Python**
  41 +
  42 +.. code-block:: python
  43 + :linenos:
  44 +
  45 + vector1 = gammalib.GVector(1.0) # Allocates vector [1.0]
  46 + vector2 = gammalib.GVector(1.0, 2.0) # Allocates vector [1.0, 2.0]
  47 + vector3 = gammalib.GVector(1.0, 2.0, 3.0) # Allocates vector [1.0, 2.0, 3.0]
  48 +
  49 +You can access vector elements using the :doxy:`GVector::operator[]` operator.
  50 +As usual in C++ and Python, indices start with 0:
  51 +
  52 +**C++**
  53 +
  54 +.. code-block:: cpp
  55 + :linenos:
  56 +
  57 + std::cout << vector2[1] << std::endl; // Print 2nd element
  58 + 2.0 // Result
  59 +
  60 +**Python**
  61 +
  62 +.. code-block:: python
  63 + :linenos:
  64 +
  65 + print(vector2[1]) # Print 2nd element
  66 + 2.0 # Result
  67 +
  68 +Note that in C++ the :doxy:`GVector::operator[]` operator does not check the
  69 +validity of the element index. If index checking is needed in C++, use the
  70 +:doxy:`GVector::at` method:
  71 +
  72 +**C++**
  73 +
  74 +.. code-block:: cpp
  75 + :linenos:
  76 +
  77 + std::cout << vector2.at(1) << std::endl; // Print 2nd element with index checking
  78 + 2.0 // Result
  79 +
  80 +In Python, index checking is always performed.
  81 +
  82 +All GammaLib objects are printable, and vectors can be printed using
  83 +
  84 +**C++**
  85 +
  86 +.. code-block:: cpp
  87 + :linenos:
  88 +
  89 + std::cout << vector3 << std::endl; // Print vector
  90 + (1, 2, 3) // Result
  91 +
  92 +**Python**
  93 +
  94 +.. code-block:: python
  95 + :linenos:
  96 +
  97 + print(vector3) # Print result
  98 + (1, 2, 3) # Result
  99 +
  100 +
  101 +You can handle vectors pretty much the same way you handle floating point
  102 +variables. :doxy:`GVector` supports various arithmetic operations:
  103 +
  104 +**C++**
  105 +
  106 +.. code-block:: cpp
  107 + :linenos:
  108 +
  109 + GVector a(1.0, 2.0, 3.0); // A vector
  110 + GVector b(2.0, 4.0, 6.0); // Another vector
  111 + GVector c; // Result vector
  112 + double s = 2.0; // A floating point value
  113 + c = a + b; // Vector + Vector addition
  114 + c += a; // Unary vector addition
  115 + c = a + s; // Vector + Scalar addition
  116 + c += s; // Unary scalar addition
  117 + c = s + b; // Scalar + Vector addition (only C++)
  118 + c = a - b; // Vector - Vector subtraction
  119 + c -= a; // Unary vector subtraction
  120 + c = a - s; // Vector - Scalar subtraction
  121 + c -= s; // Unary scalar subtraction
  122 + c = s - b; // Scalar - Vector subtraction (only C++)
  123 + s = a * b; // Vector * Vector multiplication (dot product)
  124 + c = a * s; // Vector * Scalar multiplication
  125 + c *= s; // Unary scalar multiplication
  126 + c = s * b; // Scalar * Vector multiplication (only C++)
  127 + c = a / s; // Vector * Scalar division
  128 + c /= s; // Unary scalar division
  129 + c = s; // Assigns scalar to all vector elements
  130 + c = -a; // Vector negation
  131 +
  132 +**Python**
  133 +
  134 +.. code-block:: python
  135 + :linenos:
  136 +
  137 + a = gammalib.GVector(1.0, 2.0, 3.0) # A vector
  138 + b = gammalib.GVector(2.0, 4.0, 6.0) # Another vector
  139 + c = gammalib.GVector() # Result vector
  140 + s = 2.0 # A floating point value
  141 + c = a + b # Vector + Vector addition
  142 + c += a # Unary vector addition
  143 + c = a + s # Vector + Scalar addition
  144 + c += s # Unary scalar addition
  145 + c = a - b # Vector - Vector subtraction
  146 + c -= a # Unary vector subtraction
  147 + c = a - s # Vector - Scalar subtraction
  148 + c -= s # Unary scalar subtraction
  149 + s = a * b # Vector * Vector multiplication (dot product)
  150 + c = a * s # Vector * Scalar multiplication
  151 + c *= s # Unary scalar multiplication
  152 + c = a / s # Vector * Scalar division
  153 + c /= s # Unary scalar division
  154 + c = -a # Vector negation
  155 +
  156 +Most of these operations operate element-wise. For example, scalar
  157 +additions or subtractions add or subtract a given scalar value from every
  158 +vector element. And scalar multiplications and divisions multiply or
  159 +divide every vector element by a given value. The dot product implements
  160 +the usual formula
  161 +
  162 +.. math::
  163 + s = \sum_{i=0}^{N-1} a_i b_i
  164 +
  165 +(where :math:`N` is the number of vector elements).
  166 +It is obvious that the dot product, as well as vector addition and
  167 +subtraction, require vectors of identical dimensions. If vectors are not
  168 +identical, an :doxy:`GException::vector_mismatch` exception will be thrown.
  169 +
  170 +You can compare vectors using
  171 +
  172 +Finally, you can use the comparison operators
  173 +
  174 +**C++**
  175 +
  176 +.. code-block:: cpp
  177 + :linenos:
  178 +
  179 + int equal = (a == b); // True if all elements equal
  180 + int unequal = (a != b); // True if at least one elements unequal
  181 +
  182 +**Python**
  183 +
  184 +.. code-block:: python
  185 + :linenos:
  186 +
  187 + equal = (a == b) # True if all elements equal
  188 + unequal = (a != b) # True if at least one elements unequal
  189 +
  190 +In addition to the operators, you can apply the following mathematical functions
  191 +to vectors
  192 +
  193 +**C++**
  194 +
  195 +.. code-block:: cpp
  196 + :linenos:
  197 +
  198 + c = acos(a); // Vector with acos of all vector elements
  199 + c = acosh(a); // Vector with acosh of all vector elements
  200 + c = asin(a); // Vector with asin of all vector elements
  201 + c = asinh(a); // Vector with asinh of all vector elements
  202 + c = atan(a); // Vector with atan of all vector elements
  203 + c = atanh(a); // Vector with atanh of all vector elements
  204 + c = cos(a); // Vector with cos of all vector elements
  205 + c = cosh(a); // Vector with cosh of all vector elements
  206 + c = exp(a); // Vector with exp of all vector elements
  207 + c = abs(a); // Vector with absolute values of all vector elements
  208 + c = log(a); // Vector with natural logarithm of all vector elements
  209 + c = log10(a); // Vector with base 10 logarithm of all vector elements
  210 + c = sin(a); // Vector with sin of all vector elements
  211 + c = sinh(a); // Vector with sinh of all vector elements
  212 + c = tan(a); // Vector with tan of all vector elements
  213 + c = tanh(a); // Vector with tanh of all vector elements
  214 + c = pow(a, 2.7); // Vector with power of 2.7 of all vector elements (only C++)
  215 + c = cross(a, b); // Vector with cross product of 3 element vectors
  216 + s = norm(a); // Vector norm |a|
  217 + s = min(a); // Minimum element of vector
  218 + s = max(a); // Maximum element of vector
  219 + s = sum(a); // Sum of vector elements
  220 +
  221 +**Python**
  222 +
  223 +.. code-block:: python
  224 + :linenos:
  225 +
  226 + c = a.acos() # Vector with acos of all vector elements
  227 + c = a.acosh() # Vector with acosh of all vector elements
  228 + c = a.asin() # Vector with asin of all vector elements
  229 + c = a.asinh() # Vector with asinh of all vector elements
  230 + c = a.atan() # Vector with atan of all vector elements
  231 + c = a.atanh() # Vector with atanh of all vector elements
  232 + c = a.cos() # Vector with cos of all vector elements
  233 + c = a.cosh() # Vector with cosh of all vector elements
  234 + c = a.exp() # Vector with exp of all vector elements
  235 + c = a.abs() # Vector with absolute values of all vector elements
  236 + c = a.log() # Vector with natural logarithm of all vector elements
  237 + c = a.log10() # Vector with base 10 logarithm of all vector elements
  238 + c = a.sin() # Vector with sin of all vector elements
  239 + c = a.sinh() # Vector with sinh of all vector elements
  240 + c = a.tan() # Vector with tan of all vector elements
  241 + c = a.tanh() # Vector with tanh of all vector elements
  242 + c = a.cross(b) # Vector with cross product of 3 element vectors
  243 + s = a.norm() # Vector norm |a|
  244 + s = a.min() # Minimum element of vector
  245 + s = a.max() # Maximum element of vector
  246 + s = a.sum() # Sum of vector elements
  247 +
  248 +Finally, the following methods exist:
  249 +
  250 +**C++**
  251 +
  252 +.. code-block:: cpp
  253 + :linenos:
  254 +
  255 + int size = a.size(); // Returns number of vector elements
  256 + int nonzeros = a.non_zeros(); // Returns number of non-zero vector elements
  257 +
  258 +**Python**
  259 +
  260 +.. code-block:: python
  261 + :linenos:
  262 +
  263 + size = a.size(a) # Returns number of vector elements
  264 + nonzeros = a.non_zeros() # Returns number of non-zero vector elements
... ...