Commit 381fb883a159164f722de042e4771b9fa6b4f08e
1 parent
2a7cdabb
Clean up of old vector and matrix documentation
Showing
10 changed files
with
663 additions
and
917 deletions
doc/source/users/tutorial/index.rst
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
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 | ... | ... |