Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Matrix.hh
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5 Multimediale Systeme der Informationsverarbeitung
6 Institut fuer Informatik
7 Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 #ifndef _Matrix_hh_
27 #define _Matrix_hh_
28 
29 #include "bias_config.h"
30 
31 #define _USE_MATH_DEFINES
32 #include <math.h>
33 
34 #include <Base/Debug/Error.hh>
35 
36 #include <Base/Math/tnt/tnt.h>
37 #include <Base/Math/tnt/cmat.h>
38 #include <Base/Math/tnt/fmat.h>
39 #include <iostream>
40 #include <string>
41 
42 #ifdef BUILD_ALLOW_NON_INTEGRAL_MATRIX_ELEMENTS
43 #include "Base/Math/Polynom.hh"
44 #endif
45 
46 namespace BIAS {
47 
48 #ifndef DOUBLE_EPSILON
49 # define DOUBLE_EPSILON 1E-12
50 #endif
51 
52  template <class T> class Vector;
53  template <class T> class Vector3;
54  template <class T> class Matrix3x3;
55 
56  /** @enum MatrixInitType
57  @brief can be passed to matrix constructors to init the matrix with
58  the most often used values */
60 
61  /** @class Matrix
62  @ingroup g_math
63  @brief matrix class with arbitrary size, indexing is row major. <br>
64  Access the data by M[row][col].
65 
66  class Matrix is the matrix class that should be used by common BIAS
67  algorithms and data structures with arbitrary size <br>
68 
69  Access the data simply by M[row][col]. <br>
70 
71  It is derived from TNT::Matrix to inherit the basic operations and
72  algorithm.
73  special implementations should be done here and NOT in TNT:Matrix
74  because the true 'base' Matrix class "TNT::Matrix"
75  should be interchangeable and aside from this maintained by NIST.
76 
77  Note the specialized fixed size classes Matrix3x3, Matrix3x4, ...
78  with more efficient memory layout.
79 
80  moved from MIP to BIAS (11/05/2002)
81  operators are no longer class members, they are defined outside the
82  class.
83 
84  @author Jan Woetzel, woelk
85  */
86  template <class T=double>
87  class BIASMathBase_EXPORT Matrix : public TNT::Matrix<T>
88  {
89  public:
90  virtual ~Matrix();
91 
92  Matrix() : TNT::Matrix<T>() {};
93 
94  explicit Matrix(const Matrix3x3<T>& mat);
95 
96  /** @author Jan Woetzel
97  **/
98  Matrix(int rows, int cols) :TNT::Matrix<T>(rows, cols) {};
99 
100  /** assignment with a constant values for all elements (=set)
101  @author Jan Woetzel **/
102  Matrix(int rows, int cols, const T value)
103  : TNT::Matrix<T>(rows, cols, value) {};
104 
105  /** init with standard form
106  @author koeser **/
107  Matrix(int rows, int cols, const MatrixInitType& i)
108  : TNT::Matrix<T>(rows, cols, T(0)) {
109  switch (i) {
110  case MatrixZero:return;
111  case MatrixIdentity:{
112  for (int r=0; r<rows; r++) {
113  if (r==cols) return;
114  (*this)[r][r] = T(1);
115  }
116  return;
117  }
118  default: BIASERR("undefined MatrixInitType");
119  BIASABORT;
120  }
121  };
122 
123 
124  /** DEPRECATED due to instantiation problem @author Jan Woetzel **/
125  //Matrix(int rows, int cols, const char *s) : TNT::Matrix<T>(rows, cols, s){};
126 
127  /// replacement for the above to be called as Matrix<>(2,3, "1 2 3 4 5 6") @author Jan Woetzel
128  explicit Matrix(const int rows, const int cols, const std::string & s);
129 
130  /** @author Jan Woetzel **/
131  Matrix(const Matrix<T> &A) : TNT::Matrix<T>(A) {};
132 
133  /** @author Jan Woetzel **/
134  Matrix(const TNT::Matrix<T> &A) : TNT::Matrix<T>(A) {};
135 
136  /** @brief constructs Nx1 Matrix from N-Vector */
137  Matrix(const Vector<T> &v) : TNT::Matrix<T>(v.size(), 1) {
138  for (int i=0; i<v.size(); i++)
139  (*this)[i][0] = v[i];
140  }
141 
142  /** transpose function, storing data destination matrix
143  @author JMF **/
144  inline Matrix<T> Transpose() const;
145 
146  /** returns an matrix the same size as the matrix n and m with the
147  * largest elements taken from n or m
148  * @author bangerer 01/2009
149  */
150  Matrix<T> GetMax(Matrix<T>& m);
151 
152  /** returns an matrix the same size as the matrix n and m with the
153  * smallest elements taken from n or m
154  * @author bangerer 01/2009
155  */
156  Matrix<T> GetMin(Matrix<T>& m);
157 
158  /** absolute values of all elements of the matrix (in place)
159  * @author bangerer 01/2009
160  */
161  void AbsIP();
162 
163  /** @brief computes the adjoint matrix
164  @author Christian Beder */
165  inline Matrix<T> Adjoint() const;
166 
167  /////////////////////// Get Functions ////////////////////////////////
168  /** @name Get Functions
169  @{
170  */
171  /** get the pointer to the data array of the matrix
172  (for faster direct memeory access)
173 
174  the order of the data is linewise, which means an elemnt
175  sequence of e.g.
176  [0] = M(0,0)
177  [1] = M(0,1)
178  [2] = M(0,2)
179  [3] = M(1,0) // next line
180  [4] = M(1,1) ...
181  @author Jan Woetzel
182  @return a pointer to the data array (beginning with GetData[0])
183  @status alpha (02/27/2002)
184  -added const (jw) 03/12/2002 **/
185  inline T *GetData()
186  { return this->v_; };
187 
188  inline const T *GetData() const
189  { return this->v_; };
190 
191  /** returns zero based arry for data access */
192  inline const T **GetDataArray() const
193  { return (const T **)this->row_; }
194 
195  inline T **GetDataArray()
196  { return this->row_; }
197 
198  /** returns 1 based array to data access */
199  inline T **GetDataArray1() const
200  { return this->rowm1_; };
201 
202  inline unsigned int GetRows() const { return this->m_; }
203 
204  inline unsigned int GetCols() const { return this->n_; }
205 
206  /** Get a pointer to the last data element
207  Do not use this on unitilized matrices with <= on pointers
208  because on an unitilized matrix
209  GetData() will be NULL and last Element < (typically FFFFF8)
210  We don't want an if here for performance reasons of the innerst loop.
211  @author Ingo Thomsen, Jan Woetzel
212  @date 04/11/2002 **/
213  inline const T* GetDataLast() const
214  {
215  BIASASSERT( GetNumElements()>0 ); // check NULL matrix outside
216  return GetData() + GetNumElements() - 1;
217  };
218 
219  inline T* GetDataLast()
220  {
221  BIASASSERT( GetNumElements()>0 ); // check NULL matrix outside
222  return GetData() + GetNumElements() - 1;
223  };
224 
225  /** @brief return a copy of row "row" of this matrix, zero based counting
226  @author Jan Woetzel **/
227  Vector<T> GetRow(const int& row) const;
228 
229  /** @brief return a copy of column "col", zero based counting
230  @author Jan Woetzel **/
231  Vector<T> GetCol(const int& col) const;
232 
233  /** @brief return a submatrix from this. Start index is [startRow][startCol]
234  end index is [startRow+numRows-1][startCol+numCols-1].
235  submatrix is resized to numRows/numCols if necessary.
236  @author apetersen 12/2010
237  */
238  void GetSubMatrix(const size_t startRow, const size_t startCol,
239  const size_t numRows, const size_t numCols,
240  Matrix<T> &submatrix) const;
241 
242  /** @brief return a submatrix from this. Similar to matlab notation (except
243  indexing, starts with 0 of course!). Vectors rows = '1 3' and
244  cols = '1 2' for matrix:
245  / 1 2 3 \
246  | 4 5 6 |
247  \ 7 8 9 /
248  results in:
249  / 1 2 \
250  \ 7 8 /
251  Matrix has to be initialized!!!
252  @author apetersen 7/2011
253  */
254  void GetSubMatrix(const Vector<int> &rows, const Vector<int> &cols,
255  Matrix<T> &submatrix) const;
256 
257  /** @brief return a submatrix from this. Similar to matlab notation (except
258  indexing, starts with 0 of course!), see
259  GetSubMatrix(const Vector<int> &rows, const Vector<int> &cols,
260  Matrix<T> &submatrix)
261  @author apetersen 7/2011
262  */
263  Matrix<T> GetSubMatrix(const Vector<int> &rows,
264  const Vector<int> &cols) const;
265 
266  /** @brief sets a submatrix in this. Start index in this is [startRowInThis][startColInThis]
267  end index is [startRowInThis+numRows-1][startColInThis+numCols-1]. Entries copyed
268  from submatrix beginning at [startRowInSub][startColInSub] and stop at
269  [startRowInSub+numRows-1][startColInSub+numCols-1]
270  @author apetersen 12/2010
271  */
272  void SetSubMatrix(const size_t startRowInThis, const size_t startColInThis,
273  const Matrix<T> &submatrix,
274  const size_t startRowInSub, const size_t startColInSub,
275  const size_t numRows, const size_t numCols);
276 
277  /** @brief sets a 3x3 submatrix in this. Start index in this is [startRowInThis][startColInThis]
278  end index is [startRowInThis+2][startColInThis+2].
279  @author apetersen 12/2010
280  */
281  void SetSubMatrix(const size_t startRowInThis, const size_t startColInThis,
282  const Matrix3x3<T> &submatrix);
283 
284  /** @brief sets a 3x1 submatrix in this. Start index in this is [startRowInThis][startColInThis]
285  end index is [startRowInThis+2][startColInThis].
286  @author apetersen 12/2010
287  */
288  void SetSubMatrix(const size_t startRowInThis, const size_t startColInThis,
289  const Vector3<T> &subvector);
290 
291  /** @brief set a row of matrix from vector
292  @author woelk 08/2004 */
293  void SetRow(const int row, const Vector<T>& data);
294 
295  /** @brief set a col of matrix from vector
296  @author woelk 08/2004 */
297  void SetCol(const int row, const Vector<T>& data);
298 
299  /** Copies the contents of data into this at the position indicated by
300  row and col. The size of *this must be big enought to carry data
301  @author woelk 05/2008 (c) www.vision-n.de */
302  void Set(const int row, const int col, const Matrix<T> &data);
303 
304  /** Copies the contents of data into this at the position indicated by
305  row and col. The size of *this must be big enought to carry data.
306  Data i interpreted as column vector
307  @author woelk 05/2008 (c) www.vision-n.de */
308  void Set(const int row, const int col, const Vector<T> &data);
309 
310  /** Copies the contents of data into this at the position indicated by
311  row and col. The size of *this must be big enought to carry data.
312  Data is interpreted as row vector.
313  @author woelk 05/2008 (c) www.vision-n.de */
314  void SetTranspose(const int row, const int col, const Vector<T> &data);
315 
316 
317  /** Returns the total number of elements
318  @author Ingo Thomsen
319  @date 04/11/2002
320  @status tested **/
321  inline int GetNumElements() const
322  { return this->num_cols() * this->num_rows(); };
323 
324  /** Returns the minimum value of the matrix elements
325  @author Ingo Thomsen
326  @date 04/11/2002
327  @status tested **/
328  T GetMin() const;
329 
330  /** Returns the maximum value of the matrix elements
331  @author Ingo Thomsen
332  @date 04/11/2002
333  @status tested **/
334  T GetMax() const;
335 
336  /// return biggest and smallest entry
337  void GetMaxMin(T& max, T& min) const;
338 
339  /// return biggest and smallest absolute values
340  void GetAbsMaxMin(T& max, T& min) const;
341 
342 
343  /** Returns the mean value of the matrix elements
344  @author Ingo Thomsen
345  @date 04/11/2002
346  @status tested **/
347  T GetMean() const;
348 
349  /** Return the L1 norm: |a| + |b| + |c| + ...
350  @author Ingo Thomsen
351  @date 04/11/2002
352  @status untested **/
353  inline T NormL1() const;
354 
355  /** Return the L2 norm: a^2 + b^2 + c^2 + ...
356  @author woelk 07/2004 */
357  inline double NormL2() const;
358 
359  /** @brief Return Frobenius norm = sqrt(trace(A^t * A)). This function is deprecated, because it is equivalent to NormL2.
360  @author koeser 02/2004 */
361  inline double NormFrobenius() const;
362 
363  /** @author koeser */
364  inline T Trace() const;
365 
366  /** @author koeser
367  @warning very slow, generic implementation (order "n!"), better to use
368  matrix decomposition (see BIAS/MathAlgo/Lapack.hh) */
369  inline T DetSquare() const {
370  BIASASSERT((*this).num_cols()==(*this).num_rows());
371  const unsigned int dim = (*this).num_rows();
372  const unsigned int subdim = dim-1;
373  // end of recursion in 1x1:
374  if (subdim==0)
375  return ((*this)[0][0]);
376  // end of recursion in 2x2:
377  else if (subdim==1) return ((*this)[0][0]*(*this)[1][1]-
378  (*this)[1][0]*(*this)[0][1]);
379  T d = 0;
380  Matrix<T> SubMatrix(subdim, subdim);
381  for (register unsigned int sub=0; sub<dim; sub++) {
382  // first column is used,
383  // set up the n-1xn-1 submatrices from the right matrix part
384  // this is done n times (loop counter="sub")
385  for (register unsigned int i=0; i<subdim; i++) {
386  // construct the sub matrix under inspection,
387  // skip the first column
388  for (register unsigned int j=0; j<subdim; j++) {
389  SubMatrix[j][i] = (*this)[(sub+j+1)%dim][i+1];
390  }
391  }
392  // add value of subdeterminant to overall sum
393  d += SubMatrix.DetSquare() * (*this)[sub][0];
394  }
395  return d;
396  }
397 
398 
399  //@}
400 
401  //////////////////////////// Arithmetic ////////////////////
402  /** @name Arithmetic
403  @{
404  */
405  /** \brief assignment operators
406  calling corresponding operator from base class if appropriate
407  @author Jan Woetzel
408  @status alpha (02/25/2002) */
409  inline Matrix<T>& operator=(const TNT::Matrix<T> &mat);
410  inline Matrix<T>& operator=(const Matrix<T> &mat);
411 
412  /** in place addition function
413  @author Ingo Thomsen
414  @status tested **/
415  inline void AddIP(const T& scalar)
416  { Add(scalar, *this); };
417 
418  /** Adds arg to this
419  @author grest,2004
420  */
421  inline void AddIP(const Matrix<T> &arg);
422 
423  /** Subtracts arg from this <br>
424  this -= arg
425  @author grest, 2004
426  */
427  inline void SubIP(const Matrix<T> &arg);
428 
429  /** addition function, storing data destination matrix
430  @author Ingo Thomsen
431  @status tested **/
432  inline void Add(const T& scalar, Matrix<T> &dest) const;
433 
434  /** in place subtraction function
435  @author Ingo Thomsen
436  @status tested **/
437  inline void SubIP(const T& scalar)
438  { Sub(scalar, *this); };
439 
440  /** substraction function, storing data destination matrix
441  @author Ingo Thomsen
442  @status tested **/
443  inline void Sub(const T& scalar, Matrix<T> &dest) const;
444 
445  /** in place multiplication function
446  @author Ingo Thomsen
447  @status tested **/
448  inline void MultiplyIP(const T& scalar)
449  { Multiply(scalar, *this); };
450 
451  /** multiplication function, storing data destination matrix
452  @author Ingo Thomsen
453  @status tested **/
454  inline void Multiply(const T& scalar, Matrix<T> &dest) const;
455 
456  /** matrix multiplication, result is not allocated
457  @author Felix Woelk */
458  inline void Mult(const Matrix<T>& arg, Matrix<T>& result) const;
459 
460  /** in Place matrix multiplication
461  this is equal to M = M * arg, but faster
462  @author Daniel Grest */
463  inline void Mult(const Matrix<T>& arg);
464 
465  /** in Place matrix multiplication
466  this is equal to M = arg*M, but faster
467  @author Daniel Grest */
468  inline void MultLeft(const Matrix<T>& arg);
469 
470  /** matrix vector multiplication, result is not allocated
471  @author Felix Woelk */
472  inline void Mult(const Vector<T>& arg, Vector<T>& result) const;
473 
474  /** vector matrix multiplication result=arg*this.
475  @author Marcel Lilienthal */
476  inline void MultLeft(const Vector<T>& arg, Vector<T>& result) const;
477 
478  /** matrix matrix multiplication for multiplication with the transpose of
479  the given matrix, result=this*arg^T.
480  @author Arne Petersen */
481  inline void MultiplyWithTransposeOf(const Matrix<T>& arg, Matrix<T>& result) const;
482 
483  /** in place division function
484  @author Ingo Thomsen
485  @status tested **/
486  inline void DivideIP(const T& scalar)
487  { Divide(scalar, *this); };
488 
489  /** division function, storing data destination matrix
490  @author Ingo Thomsen
491  @status tested **/
492  inline void Divide(const T& scalar, Matrix<T> &dest) const;
493 
494  /** elementwise division function in place
495  @author Ingo Schiller
496  @status tested **/
497  inline void DivideElementwise(const Matrix<T> &arg);
498 
499  /** @brief compute square system matrix dest = A^T * A
500  @param dest holds result of this->Transpose * this
501 
502  If you want to solve A * x = b, where A has more rows than columns,
503  a common technique is to solve x = (A^T * A)^-1 * A^T * b.
504  This function provides a fast way to compute A^T*A from A.
505  @author grest/koeser */
506  inline void GetSystemMatrix(Matrix<T> &dest) const;
507 
508  //@}
509  /////////////// Set Functions //////////////////////////////////////////
510  /** @name Set Functions
511  @{
512  */
513  /** Sets all values to zero
514  @author Ingo Thomsen, JW
515  @date 04/11/2002
516  @status tested **/
517  inline void SetZero();
518 
519  /** @brief componentwise: this = 0.5(this + this^T) yields symmetric matrix
520  only allowed for square shaped matrices
521  @author koeser 01/2007 */
522  inline void MakeSymmetric(){
523  BIASASSERT(GetCols()==GetRows());
524  const int num = GetCols();
525  for (int r=0; r<num; r++){
526  for (int c=r; c<num; c++){
527  (*this)[c][r] = (*this)[r][c] =
528  T(((*this)[c][r] + (*this)[r][c]) / 2.0);
529  }
530  }
531  }
532 
533  /// stl conform interface destroys Matrix JW
534  virtual inline void clear() {
535  this->destroy();
536  };
537 
538  /** @brief Converts matrix to identity matrix
539 
540  Even if the matrix is not quadratic, the diagonal values
541  starting with the upper left element are set to 1. Example:
542 
543  1 0 0 1 0 0 0
544  0 1 0 or 0 1 0 0
545  0 0 1 0 0 1 0
546  0 0 0
547 
548  @author Ingo Thomsen
549  **/
550  void SetIdentity();
551 
552  /** Takes the elements of a Vector and put them as diagonal elements into
553  a matrix. The size of this Vector must be exactly
554  min( matrix.width, matrix.height). Optionally all other elements may
555  be set to zero
556  @author Ingo Thomsen
557  @param zero_others Must be true, if all non-diagonal elements shall be
558  set to zero **/
559  //void set_diagonal_elements(const Vector<T>& argV, const bool zero_others);
560 
561  void Fill(const T& scalar);
562 
563  // @}
564 
565  //////////////////// Scaling and Normalization //////////////////////////
566  /** @name Scaling and Normalization
567  @{
568  */
569  /** divides each column of the matrix through the element norm_row_index.
570  index runs [0..num_rows-1]
571  for example:
572  2 3
573  4 5
574  normalized with row '1' will be
575  2/4 3/5
576  1 1 **/
577  void NormalizeColsToOne(const int norm_row_index);
578 
579  /** divides each row of the matrix through the element norm_col_index.
580  index runs [0..num_cols-1]
581  for example:
582  2 3
583  4 5
584  normalized with row '1' will be
585  2/3 1
586  4/5 1 **/
587  void NormalizeRowsToOne(const int norm_col_index);
588 
589  /** Normalizes each row to L2 norm one. Attention each row is normaized
590  by its own scale! */
591  void NormalizeRows();
592 
593  /** Normalizes each coloumn to L_2 norm one. Attention each column is
594  normaized by its own scale! */
595  void NormalizeCols();
596 
597  /** Normalizes the matrix by the entry with the biggest absolute value
598  by dividing all elements with this one
599  @return value of the element the matrix is normalized with
600  @author mdunda 09 2003 */
601  T Normalize();
602 
603  /** Scales row NoRow with scale. */
604  void ScaleRow(int NoRow,T scale);
605 
606  /** Scales column NoCol with scale. */
607  void ScaleCol(int NoCol,T scale);
608  // @}
609 
610  /////////////////// Input / Output ////////////////////////////////////
611  /** @name Input / Output
612  @{
613  */
614  /** method to load directly from a given filename.
615  internally using stream operator
616  @author Jan Woetzel 05/2003
617  @return false in case of error, true in case of success
618  */
619  bool Load(const std::string & filename);
620 
621  /** method to save directly to a given filename.
622  internally using stream operator
623  @author Jan Woetzel 05/2003
624  @return false in case of error, true in case of success
625  */
626  bool Save(const std::string & filename) const;
627 
628  /** Write the matrix in Matlab format to the given stream
629  @param name Is the name of the Matlab variable
630  @author streckel 08/2006
631  @return negativev if error
632  */
633  int WriteMatlab(std::ostream& ostr, const std::string& name) const;
634 
635  /** This method reads a matrix from a given file in binary format.
636  The file is not human read-/editable but provides full precision.
637  A dimension check is performed.
638  @return true on success
639  @author mdunda 04 2004 */
640  bool BinRead(const char * filename) const;
641 
642  /** This method writes a matrix to a given file in binary format.
643  The file is not human read-/editable but provides full precision.
644  @return true on success
645  @author mdunda 04 2004 */
646  bool BinWrite(const char * filename) const;
647 
648  // @}
649 
650  /** Checks if the matrix is a null matrix.
651  @author mdunda 12 2003
652  @return true if all elements are zero */
653  bool IsZero( double eps=0.0 ) const;
654 
655  /** Checks if the matrix a an identity. I.e. all elements with index
656  i==j are equal 1 and all others are zero.
657  @author mdunda 12 2003
658  @return true if matrix is identity */
659  bool IsIdentity( double eps=0.0 ) const;
660 
661  /** vec-operator returns the elements of the matrix columwise as vector */
662  void Vec(Vector<T> &dest) const;
663 
664  /** Kronecker-product with matrix, result in dest */
665  void Kronecker(Matrix<T> const B, Matrix<T> &dest) const;
666 
667  /** @brief swaps two rows
668  @author woelk 05/2008 www.vision-n.de */
669  void SwapRows(const int i, const int r);
670 
671  /** @brief use the Gauss Jordan Algrithm to transform the matrix to
672  reduced row echelon form.
673  @author woelk 05/2008 www.vision-n.de */
674  void GaussJordan();
675 
676 
677 
678  }; // class
679 
680 
681  //////////////////////////////////////////////////////////////////
682  /// operators
683  ///////////////////////////////////////////////////////////////////
684 
685 
686 
687  /** @relates Matrix
688  addition operator
689  @author Ingo Thomsen **/
690  template<class T>
691  inline Matrix<T>& operator+=(Matrix<T>& mat, const T& scalar)
692  { mat.AddIP(scalar); return mat; }
693 
694  /** @relates Matrix
695  addition in place operator
696  @author grest **/
697  template<class T>
698  inline Matrix<T>& operator+=(Matrix<T>& mat, const Matrix<T>& arg)
699  { mat.AddIP(arg); return mat; }
700 
701  /** @relates Matrix
702  subtracts arg from mat, mat = mat - arg
703  @author grest **/
704  template<class T>
705  inline Matrix<T>& operator-=(Matrix<T>& mat, const Matrix<T>& arg)
706  { mat.SubIP(arg); return mat; }
707 
708  /** @relates Matrix
709  substraction operator
710  @author Ingo Thomsen */
711  template<class T>
712  inline Matrix<T>& operator-=(Matrix<T>& mat, const T& scalar)
713  { mat.AddIP(scalar); return mat; }
714 
715  /** @relates Matrix
716  multiplication operator
717  @author Ingo Thomsen */
718  template<class T>
719  inline Matrix<T>& operator*=(Matrix<T>& mat, const T& scalar)
720  { mat.MultiplyIP(scalar); return mat; }
721 
722 
723 
724 
725  /** @relates Matrix
726  operator for equal
727  @author Ingo Thomsen (07/02/2002)
728  @status tested */
729  template<class T>
730  inline bool operator==(const Matrix<T>& argl, const Matrix<T>& argr)
731  {
732  BIASASSERT( argl.size() == argr.size() );
733  register const T* argP = argl.GetData();
734  register const T* matP = argr.GetData();
735  for (; matP < argr.GetDataLast() ; matP++, argP++)
736  if (*matP != *argP)
737  return false;
738  return true;
739  }
740 
741  /** @relates Matrix
742  operator for not equal
743  @author Ingo Thomsen (07/02/2002) **/
744  template<class T>
745  inline bool operator!=(const Matrix<T>& argl, const Matrix<T>& argr)
746  { return !(argl==argr); }
747 
748  ////////////////////////////////////////////////////////////////////
749  /// implementation
750  ///////////////////////////////////////////////////////////////////
751 
752  template<class T>
753  inline void Matrix<T>::Add(const T& scalar, Matrix<T> &dest) const
754  {
755  if (this->num_rows() != dest.num_rows() ||
756  this->num_cols() != dest.num_cols())
757  dest.newsize(this->num_rows(), this->num_cols());
758  register T* destP = dest.GetData();
759  register const T* matP = GetData();
760  for(;matP <= GetDataLast(); matP++, destP++) {
761  *destP = *matP + scalar;
762  }
763  }
764 
765  template<class T>
766  inline void Matrix<T>::Sub(const T& scalar, Matrix<T> &dest) const
767  {
768  if (this->num_rows() != dest.num_rows() ||
769  this->num_cols() != dest.num_cols())
770  dest.newsize(this->num_rows(), this->num_cols());
771  register T* destP = dest.GetData();
772  register const T* matP = GetData();
773  for(;matP <= GetDataLast(); matP++, destP++) {
774  *destP = *matP - scalar;
775  }
776  }
777 
778  template<class T>
779  inline void Matrix<T>::Multiply(const T& scalar, Matrix<T> &dest) const
780  {
781  if (this->num_rows() != dest.num_rows() || this->num_cols() != dest.num_cols())
782  dest.newsize(this->num_rows(), this->num_cols());
783  register T* destP = dest.GetData();
784  register const T* matP = GetData();
785  for(;matP <= GetDataLast(); matP++, destP++) {
786  *destP = *matP * scalar;
787  }
788  }
789 
790  template<class T>
791  inline void Matrix<T>::Divide(const T& scalar, Matrix<T> &dest) const
792  {
793  if (this->num_rows() != dest.num_rows() || this->num_cols() != dest.num_cols())
794  dest.newsize(this->num_rows(), this->num_cols());
795  if (scalar == 0) {
796  BIASERR("Division by Zero");
797  //BIASASSERT(false);
798  BIASABORT;
799  } else {
800  register T* destP = dest.GetData();
801  register const T* matP = GetData();
802  for(;matP <= GetDataLast(); matP++, destP++) {
803  *destP = *matP / scalar;
804  }
805  }
806  }
807 
808  template<class T>
809  inline void Matrix<T>::DivideElementwise(const Matrix<T> &arg)
810  {
811  if (this->num_rows() != arg.num_rows() || this->num_cols() != arg.num_cols()){
812  BIASERR("Unequal matrix dimensions");
813  return;
814  }
815  register const T* argP = arg.GetData();
816  register T* matP = GetData();
817  for(;matP <= GetDataLast(); matP++, argP++) {
818  *matP = *matP / *argP;
819  }
820  }
821 
822  template<class T>
824  {
825  Matrix<T> Out(this->num_cols(),this->num_rows());
826  for (int i=0; i<this->num_rows(); i++)
827  for (int j=0; j<this->num_cols(); j++)
828  Out[j][i]= (*this)[i][j];
829  return Out;
830  }
831 
832  template<class T>
834  {
835  unsigned int num_rows = this->num_rows();
836  unsigned int num_cols = this->num_cols();
837  BIASASSERT (num_rows==num_cols);
838  Matrix<T> Out(num_cols,num_rows);
839  Matrix<T> SubMatrix(num_rows-1,num_cols-1);
840  for (unsigned int i=0; i<num_rows; i++) {
841  for (unsigned int j=0; j<num_cols; j++) {
842  for (unsigned int k=0; k<num_rows-1; k++) {
843  unsigned int kk = k<i?k:k+1;
844  for (unsigned int r=0; r<num_rows-1; r++) {
845  unsigned int rr = r<j?r:r+1;
846  SubMatrix[k][r] = (*this)[kk][rr];
847  }
848  }
849  Out[j][i]= (((i+j)%2==0)?1:-1) * SubMatrix.DetSquare();
850  }
851  }
852  return Out;
853  }
854 
855  template<class T>
856  inline void Matrix<T>::SetZero()
857  {
858 #ifdef BUILD_ALLOW_NON_INTEGRAL_MATRIX_ELEMENTS
859  for(register T* dataP = GetData(); dataP <= GetDataLast(); dataP++)
860  *dataP = (T)(0);
861 #else
862  memset(GetData(), 0, GetNumElements()*sizeof(T)); // JW
863 #endif
864  }
865 
866  template<class T>
867  inline T Matrix<T>::NormL1() const
868  {
869  T result = 0;
870  for(register const T* dataP = GetDataLast(); dataP >= GetData(); dataP--) {
871  result += *dataP > 0 ? *dataP : *dataP * -1;
872  }
873  return result;
874  }
875 
876 
877  template<class T>
878  inline double Matrix<T>::NormL2() const
879  {
880  double result = 0;
881  for (register const T* dataP = GetDataLast(); dataP >= GetData(); dataP--){
882  result += (double)((*dataP) * (*dataP));
883  }
884  return sqrt(result);
885  }
886 #ifdef BUILD_ALLOW_NON_INTEGRAL_MATRIX_ELEMENTS
887  template<>
888  inline double Matrix<BIAS::Polynom>::NormL2() const {
889  BIASERR("NormL2 is only pollsible for integral types");
890  BIASABORT;
891  return 0;
892  }
893 #endif
894 
895 /** this method is deprecated because it is equivalent to NormL2 */
896  template<class T>
897  inline double Matrix<T>::NormFrobenius() const
898  {
899  return NormL2();
900  }
901 
902  template<class T>
903  inline T Matrix<T>::Trace() const
904  {
905  BIASASSERT(this->num_cols() == this->num_rows())
906  T result = 0;
907  for (int x=0; x<this->num_rows(); x++)
908  result = result + (*this)[x][x];
909  return result;
910  }
911 
912  template<class T>
913  inline void Matrix<T>::Mult(const Matrix<T>& arg, Matrix<T>& result) const
914  {
915  if (result.num_cols() != arg.num_cols() ||
916  result.num_rows() != this->num_rows()){
917  result.newsize(this->num_rows(), arg.num_cols());
918  }
919 #ifdef BIAS_DEBUG
920  if (this->num_cols() != arg.num_rows() ||
921  result.num_cols() != arg.num_cols() ||
922  result.num_rows() != this->num_rows()){
923  BIASERR("invalid matrix sizes "<<this->num_rows()<<"x"<< this->num_cols()
924  <<" * "<<arg.num_rows()<<"x"<<arg.num_cols()
925  <<" = "<<result.num_rows()<<"x"<<result.num_cols());
926  //BIASASSERT(false);
927  BIASABORT;
928  }
929 #endif
930  result.SetZero();
931  register int x, y, i;
932  for (x=0; x<result.num_cols(); x++)
933  for (y=0; y<result.num_rows(); y++)
934  for (i=0; i<this->num_cols(); i++)
935  result[y][x]+=(*this)[y][i]*arg[i][x];
936  }
937 
938  template<class T>
939  inline void Matrix<T>::Mult(const Matrix<T>& arg)
940  {
941  Matrix<T> result(this->num_rows(),arg.num_cols());
942  Mult(arg,result);
943  (*this)=result;
944  }
945 
946  template<class T>
947  inline void Matrix<T>::MultLeft(const Matrix<T>& arg)
948  {
949  Matrix<T> result(arg.num_rows(),this->num_cols());
950  arg.Mult(*this,result);
951  (*this)=result;
952  }
953 
954  template<class T>
955  inline void Matrix<T>::Mult(const Vector<T>& arg, Vector<T>& result) const
956  {
957  if (result.size() != this->num_rows()) {
958  result.newsize(this->num_rows());
959  }
960 #ifdef BIAS_DEBUG
961  if (this->num_cols() != arg.size() ||
962  result.size() != this->num_rows()) {
963  BIASERR("invalid matrix/vector sizes "<<this->num_rows()<<"x"<< this->num_cols()
964  <<" * "<<arg.size()<<"x1"
965  <<" = "<<result.size()<<"x1");
966  BIASABORT;
967  }
968 #endif
969 
970  result.Fill((T)0);
971  register int y, i;
972  for (y=0; y<result.size(); y++)
973  for (i=0; i<this->num_cols(); i++)
974  result[y]+=(*this)[y][i]*arg[i];
975  }
976 
977  template<class T>
978  inline void Matrix<T>::MultLeft(const Vector<T>& arg,
979  Vector<T>& result) const
980  {
981  if (result.size() != this->num_cols()) {
982  result.newsize(this->num_cols());
983  }
984 #ifdef BIAS_DEBUG
985  if (this->num_rows() != arg.size() ||
986  result.size() != this->num_cols()) {
987  BIASERR("invalid matrix/vector sizes "
988  <<arg.size()<<"x1"<<" * "
989  <<this->num_rows()<<"x"<< this->num_cols()
990  <<" = "<<result.size()<<"x1");
991  BIASABORT;
992  }
993 #endif
994  if (result.size() != this->num_cols()) {
995  result.newsize(this->num_cols());
996  }
997  result.SetZero();
998  register int y, i;
999  for (y=0; y<this->num_cols(); y++)
1000  for (i=0; i<this->num_rows(); i++)
1001  result[y]+=(*this)[i][y]*arg[i];
1002 
1003  }
1004 
1005  template<class T>
1006  inline void Matrix<T>::MultiplyWithTransposeOf(const Matrix<T>& arg, Matrix<T>& result) const
1007  {
1008  if (result.num_cols() != arg.num_rows() ||
1009  result.num_rows() != this->num_rows()){
1010  result.newsize(this->num_rows(), arg.num_rows());
1011 #ifdef BIAS_DEBUG
1012  BIASWARN("Result-matrix has been resized!");
1013 #endif //BIAS_DEBUG
1014  }
1015 #ifdef BIAS_DEBUG
1016  if (this->num_cols() != arg.num_cols()){
1017  BIASERR("invalid matrix sizes "<<this->num_rows()<<"x"<< this->num_cols()
1018  <<" * "<<arg.num_rows()<<"x"<<arg.num_cols()
1019  <<" = "<<result.num_rows()<<"x"<<result.num_cols());
1020  //BIASASSERT(false);
1021  BIASABORT;
1022  }
1023 #endif
1024  result.SetZero();
1025  register int x, y, i;
1026  for (x=0; x<result.num_cols(); x++)
1027  for (y=0; y<result.num_rows(); y++)
1028  for (i=0; i<this->num_cols(); i++)
1029  result[y][x]+=(*this)[y][i]*arg[x][i];
1030  }
1031 
1032  template<class T>
1033  inline void Matrix<T>::AddIP(const Matrix<T> &arg)
1034  {
1035 #ifdef BIAS_DEBUG
1036  if (this->num_cols() != arg.num_cols() ||
1037  this->num_rows() != arg.num_rows()) {
1038  BIASERR("invalid matrix sizes "<<this->num_rows()<<"x"<< this->num_cols()
1039  <<" + "<<arg.num_rows()<<"x"<<arg.num_cols());
1040  //BIASASSERT(false);
1041  BIASABORT;
1042  }
1043 #endif
1044  T* thisData=GetData();
1045  const T* argData=arg.GetData();
1046  register unsigned int size=this->num_rows()*this->num_cols();
1047  for (unsigned int i=0;i<size;i++) {
1048  *thisData = *thisData + T(*argData);
1049  thisData++; argData++;
1050  }
1051  }
1052 
1053  template<class T>
1054  inline void Matrix<T>::SubIP(const Matrix<T> &arg)
1055  {
1056 #ifdef BIAS_DEBUG
1057  if (this->num_cols() != arg.num_cols() ||
1058  this->num_rows() != arg.num_rows()) {
1059  BIASERR("invalid matrix sizes "<<this->num_rows()<<"x"<< this->num_cols()
1060  <<" - "<<arg.num_rows()<<"x"<<arg.num_cols());
1061  //BIASASSERT(false);
1062  BIASABORT;
1063  }
1064 #endif
1065  T* thisData=GetData();
1066  const T* argData=arg.GetData();
1067  register unsigned int size=this->num_rows()*this->num_cols();
1068  for (unsigned int i=0;i<size;i++) {
1069  *thisData = *thisData - T(*argData);
1070  thisData++; argData++;
1071  }
1072  }
1073 
1074  template <class T>
1075  inline void Matrix<T>::GetSystemMatrix(Matrix<T> &dest) const
1076  {
1077  const unsigned int colsJ = this->num_cols(), rowsJ = this->num_rows();
1078  // resize result to square matrix
1079  dest.newsize(colsJ, colsJ);
1080  dest.SetZero();
1081  /// Hessian is symmetric! so first diagonal then lower left
1082  // diagonal
1083  for (unsigned int col = 0; col<colsJ; col++) {
1084  for (unsigned int k = 0; k<rowsJ; k++) {
1085  dest[col][col]+=this->row_[k][col]*this->row_[k][col];
1086  }
1087  }
1088  // lower left (which is equal to transposed upper right)
1089  for (unsigned int r=1; r<colsJ; r++) {
1090  for (unsigned int c=0; c<r; c++) {
1091  for (unsigned int k = 0; k<rowsJ; k++) {
1092  const T* pJ_k_ = this->row_[k];
1093  dest[r][c] += pJ_k_[r] * pJ_k_[c];
1094  }
1095  dest[c][r]=dest[r][c]; // symmetry of Hessian!
1096  }
1097  }
1098  }
1099 
1100  template <class T>
1102  {
1103  TNT::Matrix<T>::operator=(mat); // call the operator of the base class
1104  return *this;
1105  }
1106 
1107  template <class T>
1109  {
1110  TNT::Matrix<T>::operator=(mat); // call the operator of the base class
1111  return *this;
1112  }
1113 
1114 } // namespace BIAS
1115 
1116 #include <Base/Math/Operators.hh>
1117 
1118 #endif // _Matrix_hh_
Matrix(int rows, int cols, const T value)
assignment with a constant values for all elements (=set)
Definition: Matrix.hh:102
void SubIP(const T &scalar)
in place subtraction function
Definition: Matrix.hh:437
Matrix< T > & operator=(const Matrix< T > &A)
Definition: cmat.h:285
T * GetDataLast()
Definition: Matrix.hh:219
MatrixInitType
can be passed to matrix constructors to init the matrix with the most often used values ...
Definition: Matrix.hh:59
Subscript num_cols() const
Definition: cmat.h:320
class for column vectors with arbitrary size
Matrix< T > Transpose() const
transpose function, storing data destination matrix
Definition: Matrix.hh:823
void DivideElementwise(const Matrix< T > &arg)
elementwise division function in place
Definition: Matrix.hh:809
Matrix< T > & newsize(Subscript M, Subscript N)
Definition: cmat.h:269
int GetNumElements() const
Returns the total number of elements.
Definition: Matrix.hh:321
bool operator!=(const Matrix< T > &argl, const Matrix< T > &argr)
Definition: Matrix.hh:745
Matrix< T > & operator=(const TNT::Matrix< T > &mat)
assignment operators calling corresponding operator from base class if appropriate ...
Definition: Matrix.hh:1101
Matrix(const Matrix< T > &A)
Definition: Matrix.hh:131
double NormL2() const
Return the L2 norm: a^2 + b^2 + c^2 + ...
Definition: Matrix.hh:878
void SetZero()
equivalent to matrix call
Definition: Vector.hh:156
Matrix(const Vector< T > &v)
constructs Nx1 Matrix from N-Vector
Definition: Matrix.hh:137
class BIASMathBase_EXPORT Matrix
Definition: Operators.hh:37
virtual void clear()
stl conform interface destroys Matrix JW
Definition: Matrix.hh:534
Matrix< T > & operator+=(Matrix< T > &mat, const Matrix< T > &arg)
Definition: Matrix.hh:698
const T * GetDataLast() const
Get a pointer to the last data element Do not use this on unitilized matrices with &lt;= on pointers beca...
Definition: Matrix.hh:213
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
T ** GetDataArray1() const
returns 1 based array to data access
Definition: Matrix.hh:199
T ** GetDataArray()
Definition: Matrix.hh:195
unsigned int GetRows() const
Definition: Matrix.hh:202
Matrix< T > & operator+=(Matrix< T > &mat, const T &scalar)
operators
Definition: Matrix.hh:691
T * GetData()
get the pointer to the data array of the matrix (for faster direct memeory access) ...
Definition: Matrix.hh:185
is a &#39;fixed size&#39; quadratic matrix of dim.
Definition: Matrix.hh:54
Matrix(int rows, int cols)
Definition: Matrix.hh:98
void DivideIP(const T &scalar)
in place division function
Definition: Matrix.hh:486
Matrix< T > & operator*=(Matrix< T > &mat, const T &scalar)
Definition: Matrix.hh:719
Matrix(const TNT::Matrix< T > &A)
Definition: Matrix.hh:134
class Vector3 contains a Vector of fixed dim.
Definition: Matrix.hh:53
bool operator==(const Matrix< T > &argl, const Matrix< T > &argr)
Definition: Matrix.hh:730
unsigned int GetCols() const
Definition: Matrix.hh:204
void Mult(const Matrix< T > &arg, Matrix< T > &result) const
matrix multiplication, result is not allocated
Definition: Matrix.hh:913
matrix class with arbitrary size, indexing is row major.
const T ** GetDataArray() const
returns zero based arry for data access
Definition: Matrix.hh:192
Matrix(int rows, int cols, const MatrixInitType &i)
init with standard form
Definition: Matrix.hh:107
Subscript size() const
Definition: cmat.h:212
const T * GetData() const
Definition: Matrix.hh:188
Matrix< T > Adjoint() const
computes the adjoint matrix
Definition: Matrix.hh:833
void Multiply(const T &scalar, Matrix< T > &dest) const
multiplication function, storing data destination matrix
Definition: Matrix.hh:779
void MultiplyIP(const T &scalar)
in place multiplication function
Definition: Matrix.hh:448
void Sub(const T &scalar, Matrix< T > &dest) const
substraction function, storing data destination matrix
Definition: Matrix.hh:766
void MultLeft(const Matrix< T > &arg)
in Place matrix multiplication this is equal to M = arg*M, but faster
Definition: Matrix.hh:947
T Trace() const
Definition: Matrix.hh:903
void AddIP(const T &scalar)
in place addition function
Definition: Matrix.hh:415
void Add(const T &scalar, Matrix< T > &dest) const
addition function, storing data destination matrix
Definition: Matrix.hh:753
class BIASMathBase_EXPORT Vector
Subscript num_rows() const
Definition: cmat.h:319
void Divide(const T &scalar, Matrix< T > &dest) const
division function, storing data destination matrix
Definition: Matrix.hh:791
void SubIP(const Matrix< T > &arg)
Subtracts arg from this this -= arg.
Definition: Matrix.hh:1054
void MultiplyWithTransposeOf(const Matrix< T > &arg, Matrix< T > &result) const
matrix matrix multiplication for multiplication with the transpose of the given matrix, result=this*arg^T.
Definition: Matrix.hh:1006
T NormL1() const
Return the L1 norm: |a| + |b| + |c| + ...
Definition: Matrix.hh:867
void MakeSymmetric()
componentwise: this = 0.5(this + this^T) yields symmetric matrix only allowed for square shaped matri...
Definition: Matrix.hh:522
double NormFrobenius() const
Return Frobenius norm = sqrt(trace(A^t * A)).
Definition: Matrix.hh:897
Matrix< T > & operator-=(Matrix< T > &mat, const Matrix< T > &arg)
Definition: Matrix.hh:705
Matrix< T > & operator-=(Matrix< T > &mat, const T &scalar)
Definition: Matrix.hh:712
T DetSquare() const
Definition: Matrix.hh:369
void GetSystemMatrix(Matrix< T > &dest) const
compute square system matrix dest = A^T * A
Definition: Matrix.hh:1075
Subscript size() const
Definition: vec.h:262
void Fill(const T &scalar)
fills complete Vector with scalar value
Definition: Vector.cpp:92