Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Lapack.cpp
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 #include "Lapack.hh"
27 #include <Base/Math/tnt/fortran.h>
28 #include <Base/Math/tnt/vec.h>
29 #include <Base/Math/tnt/fmat.h>
30 
31 #include <Base/Common/CompareFloatingPoint.hh>
32 
33 using namespace std;
34 
35 #ifdef BIAS_DEBUG
36 #include "SVD.hh"
37 #endif
38 
39 #define F77_DGEEV dgeev_
40 #define F77_DGELS dgels_
41 #define F77_DGESV dgesv_
42 #define F77_DGESVD dgesvd_
43 #define F77_DGGGLM dggglm_
44 #define F77_DSPEV dspev_
45 #define F77_DSYEV dsyev_
46 #define F77_DSYEVD dsyevd_
47 #define F77_SGGEV sggev_
48 
49 #ifdef WIN32
50 # define BIAS_LPK_INT long int
51 # define BIAS_LPK_CONST_INT const long int
52 #else // WIN32
53 # ifdef __APPLE__
54 # define BIAS_LPK_INT __CLPK_integer
55 # define BIAS_LPK_CONST_INT __CLPK_integer
56 # else // __APPLE__
57 # define BIAS_LPK_INT Fortran_integer
58 # define BIAS_LPK_CONST_INT const Fortran_integer
59 # endif // __APPLE__
60 #endif // WIN32
61 
62 
63 #ifdef WIN32
64 // Windows
65 # include "MathAlgo/minpack/win32_f2c.h"
66 # include <blas.h>
67 
68 // JW: VCLapack header.
69 // "small" conflicts with rpcndr.h:144 as define to char (JW)
70 # pragma warning(push)
71 # pragma warning (disable: 4518)
72 # ifdef small
73 # pragma warning(disable: 4005)
74 # define small smallUnique1852_
75 # include "lapack.h"
76 # define small char
77 # else // small
78 # include "lapack.h"
79 # endif // small
80 # pragma warning(pop)
81 #else // WIN32
82 // Unix: Fortran Lapack, not CLapack
83 
84 # ifdef __APPLE__
85 # include <Accelerate/Accelerate.h> // for lapack
86 # else // __APPLE__
87 
88 extern "C"
89 {
90  // linear equations (general) using LU factorizaiton
91  void F77_DGESV(cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda,
92  fia_ ipiv, fda_ b, cfi_ ldb, fi_ info);
93 
94  // solve linear least squares using QR or LU factorization
95  void F77_DGELS(cfch_ trans, cfi_ M, cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda,
96  fda_ B, cfi_ ldb, fda_ work, cfi_ lwork, fi_ info);
97 
98  // solve weighted linear least squares
99  void F77_DGGGLM(cfi_ N, cfi_ M, cfi_ P, fda_ A, cfi_ lda, fda_ B, cfi_ ldb,
100  fda_ b, fda_ x, fda_ y, fda_ work, cfi_ lwork, fi_ info);
101 
102  // solve symmetric eigenvalues
103  void F77_DSYEV(cfch_ jobz, cfch_ uplo, cfi_ N, fda_ A, cfi_ lda,
104  fda_ W, fda_ work, cfi_ lwork, fi_ info);
105 
106  // solve symmetric eigenvalues and vectors
107  void F77_DSYEVD(cfch_ jobz, cfch_ uplo, cfi_ N, fda_ A, cfi_ lda,
108  fda_ W, fda_ work, cfi_ lwork, fia_ iwork, cfi_ liwork, fi_ info);
109 
110  // solve symmetric eigenvalues (packed matrix storage)
111  void F77_DSPEV(cfch_ jobz, cfch_ uplo, cfi_ N, fda_ A, fda_ W,
112  fda_ Z, cfi_ ldz, fda_ work, fi_ info);
113 
114  // solve unsymmetric eigenvalues
115  void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
116  fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
117  cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
118 
119  /**
120  [see fortran.h for typedefs]
121  SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
122  WORK, LWORK, INFO )
123 
124  Scalar Arguments:
125  CHARACTER JOBU, JOBVT
126  INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N
127 
128  Array Arguments:
129  DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ), VT( LDVT, * ), WORK( * )
130 
131  Purpose
132  =======
133 
134  DGESVD computes the singular value decomposition (SVD) of a real
135  M-by-N matrix A, optionally computing the left and/or right singular
136  vectors. The SVD is written
137 
138  A = U * SIGMA * transpose(V)
139 
140  where SIGMA is an M-by-N matrix which is zero except for its
141  min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
142  V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
143  are the singular values of A; they are real and non-negative, and
144  are returned in descending order. The first min(m,n) columns of
145  U and V are the left and right singular vectors of A.
146 
147  Note that the routine returns V**T, not V.
148  (JW, 03/2002)
149  */
150  void F77_DGESVD(cfch_ JOBU, cfch_ JOBVT, fi_ M, fi_ N,
151  fda_ A, fi_ LDA, fda_ S, fda_ U,fi_ LDU,
152  fda_ VT, fi_ LDVT, fda_ WORK, fi_ LWORK, fi_ INFO);
153 
154  void dpotf2_(cfch_ UPLO, cfi_ N, fda_ A, cfi_ LDA, fi_ INFO);
155 
156  void F77_SGGEV(cfch_ jobvl, cfch_ jobvr, fi_ n, fda_ a,
157  fi_ lda, fda_ b, fi_ ldb, fda_ alphar, fda_ alphai,
158  fda_ beta, fda_ vl, fi_ ldvl, fda_ vr, fi_ ldvr,
159  fda_ work, fi_ lwork, fda_ rwork, fi_ info);
160 
161 } // end extern C
162 # endif // __APPLE__
163 #endif //WIN32
164 
165 
166 using namespace TNT;
167 
170 {
171  BIAS::Matrix < double > res(FMat.num_rows(), FMat.num_cols());
172 
173  // get the pointer to the data array of the Matrix
174  double *dataP = res.GetData();
175  int nCols = res.num_cols(); // nr of rows of the Matrix
176 
177  // copy the elements to this, rember the different index base (0/1)
178  // and the difference between row-major / col-major order
179  // transpose the values because Fortran_Matrices are column-major
180  // and Matrix is row-major
181  for (int row = 0; row < res.num_rows(); row++) {
182  for (int col = 0; col < res.num_cols(); col++) {
183  dataP[nCols * row + col] = FMat(row + 1, col + 1); // assign elementwise
184  }
185  }
186  return res;
187 }
188 
189 void
191  BIAS::Matrix<double> &res)
192 {
193  res.newsize(FMat.num_rows(), FMat.num_cols());
194 
195  // get the pointer to the data array of the Matrix
196  double *dataP = res.GetData();
197  int nCols = res.num_cols(); // nr of rows of the Matrix
198 
199  // copy the elements to this, rember the different index base (0/1)
200  // and the difference between row-major / col-major order
201  // transpose the values because Fortran_Matrices are column-major
202  // and Matrix is row-major
203  for (int row = 0; row < res.num_rows(); row++) {
204  for (int col = 0; col < res.num_cols(); col++) {
205  dataP[nCols * row + col] = FMat(row + 1, col + 1); // assign elementwise
206  }
207  }
208 }
209 
210 
211 int
214  const char ul)
215 {
216  BIASASSERT(A.GetCols() == A.GetRows());
217  BIASASSERT(ul=='U' || ul=='L');
218  char UPLO=ul;
220  ((BIAS::Matrix<double>)transpose(A)).GetData());
221 
222 #ifdef WIN32
223  integer LDA = FMA.num_rows();
224  integer N=LDA;
225  integer INFO=0;
226 #else
227  BIAS_LPK_CONST_INT LDA = FMA.num_rows();
228  BIAS_LPK_CONST_INT N=LDA;
229  BIAS_LPK_INT INFO=0;
230 #endif
231  //std::cout << "N="<<N<<"\tA = "<<A<<"\nLDA = "<<LDA<<std::endl;
232  dpotf2_(&UPLO, &N, &FMA(1,1), &LDA, &INFO);
233 
234 
235  if (INFO==0){
236  UL.newsize(LDA, LDA);
237  UL.SetZero();
238  if (ul=='U'){
239  for (long int y=0; y<LDA; y++){
240  for (long int x=y; x<LDA; x++){
241  UL[y][x]=FMA(y+1,x+1);
242  }
243  }
244  } else {
245  for (long int x=0; x<LDA; x++){
246  for (long int y=x; y<LDA; y++){
247  UL[y][x]=FMA(y+1,x+1);
248  }
249  }
250  }
251  } else if (INFO>0) {
252  // comment on what info means (LAPACK doc):
253  // = 0: successful exit
254  // < 0: if INFO = -k, the k-th argument had an illegal value
255  // > 0: if INFO = k, the leading minor of order k is not
256  // positive definite, and the factorization could not be completed.
257 #ifdef BIAS_DEBUG
258  BIASERR("You did not provide a positive definite symmetric matrix:"
259  <<A<<" Error Code:"<<INFO);
260 #endif
261  }
262  //std::cout << "FMA = "<<FMA<<"\nUL = "<<UL<<std::endl;
263 
264  return INFO;
265 }
266 
267 
270  const BIAS::Vector<double> &b)
271 {
273  ((BIAS::Matrix<double>)transpose(A)).GetData());
274  Vector<double> FVY(b.size(),b.GetData());
275 
276  BIAS_LPK_CONST_INT one=1;
277  BIAS_LPK_INT M=FMA.num_rows();
278  BIAS_LPK_INT N=FMA.num_cols();
279  BIAS_LPK_INT info = 0;
280 
281  Vector<double> x(b);
282  Vector<Fortran_integer> index(M);
283 
284 #ifdef WIN32
285  //different calling arguments in WIN32
286  long int NT(N);
287  long int oneT(one);
288  long int MT(M);
289  long int* indT = new long int[M];
290  long int infT(info);
291 
292  F77_DGESV(&NT, &oneT, &FMA(1,1), &MT, indT, &x(1), &MT, &infT); //WIN32
293  info = infT;
294  delete[] indT;
295 #else
296  F77_DGESV(&N, &one, &FMA(1,1), &M, &index(1), &x(1), &M, &info); //UNIX
297 #endif
298 
299  BIAS::Vector<double> vecResult(A.num_cols());
300 
301  if (info != 0)
302  return BIAS::Vector<double>(0);
303  else {
304  for (int i=0;i<vecResult.size();i++)
305  vecResult[i]=x[i];
306  return vecResult;
307  }
308 }
309 
312  const BIAS::Vector<double> &b, int &res)
313 {
314  res=0;
315 #if defined(BIAS_DEBUG) && defined(COMPILE_DEBUG) && !defined(COMPILE_NDEBUG)
316  BIAS::SVD svd(A);
317  if (svd.Rank()!=(unsigned)((A.num_cols()>A.num_rows())?A.num_rows():A.num_cols())){
318  BIASERR("cannot solve because rank of A is too low (see man dgels)"
319  << "\nA is "<<A.num_rows()<<"x"<<A.num_cols()
320  <<" and has rank "<<svd.Rank()<<" should have rank "
321  <<((A.num_cols()>A.num_rows())?(A.num_rows()):(A.num_cols())));
322  res=-1;
323  BIASERR("A: "<<A<<" Singular Values: "<<svd.GetS());
324  //BIASASSERT(false);
325  }
326  if (A.num_rows()<A.num_cols()){
327  BIASERR("system is not overdetermined since A is a "<<A.num_rows()
328  <<"x"<<A.num_cols()<<" matrix");
329  }
330 #endif
332  ((BIAS::Matrix<double>)transpose(A)).GetData());
333  Vector<double> FVY(b.size(),b.GetData());
334  BIAS_LPK_CONST_INT one=1;
335  long int M=FMA.num_rows();
336  long int N=FMA.num_cols();
337 
338  Vector<double> x(b);
339  BIAS_LPK_INT info = 0;
340 
341  char transp = 'N';
342  BIAS_LPK_INT lwork = 5 * (M+N); // temporary work space
343  Vector<double> work(lwork);
344 
345 #ifdef WIN32
346  //different function prarams in WIN32
347  long int NT(N);
348  long int oneT(one);
349  long int MT(M);
350  long int infT(info);
351  long int lworkT(lwork);
352 
353  F77_DGELS(&transp, &MT, &NT, &oneT, &FMA(1,1), &MT, &x(1), &MT, &work(1),
354  &lworkT, &infT);
355  info = infT;
356 #else //WIN32
357  F77_DGELS(&transp, &M, &N, &one, &FMA(1,1), &M, &x(1), &M, &work(1),
358  &lwork, &info);
359 #endif //WIN32
360 
361  res|=info;
362  BIAS::Vector<double> vecResult(N);
363  if (res != 0) {
364  BIASERR("error calculating linear least squares problem "<<res);
365  return BIAS::Vector<double>(0);
366  }
367  else {
368  for (int i=0;i<vecResult.size();i++)
369  vecResult[i]=x[i];
370  return vecResult;
371  }
372 }
373 
374 
377  const BIAS::Vector<double> &b,
378  const BIAS::Matrix<double> &B, int &res)
379 {
380 #ifdef MIP_DEBUG
381  if (A.num_rows()!=B.num_rows()){
382  BIASERR("wrong matrix dimension ");
383  res=-1;
384  }
385  if (A.num_rows()!=b.num_rows()){
386  BIASERR("wrong vector dimension ");
387  res=-2;
388  }
389  // to befinished (see man dggglm);
390 #endif
392  ((BIAS::Matrix<double>)transpose(A)).GetData());
394  ((BIAS::Matrix<double>)transpose(B)).GetData());
395  Vector<double> FVY(b.size(),b.GetData());
396  long int N=FMA.num_rows();
397  long int M=FMA.num_cols();
398  long int P=FMB.num_cols();
399  Vector<double> x(M);
400  Vector<double> y(P);
401  Fortran_integer info = 0;
402 
403  Fortran_integer lwork = 5 * (M+N+P); // temporary work space
404  Vector<double> work(lwork);
405 
406 #ifdef WIN32
407  //different calling arguments in WIN32
408  long int NT(N);
409  long int MT(M);
410  long int PT(P);
411  long int infT(info);
412  long int lworkT(lwork);
413 
414  F77_DGGGLM(&NT, &MT, &PT, &FMA(1,1), &NT, &FMB(1,1), &NT, &FVY(1), &x(1), &y(1),
415  &work(1), &lworkT, &infT);
416  info = infT;
417 #else //WIN32
418  F77_DGGGLM(&N, &M, &P, &FMA(1,1), &N, &FMB(1,1), &N, &FVY(1), &x(1), &y(1),
419  &work(1), &lwork, &info);
420 #endif //WIN32
421 
422  res=info;
423  BIAS::Vector<double> vecResult(x.size());
424  if (info != 0) {
425  BIASERR("error calculating weighted linear least squares problem "<<res);
426  return BIAS::Vector<double>(0);
427  } else {
428  for (int i=0;i<vecResult.size();i++)
429  vecResult[i]=x[i];
430  return vecResult;
431  }
432 }
433 
434 // *********************** Eigenvalue problems *******************
435 
436 // solve symmetric eigenvalue problem (eigenvalues only)
439 {
441  ((BIAS::Matrix<double>)transpose(A)).GetData());
442  char jobz = 'N';
443  char uplo = 'U';
444  long int N = FMA.num_rows();
445 
446  assert(N == FMA.num_cols());
447 
448  Vector<double> eigvals(N);
449  Fortran_integer worksize = 3*N;
450  Fortran_integer info = 0;
451  Vector<double> work(worksize);
452 
453 #ifdef WIN32
454  //different calling arguments in WIN32
455  long int NT(N);
456  long int infT(info);
457  long int worksizeT(worksize);
458 
459  F77_DSYEV(&jobz, &uplo, &NT, &FMA(1,1), &NT, eigvals.begin(), work.begin(),
460  &worksizeT, &infT);
461  info = infT;
462 #else //WIN32
463  F77_DSYEV(&jobz, &uplo, &N, &FMA(1,1), &N, eigvals.begin(), work.begin(),
464  &worksize, &info);
465 #endif //WIN32
466 
467  BIAS::Vector<double> vecResult(eigvals.size());
468 
469  if (info != 0) return BIAS::Vector<double>(0);
470  else {
471  for (int i=0;i<vecResult.size();i++)
472  vecResult[i]=eigvals[i];
473  return vecResult;
474  }
475 }
476 
478  BIAS::Vector<double>& eigenvalues,
479  std::vector<BIAS::Vector<double> >& eigenvectors)
480 {
482  ((BIAS::Matrix<double>)transpose(A)).GetData());
483  char jobz = 'V'; // compute eigenvalues and eigenvectors
484  char uplo = 'U'; // upper triangle
485  long int N = FMA.num_rows();
486 
487  assert(N == FMA.num_cols());
488 
489  eigenvalues.newsize(N);
490 
491  Fortran_integer info = 0;
492 #ifdef WIN32
493  BIASABORT;
494 #else //WIN32
495  // compute work size
496  double tmp_work;
497  long int iwork_size = -1, work_size = -1;
498  F77_DSYEVD(&jobz, &uplo, &N, &FMA(1,1), &N, eigenvalues.begin(), &tmp_work,
499  &work_size, &iwork_size, &iwork_size, &info);
500  work_size = (int)tmp_work;
501  Vector<double> work(work_size);
502  Vector<long int> iwork(iwork_size);
503  F77_DSYEVD(&jobz, &uplo, &N, &FMA(1,1), &N, eigenvalues.begin(), work.begin(),
504  &work_size, iwork.begin(), &iwork_size, &info);
505 #endif //WIN32
506  if (info==0){
507  eigenvectors.resize(N);
508  for (int r=0; r<N; r++){
509  eigenvectors[r].newsize(N);
510  for (int c=0; c<N; c++){
511  eigenvectors[r][c] = FMA(c + 1, r + 1);
512  }
513  }
514  }
515 /*
516 #ifdef BIAS_DEBUG
517  BIAS::Vector<double> mv, vv, diff;
518  for (int i=0; i<N; i++){
519  mv = A * eigenvectors[i];
520  vv = eigenvalues[i] * eigenvectors[i];
521  diff = mv - vv;
522  //std::cout << "A * evec: "<<mv<<"\n eval * evec: "<<vv<<endl;
523  if (fabs(diff.NormL2())>1e-20){
524  std::cout << "diff: "<< diff << std::endl
525  << "diff.NormL2(): "<<diff.NormL2()<< std::endl ;
526  //BIASASSERT(BIAS::Equal(diff.NormL2(), 0.0, 1e-15));
527  }
528  }
529 #endif
530 */
531  return info;
532 }
533 
534 // Solve symmetric eigenvalue problem for matrix in packed storage
536  const BIAS::Vector<double> &A,
537  BIAS::Vector<double>& eigVals,
538  std::vector<BIAS::Vector<double> >& eigVecs,
539  const bool upperTriangle)
540 {
541  // Compute eigenvalues and eigenvectors of A
542  char jobz = 'V';
543  // Is upper or lower triangle of A given in packed data vector?
544  char uplo = (upperTriangle ? 'U' : 'L');
545  // Matrix size is N x N, vector length is N * (N+1) / 2
546  BIASASSERT(N*(N+1) == 2*(int)A.Size());
547  eigVals.newsize(N);
548  eigVals.SetZero();
549 
550  // Compute work space
551  BIAS::Vector<double> work(3*N);
552  Fortran_Matrix<double> Z(N,N);
553  BIAS::Vector<double> tmpA = A;
554 
555  // Call LAPACK routine
556  Fortran_integer info = 0;
557 #ifdef WIN32
558  Fortran_integer num = N;
559  F77_DSPEV(&jobz, &uplo, &num, tmpA.begin(), eigVals.begin(),
560  &(Z(1,1)), &num, work.begin(), &info);
561 #else
562  F77_DSPEV(&jobz, &uplo, &N, tmpA.begin(), eigVals.begin(),
563  &(Z(1,1)), &N, work.begin(), &info);
564 #endif
565 
566  // Return results
567  if (info == 0) {
568  eigVecs.resize(N);
569  for (int i = 0; i < N; i++) {
570  eigVecs[i].newsize(N);
571  for (int j = 0; j < N; j++) {
572  eigVecs[i][j] = Z(j+1,i+1);
573  }
574  }
575  }
576  return info;
577 }
578 
579 // solve unsymmetric eigenvalue problems (for a rectangular matrix)
582 {
584  ((BIAS::Matrix<double>)transpose(A)).GetData());
585  char jobvl = 'N';
586  char jobvr = 'N';
587 
588  Fortran_integer N = FMA.num_rows();
589  assert(N == FMA.num_cols());
590 
591  if (N<1) return 1;
592 
593  Fortran_Matrix<double> vl(1,N); // should be NxN ?
594  Fortran_Matrix<double> vr(1,N);
595  Fortran_integer one = 1;
596 
597  Fortran_integer worksize = 5*N;
598  Fortran_integer info = 0;
599  Vector<double> work(worksize, 0.0);
600 
601  Vector<double> FWR(N), FWI(N);
602 
603 #ifdef WIN32
604  //different function arguments in WIN32
605  long int NT(N);
606  long int oneT(one);
607  long int infT(info);
608  long int worksizeT(worksize);
609 
610  F77_DGEEV(&jobvl, &jobvr, &NT, &FMA(1,1), &NT, &(FWR(1)), //WIN32
611  &(FWI(1)), &(vl(1,1)), &oneT, &(vr(1,1)), &oneT,
612  &(work(1)), &worksizeT, &infT);
613  info = infT;
614 #else //WIN32
615  F77_DGEEV(&jobvl, &jobvr, &N, &FMA(1,1), &N, &(FWR(1)), //UNIX
616  &(FWI(1)), &(vl(1,1)), &one, &(vr(1,1)), &one,
617  &(work(1)), &worksize, &info);
618 #endif //WIN32
619 
620  wr=FWR;
621  wi=FWI;
622  return (info==0 ? 0: 1);
623 }
624 
625 int
627  BIAS::Vector<double> &ret_EigenValuesReal,
628  BIAS::Vector<double> &ret_EigenValuesImag,
629  BIAS::Matrix<double> &eigenVectors)
630 {
632  ((BIAS::Matrix<double>)transpose(A)).GetData());
633  char jobvl = 'V'; // calculate the left eigenvectors
634  char jobvr = 'V'; // calculate the right eigenvectors
635 
636  Fortran_integer N = FMA.num_rows(); // dim of the Matrix should be NxN
637  assert(N == FMA.num_cols() ); // A must be rectangular NxN matrix
638  if (N<1) return 1; // 1x1 matrix is a scalar, decomposition is nonsense
639 
640  Fortran_integer ldvl = N; // size of the left eigenvectormatrix
641  Fortran_integer ldvr = N; // size of the right eigenvectormatrix
642 
643  // should be NxN, but left Eigenvectorss are not calculated due to jobvl=N
644  Fortran_Matrix<double> eigenVectsLeft( N,ldvl );
645  // will contain a (NxN) Matrix with the right Eigenvectors in columns.
646  Fortran_Matrix<double> eigenVectsRight( N,ldvr );
647 
648  Fortran_integer worksize = 5*N;
649  Fortran_integer info = 0;
650  Vector<double> work(worksize, 0.0);
651 
652  Vector<double> ret_EigenValuesRealPart(N,0.0);
653  Vector<double> ret_EigenValuesImagPart(N,0.0);
654 
655 #ifdef WIN32
656  //different function arguments in WIN32
657  long int NT(N);
658  long int infT(info);
659  long int worksizeT(worksize);
660  long int ldvlT(ldvl);
661  long int ldvrT(ldvr);
662 
663  F77_DGEEV(&jobvl, &jobvr, &NT, &FMA(1,1), &NT, &(ret_EigenValuesRealPart(1)), //WIN32
664  &(ret_EigenValuesImagPart(1)),
665  &(eigenVectsLeft(1,1)), &ldvlT,
666  &(eigenVectsRight(1,1)), &ldvrT,
667  &(work(1)), &worksizeT, &infT);
668  info = infT;
669 #else //WIN32
670  F77_DGEEV(&jobvl, &jobvr, &N, &FMA(1,1), &N, &(ret_EigenValuesRealPart(1)), //UNIX
671  &(ret_EigenValuesImagPart(1)),
672  &(eigenVectsLeft(1,1)), &ldvl,
673  &(eigenVectsRight(1,1)), &ldvr,
674  &(work(1)), &worksize, &info);
675 #endif //WIN32
676 
677  eigenVectors.newsize(eigenVectsRight.num_rows(),eigenVectsRight.num_cols());
678  for (int i = 0; i < eigenVectors.size(); i++) {
679  eigenVectors.GetData()[i] = eigenVectsRight.begin()[i];
680  };
681  eigenVectors=transpose(eigenVectors);
682  ret_EigenValuesReal= ret_EigenValuesRealPart;
683  ret_EigenValuesImag= ret_EigenValuesImagPart;
684  return (info==0 ? 0: 1);
685 }
686 
687 int
689  const BIAS::Matrix<double> &A,
690  BIAS::Vector<double> &ret_S,
691  BIAS::Matrix<double> &ret_U,
692  BIAS::Matrix<double> &ret_VT)
693 {
694 
695 #ifdef BIAS_DEBUG
696  // svd does not like nans/infs and hangs sometimes.
697  // It is better to abort before in that case
698  for (int i=0; i<A.num_rows(); i++) {
699  for (int j=0; j<A.num_cols(); j++) {
700  INFNANCHECK(A[i][j]);
701  }
702  }
703 #endif
704 
706  ((BIAS::Matrix<double>)transpose(A)).GetData());
707  //char jobu = 'A'; // calculate all columns of U
708  //char jobvt = 'A'; // calculate all n rows of V_h
709 
710  Fortran_integer M = FMA.num_rows(); // dim of the Matrix A should be MxN
711  Fortran_integer N = FMA.num_cols(); // dim of the Matrix A should be MxN
712 
713  Fortran_Matrix<double> U ( M, M );// M x M Orthogonal/Unitary matrix
714  Fortran_Matrix<double> V ( N, N );// N x N Orthogonal/Unitary matrix
715  Fortran_Matrix<double> VT(N,N); // N x N Orthogonal/Unitary matrix transposed
716  Vector<double> S ( (int)max( (int)M, (int)N) );// the M singular values
717 
718  Fortran_integer lda = M;
719  Fortran_integer ldu = M; // because jobu = A
720  Fortran_integer ldvt = N; // because jobvt = A
721 
722  Fortran_integer worksize = 6 * (M > N ? M : N) ;
723 
724  Fortran_integer info = 0;
725  Vector<double> work(worksize, 0.0);
726 
727 #ifdef WIN32
728  //different function arguments in WIN32
729  long int NT(N);
730  long int MT(M);
731  long int infT(info);
732  long int ldaT(lda);
733  long int lduT(ldu);
734  long int ldvtT(ldvt);
735  long int worksizeT(worksize);
736 
737  // call extern Fortran2C routine from liblapack:
738  F77_DGESVD( &jobu, &jobvt, &MT, &NT, &FMA(1,1), &ldaT, &S(1), &U(1,1),
739  &lduT, &VT(1,1), &ldvtT, &work(1), &worksizeT, &infT); //WIN32
740  info = infT;
741 #else //WIN32
742  F77_DGESVD( &jobu, &jobvt, &M, &N, &FMA(1,1), &lda, &S(1), &U(1,1),
743  &ldu, &VT(1,1), &ldvt, &work(1), &worksize, &info); //UNIX
744 #endif //WIN32
745 
746  // S is zero exept for the first min(M,N) diagonal elements
747  // therefore only copy these elements
748  ret_S.newsize((int)min((int) M,(int)N));
749  for (int i=0;i<min((int) M,(int)N);i++)
750  ret_S[i] = S[i];
751 
752  ret_U=Fortran_Matrix_to_Matrix(U);
753  ret_VT=Fortran_Matrix_to_Matrix(VT);
754  if (info==0) {
755  return 0;
756  } else {
757  /* from documentaion of F77_DGESVD:
758  * INFO (output) INTEGER
759  * = 0: successful exit.
760  * < 0: if INFO = -i, the i-th argument had an illegal value.
761  * > 0: if DBDSQR did not converge, INFO specifies how many
762  * superdiagonals of an intermediate bidiagonal form B
763  * did not converge to zero. See the description of WORK
764  * above for details.
765  * On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
766  * if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged
767  * superdiagonal elements of an upper bidiagonal matrix B
768  * whose diagonal is in S (not necessarily sorted). B
769  * satisfies A = U * B * VT, so it has the same singular values
770  * as A, and singular vectors related by U and VT. */
771 
772  // std::cout<<"F77_DGESVD returned "<<info<<std::endl;
773  return 1;
774  }
775  return (info==0 ? 0: 1); // if info != 0 the arrays were too small.
776 }
777 
778 
779 
781  const BIAS::Vector<double> &V) {
782  double dist = SquaredMahalanobisDistance(Sigma,V);
783  if (dist>0.0) return sqrt(dist);
784  return dist;
785 }
786 
788  const BIAS::Vector<double> &V) {
789  // solve dist = V^T A^-1 V
790  // first convert to dist = V^T (U U^T)^-1 V = V^T U^-T U^-1 V
791  // = (U^-1 V)^T * (U^-1 V)
792  // compute U
793  BIAS::Matrix<double> U=Sigma;
794 
795  U.MakeSymmetric();
796  double scale = U.NormFrobenius()/U.num_rows();
797  BIAS::Matrix<double> s2 = U *(1.0/scale);
798 
799  int result =
801  if (result!=0) {
802  BIASERR("cholesky failed with "<<result);
803  return -1.0;
804  }
805 
806  // set m = (U^-1 V) <=> U m = V with dist = m^T m
807  // solve for m:
808 
809  // Optimization: dont call Lapack_LU_linear_solve here, this is already
810  // triangular. Call BLAS::DTRSV directly. This also avoids FORTRAN-BIAS
811  // conversion of matrices.
812 
814  // compute dist = m^T m
815  double dist = 0;
816  for (unsigned int i=0; i<m.Size(); i++) {
817  dist += m[i]*m[i];
818  }
819  return sqrt(dist/scale);
820 }
821 
822 // The right generalized eigenvector v(j) corresponding to the
823 // generalized eigenvalue lambda(j) of (A,B) satisfies
824 // A * v(j) = lambda(j) * B * v(j).
825 // A and B are both M x M matrices.
828 {
829 #ifndef WIN32
832 
833  char jobvl = 'N';
834  char jobvr = 'V';
835 
836  Fortran_integer M = A_.num_rows();
837  Fortran_integer N = B_.num_rows();
838  Fortran_integer lda = M;
839  Fortran_integer n = M;
840  Fortran_integer ldb = N;
841  Fortran_integer ldvl = 1;
842  Fortran_integer ldvr = N;
843  Fortran_integer info = 0;
844 
845  Fortran_integer lwork = N*N+64;
846  Vector<double> work(lwork, 0.0);
847  Vector<double> rwork(N*8, 0.0);
848 
849  Vector<double> alpha(M, 0.0);
850  Vector<double> alphai(M, 0.0);
851  Vector<double> beta(M, 0.0);
852 
853  Fortran_Matrix<double> vl(ldvl, M);
854  Fortran_Matrix<double> vr(ldvr, N);
855 
856  // call extern Fortran2C routine from liblapack
857  F77_SGGEV(
858  &jobvl,
859  &jobvr,
860  &n,
861  &(a(1,1)),
862  &lda,
863  &(b(1,1)),
864  &ldb,
865  &(alpha(1)),
866  &(alphai(1)),
867  &(beta(1)),
868  &(vl(1,1)),
869  &ldvl,
870  &(vr(1,1)),
871  &ldvr,
872  &work(1),
873  &lwork,
874  &rwork(1),
875  &info);
876 
878  out.newsize(N,N);
879  for(unsigned int i =0; i< N; i++){
880  for(unsigned int j =0; j< M; j++){
881  out[i][j]=vr(i+1,j+1);
882  }
883  }
884  return out;
885 
886 #else // WIN32
887 
888  BIASERR("Disabled function generalised_eigenvalue_matrix_solve() "
889  "because F77_SGGEV is not available yet in WIN32 build!");
890 
892  return out;
893 
894 #endif // WIN32
895 }
BIAS::Matrix< double > generalised_eigenvalue_matrix_solve(BIAS::Matrix< double > &A_, BIAS::Matrix< double > &B_)
Definition: Lapack.cpp:826
BIAS::Vector< double > Lapack_LLS_QR_linear_solve(const BIAS::Matrix< double > &A, const BIAS::Vector< double > &b, int &res)
linear least squares solves |Ax-b|=min res=0 on success, anything else rudimentary tested (woelk) ...
Definition: Lapack.cpp:311
Matrix< T > transpose(const Matrix< T > &A)
Definition: cmat.h:793
int Eigenvalue_solve(const BIAS::Matrix< double > &A, BIAS::Vector< double > &wr, BIAS::Vector< double > &wi)
solve unsymmetric eigenvalue problems (for a rectangular matrix) untested, grest ...
Definition: Lapack.cpp:580
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
Subscript num_cols() const
Definition: cmat.h:320
unsigned int Rank()
returns the rank of A_
Definition: SVD.cpp:506
Matrix< T > & newsize(Subscript M, Subscript N)
Definition: cmat.h:269
BIAS::Vector< double > Lapack_WLLS_solve(const BIAS::Matrix< double > &A, const BIAS::Vector< double > &b, const BIAS::Matrix< double > &B, int &res)
weighted linear least squares solves |B^-1(b-Ax)|=min res=0 on success, anything else rudimentary tes...
Definition: Lapack.cpp:376
unsigned int Size() const
length of the vector
Definition: Vector.hh:143
void SetZero()
equivalent to matrix call
Definition: Vector.hh:156
double SquaredMahalanobisDistance(const BIAS::Matrix< double > &Sigma, const BIAS::Vector< double > &V)
computes Mahalanobis distance V^T Sigma^-1 V efficiently using cholesky decomposition and exploitatio...
Definition: Lapack.cpp:787
BIAS::Vector< double > Lapack_LU_linear_solve(const BIAS::Matrix< double > &A, const BIAS::Vector< double > &b)
solve linear equations using LU factorization
Definition: Lapack.cpp:269
int Lapack_Cholesky_SymmetricPositiveDefinit(const BIAS::Matrix< double > &A, BIAS::Matrix< double > &UL, const char ul)
Coputes the Cholesky decomposition of a symmetric positive definit matrix A.
Definition: Lapack.cpp:212
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
unsigned int GetRows() const
Definition: Matrix.hh:202
BIAS::Matrix< double > Fortran_Matrix_to_Matrix(const Fortran_Matrix< double > &FMat)
converts the argument Fortran_Matrix to a Matrix and returns it.
Definition: Lapack.cpp:169
const Vector< double > & GetS() const
return S which is a vector of the singular values of A in descending order.
Definition: SVD.hh:167
T * GetData()
get the pointer to the data array of the matrix (for faster direct memeory access) ...
Definition: Matrix.hh:185
int General_singular_value_decomposition(char jobu, char jobvt, const BIAS::Matrix< double > &A, BIAS::Vector< double > &ret_S, BIAS::Matrix< double > &ret_U, BIAS::Matrix< double > &ret_VT)
solve general eigenproblem.
Definition: Lapack.cpp:688
Subscript num_cols() const
Definition: fmat.h:260
unsigned int GetCols() const
Definition: Matrix.hh:204
T * GetData() const
get the pointer to the data array of the vector (for faster direct memory access) ...
Definition: Vector.hh:219
Subscript size() const
Definition: cmat.h:212
iterator begin()
Definition: vec.h:164
int Eigenproblem_quadratic_matrix(const BIAS::Matrix< double > &A, BIAS::Vector< double > &ret_EigenValuesReal, BIAS::Vector< double > &ret_EigenValuesImag, BIAS::Matrix< double > &eigenVectors)
solve general eigenproblem for a general quadratix (n x n) matrix.
Definition: Lapack.cpp:626
Subscript num_rows() const
Definition: cmat.h:319
double MahalanobisDistance(const BIAS::Matrix< double > &Sigma, const BIAS::Vector< double > &V)
computes squared Mahalanobis distance V^T Sigma^-1 V efficiently using cholesky decomposition and exp...
Definition: Lapack.cpp:780
int Packed_symmetric_eigenvalue_solve(long int N, const BIAS::Vector< double > &A, BIAS::Vector< double > &eigVals, std::vector< BIAS::Vector< double > > &eigVecs, const bool upperTriangle)
Solve symmetric eigenvalue problem for matrix in packed storage.
Definition: Lapack.cpp:535
BIAS::Vector< double > Upper_symmetric_eigenvalue_solve(const BIAS::Matrix< double > &A)
Solve symmetric eigenvalue problem (eigenvalues only)
Definition: Lapack.cpp:438
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
Subscript num_rows() const
Definition: fmat.h:259
Subscript size() const
Definition: vec.h:262