npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
Matrix.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_MATRIX_HH_
2 #define NPSTAT_MATRIX_HH_
3 
4 /*!
5 // \file Matrix.hh
6 //
7 // \brief Template matrix class
8 //
9 // Author: I. Volobouev
10 //
11 // November 2008
12 */
13 
14 #include <vector>
15 #include <algorithm>
16 #include <stdexcept>
17 #include <utility>
18 
19 #include "geners/ClassId.hh"
20 
21 #include "npstat/nm/EigenMethod.hh"
22 #include "npstat/nm/SvdMethod.hh"
24 
25 namespace npstat {
26  /**
27  // A simple helper class for matrix manipulations. Depending on how much
28  // space is provided with the "Len" parameter, the data will be placed
29  // either on the stack or on the heap. Do not set "Len" to 0, the code
30  // assumes that the stack space is available for at least one element.
31  //
32  // C storage convention is used for internal data. In the element access
33  // operations, array bounds are not checked.
34  //
35  // A number of operations (solving linear systems, calculating eigenvalues
36  // and eigenvectors, singular value decomposition, etc) are performed
37  // by calling appropriate routines from LAPACK. This usually limits
38  // the Numeric template parameter types for which these operations are
39  // available to float and double. If the operation is unavailable for
40  // the template parameter used, std::invalid_argument exception is raised.
41  //
42  // Note that for simple matrix operations this class is likely to be
43  // slower than matrix classes based on expression templates (such as
44  // those in boost uBLAS or in Blitz++). If speed is really important
45  // for your calculations, consider using a dedicated matrix library.
46  */
47  template<typename Numeric, unsigned Len=16U>
48  class Matrix
49  {
50  template <typename Num2, unsigned Len2>
51  friend class Matrix;
52 
53  public:
54  typedef Numeric value_type;
55 
56  /**
57  // Default constructor creates an unitialized matrix
58  // which can be assigned from other matrices
59  */
60  Matrix();
61 
62  /**
63  // This constructor creates an unitialized matrix
64  // which can be assigned element-by-element or from
65  // another matrix with the same dimensions
66  */
67  Matrix(unsigned nrows, unsigned ncols);
68 
69  /**
70  // This constructor initializes the matrix as follows:
71  //
72  // initCode = 0: all elements are initialized to 0.
73  //
74  // initCode = 1: matrix must be square; diagonal elements are
75  // initialized to 1, all other elements to 0.
76  */
77  Matrix(unsigned nrows, unsigned ncols, int initCode);
78 
79  /**
80  // This constructor initializes the matrix from the
81  // given 1-d array using C storage conventions
82  */
83  Matrix(unsigned nrows, unsigned ncols, const Numeric* data);
84 
85  /** Copy constructor */
86  Matrix(const Matrix&);
87 
88  /** Move constructor */
90 
91  /** Converting copy constructor */
92  template <typename Num2, unsigned Len2>
94 
95  /**
96  // Constructor from a subrange of another matrix. The minimum row
97  // and column numbers are included, maximum numbers are excluded.
98  */
99  template <typename Num2, unsigned Len2>
101  unsigned rowMin, unsigned rowMax,
102  unsigned columnMin, unsigned columnMax);
103 
104  ~Matrix();
105 
106  /**
107  // Assignment operator. The matrix on the left must either be
108  // in an uninitialized state or have compatible dimensions with
109  // the matrix on the right.
110  */
112 
113  /** Move assignment operator */
115 
116  /** Converting assignment operator */
117  template <typename Num2, unsigned Len2>
119 
120  /** Set from triplets (for compatibility with Eigen) */
121  template<typename Iterator>
122  Matrix& setFromTriplets(Iterator first, Iterator last);
123 
124  /** Set all data from an external array */
125  template <typename Num2>
126  Matrix& setData(const Num2* data, unsigned dataLength);
127 
128  /** Set a row from an external array */
129  template <typename Num2>
130  Matrix& setRow(unsigned row, const Num2* data, unsigned dataLength);
131 
132  /** Set a column from an external array */
133  template <typename Num2>
134  Matrix& setColumn(unsigned col, const Num2* data, unsigned dataLength);
135 
136  /**
137  // Tag this matrix as diagonal. This may improve the speed
138  // of certain operations. Of course, this should be done only
139  // if you know for sure that this matrix is, indeed, diagonal.
140  // Works for square matrices only.
141  //
142  // This method can also be used to tag matrices as non-diagonal.
143  */
144  Matrix& tagAsDiagonal(bool b=true);
145 
146  /**
147  // Fill the main diagonal and set all other elements to zero.
148  // This operation tags the matrix as diagonal.
149  */
150  template <typename Num2>
151  Matrix& diagFill(const Num2* data, unsigned dataLen);
152 
153  //@{
154  /** A simple inspection of matrix properties */
155  inline unsigned nRows() const {return nrows_;}
156  inline unsigned nColumns() const {return ncols_;}
157  inline unsigned long length() const
158  {return static_cast<unsigned long>(nrows_)*ncols_;}
159  inline Numeric* data() const {return data_;}
160  inline bool isSquare() const {return data_ && ncols_ == nrows_;}
161  bool isSymmetric() const;
162  bool isAntiSymmetric() const;
163  bool isDiagonal() const;
164  bool isMainDiagonal() const; // Works for non-square matrices
165  bool isZero() const;
166  //@}
167 
168  /**
169  // This method resets the object to an unintialized state
170  // Can be applied in order to force the assignment operators to work.
171  */
173 
174  /**
175  // Check if this matrix has the same number of rows and columns
176  // as the other one. "false" will be returned in case any one of
177  // the two matrices (or both) is not initialized.
178  */
179  bool isCompatible(const Matrix& other) const;
180 
181  /**
182  // This method changes the object dimensions.
183  // All data is lost in the process.
184  */
185  Matrix& resize(unsigned nrows, unsigned ncols);
186 
187  /** This method sets all elements to 0 */
189 
190  /**
191  // This method sets all diagonal elements to 0.
192  // It can only be used with square matrices.
193  */
195 
196  /**
197  // This method sets all non-diagonal elements to 0.
198  // This operation is only valid for square matrices.
199  // It tags the matrix as diagonal.
200  */
202 
203  /** This method sets all elements to the given value */
204  Matrix& constFill(Numeric c);
205 
206  /**
207  // Method for transposing this matrix. Uses std::swap for square
208  // matrices but might allocate memory from the heap if the matrix
209  // is not square.
210  */
212 
213  //@{
214  /** Compare two matrices for equality */
215  bool operator==(const Matrix&) const;
216  bool operator!=(const Matrix&) const;
217  //@}
218 
219  /**
220  // Non-const access to the data (works like 2-d array in C).
221  // No bounds checking.
222  */
223  Numeric* operator[](unsigned);
224 
225  /**
226  // Const access to the data (works like 2-d array in C).
227  // No bounds checking.
228  */
229  const Numeric* operator[](unsigned) const;
230 
231  /** Data modification method with bounds checking */
232  Matrix& set(unsigned row, unsigned column, Numeric value);
233 
234  /** Access by value without bounds checking */
235  Numeric operator()(unsigned row, unsigned column) const;
236 
237  /** Access by value with bounds checking */
238  Numeric at(unsigned row, unsigned column) const;
239 
240  /** Sum of the values in the given row */
241  Numeric rowSum(unsigned row) const;
242 
243  /** Sum of the values in the given column */
244  Numeric columnSum(unsigned column) const;
245 
246  /** Remove row and/or column. Indices out of range are ignored */
247  Matrix removeRowAndColumn(unsigned row, unsigned column) const;
248 
249  /** Number of non-zero elements */
250  unsigned nonZeros() const;
251 
252  /**
253  // Replace every n x m square block in the matrix by its sum.
254  // The number of rows must be divisible by n. The number of
255  // columns must be divisible by m.
256  */
257  void coarseSum(unsigned n, unsigned m, Matrix* result) const;
258 
259  /**
260  // Replace every n x m square block in the matrix by its average
261  // The number of rows must be divisible by n. The number of
262  // columns must be divisible by m.
263  */
264  void coarseAverage(unsigned n, unsigned m, Matrix* result) const;
265 
266  /** Unary plus */
267  Matrix operator+() const;
268 
269  /** Unary minus */
270  Matrix operator-() const;
271 
272  //@{
273  /** Binary algebraic operation with matrix or scalar */
274  Matrix operator*(const Matrix& r) const;
275  Matrix operator*(Numeric r) const;
276  Matrix operator/(Numeric r) const;
277  Matrix operator+(const Matrix& r) const;
278  Matrix operator-(const Matrix& r) const;
279  //@}
280 
281  /** Hadamard product (a.k.a. Schur product) */
282  Matrix hadamardProduct(const Matrix& r) const;
283 
284  /** Hadamard ratio. All elements of the denominator must be non-zero */
285  Matrix hadamardRatio(const Matrix& denominator) const;
286 
287  //@{
288  /**
289  // Binary algebraic operation which writes its result into
290  // an existing matrix potentially avoiding memory allocation
291  */
292  void times(const Matrix& r, Matrix* result) const;
293  void times(Numeric r, Matrix* result) const;
294  void over(Numeric r, Matrix* result) const;
295  void plus(const Matrix& r, Matrix* result) const;
296  void minus(const Matrix& r, Matrix* result) const;
297  //@}
298 
299  //@{
300  /** In-place algebraic operations with matrices and scalars */
301  Matrix& operator*=(Numeric r);
302  Matrix& operator/=(Numeric r);
303  Matrix& operator+=(const Matrix& r);
304  Matrix& operator-=(const Matrix& r);
305  //@}
306 
307  //@{
308  /** Multiplication by a vector represented by a pointer and array size */
309  template <typename Num2>
310  Matrix timesVector(const Num2* data, unsigned dataLen) const;
311 
312  template <typename Num2, typename Num3>
313  void timesVector(const Num2* data, unsigned dataLen,
314  Num3* result, unsigned resultLen) const;
315  //@}
316 
317  /**
318  // Multiplication by a vector represented by a pointer and array size.
319  // This function is useful when only one element of the result is needed
320  // (or elements are needed one at a time).
321  */
322  template <typename Num2>
323  Numeric timesVector(unsigned rowNumber,
324  const Num2* data, unsigned dataLen) const;
325 
326  //@{
327  /** Multiplication by a row on the left */
328  template <typename Num2>
329  Matrix rowMultiply(const Num2* data, unsigned dataLen) const;
330 
331  template <typename Num2, typename Num3>
332  void rowMultiply(const Num2* data, unsigned dataLen,
333  Num3* result, unsigned resultLen) const;
334  //@}
335 
336  /**
337  // Multiplication by a row on the left. This function is useful when
338  // only one element of the result is needed (or elements are needed
339  // one at a time).
340  */
341  template <typename Num2>
342  Numeric rowMultiply(unsigned columnNumber,
343  const Num2* data, unsigned dataLen) const;
344 
345  /** Bilinear form with a vector (v^T M v) */
346  template <typename Num2>
347  Numeric bilinear(const Num2* data, unsigned dataLen) const;
348 
349  /** Bilinear form with a matrix (r^T M r) */
350  Matrix bilinear(const Matrix& r) const;
351 
352  /** Bilinear form with a transposed matrix (r M r^T) */
353  Matrix bilinearT(const Matrix& r) const;
354 
355  /**
356  // Solution of a linear system of equations M*x = rhs.
357  // The matrix must be square. "false" is returned in case
358  // the matrix is degenerate.
359  */
360  bool solveLinearSystem(const Numeric* rhs, unsigned lenRhs,
361  Numeric* solution) const;
362 
363  /**
364  // Solution of linear systems of equations M*X = RHS.
365  // The matrix M (this one) must be square. "false" is
366  // returned in case this matrix is degenerate.
367  */
368  bool solveLinearSystems(const Matrix& RHS, Matrix* X) const;
369 
370  /**
371  // Solution of an underdetermined linear system of equations M*x = rhs
372  // in the minimum norm sense (M is this matrix). The norm is defined by
373  // sqrt(x^T*V^(-1)*x). The result is given by A*rhs, where A is the
374  // right inverse of M (i.e., M*A = I) minimizing the norm. V plays
375  // the role of the inverse Gram matrix. It must be symmetric and
376  // positive-definite.
377  //
378  // This method can also be used for solving constrained least squares
379  // problems. For example, minimization of (y - y0)^T*V^(-1)*(y - y0)
380  // under the condition M*y = rhs can be reduced to solving an
381  // underdetermined linear system using x = y - y0 and
382  // M*x = rhs' = rhs - M*y0. The application code can call this function
383  // assuming that V is the covariance matrix of y and using rhs' as the
384  // "rhs" argument. Subsequently, y can be calculated as x + y0.
385  // The covariance matrix of y can be subsequently calculated by
386  // V_y = (I - P)*V*(I - P)^T, where P = A*M. Operator (I - P) actually
387  // projects the x (i.e., y - y0) space onto the space of solutions of
388  // the equation M*x = 0.
389  //
390  // "false" is returned in case of failure.
391  */
392  bool underdeterminedLinearSystem(const Numeric* rhs, unsigned lenRhs,
393  const Matrix& V,
394  Numeric* solution, unsigned lenSolution,
395  Numeric* resultNormSquared = 0,
396  Matrix* A = 0) const;
397 
398  /**
399  // Solution of a linear overdetermined system of equations M*x = rhs
400  // in the least squares sense. The "lenRhs" parameter should be equal
401  // to the number of matrix rows, and it should exceed "lenSolution"
402  // ("lenSolution" should be equal to the number of columns). "false"
403  // is returned in case of failure.
404  */
405  bool linearLeastSquares(const Numeric* rhs, unsigned lenRhs,
406  Numeric* solution, unsigned lenSolution) const;
407 
408  /**
409  // Solution of a linear system of equations M*x = rhs1 in the least
410  // squares sense, subject to the constraint B*x = rhs2. Number of
411  // equations (i.e., dimensionality of rhs1) plus the number of
412  // constraints (i.e., dimensionality of rhs2) should exceed the
413  // dimensionality of x. "false" is returned in case of failure. If
414  // the chi-square of the result is desired, make the "resultChiSquare"
415  // argument point to some valid location. Same goes for the result
416  // covariance matrix and all subsequent arguments which can be used
417  // to extract various intermediate results:
418  //
419  // unconstrainedSolution -- Array to store the unconstrained solution.
420  // Must have at least "lenSol" elements.
421  //
422  // unconstrainedCovmat -- Covariance matrix of the unconstrained
423  // solution.
424  //
425  // projectionMatrix -- Projection matrix used to obtain a part
426  // of the constrained solution from the
427  // unconstrained one.
428  //
429  // A -- Matrix multiplied by rhs2 to get the second
430  // part of the constrained solution.
431  //
432  // Note that requesting the result covariance matrix or any other
433  // subsequent output switches the code to a different and slower
434  // "textbook" algorithm instead of an optimized algorithm from Lapack.
435  */
436  bool constrainedLeastSquares(const Numeric* rhs1, unsigned lenRhs1,
437  const Matrix& B,
438  const Numeric* rhs2, unsigned lenRhs2,
439  Numeric* solution, unsigned lenSol,
440  Numeric* resultChiSquare = 0,
441  Matrix* resultCovarianceMatrix = 0,
442  Numeric* unconstrainedSolution = 0,
443  Matrix* unconstrainedCovmat = 0,
444  Matrix* projectionMatrix = 0,
445  Matrix* A = 0) const;
446 
447  /**
448  // Weighted least squares problem. The inverse covariance matrix
449  // must be symmetric and positive definite. If the chi-square of the
450  // result is desired, make the "resultChiSquare" argument point to
451  // some valid location. Same goes for the result covariance matrix.
452  // "false" is returned in case of failure.
453  */
454  bool weightedLeastSquares(const Numeric* rhs, unsigned lenRhs,
455  const Matrix& inverseCovarianceMatrix,
456  Numeric* solution, unsigned lenSolution,
457  Numeric* resultChiSquare = 0,
458  Matrix* resultCovarianceMatrix = 0) const;
459 
460  /** Return transposed matrix */
461  Matrix T() const;
462 
463  /** Return the product of this matrix transposed with this, M^T*M */
465 
466  /** Return the product of this matrix with its transpose, M*M^T */
467  Matrix timesT() const;
468 
469  /** Return the product of this matrix with the transposed argument */
470  Matrix timesT(const Matrix& r) const;
471 
472  /** Return the product of this matrix transposed with the argument */
473  Matrix Ttimes(const Matrix& r) const;
474 
475  /**
476  // "directSum" method constructs a block-diagonal matrix with
477  // this matrix and the argument matrix inside the diagonal blocks.
478  // Block which contains this matrix is the top left one.
479  */
480  Matrix directSum(const Matrix& added) const;
481 
482  /** Construct a symmetric matrix from this one (symmetrize) */
484 
485  /** Construct an antisymmetric matrix from this one (antisymmetrize) */
487 
488  /**
489  // Matrix outer product. The number of rows of the result equals
490  // the product of the numbers of rows of this matrix and the argument
491  // matrix. The number of columns of the result is the product of the
492  // numbers of columns.
493  */
494  Matrix outer(const Matrix& r) const;
495 
496  /** Minimum value for any row/column */
497  Numeric minValue() const;
498 
499  /** Maximum value for any row/column */
500  Numeric maxValue() const;
501 
502  /** Maximum absolute value for any row/column */
503  Numeric maxAbsValue() const;
504 
505  /** Row and column of the smallest matrix element */
506  std::pair<unsigned,unsigned> argmin() const;
507 
508  /** Row and column of the largest matrix element */
509  std::pair<unsigned,unsigned> argmax() const;
510 
511  /**
512  // Row and column of the matrix element with the largest
513  // absolute value
514  */
515  std::pair<unsigned,unsigned> argmaxAbs() const;
516 
517  /** Frobenius norm of this matrix */
518  double frobeniusNorm() const;
519 
520  //@{
521  /** Calculate the trace (matrix must be square) */
522  Numeric tr() const;
523  inline Numeric sp() const {return tr();}
524  //@}
525 
526  //@{
527  /**
528  // Calculate the trace of a product of this matrix with another.
529  // This works faster if only the trace is of interest but not the
530  // product itself.
531  */
532  Numeric productTr(const Matrix& r) const;
533  inline Numeric productSp(const Matrix& r) const {return productTr(r);}
534  //@}
535 
536  /** Calculate the determinant (matrix must be square) */
537  Numeric det() const;
538 
539  /**
540  // Inverse of a real symmetric positive-definite matrix. Use this
541  // function (it has better numerical precision than symInv()) if
542  // you know that your matrix is symmetric and positive definite.
543  // For example, a non-singular covariance matrix calculated for
544  // some dataset has these properties.
545  */
546  Matrix symPDInv() const;
547 
548  /**
549  // Invert real symmetric positive-definite matrix using
550  // eigendecomposition. Use this function if you know that your
551  // matrix is supposed to be symmetric and positive-definite but
552  // might not be due to numerical round-offs. The arguments of
553  // this method are as folows:
554  //
555  // tol -- Eigenvalues whose ratios to the largest eigenvalue
556  // are below this parameter will be either truncated
557  // or extended (per value of the next argument).
558  // This parameter must lie in (0, 1).
559  //
560  // extend -- If "true", the inverse of small eigenvalues will
561  // be replaced by the inverse of the largest eigenvalue
562  // divided by the tolerance parameter. If "false",
563  // inverse of such eigenvalues will be set to 0.
564  //
565  // m -- LAPACK method to use for calculating the
566  // eigendecomposition.
567  */
568  Matrix symPDEigenInv(double tol, bool extend=true,
569  EigenMethod m=EIGEN_SIMPLE) const;
570 
571  /**
572  // Inverse of a real symmetric matrix. If the matrix is not symmetric,
573  // its symmetrized version will be used internally. Use this function
574  // (it has better numerical precision than inv()) if you know that
575  // your matrix is symmetric.
576  */
577  Matrix symInv() const;
578 
579  /** Inverse of a square tridiagonal matrix */
581 
582  /**
583  // Inverse of a general matrix (which must be square and non-singular)
584  */
585  Matrix inv() const;
586 
587  /**
588  // Left pseudoinverse of a real, full rank matrix. This
589  // pseudoinverse can be calculated when the number of columns
590  // does not exceed the number of rows.
591  */
592  Matrix leftInv() const;
593 
594  /**
595  // Right pseudoinverse of a real, full rank matrix. This
596  // pseudoinverse can be calculated when the number of rows
597  // does not exceed the number of columns.
598  */
599  Matrix rightInv() const;
600 
601  /**
602  // Eigenvalues and eigenvectors of a real tridiagonal symmetric
603  // matrix. The "eigenvectors" pointer can be NULL if only eigenvalues
604  // are needed. If it is not NULL, the _rows_ of that matrix will be
605  // set to the computed eigenvectors.
606  //
607  // The "m" parameter specifies the LAPACK method to use for
608  // calculating the eigendecomposition.
609  */
610  void tdSymEigen(Numeric* eigenvalues, unsigned lenEigenvalues,
611  Matrix* eigenvectors=0, EigenMethod m=EIGEN_RRR) const;
612 
613  /**
614  // Eigenvalues and eigenvectors of a real symmetric matrix.
615  // The "eigenvectors" pointer can be NULL if only eigenvalues
616  // are needed. If it is not NULL, the _rows_ of that matrix
617  // will be set to the computed eigenvectors.
618  //
619  // The "m" parameter specifies the LAPACK method to use for
620  // calculating the eigendecomposition.
621  */
622  void symEigen(Numeric* eigenvalues, unsigned lenEigenvalues,
623  Matrix* eigenvectors=0, EigenMethod m=EIGEN_SIMPLE) const;
624 
625  /**
626  // Eigenvalues and eigenvectors of a real general matrix.
627  // Either "rightEigenvectors" or "leftEigenvectors" or both
628  // can be NULL if they are not needed.
629  //
630  // If an eigenvalue is real, the corresponding row of the
631  // output eigenvector matrix is set to the computed eigenvector.
632  // If an eigenvalue is complex, all such eigenvalues come in
633  // complex conjugate pairs. Corresponding eigenvectors make up
634  // such a pair as well. The matrix row which corresponds to the
635  // first eigenvalue in the pair is set to the real part of the pair
636  // and the matrix row which corresponds to the second eigenvalue
637  // in the pair is set to the imaginary part of the pair. For the
638  // right eigenvectors, the first complex eigenvector in the pair
639  // needs to be constructed by adding the imaginary part. The second
640  // eigenvector has the imaginary part subtracted. For the left
641  // eigenvectors the order is reversed: the first eigenvector needs
642  // to be constructed by subtracting the imaginary part, and the
643  // second by adding it.
644  */
645  void genEigen(typename GeneralizedComplex<Numeric>::type *eigenvalues,
646  unsigned lenEigenvalues,
647  Matrix* rightEigenvectors = 0,
648  Matrix* leftEigenvectors = 0) const;
649 
650  /**
651  // Singular value decomposition of a matrix. The length of the
652  // singular values buffer must be at least min(nrows, ncolumns).
653  //
654  // On exit, matrices U and V will contain singular vectors of
655  // the current matrix, row-by-row. The decomposition is then
656  //
657  // *this = U^T * diag(singularValues, nrows, ncolumns) * V
658  */
659  void svd(Numeric* singularValues, unsigned lenSingularValues,
660  Matrix* U, Matrix* V, SvdMethod m = SVD_D_AND_C) const;
661 
662  /**
663  // Calculate entropy-based effective rank. It is assumed that
664  // the matrix is symmetric positive semidefinite.
665  //
666  // The "tol" parameter specifies the eigenvalue cutoff:
667  // all eigenvalues equal to tol*maxEigenvalue or smaller
668  // will be ignored. This parameter must be non-negative.
669  //
670  // The "m" parameter specifies the LAPACK method to use for
671  // calculating eigenvalues.
672  //
673  // If "eigenSum" pointer is not NULL, *eigenSum will be filled
674  // on exit with the sum of eigenvalues above the cutoff divided
675  // by the largest eigenvalue.
676  */
677  double symPSDefEffectiveRank(double tol = 0.0,
678  EigenMethod m = EIGEN_D_AND_C,
679  double* eigenSum = 0) const;
680 
681  /**
682  // Calculate a function of this matrix. It is assumed that the
683  // matrix is symmetric and real. The calculation is performed by
684  // calculating the eignenbasis, evaluating the function of the
685  // eigenvalues, and then transforming back to the original basis.
686  */
687  template <class Functor>
688  Matrix symFcn(const Functor& fcn) const;
689 
690  /** Power of a matrix. Matrix must be square. */
691  Matrix pow(unsigned degree) const;
692 
693  /**
694  // The following function derives a correlation matrix
695  // out of a covariance matrix. In the returned matrix
696  // all diagonal elements will be set to 1.
697  */
699 
700  /**
701  // The following function derives a covariance matrix
702  // out of a correlation matrix and of the covariances.
703  */
704  Matrix corrToCovar(const double* variances, unsigned lenVariances) const;
705 
706  //@{
707  /** Method related to "geners" I/O */
708  inline gs::ClassId classId() const {return gs::ClassId(*this);}
709  bool write(std::ostream& of) const;
710  //@}
711 
712  static const char* classname();
713  static inline unsigned version() {return 1;}
714  static void restore(const gs::ClassId& id, std::istream& in, Matrix* m);
715 
716  private:
717  void initialize(unsigned nrows, unsigned ncols);
718  void calcDiagonal();
719  void makeCoarse(unsigned n, unsigned m, Matrix* result) const;
720  void invertDiagonal(Matrix* result) const;
721 
722  Numeric local_[Len];
723  Numeric* data_;
724  unsigned nrows_;
725  unsigned ncols_;
726  unsigned len_;
727  bool isDiagonal_;
728  bool diagonalityKnown_;
729 
730 #ifdef SWIG
731  public:
732  inline std::vector<Numeric> mainDiagonal() const
733  {
734  if (!nrows_) throw std::runtime_error(
735  "In npstat::Matrix::mainDiagonal: uninitialized matrix");
736  const unsigned len = std::min(nrows_, ncols_);
737  std::vector<Numeric> d(len);
738  for (unsigned i=0; i<len; ++i)
739  d[i] = (*this)[i][i];
740  return d;
741  }
742 
743  inline void setData2(const Numeric* data, unsigned dataLen)
744  {this->setData(data, dataLen);}
745 
746  inline void setRow2(unsigned row, const Numeric* data, unsigned dataLen)
747  {this->setRow(row, data, dataLen);}
748 
749  inline void setColumn2(unsigned col, const Numeric* data, unsigned dataLen)
750  {this->setColumn(col, data, dataLen);}
751 
752  inline Matrix timesVector2(const Numeric* data, unsigned dataLen) const
753  {return timesVector(data, dataLen);}
754 
755  inline Matrix rowMultiply2(const Numeric* data, unsigned dataLen) const
756  {return rowMultiply(data, dataLen);}
757 
758  inline Numeric bilinear2(const Numeric* data, unsigned dataLen) const
759  {return bilinear(data, dataLen);}
760 
761  inline std::vector<Numeric> solveLinearSystem2(
762  const Numeric* data, unsigned dataLen) const
763  {
764  std::vector<Numeric> result(dataLen);
765  if (!solveLinearSystem(data, dataLen, dataLen ? &result[0] : 0))
766  result.clear();
767  return result;
768  }
769 
770  inline std::pair<double,double> symPSDefEffectiveRank2(
771  double tol = 0.0, EigenMethod m = EIGEN_D_AND_C) const
772  {
773  double eigenSum = 0;
774  double erunk = this->symPSDefEffectiveRank(tol, m, &eigenSum);
775  return std::pair<double,double>(erunk, eigenSum);
776  }
777 
778  inline std::vector<Numeric> symEigenValues(EigenMethod m = EIGEN_SIMPLE) const
779  {
780  std::vector<Numeric> result(nrows_);
781  symEigen(&result[0], nrows_, 0, m);
782  return result;
783  }
784 
785  inline Matrix rmul2(Numeric r) const
786  {return *this * r;}
787 
788  inline Matrix subrange2(unsigned rowMin, unsigned rowMax,
789  unsigned columnMin, unsigned columnMax) const
790  {return Matrix(*this, rowMin, rowMax, columnMin, columnMax);}
791 
792  // Perhaps, some day SWIG will be able to wrap the following. Currently,
793  // its type deduction for GeneralizedComplex<Numeric>::type fails.
794  //
795  // inline std::vector<typename GeneralizedComplex<Numeric>::type>
796  // genEigenValues() const
797  // {
798  // std::vector<typename GeneralizedComplex<Numeric>::type> r(nrows_);
799  // genEigen(&r[0], nrows_);
800  // return r;
801  // }
802 #endif // SWIG
803  };
804 
805  /** Utility for making square diagonal matrices from the given array */
806  template<typename Numeric>
807  Matrix<Numeric> diag(const Numeric* data, unsigned dataLen);
808 
809  /**
810  // Utility for making rectangular diagonal matrices from the given array.
811  // The length of the array must be at least min(nrows, ncols).
812  */
813  template<typename Numeric>
814  Matrix<Numeric> diag(const Numeric* data, unsigned nrows, unsigned ncols);
815 }
816 
817 #include <iostream>
818 
819 template<typename N, unsigned Len>
820 std::ostream& operator<<(std::ostream& os, const npstat::Matrix<N, Len>& m);
821 
822 template <typename Numeric, unsigned Len>
824 operator*(const Numeric& l, const npstat::Matrix<Numeric,Len>& r)
825 {
826  return r*l;
827 }
828 
829 #include "npstat/nm/Matrix.icc"
830 
831 #endif // NPSTAT_MATRIX_HH_
Enumeration of LAPACK methods used to calculate eigenvalues and eigenvectors.
Typedef complex type if it makes sense (parameter is real); otherwise typedef the original type.
Enumeration of LAPACK methods used to calculate singular value decompositions.
Definition: Matrix.hh:49
const Numeric * operator[](unsigned) const
Matrix(const Matrix< Num2, Len2 > &)
bool linearLeastSquares(const Numeric *rhs, unsigned lenRhs, Numeric *solution, unsigned lenSolution) const
Matrix directSum(const Matrix &added) const
Numeric bilinear(const Num2 *data, unsigned dataLen) const
void svd(Numeric *singularValues, unsigned lenSingularValues, Matrix *U, Matrix *V, SvdMethod m=SVD_D_AND_C) const
Matrix(unsigned nrows, unsigned ncols, const Numeric *data)
Numeric tr() const
gs::ClassId classId() const
Definition: Matrix.hh:708
Matrix(Matrix &&)
Matrix timesT(const Matrix &r) const
Matrix symFcn(const Functor &fcn) const
Matrix hadamardProduct(const Matrix &r) const
Numeric operator()(unsigned row, unsigned column) const
Matrix & makeDiagonal()
Numeric rowSum(unsigned row) const
Matrix covarToCorr() const
Matrix(unsigned nrows, unsigned ncols, int initCode)
Matrix triDiagInv() const
Matrix TtimesThis() const
void times(const Matrix &r, Matrix *result) const
Matrix removeRowAndColumn(unsigned row, unsigned column) const
Matrix & setFromTriplets(Iterator first, Iterator last)
Numeric columnSum(unsigned column) const
void coarseSum(unsigned n, unsigned m, Matrix *result) const
Matrix outer(const Matrix &r) const
std::pair< unsigned, unsigned > argmaxAbs() const
Numeric maxAbsValue() const
Matrix operator-() const
Matrix & operator=(const Matrix< Num2, Len2 > &)
unsigned nRows() const
Definition: Matrix.hh:155
bool solveLinearSystems(const Matrix &RHS, Matrix *X) const
Numeric timesVector(unsigned rowNumber, const Num2 *data, unsigned dataLen) const
Matrix symmetrize() const
Matrix pow(unsigned degree) const
Matrix symInv() const
Matrix antiSymmetrize() const
double frobeniusNorm() const
Matrix rightInv() const
Matrix timesT() const
Matrix & operator*=(Numeric r)
Matrix operator*(const Matrix &r) const
Numeric at(unsigned row, unsigned column) const
Numeric rowMultiply(unsigned columnNumber, const Num2 *data, unsigned dataLen) const
bool underdeterminedLinearSystem(const Numeric *rhs, unsigned lenRhs, const Matrix &V, Numeric *solution, unsigned lenSolution, Numeric *resultNormSquared=0, Matrix *A=0) const
Matrix & constFill(Numeric c)
Matrix & clearMainDiagonal()
Numeric maxValue() const
Matrix & resize(unsigned nrows, unsigned ncols)
double symPSDefEffectiveRank(double tol=0.0, EigenMethod m=EIGEN_D_AND_C, double *eigenSum=0) const
Matrix & setRow(unsigned row, const Num2 *data, unsigned dataLength)
Matrix & zeroOut()
bool weightedLeastSquares(const Numeric *rhs, unsigned lenRhs, const Matrix &inverseCovarianceMatrix, Numeric *solution, unsigned lenSolution, Numeric *resultChiSquare=0, Matrix *resultCovarianceMatrix=0) const
Matrix T() const
void genEigen(typename GeneralizedComplex< Numeric >::type *eigenvalues, unsigned lenEigenvalues, Matrix *rightEigenvectors=0, Matrix *leftEigenvectors=0) const
Matrix hadamardRatio(const Matrix &denominator) const
void tdSymEigen(Numeric *eigenvalues, unsigned lenEigenvalues, Matrix *eigenvectors=0, EigenMethod m=EIGEN_RRR) const
void symEigen(Numeric *eigenvalues, unsigned lenEigenvalues, Matrix *eigenvectors=0, EigenMethod m=EIGEN_SIMPLE) const
Matrix & uninitialize()
Matrix operator+() const
Matrix & diagFill(const Num2 *data, unsigned dataLen)
Matrix inv() const
Matrix & tagAsDiagonal(bool b=true)
unsigned nonZeros() const
Matrix & setData(const Num2 *data, unsigned dataLength)
Matrix & operator=(Matrix &&)
Matrix timesVector(const Num2 *data, unsigned dataLen) const
Matrix symPDInv() const
std::pair< unsigned, unsigned > argmin() const
Numeric * operator[](unsigned)
Matrix corrToCovar(const double *variances, unsigned lenVariances) const
bool constrainedLeastSquares(const Numeric *rhs1, unsigned lenRhs1, const Matrix &B, const Numeric *rhs2, unsigned lenRhs2, Numeric *solution, unsigned lenSol, Numeric *resultChiSquare=0, Matrix *resultCovarianceMatrix=0, Numeric *unconstrainedSolution=0, Matrix *unconstrainedCovmat=0, Matrix *projectionMatrix=0, Matrix *A=0) const
Matrix(unsigned nrows, unsigned ncols)
Matrix & operator=(const Matrix &)
void coarseAverage(unsigned n, unsigned m, Matrix *result) const
Matrix rowMultiply(const Num2 *data, unsigned dataLen) const
Matrix leftInv() const
bool solveLinearSystem(const Numeric *rhs, unsigned lenRhs, Numeric *solution) const
bool operator==(const Matrix &) const
Matrix & set(unsigned row, unsigned column, Numeric value)
Matrix(const Matrix &)
Numeric minValue() const
Matrix bilinear(const Matrix &r) const
Matrix & setColumn(unsigned col, const Num2 *data, unsigned dataLength)
std::pair< unsigned, unsigned > argmax() const
Matrix & Tthis()
Numeric det() const
Matrix(const Matrix< Num2, Len2 > &, unsigned rowMin, unsigned rowMax, unsigned columnMin, unsigned columnMax)
Matrix Ttimes(const Matrix &r) const
Numeric productTr(const Matrix &r) const
Matrix bilinearT(const Matrix &r) const
bool isCompatible(const Matrix &other) const
Matrix symPDEigenInv(double tol, bool extend=true, EigenMethod m=EIGEN_SIMPLE) const
Definition: AbsArrayProjector.hh:14
SvdMethod
Definition: SvdMethod.hh:24
EigenMethod
Definition: EigenMethod.hh:27
Matrix< Numeric > diag(const Numeric *data, unsigned dataLen)