Structural deformable models
DMatrixLinAlg.h
Go to the documentation of this file.
1 #ifndef _DMATRIXLINALG_H_
2 #define _DMATRIXLINALG_H_
3 #include "DMatrix.h"
4 #include "DMatrixUtil.h"
5 #include <Eigen/SVD>
6 #include <Eigen/Dense>
7 #include <Eigen/Core>
8 #include <functional>
9 #include <algorithm>
10 #include <vector>
11 
12 #define DMLA_TAU 0.0000001f
13 
14 namespace dmutil {
15 
16  template<class T>
17  typename DMatrix<T>::EMT convert(const DMatrix<T>& dmat)
18  {
19  Eigen::Map<const typename DMatrix<T>::EMT> mat(&*dmat.getData().begin(), (int)dmat.sizeY(), (int)dmat.sizeX());
20  //typename DMatrix<T>::const_iterator dat = dmat.getData().begin();
21  //for(int k=dmat.size(); k>0; k--, dat++)
22  // mat << *dat;
23  //linalg::Matrix eth(mat);
24  // TODO: translate this code from LinAlg to Eigen
25  //for(register int i=eth.q_row_lwb(); i<=eth.q_row_upb(); i++)
26  // for(register int j=eth.q_col_lwb(); j<=eth.q_col_upb(); j++)
27  // eth(i,j) = dmat.at(j-1,i-1);
28 
29  return mat;
30  }
31 
32  template<class T>
33  DMatrix<T> convert(const typename DMatrix<T>::EMT& mat)
34  {
35  typename DMatrix<T>::EMT cmat(mat);
36  typename DMatrix<T>::EMT eth(cmat);
37  DMatrix<T> dmat(mat.cols(), mat.rows(), &mat(0));
38  // (eth.q_col_upb()-eth.q_col_lwb()+1, // TODO
39  // eth.q_row_upb()-eth.q_row_lwb()+1);
40  //typename DMatrix<T>::iterator dat = dmat.getData().begin();
41  //for(register int i=eth.q_row_lwb(); i<=eth.q_row_upb(); i++)
42  // for(register int j=eth.q_col_lwb(); j<=eth.q_col_upb(); j++)
43  // dmat.at(j-1,i-1) = eth(i,j);
44  return dmat;
45  }
46 
47  template<class T>
49  {
50  bool m_Verbose = false;
51  if(!dmat.empty()) {
52  try {
53  //if(!m_Verbose) freopen("/dev/null","a+",stderr);
54  typename DMatrix<T>::EMT mat = convert<T>(dmat);
55  //dmat = convert<T>(linalg::inverse(mat)); // TODO
56  dmat = convert<T>(mat.inverse());
57  } catch(void*)
58  {
59  //if(!m_Verbose) freopen("/dev/stdout","a+",stderr);
60  }
61  //if(!m_Verbose) freopen("/dev/stdout","a+",stderr);
62  }
63  return dmat;
64  }
65 
66  template<class T>
68  {
69  DMatrix<T> imat(dmat);
70  return invert(imat);
71  }
72 
73  template<class T>
74  bool SVD(const DMatrix<T>& dmat,
75  DMatrix<T>& mU, DMatrix<T>& mS, DMatrix<T>& mV)
76  {
77  using namespace Eigen;
78  bool m_Verbose = false;
79  try {
80  //if(!m_Verbose) freopen("/dev/null","a+",stderr);
81  // zeropad matrix to make enough rows
82  // (rank doesn't matter for the algorithm)
83  int d = dmat.sizeX() - dmat.sizeY();
84  if(d<0) d=0;
85  typename DMatrix<T>::EMT mat =
86  convert<T>(DMatrix<T>(dmat.sizeX(), dmat.sizeY()+d,0.0f)
87  .setRange(0,0,dmat));
88  JacobiSVD<typename DMatrix<T>::EMT> svd( mat, ComputeThinU | ComputeThinV);
89  //linalg::SVD svd(mat); // TODO
90  //if(m_Verbose) cout << "condition number of matrix A " <<
91  // svd.q_cond_number() << endl;
92  //if(m_Verbose) cout << svd.q_U().q_nrows() << " rows" << endl;
93 
94  DMatrix<T> U = dmutil::convert<T>(svd.matrixU());
95  DMatrix<T> V = dmutil::convert<T>(svd.matrixV());
96  VectorXf sig(svd.singularValues());
97  DMatrix<T> S;
98  S.resize(V.sizeY(),U.sizeX(),T(0));
99  dword sxy = std::min(S.sizeX(),S.sizeY());
100  std::vector< std::pair<T,dword> > sdiag(sxy);
101  for(dword i=0; i<sxy; i++) {
102  S.at(i,i) = sig(i);
103  sdiag[i].first = sig(i);
104  sdiag[i].second = i;
105  }
106  mS = S; mU = U; mV = V;
107  //sort by diagonal of S
108  sort(sdiag.begin(), sdiag.end(), std::greater< std::pair<float,T> >());
109  DMatrix<T> colu(1,U.sizeY());
110  DMatrix<T> colv(1,V.sizeY());
111  for(dword i=0; i<sxy; i++) {
112  dword permi = sdiag[i].second;
113  if(permi != i) {
114  U.getRange(permi,0,colu);
115  mU.setCol(i, colu);
116  V.getRange(permi,0,colv);
117  mV.setCol(i, colv);
118  mS.at(i,i) = S.at(permi,permi);
119  }
120  }
121  } catch(void*)
122  {
123  //if(!m_Verbose) freopen("/dev/stdout","a+",stderr);
124  return false;
125  }
126  //if(!m_Verbose) freopen("/dev/stdout","a+",stderr);
127  return true;
128  }
129 
130  template<class T>
132  {
133  DMatrix<T> U,S,V;
134  if(dmutil::SVD(dmat, U,S,V)) {
135  //create an inverted S and skip the nearly-zero elements
136  //on the diagonal
137  dword sxy = std::min(S.sizeX(),S.sizeY());
138  for(dword i=0; i<sxy; i++)
139  if(S.at(i,i)>T(DMLA_TAU)) S.at(i,i) = T(1)/S.at(i,i);
140  else S.at(i,i) = 0;
141  S.transpose();
142  U.transpose();
143  DMatrix<T> P = V.mulRight(S.mulRight(U)); // actually V * S(+)*Ut
144  return P;
145  }
146  return dmat;
147  }
148 };
149 
150 
151 #undef DMLA_TAU
152 
153 #endif
#define DMLA_TAU
Definition: DMatrixLinAlg.h:12
MT & transpose()
Definition: DMatrix.h:260
DMatrix< T > inverse(const DMatrix< T > &dmat)
Definition: DMatrixLinAlg.h:67
DMatrix< T > pseudoInv(const DMatrix< T > &dmat)
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > EMT
Definition: DMatrix.h:20
bool empty() const
Definition: DMatrix.h:50
DMatrix< T > & invert(DMatrix< T > &dmat)
Definition: DMatrixLinAlg.h:48
DMatrix< T >::EMT convert(const DMatrix< T > &dmat)
Definition: DMatrixLinAlg.h:17
dword sizeX() const
Definition: DMatrix.h:42
bool SVD(const DMatrix< T > &dmat, DMatrix< T > &mU, DMatrix< T > &mS, DMatrix< T > &mV)
Definition: DMatrixLinAlg.h:74
MT & resize(dword _sx, dword _sy, const T &inival=T())
Definition: DMatrix.h:30
unsigned long dword
Definition: simpletypes.h:6
MT & setCol(dword col, MT &vec)
Definition: DMatrix.h:163
dword sizeY() const
Definition: DMatrix.h:43
T & at(dword x, dword y)
Definition: DMatrix.h:46
MT & getRange(dword ox, dword oy, MT &mat) const
Definition: DMatrix.h:197
std::vector< T > & getData()
Definition: DMatrix.h:48
MT mulRight(const MT &rhs) const
Definition: DMatrix.h:149