DMRITool  v0.1.1-139-g860d86b4
Diffusion MRI Tool
utlVNLLapack.h
Go to the documentation of this file.
1 
18 #ifndef __utlVNLLapack_h
19 #define __utlVNLLapack_h
20 
21 
22 #include "utlCore.h"
23 #include "utlVNL.h"
24 #include "utlLapack.h"
25 #include "utlVNLBlas.h"
26 
27 namespace utl
28 {
29 
59 __utl_geev_Matrix(T, geev_VnlMatrix, vnl_matrix<T>, rows, cols, data_block, vnl_vector<T>, data_block, set_size);
60 
70 template <class T> inline void
71 syev_VnlMatrix ( const vnl_matrix<T>& mat, vnl_vector<T>& eigenValues, vnl_matrix<T>& eigenVectors)
72 {
73  utlException(mat.rows()!=mat.columns(), "The matrix should be symmetric");
74  char JOBZ='V', UPLO='U';
75  int N = mat.rows(),INFO=0, LWORK=-1;
76 
77  utl::MatrixCopy(mat, eigenVectors, 1.0, 'N');
78  eigenValues.set_size(N);
79  // T query;
80  // // utl::syev<T>(&JOBZ,&UPLO,&N,eigenVectors.data_block(), &N, eigenValues.data_block(),&query,&LWORK,&INFO);
81  // utl::syev<T>(LAPACK_ROW_MAJOR, JOBZ,UPLO,N,eigenVectors.data_block(), N, eigenValues.data_block(),query,LWORK,&INFO);
82  // LWORK=static_cast<int>(query);
83 
84  // T *const WORK = new T[LWORK];
85  // utl::syev<T>(&JOBZ,&UPLO,&N,eigenVectors.data_block(), &N, eigenValues.data_block(),WORK,&LWORK,&INFO);
86  // delete[] WORK;
87  // utlGlobalException(INFO, "LAPACK library function dsyev_() returned error code INFO=" << INFO);
88 
89  INFO = utl::syev<T>(LAPACK_COL_MAJOR, JOBZ,UPLO,N,eigenVectors.data_block(), N, eigenValues.data_block());
90  utlGlobalException(INFO, "LAPACK library function dsyev_() returned error code INFO=" << INFO);
91 }
92 
102 template <class T> inline void
103 syevd_VnlMatrix ( const vnl_matrix<T>& mat, vnl_vector<T>& eigenValues, vnl_matrix<T>& eigenVectors)
104 {
105  utlException(mat.rows()!=mat.columns(), "The matrix should be symmetric");
106  char JOBZ='V', UPLO='U';
107  int N = mat.rows(),INFO=0, LWORK=-1, LIWORK=-1;
108 
109  utl::MatrixCopy(mat, eigenVectors, 1.0, 'N');
110  eigenValues.set_size(N);
111 
112  // T query;
113  // int queryI;
114  // utl::syevd<T>(&JOBZ,&UPLO,&N,eigenVectors.data_block(), &N, eigenValues.data_block(),&query,&LWORK,&queryI,&LIWORK,&INFO);
115  // LWORK=static_cast<int>(query);
116  // LIWORK=static_cast<int>(queryI);
117 
118  // T *const WORK = new T[LWORK];
119  // int *const IWORK = new int[LIWORK];
120  // utl::syevd<T>(&JOBZ,&UPLO,&N,eigenVectors.data_block(), &N, eigenValues.data_block(),WORK,&LWORK,IWORK,&LIWORK,&INFO);
121  // delete[] WORK;
122  // delete[] IWORK;
123  // utlGlobalException(INFO, "LAPACK library function dsyevd_() returned error code INFO=" << INFO);
124 
125  INFO = utl::syevd<T>(LAPACK_COL_MAJOR, JOBZ,UPLO,N,eigenVectors.data_block(), N, eigenValues.data_block());
126  utlGlobalException(INFO, "LAPACK library function dsyevd_() returned error code INFO=" << INFO);
127 }
128 
129 
139 template <class T> inline void
140 gesvd_VnlMatrix(const vnl_matrix<T>& mat, vnl_matrix<T>& U, vnl_vector<T>& s, vnl_matrix<T>& V, char format='S' )
141 {
142  utlException(format!='S' && format!='A', "wrong format. format should be 'A' or 'S' ");
143  int M=mat.rows(), N=mat.columns(), INFO=0;
144  int min_MN = utl::min(M,N), LDVT;
145  s.set_size(min_MN);
146  if (format=='S')
147  {
148  U.set_size(min_MN, M);
149  V.set_size(N, min_MN);
150  LDVT = min_MN;
151  }
152  else
153  {
154  U.set_size(M, M);
155  V.set_size(N, N);
156  LDVT = N;
157  }
158  char formatU=format, formatV=format;
159  int LDA=M, LDU=M, LWORK=-1;
160  vnl_matrix<T> matTmp;
161  utl::MatrixCopy(mat, matTmp, 1.0, 'T');
162 
163  // T query;
164  // // dgesdd_(&format, &M, &N, matTmp.data_block(), &LDA, s.data_block(), U.data_block(), &LDU, V.data_block(), &LDVT, &query, &LWORK, IWORK, &INFO);
165  // utl::gesvd<T>(&formatU, &formatV, &M, &N, matTmp.data_block(), &LDA, s.data_block(), U.data_block(), &LDU, V.data_block(), &LDVT, &query, &LWORK, &INFO);
166  // LWORK=static_cast<int>(query);
167 
168  // T* WORK = new T[LWORK];
169  // // dgesdd_(&format, &M, &N, matTmp.data_block(), &LDA, s.data_block(), U.data_block(), &LDU, V.data_block(), &LDVT, WORK, &LWORK, IWORK, &INFO);
170  // utl::gesvd<T>(&formatU, &formatV, &M, &N, matTmp.data_block(), &LDA, s.data_block(), U.data_block(), &LDU, V.data_block(), &LDVT, WORK, &LWORK, &INFO);
171  // delete[] WORK;
172 
173  T* superb = new T[min_MN];
174  INFO=utl::gesvd<T>(LAPACK_COL_MAJOR, formatU, formatV, M, N, matTmp.data_block(), LDA, s.data_block(), U.data_block(), LDU, V.data_block(), LDVT, superb);
175  delete[] superb;
176  U.inplace_transpose();
177 
178  utlGlobalException(INFO, "LAPACK library function dgesvd_() returned error code INFO=" << INFO);
179 }
180 
193 template <class T> inline void
194 gesdd_VnlMatrix(const vnl_matrix<T>& mat, vnl_matrix<T>& U, vnl_vector<T>& s, vnl_matrix<T>& V, char format='S' )
195 {
196  utlException(format!='S' && format!='A', "wrong format. format should be 'A' or 'S' ");
197  int M=mat.rows(), N=mat.columns(), INFO=0;
198  int min_MN = utl::min(M,N), LDVT;
199  s.set_size(min_MN);
200  if (format=='S')
201  {
202  U.set_size(min_MN, M);
203  V.set_size(N, min_MN);
204  LDVT = min_MN;
205  }
206  else
207  {
208  U.set_size(M, M);
209  V.set_size(N, N);
210  LDVT = N;
211  }
212 
213  vnl_matrix<T> matTmp;
214  utl::MatrixCopy(mat, matTmp, 1.0, 'T');
215  char formatU=format, formatV=format;
216  int LDA=M, LDU=M, LWORK;
217 
218  // int* IWORK = new int[8*min_MN];
219  // T query;
220  // LWORK=-1;
221  // utl::gesdd<T>(&format, &M, &N, matTmp.data_block(), &LDA, s.data_block(), U.data_block(), &LDU, V.data_block(), &LDVT, &query, &LWORK, IWORK, &INFO);
222  // // dgesvd_(&formatU, &formatV, &M, &N, matTmp.data_block(), &LDA, s.data_block(), U.data_block(), &LDU, V.data_block(), &LDVT, &query, &LWORK, &INFO);
223  // LWORK=static_cast<int>(query);
224 
225  // // LWORK = min_MN*(6+4*min_MN)+utl::max(M,N);
226  // T* WORK = new T[LWORK];
227  // utl::gesdd<T>(&format, &M, &N, matTmp.data_block(), &LDA, s.data_block(), U.data_block(), &LDU, V.data_block(), &LDVT, WORK, &LWORK, IWORK, &INFO);
228  // // dgesvd_(&formatU, &formatV, &M, &N, matTmp.data_block(), &LDA, s.data_block(), U.data_block(), &LDU, V.data_block(), &LDVT, WORK, &LWORK, &INFO);
229  // delete[] WORK;
230  // delete[] IWORK;
231 
232  INFO=utl::gesdd<T>(LAPACK_COL_MAJOR, format, M, N, matTmp.data_block(), LDA, s.data_block(), U.data_block(), LDU, V.data_block(), LDVT);
233  U.inplace_transpose();
234 
235  utlGlobalException(INFO, "LAPACK library function dgesdd_() returned error code INFO=" << INFO);
236 }
237 
238 
239 
248 template <class T> inline void
249 EigenDecompositionSymmetricVnlMatrix ( const vnl_matrix<T>& mat, vnl_vector<T>& eigenValues, vnl_matrix<T>& eigenVectors )
250 {
251 #ifdef UTL_USE_FASTLAPACK
252  // NOTE: fast but may be wrong for big matrix and multi-thread if openblas is not correctly built
253  syevd_VnlMatrix<T>(mat, eigenValues, eigenVectors);
254 #else
255  // slow but robust
256  syev_VnlMatrix<T>(mat, eigenValues, eigenVectors);
257 #endif
258 }
259 
269 template <class T> inline void
270 SVDVnlMatrix ( const vnl_matrix<T>& mat, vnl_matrix<T>& U, vnl_vector<T>& s, vnl_matrix<T>& V, char format='S' )
271 {
272 #ifdef UTL_USE_FASTLAPACK
273  // NOTE: fast but may be wrong for big matrix and multi-thread if openblas is not correctly built
274  utl::gesdd_VnlMatrix<T>(mat, U, s, V, format);
275 #else
276  // slow but robust
277  utl::gesvd_VnlMatrix<T>(mat, U, s, V, format);
278 #endif
279 }
280 
283 template <class T> inline void
284 InverseSymmericVnlMatrix( const vnl_matrix<T>& mat, vnl_matrix<T>& result, const T eps=1e-8 )
285 {
286  int n = mat.rows();
287  utl::MatrixCopy(mat, result, 1.0, 'N');
288 
289  char uplo='U';
290  int lwork=-1, INFO=0;
291  int* ipiv= new int[n];
292 
293  // T *query, *work;
294  // query = new T[1];
295  // utl::sytrf<T>(&uplo,&n,result.data_block(),&n,ipiv,query,&lwork,&INFO);
296  // lwork=static_cast<INTT>(*query);
297  // delete[] query;
298  // work = new T[lwork];
299  // utl::sytrf<T>(&uplo,&n,result.data_block(),&n,ipiv,work,&lwork,&INFO);
300  // delete[] work;
301  // work = new T[2*n];
302  // utl::sytri<T>(&uplo,&n,result.data_block(),&n,ipiv,work,&INFO);
303  // delete[] work;
304 
305  utl::sytrf<T>(LAPACK_COL_MAJOR, uplo,n,result.data_block(),n,ipiv);
306  INFO=utl::sytri<T>(LAPACK_COL_MAJOR, uplo,n,result.data_block(),n,ipiv);
307  delete[] ipiv;
308 
309  utlGlobalException(INFO>0, "The matrix is singular and its inverse could not be computed. \
310  LAPACK library function sytrid_() returned error code INFO=" << INFO);
311  utlGlobalException(INFO<0, "LAPACK library function sytrid_() returned error code INFO=" << INFO);
312 
313  T* data = result.data_block();
314  for ( int i = 0; i < n; ++i )
315  for ( int j = 0; j < i; ++j )
316  data[j*n+i] = data[i*n+j];
317 }
318 
320 template <class T> inline void
321 PInverseSymmericVnlMatrix( const vnl_matrix<T>& mat, vnl_matrix<T>& result, const T eps=1e-8 )
322 {
323  int N = mat.rows();
324  vnl_matrix<T> eigenVectors, tmp, S(N,N,0.0);
325  vnl_vector<T> eigenValues, v;
326  EigenDecompositionSymmetricVnlMatrix(mat, eigenValues, eigenVectors);
327  for (unsigned i=0; i<N; ++i)
328  {
329  if ( eigenValues[i]>eps || eigenValues[i]<-eps )
330  S(i,i) = 1.0/eigenValues[i];
331  else
332  S(i,i)=0.0;
333  }
334  utl::ProductVnlMtM(eigenVectors, S, tmp);
335  utl::ProductVnlMM(tmp, eigenVectors, result);
336 }
337 
339 template <class T> inline void
340 PInverseVnlMatrix( const vnl_matrix<T>& mat, vnl_matrix<T>& result, const T eps=1e-8 )
341 {
342  vnl_matrix<T> U,V, tmp;
343  vnl_vector<T> S, uVec, vVec;
344  SVDVnlMatrix(mat, U, S, V, 'S');
345 
346  vnl_matrix<T> diag(S.size(), S.size(),0.0);
347  for ( int i = 0; i < S.size(); i += 1 )
348  {
349  if ( S[i]>eps || S[i]<-eps )
350  diag(i,i) = 1.0/S[i];
351  else
352  diag(i,i) = 0.0;
353  }
354  utl::ProductVnlMM(V, diag, tmp);
355  utl::ProductVnlMMt(tmp, U, result);
356 
357  // result.set_size(mat.cols(), mat.rows());
358  // result.fill(0.0);
359  // vnl_vector<T> vV(V.rows()), vU(U.cols());
360  // for ( int i = 0; i < S.size(); ++i )
361  // {
362  // if ( S[i]>eps || S[i]<-eps )
363  // {
364  // utl::GetColumn(V,i,vV);
365  // utl::GetColumn(U,i,vU);
366  // utl::OuterProductvv(vV, vU, result, 1.0/S[i]);
367  // }
368  // }
369 }
370 
372 template <class T>
373 void
374 GetEqualityConstraintProjection ( const vnl_matrix<T>& Aeq, const vnl_vector<T>& beq, const vnl_matrix<T>& QInverse,
375  vnl_matrix<T>& projMatrix, vnl_vector<T>& projVector )
376 {
377  int n = QInverse.rows();
378  utlException(Aeq.rows()!=n, "wrong size! Aeq.rows()="<<Aeq.rows()<<", n="<<n);
379  vnl_matrix<T> AeqT=Aeq.transpose();
380  projMatrix.set_size(n,n);
381  projMatrix.set_identity();
382  vnl_matrix<T> temp, tmp2, tmp3;
383  ProductVnlMM(AeqT, QInverse, Aeq, tmp2);
384  PInverseSymmericVnlMatrix(tmp2, temp);
385  ProductVnlMM( QInverse, Aeq, temp, tmp2);
386  ProductVnlMM( tmp2, AeqT, tmp3);
387  projMatrix -= tmp3;
388 
389  ProductVnlMv( tmp2, beq, projVector);
390 }
393 }
394 
395 
396 #endif
void EigenDecompositionSymmetricVnlMatrix(const vnl_matrix< T > &mat, vnl_vector< T > &eigenValues, vnl_matrix< T > &eigenVectors)
EigenDecompositionSymmetricVnlMatrix eigen-decomposition for symmetric matrix.
Definition: utlVNLLapack.h:249
#define __utl_geev_Matrix(T, FuncName, RowMajorMatrixName, GetRowsFuncName, GetColsFuncName, MatrixGetDataFuncName, VectorName, VectorGetDataFuncName, ReSizeFuncName)
geev_VnlMatrix Calculate non-symmetric eigen-decomposition. Define 3 functions. 1) calculate only eig...
Definition: utlLapack.h:355
void geev_VnlMatrix(const vnl_matrix< T > &mat, vnl_vector< T > &valReal, vnl_vector< T > &valImg, vnl_matrix< T > &vecRealR, vnl_matrix< T > &vecImgR, vnl_matrix< T > &vecRealL, vnl_matrix< T > &vecImgL)
geev_VnlMatrix calculate non-symmetric eigen-decomposition.
Definition: utlVNLLapack.h:59
void PInverseSymmericVnlMatrix(const vnl_matrix< T > &mat, vnl_matrix< T > &result, const T eps=1e-8)
Definition: utlVNLLapack.h:321
#define utlException(cond, expout)
Definition: utlCoreMacro.h:548
void gesdd_VnlMatrix(const vnl_matrix< T > &mat, vnl_matrix< T > &U, vnl_vector< T > &s, vnl_matrix< T > &V, char format='S')
dgesdd_VnlMatrix dgesdd is faster than dgesvd. http://www.netlib.org/lapack/explore-html/db/db4/dgesd...
Definition: utlVNLLapack.h:194
void PInverseVnlMatrix(const vnl_matrix< T > &mat, vnl_matrix< T > &result, const T eps=1e-8)
Definition: utlVNLLapack.h:340
void MatrixCopy(const vnl_matrix< T > &mat, vnl_matrix< T > &matOut, const T alpha, const char trans='N')
MatrixCopy. A := alpha * op(A)
Definition: utlVNLBlas.h:45
const T & min(const T &a, const T &b)
Return the minimum between a and b.
Definition: utlCore.h:257
void ProductVnlMv(const vnl_matrix< T > &A, const vnl_vector< T > &b, vnl_vector< T > &c, const double alpha=1.0, const double beta=0.0)
Definition: utlVNLBlas.h:140
#define utlGlobalException(cond, expout)
Definition: utlCoreMacro.h:372
Definition: utl.h:90
void InverseSymmericVnlMatrix(const vnl_matrix< T > &mat, vnl_matrix< T > &result, const T eps=1e-8)
Definition: utlVNLLapack.h:284
void syevd_VnlMatrix(const vnl_matrix< T > &mat, vnl_vector< T > &eigenValues, vnl_matrix< T > &eigenVectors)
syevd_VnlMatrix eigen-decomposition for symmetric matrix. dsyevd is faster than dsyev http://www...
Definition: utlVNLLapack.h:103
void syev_VnlMatrix(const vnl_matrix< T > &mat, vnl_vector< T > &eigenValues, vnl_matrix< T > &eigenVectors)
syev_VnlMatrix eigen-decomposition for symmetric matrix. http://www.netlib.org/lapack/explore-html/dd...
Definition: utlVNLLapack.h:71
void GetEqualityConstraintProjection(const NDArray< T, 2 > &Aeq, const NDArray< T, 1 > &beq, const NDArray< T, 2 > &QInverse, NDArray< T, 2 > &projMatrix, NDArray< T, 1 > &projVector)
void ProductVnlMMt(const vnl_matrix< T > &A, const vnl_matrix< T > &B, vnl_matrix< T > &C, const double alpha=1.0, const double beta=0.0)
Definition: utlVNLBlas.h:117
void gesvd_VnlMatrix(const vnl_matrix< T > &mat, vnl_matrix< T > &U, vnl_vector< T > &s, vnl_matrix< T > &V, char format='S')
dgesvd_VnlMatrix
Definition: utlVNLLapack.h:140
void ProductVnlMM(const vnl_matrix< T > &A, const vnl_matrix< T > &B, vnl_matrix< T > &C, const double alpha=1.0, const double beta=0.0)
Definition: utlVNLBlas.h:117
help functions for VNL
void ProductVnlMtM(const vnl_matrix< T > &A, const vnl_matrix< T > &B, vnl_matrix< T > &C, const double alpha=1.0, const double beta=0.0)
Definition: utlVNLBlas.h:117
void SVDVnlMatrix(const vnl_matrix< T > &mat, vnl_matrix< T > &U, vnl_vector< T > &s, vnl_matrix< T > &V, char format='S')
SVDVnlMatrix.
Definition: utlVNLLapack.h:270