source: src/LinearAlgebra/MatrixContent.cpp@ 9df680

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 9df680 was ad011c, checked in by Frederik Heber <heber@…>, 14 years ago

CodePatterns places all includes now in subfolder CodePatterns/.

  • change all includes accordingly.
  • this was necessary as Helpers and Patterns are not very distinctive names for include folders. Already now, we had a conflict between Helpers from CodePatterns and Helpers from this project.
  • changed compilation test in ax_codepatterns.m4 when changing CodePatterns includes.
  • Property mode set to 100644
File size: 21.4 KB
Line 
1/*
2 * MatrixContent.cpp
3 *
4 * Created on: Nov 14, 2010
5 * Author: heber
6 */
7
8
9// include config.h
10#ifdef HAVE_CONFIG_H
11#include <config.h>
12#endif
13
14#include "CodePatterns/MemDebug.hpp"
15
16#include "LinearAlgebra/RealSpaceMatrix.hpp"
17#include "Exceptions/NotInvertibleException.hpp"
18#include "CodePatterns/Assert.hpp"
19#include "Helpers/defs.hpp"
20#include "Helpers/fast_functions.hpp"
21#include "LinearAlgebra/Vector.hpp"
22#include "LinearAlgebra/VectorContent.hpp"
23#include "LinearAlgebra/MatrixContent.hpp"
24
25#include <gsl/gsl_blas.h>
26#include <gsl/gsl_eigen.h>
27#include <gsl/gsl_linalg.h>
28#include <gsl/gsl_matrix.h>
29#include <gsl/gsl_multimin.h>
30#include <gsl/gsl_vector.h>
31#include <cmath>
32#include <cassert>
33#include <iostream>
34#include <set>
35
36using namespace std;
37
38
39/** Constructor for class MatrixContent.
40 * \param rows number of rows
41 * \param columns number of columns
42 */
43MatrixContent::MatrixContent(size_t _rows, size_t _columns) :
44 rows(_rows),
45 columns(_columns)
46{
47 content = gsl_matrix_calloc(rows, columns);
48}
49
50/** Constructor of class VectorContent.
51 * We need this MatrixBaseCase for the VectorContentView class.
52 * There no content should be allocated, as it is just a view with an internal
53 * gsl_vector_view. Hence, MatrixBaseCase is just dummy class to give the
54 * constructor a unique signature.
55 * \param MatrixBaseCase
56 */
57MatrixContent::MatrixContent(size_t _rows, size_t _columns, MatrixBaseCase) :
58 rows(_rows),
59 columns(_columns)
60{}
61
62/** Constructor for class MatrixContent.
63 * \param rows number of rows
64 * \param columns number of columns
65 * \param *src array with components to initialize matrix with
66 */
67MatrixContent::MatrixContent(size_t _rows, size_t _columns, const double *src) :
68 rows(_rows),
69 columns(_columns)
70{
71 content = gsl_matrix_calloc(rows, columns);
72 set(0,0, src[0]);
73 set(1,0, src[1]);
74 set(2,0, src[2]);
75
76 set(0,1, src[3]);
77 set(1,1, src[4]);
78 set(2,1, src[5]);
79
80 set(0,2, src[6]);
81 set(1,2, src[7]);
82 set(2,2, src[8]);
83}
84
85/** Constructor for class MatrixContent.
86 * We embed the given gls_matrix pointer within this class and set it to NULL
87 * afterwards.
88 * \param *src source gsl_matrix vector to embed within this class
89 */
90MatrixContent::MatrixContent(gsl_matrix *&src) :
91 rows(src->size1),
92 columns(src->size2)
93{
94 content = gsl_matrix_alloc(src->size1, src->size2);
95 gsl_matrix_memcpy(content,src);
96// content = src;
97// src = NULL;
98}
99
100/** Copy constructor for class MatrixContent.
101 * \param &src reference to source MatrixContent
102 */
103MatrixContent::MatrixContent(const MatrixContent &src) :
104 rows(src.rows),
105 columns(src.columns)
106{
107 content = gsl_matrix_alloc(src.rows, src.columns);
108 gsl_matrix_memcpy(content,src.content);
109}
110
111/** Copy constructor for class MatrixContent.
112 * \param *src pointer to source MatrixContent
113 */
114MatrixContent::MatrixContent(const MatrixContent *src) :
115 rows(src->rows),
116 columns(src->columns)
117{
118 ASSERT(src != NULL, "MatrixContent::MatrixContent - pointer to source matrix is NULL!");
119 content = gsl_matrix_alloc(src->rows, src->columns);
120 gsl_matrix_memcpy(content,src->content);
121}
122
123/** Destructor for class MatrixContent.
124 */
125MatrixContent::~MatrixContent()
126{
127 gsl_matrix_free(content);
128}
129
130/** Getter for MatrixContent::rows.
131 * \return MatrixContent::rows
132 */
133const size_t MatrixContent::getRows() const
134{
135 return rows;
136}
137
138/** Getter for MatrixContent::columns.
139 * \return MatrixContent::columns
140 */
141const size_t MatrixContent::getColumns() const
142{
143 return columns;
144}
145
146/** Return a VectorViewContent of the \a column -th column vector.
147 *
148 * @param column index of column
149 * @return column of matrix as VectorContent
150 */
151VectorContent *MatrixContent::getColumnVector(size_t column) const
152{
153 ASSERT(column < columns,
154 "MatrixContent::getColumnVector() - requested column "+toString(column)
155 +" greater than dimension "+toString(columns));
156 return (new VectorViewContent(gsl_matrix_column(content,column)));
157}
158
159/** Returns a VectorViewContent of the \a row -th row vector.
160 * @param row row index
161 * @return VectorContent of row vector
162 */
163VectorContent *MatrixContent::getRowVector(size_t row) const
164{
165 ASSERT(row < rows,
166 "MatrixContent::getColumnVector() - requested row "+toString(row)
167 +" greater than dimension "+toString(rows));
168 return (new VectorViewContent(gsl_matrix_row(content,row)));
169}
170
171/** Returns the main diagonal of the matrix as VectorContent.
172 * @return diagonal as VectorContent.
173 */
174VectorContent *MatrixContent::getDiagonalVector() const
175{
176 return (new VectorViewContent(gsl_matrix_diagonal(content)));
177}
178
179/** Set matrix to identity.
180 */
181void MatrixContent::setIdentity()
182{
183 for(int i=rows;i--;){
184 for(int j=columns;j--;){
185 set(i,j,(double)(i==j));
186 }
187 }
188}
189
190/** Set all matrix components to zero.
191 */
192void MatrixContent::setZero()
193{
194 for(int i=rows;i--;){
195 for(int j=columns;j--;){
196 set(i,j,0.);
197 }
198 }
199}
200
201/** Set all matrix components to a given value.
202 * \param _value value to set each component to
203 */
204void MatrixContent::setValue(double _value)
205{
206 for(int i=rows;i--;){
207 for(int j=columns;j--;){
208 set(i,j,_value);
209 }
210 }
211}
212
213/** Copy operator for MatrixContent with self-assignment check.
214 * \param &src matrix to compare to
215 * \return reference to this
216 */
217MatrixContent &MatrixContent::operator=(const MatrixContent &src)
218{
219 if(&src!=this){
220 gsl_matrix_memcpy(content,src.content);
221 }
222 return *this;
223}
224
225/** Addition operator.
226 * \param &rhs matrix to add
227 * \return reference to this
228 */
229const MatrixContent &MatrixContent::operator+=(const MatrixContent &rhs)
230{
231 gsl_matrix_add(content, rhs.content);
232 return *this;
233}
234
235/** Subtraction operator.
236 * \param &rhs matrix to subtract
237 * \return reference to this
238 */
239const MatrixContent &MatrixContent::operator-=(const MatrixContent &rhs)
240 {
241 gsl_matrix_sub(content, rhs.content);
242 return *this;
243}
244
245/** Multiplication operator.
246 * Note that here matrix have to have same dimensions.
247 * \param &rhs matrix to multiply with
248 * \return reference to this
249 */
250const MatrixContent &MatrixContent::operator*=(const MatrixContent &rhs)
251{
252 ASSERT(rhs.columns == rhs.rows,
253 "MatrixContent::operator*=() - rhs matrix is not square: "+toString(rhs.columns)+" != "+toString(rhs.rows)+".");
254 ASSERT(columns == rhs.rows,
255 "MatrixContent::operator*=() - columns dimension differ: "+toString(columns)+" != "+toString(rhs.rows)+".");
256 (*this) = (*this)*rhs;
257 return *this;
258}
259
260/** Multiplication with copy operator.
261 * \param &rhs matrix to multiply with
262 * \return reference to newly allocated MatrixContent
263 */
264const MatrixContent MatrixContent::operator*(const MatrixContent &rhs) const
265{
266 ASSERT (columns == rhs.rows,
267 "MatrixContent::operator*() - dimensions not match for matrix product (a,b)*(b,c) = (a,c):"
268 "("+toString(rows)+","+toString(columns)+")*("+toString(rhs.rows)+","+toString(rhs.columns)+")");
269 gsl_matrix *res = gsl_matrix_alloc(rows, rhs.columns);
270 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, content, rhs.content, 0.0, res);
271 // gsl_matrix is taken over by constructor, hence no free
272 MatrixContent tmp(res);
273 gsl_matrix_free(res);
274 return tmp;
275}
276
277/** Hadamard multiplication with copy operator.
278 * The Hadamard product is component-wise matrix product.
279 * \param &rhs matrix to hadamard-multiply with
280 * \return reference to newly allocated MatrixContent
281 */
282const MatrixContent MatrixContent::operator&(const MatrixContent &rhs) const
283{
284 ASSERT ((rows == rhs.rows) && (columns == rhs.columns),
285 "MatrixContent::operator&() - dimensions not match for matrix product (a,b) != (b,c):"
286 "("+toString(rows)+","+toString(columns)+") != ("+toString(rhs.rows)+","+toString(rhs.columns)+")");
287 gsl_matrix *res = gsl_matrix_alloc(rows, rhs.columns);
288 for (size_t i=0;i<rows;++i)
289 for (size_t j=0;j<columns;++j)
290 gsl_matrix_set(res, i,j, gsl_matrix_get(content, i,j)*gsl_matrix_get(rhs.content, i,j));
291 // gsl_matrix is taken over by constructor, hence no free
292 MatrixContent tmp(res);
293 gsl_matrix_free(res);
294 return tmp;
295}
296
297/** Hadamard multiplication with copy operator.
298 * The Hadamard product is component-wise matrix product.
299 * Note that Hadamard product can easily be done on top of \a *this matrix.
300 * Hence, we don't need to use the multiply and copy operator as in the case of
301 * MatrixContent::operator*=().
302 * \param &rhs matrix to hadamard-multiply with
303 * \return reference to newly allocated MatrixContent
304 */
305const MatrixContent &MatrixContent::operator&=(const MatrixContent &rhs)
306{
307 ASSERT ((rows == rhs.rows) && (columns == rhs.columns),
308 "MatrixContent::operator&() - dimensions not match for matrix product (a,b) != (b,c):"
309 "("+toString(rows)+","+toString(columns)+") != ("+toString(rhs.rows)+","+toString(rhs.columns)+")");
310 for (size_t i=0;i<rows;++i)
311 for (size_t j=0;j<columns;++j)
312 gsl_matrix_set(content, i,j, gsl_matrix_get(content, i,j)*gsl_matrix_get(rhs.content, i,j));
313 return *this;
314}
315
316/* ========================== Accessing =============================== */
317
318/** Accessor for manipulating component (i,j).
319 * \param i row number
320 * \param j column number
321 * \return reference to component (i,j)
322 */
323double &MatrixContent::at(size_t i, size_t j)
324{
325 ASSERT((i>=0) && (i<rows),
326 "MatrixContent::at() - Index i="+toString(i)+" for Matrix access out of range [0,"+toString(rows)+"]");
327 ASSERT((j>=0) && (j<columns),
328 "MatrixContent::at() - Index j="+toString(j)+" for Matrix access out of range [0,"+toString(columns)+"]");
329 return *gsl_matrix_ptr (content, i, j);
330}
331
332/** Constant accessor for (value of) component (i,j).
333 * \param i row number
334 * \param j column number
335 * \return const component (i,j)
336 */
337const double MatrixContent::at(size_t i, size_t j) const
338{
339 ASSERT((i>=0) && (i<rows),
340 "MatrixContent::at() - Index i="+toString(i)+" for Matrix access out of range [0,"+toString(rows)+"]");
341 ASSERT((j>=0) && (j<columns),
342 "MatrixContent::at() - Index j="+toString(j)+" for Matrix access out of range [0,"+toString(columns)+"]");
343 return gsl_matrix_get(content, i, j);
344}
345
346/** These functions return a pointer to the \a m-th element of a matrix.
347 * If \a m or \a n lies outside the allowed range of 0 to MatrixContent::dimension-1 then the error handler is invoked and a null pointer is returned.
348 * \param m index
349 * \return pointer to \a m-th element
350 */
351double *MatrixContent::Pointer(size_t m, size_t n)
352{
353 return gsl_matrix_ptr (content, m, n);
354};
355
356/** These functions return a constant pointer to the \a m-th element of a matrix.
357 * If \a m or \a n lies outside the allowed range of 0 to MatrixContent::dimension-1 then the error handler is invoked and a null pointer is returned.
358 * \param m index
359 * \return const pointer to \a m-th element
360 */
361const double *MatrixContent::const_Pointer(size_t m, size_t n) const
362{
363 return gsl_matrix_const_ptr (content, m, n);
364};
365
366/* ========================== Initializing =============================== */
367
368/** Setter for component (i,j).
369 * \param i row numbr
370 * \param j column numnber
371 * \param value value to set componnt (i,j) to
372 */
373void MatrixContent::set(size_t i, size_t j, const double value)
374{
375 ASSERT((i>=0) && (i<rows),
376 "MatrixContent::set() - Index i="+toString(i)+" for Matrix access out of range [0,"+toString(rows)+"]");
377 ASSERT((j>=0) && (j<columns),
378 "MatrixContent::set() - Index j="+toString(j)+" for Matrix access out of range [0,"+toString(columns)+"]");
379 gsl_matrix_set(content,i,j,value);
380}
381
382/** This function sets the matrix from a double array.
383 * Creates a matrix view of the array and performs a memcopy.
384 * \param *x array of values (no dimension check is performed)
385 */
386void MatrixContent::setFromDoubleArray(double * x)
387{
388 gsl_matrix_view m = gsl_matrix_view_array (x, rows, columns);
389 gsl_matrix_memcpy (content, &m.matrix);
390};
391
392/* ====================== Exchanging elements ============================ */
393/** This function exchanges the \a i-th and \a j-th row of the matrix in-place.
394 * \param i i-th row to swap with ...
395 * \param j ... j-th row to swap against
396 */
397bool MatrixContent::SwapRows(size_t i, size_t j)
398{
399 return (gsl_matrix_swap_rows (content, i, j) == GSL_SUCCESS);
400};
401
402/** This function exchanges the \a i-th and \a j-th column of the matrix in-place.
403 * \param i i-th column to swap with ...
404 * \param j ... j-th column to swap against
405 */
406bool MatrixContent::SwapColumns(size_t i, size_t j)
407{
408 return (gsl_matrix_swap_columns (content, i, j) == GSL_SUCCESS);
409};
410
411/** This function exchanges the \a i-th row and \a j-th column of the matrix in-place.
412 * The matrix must be square for this operation to be possible.
413 * \param i i-th row to swap with ...
414 * \param j ... j-th column to swap against
415 */
416bool MatrixContent::SwapRowColumn(size_t i, size_t j)
417{
418 ASSERT (rows == columns,
419 "MatrixContent::SwapRowColumn() - The matrix must be square for swapping row against column to be possible.");
420 return (gsl_matrix_swap_rowcol (content, i, j) == GSL_SUCCESS);
421};
422
423/** Return transposed matrix.
424 * \return new matrix that is transposed of this.
425 */
426MatrixContent MatrixContent::transpose() const
427{
428 gsl_matrix *res = gsl_matrix_alloc(columns, rows); // column and row dimensions exchanged!
429 gsl_matrix_transpose_memcpy(res, content);
430 MatrixContent newContent(res);
431 gsl_matrix_free(res);
432 return newContent;
433}
434
435/** Turn this matrix into its transposed.
436 * Note that this is only possible if rows == columns.
437 */
438MatrixContent &MatrixContent::transpose()
439{
440 ASSERT( rows == columns,
441 "MatrixContent::transpose() - cannot transpose onto itself as matrix not square: "+toString(rows)+"!="+toString(columns)+"!");
442 double tmp;
443 for (size_t i=0;i<rows;i++)
444 for (size_t j=i+1;j<rows;j++) {
445 tmp = at(j,i);
446 at(j,i) = at(i,j);
447 at(i,j) = tmp;
448 }
449 return *this;
450}
451
452/** Transform the matrix to its eigenbasis and return resulting eigenvalues.
453 * Note that we only return real-space part in case of non-symmetric matrix.
454 * \warn return vector has to be freed'd
455 * TODO: encapsulate return value in boost::shared_ptr or in VectorContent.
456 * \return gsl_vector pointer to vector of eigenvalues
457 */
458gsl_vector* MatrixContent::transformToEigenbasis()
459{
460 if (rows == columns) { // symmetric
461 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(rows);
462 gsl_vector *eval = gsl_vector_alloc(rows);
463 gsl_matrix *evec = gsl_matrix_alloc(rows, rows);
464 gsl_eigen_symmv(content, eval, evec, T);
465 gsl_eigen_symmv_free(T);
466 gsl_matrix_memcpy(content, evec);
467 gsl_matrix_free(evec);
468 return eval;
469 } else { // non-symmetric
470 // blow up gsl_matrix in content to square matrix, fill other components with zero
471 const size_t greaterDimension = rows > columns ? rows : columns;
472 gsl_matrix *content_square = gsl_matrix_alloc(greaterDimension, greaterDimension);
473 for (size_t i=0; i<greaterDimension; i++) {
474 for (size_t j=0; j<greaterDimension; j++) {
475 const double value = ((i < rows) && (j < columns)) ? gsl_matrix_get(content,i,j) : 0.;
476 gsl_matrix_set(content_square, i,j, value);
477 }
478 }
479
480 // show squared matrix by putting it into a MatrixViewContent
481 MatrixContent *ContentSquare = new MatrixViewContent(gsl_matrix_submatrix(content_square,0,0,content_square->size1, content_square->size2));
482 std::cout << "The squared matrix is " << *ContentSquare << std::endl;
483
484 // solve eigenvalue problem
485 gsl_eigen_nonsymmv_workspace *T = gsl_eigen_nonsymmv_alloc(rows);
486 gsl_vector_complex *eval = gsl_vector_complex_alloc(greaterDimension);
487 gsl_matrix_complex *evec = gsl_matrix_complex_alloc(greaterDimension, greaterDimension);
488 gsl_eigen_nonsymmv(content_square, eval, evec, T);
489 gsl_eigen_nonsymmv_free(T);
490
491 // copy eigenvectors real-parts into content_square and ...
492 for (size_t i=0; i<greaterDimension; i++)
493 for (size_t j=0; j<greaterDimension; j++)
494 gsl_matrix_set(content_square, i,j, GSL_REAL(gsl_matrix_complex_get(evec,i,j)));
495
496 // ... show complex-valued eigenvector matrix
497 std::cout << "The real-value eigenvector matrix is " << *ContentSquare << std::endl;
498// std::cout << "Resulting eigenvector matrix is [";
499// for (size_t i=0; i<greaterDimension; i++) {
500// for (size_t j=0; j<greaterDimension; j++) {
501// std::cout << "(" << GSL_REAL(gsl_matrix_complex_get(evec,i,j))
502// << "," << GSL_IMAG(gsl_matrix_complex_get(evec,i,j)) << ")";
503// if (j < greaterDimension-1)
504// std::cout << " ";
505// }
506// if (i < greaterDimension-1)
507// std::cout << "; ";
508// }
509// std::cout << "]" << std::endl;
510
511 // copy real-parts of complex eigenvalues and eigenvectors (column-wise orientation)
512 gsl_vector *eval_real = gsl_vector_alloc(columns);
513 size_t I=0;
514 for (size_t i=0; i<greaterDimension; i++) { // only copy real space part
515 if (fabs(GSL_REAL(gsl_vector_complex_get(eval,i))) > MYEPSILON) { // only take eigenvectors with value > 0
516 std::cout << i << "th eigenvalue is (" << GSL_REAL(gsl_vector_complex_get(eval,i)) << "," << GSL_IMAG(gsl_vector_complex_get(eval,i)) << ")" << std::endl;
517 for (size_t j=0; j<greaterDimension; j++) {
518 if (fabs(GSL_IMAG(gsl_matrix_complex_get(evec,j,i))) > MYEPSILON)
519 std::cerr << "MatrixContent::transformToEigenbasis() - WARNING: eigenvectors are complex-valued!" << std::endl;
520 gsl_matrix_set(content, j,I, GSL_REAL(gsl_matrix_complex_get(evec,j,i)));
521 }
522 if (fabs(GSL_IMAG(gsl_vector_complex_get(eval,I))) > MYEPSILON)
523 std::cerr << "MatrixContent::transformToEigenbasis() - WARNING: eigenvectors are complex-valued!" << std::endl;
524 gsl_vector_set(eval_real, I, GSL_REAL(gsl_vector_complex_get(eval, i)));
525 I++;
526 }
527 }
528 gsl_matrix_complex_free(evec);
529 gsl_vector_complex_free(eval);
530 delete ContentSquare;
531
532 return eval_real;
533 }
534}
535
536
537/** Sorts the eigenpairs in ascending order of the eigenvalues.
538 * We assume that MatrixContent::transformToEigenbasis() has just been called.
539 * @param eigenvalues vector of eigenvalue from
540 * MatrixContent::transformToEigenbasis()
541 */
542void MatrixContent::sortEigenbasis(gsl_vector *eigenvalues)
543{
544 gsl_eigen_symmv_sort (eigenvalues, content,
545 GSL_EIGEN_SORT_ABS_ASC);
546}
547
548/* ============================ Properties ============================== */
549/** Checks whether matrix' elements are strictly null.
550 * \return true - is null, false - else
551 */
552bool MatrixContent::IsNull() const
553{
554 return gsl_matrix_isnull (content);
555};
556
557/** Checks whether matrix' elements are strictly positive.
558 * \return true - is positive, false - else
559 */
560bool MatrixContent::IsPositive() const
561{
562 return gsl_matrix_ispos (content);
563};
564
565/** Checks whether matrix' elements are strictly negative.
566 * \return true - is negative, false - else
567 */
568bool MatrixContent::IsNegative() const
569{
570 return gsl_matrix_isneg (content);
571};
572
573/** Checks whether matrix' elements are strictly non-negative.
574 * \return true - is non-negative, false - else
575 */
576bool MatrixContent::IsNonNegative() const
577{
578 return gsl_matrix_isnonneg (content);
579};
580
581/** This function performs a Cholesky decomposition to determine whether matrix is positive definite.
582 * We check whether GSL returns GSL_EDOM as error, indicating that decomposition failed due to matrix not being positive-definite.
583 * \return true - matrix is positive-definite, false - else
584 */
585bool MatrixContent::IsPositiveDefinite() const
586{
587 if (rows != columns) // only possible for square matrices.
588 return false;
589 else
590 return (gsl_linalg_cholesky_decomp (content) != GSL_EDOM);
591};
592
593
594/** Calculates the determinant of the matrix.
595 * if matrix is square, uses LU decomposition.
596 */
597double MatrixContent::Determinant() const
598{
599 int signum = 0;
600 ASSERT(rows == columns,
601 "MatrixContent::Determinant() - determinant can only be calculated for square matrices.");
602 gsl_permutation *p = gsl_permutation_alloc(rows);
603 gsl_linalg_LU_decomp(content, p, &signum);
604 gsl_permutation_free(p);
605 return gsl_linalg_LU_det(content, signum);
606};
607
608/* ============================= Operators =============================== */
609
610/** Scalar multiplication operator.
611 * \param factor factor to scale with
612 */
613const MatrixContent &MatrixContent::operator*=(const double factor)
614{
615 gsl_matrix_scale(content, factor);
616 return *this;
617}
618
619/** Scalar multiplication and copy operator.
620 * \param factor factor to scale with
621 * \param &mat MatrixContent to scale
622 * \return copied and scaled MatrixContent
623 */
624const MatrixContent operator*(const double factor,const MatrixContent& mat)
625{
626 MatrixContent tmp = mat;
627 tmp*=factor;
628 return tmp;
629}
630
631/** Scalar multiplication and copy operator (with operands exchanged).
632 * \param &mat MatrixContent to scale
633 * \param factor factor to scale with
634 * \return copied and scaled MatrixContent
635 */
636const MatrixContent operator*(const MatrixContent &mat,const double factor)
637{
638 return factor*mat;
639}
640
641/** Equality operator.
642 * Note that we use numerical sensible checking, i.e. with threshold MYEPSILON.
643 * \param &rhs MatrixContent to checks against
644 */
645bool MatrixContent::operator==(const MatrixContent &rhs) const
646 {
647 if ((rows == rhs.rows) && (columns == rhs.columns)) {
648 for(int i=rows;i--;){
649 for(int j=columns;j--;){
650 if(fabs(at(i,j)-rhs.at(i,j))>MYEPSILON){
651 return false;
652 }
653 }
654 }
655 return true;
656 }
657 return false;
658}
659
660
661std::ostream & operator<<(std::ostream &ost, const MatrixContent &mat)
662{
663 ost << "\\begin{pmatrix}";
664 for (size_t i=0;i<mat.rows;i++) {
665 for (size_t j=0;j<mat.columns;j++) {
666 ost << mat.at(i,j) << " ";
667 if (j != mat.columns-1)
668 ost << "& ";
669 }
670 if (i != mat.rows-1)
671 ost << "\\\\ ";
672 }
673 ost << "\\end{pmatrix}";
674 return ost;
675}
Note: See TracBrowser for help on using the repository browser.