Commit 5b16109ee05eb1e6c4fccf7a231fd12688d66dde
1 parent
ef62b5af
Rework matrix transformation methods.
The methods transpose(), invert() and abs() now return a matrix instead of working on the actual matrix. The transpose(), inverse(), abs(), and negate() friend functions have been removed. The method solve() has been added that solves the linear matrix equation. The Cholesky methods now also return a matrix instead of working on the actual object.
Showing
11 changed files
with
485 additions
and
622 deletions
include/GMatrix.hpp
| ... | ... | @@ -34,6 +34,7 @@ |
| 34 | 34 | /* __ Forward declarations _______________________________________________ */ |
| 35 | 35 | class GMatrixSymmetric; |
| 36 | 36 | class GMatrixSparse; |
| 37 | +class GVector; | |
| 37 | 38 | |
| 38 | 39 | |
| 39 | 40 | /***********************************************************************//** |
| ... | ... | @@ -115,10 +116,6 @@ public: |
| 115 | 116 | virtual void column(const int& column, const GVector& vector); |
| 116 | 117 | virtual void add_to_row(const int& row, const GVector& vector); |
| 117 | 118 | virtual void add_to_column(const int& column, const GVector& vector); |
| 118 | - virtual void transpose(void); | |
| 119 | - virtual void invert(void); | |
| 120 | - virtual void negate(void); | |
| 121 | - virtual void abs(void); | |
| 122 | 119 | virtual double fill(void) const; |
| 123 | 120 | virtual double min(void) const; |
| 124 | 121 | virtual double max(void) const; |
| ... | ... | @@ -126,11 +123,16 @@ public: |
| 126 | 123 | virtual std::string print(const GChatter& chatter = NORMAL) const; |
| 127 | 124 | |
| 128 | 125 | // Other methods |
| 129 | - virtual GMatrix extract_lower_triangle(void) const; | |
| 130 | - virtual GMatrix extract_upper_triangle(void) const; | |
| 131 | - virtual void eulerx(const double& angle); | |
| 132 | - virtual void eulery(const double& angle); | |
| 133 | - virtual void eulerz(const double& angle); | |
| 126 | + GMatrix transpose(void) const; | |
| 127 | + GMatrix invert(void) const; | |
| 128 | + GVector solve(const GVector& vector) const; | |
| 129 | + GMatrix negate(void) const; | |
| 130 | + GMatrix abs(void) const; | |
| 131 | + GMatrix extract_lower_triangle(void) const; | |
| 132 | + GMatrix extract_upper_triangle(void) const; | |
| 133 | + void eulerx(const double& angle); | |
| 134 | + void eulery(const double& angle); | |
| 135 | + void eulerz(const double& angle); | |
| 134 | 136 | |
| 135 | 137 | private: |
| 136 | 138 | // Private methods |
| ... | ... | @@ -262,23 +264,6 @@ GMatrix& GMatrix::operator/=(const double& scalar) |
| 262 | 264 | |
| 263 | 265 | |
| 264 | 266 | /***********************************************************************//** |
| 265 | - * @brief Negate matrix elements | |
| 266 | - * | |
| 267 | - * @return Matrix with negated elements. | |
| 268 | - * | |
| 269 | - * Returns a matrix where each element has been replaced by its negative | |
| 270 | - * element. | |
| 271 | - ***************************************************************************/ | |
| 272 | -inline | |
| 273 | -GMatrix GMatrix::operator-(void) const | |
| 274 | -{ | |
| 275 | - GMatrix result = *this; | |
| 276 | - result.negate(); | |
| 277 | - return result; | |
| 278 | -} | |
| 279 | - | |
| 280 | - | |
| 281 | -/***********************************************************************//** | |
| 282 | 267 | * @brief Return minimum matrix element |
| 283 | 268 | * |
| 284 | 269 | * @return Minimum element in matrix. |
| ... | ... | @@ -373,57 +358,4 @@ GMatrix operator/(const GMatrix& matrix, const double& scalar) |
| 373 | 358 | return result; |
| 374 | 359 | } |
| 375 | 360 | |
| 376 | - | |
| 377 | -/***********************************************************************//** | |
| 378 | - * @brief Return transpose of matrix | |
| 379 | - * | |
| 380 | - * @param[in] matrix Matrix. | |
| 381 | - * @return Transpose of matrix. | |
| 382 | - * | |
| 383 | - * Returns the transpose of a matrix. | |
| 384 | - ***************************************************************************/ | |
| 385 | -inline | |
| 386 | -GMatrix transpose(const GMatrix& matrix) | |
| 387 | -{ | |
| 388 | - GMatrix result = matrix; | |
| 389 | - result.transpose(); | |
| 390 | - return result; | |
| 391 | -} | |
| 392 | - | |
| 393 | - | |
| 394 | -/***********************************************************************//** | |
| 395 | - * @brief Return inverse of matrix | |
| 396 | - * | |
| 397 | - * @param[in] matrix Matrix. | |
| 398 | - * @return Inverse of matrix. | |
| 399 | - * | |
| 400 | - * Returns the inverse of a matrix. | |
| 401 | - ***************************************************************************/ | |
| 402 | -inline | |
| 403 | -GMatrix invert(const GMatrix& matrix) | |
| 404 | -{ | |
| 405 | - GMatrix result = matrix; | |
| 406 | - result.invert(); | |
| 407 | - return result; | |
| 408 | -} | |
| 409 | - | |
| 410 | - | |
| 411 | -/***********************************************************************//** | |
| 412 | - * @brief Return matrix with absolute values of all elements | |
| 413 | - * | |
| 414 | - * @param[in] matrix Matrix. | |
| 415 | - * @return Matrix with elements being the absolute elements of the input | |
| 416 | - * matrix. | |
| 417 | - * | |
| 418 | - * Return a matrix where each elements has been replaced by its absolute | |
| 419 | - * value. | |
| 420 | - ***************************************************************************/ | |
| 421 | -inline | |
| 422 | -GMatrix abs(const GMatrix& matrix) | |
| 423 | -{ | |
| 424 | - GMatrix result = matrix; | |
| 425 | - result.abs(); | |
| 426 | - return result; | |
| 427 | -} | |
| 428 | - | |
| 429 | 361 | #endif /* GMATRIX_HPP */ | ... | ... |
include/GMatrixBase.hpp
| ... | ... | @@ -118,20 +118,12 @@ |
| 118 | 118 | * where the size of @p vector needs to be identical to the number of |
| 119 | 119 | * columns in the matrix. |
| 120 | 120 | * |
| 121 | - * Furthermore, the following methods exist for matrix operations: | |
| 121 | + * Furthermore, the following methods exist for matrix transformations: | |
| 122 | 122 | * |
| 123 | - * matrix.transpose(); // Transposes matrix | |
| 124 | - * matrix.invert(); // Inverts matrix | |
| 125 | - * matrix.negate(); // Negates all matrix elements | |
| 126 | - * matrix.abs(); // Sets all matrix elements to their absolute values | |
| 127 | - * | |
| 128 | - * Friend functions are implemented to perform the same operations also in a | |
| 129 | - * more natural syntax that will generate a new matrix | |
| 130 | - * | |
| 131 | - * transposed_matrix = transpose(matrix); | |
| 132 | - * inverted_matrix = invert(matrix); | |
| 133 | - * negated_matrix = -matrix; | |
| 134 | - * absolute_matrix = abs(matrix); | |
| 123 | + * new_matrix = matrix.transpose(); // Transposes matrix | |
| 124 | + * new_matrix = matrix.invert(); // Inverts matrix | |
| 125 | + * new_vector = matrix.solve(vector); // Solves linear matrix equation | |
| 126 | + * new_matrix = matrix.abs(); // Returns matrix with all elements replaced by their absolute values | |
| 135 | 127 | * |
| 136 | 128 | * The following methods allow to access matrix attributes: |
| 137 | 129 | * |
| ... | ... | @@ -172,10 +164,6 @@ public: |
| 172 | 164 | virtual void column(const int& column, const GVector& vector) = 0; |
| 173 | 165 | virtual void add_to_row(const int& row, const GVector& vector) = 0; |
| 174 | 166 | virtual void add_to_column(const int& column, const GVector& vector) = 0; |
| 175 | - virtual void transpose(void) = 0; | |
| 176 | - virtual void invert(void) = 0; | |
| 177 | - virtual void negate(void) = 0; | |
| 178 | - virtual void abs(void) = 0; | |
| 179 | 167 | virtual double fill(void) const = 0; |
| 180 | 168 | virtual double min(void) const = 0; |
| 181 | 169 | virtual double max(void) const = 0; | ... | ... |
include/GMatrixSparse.hpp
| ... | ... | @@ -40,6 +40,7 @@ |
| 40 | 40 | class GMatrix; |
| 41 | 41 | class GMatrixSymmetric; |
| 42 | 42 | class GMatrixSparse; |
| 43 | +class GVector; | |
| 43 | 44 | class GSparseSymbolic; |
| 44 | 45 | class GSparseNumeric; |
| 45 | 46 | |
| ... | ... | @@ -240,10 +241,6 @@ public: |
| 240 | 241 | virtual void column(const int& column, const GVector& vector); |
| 241 | 242 | virtual void add_to_row(const int& row, const GVector& vector); |
| 242 | 243 | virtual void add_to_column(const int& column, const GVector& vector); |
| 243 | - virtual void transpose(void); | |
| 244 | - virtual void invert(void); | |
| 245 | - virtual void negate(void); | |
| 246 | - virtual void abs(void); | |
| 247 | 244 | virtual double fill(void) const; |
| 248 | 245 | virtual double min(void) const; |
| 249 | 246 | virtual double max(void) const; |
| ... | ... | @@ -251,20 +248,24 @@ public: |
| 251 | 248 | virtual std::string print(const GChatter& chatter = NORMAL) const; |
| 252 | 249 | |
| 253 | 250 | // Other methods |
| 254 | - void column(const int& column, const double* values, | |
| 255 | - const int* rows, int number); | |
| 256 | - void add_to_column(const int& column, const double* values, | |
| 257 | - const int* rows, int number); | |
| 258 | - void cholesky_decompose(bool compress = true); | |
| 259 | - GVector cholesky_solver(const GVector& vector, bool compress = true); | |
| 260 | - void cholesky_invert(bool compress = true); | |
| 261 | - void set_mem_block(const int& block); | |
| 262 | - void stack_init(const int& size = 0, const int& entries = 0); | |
| 263 | - int stack_push_column(const GVector& vector, const int& col); | |
| 264 | - int stack_push_column(const double* values, const int* rows, | |
| 265 | - const int& number, const int& col); | |
| 266 | - void stack_flush(void); | |
| 267 | - void stack_destroy(void); | |
| 251 | + void column(const int& column, const double* values, | |
| 252 | + const int* rows, int number); | |
| 253 | + void add_to_column(const int& column, const double* values, | |
| 254 | + const int* rows, int number); | |
| 255 | + GMatrixSparse transpose(void) const; | |
| 256 | + GMatrixSparse invert(void) const; | |
| 257 | + GVector solve(const GVector& vector) const; | |
| 258 | + GMatrixSparse abs(void) const; | |
| 259 | + GMatrixSparse cholesky_decompose(bool compress = true) const; | |
| 260 | + GVector cholesky_solver(const GVector& vector, bool compress = true) const; | |
| 261 | + GMatrixSparse cholesky_invert(bool compress = true) const; | |
| 262 | + void set_mem_block(const int& block); | |
| 263 | + void stack_init(const int& size = 0, const int& entries = 0); | |
| 264 | + int stack_push_column(const GVector& vector, const int& col); | |
| 265 | + int stack_push_column(const double* values, const int* rows, | |
| 266 | + const int& number, const int& col); | |
| 267 | + void stack_flush(void); | |
| 268 | + void stack_destroy(void); | |
| 268 | 269 | |
| 269 | 270 | private: |
| 270 | 271 | // Private methods |
| ... | ... | @@ -416,20 +417,6 @@ GMatrixSparse& GMatrixSparse::operator/=(const double& scalar) |
| 416 | 417 | |
| 417 | 418 | |
| 418 | 419 | /***********************************************************************//** |
| 419 | - * @brief Negate matrix elements | |
| 420 | - * | |
| 421 | - * @return Matrix with negated elements. | |
| 422 | - ***************************************************************************/ | |
| 423 | -inline | |
| 424 | -GMatrixSparse GMatrixSparse::operator-(void) const | |
| 425 | -{ | |
| 426 | - GMatrixSparse result = *this; | |
| 427 | - result.negate(); | |
| 428 | - return result; | |
| 429 | -} | |
| 430 | - | |
| 431 | - | |
| 432 | -/***********************************************************************//** | |
| 433 | 420 | * @brief Multiply matrix by scalar |
| 434 | 421 | * |
| 435 | 422 | * @param[in] matrix Matrix. |
| ... | ... | @@ -479,84 +466,4 @@ GMatrixSparse operator/(const GMatrixSparse& matrix, const double& scalar) |
| 479 | 466 | return result; |
| 480 | 467 | } |
| 481 | 468 | |
| 482 | - | |
| 483 | -/***********************************************************************//** | |
| 484 | - * @brief Return transpose of matrix | |
| 485 | - * | |
| 486 | - * @param[in] matrix Matrix. | |
| 487 | - * @return Transpose of matrix. | |
| 488 | - ***************************************************************************/ | |
| 489 | -inline | |
| 490 | -GMatrixSparse transpose(const GMatrixSparse& matrix) | |
| 491 | -{ | |
| 492 | - GMatrixSparse result = matrix; | |
| 493 | - result.transpose(); | |
| 494 | - return result; | |
| 495 | -} | |
| 496 | - | |
| 497 | - | |
| 498 | -/***********************************************************************//** | |
| 499 | - * @brief Return inverse of matrix | |
| 500 | - * | |
| 501 | - * @param[in] matrix Matrix. | |
| 502 | - * @return Inverse of matrix. | |
| 503 | - ***************************************************************************/ | |
| 504 | -inline | |
| 505 | -GMatrixSparse invert(const GMatrixSparse& matrix) | |
| 506 | -{ | |
| 507 | - GMatrixSparse result = matrix; | |
| 508 | - result.invert(); | |
| 509 | - return result; | |
| 510 | -} | |
| 511 | - | |
| 512 | - | |
| 513 | -/***********************************************************************//** | |
| 514 | - * @brief Return matrix with absolute values of all elements | |
| 515 | - * | |
| 516 | - * @param[in] matrix Matrix. | |
| 517 | - * @return Matrix with elements being the absolute elements of the input | |
| 518 | - * matrix. | |
| 519 | - ***************************************************************************/ | |
| 520 | -inline | |
| 521 | -GMatrixSparse abs(const GMatrixSparse& matrix) | |
| 522 | -{ | |
| 523 | - GMatrixSparse result = matrix; | |
| 524 | - result.abs(); | |
| 525 | - return result; | |
| 526 | -} | |
| 527 | - | |
| 528 | - | |
| 529 | -/***********************************************************************//** | |
| 530 | - * @brief Return Cholesky decomposition of matrix | |
| 531 | - * | |
| 532 | - * @param[in] matrix Matrix. | |
| 533 | - * @param[in] compress Use matrix compression (defaults to true). | |
| 534 | - * @return Cholesky decomposition of matrix. | |
| 535 | - ***************************************************************************/ | |
| 536 | -inline | |
| 537 | -GMatrixSparse cholesky_decompose(const GMatrixSparse& matrix, | |
| 538 | - bool compress = true) | |
| 539 | -{ | |
| 540 | - GMatrixSparse result = matrix; | |
| 541 | - result.cholesky_decompose(compress); | |
| 542 | - return result; | |
| 543 | -} | |
| 544 | - | |
| 545 | - | |
| 546 | -/***********************************************************************//** | |
| 547 | - * @brief Return inverse matrix using Cholesky decomposition | |
| 548 | - * | |
| 549 | - * @param[in] matrix Matrix. | |
| 550 | - * @param[in] compress Use matrix compression (defaults to true). | |
| 551 | - * @return Inverse of matrix. | |
| 552 | - ***************************************************************************/ | |
| 553 | -inline | |
| 554 | -GMatrixSparse cholesky_invert(const GMatrixSparse& matrix, | |
| 555 | - bool compress = true) | |
| 556 | -{ | |
| 557 | - GMatrixSparse result = matrix; | |
| 558 | - result.cholesky_invert(compress); | |
| 559 | - return result; | |
| 560 | -} | |
| 561 | - | |
| 562 | 469 | #endif /* GMATRIXSPARSE_HPP */ | ... | ... |
include/GMatrixSymmetric.hpp
| ... | ... | @@ -34,6 +34,7 @@ |
| 34 | 34 | /* __ Forward declarations _______________________________________________ */ |
| 35 | 35 | class GMatrix; |
| 36 | 36 | class GMatrixSparse; |
| 37 | +class GVector; | |
| 37 | 38 | |
| 38 | 39 | |
| 39 | 40 | /***********************************************************************//** |
| ... | ... | @@ -106,10 +107,6 @@ public: |
| 106 | 107 | virtual void column(const int& column, const GVector& vector); |
| 107 | 108 | virtual void add_to_row(const int& row, const GVector& vector); |
| 108 | 109 | virtual void add_to_column(const int& column, const GVector& vector); |
| 109 | - virtual void transpose(void); | |
| 110 | - virtual void invert(void); | |
| 111 | - virtual void negate(void); | |
| 112 | - virtual void abs(void); | |
| 113 | 110 | virtual double fill(void) const; |
| 114 | 111 | virtual double min(void) const; |
| 115 | 112 | virtual double max(void) const; |
| ... | ... | @@ -117,11 +114,15 @@ public: |
| 117 | 114 | virtual std::string print(const GChatter& chatter = NORMAL) const; |
| 118 | 115 | |
| 119 | 116 | // Other methods |
| 120 | - virtual GMatrix extract_lower_triangle(void) const; | |
| 121 | - virtual GMatrix extract_upper_triangle(void) const; | |
| 122 | - virtual void cholesky_decompose(bool compress = true); | |
| 123 | - virtual GVector cholesky_solver(const GVector& vector, bool compress = true); | |
| 124 | - virtual void cholesky_invert(bool compress = true); | |
| 117 | + GMatrixSymmetric transpose(void) const; | |
| 118 | + GMatrixSymmetric invert(void) const; | |
| 119 | + GVector solve(const GVector& vector) const; | |
| 120 | + GMatrixSymmetric abs(void) const; | |
| 121 | + GMatrix extract_lower_triangle(void) const; | |
| 122 | + GMatrix extract_upper_triangle(void) const; | |
| 123 | + GMatrixSymmetric cholesky_decompose(bool compress = true) const; | |
| 124 | + GVector cholesky_solver(const GVector& vector, bool compress = true) const; | |
| 125 | + GMatrixSymmetric cholesky_invert(bool compress = true) const; | |
| 125 | 126 | |
| 126 | 127 | private: |
| 127 | 128 | // Private methods |
| ... | ... | @@ -138,16 +139,18 @@ private: |
| 138 | 139 | |
| 139 | 140 | |
| 140 | 141 | /***********************************************************************//** |
| 141 | - * @brief Transpose matrix | |
| 142 | + * @brief Return transposed matrix | |
| 142 | 143 | * |
| 143 | - * Transpose matrix. As the transposed matrix of a symmetric matrix is | |
| 144 | - * identical to the original matrix, this method simply returns without | |
| 145 | - * taking any action. | |
| 144 | + * @return Transposed matrix. | |
| 145 | + * | |
| 146 | + * Returns transposed matrix of the matrix. As the transposed matrix of a | |
| 147 | + * symmetric matrix is identical to the original matrix, this method simply | |
| 148 | + * returns the actual matrix. | |
| 146 | 149 | ***************************************************************************/ |
| 147 | 150 | inline |
| 148 | -void GMatrixSymmetric::transpose(void) | |
| 151 | +GMatrixSymmetric GMatrixSymmetric::transpose(void) const | |
| 149 | 152 | { |
| 150 | - return; | |
| 153 | + return (*this); | |
| 151 | 154 | } |
| 152 | 155 | |
| 153 | 156 | |
| ... | ... | @@ -250,22 +253,6 @@ GMatrixSymmetric& GMatrixSymmetric::operator/=(const double& scalar) |
| 250 | 253 | |
| 251 | 254 | |
| 252 | 255 | /***********************************************************************//** |
| 253 | - * @brief Negate matrix elements | |
| 254 | - * | |
| 255 | - * @return Matrix with negated elements. | |
| 256 | - * | |
| 257 | - * Returns a matrix where each element is replaced by its negative element. | |
| 258 | - ***************************************************************************/ | |
| 259 | -inline | |
| 260 | -GMatrixSymmetric GMatrixSymmetric::operator-(void) const | |
| 261 | -{ | |
| 262 | - GMatrixSymmetric result = *this; | |
| 263 | - result.negate(); | |
| 264 | - return result; | |
| 265 | -} | |
| 266 | - | |
| 267 | - | |
| 268 | -/***********************************************************************//** | |
| 269 | 256 | * @brief Multiply matrix by scalar |
| 270 | 257 | * |
| 271 | 258 | * @param[in] matrix Matrix. |
| ... | ... | @@ -318,93 +305,4 @@ GMatrixSymmetric operator/(const GMatrixSymmetric& matrix, const double& scalar) |
| 318 | 305 | return result; |
| 319 | 306 | } |
| 320 | 307 | |
| 321 | - | |
| 322 | -/***********************************************************************//** | |
| 323 | - * @brief Return transpose of matrix | |
| 324 | - * | |
| 325 | - * @param[in] matrix Matrix. | |
| 326 | - * @return Transpose of matrix. | |
| 327 | - * | |
| 328 | - * Returns the transpose of the matrix. This is trivial for a symmetric | |
| 329 | - * matrix, as its transpose is the original matrix. | |
| 330 | - ***************************************************************************/ | |
| 331 | -inline | |
| 332 | -GMatrixSymmetric transpose(const GMatrixSymmetric& matrix) | |
| 333 | -{ | |
| 334 | - return matrix; | |
| 335 | -} | |
| 336 | - | |
| 337 | - | |
| 338 | -/***********************************************************************//** | |
| 339 | - * @brief Return inverse of matrix | |
| 340 | - * | |
| 341 | - * @param[in] matrix Matrix. | |
| 342 | - * @return Inverse of matrix. | |
| 343 | - * | |
| 344 | - * Returns the inverse of the matrix. | |
| 345 | - ***************************************************************************/ | |
| 346 | -inline | |
| 347 | -GMatrixSymmetric invert(const GMatrixSymmetric& matrix) | |
| 348 | -{ | |
| 349 | - GMatrixSymmetric result = matrix; | |
| 350 | - result.invert(); | |
| 351 | - return result; | |
| 352 | -} | |
| 353 | - | |
| 354 | - | |
| 355 | -/***********************************************************************//** | |
| 356 | - * @brief Return matrix with absolute values of all elements | |
| 357 | - * | |
| 358 | - * @param[in] matrix Matrix. | |
| 359 | - * @return Matrix with elements being the absolute elements of the input | |
| 360 | - * matrix. | |
| 361 | - * | |
| 362 | - * Returns a matrix where each element is replaced by its absolute value. | |
| 363 | - ***************************************************************************/ | |
| 364 | -inline | |
| 365 | -GMatrixSymmetric abs(const GMatrixSymmetric& matrix) | |
| 366 | -{ | |
| 367 | - GMatrixSymmetric result = matrix; | |
| 368 | - result.abs(); | |
| 369 | - return result; | |
| 370 | -} | |
| 371 | - | |
| 372 | - | |
| 373 | -/***********************************************************************//** | |
| 374 | - * @brief Return Cholesky decomposition of matrix | |
| 375 | - * | |
| 376 | - * @param[in] matrix Matrix. | |
| 377 | - * @param[in] compress Use matrix compression (defaults to true). | |
| 378 | - * @return Cholesky decomposition of matrix. | |
| 379 | - * | |
| 380 | - * Returns a Cholesky decomposition of a matrix. | |
| 381 | - ***************************************************************************/ | |
| 382 | -inline | |
| 383 | -GMatrixSymmetric cholesky_decompose(const GMatrixSymmetric& matrix, | |
| 384 | - bool compress = true) | |
| 385 | -{ | |
| 386 | - GMatrixSymmetric result = matrix; | |
| 387 | - result.cholesky_decompose(compress); | |
| 388 | - return result; | |
| 389 | -} | |
| 390 | - | |
| 391 | - | |
| 392 | -/***********************************************************************//** | |
| 393 | - * @brief Return inverse matrix using Cholesky decomposition | |
| 394 | - * | |
| 395 | - * @param[in] matrix Matrix. | |
| 396 | - * @param[in] compress Use matrix compression (defaults to true). | |
| 397 | - * @return Inverse of matrix. | |
| 398 | - * | |
| 399 | - * Returns the inverse of the matrix by performing a Cholesky decomposition. | |
| 400 | - ***************************************************************************/ | |
| 401 | -inline | |
| 402 | -GMatrixSymmetric cholesky_invert(const GMatrixSymmetric& matrix, | |
| 403 | - bool compress = true) | |
| 404 | -{ | |
| 405 | - GMatrixSymmetric result = matrix; | |
| 406 | - result.cholesky_invert(compress); | |
| 407 | - return result; | |
| 408 | -} | |
| 409 | - | |
| 410 | 308 | #endif /* GMATRIXSYMMETRIC_HPP */ | ... | ... |
pyext/GMatrix.i
| ... | ... | @@ -72,21 +72,20 @@ public: |
| 72 | 72 | virtual void column(const int& column, const GVector& vector); |
| 73 | 73 | virtual void add_to_row(const int& row, const GVector& vector); |
| 74 | 74 | virtual void add_to_column(const int& column, const GVector& vector); |
| 75 | - virtual void transpose(void); | |
| 76 | - virtual void invert(void); | |
| 77 | - virtual void negate(void); | |
| 78 | - virtual void abs(void); | |
| 79 | 75 | virtual double fill(void) const; |
| 80 | 76 | virtual double min(void) const; |
| 81 | 77 | virtual double max(void) const; |
| 82 | 78 | virtual double sum(void) const; |
| 83 | 79 | |
| 84 | 80 | // Other methods |
| 85 | - virtual GMatrix extract_lower_triangle(void) const; | |
| 86 | - virtual GMatrix extract_upper_triangle(void) const; | |
| 87 | - virtual void eulerx(const double& angle); | |
| 88 | - virtual void eulery(const double& angle); | |
| 89 | - virtual void eulerz(const double& angle); | |
| 81 | + GMatrix transpose(void) const; | |
| 82 | + GMatrix invert(void) const; | |
| 83 | + GMatrix abs(void) const; | |
| 84 | + GMatrix extract_lower_triangle(void) const; | |
| 85 | + GMatrix extract_upper_triangle(void) const; | |
| 86 | + void eulerx(const double& angle); | |
| 87 | + void eulery(const double& angle); | |
| 88 | + void eulerz(const double& angle); | |
| 90 | 89 | }; |
| 91 | 90 | |
| 92 | 91 | |
| ... | ... | @@ -120,11 +119,3 @@ public: |
| 120 | 119 | return (*self); |
| 121 | 120 | } |
| 122 | 121 | }; |
| 123 | - | |
| 124 | - | |
| 125 | -/***********************************************************************//** | |
| 126 | - * @brief GMatrix friends | |
| 127 | - ***************************************************************************/ | |
| 128 | -GMatrix transpose(const GMatrix& matrix); | |
| 129 | -GMatrix invert(const GMatrix& matrix); | |
| 130 | -GMatrix abs(const GMatrix& matrix); | ... | ... |
pyext/GMatrixBase.i
| ... | ... | @@ -55,10 +55,6 @@ public: |
| 55 | 55 | virtual void column(const int& column, const GVector& vector) = 0; |
| 56 | 56 | virtual void add_to_row(const int& row, const GVector& vector) = 0; |
| 57 | 57 | virtual void add_to_column(const int& column, const GVector& vector) = 0; |
| 58 | - virtual void transpose(void) = 0; | |
| 59 | - virtual void invert(void) = 0; | |
| 60 | - virtual void negate(void) = 0; | |
| 61 | - virtual void abs(void) = 0; | |
| 62 | 58 | virtual double fill(void) const = 0; |
| 63 | 59 | virtual double min(void) const = 0; |
| 64 | 60 | virtual double max(void) const = 0; | ... | ... |
pyext/GMatrixSparse.i
| ... | ... | @@ -76,30 +76,29 @@ public: |
| 76 | 76 | virtual void column(const int& column, const GVector& vector); |
| 77 | 77 | virtual void add_to_row(const int& row, const GVector& vector); |
| 78 | 78 | virtual void add_to_column(const int& column, const GVector& vector); |
| 79 | - virtual void transpose(void); | |
| 80 | - virtual void invert(void); | |
| 81 | - virtual void negate(void); | |
| 82 | - virtual void abs(void); | |
| 83 | 79 | virtual double fill(void) const; |
| 84 | 80 | virtual double min(void) const; |
| 85 | 81 | virtual double max(void) const; |
| 86 | 82 | virtual double sum(void) const; |
| 87 | 83 | |
| 88 | 84 | // Other methods |
| 89 | - void column(const int& column, const double* values, | |
| 90 | - const int* rows, int number); | |
| 91 | - void add_to_column(const int& column, const double* values, | |
| 92 | - const int* rows, int number); | |
| 93 | - void cholesky_decompose(bool compress = true); | |
| 94 | - GVector cholesky_solver(const GVector& vector, bool compress = true); | |
| 95 | - void cholesky_invert(bool compress = true); | |
| 96 | - void set_mem_block(const int& block); | |
| 97 | - void stack_init(const int& size = 0, const int& entries = 0); | |
| 98 | - int stack_push_column(const GVector& vector, const int& col); | |
| 99 | - int stack_push_column(const double* values, const int* rows, | |
| 100 | - const int& number, const int& col); | |
| 101 | - void stack_flush(void); | |
| 102 | - void stack_destroy(void); | |
| 85 | + void column(const int& column, const double* values, | |
| 86 | + const int* rows, int number); | |
| 87 | + void add_to_column(const int& column, const double* values, | |
| 88 | + const int* rows, int number); | |
| 89 | + GMatrixSparse transpose(void) const; | |
| 90 | + GMatrixSparse invert(void) const; | |
| 91 | + GMatrixSparse abs(void) const; | |
| 92 | + GMatrixSparse cholesky_decompose(bool compress = true); | |
| 93 | + GVector cholesky_solver(const GVector& vector, bool compress = true); | |
| 94 | + GMatrixSparse cholesky_invert(bool compress = true); | |
| 95 | + void set_mem_block(const int& block); | |
| 96 | + void stack_init(const int& size = 0, const int& entries = 0); | |
| 97 | + int stack_push_column(const GVector& vector, const int& col); | |
| 98 | + int stack_push_column(const double* values, const int* rows, | |
| 99 | + const int& number, const int& col); | |
| 100 | + void stack_flush(void); | |
| 101 | + void stack_destroy(void); | |
| 103 | 102 | }; |
| 104 | 103 | |
| 105 | 104 | |
| ... | ... | @@ -133,11 +132,3 @@ public: |
| 133 | 132 | return (*self); |
| 134 | 133 | } |
| 135 | 134 | }; |
| 136 | - | |
| 137 | - | |
| 138 | -/***********************************************************************//** | |
| 139 | - * @brief GMatrixSparse friends | |
| 140 | - ***************************************************************************/ | |
| 141 | -GMatrixSparse transpose(const GMatrixSparse& matrix); | |
| 142 | -GMatrixSparse invert(const GMatrixSparse& matrix); | |
| 143 | -GMatrixSparse abs(const GMatrixSparse& matrix); | ... | ... |
pyext/GMatrixSymmetric.i
| ... | ... | @@ -70,21 +70,21 @@ public: |
| 70 | 70 | virtual void column(const int& column, const GVector& vector); |
| 71 | 71 | virtual void add_to_row(const int& row, const GVector& vector); |
| 72 | 72 | virtual void add_to_column(const int& column, const GVector& vector); |
| 73 | - virtual void transpose(void); | |
| 74 | - virtual void invert(void); | |
| 75 | - virtual void negate(void); | |
| 76 | - virtual void abs(void); | |
| 77 | 73 | virtual double fill(void) const; |
| 78 | 74 | virtual double min(void) const; |
| 79 | 75 | virtual double max(void) const; |
| 80 | 76 | virtual double sum(void) const; |
| 81 | 77 | |
| 82 | 78 | // Other methods |
| 83 | - virtual GMatrix extract_lower_triangle(void) const; | |
| 84 | - virtual GMatrix extract_upper_triangle(void) const; | |
| 85 | - virtual void cholesky_decompose(bool compress = true); | |
| 86 | - virtual GVector cholesky_solver(const GVector& vector, bool compress = true); | |
| 87 | - virtual void cholesky_invert(bool compress = true); | |
| 79 | + GMatrixSymmetric transpose(void) const; | |
| 80 | + GMatrixSymmetric invert(void) const; | |
| 81 | + GVector solve(const GVector& vector) const; | |
| 82 | + GMatrixSymmetric abs(void) const; | |
| 83 | + GMatrix extract_lower_triangle(void) const; | |
| 84 | + GMatrix extract_upper_triangle(void) const; | |
| 85 | + GMatrixSymmetric cholesky_decompose(bool compress = true) const; | |
| 86 | + GVector cholesky_solver(const GVector& vector, bool compress = true) const; | |
| 87 | + GMatrixSymmetric cholesky_invert(bool compress = true) const; | |
| 88 | 88 | }; |
| 89 | 89 | |
| 90 | 90 | |
| ... | ... | @@ -118,11 +118,3 @@ public: |
| 118 | 118 | return (*self); |
| 119 | 119 | } |
| 120 | 120 | }; |
| 121 | - | |
| 122 | - | |
| 123 | -/***********************************************************************//** | |
| 124 | - * @brief GMatrixSymmetric friends | |
| 125 | - ***************************************************************************/ | |
| 126 | -GMatrixSymmetric transpose(const GMatrixSymmetric& matrix); | |
| 127 | -GMatrixSymmetric invert(const GMatrixSymmetric& matrix); | |
| 128 | -GMatrixSymmetric abs(const GMatrixSymmetric& matrix); | ... | ... |
src/linalg/GMatrix.cpp
| ... | ... | @@ -51,6 +51,7 @@ |
| 51 | 51 | #define G_ADD_TO_ROW "GMatrix::add_to_row(int&, GVector&)" |
| 52 | 52 | #define G_ADD_TO_COLUMN "GMatrix::add_to_column(int&, GVector&)" |
| 53 | 53 | #define G_INVERT "GMatrix::invert()" |
| 54 | +#define G_SOLVE "GMatrix::solve(GVector&)" | |
| 54 | 55 | #define G_EXTRACT_LOWER "GMatrix::extract_lower_triangle()" |
| 55 | 56 | #define G_EXTRACT_UPPER "GMatrix::extract_upper_triangle()" |
| 56 | 57 | |
| ... | ... | @@ -305,6 +306,30 @@ GVector GMatrix::operator*(const GVector& vector) const |
| 305 | 306 | |
| 306 | 307 | |
| 307 | 308 | /***********************************************************************//** |
| 309 | + * @brief Negate matrix elements | |
| 310 | + * | |
| 311 | + * @return Matrix with negated elements. | |
| 312 | + * | |
| 313 | + * Returns a matrix where each element has been replaced by its negative | |
| 314 | + * element. | |
| 315 | + ***************************************************************************/ | |
| 316 | +GMatrix GMatrix::operator-(void) const | |
| 317 | +{ | |
| 318 | + // Copy matrix | |
| 319 | + GMatrix matrix = *this; | |
| 320 | + | |
| 321 | + // Take the absolute value of all matrix elements | |
| 322 | + double* ptr = matrix.m_data; | |
| 323 | + for (int i = 0; i < matrix.m_elements; ++i, ++ptr) { | |
| 324 | + *ptr = -(*ptr); | |
| 325 | + } | |
| 326 | + | |
| 327 | + // Return matrix | |
| 328 | + return matrix; | |
| 329 | +} | |
| 330 | + | |
| 331 | + | |
| 332 | +/***********************************************************************//** | |
| 308 | 333 | * @brief Unary matrix addition operator |
| 309 | 334 | * |
| 310 | 335 | * @param[in] matrix Matrix. |
| ... | ... | @@ -773,98 +798,106 @@ void GMatrix::add_to_column(const int& column, const GVector& vector) |
| 773 | 798 | |
| 774 | 799 | |
| 775 | 800 | /***********************************************************************//** |
| 776 | - * @brief Transpose matrix | |
| 801 | + * @brief Return transposed matrix | |
| 802 | + * | |
| 803 | + * @return Transposed matrix. | |
| 777 | 804 | * |
| 778 | - * The transpose operation exchanges the number of rows against the number | |
| 779 | - * of columns. For a square matrix the exchange is done inplace. Otherwise | |
| 780 | - * a copy of the matrix is made. | |
| 805 | + * Returns transposed matrix of the matrix. | |
| 781 | 806 | ***************************************************************************/ |
| 782 | -void GMatrix::transpose(void) | |
| 807 | +GMatrix GMatrix::transpose(void) const | |
| 783 | 808 | { |
| 784 | - // Case A: Matrix is square then simply swap the elements | |
| 785 | - if (m_rows == m_cols) { | |
| 786 | - double swap; | |
| 787 | - double* ptr_dst; | |
| 788 | - double* ptr_src; | |
| 789 | - for (int row = 0; row < m_rows; ++row) { | |
| 790 | - for (int col = row; col < m_cols; ++col) { | |
| 791 | - ptr_dst = m_data + m_cols*row + col; | |
| 792 | - ptr_src = m_data + m_rows*col + row; | |
| 793 | - swap = *ptr_dst; | |
| 794 | - *ptr_dst = *ptr_src; | |
| 795 | - *ptr_src = swap; | |
| 796 | - } | |
| 797 | - } | |
| 798 | - } | |
| 809 | + // Allocate result matrix | |
| 810 | + GMatrix matrix(m_cols, m_rows); | |
| 799 | 811 | |
| 800 | - // Case B: Non-rectangular transpose. No code optimization has been | |
| 801 | - // done so far. | |
| 802 | - else { | |
| 803 | - GMatrix result(m_cols, m_rows); | |
| 804 | - for (int row = 0; row < m_rows; ++row) { | |
| 805 | - for (int col = 0; col < m_cols; ++col) { | |
| 806 | - result(col, row) = (*this)(row, col); | |
| 807 | - } | |
| 812 | + // Transpose matrix | |
| 813 | + for (int row = 0; row < m_rows; ++row) { | |
| 814 | + for (int col = 0; col < m_cols; ++col) { | |
| 815 | + matrix(col, row) = (*this)(row, col); | |
| 808 | 816 | } |
| 809 | - *this = result; | |
| 810 | 817 | } |
| 811 | 818 | |
| 812 | - // Return | |
| 813 | - return; | |
| 819 | + // Return matrix | |
| 820 | + return matrix; | |
| 814 | 821 | } |
| 815 | 822 | |
| 816 | 823 | |
| 817 | 824 | /***********************************************************************//** |
| 818 | - * @brief Invert matrix | |
| 825 | + * @brief Return inverted matrix | |
| 826 | + * | |
| 827 | + * @return Inverted matrix. | |
| 819 | 828 | * |
| 820 | 829 | * @exception GException::feature_not_implemented |
| 821 | 830 | * Feature not yet implemented. |
| 822 | 831 | * |
| 832 | + * Returns inverse of matrix. | |
| 833 | + * | |
| 823 | 834 | * @todo Needs to be implemented. |
| 824 | 835 | ***************************************************************************/ |
| 825 | -void GMatrix::invert(void) | |
| 836 | +GMatrix GMatrix::invert(void) const | |
| 826 | 837 | { |
| 838 | + // Allocate result matrix | |
| 839 | + GMatrix matrix(m_cols, m_rows); | |
| 840 | + | |
| 827 | 841 | // Throw exception |
| 828 | 842 | throw GException::feature_not_implemented(G_INVERT); |
| 829 | 843 | |
| 830 | - // Return | |
| 831 | - return; | |
| 844 | + // Return matrix | |
| 845 | + return matrix; | |
| 832 | 846 | } |
| 833 | 847 | |
| 834 | 848 | |
| 835 | 849 | /***********************************************************************//** |
| 836 | - * @brief Negate all matrix elements | |
| 850 | + * @brief Solves linear matrix equation | |
| 851 | + * | |
| 852 | + * @param[in] vector Solution vector. | |
| 853 | + * | |
| 854 | + * @exception GException::feature_not_implemented | |
| 855 | + * Feature not yet implemented. | |
| 856 | + * | |
| 857 | + * Solves the linear equation | |
| 858 | + * | |
| 859 | + * \f[M \times {\tt solution} = {\tt vector} \f] | |
| 860 | + * | |
| 861 | + * where \f$M\f$ is the matrix, \f${\tt vector}\f$ is the result, and | |
| 862 | + * \f${\tt solution}\f$ is the solution. | |
| 837 | 863 | * |
| 838 | - * Negates all matrix elements. | |
| 864 | + * @todo Needs to be implemented. | |
| 839 | 865 | ***************************************************************************/ |
| 840 | -void GMatrix::negate(void) | |
| 866 | +GVector GMatrix::solve(const GVector& vector) const | |
| 841 | 867 | { |
| 842 | - // Negate all matrix elements | |
| 843 | - double* ptr = m_data; | |
| 844 | - for (int i = 0; i < m_elements; ++i, ++ptr) { | |
| 845 | - *ptr = -(*ptr); | |
| 846 | - } | |
| 868 | + // Allocate result vector | |
| 869 | + GVector result; | |
| 847 | 870 | |
| 848 | - // Return | |
| 849 | - return; | |
| 871 | + // Throw exception | |
| 872 | + throw GException::feature_not_implemented(G_SOLVE); | |
| 873 | + | |
| 874 | + // Return vector | |
| 875 | + return result; | |
| 850 | 876 | } |
| 851 | 877 | |
| 852 | 878 | |
| 853 | 879 | /***********************************************************************//** |
| 854 | - * @brief Take absolute value of matrix elements | |
| 880 | + * @brief Return absolute of matrix | |
| 855 | 881 | * |
| 856 | - * Replaces all elements of the matrix by their absolute values. | |
| 882 | + * @return Absolute of matrix | |
| 883 | + * | |
| 884 | + * Returns matrix where all elements of the matrix have been replaced by | |
| 885 | + * their absolute values. | |
| 857 | 886 | ***************************************************************************/ |
| 858 | -void GMatrix::abs(void) | |
| 887 | +GMatrix GMatrix::abs(void) const | |
| 859 | 888 | { |
| 889 | + // Allocate result matrix | |
| 890 | + GMatrix matrix(m_rows, m_cols); | |
| 891 | + | |
| 860 | 892 | // Take the absolute value of all matrix elements |
| 861 | - double* ptr = m_data; | |
| 862 | - for (int i = 0; i < m_elements; ++i, ++ptr) { | |
| 863 | - *ptr = std::abs(*ptr); | |
| 893 | + double* src = m_data; | |
| 894 | + double* dst = matrix.m_data; | |
| 895 | + for (int i = 0; i < m_elements; ++i) { | |
| 896 | + *dst++ = std::abs(*src++); | |
| 864 | 897 | } |
| 865 | 898 | |
| 866 | - // Return | |
| 867 | - return; | |
| 899 | + // Return matrix | |
| 900 | + return matrix; | |
| 868 | 901 | } |
| 869 | 902 | |
| 870 | 903 | ... | ... |
src/linalg/GMatrixSparse.cpp
| ... | ... | @@ -453,6 +453,30 @@ GVector GMatrixSparse::operator*(const GVector& vector) const |
| 453 | 453 | |
| 454 | 454 | |
| 455 | 455 | /***********************************************************************//** |
| 456 | + * @brief Negate matrix elements | |
| 457 | + * | |
| 458 | + * @return Matrix with negated elements. | |
| 459 | + ***************************************************************************/ | |
| 460 | +GMatrixSparse GMatrixSparse::operator-(void) const | |
| 461 | +{ | |
| 462 | + // Copy matrix | |
| 463 | + GMatrixSparse matrix = *this; | |
| 464 | + | |
| 465 | + // Fill pending element | |
| 466 | + matrix.fill_pending(); | |
| 467 | + | |
| 468 | + // Negate all matrix elements | |
| 469 | + double* ptr = matrix.m_data; | |
| 470 | + for (int i = 0; i < matrix.m_elements; ++i, ++ptr) { | |
| 471 | + *ptr = -(*ptr); | |
| 472 | + } | |
| 473 | + | |
| 474 | + // Return matrix | |
| 475 | + return matrix; | |
| 476 | +} | |
| 477 | + | |
| 478 | + | |
| 479 | +/***********************************************************************//** | |
| 456 | 480 | * @brief Equalty operator |
| 457 | 481 | * |
| 458 | 482 | * @param[in] matrix Matrix. |
| ... | ... | @@ -1380,81 +1404,103 @@ void GMatrixSparse::add_to_column(const int& column, const double* values, |
| 1380 | 1404 | |
| 1381 | 1405 | |
| 1382 | 1406 | /***********************************************************************//** |
| 1383 | - * @brief Transpose matrix | |
| 1407 | + * @brief Return transposed matrix | |
| 1384 | 1408 | * |
| 1385 | - * The transpose operation exchanges the number of rows against the number | |
| 1386 | - * of columns. | |
| 1409 | + * @return Transposed matrix. | |
| 1410 | + * | |
| 1411 | + * Returns transposed matrix of the matrix. | |
| 1387 | 1412 | ***************************************************************************/ |
| 1388 | -void GMatrixSparse::transpose(void) | |
| 1413 | +GMatrixSparse GMatrixSparse::transpose(void) const | |
| 1389 | 1414 | { |
| 1415 | + // Copy matrix | |
| 1416 | + GMatrixSparse matrix = *this; | |
| 1417 | + | |
| 1390 | 1418 | // Fill pending element |
| 1391 | - fill_pending(); | |
| 1419 | + matrix.fill_pending(); | |
| 1392 | 1420 | |
| 1393 | 1421 | // Compute the transpose |
| 1394 | - *this = cs_transpose(*this, 1); | |
| 1422 | + matrix = cs_transpose(matrix, 1); | |
| 1395 | 1423 | |
| 1396 | - // Return | |
| 1397 | - return; | |
| 1424 | + // Return matrix | |
| 1425 | + return matrix; | |
| 1398 | 1426 | } |
| 1399 | 1427 | |
| 1400 | 1428 | |
| 1401 | 1429 | /***********************************************************************//** |
| 1402 | - * @brief Invert matrix | |
| 1430 | + * @brief Return inverted matrix | |
| 1431 | + * | |
| 1432 | + * @return Inverted matrix. | |
| 1403 | 1433 | * |
| 1404 | - * Inverts the matrix using the Cholesky decomposition. This does not work | |
| 1405 | - * on any kind of matrix. | |
| 1434 | + * Returns inverse of matrix. Inversion is done for the moment using Cholesky | |
| 1435 | + * decomposition. This does not work on any kind of matrix. | |
| 1406 | 1436 | * |
| 1407 | 1437 | * @todo Specify in documentation for which kind of matrix the method works. |
| 1408 | 1438 | ***************************************************************************/ |
| 1409 | -void GMatrixSparse::invert(void) | |
| 1439 | +GMatrixSparse GMatrixSparse::invert(void) const | |
| 1410 | 1440 | { |
| 1441 | + // Allocate result matrix | |
| 1442 | + GMatrixSparse matrix(m_cols, m_rows); | |
| 1443 | + | |
| 1411 | 1444 | // Invert matrix |
| 1412 | - cholesky_invert(true); | |
| 1445 | + matrix.cholesky_invert(true); | |
| 1413 | 1446 | |
| 1414 | - // Return | |
| 1415 | - return; | |
| 1447 | + // Return matrix | |
| 1448 | + return matrix; | |
| 1416 | 1449 | } |
| 1417 | 1450 | |
| 1418 | 1451 | |
| 1419 | 1452 | /***********************************************************************//** |
| 1420 | - * @brief Negate all matrix elements | |
| 1453 | + * @brief Solves linear matrix equation | |
| 1421 | 1454 | * |
| 1422 | - * Negates all matrix elements. | |
| 1455 | + * @param[in] vector Solution vector. | |
| 1456 | + * | |
| 1457 | + * Solves the linear equation | |
| 1458 | + * | |
| 1459 | + * \f[M \times {\tt solution} = {\tt vector} \f] | |
| 1460 | + * | |
| 1461 | + * where \f$M\f$ is the matrix, \f${\tt vector}\f$ is the result, and | |
| 1462 | + * \f${\tt solution}\f$ is the solution. Solving is done using Cholesky | |
| 1463 | + * decomposition. This does not work on any kind of matrix. | |
| 1464 | + * | |
| 1465 | + * @todo Specify in documentation for which kind of matrix the method works. | |
| 1423 | 1466 | ***************************************************************************/ |
| 1424 | -void GMatrixSparse::negate(void) | |
| 1467 | +GVector GMatrixSparse::solve(const GVector& vector) const | |
| 1425 | 1468 | { |
| 1426 | - // Fill pending element | |
| 1427 | - fill_pending(); | |
| 1469 | + // Get Cholesky decomposition of matrix | |
| 1470 | + GMatrixSparse decomposition = cholesky_decompose(true); | |
| 1428 | 1471 | |
| 1429 | - // Negate all matrix elements | |
| 1430 | - double* ptr = m_data; | |
| 1431 | - for (int i = 0; i < m_elements; ++i, ++ptr) { | |
| 1432 | - *ptr = -(*ptr); | |
| 1433 | - } | |
| 1434 | - | |
| 1435 | - // Return | |
| 1436 | - return; | |
| 1472 | + // Solve linear equation | |
| 1473 | + GVector result = decomposition.cholesky_solver(vector); | |
| 1474 | + | |
| 1475 | + // Return result | |
| 1476 | + return result; | |
| 1437 | 1477 | } |
| 1438 | 1478 | |
| 1439 | 1479 | |
| 1440 | 1480 | /***********************************************************************//** |
| 1441 | - * @brief Take absolute value of matrix elements | |
| 1481 | + * @brief Return absolute of matrix | |
| 1482 | + * | |
| 1483 | + * @return Absolute of matrix | |
| 1442 | 1484 | * |
| 1443 | - * Replaces all elements of the matrix by their absolute values. | |
| 1485 | + * Returns matrix where all elements of the matrix have been replaced by | |
| 1486 | + * their absolute values. | |
| 1444 | 1487 | ***************************************************************************/ |
| 1445 | -void GMatrixSparse::abs(void) | |
| 1488 | +GMatrixSparse GMatrixSparse::abs(void) const | |
| 1446 | 1489 | { |
| 1490 | + // Copy matrix | |
| 1491 | + GMatrixSparse matrix = *this; | |
| 1492 | + | |
| 1447 | 1493 | // Fill pending element |
| 1448 | - fill_pending(); | |
| 1494 | + matrix.fill_pending(); | |
| 1449 | 1495 | |
| 1450 | 1496 | // Take the absolute value of all matrix elements |
| 1451 | - double* ptr = m_data; | |
| 1452 | - for (int i = 0; i < m_elements; ++i, ++ptr) { | |
| 1497 | + double* ptr = matrix.m_data; | |
| 1498 | + for (int i = 0; i < matrix.m_elements; ++i, ++ptr) { | |
| 1453 | 1499 | *ptr = std::abs(*ptr); |
| 1454 | 1500 | } |
| 1455 | - | |
| 1456 | - // Return | |
| 1457 | - return; | |
| 1501 | + | |
| 1502 | + // Return matrix | |
| 1503 | + return matrix; | |
| 1458 | 1504 | } |
| 1459 | 1505 | |
| 1460 | 1506 | |
| ... | ... | @@ -1561,25 +1607,29 @@ double GMatrixSparse::sum(void) const |
| 1561 | 1607 | |
| 1562 | 1608 | |
| 1563 | 1609 | /***********************************************************************//** |
| 1564 | - * @brief Perform a Cholesky decomposition | |
| 1610 | + * @brief Return Cholesky decomposition | |
| 1565 | 1611 | * |
| 1566 | - * @param[in] compress Use zero-row/column compression (default: true). | |
| 1612 | + * @param[in] compress Use zero-row/column compression (defaults to true). | |
| 1613 | + * @return Cholesky decomposition of matrix | |
| 1567 | 1614 | * |
| 1568 | - * Cholesky decomposition of a sparse matrix. The decomposition is stored | |
| 1569 | - * within the GMatrixSparse without destroying the original matrix. | |
| 1615 | + * Returns the Cholesky decomposition of a sparse matrix. The decomposition | |
| 1616 | + * is stored within a GMatrixSparse object. | |
| 1570 | 1617 | ***************************************************************************/ |
| 1571 | -void GMatrixSparse::cholesky_decompose(bool compress) | |
| 1618 | +GMatrixSparse GMatrixSparse::cholesky_decompose(bool compress) const | |
| 1572 | 1619 | { |
| 1620 | + // Create copy of matrix | |
| 1621 | + GMatrixSparse matrix = *this; | |
| 1622 | + | |
| 1573 | 1623 | // Save original matrix size |
| 1574 | - int matrix_rows = m_rows; | |
| 1575 | - int matrix_cols = m_cols; | |
| 1624 | + int matrix_rows = matrix.m_rows; | |
| 1625 | + int matrix_cols = matrix.m_cols; | |
| 1576 | 1626 | |
| 1577 | 1627 | // Delete any existing symbolic and numeric analysis object and reset |
| 1578 | 1628 | // pointers |
| 1579 | - if (m_symbolic != NULL) delete m_symbolic; | |
| 1580 | - if (m_numeric != NULL) delete m_numeric; | |
| 1581 | - m_symbolic = NULL; | |
| 1582 | - m_numeric = NULL; | |
| 1629 | + if (matrix.m_symbolic != NULL) delete matrix.m_symbolic; | |
| 1630 | + if (matrix.m_numeric != NULL) delete matrix.m_numeric; | |
| 1631 | + matrix.m_symbolic = NULL; | |
| 1632 | + matrix.m_numeric = NULL; | |
| 1583 | 1633 | |
| 1584 | 1634 | // Allocate symbolic analysis object |
| 1585 | 1635 | GSparseSymbolic* symbolic = new GSparseSymbolic(); |
| ... | ... | @@ -1590,42 +1640,42 @@ void GMatrixSparse::cholesky_decompose(bool compress) |
| 1590 | 1640 | GSparseNumeric numeric; |
| 1591 | 1641 | |
| 1592 | 1642 | // Fill pending element into matrix |
| 1593 | - fill_pending(); | |
| 1643 | + matrix.fill_pending(); | |
| 1594 | 1644 | |
| 1595 | 1645 | // Remove rows and columns containing only zeros if matrix compression |
| 1596 | 1646 | // has been selected |
| 1597 | 1647 | if (compress) { |
| 1598 | - remove_zero_row_col(); | |
| 1648 | + matrix.remove_zero_row_col(); | |
| 1599 | 1649 | } |
| 1600 | 1650 | |
| 1601 | 1651 | // Ordering an symbolic analysis of matrix. This sets up an array 'pinv' |
| 1602 | 1652 | // which contains the fill-in reducing permutations |
| 1603 | - symbolic->cholesky_symbolic_analysis(1, *this); | |
| 1653 | + symbolic->cholesky_symbolic_analysis(1, matrix); | |
| 1604 | 1654 | |
| 1605 | 1655 | // Store symbolic pointer in sparse matrix object |
| 1606 | - m_symbolic = symbolic; | |
| 1656 | + matrix.m_symbolic = symbolic; | |
| 1607 | 1657 | |
| 1608 | 1658 | // Perform numeric Cholesky decomposition |
| 1609 | - numeric.cholesky_numeric_analysis(*this, *symbolic); | |
| 1659 | + numeric.cholesky_numeric_analysis(matrix, *symbolic); | |
| 1610 | 1660 | |
| 1611 | 1661 | // Copy L matrix into this object |
| 1612 | - free_elements(0, m_elements); | |
| 1613 | - alloc_elements(0, numeric.m_L->m_elements); | |
| 1614 | - for (int i = 0; i < m_elements; ++i) { | |
| 1615 | - m_data[i] = numeric.m_L->m_data[i]; | |
| 1616 | - m_rowinx[i] = numeric.m_L->m_rowinx[i]; | |
| 1662 | + matrix.free_elements(0, matrix.m_elements); | |
| 1663 | + matrix.alloc_elements(0, numeric.m_L->m_elements); | |
| 1664 | + for (int i = 0; i < matrix.m_elements; ++i) { | |
| 1665 | + matrix.m_data[i] = numeric.m_L->m_data[i]; | |
| 1666 | + matrix.m_rowinx[i] = numeric.m_L->m_rowinx[i]; | |
| 1617 | 1667 | } |
| 1618 | - for (int col = 0; col <= m_cols; ++col) { | |
| 1619 | - m_colstart[col] = numeric.m_L->m_colstart[col]; | |
| 1668 | + for (int col = 0; col <= matrix.m_cols; ++col) { | |
| 1669 | + matrix.m_colstart[col] = numeric.m_L->m_colstart[col]; | |
| 1620 | 1670 | } |
| 1621 | 1671 | |
| 1622 | 1672 | // Insert zero rows and columns if they have been removed previously. |
| 1623 | 1673 | if (compress) { |
| 1624 | - insert_zero_row_col(matrix_rows, matrix_cols); | |
| 1674 | + matrix.insert_zero_row_col(matrix_rows, matrix_cols); | |
| 1625 | 1675 | } |
| 1626 | 1676 | |
| 1627 | - // Return | |
| 1628 | - return; | |
| 1677 | + // Return matrix | |
| 1678 | + return matrix; | |
| 1629 | 1679 | } |
| 1630 | 1680 | |
| 1631 | 1681 | |
| ... | ... | @@ -1644,7 +1694,8 @@ void GMatrixSparse::cholesky_decompose(bool compress) |
| 1644 | 1694 | * This function is to be applied on a GMatrixSparse matrix for which a |
| 1645 | 1695 | * Choleksy factorization has been produced using 'cholesky_decompose'. |
| 1646 | 1696 | ***************************************************************************/ |
| 1647 | -GVector GMatrixSparse::cholesky_solver(const GVector& vector, bool compress) | |
| 1697 | +GVector GMatrixSparse::cholesky_solver(const GVector& vector, | |
| 1698 | + bool compress) const | |
| 1648 | 1699 | { |
| 1649 | 1700 | // Dump header |
| 1650 | 1701 | #if defined(G_DEBUG_SPARSE_COMPRESSION) |
| ... | ... | @@ -1862,22 +1913,20 @@ GVector GMatrixSparse::cholesky_solver(const GVector& vector, bool compress) |
| 1862 | 1913 | |
| 1863 | 1914 | |
| 1864 | 1915 | /***********************************************************************//** |
| 1865 | - * @brief Cholesky invert | |
| 1916 | + * @brief Invert matrix using a Cholesky decomposition | |
| 1866 | 1917 | * |
| 1867 | - * @param[in] compress Use zero-row/column compression (default: true). | |
| 1918 | + * @param[in] compress Use zero-row/column compression (defaults to true). | |
| 1919 | + * @return Inverted matrix. | |
| 1868 | 1920 | * |
| 1869 | - * @exception GException::matrix_zero | |
| 1870 | - * All matrix elements are zero. | |
| 1871 | - * | |
| 1872 | - * Inplace matrix inversion using the Cholesky decomposition. | |
| 1921 | + * Inverts the matrix using a Cholesky decomposition. | |
| 1873 | 1922 | ***************************************************************************/ |
| 1874 | -void GMatrixSparse::cholesky_invert(bool compress) | |
| 1923 | +GMatrixSparse GMatrixSparse::cholesky_invert(bool compress) const | |
| 1875 | 1924 | { |
| 1876 | 1925 | // Generate Cholesky decomposition of matrix |
| 1877 | - cholesky_decompose(compress); | |
| 1926 | + GMatrixSparse decomposition = cholesky_decompose(compress); | |
| 1878 | 1927 | |
| 1879 | 1928 | // Allocate result matrix and unit vector |
| 1880 | - GMatrixSparse result(m_rows, m_cols); | |
| 1929 | + GMatrixSparse matrix(m_rows, m_cols); | |
| 1881 | 1930 | GVector unit(m_rows); |
| 1882 | 1931 | |
| 1883 | 1932 | // Column-wise solving of the problem |
| ... | ... | @@ -1887,27 +1936,25 @@ void GMatrixSparse::cholesky_invert(bool compress) |
| 1887 | 1936 | unit[col] = 1.0; |
| 1888 | 1937 | |
| 1889 | 1938 | // Solve for column |
| 1890 | - GVector x = cholesky_solver(unit, compress); | |
| 1939 | + GVector x = decomposition.cholesky_solver(unit, compress); | |
| 1891 | 1940 | |
| 1892 | 1941 | // Insert column in matrix |
| 1893 | - result.column(col, x); | |
| 1942 | + matrix.column(col, x); | |
| 1894 | 1943 | |
| 1895 | 1944 | // Clear unit vector for next round |
| 1896 | 1945 | unit[col] = 0.0; |
| 1897 | 1946 | |
| 1898 | 1947 | } |
| 1899 | 1948 | |
| 1900 | - // Assign result | |
| 1901 | - *this = result; | |
| 1902 | - | |
| 1903 | - // Return | |
| 1904 | - return; | |
| 1949 | + // Return matrix | |
| 1950 | + return matrix; | |
| 1905 | 1951 | } |
| 1906 | 1952 | |
| 1907 | 1953 | |
| 1908 | 1954 | /***********************************************************************//** |
| 1909 | 1955 | * @brief Print matrix |
| 1910 | 1956 | * |
| 1957 | + * @param[in] chatter Chattiness (defaults to NORMAL). | |
| 1911 | 1958 | * @return String containing matrix information |
| 1912 | 1959 | ***************************************************************************/ |
| 1913 | 1960 | std::string GMatrixSparse::print(const GChatter& chatter) const | ... | ... |
src/linalg/GMatrixSymmetric.cpp
| ... | ... | @@ -356,6 +356,30 @@ GVector GMatrixSymmetric::operator*(const GVector& vector) const |
| 356 | 356 | |
| 357 | 357 | |
| 358 | 358 | /***********************************************************************//** |
| 359 | + * @brief Negate matrix elements | |
| 360 | + * | |
| 361 | + * @return Matrix with negated elements. | |
| 362 | + * | |
| 363 | + * Returns a matrix where each element has been replaced by its negative | |
| 364 | + * element. | |
| 365 | + ***************************************************************************/ | |
| 366 | +GMatrixSymmetric GMatrixSymmetric::operator-(void) const | |
| 367 | +{ | |
| 368 | + // Copy matrix | |
| 369 | + GMatrixSymmetric matrix = *this; | |
| 370 | + | |
| 371 | + // Take the absolute value of all matrix elements | |
| 372 | + double* ptr = matrix.m_data; | |
| 373 | + for (int i = 0; i < matrix.m_elements; ++i, ++ptr) { | |
| 374 | + *ptr = -(*ptr); | |
| 375 | + } | |
| 376 | + | |
| 377 | + // Return matrix | |
| 378 | + return matrix; | |
| 379 | +} | |
| 380 | + | |
| 381 | + | |
| 382 | +/***********************************************************************//** | |
| 359 | 383 | * @brief Unary matrix addition operator |
| 360 | 384 | * |
| 361 | 385 | * @param[in] matrix Matrix. |
| ... | ... | @@ -687,56 +711,78 @@ void GMatrixSymmetric::add_to_column(const int& column, const GVector& vector) |
| 687 | 711 | |
| 688 | 712 | |
| 689 | 713 | /***********************************************************************//** |
| 690 | - * @brief Invert matrix | |
| 714 | + * @brief Return inverted matrix | |
| 691 | 715 | * |
| 692 | - * Inverts the matrix using the Cholesky decomposition. This does not work | |
| 693 | - * on any kind of matrix. | |
| 716 | + * @return Inverted matrix. | |
| 717 | + * | |
| 718 | + * Returns inverse of matrix. Inversion is done for the moment using Cholesky | |
| 719 | + * decomposition. This does not work on any kind of matrix. | |
| 694 | 720 | * |
| 695 | 721 | * @todo Specify in documentation for which kind of matrix the method works. |
| 696 | 722 | ***************************************************************************/ |
| 697 | -void GMatrixSymmetric::invert(void) | |
| 723 | +GMatrixSymmetric GMatrixSymmetric::invert(void) const | |
| 698 | 724 | { |
| 725 | + // Allocate result matrix | |
| 726 | + GMatrixSymmetric matrix(m_cols, m_rows); | |
| 727 | + | |
| 699 | 728 | // Invert matrix |
| 700 | - cholesky_invert(true); | |
| 729 | + matrix.cholesky_invert(true); | |
| 701 | 730 | |
| 702 | - // Return | |
| 703 | - return; | |
| 731 | + // Return matrix | |
| 732 | + return matrix; | |
| 704 | 733 | } |
| 705 | 734 | |
| 706 | 735 | |
| 707 | 736 | /***********************************************************************//** |
| 708 | - * @brief Negate all matrix elements | |
| 737 | + * @brief Solves linear matrix equation | |
| 738 | + * | |
| 739 | + * @param[in] vector Solution vector. | |
| 740 | + * | |
| 741 | + * Solves the linear equation | |
| 709 | 742 | * |
| 710 | - * Negates all matrix elements. | |
| 743 | + * \f[M \times {\tt solution} = {\tt vector} \f] | |
| 744 | + * | |
| 745 | + * where \f$M\f$ is the matrix, \f${\tt vector}\f$ is the result, and | |
| 746 | + * \f${\tt solution}\f$ is the solution. Solving is done using Cholesky | |
| 747 | + * decomposition. This does not work on any kind of matrix. | |
| 748 | + * | |
| 749 | + * @todo Specify in documentation for which kind of matrix the method works. | |
| 711 | 750 | ***************************************************************************/ |
| 712 | -void GMatrixSymmetric::negate(void) | |
| 751 | +GVector GMatrixSymmetric::solve(const GVector& vector) const | |
| 713 | 752 | { |
| 714 | - // Negate all matrix elements | |
| 715 | - double* ptr = m_data; | |
| 716 | - for (int i = 0; i < m_elements; ++i, ++ptr) { | |
| 717 | - *ptr = -(*ptr); | |
| 718 | - } | |
| 719 | - | |
| 720 | - // Return | |
| 721 | - return; | |
| 753 | + // Get Cholesky decomposition of matrix | |
| 754 | + GMatrixSymmetric decomposition = cholesky_decompose(true); | |
| 755 | + | |
| 756 | + // Solve linear equation | |
| 757 | + GVector result = decomposition.cholesky_solver(vector); | |
| 758 | + | |
| 759 | + // Return result | |
| 760 | + return result; | |
| 722 | 761 | } |
| 723 | 762 | |
| 724 | 763 | |
| 725 | 764 | /***********************************************************************//** |
| 726 | - * @brief Take absolute value of matrix elements | |
| 765 | + * @brief Return absolute of matrix | |
| 766 | + * | |
| 767 | + * @return Absolute of matrix | |
| 727 | 768 | * |
| 728 | - * Replaces all elements of the matrix by their absolute values. | |
| 769 | + * Returns matrix where all elements of the matrix have been replaced by | |
| 770 | + * their absolute values. | |
| 729 | 771 | ***************************************************************************/ |
| 730 | -void GMatrixSymmetric::abs(void) | |
| 772 | +GMatrixSymmetric GMatrixSymmetric::abs(void) const | |
| 731 | 773 | { |
| 774 | + // Allocate result matrix | |
| 775 | + GMatrixSymmetric matrix(m_rows, m_cols); | |
| 776 | + | |
| 732 | 777 | // Take the absolute value of all matrix elements |
| 733 | - double* ptr = m_data; | |
| 734 | - for (int i = 0; i < m_elements; ++i, ++ptr) { | |
| 735 | - *ptr = std::abs(*ptr); | |
| 778 | + double* src = m_data; | |
| 779 | + double* dst = matrix.m_data; | |
| 780 | + for (int i = 0; i < m_elements; ++i) { | |
| 781 | + *dst++ = std::abs(*src++); | |
| 736 | 782 | } |
| 737 | - | |
| 738 | - // Return | |
| 739 | - return; | |
| 783 | + | |
| 784 | + // Return matrix | |
| 785 | + return matrix; | |
| 740 | 786 | } |
| 741 | 787 | |
| 742 | 788 | |
| ... | ... | @@ -848,60 +894,69 @@ GMatrix GMatrixSymmetric::extract_upper_triangle(void) const |
| 848 | 894 | |
| 849 | 895 | |
| 850 | 896 | /***********************************************************************//** |
| 851 | - * @brief Perform a Cholesky decomposition | |
| 897 | + * @brief Return Cholesky decomposition | |
| 852 | 898 | * |
| 853 | - * @param[in] compress Use zero-row/column compression (default: true). | |
| 899 | + * @param[in] compress Use zero-row/column compression (defaults to true). | |
| 900 | + * @return Cholesky decomposition of matrix | |
| 854 | 901 | * |
| 855 | 902 | * @exception GException::matrix_not_pos_definite |
| 856 | 903 | * Matrix is not positive definite. |
| 857 | 904 | * @exception GException::matrix_zero |
| 858 | 905 | * All matrix elements are zero. |
| 859 | 906 | * |
| 860 | - * Inplace Cholesky decomposition inspired by Numerical Recipes algorithm. | |
| 907 | + * Returns the Cholesky decomposition of a sparse matrix. The decomposition | |
| 908 | + * is stored within a GMatrixSymmetric object. | |
| 909 | + * | |
| 910 | + * The method is inspired by the algorithm found in Numerical Recipes. | |
| 861 | 911 | * The decomposition, which is a matrix occupying only the lower triange, |
| 862 | 912 | * is stored in the elements of the symmetric matrix. To visualise the |
| 863 | 913 | * matrix one has to use 'lower_triangle()' to extract the relevant part. |
| 864 | 914 | * Case A operates on a full matrix, Case B operates on a (logically) |
| 865 | 915 | * compressed matrix where zero rows/columns have been removed. |
| 866 | 916 | ***************************************************************************/ |
| 867 | -void GMatrixSymmetric::cholesky_decompose(bool compress) | |
| 917 | +GMatrixSymmetric GMatrixSymmetric::cholesky_decompose(bool compress) const | |
| 868 | 918 | { |
| 919 | + // Create copy of matrix | |
| 920 | + GMatrixSymmetric matrix = *this; | |
| 921 | + | |
| 869 | 922 | // Set-up incides of non zero rows if matrix compression is requested |
| 870 | 923 | if (compress) { |
| 871 | - set_inx(); | |
| 924 | + matrix.set_inx(); | |
| 872 | 925 | } |
| 873 | 926 | |
| 874 | 927 | // Check if zero-row/col compression is needed |
| 875 | - int no_zeros = ((compress && (m_num_inx == m_rows)) || !compress); | |
| 928 | + int no_zeros = ((compress && (matrix.m_num_inx == matrix.m_rows)) || !compress); | |
| 876 | 929 | |
| 877 | 930 | // Case A: no zero-row/col compression needed |
| 878 | 931 | if (no_zeros) { |
| 879 | 932 | |
| 880 | 933 | // Loop over upper triangle (col >= row) |
| 881 | 934 | double diag = 0.0; |
| 882 | - for (int row = 0; row < m_rows; ++row) { | |
| 883 | - double* ptr = m_data + m_colstart[row]; | |
| 884 | - for (int col = row; col < m_cols; ++col, ++ptr) { | |
| 885 | - double sum = *ptr; // sum = M(row,col) | |
| 935 | + for (int row = 0; row < matrix.m_rows; ++row) { | |
| 936 | + double* ptr = matrix.m_data + matrix.m_colstart[row]; | |
| 937 | + for (int col = row; col < matrix.m_cols; ++col, ++ptr) { | |
| 938 | + // sum = M(row,col) | |
| 939 | + double sum = *ptr; | |
| 886 | 940 | for (int k = 0; k < row; ++k) { |
| 887 | - int offset = m_colstart[k] - k; // is always positive | |
| 888 | - sum -= m_data[offset+row] * m_data[offset+col]; // sum -= M(row,k)*M(col,k) | |
| 941 | + int offset = matrix.m_colstart[k] - k; // is always positive | |
| 942 | + sum -= matrix.m_data[offset+row] * matrix.m_data[offset+col]; // sum -= M(row,k)*M(col,k) | |
| 889 | 943 | } |
| 890 | 944 | if (row == col) { |
| 891 | 945 | if (sum <= 0.0) { |
| 892 | 946 | throw GException::matrix_not_pos_definite(G_CHOL_DECOMP, row, sum); |
| 893 | 947 | } |
| 894 | - *ptr = sqrt(sum); // M(row,row) = sqrt(sum) | |
| 948 | + *ptr = std::sqrt(sum); // M(row,row) = sqrt(sum) | |
| 895 | 949 | diag = 1.0/(*ptr); |
| 896 | 950 | } |
| 897 | - else | |
| 898 | - *ptr = sum*diag; // M(row,col) = sum/M(row,row) | |
| 951 | + else { | |
| 952 | + *ptr = sum*diag; // M(row,col) = sum/M(row,row) | |
| 953 | + } | |
| 899 | 954 | } |
| 900 | 955 | } |
| 901 | 956 | } // endif: there were no zero rows/cols in matrix |
| 902 | 957 | |
| 903 | 958 | // Case B: zero-row/col compression needed |
| 904 | - else if (m_num_inx > 0) { | |
| 959 | + else if (matrix.m_num_inx > 0) { | |
| 905 | 960 | |
| 906 | 961 | // Allocate loop variables and pointers |
| 907 | 962 | int row; |
| ... | ... | @@ -913,25 +968,27 @@ void GMatrixSymmetric::cholesky_decompose(bool compress) |
| 913 | 968 | |
| 914 | 969 | // Loop over upper triangle (col >= row) |
| 915 | 970 | double diag = 0.0; |
| 916 | - for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) { | |
| 917 | - double* ptr_0 = m_data + m_colstart[*row_ptr] - *row_ptr; | |
| 918 | - for (col = row, col_ptr = m_inx + row; col < m_num_inx; ++col, ++col_ptr) { | |
| 971 | + for (row = 0, row_ptr = matrix.m_inx; row < matrix.m_num_inx; ++row, ++row_ptr) { | |
| 972 | + double* ptr_0 = matrix.m_data + matrix.m_colstart[*row_ptr] - *row_ptr; | |
| 973 | + for (col = row, col_ptr = matrix.m_inx + row; col < matrix.m_num_inx; ++col, ++col_ptr) { | |
| 919 | 974 | double* ptr = ptr_0 + *col_ptr; |
| 920 | 975 | double sum = *ptr; // sum = M(row,col) |
| 921 | - for (k = 0, k_ptr = m_inx; k < row; ++k, ++k_ptr) { | |
| 922 | - int offset = m_colstart[*k_ptr] - *k_ptr; // is always positive | |
| 923 | - sum -= m_data[offset+*row_ptr] * m_data[offset+*col_ptr]; | |
| 976 | + for (k = 0, k_ptr = matrix.m_inx; k < row; ++k, ++k_ptr) { | |
| 977 | + int offset = matrix.m_colstart[*k_ptr] - *k_ptr; // is always positive | |
| 978 | + sum -= matrix.m_data[offset+*row_ptr] * | |
| 979 | + matrix.m_data[offset+*col_ptr]; | |
| 924 | 980 | // sum -= M(row,k)*M(col,k) |
| 925 | 981 | } |
| 926 | 982 | if (*row_ptr == *col_ptr) { |
| 927 | 983 | if (sum <= 0.0) { |
| 928 | 984 | throw GException::matrix_not_pos_definite(G_CHOL_DECOMP, *row_ptr, sum); |
| 929 | 985 | } |
| 930 | - *ptr = sqrt(sum); // M(row,row) = sqrt(sum) | |
| 986 | + *ptr = std::sqrt(sum); // M(row,row) = sqrt(sum) | |
| 931 | 987 | diag = 1.0/(*ptr); |
| 932 | 988 | } |
| 933 | - else | |
| 934 | - *ptr = sum*diag; // M(row,col) = sum/M(row,row) | |
| 989 | + else { | |
| 990 | + *ptr = sum*diag; // M(row,col) = sum/M(row,row) | |
| 991 | + } | |
| 935 | 992 | } |
| 936 | 993 | } |
| 937 | 994 | } // endelse: zero-row/col compression needed |
| ... | ... | @@ -941,8 +998,8 @@ void GMatrixSymmetric::cholesky_decompose(bool compress) |
| 941 | 998 | throw GException::matrix_zero(G_CHOL_DECOMP); |
| 942 | 999 | } |
| 943 | 1000 | |
| 944 | - // Return | |
| 945 | - return; | |
| 1001 | + // Return matrix | |
| 1002 | + return matrix; | |
| 946 | 1003 | } |
| 947 | 1004 | |
| 948 | 1005 | |
| ... | ... | @@ -962,7 +1019,8 @@ void GMatrixSymmetric::cholesky_decompose(bool compress) |
| 962 | 1019 | * that is produced by 'cholesky_decompose'. Case A operates on a full |
| 963 | 1020 | * matrix, Case B on a zero rows/columns (logically) compressed matrix. |
| 964 | 1021 | ***************************************************************************/ |
| 965 | -GVector GMatrixSymmetric::cholesky_solver(const GVector& vector, bool compress) | |
| 1022 | +GVector GMatrixSymmetric::cholesky_solver(const GVector& vector, | |
| 1023 | + bool compress) const | |
| 966 | 1024 | { |
| 967 | 1025 | // Raise an exception if the matrix and vector dimensions are not compatible |
| 968 | 1026 | if (m_rows != vector.size()) { |
| ... | ... | @@ -1041,60 +1099,72 @@ GVector GMatrixSymmetric::cholesky_solver(const GVector& vector, bool compress) |
| 1041 | 1099 | |
| 1042 | 1100 | |
| 1043 | 1101 | /***********************************************************************//** |
| 1044 | - * @brief Cholesky invert | |
| 1102 | + * @brief Invert matrix using a Cholesky decomposition | |
| 1045 | 1103 | * |
| 1046 | - * @param[in] compress Use zero-row/column compression (default: true). | |
| 1104 | + * @param[in] compress Use zero-row/column compression (defaults to true). | |
| 1105 | + * @return Inverted matrix. | |
| 1047 | 1106 | * |
| 1048 | 1107 | * @exception GException::matrix_zero |
| 1049 | 1108 | * All matrix elements are zero. |
| 1050 | 1109 | * |
| 1051 | - * Inplace matrix inversion using the Cholesky decomposition. Case A | |
| 1052 | - * operates on a full matrix while Case B operates on a (logically) | |
| 1053 | - * compressed matrix where all zero rows/columns are skipped. | |
| 1110 | + * Inverts the matrix using a Cholesky decomposition. | |
| 1111 | + * | |
| 1112 | + * The method distinguish two cases. Case A operates on a full matrix while | |
| 1113 | + * Case B operates on a (logically) compressed matrix where all zero | |
| 1114 | + * rows/columns are skipped. | |
| 1054 | 1115 | ***************************************************************************/ |
| 1055 | -void GMatrixSymmetric::cholesky_invert(bool compress) | |
| 1116 | +GMatrixSymmetric GMatrixSymmetric::cholesky_invert(bool compress) const | |
| 1056 | 1117 | { |
| 1057 | 1118 | // Generate Cholesky decomposition of matrix |
| 1058 | - this->cholesky_decompose(compress); | |
| 1119 | + GMatrixSymmetric matrix = cholesky_decompose(compress); | |
| 1059 | 1120 | |
| 1060 | 1121 | // Check if zero-row/col compression is needed |
| 1061 | - int no_zeros = ((compress && (m_num_inx == m_rows)) || !compress); | |
| 1122 | + int no_zeros = ((compress && (matrix.m_num_inx == matrix.m_rows)) || !compress); | |
| 1062 | 1123 | |
| 1063 | 1124 | // Case A: no zero-row/col compression needed |
| 1064 | 1125 | if (no_zeros) { |
| 1065 | 1126 | |
| 1066 | 1127 | // Generate inverse of Cholesky decomposition (col>row) |
| 1067 | - for (int row = 0; row < m_rows; ++row) { | |
| 1068 | - double* ptr = m_data + m_colstart[row]; | |
| 1069 | - *ptr = 1.0/(*ptr); // M(row,row) = 1/M(row,row) | |
| 1070 | - for (int col = row+1; col < m_cols; ++col) { | |
| 1128 | + for (int row = 0; row < matrix.m_rows; ++row) { | |
| 1129 | + | |
| 1130 | + // M(row,row) = 1/M(row,row) | |
| 1131 | + double* ptr = matrix.m_data + matrix.m_colstart[row]; | |
| 1132 | + *ptr = 1.0/(*ptr); | |
| 1133 | + | |
| 1134 | + for (int col = row+1; col < matrix.m_cols; ++col) { | |
| 1135 | + | |
| 1136 | + // sum -= M(col,k)*M(k,row) | |
| 1071 | 1137 | double sum = 0.0; |
| 1072 | - double* ptr1 = m_data + col - row; | |
| 1138 | + double* ptr1 = matrix.m_data + col - row; | |
| 1073 | 1139 | double* ptr2 = ptr; |
| 1074 | 1140 | for (int k = row; k < col; ++k) { |
| 1075 | - sum -= *(ptr1-- + m_colstart[k]) * *ptr2++; // sum -= M(col,k)*M(k,row) | |
| 1141 | + sum -= *(ptr1-- + matrix.m_colstart[k]) * *ptr2++; | |
| 1076 | 1142 | } |
| 1077 | - *(ptr+col-row) = sum/m_data[m_colstart[col]]; // M(col,row) = sum/M(col,col) | |
| 1143 | + | |
| 1144 | + // M(col,row) = sum/M(col,col) | |
| 1145 | + *(ptr+col-row) = sum/matrix.m_data[matrix.m_colstart[col]]; | |
| 1078 | 1146 | } |
| 1079 | 1147 | } |
| 1080 | 1148 | |
| 1081 | 1149 | // Matrix multiplication (col>=row) |
| 1082 | - for (int row = 0; row < m_rows; ++row) { | |
| 1083 | - double* ptr = m_data + m_colstart[row]; | |
| 1084 | - for (int col = row; col < m_cols; ++col) { | |
| 1150 | + for (int row = 0; row < matrix.m_rows; ++row) { | |
| 1151 | + double* ptr = matrix.m_data + matrix.m_colstart[row]; | |
| 1152 | + for (int col = row; col < matrix.m_cols; ++col) { | |
| 1153 | + // sum += M(row,k)*M(k,col) | |
| 1085 | 1154 | double sum = 0.0; |
| 1086 | 1155 | double* ptr1 = ptr + col - row; |
| 1087 | - double* ptr2 = m_data + m_colstart[col]; | |
| 1088 | - for (int k = col; k < m_cols; ++k) { | |
| 1089 | - sum += *ptr1++ * *ptr2++; // sum += M(row,k)*M(k,col) | |
| 1156 | + double* ptr2 = matrix.m_data + matrix.m_colstart[col]; | |
| 1157 | + for (int k = col; k < matrix.m_cols; ++k) { | |
| 1158 | + sum += *ptr1++ * *ptr2++; | |
| 1090 | 1159 | } |
| 1091 | - *(ptr+col-row) = sum; // M(row,col) = sum | |
| 1160 | + // M(row,col) = sum | |
| 1161 | + *(ptr+col-row) = sum; | |
| 1092 | 1162 | } |
| 1093 | 1163 | } |
| 1094 | 1164 | } // endif: no zero-row/col compression needed |
| 1095 | 1165 | |
| 1096 | 1166 | // Case B: zero-row/col compression needed |
| 1097 | - else if (m_num_inx > 0) { | |
| 1167 | + else if (matrix.m_num_inx > 0) { | |
| 1098 | 1168 | |
| 1099 | 1169 | // Allocate loop variables and pointers |
| 1100 | 1170 | int row; |
| ... | ... | @@ -1105,33 +1175,51 @@ void GMatrixSymmetric::cholesky_invert(bool compress) |
| 1105 | 1175 | int* k_ptr; |
| 1106 | 1176 | |
| 1107 | 1177 | // Generate inverse of Cholesky decomposition (col>row) |
| 1108 | - for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) { | |
| 1109 | - double* ptr_diag = m_data + m_colstart[*row_ptr]; | |
| 1178 | + for (row = 0, row_ptr = matrix.m_inx; | |
| 1179 | + row < matrix.m_num_inx; ++row, ++row_ptr) { | |
| 1180 | + | |
| 1181 | + // M(row,row) = 1/M(row,row) | |
| 1182 | + double* ptr_diag = matrix.m_data + matrix.m_colstart[*row_ptr]; | |
| 1110 | 1183 | double* ptr_2 = ptr_diag - *row_ptr; |
| 1111 | - *ptr_diag = 1.0/(*ptr_diag); // M(row,row) = 1/M(row,row) | |
| 1112 | - for (col = row+1, col_ptr = m_inx+row+1; col < m_num_inx; ++col, ++col_ptr) { | |
| 1184 | + *ptr_diag = 1.0/(*ptr_diag); | |
| 1185 | + | |
| 1186 | + for (col = row+1, col_ptr = matrix.m_inx+row+1; | |
| 1187 | + col < matrix.m_num_inx; ++col, ++col_ptr) { | |
| 1188 | + | |
| 1189 | + // sum -= M(col,k)*M(k,row) | |
| 1113 | 1190 | double sum = 0.0; |
| 1114 | - double* ptr_1 = m_data + *col_ptr; | |
| 1115 | - for (k = row, k_ptr = m_inx+row; k < col; ++k, ++k_ptr) { | |
| 1116 | - sum -= *(ptr_1 + m_colstart[*k_ptr] - *k_ptr) * | |
| 1117 | - *(ptr_2 + *k_ptr); // sum -= M(col,k)*M(k,row) | |
| 1191 | + double* ptr_1 = matrix.m_data + *col_ptr; | |
| 1192 | + for (k = row, k_ptr = matrix.m_inx+row; | |
| 1193 | + k < col; ++k, ++k_ptr) { | |
| 1194 | + sum -= *(ptr_1 + matrix.m_colstart[*k_ptr] - *k_ptr) * | |
| 1195 | + *(ptr_2 + *k_ptr); | |
| 1118 | 1196 | } |
| 1119 | - *(ptr_2 + *col_ptr) = sum/m_data[m_colstart[*col_ptr]]; | |
| 1120 | - // M(col,row) = sum/M(col,col) | |
| 1197 | + | |
| 1198 | + // M(col,row) = sum/M(col,col) | |
| 1199 | + *(ptr_2 + *col_ptr) = | |
| 1200 | + sum/matrix.m_data[matrix.m_colstart[*col_ptr]]; | |
| 1121 | 1201 | } |
| 1122 | 1202 | } |
| 1123 | 1203 | |
| 1124 | 1204 | // Matrix multiplication (col>=row) |
| 1125 | - for (row = 0, row_ptr = m_inx; row < m_num_inx; ++row, ++row_ptr) { | |
| 1126 | - double* ptr_diag = m_data + m_colstart[*row_ptr]; | |
| 1205 | + for (row = 0, row_ptr = matrix.m_inx; | |
| 1206 | + row < matrix.m_num_inx; ++row, ++row_ptr) { | |
| 1207 | + double* ptr_diag = matrix.m_data + matrix.m_colstart[*row_ptr]; | |
| 1127 | 1208 | double* ptr_1 = ptr_diag - *row_ptr; |
| 1128 | - for (col = row, col_ptr = m_inx+row; col < m_num_inx; ++col, ++col_ptr) { | |
| 1209 | + | |
| 1210 | + for (col = row, col_ptr = matrix.m_inx+row; | |
| 1211 | + col < matrix.m_num_inx; ++col, ++col_ptr) { | |
| 1212 | + | |
| 1213 | + // sum += M(row,k)*M(k,col) | |
| 1129 | 1214 | double sum = 0.0; |
| 1130 | - double* ptr_2 = m_data + m_colstart[*col_ptr] - *col_ptr; | |
| 1131 | - for (k = col, k_ptr = m_inx+col; k < m_num_inx; ++k, ++k_ptr) { | |
| 1132 | - sum += *(ptr_1 + *k_ptr) * *(ptr_2 + *k_ptr); // sum += M(row,k)*M(k,col) | |
| 1215 | + double* ptr_2 = matrix.m_data + matrix.m_colstart[*col_ptr] - *col_ptr; | |
| 1216 | + for (k = col, k_ptr = matrix.m_inx+col; | |
| 1217 | + k < matrix.m_num_inx; ++k, ++k_ptr) { | |
| 1218 | + sum += *(ptr_1 + *k_ptr) * *(ptr_2 + *k_ptr); | |
| 1133 | 1219 | } |
| 1134 | - *(ptr_1 + *col_ptr) = sum; // M(row,col) = sum | |
| 1220 | + | |
| 1221 | + // M(row,col) = sum | |
| 1222 | + *(ptr_1 + *col_ptr) = sum; | |
| 1135 | 1223 | } |
| 1136 | 1224 | } |
| 1137 | 1225 | } // endelse: zero-row/col compression needed |
| ... | ... | @@ -1141,8 +1229,8 @@ void GMatrixSymmetric::cholesky_invert(bool compress) |
| 1141 | 1229 | throw GException::matrix_zero(G_CHOL_INVERT); |
| 1142 | 1230 | } |
| 1143 | 1231 | |
| 1144 | - // Return | |
| 1145 | - return; | |
| 1232 | + // Return matrix | |
| 1233 | + return matrix; | |
| 1146 | 1234 | } |
| 1147 | 1235 | |
| 1148 | 1236 | ... | ... |