cgv
mat.h
1 #pragma once
2 
3 #include "vec.h"
4 #include <limits>
5 #include <cassert>
6 
7 namespace cgv {
9  namespace math {
10 
11 
12 
13 template <typename T>
14 class mat;
15 
16 
17 
18 
19 template <typename RandomAccessIterator>
20 struct step_iterator
21 {
22 public:
23  typedef RandomAccessIterator base_type;
24  typedef typename base_type::pointer pointer;
25  typedef typename base_type::reference reference;
26  typedef typename base_type::value_type value_type;
27  typedef typename base_type::difference_type difference_type;
28  typedef typename base_type::iterator_category iterator_category;
29 private:
30  RandomAccessIterator internal_iter;
31  int step;
32 
33 
34  friend class mat<value_type>;
35 
36  step_iterator( RandomAccessIterator begin,int step=1):internal_iter(begin),step(step)
37  {}
38 
39 
40 public:
41 
42 
43  step_iterator():internal_iter(NULL)
44  {
45  step=0;
46  }
47 
48  step_iterator(const step_iterator& other)
49  {
50  internal_iter=other.internal_iter;
51  step=other.step;
52  }
53 
54  step_iterator& operator=(const step_iterator& other)
55  {
56  if(*this != other)
57  {
58  internal_iter = other.internal_iter;
59  step = other.step;
60  }
61  return *this;
62  }
63 
64  bool operator==(const step_iterator& other) const
65  {
66  return internal_iter == other.internal_iter;
67  }
68 
69  bool operator!=(const step_iterator& other) const
70  {
71  return !(*this==other);
72  }
73 
74  reference operator*()
75  {
76  return *internal_iter;
77  }
78 
79  reference operator*() const
80  {
81  return *internal_iter;
82  }
83  pointer operator->()
84  {
85  return &**this;
86  }
87 
88  pointer operator->() const
89  {
90  return &**this;
91  }
92 
93  step_iterator& operator ++()
94  {
95 
96  internal_iter+=step;
97  return *this;
98  }
99 
100  step_iterator operator ++(int)
101  {
102  step_iterator tmp=*this;
103  ++*this;
104  return tmp;
105 
106  }
107  step_iterator& operator --()
108  {
109  internal_iter-=step;
110  return *this;
111  }
112  step_iterator operator --(int)
113  {
114  step_iterator tmp=*this;
115  --*this;
116  return tmp;
117  }
118 
119 
120 
121  step_iterator& operator +=(difference_type n)
122  {
123  internal_iter+=n*step;
124  return *this;
125 
126  }
127 
128  step_iterator& operator -=(difference_type n)
129  {
130  internal_iter-=n*step;
131  return *this;
132  }
133 
134  step_iterator operator -(difference_type n) const
135  {
136  step_iterator tmp=*this;
137  tmp-=n;
138  return tmp;
139  }
140  difference_type operator-(const step_iterator& right) const
141  {
142  return (internal_iter - right.internal_iter)/step;
143  }
144 
145 
146  step_iterator operator +(difference_type n)const
147  {
148  step_iterator tmp=*this;
149  tmp+=n;
150  return tmp;
151  }
152 
153  reference operator[](difference_type offset) const
154  {
155  return (*(*this + offset));
156  }
157 
158  bool operator <(const step_iterator& other) const
159  {
160  if(step > 0)
161  return internal_iter < other.internal_iter;
162  else
163  return internal_iter > other.internal_iter;
164  }
165 
166  bool operator >(const step_iterator& other) const
167  {
168  if(step > 0)
169  return internal_iter > other.internal_iter;
170  else
171  return internal_iter < other.internal_iter;
172  }
173 
174  bool operator <=(const step_iterator& other) const
175  {
176  if(step > 0)
177  return internal_iter <= other.internal_iter;
178  else
179  return internal_iter >= other.internal_iter;
180  }
181 
182  bool operator >=(const step_iterator& other) const
183  {
184  if(step > 0)
185  return internal_iter >= other.internal_iter;
186  else
187  return internal_iter <= other.internal_iter;
188  }
189 
190 
191 };
192 
193 
194 
195 
196 
197 
198 
199 
200 
201 
202 
207 template <typename T>
208 class mat
209 {
210 protected:
214  unsigned _ncols;
216  unsigned _nrows;
217 
218 
219 public:
220  typedef typename vec<T>::value_type value_type;
221  typedef typename vec<T>::reference reference;
222  typedef typename vec<T>::const_reference const_reference;
223  typedef typename vec<T>::pointer pointer;
224  typedef typename vec<T>::const_pointer const_pointer;
225  typedef typename vec<T>::iterator iterator;
226  typedef typename vec<T>::const_iterator const_iterator;
227  typedef typename vec<T>::reverse_iterator reverse_iterator;
228  typedef typename vec<T>::const_reverse_iterator const_reverse_iterator;
229 
230  typedef iterator col_iterator;
231  typedef const col_iterator const_col_iterator;
232  typedef std::reverse_iterator<col_iterator> reverse_col_iterator;
233  typedef std::reverse_iterator<const_col_iterator> const_reverse_col_iterator;
234 
235  typedef step_iterator<iterator> row_iterator;
236  typedef const row_iterator const_row_iterator;
237  typedef std::reverse_iterator<row_iterator> reverse_row_iterator;
238  typedef std::reverse_iterator<const_row_iterator> const_reverse_row_iterator;
239 
240  typedef step_iterator<iterator > diag_iterator;
241  typedef const diag_iterator const_diag_iterator;
242  typedef std::reverse_iterator<diag_iterator> reverse_diag_iterator;
243  typedef std::reverse_iterator<const_diag_iterator> const_reverse_diag_iterator;
244 
245  typedef step_iterator<iterator > anti_diag_iterator;
246  typedef const anti_diag_iterator const_anti_diag_iterator;
247  typedef std::reverse_iterator<anti_diag_iterator> reverse_anti_diag_iterator;
248  typedef std::reverse_iterator<const_anti_diag_iterator> const_reverse_anti_diag_iterator;
249 
250 
251 
252 
253 
254  iterator begin(){return _data.begin();}
255  iterator end(){return _data.end();}
256  const_iterator begin() const{return _data.begin();}
257  const_iterator end() const{return _data.end();}
258  reverse_iterator rbegin(){return _data.rbegin();}
259  reverse_iterator rend(){return _data.rend();}
260  const_reverse_iterator rbegin() const{return _data.rbegin();}
261  const_reverse_iterator rend() const {return _data.rend();}
262 
263 
264 
265  col_iterator col_begin(int c)
266  {
267  return col_iterator(_data.begin()+(c*_nrows));
268  }
269  col_iterator col_end(int c)
270  {
271  return col_iterator(_data.begin()+(c+1)*_nrows );
272  }
273  const_col_iterator col_begin(int c) const
274  {
275  return const_col_iterator(_data.begin()+(c*_nrows));
276  }
277  const_col_iterator col_end(int c) const
278  {
279  return const_col_iterator(_data.begin()+(c+1)*_nrows );
280  }
281  reverse_col_iterator col_rbegin(int c)
282  {
283  return (reverse_col_iterator(col_end(c)));
284  }
285  reverse_col_iterator col_rend(int c)
286  {
287  return (reverse_col_iterator(col_begin(c)));
288  }
289  const_reverse_col_iterator col_rbegin(int c) const
290  {
291  return (const_reverse_col_iterator(col_end(c)));
292  }
293  const_reverse_col_iterator col_rend(int c) const
294  {
295  return (const_reverse_col_iterator(col_begin(c)));
296  }
297 
298  row_iterator row_begin(int r)
299  {
300  return row_iterator(_data.begin()+r,_nrows);
301  }
302  row_iterator row_end(int r)
303  {
304  return row_iterator(_data.begin()+(r+_ncols*_nrows),_nrows);
305  }
306  const_row_iterator row_begin(int r) const
307  {
308  return const_row_iterator(_data.begin()+r,_nrows);
309  }
310  const_row_iterator row_end(int r) const
311  {
312  return const_row_iterator(_data.begin()+(r+_ncols*_nrows),_nrows);
313  }
314 
315  reverse_row_iterator row_rbegin(int r)
316  {
317  return (reverse_row_iterator(row_end(r)));
318  }
319 
320  reverse_row_iterator row_rend(int r)
321  {
322  return (reverse_row_iterator(row_begin(r)));
323  }
324 
325  const_reverse_row_iterator row_rbegin(int r) const
326  {
327  return (const_reverse_row_iterator(row_end(r)));
328  }
329 
330  const_reverse_row_iterator row_rend(int r) const
331  {
332  return (const_reverse_row_iterator(row_begin(r)));
333  }
334 
335 
336 
337 
338  diag_iterator diag_begin(int d=0)
339  {
340  if(d <= 0)
341  return diag_iterator(_data.begin()-d ,_nrows+1);
342  else
343  return diag_iterator(_data.begin()+d*_nrows,_nrows+1);
344 
345  }
346  diag_iterator diag_end(int d=0)
347  {
348  if(d <= 0)
349  {
350  int n=std::min<int>(_nrows+d,_ncols);
351  return diag_iterator(_data.begin()-d+n*(_nrows+1),_nrows+1);
352  }
353  else
354  {
355  int n = std::min<int>(_ncols-d,_nrows);
356  return diag_iterator(_data.begin()+d*_nrows+n*(_nrows+1),_nrows+1) ;
357  }
358  }
359  const_diag_iterator diag_begin(int d=0) const
360  {
361  if(d <= 0)
362  return const_diag_iterator(begin()-d ,_nrows+1);
363  else
364  return const_diag_iterator(begin()+d*_nrows,_nrows+1);
365 
366  }
367  const_diag_iterator diag_end(int d=0) const
368  {
369  if(d <= 0)
370  {
371  int n=std::min<int>(_nrows+d,_ncols);
372  return const_diag_iterator(_data.begin()-d+n*(_nrows+1),_nrows+1);
373  }
374  else
375  {
376  int n = std::min<int>(_ncols-d,_nrows);
377  return const_diag_iterator(_data.begin()+d*_nrows+n*(_nrows+1),_nrows+1) ;
378  }
379  }
380  reverse_diag_iterator diag_rbegin(int d=0)
381  {
382  return (reverse_diag_iterator(diag_end(d)));
383  }
384  reverse_diag_iterator diag_rend(int d=0)
385  {
386  return (reverse_diag_iterator(diag_begin(d)));
387  }
388  const_reverse_diag_iterator diag_rbegin(int d=0) const
389  {
390  return (const_reverse_diag_iterator(diag_end(d)));
391  }
392  const_reverse_diag_iterator diag_rend(int d=0) const
393  {
394  return (const_reverse_diag_iterator(diag_begin(d)));
395  }
396 
397  anti_diag_iterator anti_diag_begin(int d=0)
398  {
399  if(d >= 0)
400  return anti_diag_iterator(_data.begin()+(_ncols-1-d)*_nrows ,1-_nrows);
401  else
402  return anti_diag_iterator(_data.begin()+(_ncols-1)*_nrows-d ,1-_nrows);
403  }
404 
405  anti_diag_iterator anti_diag_end(int d=0)
406  {
407  if(d >= 0)
408  {
409  int n=std::min(_ncols-d,_nrows);
410  return anti_diag_iterator(_data.begin()+(_ncols-1-d)*_nrows +n*(1-_nrows),1-_nrows);
411  }
412  else
413  {
414  int n=std::min(_nrows+d,_ncols);
415  return anti_diag_iterator(_data.begin()+(_ncols-1)*_nrows-d +n*(1-_nrows),1-_nrows);
416  }
417  }
418 
419  const_anti_diag_iterator anti_diag_begin(int d=0) const
420  {
421  if(d >= 0)
422  return const_anti_diag_iterator(_data.begin()+(_ncols-1-d)*_nrows ,1-_nrows);
423  else
424  return const_anti_diag_iterator(_data.begin()+(_ncols-1)*_nrows-d ,1-_nrows);
425  }
426 
427  const_anti_diag_iterator anti_diag_end(int d=0) const
428  {
429  if(d >= 0)
430  {
431  int n=std::min(_ncols-d,_nrows);
432  return const_anti_diag_iterator(_data.begin()+(_ncols-1-d)*_nrows +n*(1-_nrows),1-_nrows);
433  }
434  else
435  {
436  int n=std::min(_nrows+d,_ncols);
437  return const_anti_diag_iterator(_data.begin()+(_ncols-1)*_nrows-d +n*(1-_nrows),1-_nrows);
438  }
439  }
440 
441  reverse_anti_diag_iterator anti_diag_rbegin(int d=0)
442  {
443  return (reverse_anti_diag_iterator(anti_diag_end(d)));
444  }
445 
446  reverse_anti_diag_iterator anti_diag_rend(int d=0)
447  {
448  return (reverse_anti_diag_iterator(anti_diag_begin(d)));
449  }
450 
451  const_reverse_anti_diag_iterator anti_diag_rbegin(int d=0) const
452  {
453  return (const_reverse_anti_diag_iterator(anti_diag_end(d)));
454  }
455 
456  const_reverse_anti_diag_iterator anti_diag_rend(int d=0) const
457  {
458  return (const_reverse_anti_diag_iterator(anti_diag_begin(d)));
459  }
460 
462  mat()
463  {
464  _ncols = 0;
465  _nrows = 0;
466  }
467 
468 
470  mat(unsigned nrows, unsigned ncols) : _data(nrows*ncols)
471  {
472  _nrows = nrows;
473  _ncols = ncols;
474  }
475 
477  mat(unsigned nrows, unsigned ncols, const T& c) :_data(nrows*ncols)
478  {
479  _nrows = nrows;
480  _ncols = ncols;
481  _data.fill(c);
482  }
483 
484 
487  mat(unsigned nrows, unsigned ncols, const T* marray,bool column_major=true)
488  :_data(nrows*ncols)
489  {
490  _nrows = nrows;
491  _ncols = ncols;
492  if(column_major)
493  memcpy(_data, marray, size()*sizeof(T));
494  else
495  {
496 
497  for(unsigned i = 0; i < _nrows; i++)
498  for(unsigned j = 0; j < _ncols;j++)
499  {
500  operator()(i,j) = marray[i*_ncols +j];
501  }
502 
503 
504  }
505  }
506 
507 
508 
510  template <typename S>
511  mat(const mat<S>& m):_data(m.size())
512  {
513  _nrows = m.nrows();
514  _ncols = m.ncols();
515  for(unsigned i = 0; i < _nrows; i++)
516  for(unsigned j = 0; j < _ncols;j++)
517  {
518  operator()(i,j)=(T)m(i,j);
519  }
520 
521  }
522 
524  void set_extern_data(unsigned nrows, unsigned ncols, T* data)
525  {
526  _data.set_extern_data(nrows*ncols,data);
527  _nrows = nrows;
528  _ncols = ncols;
529  }
530  void destruct()
531  {
532  _data.destruct();
533  }
535  unsigned size() const
536  {
537  return _data.size();
538  }
539 
541  unsigned nrows() const
542  {
543  return _nrows;
544  }
545 
547  unsigned ncols() const
548  {
549  return _ncols;
550  }
551 
552 
553 
555  template <typename S>
557  {
558  resize(m.nrows(),m.ncols());
559  for(unsigned i = 0; i < _nrows; i++)
560  for(unsigned j = 0; j < _ncols;j++)
561  {
562  operator()(i,j)=(T)m(i,j);
563  }
564  return *this;
565  }
566 
568  mat<T>& operator = (const T& s)
569  {
570  fill (s);
571  return *this;
572  }
573 
575  void resize(unsigned rows, unsigned cols)
576  {
577 
578  unsigned newsize = rows*cols;
579  _nrows = rows;
580  _ncols = cols;
581  _data.resize(newsize);
582  }
583 
585  operator T*()
586  {
587  return (T*)_data;
588  }
589 
591  operator const T*() const
592  {
593  return (const T*)_data;
594  }
595 
597  bool is_square() const
598  {
599  return _ncols == _nrows;
600  }
601 
603  template <typename S>
604  void fill(const S& v)
605  {
606  T val = (T)v;
607  _data.fill(val);
608  }
609 
611  T& operator () (unsigned i, unsigned j)
612  {
613  assert(i < _nrows && j < _ncols);
614  return _data[j*_nrows+i];
615  }
616 
618  const T& operator () (unsigned i, unsigned j) const
619  {
620  assert(_data != NULL && i < _nrows && j < _ncols);
621  return _data[j*_nrows+i];
622  }
623 
625  template <typename S>
626  bool operator == (const mat<S>& m) const
627  {
628  if(_ncols != m.ncols() || _nrows != m.nrows())
629  return false;
630 
631  return _data == m._data;
632  }
633 
635  template <typename S>
636  bool operator != (const mat<S>& m) const
637  {
638  if(_ncols != m.ncols() || _nrows != m.nrows())
639  return false;
640  return _data != m._data;
641  return false;
642  }
643 
644 
645  //in place scalar multiplication
646  mat<T>& operator *= (const T& s)
647  {
648  _data *= (T)s;
649  return *this;
650  }
651 
653  const mat<T> operator*(const T& s) const
654  {
655  mat<T> r=(*this);
656  r*=(T)s;
657  return r;
658  }
659 
661  mat<T>& operator /= (const T& s)
662  {
663  _data /= (T)s;
664  return *this;
665  }
666 
668  const mat<T> operator / (const T& s) const
669  {
670  mat<T> r=(*this);
671  r/=s;
672  return r;
673  }
674 
675 
677  mat<T>& operator += (const T& s)
678  {
679  _data += (T)s;
680  return *this;
681  }
682 
684  const mat<T> operator + (const T& s)
685  {
686  mat<T> r=(*this);
687  r+=s;
688  return r;
689  }
690 
692  mat<T>& operator -= (const T& s)
693  {
694  _data -= (T)s;
695  return *this;
696  }
697 
699  const mat<T> operator - (const T& s)
700  {
701  mat<T> r=(*this);
702  r-=s;
703  return r;
704  }
705 
707  const mat<T> operator-() const
708  {
709  mat<T> r=(*this)*((T)-1);
710  return r;
711  }
712 
714  template <typename S>
716  {
717  assert(_ncols == m.ncols() && _nrows == m.nrows());
718  _data+=m._data;
719  return *this;
720  }
721 
723  template <typename S>
725  {
726  assert(_ncols == m.ncols() && _nrows == m.nrows());
727  _data-=m._data;
728  return *this;
729  }
730 
731 
732 
733 
735  template <typename S>
736  const mat<T> operator+(const mat<S> m2)const
737  {
738  mat<T> r=(*this);
739  r += m2;
740  return r;
741  }
742 
744  template <typename S>
745  const mat<T> operator-(const mat<S> m2)const
746  {
747  mat<T> r=(*this);
748  r-= m2;
749  return r;
750  }
751 
752 
754  template <typename S>
755  const mat<T> operator*=(const mat<S>& m2)
756  {
757  assert(ncols() == m2.ncols() && nrows() == m2.nrows() && ncols() == nrows());
758  mat<T> r(_nrows,_ncols,(T)0);
759 
760  for(unsigned i = 0; i < _nrows; i++)
761  for(unsigned j = 0; j < _ncols;j++)
762  for(unsigned k = 0; k < _ncols; k++)
763  r(i,j) += operator()(i,k) * (T)(m2(k,j));
764  (*this)=r;
765 
766  return *this;
767  }
768 
769 
770 
772  template <typename S>
773  const mat<T> operator*(const mat<S>& m2) const
774  {
775  assert(m2.nrows() == _ncols);
776  unsigned M = m2.ncols();
777  mat<T> r(_nrows,M,(T)0);
778  for(unsigned i = 0; i < _nrows; i++)
779  for(unsigned j = 0; j < M;j++)
780  for(unsigned k = 0; k < _ncols; k++)
781  r(i,j) += operator()(i,k) * (T)(m2(k,j));
782 
783  return r;
784  }
785 
786 
788  template < typename S>
789  const vec<T> operator*(const vec<S>& v) const
790  {
791  assert(_ncols==v.size());
792  vec<T> r;
793  r.zeros(_nrows);
794 
795  for(unsigned j = 0; j < _ncols; j++)
796  for(unsigned i = 0; i < _nrows; i++)
797  r(i) += operator()(i,j) * (T)(v(j));
798 
799  return r;
800  }
801 
803  mat<T> sub_mat(unsigned top, unsigned left, unsigned rows, unsigned cols) const
804  {
805 
806  mat<T> mnew(rows,cols);
807 
808  for(unsigned i = 0; i < rows;i++)
809  for(unsigned j = 0; j < cols;j++)
810  mnew(i,j)=operator()(i+top,j+left);
811 
812  return mnew;
813  }
814 
816  const vec<T> row(unsigned i) const
817  {
818 
819  vec<T> mnew(_ncols);
820 
821 
822  for(unsigned j = 0; j < _ncols;j++)
823  mnew(j)=operator()(i,j);
824 
825  return mnew;
826  }
827 
829  void set_row(unsigned i,const vec<T>& v)
830  {
831 
832  for(unsigned j = 0; j < _ncols;j++)
833  operator()(i,j)=v(j);
834 
835 
836  }
837 
839  const vec<T> col(unsigned j) const
840  {
841 
842  vec<T> mnew(_nrows);
843 
844 
845  for(unsigned i = 0; i < _nrows;i++)
846  mnew(i)=operator()(i,j);
847 
848  return mnew;
849  }
850 
852  void set_col(unsigned j,const vec<T>& v)
853  {
854 
855  for(unsigned i = 0; i < _nrows;i++)
856  operator()(i,j)=v(i);
857  }
858 
859 
860 
861 
863  void copy(unsigned top, unsigned left, unsigned rows, unsigned cols, mat<T>& submat) const
864  {
865  assert(submat.nrows() == rows && submat.ncols() == cols);
866 
867  for(unsigned i = 0; i < rows;i++)
868  for(unsigned j = 0; j < cols;j++)
869  submat(i,j)=operator()(i+top,j+left);
870 
871 
872  }
873 
875  void paste(int top, int left,const mat<T>& m)
876  {
877  for(unsigned i = 0; i < m.nrows(); i++)
878  for(unsigned j = 0; j < m.ncols(); j++)
879  operator()(i+top,j+left)=m(i,j);
880 
881  }
882 
883 
885  void swap_rows(unsigned i, unsigned j)
886  {
887  assert(i < _nrows && j < _nrows);
888  for(unsigned k = 0; k < _ncols;k++)
889  std::swap(operator()(i,k),operator()(j,k));
890  }
891 
893  void swap_columns(unsigned i, unsigned j)
894  {
895  assert(i < _ncols && j < _ncols);
896  for(unsigned k = 0; k < _nrows;k++)
897  std::swap(operator()(k,i),operator()(k,j));
898 
899  }
900 
902  void swap_diagonal_elements(unsigned i, unsigned j)
903  {
904  assert(i < _ncols && j < _ncols);
905  std::swap(operator()(i,i),operator()(j,j));
906  }
907 
908 
909 
910 
912  T trace() const
913  {
914  assert(_nrows == _ncols);
915  T t = 0;
916  for(unsigned i = 0; i < _nrows;i++)
917  t+=operator()(i,i);
918  return t;
919  }
920 
922  void transpose()
923  {
924  mat<T> r(_ncols,_nrows);
925 
926  for(unsigned i = 0; i < _nrows;i++)
927  for(unsigned j = 0; j < _ncols;j++)
928  r(j,i) = operator()(i,j);
929 
930  *this = r;
931  }
932 
933  //flip columns left-right
934  void fliplr()
935  {
936  mat<T> r(_nrows,_ncols);
937 
938  for(unsigned i = 0; i < _nrows;i++)
939  for(unsigned j = 0; j < _ncols;j++)
940  r(i,j) = operator()(i,_ncols-j-1);
941 
942  *this = r;
943 
944  }
945 
946  //flip rows up-down
947  void flipud()
948  {
949  mat<T> r(_nrows,_ncols);
950 
951  for(unsigned i = 0; i < _nrows;i++)
952  for(unsigned j = 0; j < _ncols;j++)
953  r(i,j) = operator()(_nrows-i-1,j);
954 
955  *this = r;
956 
957  }
958 
960  void ceil()
961  {
962  for(unsigned i = 0; i < _nrows;i++)
963  for(unsigned j = 0; j < _ncols;j++)
964  operator()(i,j) =::ceil(operator()(i,j));
965  }
966 
968  void floor()
969  {
970  for(unsigned i = 0; i < _nrows;i++)
971  for(unsigned j = 0; j < _ncols;j++)
972  operator()(i,j) =::floor(operator()(i,j));
973  }
974 
976  void round()
977  {
978  for(unsigned i = 0; i < _nrows;i++)
979  for(unsigned j = 0; j < _ncols;j++)
980  operator()(i,j) =::floor(operator()(i,j)+(T)0.5);
981 
982  }
983 
984 
985 
987  T frobenius_norm() const
988  {
989  T n=0;
990  for(unsigned i =0; i < _nrows;i++)
991  for(unsigned j=0;j <_ncols;j++)
992  n+=operator()(i,j)*operator()(i,j);
993 
994  return (T)sqrt((double)n);
995  }
996 
997 
999  void identity()
1000  {
1001  assert(_ncols == _nrows);
1002  zeros();
1003  for(unsigned i = 0; i < _ncols;++i)
1004  operator()(i,i)=1;
1005  }
1006 
1008  void identity(unsigned dim)
1009  {
1010  zeros(dim,dim);
1011  for(unsigned i = 0; i < _ncols;++i)
1012  operator()(i,i)=1;
1013  }
1014 
1016  void zeros()
1017  {
1018  fill(0);
1019  }
1020 
1022  void zeros(unsigned rows, unsigned cols)
1023  {
1024  resize(rows,cols);
1025  fill((T)0);
1026  }
1027 
1029  void ones(unsigned rows, unsigned cols)
1030  {
1031  resize(rows,cols);
1032  fill((T)1);
1033  }
1034 
1035 
1036 
1037 
1038 };
1039 
1040 template <typename T>
1041 mat<T> zeros(unsigned rows, unsigned cols)
1042 {
1043  mat<T> m;
1044  m.zeros(rows,cols);
1045  return m;
1046 }
1047 
1048 template <typename T>
1049 mat<T> ones(unsigned rows, unsigned cols)
1050 {
1051  mat<T> m(rows,cols);
1052  m.fill((T)1);
1053  return m;
1054 }
1055 
1056 template<typename T>
1057 mat<T> identity(unsigned dim)
1058 {
1059  mat<T> m;
1060  m.identity(dim);
1061  return m;
1062 }
1063 
1064 //return frobenius norm
1065 template<typename T>
1066 T frobenius_norm(const mat<T>& m)
1067 {
1068  return m.frobenius_norm();
1069 }
1070 
1071 //return trace of matrix
1072 template<typename T>
1073 T trace(const mat<T>& m)
1074 {
1075  return m.trace();
1076 }
1077 
1078 
1079 //concatenate two matrices horizontally
1080 template<typename T, typename S>
1081 const mat<T> horzcat(const mat<T>& m1, const mat<S>& m2)
1082 {
1083 
1084  assert(m1.nrows() == m2.nrows());
1085  mat<T> r(m1.nrows(),m1.ncols()+m2.ncols());
1086  for(unsigned i = 0; i < m1.nrows();i++)
1087  {
1088  for(unsigned j = 0; j < m1.ncols(); j++)
1089  r(i,j) = m1(i,j);
1090  for(unsigned j = 0; j < m2.ncols(); j++)
1091  r(i,j+m1.ncols())=(T)m2(i,j);
1092  }
1093  return r;
1094 }
1095 
1096 //concatenates a matrix and a column vector horizontally
1097 template<typename T, typename S>
1098 const mat<T> horzcat(const mat<T>& m1, const vec<S>& v)
1099 {
1100 
1101  assert(m1.nrows() == v.size());
1102  mat<T> r(m1.nrows(),m1.ncols()+1);
1103  for(unsigned i = 0; i < m1.nrows();i++)
1104  {
1105  for(unsigned j = 0; j < m1.ncols(); j++)
1106  r(i,j) = m1(i,j);
1107 
1108  r(i,m1.ncols())=(T)v(i);
1109  }
1110  return r;
1111 }
1112 
1113 //concatenates two vectors horizontally
1114 template<typename T, typename S>
1115 const mat<T> horzcat(const vec<T>& v1, const vec<S>& v2)
1116 {
1117 
1118  assert(v1.size() == v2.size());
1119  mat<T> r(v1.size(),2);
1120  for(unsigned i = 0; i < v1.size();i++)
1121  {
1122  r(i,0) = v1(i);
1123  r(i,1) = v2(i);
1124  }
1125  return r;
1126 }
1127 
1128 //concatenates two column vectors vertically
1129 template<typename T, typename S>
1130 const vec<T> vertcat(const vec<T>& v1, const vec<S>& v2)
1131 {
1132 
1133  vec<T> r(v1.size()+v2.size());
1134  unsigned off = v1.size();
1135  for(unsigned i = 0; i < v1.size();i++)
1136  r(i) = v1(i);
1137  for(unsigned i = 0; i < v2.size();i++)
1138  r(i+off) = v2(i);
1139 
1140  return r;
1141 }
1142 
1143 
1144 //concatenates two matrices vertically
1145 template<typename T, typename S>
1146 const mat<T> vertcat(const mat<T>& m1, const mat<S>& m2)
1147 {
1148 
1149  assert(m1.ncols() == m2.ncols());
1150  mat<T> r(m1.nrows()+m2.nrows(),m1.ncols());
1151  for(unsigned i = 0; i < m1.nrows();i++)
1152  {
1153  for(unsigned j = 0; j < m1.ncols(); j++)
1154  r(i,j) = m1(i,j);
1155  }
1156 
1157  for(unsigned i = 0; i < m2.nrows();i++)
1158  {
1159  for(unsigned j = 0; j < m1.ncols(); j++)
1160  r(i+m1.nrows(),j) = m2(i,j);
1161  }
1162 
1163  return r;
1164 }
1165 
1166 
1167 
1168 
1169 //transpose of a matrix m
1170 template <typename T>
1171 const mat<T> transpose(const mat<T> &m)
1172 {
1173  mat<T> r = m;
1174  r.transpose();
1175  return r;
1176 }
1177 //transpose of a column vector
1178 template <typename T>
1179 const mat<T> transpose(const vec<T> &v)
1180 {
1181  mat<T> r(1, v.size());
1182  for(unsigned i = 0; i < v.size(); i++)
1183  r(0,i)= v(i);
1184 
1185  return r;
1186 }
1187 
1189 template <typename T>
1190 const mat<T> ceil(const mat<T> &m)
1191 {
1192  mat<T> r = m;
1193  r.ceil();
1194  return r;
1195 }
1196 
1198 template <typename T>
1199 const mat<T> floor(const mat<T> &m)
1200 {
1201  mat<T> r = m;
1202  r.floor();
1203  return r;
1204 }
1205 
1207 template <typename T>
1208 const mat<T> round(const mat<T> &m)
1209 {
1210  mat<T> r = m;
1211  r.round();
1212  return r;
1213 }
1214 
1215 
1216 
1217 
1219 template <typename T>
1220 mat<T> operator * (const T& s, const mat<T>& m)
1221 {
1222  return m*(T)s;
1223 }
1224 
1225 
1226 
1228 template <typename T>
1229 std::ostream& operator<<(std::ostream& out, const mat<T>& m)
1230 {
1231 
1232  for (unsigned i=0;i<m.nrows();++i)
1233  {
1234  for(unsigned j =0;j < m.ncols()-1;++j)
1235  out << m(i,j)<<" ";
1236  out << m(i,m.ncols()-1);
1237  if(i != m.nrows()-1)
1238  out <<"\n";
1239  }
1240 
1241  return out;
1242 
1243 }
1244 
1245 
1247 template <typename T>
1248 std::istream& operator>>(std::istream& in, mat<T>& m)
1249 {
1250  assert(m.size() > 0);
1251  for (unsigned i=0;i<m.nrows();++i)
1252  for(unsigned j =0;j < m.ncols();++j)
1253  in >> m(i,j);
1254 
1255 
1256  return in;
1257 
1258 }
1259 
1260 
1261 
1262 
1263 
1264 
1265 //compute transpose(A)*A
1266 template <typename T>
1267 void AtA(const mat<T>& a, mat<T>& ata)
1268 {
1269  ata.resize(a.ncols(),a.ncols());
1270  ata.zeros();
1271  for(unsigned r = 0; r < a.nrows();r++)
1272  {
1273  for(unsigned i = 0; i < a.ncols();i++)
1274  {
1275  for(unsigned j = 0; j < a.ncols();j++)
1276  {
1277  ata(i,j)+=a(r,i)*a(r,j);
1278  }
1279  }
1280  }
1281 }
1282 //compute A*transpose(A)
1283 template <typename T>
1284 void AAt(const mat<T>& a, mat<T>& aat)
1285 {
1286  aat.resize(a.nrows(),a.nrows());
1287  aat.zeros();
1288  for(unsigned c = 0; c < a.ncols();c++)
1289  {
1290  for(unsigned i = 0; i < a.nrows();i++)
1291  {
1292  for(unsigned j = 0; j < a.nrows();j++)
1293  {
1294  aat(i,j)+=a(i,c)*a(j,c);
1295  }
1296  }
1297  }
1298 
1299 }
1300 
1301 template <typename T>
1302 mat<T> reshape(const vec<T>& v,unsigned r,unsigned c)
1303 {
1304  assert(v.size() == r*c);
1305  return mat<T>(r,c,(const T*)v);
1306 }
1307 
1308 template <typename T>
1309 mat<T> reshape(const mat<T>& m,unsigned r,unsigned c)
1310 {
1311  assert(m.size() == r*c);
1312  return mat<T>(r,c,(const T*)m);
1313 }
1314 
1315 
1316 template <typename T>
1317 void AtB(const mat<T>& a,const mat<T>& b, mat<T>& atb)
1318 {
1319  atb.resize(a.ncols(),b.ncols());
1320  atb.zeros();
1321 
1322  for(unsigned i = 0; i < a.ncols(); i++)
1323  for(unsigned j = 0; j < b.ncols();j++)
1324  for(unsigned k = 0; k < a.nrows(); k++)
1325  atb(i,j) += a(k,i)*b(k,j);
1326 
1327 }
1328 
1331 template <typename T>
1332 void Atx(const mat<T>& a,const vec<T>& x, vec<T>& atx)
1333 {
1334  atx.resize(a.ncols());
1335  atx.zeros();
1336 
1337  for(unsigned i = 0; i < a.ncols(); i++)
1338  for(unsigned j = 0; j < a.nrows(); j++)
1339  atx(i) += a(j,i) * (T)(x(j));
1340 
1341 
1342 }
1343 
1344 
1346 template < typename T, typename S>
1347 mat<T> dyad(const vec<T>& v, const vec<S>& w)
1348 {
1349  mat<T> m(v.size(),w.size());
1350 
1351  for(unsigned i = 0; i < v.size();i++)
1352  for(unsigned j = 0; j < w.size();j++)
1353  m(i,j) =v(i)*(T)w(j);
1354 
1355  return m;
1356 }
1357 
1358 
1359 
1360 }
1361 
1362 
1363 }
cgv::math::mat::operator+
const mat< T > operator+(const mat< S > m2) const
matrix addition
Definition: mat.h:736
cgv::math::vec::resize
void resize(unsigned dim)
resize the vector
Definition: vec.h:557
cgv::math::mat::ones
void ones(unsigned rows, unsigned cols)
resize and fill matrix with ones
Definition: mat.h:1029
cgv::math::mat::mat
mat()
standard constructor
Definition: mat.h:462
cgv::math::mat::_ncols
unsigned _ncols
number of columns
Definition: mat.h:214
cgv::math::mat::operator*
const mat< T > operator*(const mat< S > &m2) const
multiplication with a ncols x M matrix m2
Definition: mat.h:773
cgv::math::mat::swap_rows
void swap_rows(unsigned i, unsigned j)
exchange row i with row j
Definition: mat.h:885
cgv::math::mat::zeros
void zeros()
set zero matrix
Definition: mat.h:1016
cgv::math::round
fvec< T, N > round(const fvec< T, N > &v)
apply round function component wise to vector
Definition: fvec.h:318
cgv::math::mat::operator/=
mat< T > & operator/=(const T &s)
in place division by a scalar
Definition: mat.h:661
cgv::math::mat
Definition: mat.h:14
cgv::math::mat::operator-=
mat< T > & operator-=(const T &s)
in place substraction of a scalar
Definition: mat.h:692
cgv::math::mat::mat
mat(const mat< S > &m)
copy constructor for matrix with different element type
Definition: mat.h:511
cgv::math::vec
A column vector class.
Definition: fvec.h:13
cgv::math::vec::size
unsigned size() const
number of elements
Definition: vec.h:97
cgv::math::mat::size
unsigned size() const
number of stored elements
Definition: mat.h:535
cgv::math::mat::operator==
bool operator==(const mat< S > &m) const
test for equality
Definition: mat.h:626
cgv::math::mat::operator*=
const mat< T > operator*=(const mat< S > &m2)
in place matrix multiplication with a ncols x ncols matrix m2
Definition: mat.h:755
cgv::math::mat::floor
void floor()
floor all components of the matrix
Definition: mat.h:968
cgv::math::mat::operator=
mat< T > & operator=(const mat< S > &m)
assignment of a matrix with a different element type
Definition: mat.h:556
cgv::math::floor
fvec< T, N > floor(const fvec< T, N > &v)
apply floor function component wise to vector
Definition: fvec.h:322
cgv::math::mat::transpose
void transpose()
transpose matrix
Definition: mat.h:922
cgv::math::mat::ceil
void ceil()
ceil all components of the matrix
Definition: mat.h:960
cgv::math::mat::round
void round()
round to integer
Definition: mat.h:976
cgv::math::transpose
fmat< T, N, N > transpose(const fmat< T, N, N > &m)
return the transposed of a square matrix
Definition: fmat.h:196
cgv::math::operator<<
std::ostream & operator<<(std::ostream &out, const diag_mat< T > &m)
output of a diagonal matrix onto an ostream
Definition: diag_mat.h:442
cgv::math::Atx
void Atx(const mat< T > &a, const vec< T > &x, vec< T > &atx)
Definition: mat.h:1332
cgv::math::mat::col
const vec< T > col(unsigned j) const
extract a column of the matrix as a vector
Definition: mat.h:839
cgv::math::mat::paste
void paste(int top, int left, const mat< T > &m)
paste matrix m at position: top, left
Definition: mat.h:875
cgv::math::dyad
fmat< T, N, M > dyad(const fvec< T, N > &v, const fvec< S, M > &w)
returns the outer product of vector v and w
Definition: fmat.h:248
cgv::math::mat::resize
void resize(unsigned rows, unsigned cols)
resize the matrix, the content of the matrix will be destroyed
Definition: mat.h:575
cgv::math::mat::swap_diagonal_elements
void swap_diagonal_elements(unsigned i, unsigned j)
exchange diagonal elements (i,i) (j,j)
Definition: mat.h:902
cgv::math::mat::operator-
const mat< T > operator-(const mat< S > m2) const
matrix subtraction
Definition: mat.h:745
cgv::math::mat::copy
void copy(unsigned top, unsigned left, unsigned rows, unsigned cols, mat< T > &submat) const
copy submatrix m(top,left)...m(top+rows,left+cols) into submat
Definition: mat.h:863
cgv::math::mat::mat
mat(unsigned nrows, unsigned ncols, const T &c)
construct a matrix with all elements set to c
Definition: mat.h:477
cgv::math::mat::zeros
void zeros(unsigned rows, unsigned cols)
resize and fill matrix with zeros
Definition: mat.h:1022
cgv::math::ceil
fvec< T, N > ceil(const fvec< T, N > &v)
apply ceil function component wise to vector
Definition: fvec.h:326
cgv::math::mat::set_col
void set_col(unsigned j, const vec< T > &v)
set column j of the matrix to vector v
Definition: mat.h:852
cgv::math::mat::identity
void identity()
set identity matrix
Definition: mat.h:999
cgv::math::mat::_nrows
unsigned _nrows
number of rows
Definition: mat.h:216
cgv::math::mat::mat
mat(unsigned nrows, unsigned ncols, const T *marray, bool column_major=true)
Definition: mat.h:487
cgv::math::mat::operator!=
bool operator!=(const mat< S > &m) const
test for inequality
Definition: mat.h:636
cgv::math::mat::frobenius_norm
T frobenius_norm() const
returns the frobenius norm of matrix m
Definition: mat.h:987
cgv::math::operator>>
std::istream & operator>>(std::istream &in, diag_mat< T > &m)
input of a diagonal matrix from an istream
Definition: diag_mat.h:453
cgv::math::vec::zeros
void zeros()
fill the vector with zeros
Definition: vec.h:531
cgv::math::mat::sub_mat
mat< T > sub_mat(unsigned top, unsigned left, unsigned rows, unsigned cols) const
create submatrix m(top,left)...m(top+rows,left+cols)
Definition: mat.h:803
cgv::math::mat::identity
void identity(unsigned dim)
set dim x dim identity matrix
Definition: mat.h:1008
cgv::math::mat::nrows
unsigned nrows() const
number of rows
Definition: mat.h:541
cgv::math::mat::is_square
bool is_square() const
returns true if matrix is a square matrix
Definition: mat.h:597
cgv::math::mat::operator*
const vec< T > operator*(const vec< S > &v) const
matrix vector multiplication
Definition: mat.h:789
cgv::math::mat::operator*
const mat< T > operator*(const T &s) const
scalar multiplication
Definition: mat.h:653
cgv::math::mat::operator-
const mat< T > operator-() const
negation operator
Definition: mat.h:707
cgv::math::mat::operator+=
mat< T > & operator+=(const T &s)
in place addition by a scalar
Definition: mat.h:677
cgv::math::mat::fill
void fill(const S &v)
fills all elements of the matrix with v
Definition: mat.h:604
cgv::math::mat::set_row
void set_row(unsigned i, const vec< T > &v)
set row i of the matrix to vector v
Definition: mat.h:829
cgv::math::mat::trace
T trace() const
returns the trace
Definition: mat.h:912
cgv::math::mat::set_extern_data
void set_extern_data(unsigned nrows, unsigned ncols, T *data)
set data pointer to an external data array
Definition: mat.h:524
cgv::math::mat::_data
vec< T > _data
pointer to data storage
Definition: mat.h:212
cgv::math::mat::row
const vec< T > row(unsigned i) const
extract a row from the matrix as a vector
Definition: mat.h:816
cgv::math::mat::ncols
unsigned ncols() const
number of columns
Definition: mat.h:547
cgv
the cgv namespace
Definition: vr_calib.cxx:9
cgv::math::mat::operator/
const mat< T > operator/(const T &s) const
division by a scalar
Definition: mat.h:668
cgv::math::mat::swap_columns
void swap_columns(unsigned i, unsigned j)
exchange column i with column j
Definition: mat.h:893
cgv::math::mat::operator+
const mat< T > operator+(const T &s)
componentwise addition of a scalar
Definition: mat.h:684
cgv::math::mat::operator()
T & operator()(unsigned i, unsigned j)
access to the element in the ith row in column j
Definition: mat.h:611
cgv::math::mat::mat
mat(unsigned nrows, unsigned ncols)
constructor creates a nrows x ncols full matrix
Definition: mat.h:470