00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef TOON_INCLUDE_CHOLESKY_H
00032 #define TOON_INCLUDE_CHOLESKY_H
00033
00034 #include <TooN/TooN.h>
00035
00036 namespace TooN {
00037
00038
00068 template <int Size=Dynamic, class Precision=DefaultPrecision>
00069 class Cholesky {
00070 public:
00071 Cholesky(){}
00072
00076 template<class P2, class B2>
00077 Cholesky(const Matrix<Size, Size, P2, B2>& m)
00078 : my_cholesky(m) {
00079 SizeMismatch<Size,Size>::test(m.num_rows(), m.num_cols());
00080 do_compute();
00081 }
00082
00084 Cholesky(int size) : my_cholesky(size,size) {}
00085
00086
00089 template<class P2, class B2> void compute(const Matrix<Size, Size, P2, B2>& m){
00090 SizeMismatch<Size,Size>::test(m.num_rows(), m.num_cols());
00091 SizeMismatch<Size,Size>::test(m.num_rows(), my_cholesky.num_rows());
00092 my_cholesky=m;
00093 do_compute();
00094 }
00095
00096 private:
00097 void do_compute() {
00098 int size=my_cholesky.num_rows();
00099 for(int col=0; col<size; col++){
00100 Precision inv_diag = 1;
00101 for(int row=col; row < size; row++){
00102
00103 Precision val = my_cholesky(row,col);
00104 for(int col2=0; col2<col; col2++){
00105
00106 val-=my_cholesky(col2,col)*my_cholesky(row,col2);
00107 }
00108 if(row==col){
00109
00110 my_cholesky(row,col)=val;
00111 inv_diag=1/val;
00112 } else {
00113
00114 my_cholesky(col,row)=val;
00115
00116 my_cholesky(row,col)=val*inv_diag;
00117 }
00118 }
00119 }
00120 }
00121 public:
00122
00125 template<int Size2, class P2, class B2>
00126 Vector<Size, Precision> backsub (const Vector<Size2, P2, B2>& v) const {
00127 int size=my_cholesky.num_rows();
00128 SizeMismatch<Size,Size2>::test(size, v.size());
00129
00130
00131 Vector<Size, Precision> y(size);
00132 for(int i=0; i<size; i++){
00133 Precision val = v[i];
00134 for(int j=0; j<i; j++){
00135 val -= my_cholesky(i,j)*y[j];
00136 }
00137 y[i]=val;
00138 }
00139
00140
00141 for(int i=0; i<size; i++){
00142 y[i]/=my_cholesky(i,i);
00143 }
00144
00145
00146 Vector<Size,Precision> result(size);
00147 for(int i=size-1; i>=0; i--){
00148 Precision val = y[i];
00149 for(int j=i+1; j<size; j++){
00150 val -= my_cholesky(j,i)*result[j];
00151 }
00152 result[i]=val;
00153 }
00154
00155 return result;
00156 }
00157
00160 template<int Size2, int C2, class P2, class B2>
00161 Matrix<Size, C2, Precision> backsub (const Matrix<Size2, C2, P2, B2>& m) const {
00162 int size=my_cholesky.num_rows();
00163 SizeMismatch<Size,Size2>::test(size, m.num_rows());
00164
00165
00166 Matrix<Size, C2, Precision> y(size, m.num_cols());
00167 for(int i=0; i<size; i++){
00168 Vector<C2, Precision> val = m[i];
00169 for(int j=0; j<i; j++){
00170 val -= my_cholesky(i,j)*y[j];
00171 }
00172 y[i]=val;
00173 }
00174
00175
00176 for(int i=0; i<size; i++){
00177 y[i]*=(1/my_cholesky(i,i));
00178 }
00179
00180
00181 Matrix<Size,C2,Precision> result(size, m.num_cols());
00182 for(int i=size-1; i>=0; i--){
00183 Vector<C2,Precision> val = y[i];
00184 for(int j=i+1; j<size; j++){
00185 val -= my_cholesky(j,i)*result[j];
00186 }
00187 result[i]=val;
00188 }
00189 return result;
00190 }
00191
00192
00195
00196 Matrix<Size,Size,Precision> get_inverse(){
00197 Matrix<Size,Size,Precision>I(Identity(my_cholesky.num_rows()));
00198 return backsub(I);
00199 }
00200
00202 Precision determinant(){
00203 Precision answer=my_cholesky(0,0);
00204 for(int i=1; i<my_cholesky.num_rows(); i++){
00205 answer*=my_cholesky(i,i);
00206 }
00207 return answer;
00208 }
00209
00210 template <int Size2, typename P2, typename B2>
00211 Precision mahalanobis(const Vector<Size2, P2, B2>& v) const {
00212 return v * backsub(v);
00213 }
00214
00215 Matrix<Size,Size,Precision> get_unscaled_L() const {
00216 Matrix<Size,Size,Precision> m(my_cholesky.num_rows(),
00217 my_cholesky.num_rows());
00218 m=Identity;
00219 for (int i=1;i<my_cholesky.num_rows();i++) {
00220 for (int j=0;j<i;j++) {
00221 m(i,j)=my_cholesky(i,j);
00222 }
00223 }
00224 return m;
00225 }
00226
00227 Matrix<Size,Size,Precision> get_D() const {
00228 Matrix<Size,Size,Precision> m(my_cholesky.num_rows(),
00229 my_cholesky.num_rows());
00230 m=Zeros;
00231 for (int i=0;i<my_cholesky.num_rows();i++) {
00232 m(i,i)=my_cholesky(i,i);
00233 }
00234 return m;
00235 }
00236
00237 Matrix<Size,Size,Precision> get_L() const {
00238 Matrix<Size,Size,Precision> m(my_cholesky.num_rows(),
00239 my_cholesky.num_rows());
00240 m=Zeros;
00241 for (int j=0;j<my_cholesky.num_cols();j++) {
00242 Precision sqrtd=sqrt(my_cholesky(j,j));
00243 m(j,j)=sqrtd;
00244 for (int i=j+1;i<my_cholesky.num_rows();i++) {
00245 m(i,j)=my_cholesky(i,j)*sqrtd;
00246 }
00247 }
00248 return m;
00249 }
00250
00251 private:
00252 Matrix<Size,Size,Precision> my_cholesky;
00253 };
00254
00255
00256 }
00257
00258 #endif