ViSP  2.8.0
vpMatrix_qr.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMatrix_lu.cpp 3530 2012-01-03 10:52:12Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Matrix QR decomposition.
36  *
37  * Authors:
38  * Filip Novotny
39  *
40  *****************************************************************************/
41 
42 #include <visp/vpConfig.h>
43 
44 #include <visp/vpMatrix.h>
45 #include <visp/vpMath.h>
46 #include <visp/vpColVector.h>
47 
48 // Exception
49 #include <visp/vpException.h>
50 #include <visp/vpMatrixException.h>
51 
52 // Debug trace
53 #include <visp/vpDebug.h>
54 
55 
56 #ifdef VISP_HAVE_LAPACK
57 extern "C" int dgeqrf_(int *m, int *n, double*a, int *lda, double *tau, double *work, int *lwork, int *info);
58 extern "C" int dormqr_(char *side, char *trans, int *m, int *n,
59  int *k, double *a, int *lda, double *tau, double *c__,
60  int *ldc, double *work, int *lwork, int *info);
61 extern "C" int dorgqr_(int *, int *, int *, double *, int *,
62  double *, double *, int *, int *);
63 extern "C" int dtrtri_(char *uplo, char *diag, int *n, double *a, int *lda, int *info);
64 #endif
65 
66 int allocate_work(double** work){
67  int dimWork = (int)((*work)[0]);
68  delete[] *work;
69  *work = new double[dimWork];
70  return dimWork;
71 }
72 #ifdef VISP_HAVE_LAPACK
74  int rowNum = (int)this->getRows();
75  int colNum = (int)this->getCols();
76  int lda = (int)rowNum; //lda is the number of rows because we don't use a submatrix
77  int dimTau = std::min(rowNum,colNum);
78  int dimWork = -1;
79  double *tau = new double[dimTau];
80  double *work = new double[1];
81  int info;
82  vpMatrix C;
83  vpMatrix A = *this;
84 
85  try{
86  //1) Extract householder reflections (useful to compute Q) and R
87  dgeqrf_(
88  &rowNum, //The number of rows of the matrix A. M >= 0.
89  &colNum, //The number of columns of the matrix A. N >= 0.
90  A.data, /*On entry, the M-by-N matrix A.
91  On exit, the elements on and above the diagonal of the array
92  contain the min(M,N)-by-N upper trapezoidal matrix R (R is
93  upper triangular if m >= n); the elements below the diagonal,
94  with the array TAU, represent the orthogonal matrix Q as a
95  product of min(m,n) elementary reflectors.
96  */
97  &lda, //The leading dimension of the array A. LDA >= max(1,M).
98  tau, /*Dimension (min(M,N))
99  The scalar factors of the elementary reflectors
100  */
101  work, //Internal working array. dimension (MAX(1,LWORK))
102  &dimWork, //The dimension of the array WORK. LWORK >= max(1,N).
103  &info //status
104  );
105 
106  if(info != 0){
107  std::cout << "dgeqrf_:Preparation:" << -info << "th element had an illegal value" << std::endl;
109  }
110  dimWork = allocate_work(&work);
111 
112  dgeqrf_(
113  &rowNum, //The number of rows of the matrix A. M >= 0.
114  &colNum, //The number of columns of the matrix A. N >= 0.
115  A.data, /*On entry, the M-by-N matrix A.
116  On exit, the elements on and above the diagonal of the array
117  contain the min(M,N)-by-N upper trapezoidal matrix R (R is
118  upper triangular if m >= n); the elements below the diagonal,
119  with the array TAU, represent the orthogonal matrix Q as a
120  product of min(m,n) elementary reflectors.
121  */
122  &lda, //The leading dimension of the array A. LDA >= max(1,M).
123  tau, /*Dimension (min(M,N))
124  The scalar factors of the elementary reflectors
125  */
126  work, //Internal working array. dimension (MAX(1,LWORK))
127  &dimWork, //The dimension of the array WORK. LWORK >= max(1,N).
128  &info //status
129  );
130 
131 
132  if(info != 0){
133  std::cout << "dgeqrf_:" << -info << "th element had an illegal value" << std::endl;
135  }
136 
137  //A now contains the R matrix in its upper triangular (in lapack convention)
138  C = A;
139 
140  //2) Invert R
141  dtrtri_((char*)"U",(char*)"N",&dimTau,C.data,&lda,&info);
142  if(info!=0){
143  if(info < 0)
144  std::cout << "dtrtri_:"<< -info << "th element had an illegal value" << std::endl;
145  else if(info > 0){
146  std::cout << "dtrtri_:R("<< info << "," <<info << ")"<< " is exactly zero. The triangular matrix is singular and its inverse can not be computed." << std::endl;
147  std::cout << "R=" << std::endl << C << std::endl;
148  }
150  }
151 
152  //3) Zero-fill R^-1
153  //the matrix is upper triangular for lapack but lower triangular for visp
154  //we fill it with zeros above the diagonal (where we don't need the values)
155  for(unsigned int i=0;i<C.getRows();i++)
156  for(unsigned int j=0;j<C.getRows();j++)
157  if(j>i) C[i][j] = 0.;
158 
159 
160  dimWork = -1;
161  int ldc = lda;
162 
163  //4) Transpose Q and left-multiply it by R^-1
164  //get R^-1*tQ
165  //C contains R^-1
166  //A contains Q
167  dormqr_((char*)"R", (char*)"T", &rowNum, &colNum, &dimTau, A.data, &lda, tau, C.data, &ldc, work, &dimWork, &info);
168  if(info != 0){
169  std::cout << "dormqr_:Preparation"<< -info << "th element had an illegal value" << std::endl;
171  }
172  dimWork = allocate_work(&work);
173 
174  dormqr_((char*)"R", (char*)"T", &rowNum, &colNum, &dimTau, A.data, &lda, tau, C.data, &ldc, work, &dimWork, &info);
175 
176  if(info != 0){
177  std::cout << "dormqr_:"<< -info << "th element had an illegal value" << std::endl;
179  }
180  delete[] tau;
181  delete[] work;
182  }catch(vpMatrixException&){
183  delete[] tau;
184  delete[] work;
185  throw;
186  }
187 
188  return C;
189 
190 }
191 #endif
192 
224 #if defined(VISP_HAVE_LAPACK)
225 vpMatrix
227 {
228 
229  if ( rowNum != colNum)
230  {
231  vpERROR_TRACE("\n\t\tCannot invert a non-square vpMatrix") ;
233  "Cannot invert a non-square vpMatrix")) ;
234  }
235 #ifdef VISP_HAVE_LAPACK
236  return inverseByQRLapack();
237 #endif
238 }
239 
240 #endif
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
#define vpERROR_TRACE
Definition: vpDebug.h:379
double * data
address of the first element of the data array
Definition: vpMatrix.h:116
vpMatrix inverseByQR() const
unsigned int rowNum
number of rows
Definition: vpMatrix.h:110
unsigned int getCols() const
Return the number of columns of the matrix.
Definition: vpMatrix.h:159
error that can be emited by the vpMatrix class and its derivates
unsigned int colNum
number of columns
Definition: vpMatrix.h:112
unsigned int getRows() const
Return the number of rows of the matrix.
Definition: vpMatrix.h:157
vpMatrix inverseByQRLapack() const
Definition: vpMatrix_qr.cpp:73