TooN
QR_Lapack.h
1 // Copyright Edward Rosten 2012
2 
3 //All rights reserved.
4 //
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
7 //are met:
8 //1. Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //2. Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 //THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
15 //AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 //IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 //ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
18 //LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 //CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 //SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 //INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 //CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 //ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 //POSSIBILITY OF SUCH DAMAGE.
25 
26 #ifndef TOON_INCLUDE_QR_LAPACK_H
27 #define TOON_INCLUDE_QR_LAPACK_H
28 
29 
30 #include <TooN/TooN.h>
31 #include <TooN/lapack.h>
32 #include <algorithm>
33 #include <utility>
34 
35 namespace TooN{
36 
56 template<int Rows=Dynamic, int Cols=Rows, class Precision=double>
57 class QR_Lapack{
58 
59  private:
60  static const int square_Size = (Rows>=0 && Cols>=0)?(Rows<Cols?Rows:Cols):Dynamic;
61 
62  public:
67  template<int R, int C, class P, class B>
68  QR_Lapack(const Matrix<R,C,P,B>& m, bool p=0)
69  :copy(m),tau(square_size()),
70  Q(square_size(), square_size()),
71  do_pivoting(p),
72  pivot(Zeros(m.num_cols()))
73  {
74  //pivot is set to all zeros, which means all columns are free columns
75  //and can take part in column pivoting.
76 
77  compute();
78  }
79 
82  {
83  return copy;
84  }
85 
88  {
89  return Q;
90  }
91 
95  {
96  return pivot;
97  }
98 
99  private:
100 
101  void compute()
102  {
103  FortranInteger M = copy.num_rows();
104  FortranInteger N = copy.num_cols();
105 
106  FortranInteger LWORK=-1;
107  FortranInteger INFO;
108  FortranInteger lda = M;
109 
110  Precision size;
111 
112  //Set up the pivot vector
113  if(do_pivoting)
114  pivot = Zeros;
115  else
116  for(int i=0; i < pivot.size(); i++)
117  pivot[i] = i+1;
118 
119 
120  //Compute the working space
121  geqp3_(&M, &N, copy.get_data_ptr(), &lda, pivot.get_data_ptr(), tau.get_data_ptr(), &size, &LWORK, &INFO);
122 
123  LWORK = (FortranInteger) size;
124 
125  Precision* work = new Precision[LWORK];
126 
127  geqp3_(&M, &N, copy.get_data_ptr(), &lda, pivot.get_data_ptr(), tau.get_data_ptr(), work, &LWORK, &INFO);
128 
129 
130  if(INFO < 0)
131  std::cerr << "error in QR, INFO was " << INFO << std::endl;
132 
133  //The upper "triangle+" of copy is R
134  //The lower right and tau contain enough information to reconstruct Q
135 
136  //LAPACK provides a handy function to do the reconstruction
137  Q = copy.template slice<0,0,square_Size, square_Size>(0,0,square_size(), square_size());
138 
139  FortranInteger K = square_size();
140  M=K;
141  N=K;
142  lda = K;
143  orgqr_(&M, &N, &K, Q.get_data_ptr(), &lda, tau.get_data_ptr(), work, &LWORK, &INFO);
144 
145  if(INFO < 0)
146  std::cerr << "error in QR, INFO was " << INFO << std::endl;
147 
148  delete [] work;
149 
150  //Now zero out the lower triangle
151  for(int r=1; r < square_size(); r++)
152  for(int c=0; c<r; c++)
153  copy[r][c] = 0;
154 
155  //Now fix the pivot matrix.
156  //We need to go from FORTRAN to C numbering.
157  for(int i=0; i < pivot.size(); i++)
158  pivot[i]--;
159  }
160 
164  bool do_pivoting;
166 
167 
168  int square_size()
169  {
170  return std::min(copy.num_rows(), copy.num_cols());
171  }
172 };
173 
174 }
175 
176 
177 #endif
Pretty generic SFINAE introspection generator.
Definition: vec_test.cc:21
A vector.
Definition: vector.hh:126
const Matrix< square_Size, square_Size, Precision, ColMajor > & get_Q()
Return Q.
Definition: QR_Lapack.h:87
Performs QR decomposition.
Definition: QR_Lapack.h:57
const Vector< Cols, int > & get_P()
Return the permutation vector.
Definition: QR_Lapack.h:94
const Matrix< Rows, Cols, Precision, ColMajor > & get_R()
Return R.
Definition: QR_Lapack.h:81
QR_Lapack(const Matrix< R, C, P, B > &m, bool p=0)
Construct the QR decomposition of a matrix.
Definition: QR_Lapack.h:68