source: src/LinearAlgebra/MatrixContent.cpp@ e4fe8d

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 e4fe8d was e4fe8d, checked in by Frederik Heber <heber@…>, 14 years ago

Moved defs.?pp to subdir (and library) Helpers.

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