Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
lapack.h
1 /*
2 This file is distributed as part of the BIAS library (Basic ImageAlgorithmS)
3 but it has not been developed by the authors of BIAS.
4 
5 For copyright, author and license information see below.
6 */
7 
8 
9 /*
10 *
11 * Template Numerical Toolkit (TNT): Linear Algebra Module
12 *
13 * Mathematical and Computational Sciences Division
14 * National Institute of Technology,
15 * Gaithersburg, MD USA
16 *
17 *
18 * This software was developed at the National Institute of Standards and
19 * Technology (NIST) by employees of the Federal Government in the course
20 * of their official duties. Pursuant to title 17 Section 105 of the
21 * United States Code, this software is not subject to copyright protection
22 * and is in the public domain. The Template Numerical Toolkit (TNT) is
23 * an experimental system. NIST assumes no responsibility whatsoever for
24 * its use by other parties, and makes no guarantees, expressed or implied,
25 * about its quality, reliability, or any other characteristic.
26 *
27 * BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
28 * see http://math.nist.gov/tnt for latest updates.
29 *
30 */
31 
32 
33 
34 // Header file for Fortran Lapack
35 
36 #ifndef LAPACK_H
37 #define LAPACK_H
38 
39 // This file incomplete and included here to only demonstrate the
40 // basic framework for linking with the Fortran Lapack routines.
41 
42 #include <Base/Common/W32Compat.hh>
43 #include "fortran.h"
44 #include "vec.h"
45 #include "fmat.h"
46 
47 using namespace std;
48 
49 
50 #define F77_DGESV dgesv_
51 #define F77_DGELS dgels_
52 #define F77_DSYEV dsyev_
53 
54 // jw
55 #define F77_DGEEV dgeev_
56 // jw
57 #define F77_DGESVD dgesvd_
58 
59 extern "C"
60 {
61 
62  // linear equations (general) using LU factorizaiton
63  //
64  void F77_DGESV(cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda,
65  fia_ ipiv, fda_ b, cfi_ ldb, fi_ info);
66 
67  // solve linear least squares using QR or LU factorization
68  //
69  void F77_DGELS(cfch_ trans, cfi_ M,
70  cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda, fda_ B, cfi_ ldb, fda_ work,
71  cfi_ lwork, fi_ info);
72 
73  // solve symmetric eigenvalues
74  //
75  void F77_DSYEV( cfch_ jobz, cfch_ uplo, cfi_ N, fda_ A, cfi_ lda,
76  fda_ W, fda_ work, cfi_ lwork, fi_ info);
77 
78  // solve unsymmetric eigenvalues
79  //
80  void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
81  fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
82  cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
83 
84  /**
85  [see fortran.h for typedefs]
86  SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO )
87 
88  Scalar Arguments:
89  CHARACTER JOBU, JOBVT
90  INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N
91 
92  Array Arguments:
93  DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ), VT( LDVT, * ), WORK( * )
94 
95  Purpose
96  =======
97 
98  DGESVD computes the singular value decomposition (SVD) of a real
99  M-by-N matrix A, optionally computing the left and/or right singular
100  vectors. The SVD is written
101 
102  A = U * SIGMA * transpose(V)
103 
104  where SIGMA is an M-by-N matrix which is zero except for its
105  min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
106  V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
107  are the singular values of A; they are real and non-negative, and
108  are returned in descending order. The first min(m,n) columns of
109  U and V are the left and right singular vectors of A.
110 
111  Note that the routine returns V**T, not V.
112  (JW, 03/2002)
113  **/
114  void F77_DGESVD( cfch_ JOBU,
115  cfch_ JOBVT,
116  fi_ M,
117  fi_ N,
118  fda_ A,
119  fi_ LDA,
120  fda_ S,
121  fda_ U,
122  fi_ LDU,
123  fda_ VT,
124  fi_ LDVT,
125  fda_ WORK,
126  fi_ LWORK,
127  fi_ INFO );
128 
129 }
130 
131 // solve linear equations using LU factorization
132 
133 namespace TNT{
134 
136  const Vector<double> &b)
137  {
138  const Fortran_integer one=1;
139  long int M=A.num_rows();
140  long int N=A.num_cols();
141 
142  Fortran_Matrix<double> Tmp(A);
143  Vector<double> x(b);
144  Vector<Fortran_integer> index(M);
145  Fortran_integer info = 0;
146 
147  F77_DGESV(&N, &one, &Tmp(1,1), &M, &index(1), &x(1), &M, &info);
148 
149  if (info != 0) return Vector<double>(0);
150  else
151  return x;
152  }
153 
154  // solve linear least squares problem using QR factorization
155  //
157  const Vector<double> &b)
158  {
159  const Fortran_integer one=1;
160  Fortran_integer M=A.num_rows();
161  Fortran_integer N=A.num_cols();
162 
163  Fortran_Matrix<double> Tmp(A);
164  Vector<double> x(b);
165  Fortran_integer info = 0;
166 
167  char transp = 'N';
168  Fortran_integer lwork = 5 * (M+N); // temporary work space
169  Vector<double> work(lwork);
170 
171  F77_DGELS(&transp, &M, &N, &one, &Tmp(1,1), &M, &x(1), &M, &work(1),
172  &lwork, &info);
173 
174  if (info != 0) return Vector<double>(0);
175  else
176  return x;
177  }
178 
179  // *********************** Eigenvalue problems *******************
180 
181  // solve symmetric eigenvalue problem (eigenvalues only)
182  //
184  {
185  char jobz = 'N';
186  char uplo = 'U';
187  Fortran_integer N = A.num_rows();
188 
189  BIASASSERT(N == A.num_cols());
190 
191  Vector<double> eigvals(N);
192  Fortran_integer worksize = 3*N;
193  Fortran_integer info = 0;
194  Vector<double> work(worksize);
195  Fortran_Matrix<double> Tmp = A;
196 
197  F77_DSYEV(&jobz, &uplo, &N, &Tmp(1,1), &N, eigvals.begin(), work.begin(),
198  &worksize, &info);
199 
200  if (info != 0) return Vector<double>();
201  else
202  return eigvals;
203  }
204 
205 
206  // solve unsymmetric eigenvalue problems (for a rectangular matrix)
207  //
210  {
211  char jobvl = 'N';
212  char jobvr = 'N';
213 
214  Fortran_integer N = A.num_rows();
215 
216 
217  BIASASSERT(N == A.num_cols());
218 
219  if (N<1) return 1;
220 
221  Fortran_Matrix<double> vl(1,N); /* should be NxN ? **** */
222  Fortran_Matrix<double> vr(1,N);
223  Fortran_integer one = 1;
224 
225  Fortran_integer worksize = 5*N;
226  Fortran_integer info = 0;
227  Vector<double> work(worksize, 0.0);
228  Fortran_Matrix<double> Tmp = A;
229 
230  wr.newsize(N);
231  wi.newsize(N);
232 
233  // void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
234  // fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
235  // cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
236 
237  F77_DGEEV(&jobvl, &jobvr, &N, &Tmp(1,1), &N, &(wr(1)),
238  &(wi(1)), &(vl(1,1)), &one, &(vr(1,1)), &one,
239  &(work(1)), &worksize, &info);
240 
241  return (info==0 ? 0: 1);
242  }
243 
244 
245 
246 
247  /** solve general eigenproblem for a general quadratix (n x n) matrix.
248  computes eigenvalues and eigenvectors of A.
249  (Jan Woetzel), 03/2002
250  **/
252  Vector<double> &ret_EigenValuesRealPart, Vector<double> &ret_EigenValuesImagPart,
253  Fortran_Matrix<double> &eigenVecMatrixR )
254  {
255  char jobvl = 'V'; // calculate the left eigenvectors
256  char jobvr = 'V'; // calculate the right eigenvectors
257 
258  Fortran_integer N = A.num_rows(); // dim of the Matrix should be NxN
259  BIASASSERT(N == A.num_cols() ); // A must be rectangular NxN matrix
260  if (N<1) return 1; // 1x1 matrix is a scalar, decomposition is nonsense
261 
262  Fortran_integer ldvl = N; // size of the left eigenvectormatrix
263  Fortran_integer ldvr = N; // size of the right eigenvectormatrix
264 
265  Fortran_Matrix<double> eigenVectsLeft( N,ldvl ); // should be NxN, but left Eigenvectorss are not calculated due to jobvl=N
266  Fortran_Matrix<double> eigenVectsRight( N,ldvr ); // will contain a (NxN) Matrix with the right Eigenvectors in columns.
267 
268  Fortran_integer worksize = 5*N;
269  Fortran_integer info = 0;
270  Vector<double> work(worksize, 0.0);
271  Fortran_Matrix<double> Tmp = A;
272 
273  ret_EigenValuesRealPart.newsize(N);
274  ret_EigenValuesImagPart.newsize(N);
275 
276  // void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
277  // fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
278  // cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
279 
280  // call the lapack lib SVD routine:
281  F77_DGEEV(&jobvl, &jobvr, &N, &Tmp(1,1), &N, &(ret_EigenValuesRealPart(1)),
282  &(ret_EigenValuesImagPart(1)),
283  &(eigenVectsLeft(1,1)), &ldvl,
284  &(eigenVectsRight(1,1)), &ldvr,
285  &(work(1)), &worksize, &info);
286 
287 
288  eigenVecMatrixR = eigenVectsRight; // return a matrix with Eigenvectors in the columns (Spalten)
289 
290  return (info==0 ? 0: 1); // if info != 0 the the arrays were too small.
291  }
292 
293 
294 
295 
296  /** solve general eigenproblem.
297  computes singular value decomposition of a rectangular m x n matrix A
298  calls extern liblapack routine.
299  Jan Woetzel 03/2002
300  **/
302  Vector<double> &ret_S, /* vector with singular values of A with s(i) >= s(i+1) */
303  Fortran_Matrix<double> &ret_U, /* m x m orthogonal/unitary matrix U */
304  Fortran_Matrix<double> &ret_VT /* n x n orthogonal/unitary matrx transpose(V)*/ )
305  {
306  char jobu = 'A'; // calculate all columns of U
307  char jobvt = 'A'; // calculate all n rows of V_h
308 
309  Fortran_integer M = A.num_rows(); // dim of the Matrix A should be MxN
310  Fortran_integer N = A.num_cols(); // dim of the Matrix A should be MxN
311 
312  // create a copy od A because jobu=O or jobvt=O may replace the content of A in place !!!
313  Fortran_Matrix<double> TmpA = A; // M x N Matrix A to be decomposed
314 
315  Fortran_Matrix<double> U ( M, M );// M x M Orthogonal/Unitary matrix
316  Fortran_Matrix<double> V ( N, N );// N x N Orthogonal/Unitary matrix
317  Fortran_Matrix<double> VT ( N, N );// N x N Orthogonal/Unitary matrix transpose(V)
318  Vector<double> S ( max( (int)M, (int)N) );// the M singular values
319 
320  Fortran_integer lda = M;
321  Fortran_integer ldu = M; // because jobu = A
322  Fortran_integer ldvt = N; // because jobvt = A
323 
324 
325  Fortran_integer worksize = 6 * (M > N ? M : N) ;
326 
327  Fortran_integer info = 0;
328  Vector<double> work(worksize, 0.0);
329 
330  // call extern Fortran2C routine from liblapack:
331  F77_DGESVD( &jobu,
332  &jobvt,
333  &M,
334  &N,
335  &TmpA(1,1),
336  &lda,
337  &S(1),
338  &U(1,1),
339  &ldu,
340  &VT(1,1),
341  &ldvt,
342  &work(1),
343  &worksize,
344  &info);
345 
346  //#if 0
347  // // debug output
348  // cout << " eVals = " << endl;
349  // for (int row=1; row <= M; row++) {
350  // cout <<row<<". : " <<S( row );
351  // };
352  // cout << " U= " << endl;
353  // for (int row=1; row <= M; row++) {
354  // for (int col=1; col <= M; col++) {
355  // cout << U (row, col) << " ";
356  // };
357  // cout<<endl;
358  // };
359  // cout << " VT= " << endl;
360  // for (int row=1; row <= N; row++) {
361  // for (int col=1; col <= N; col++) {
362  // cout << VT (row, col)<< " " ;
363  // };
364  // cout<<endl;
365  // };
366  //#endif
367 
368  ret_S = S; // better compute with the return arguments in place (except A!!) (JW)
369  ret_U = U;
370  ret_VT = VT;
371 
372  return (info==0 ? 0: 1); // if info != 0 the the arrays were too small.
373  }
374 }
375 
376 
377 #endif
378 // LAPACK_H
379 
380 
381 
382 
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
int singular_value_decomposition_general_rectangular_matrix_solve(const Fortran_Matrix< double > &A, Vector< double > &ret_S, Fortran_Matrix< double > &ret_U, Fortran_Matrix< double > &ret_VT)
solve general eigenproblem.
Definition: lapack.h:301
int eigenvalue_solve(const Fortran_Matrix< double > &A, Vector< double > &wr, Vector< double > &wi)
Definition: lapack.h:208
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 eigenproblem_special_quadratic_matrix_solve(const Fortran_Matrix< double > &A, Vector< double > &ret_EigenValuesRealPart, Vector< double > &ret_EigenValuesImagPart, Fortran_Matrix< double > &eigenVecMatrixR)
solve general eigenproblem for a general quadratix (n x n) matrix.
Definition: lapack.h:251
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
Subscript num_cols() const
Definition: fmat.h:260
iterator begin()
Definition: vec.h:164
BIAS::Vector< double > Upper_symmetric_eigenvalue_solve(const BIAS::Matrix< double > &A)
Solve symmetric eigenvalue problem (eigenvalues only)
Definition: Lapack.cpp:438
Subscript num_rows() const
Definition: fmat.h:259