TooN
Lapack_Cholesky.h
1 // -*- c++ -*-
2 
3 // Copyright (C) 2009 Tom Drummond (twd20@cam.ac.uk)
4 
5 //All rights reserved.
6 //
7 //Redistribution and use in source and binary forms, with or without
8 //modification, are permitted provided that the following conditions
9 //are met:
10 //1. Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //2. Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 //
16 //THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
17 //AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 //IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 //ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
20 //LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 //CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 //SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 //INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 //CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 //ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 //POSSIBILITY OF SUCH DAMAGE.
27 
28 
29 #ifndef TOON_INCLUDE_LAPACK_CHOLESKY_H
30 #define TOON_INCLUDE_LAPACK_CHOLESKY_H
31 
32 #include <TooN/TooN.h>
33 
34 #include <TooN/lapack.h>
35 
36 #include <assert.h>
37 
38 namespace TooN {
39 
40 
69 template <int Size, typename Precision=DefaultPrecision>
71 public:
72 
73  Lapack_Cholesky(){}
74 
75  template<class P2, class B2>
77  : my_cholesky(m), my_cholesky_lapack(m) {
78  SizeMismatch<Size,Size>::test(m.num_rows(), m.num_cols());
79  do_compute();
80  }
81 
83  Lapack_Cholesky(int size) : my_cholesky(size,size), my_cholesky_lapack(size,size) {}
84 
85  template<class P2, class B2> void compute(const Matrix<Size, Size, P2, B2>& m){
86  SizeMismatch<Size,Size>::test(m.num_rows(), m.num_cols());
87  SizeMismatch<Size,Size>::test(m.num_rows(), my_cholesky.num_rows());
88  my_cholesky_lapack=m;
89  do_compute();
90  }
91 
92 
93 
94  void do_compute(){
95  FortranInteger N = my_cholesky.num_rows();
96  FortranInteger info;
97  potrf_("L", &N, my_cholesky_lapack.my_data, &N, &info);
98  for (int i=0;i<N;i++) {
99  int j;
100  for (j=0;j<=i;j++) {
101  my_cholesky[i][j]=my_cholesky_lapack[j][i];
102  }
103  // LAPACK does not set upper triangle to zero,
104  // must be done here
105  for (;j<N;j++) {
106  my_cholesky[i][j]=0;
107  }
108  }
109  assert(info >= 0);
110  if (info > 0) {
111  my_rank = info-1;
112  } else {
113  my_rank = N;
114  }
115  }
116 
117  int rank() const { return my_rank; }
118 
119  template <int Size2, typename P2, typename B2>
120  Vector<Size, Precision> backsub (const Vector<Size2, P2, B2>& v) const {
121  SizeMismatch<Size,Size2>::test(my_cholesky.num_cols(), v.size());
122 
123  Vector<Size, Precision> result(v);
124  FortranInteger N=my_cholesky.num_rows();
125  FortranInteger NRHS=1;
126  FortranInteger info;
127  potrs_("L", &N, &NRHS, my_cholesky_lapack.my_data, &N, result.my_data, &N, &info);
128  assert(info==0);
129  return result;
130  }
131 
132  template <int Size2, int Cols2, typename P2, typename B2>
134  SizeMismatch<Size,Size2>::test(my_cholesky.num_cols(), m.num_rows());
135 
137  FortranInteger N=my_cholesky.num_rows();
138  FortranInteger NRHS=m.num_cols();
139  FortranInteger info;
140  potrs_("L", &N, &NRHS, my_cholesky_lapack.my_data, &N, result.my_data, &N, &info);
141  assert(info==0);
142  return result;
143  }
144 
145  template <int Size2, typename P2, typename B2>
146  Precision mahalanobis(const Vector<Size2, P2, B2>& v) const {
147  return v * backsub(v);
148  }
149 
150  Matrix<Size,Size,Precision> get_L() const {
151  return my_cholesky;
152  }
153 
154  Precision determinant() const {
155  Precision det = my_cholesky[0][0];
156  for (int i=1; i<my_cholesky.num_rows(); i++)
157  det *= my_cholesky[i][i];
158  return det*det;
159  }
160 
161  Matrix<> get_inverse() const {
162  Matrix<Size, Size, Precision> M(my_cholesky.num_rows(),my_cholesky.num_rows());
163  M=my_cholesky_lapack;
164  FortranInteger N = my_cholesky.num_rows();
165  FortranInteger info;
166  potri_("L", &N, M.my_data, &N, &info);
167  assert(info == 0);
168  for (int i=1;i<N;i++) {
169  for (int j=0;j<i;j++) {
170  M[i][j]=M[j][i];
171  }
172  }
173  return M;
174  }
175 
176 private:
177  Matrix<Size,Size,Precision> my_cholesky;
178  Matrix<Size,Size,Precision> my_cholesky_lapack;
179  FortranInteger my_rank;
180 };
181 
182 
183 }
184 
185 #endif
Pretty generic SFINAE introspection generator.
Definition: vec_test.cc:21
A matrix.
Definition: matrix.hh:105
Decomposes a positive-semidefinite symmetric matrix A (such as a covariance) into L*L^T...
Definition: Lapack_Cholesky.h:70
Lapack_Cholesky(int size)
Constructor for Size=Dynamic.
Definition: Lapack_Cholesky.h:83
Definition: size_mismatch.hh:103