NPL
Neurological Programs and Libraries
matrix_deprecated.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2014 Micah C Chambers (micahc.vt@gmail.com)
3  *
4  * NPL is free software: you can redistribute it and/or modify it under the
5  * terms of the BSD 2-Clause License available in LICENSE or at
6  * http://opensource.org/licenses/BSD-2-Clause
7  *
8  * @file matrix.h
9  *
10  *****************************************************************************/
11 
12 #ifndef MATRIX_H
13 #define MATRIX_H
14 
15 #include <iostream>
16 #include <vector>
17 #include <iomanip>
18 #include <cassert>
19 #include <cstddef>
20 #include <cmath>
21 #include <memory>
22 
23 namespace npl {
24 
25 class MatrixP
26 {
27 public:
35  virtual double& operator[](size_t row) = 0;
36 
45  virtual double& operator()(size_t row, size_t col = 0) = 0;
46 
54  virtual const double& operator[](size_t row) const = 0;
55 
64  virtual const double& operator()(size_t row, size_t col = 0) const = 0;
65 
75  virtual void mvproduct(const MatrixP* rhs, MatrixP* out) const = 0;
76 
86  virtual void mvproduct(const MatrixP& rhs, MatrixP& out) const = 0;
87 // virtual void mvproduct(const std::vector<double>& rhs,
88 // std::vector<double>& out) const = 0;
89 // virtual void mvproduct(const std::vector<size_t>& rhs,
90 // std::vector<double>& out) const = 0;
91 
92  virtual double det() const = 0;
93  virtual double norm() const = 0;
94  virtual double sum() const = 0;
95  virtual size_t rows() const = 0;
96  virtual size_t cols() const = 0;
97 
98  bool operator==(const MatrixP& rhs) {
99  if(rows() != rhs.rows())
100  return false;
101  if(cols() != rhs.cols())
102  return false;
103  for(size_t rr=0; rr<rows(); rr++) {
104  for(size_t cc=0; cc<cols(); cc++) {
105  if(rhs(rr,cc) != (*this)(rr,cc))
106  return false;
107  }
108  }
109  return true;
110  }
111 
112  bool operator!=(const MatrixP& rhs) {
113  return !(*this == rhs);
114  }
115 };
116 
117 
118 template <int D1, int D2>
119 class Matrix : public virtual MatrixP
120 {
121 public:
122 
126  Matrix() {
127  for(size_t ii=0; ii<D1; ii++) {
128  for(size_t jj=0; jj<D2; jj++) {
129  data[ii][jj] = (ii==jj);
130  }
131  }
132  };
133 
134 
140  Matrix(double v) {
141  for(size_t ii=0; ii<D1; ii++) {
142  for(size_t jj=0; jj<D2; jj++) {
143  data[ii][jj] = v;
144  }
145  }
146  };
147 
155  Matrix(size_t l, const double* v) {
156  size_t kk=0;
157  for(size_t ii=0; ii<D1; ii++) {
158  for(size_t jj=0; jj<D2; jj++) {
159  if(kk < l)
160  data[ii][jj] = v[kk++];
161  else
162  data[ii][jj] = 0;
163  }
164  }
165  };
166 
174  Matrix(size_t l, const int64_t* v) {
175  size_t kk=0;
176  for(size_t ii=0; ii<D1; ii++) {
177  for(size_t jj=0; jj<D2; jj++) {
178  if(kk < l)
179  data[ii][jj] = v[kk++];
180  else
181  data[ii][jj] = 0;
182  }
183  }
184  };
185 
192  Matrix(std::initializer_list<double> v) {
193  auto it = v.begin();
194  for(size_t ii=0; ii<D1; ii++) {
195  for(size_t jj=0; jj<D2; jj++) {
196  if(it != v.end()) {
197  data[ii][jj] = *it;
198  it++;
199  } else {
200  data[ii][jj] = 0;
201  }
202  }
203  }
204  };
205 
212  Matrix(const std::vector<double>& v) {
213  size_t kk=0;
214  for(size_t ii=0; ii<D1; ii++) {
215  for(size_t jj=0; jj<D2; jj++) {
216  if(kk < v.size())
217  data[ii][jj] = v[kk++];
218  else
219  data[ii][jj] = 0;
220  }
221  }
222  };
223 
230  Matrix(const std::vector<size_t>& v) {
231  size_t kk=0;
232  for(size_t ii=0; ii<D1; ii++) {
233  for(size_t jj=0; jj<D2; jj++) {
234  if(kk < v.size())
235  data[ii][jj] = v[kk++];
236  else
237  data[ii][jj] = 0;
238  }
239  }
240  };
241 
248  Matrix(const std::vector<int64_t>& v) {
249  size_t kk=0;
250  for(size_t ii=0; ii<D1; ii++) {
251  for(size_t jj=0; jj<D2; jj++) {
252  if(kk < v.size())
253  data[ii][jj] = v[kk++];
254  else
255  data[ii][jj] = 0;
256  }
257  }
258  };
259 
265  Matrix(const Matrix& m)
266  {
267  for(size_t ii=0; ii<D1; ii++) {
268  for(size_t jj=0; jj<D2; jj++) {
269  data[ii][jj] = m.data[ii][jj];
270  }
271  }
272  }
273 
281  double& operator[](size_t row)
282  {
283  assert(row < D1);
284  return data[row][0];
285  };
286 
295  double& operator()(size_t row, size_t col = 0)
296  {
297  assert(row < D1 && col < D2);
298  return data[row][col];
299  };
300 
308  const double& operator[](size_t row) const
309  {
310  assert(row < D1);
311  return data[row][0];
312  };
313 
322  const double& operator()(size_t row, size_t col = 0) const
323  {
324  assert(row < D1 && col < D2);
325  return data[row][col];
326  };
327 
328 
338  void mvproduct(const MatrixP* rhs, MatrixP* out) const;
339 
349  void mvproduct(const MatrixP& rhs, MatrixP& out) const;
350 
351 // void mvproduct(const std::vector<double>& rhs,
352 // std::vector<double>& out) const;
353 // void mvproduct(const std::vector<size_t>& rhs,
354 // std::vector<double>& out) const;
355 
356  virtual double det() const;
357  virtual double norm() const;
358  virtual double sum() const;
359 
360  size_t rows() const {return D1;};
361  size_t cols() const {return D2;};
362 private:
363  double data[D1][D2];
364 };
365 
366 //double det(const Matrix<1, 1>& trg);
367 //double det(const Matrix<2, 2>& trg);
368 //template <int D1, int D2>
369 //double det(const Matrix<D1, D2>& trg);
370 //Matrix<1, 1> inverse(const Matrix<1, 1>& trg);
371 //Matrix<2, 2> inverse(const Matrix<2, 2>& trg);
372 //template <int DIM>
373 //Matrix<DIM, DIM> inverse(const Matrix<DIM, DIM>& trg);
374 //
375 
376 template <int D1, int D2>
377 void Matrix<D1,D2>::mvproduct(const MatrixP* rhs, MatrixP* out) const
378 {
379  assert(rhs != out);
380  try{
381  const Matrix<D2,1>& iv = dynamic_cast<const Matrix<D2, 1>&>(*rhs);
382  Matrix<D1,1>& ov = dynamic_cast<Matrix<D1, 1>&>(*out);
383  const Matrix<D1,D2>& m = *this;
384  for(size_t ii=0; ii<D1; ii++) {
385  ov[ii] = 0;
386  for(size_t jj=0; jj<D2; jj++) {
387  ov[ii] += m(ii,jj)*iv[jj];
388  }
389  }
390  } catch(...){
391  std::cerr << "Error, failed dynamic_cast for matrix-vector product"
392  " check the input to mvproduct matrix.h:" << __LINE__ << std::endl;
393  throw;
394  }
395 }
396 
397 template <int D1, int D2>
398 void Matrix<D1,D2>::mvproduct(const MatrixP& rhs, MatrixP& out) const
399 {
400  assert(&rhs != &out);
401  try{
402  const Matrix<D2,1>& iv = dynamic_cast<const Matrix<D2, 1>&>(rhs);
403  Matrix<D1,1>& ov = dynamic_cast<Matrix<D1, 1>&>(out);
404  const Matrix<D1,D2>& m = *this;
405  for(size_t ii=0; ii<D1; ii++) {
406  ov[ii] = 0;
407  for(size_t jj=0; jj<D2; jj++) {
408  ov[ii] += m(ii,jj)*iv[jj];
409  }
410  }
411  } catch(...){
412  std::cerr << "Error, failed dynamic_cast for matrix-vector product"
413  " check the input to mvproduct matrix.h:" << __LINE__ << std::endl;
414  throw;
415  }
416 }
417 //
418 //template <int D1, int D2>
419 //void Matrix<D1,D2>::mvproduct(const std::vector<double>& iv,
420 // std::vector<double>& ov) const
421 //{
422 // assert(&iv != &ov);
423 // assert(iv.size() == D2);
424 // ov.resize(D1);
425 // const Matrix<D1,D2>& m = *this;
426 //
427 // for(size_t ii=0; ii<D1; ii++) {
428 // ov[ii] = 0;
429 // for(size_t jj=0; jj<D2; jj++) {
430 // ov[ii] += m(ii,jj)*iv[jj];
431 // }
432 // }
433 //}
434 //
435 //template <int D1, int D2>
436 //void Matrix<D1,D2>::mvproduct(const std::vector<size_t>& iv,
437 // std::vector<double>& ov) const
438 //{
439 // assert(iv.size() == D2);
440 // ov.resize(D1);
441 // const Matrix<D1,D2>& m = *this;
442 //
443 // for(size_t ii=0; ii<D1; ii++) {
444 // ov[ii] = 0;
445 // for(size_t jj=0; jj<D2; jj++) {
446 // ov[ii] += m(ii,jj)*iv[jj];
447 // }
448 // }
449 //}
450 //
451 template <int D1, int D2>
452 std::ostream& operator<<(std::ostream& os, const Matrix<D1,D2>& b)
453 {
454  for(size_t rr=0; rr<b.rows(); rr++) {
455  os << "[ ";
456  for(size_t cc=0; cc<b.cols(); cc++) {
457  os << std::setw(11) << std::setprecision(5) << b(rr,cc);
458  }
459  os << " ];" << std::endl;
460  }
461  os << std::endl;
462  return os;
463 }
464 
465 std::ostream& operator<<(std::ostream& os, const MatrixP& b)
466 {
467  for(size_t rr=0; rr<b.rows(); rr++) {
468  os << "[ ";
469  for(size_t cc=0; cc<b.cols(); cc++) {
470  os << std::setw(11) << std::setprecision(5) << b(rr,cc);
471  }
472  os << " ];" << std::endl;
473  }
474  os << std::endl;
475  return os;
476 }
477 
478 
479 template <int D1, int D2>
481 {
482  for(size_t ii=0; ii<D1; ii++) {
483  for(size_t jj=0; jj<D2; jj++) {
484  lhs(ii,jj) += rhs(ii,jj);
485  }
486  }
487  return lhs;
488 }
489 
490 template <int D1, int D2>
492 {
493  Matrix<D1, D2> out(0.0);
494  for(size_t ii=0; ii<D1; ii++) {
495  for(size_t jj=0; jj<D2; jj++) {
496  out(ii,jj) = lhs(ii,jj)+rhs(ii,jj);
497  }
498  }
499  return out;
500 }
501 
502 template <int D1, int D2>
504 {
505  Matrix<D1, D2> out(0.0);
506  for(size_t ii=0; ii<D1; ii++) {
507  for(size_t jj=0; jj<D2; jj++) {
508  out(ii,jj) = lhs(ii,jj)-rhs(ii,jj);
509  }
510  }
511  return out;
512 }
513 
514 template <int D1, int D2>
516 {
517  Matrix<D1, D2> out(0.0);
518  for(size_t ii=0; ii<D1; ii++) {
519  for(size_t jj=0; jj<D2; jj++) {
520  out(ii,jj) = -rhs(ii,jj);
521  }
522  }
523  return out;
524 }
525 
526 template <int D1, int D2, int D3>
528 {
529  Matrix<D1, D3> out(0.0);
530  for(size_t ii=0; ii<D1; ii++) {
531  for(size_t jj=0; jj<D3; jj++) {
532  out(ii,jj) = 0;
533  for(size_t kk=0; kk<D2; kk++) {
534  out(ii,jj) += lhs(ii, kk)*rhs(kk, jj);
535  }
536  }
537  }
538  return out;
539 }
540 
553 template <int D1, int D2>
555  const Matrix<D2, D1>& bl, const Matrix<D2,D2>& br)
556 {
558 
559  // top left
560  for(size_t rr=0; rr<D1; rr++) {
561  for(size_t cc=0; cc<D1; cc++) {
562  out(rr,cc) = tl(rr,cc);
563  }
564  }
565 
566  // top right
567  for(size_t rr=0; rr<D1; rr++) {
568  for(size_t cc=0; cc<D2; cc++) {
569  out(rr,cc+D1) = tr(rr,cc);
570  }
571  }
572 
573  // bottom left
574  for(size_t rr=0; rr<D2; rr++) {
575  for(size_t cc=0; cc<D1; cc++) {
576  out(rr+D1,cc) = bl(rr,cc);
577  }
578  }
579 
580  // bottom right
581  for(size_t rr=0; rr<D2; rr++) {
582  for(size_t cc=0; cc<D2; cc++) {
583  out(rr+D1,cc+D1) = br(rr,cc);
584  }
585  }
586 
587  return out;
588 }
589 
590 template <int D1, int D2>
591 void split(const Matrix<D1+D2, D1+D2>& input,
592  Matrix<D1,D1>& tl, Matrix<D1, D2>& tr,
593  Matrix<D2, D1>& bl, Matrix<D2,D2>& br)
594 {
595  // top left
596  for(size_t rr=0; rr<D1; rr++) {
597  for(size_t cc=0; cc<D1; cc++) {
598  tl(rr,cc) = input(rr,cc);
599  }
600  }
601 
602  // top right
603  for(size_t rr=0; rr<D1; rr++) {
604  for(size_t cc=0; cc<D2; cc++) {
605  tr(rr,cc)= input(rr, cc+D1);
606  }
607  }
608 
609  // bottom left
610  for(size_t rr=0; rr<D2; rr++) {
611  for(size_t cc=0; cc<D1; cc++) {
612  bl(rr,cc) = input(rr+D1,cc);
613  }
614  }
615 
616  // bottom right
617  for(size_t rr=0; rr<D2; rr++) {
618  for(size_t cc=0; cc<D2; cc++) {
619  br(rr,cc) = input(rr+D1,cc+D1);
620  }
621  }
622 }
623 
624 // Determinant //
625 double det(const Matrix<1, 1>& trg)
626 {
627  return trg(0,0);
628 }
629 
630 double det(const Matrix<2, 2>& trg)
631 {
632  return trg(0,0)*trg(1,1) - trg(1,0)*trg(0,1);
633 }
634 
635 double det(const Matrix<3, 3>& trg)
636 {
637  double a = trg(0,0);
638  double b = trg(0,1);
639  double c = trg(0,2);
640  double d = trg(1,0);
641  double e = trg(1,1);
642  double f = trg(1,2);
643  double g = trg(2,0);
644  double h = trg(2,1);
645  double i = trg(2,2);
646  return (a*e*i + b*f*g + c*d*h) - (c*e*g + b*d*i + a*f*h);
647 }
648 
649 template <int DIM>
650 double det(const Matrix<DIM, DIM>& trg)
651 {
652 
653  // break up into smaller matrices
654  Matrix<DIM/2,DIM/2> A;
655  Matrix<DIM/2,(DIM+1)/2> B;
656  Matrix<(DIM+1)/2,DIM/2> C;
657  Matrix<(DIM+1)/2,(DIM+1)/2> D;
658  split(trg, A, B, C, D);
659 
660  auto AI = inverse(A);
661  double a = det(A)*det(D-C*AI*B);
662 
663  if(std::isnan(a)) {
664  auto DI = inverse(D);
665  double b = det(D)*det(A-B*DI*C);
666  if(std::isnan(b)) {
667  std::cerr << "Determinant failed " << std::endl;
668  return NAN;
669  } else
670  return b;
671  } else
672  return a;
673 }
674 
675 template <int D1, int D2>
676 double norm(const Matrix<D1, D2>& trg)
677 {
678  (void)(trg);
679  throw std::length_error("Matrix Passed to Norm Function");
680  return 0;
681 }
682 
683 template <int DIM>
684 double norm(const Matrix<DIM, 1>& trg)
685 {
686  double sum = 0;
687  for(size_t ii=0; ii<DIM; ii++)
688  sum += trg[ii]*trg[ii];
689  return sqrt(sum);
690 }
691 
692 template <int DIM>
693 double norm(const Matrix<1, DIM>& trg)
694 {
695  double sum = 0;
696  for(size_t ii=0; ii<DIM; ii++)
697  sum += trg(0,ii)*trg(0,ii);
698  return sqrt(sum);
699 }
700 
701 template <int D1, int D2>
702 double Matrix<D1,D2>::norm() const
703 {
704  return npl::norm<D1,D2>(*this);
705 }
706 
707 template <int D1, int D2>
708 double Matrix<D1,D2>::det() const
709 {
710  const size_t DIM = D1 < D2 ? D1 : D2;
711  Matrix<DIM,DIM> tmp;
712  for(size_t ii=0;ii<DIM; ii++){
713  for(size_t jj=0;jj<DIM; jj++){
714  tmp(ii,jj) = data[ii][jj];
715  }
716  }
717 
718  return npl::det<DIM>(tmp);
719 }
720 
721 template <int D1, int D2>
722 double Matrix<D1,D2>::sum() const
723 {
724  double sum = 0;
725  for(size_t ii=0; ii<D1; ii++) {
726  for(size_t jj=0; jj<D2; jj++) {
727  sum+=data[ii][jj];
728  }
729  }
730 
731  return sum;
732 }
733 
734 
736 {
737  return Matrix<1,1>(1./trg(0,0));
738 }
739 
741 {
742  Matrix<2,2> tmp;
743  double det = trg(0,0)*trg(1,1)-trg(1,0)*trg(0,1);
744  if(det == 0) {
745  std::cerr << "Error non-invertible matrix!" << std::endl;
746  return Matrix<2,2>();
747  }
748 
749  tmp(0,0) = trg(1,1)/det;
750  tmp(1,1) = trg(0,0)/det;
751  tmp(1,0) = -trg(1,0)/det;
752  tmp(0,1) = -trg(0,1)/det;
753  return tmp;
754 }
755 
756 template <int DIM>
758 {
759 
760  // break up into smaller matrices
761  Matrix<DIM/2,DIM/2> A;
762  Matrix<DIM/2,(DIM+1)/2> B;
763  Matrix<(DIM+1)/2,DIM/2> C;
764  Matrix<(DIM+1)/2,(DIM+1)/2> D;
765  split(trg, A, B, C, D);
766 
767  auto AI = inverse(A);
768  auto betaI = inverse(D-C*AI*B);
769 
770  auto tl = AI + AI*B*betaI*C*AI;
771  auto tr = -AI*B*betaI;
772  auto bl = -betaI*C*AI;
773  auto br = betaI;
774 
775  auto ret = join(tl, tr, bl, br);
776 
777  return ret;
778 }
779 
780 } // npl
781 
782 #endif // MATRIX_H
const double & operator()(size_t row, size_t col=0) const
Returns value at given row/column.
Definition: accessors.h:29
virtual double norm() const
Matrix(const std::vector< int64_t > &v)
Initialize matrix with vector, any missing values will be assumed zero, extra values are ignored...
virtual double & operator[](size_t row)=0
Returns row in column 0.
double norm(const Matrix< D1, D2 > &trg)
Matrix< D1+D2, D1+D2 > join(const Matrix< D1, D1 > &tl, const Matrix< D1, D2 > &tr, const Matrix< D2, D1 > &bl, const Matrix< D2, D2 > &br)
Join together 4 matrices from a blockwise decomposition.
Matrix(const std::vector< double > &v)
Initialize matrix with vector, any missing values will be assumed zero, extra values are ignored...
virtual size_t cols() const =0
virtual double sum() const =0
Matrix< D1, D2 > operator+(const Matrix< D1, D2 > &lhs, const Matrix< D1, D2 > &rhs)
double & operator()(size_t row, size_t col=0)
Returns value at given row/column.
const double & operator[](size_t row) const
Returns row in column 0.
T iv
Definition: byteswap.h:212
Matrix(double v)
Constructor, sets the entire matrix to the given constant.
virtual void mvproduct(const MatrixP *rhs, MatrixP *out) const =0
Performs matrix-vector product of right hand side (rhs) and the current matrix, writing the result in...
virtual double & operator()(size_t row, size_t col=0)=0
Returns value at given row/column.
virtual size_t rows() const =0
std::ostream & operator<<(std::ostream &os, const Matrix< D1, D2 > &b)
double & operator[](size_t row)
Returns row in column 0.
virtual double sum() const
virtual double det() const
size_t rows() const
double det(const Matrix< 1, 1 > &trg)
Matrix< D1, D3 > operator*(const Matrix< D1, D2 > &lhs, const Matrix< D2, D3 > &rhs)
bool operator!=(const MatrixP &rhs)
virtual double norm() const =0
Matrix(size_t l, const int64_t *v)
Initialize a matrix from array of length l, made up of an array at v*. Missing values are assumed to ...
Matrix(std::initializer_list< double > v)
Initialize matrix with vector, any missing values will be assumed zero, extra values are ignored...
Matrix(size_t l, const double *v)
Initialize a matrix from array of length l, made up of an array at v*. Missing values are assumed to ...
void mvproduct(const MatrixP *rhs, MatrixP *out) const
Performs matrix-vector product of right hand side (rhs) and the current matrix, writing the result in...
Matrix(const Matrix &m)
Copy constructor, copies all the elements of the other vector.
Matrix(const std::vector< size_t > &v)
Initialize matrix with vector, any missing values will be assumed zero, extra values are ignored...
virtual double det() const =0
bool operator==(const MatrixP &rhs)
Matrix< 1, 1 > inverse(const Matrix< 1, 1 > &trg)
Matrix< D1, D2 > operator+=(Matrix< D1, D2 > &lhs, const Matrix< D1, D2 > &rhs)
void split(const Matrix< D1+D2, D1+D2 > &input, Matrix< D1, D1 > &tl, Matrix< D1, D2 > &tr, Matrix< D2, D1 > &bl, Matrix< D2, D2 > &br)
size_t cols() const
Matrix< D1, D2 > operator-(const Matrix< D1, D2 > &lhs, const Matrix< D1, D2 > &rhs)
Matrix()
Default constructor, sets the matrix to the identity matrix.