00001
00002 #ifndef vpdt_eigen_sym_matrix_h_
00003 #define vpdt_eigen_sym_matrix_h_
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <vnl/algo/vnl_symmetric_eigensystem.h>
00016 #include <vpdl/vpdt/vpdt_field_traits.h>
00017 #include <vpdl/vpdt/vpdt_field_default.h>
00018 #include <vpdl/vpdt/vpdt_access.h>
00019 #include <vcl_limits.h>
00020 #include <vcl_cassert.h>
00021
00022
00023
00024 template<class T, unsigned int n>
00025 inline void vnl_symmetric_eigensystem_compute(const vnl_matrix_fixed<T,n,n>& A,
00026 vnl_matrix_fixed<T,n,n>& V,
00027 vnl_vector_fixed<T,n>& D)
00028 {
00029 vnl_matrix_ref<T> Vr(n,n,V.data_block());
00030 vnl_vector_ref<T> Dr(n,D.data_block());
00031 vnl_symmetric_eigensystem_compute(A.as_ref(),Vr,Dr);
00032 }
00033
00034
00035
00036 template<class T, unsigned int n=0>
00037 class vpdt_eigen_sym_matrix
00038 {
00039 public:
00040
00041 typedef typename vpdt_field_default<T,n>::type vector;
00042
00043 typedef typename vpdt_field_traits<vector>::matrix_type matrix;
00044
00045
00046
00047
00048 vpdt_eigen_sym_matrix(unsigned int var_dim = n)
00049 {
00050 vpdt_set_size(eigen_vec_,var_dim);
00051 vpdt_set_size(eigen_val_,var_dim);
00052 eigen_vec_.set_identity();
00053 eigen_val_.fill(T(0));
00054 }
00055
00056
00057 vpdt_eigen_sym_matrix(const matrix& evec, const vector& eval)
00058 : eigen_vec_(evec), eigen_val_(eval)
00059 {
00060 assert(are_evec_orthonormal());
00061 }
00062
00063
00064 vpdt_eigen_sym_matrix(const matrix& m)
00065 {
00066 set_matrix(m);
00067 }
00068
00069
00070 unsigned int dimension() const { return eigen_val_.size(); }
00071
00072
00073 const matrix& eigenvectors() const { return eigen_vec_; }
00074
00075
00076 const vector& eigenvalues() const { return eigen_val_; }
00077
00078
00079 void set_eigenvectors(const matrix& m)
00080 {
00081 eigen_vec_ = m;
00082 assert(are_evec_orthonormal());
00083 }
00084
00085
00086 void set_eigenvalues(const vector& v) { eigen_val_ = v; }
00087
00088
00089 void set_size(unsigned int dim)
00090 {
00091 vpdt_set_size(eigen_vec_,dim);
00092 vpdt_set_size(eigen_val_,dim);
00093 eigen_vec_.set_identity();
00094 eigen_val_.fill(T(0));
00095 }
00096
00097
00098 void set_matrix(const matrix& m)
00099 {
00100 const unsigned int dim = vpdt_size(m);
00101 vpdt_set_size(eigen_vec_,dim);
00102 vpdt_set_size(eigen_val_,dim);
00103 vnl_symmetric_eigensystem_compute(m, eigen_vec_, eigen_val_);
00104 }
00105
00106
00107 vpdt_eigen_sym_matrix<T,n>& operator*=(const T& val)
00108 {
00109 const unsigned int dim = eigen_val_.size();
00110 for (unsigned int i=0; i<dim; ++i)
00111 eigen_val_[i] *= val;
00112 return *this;
00113 }
00114
00115
00116
00117 void form_matrix(matrix& m) const
00118 {
00119 const unsigned int dim = eigen_val_.size();
00120 vpdt_set_size(m,dim);
00121 m.fill(T(0));
00122
00123 for (unsigned int i = 0; i < dim; ++i)
00124 for (unsigned int k = 0; k < dim; ++k){
00125 T tmp = eigen_vec_[i][k] * eigen_val_[k];
00126 for (unsigned int j = i; j < dim; ++j)
00127 m[i][j] += tmp * eigen_vec_[j][k];
00128 }
00129
00130
00131 for (unsigned int i = 0; i < dim; ++i)
00132 for (unsigned int j = i+1; j < dim; ++j)
00133 m[j][i] = m[i][j];
00134 }
00135
00136
00137
00138 void form_inverse(matrix& m) const
00139 {
00140 const unsigned int dim = eigen_val_.size();
00141 vpdt_set_size(m,dim);
00142 m.fill(T(0));
00143
00144 for (unsigned int k = 0; k < dim; ++k){
00145 if (eigen_val_[k] <= T(0))
00146 continue;
00147 for (unsigned int i = 0; i < dim; ++i){
00148 T tmp = eigen_vec_[i][k] / eigen_val_[k];
00149 for (unsigned int j = i; j < dim; ++j)
00150 m[i][j] += tmp * eigen_vec_[j][k];
00151 }
00152 }
00153
00154
00155 for (unsigned int i = 0; i < dim; ++i)
00156 for (unsigned int j = i+1; j < dim; ++j)
00157 m[j][i] = m[i][j];
00158 }
00159
00160
00161 void product(const vector& x, vector& y) const
00162 {
00163 const unsigned int dim = eigen_val_.size();
00164 vpdt_set_size(y,dim);
00165 vpdt_fill(y,T(0));
00166 for (unsigned int i = 0; i < dim; ++i){
00167 T t_i = T(0);
00168 for (unsigned int j = 0; j < dim; ++j){
00169 t_i += eigen_vec_[j][i] * x[j];
00170 }
00171 t_i *= eigen_val_[i];
00172 for (unsigned int j = 0; j < dim; ++j){
00173 y[j] += eigen_vec_[j][i] * t_i;
00174 }
00175 }
00176 }
00177
00178
00179 void inverse_product(const vector& x, vector& y) const
00180 {
00181 const unsigned int dim = eigen_val_.size();
00182 vpdt_set_size(y,dim);
00183 vpdt_fill(y,T(0));
00184 for (unsigned int i = 0; i < dim; ++i){
00185 T t_i = T(0);
00186 for (unsigned int j = 0; j < dim; ++j){
00187 t_i += eigen_vec_[j][i] * x[j];
00188 }
00189 t_i /= eigen_val_[i];
00190 for (unsigned int j = 0; j < dim; ++j){
00191 y[j] += eigen_vec_[j][i] * t_i;
00192 }
00193 }
00194 }
00195
00196
00197 T quad_form(const vector& x) const
00198 {
00199 const unsigned int dim = eigen_val_.size();
00200 T val = T(0);
00201 for (unsigned int i = 0; i < dim; ++i){
00202 T tmp = T(0);
00203 for (unsigned int j = 0; j < dim; ++j){
00204 tmp += eigen_vec_[j][i] * x[j];
00205 }
00206 val += tmp*tmp*eigen_val_[i];
00207 }
00208 return val;
00209 }
00210
00211
00212 T inverse_quad_form(const vector& x) const
00213 {
00214 const unsigned int dim = eigen_val_.size();
00215 T val = T(0);
00216 for (unsigned int i = 0; i < dim; ++i){
00217 if (eigen_val_[i] <= T(0))
00218 return vcl_numeric_limits<T>::infinity();
00219 T tmp = T(0);
00220 for (unsigned int j = 0; j < dim; ++j){
00221 tmp += eigen_vec_[j][i] * x[j];
00222 }
00223 val += tmp*tmp/eigen_val_[i];
00224 }
00225 return val;
00226 }
00227
00228
00229 T determinant() const
00230 {
00231 const unsigned int dim = eigen_val_.size();
00232 T det = T(1);
00233 for (unsigned int i=0; i<dim; ++i)
00234 det *= eigen_val_[i];
00235 return det;
00236 }
00237
00238 private:
00239
00240 matrix eigen_vec_;
00241
00242 vector eigen_val_;
00243
00244
00245 bool are_evec_orthonormal() const
00246 {
00247
00248 return false;
00249 }
00250 };
00251
00252
00253
00254
00255
00256 template<class T>
00257 class vpdt_eigen_sym_matrix<T,1> {};
00258
00259
00260
00261
00262
00263
00264 template <class F, class Disambiguate= void>
00265 struct vpdt_eigen_sym_matrix_gen;
00266
00267
00268 template <class F>
00269 struct vpdt_eigen_sym_matrix_gen<F,typename vpdt_field_traits<F>::type_is_vector>
00270 {
00271 typedef vpdt_eigen_sym_matrix<typename vpdt_field_traits<F>::scalar_type,
00272 vpdt_field_traits<F>::dimension> type;
00273 };
00274
00275
00276 template <class F>
00277 struct vpdt_eigen_sym_matrix_gen<F,typename vpdt_field_traits<F>::type_is_scalar>
00278 {
00279 typedef typename vpdt_field_traits<F>::matrix_type type;
00280 };
00281
00282
00283
00284
00285
00286
00287 template <class T>
00288 inline void vpdt_set_size(vpdt_eigen_sym_matrix<T,0>& m, unsigned int s)
00289 {
00290 m.set_size(s);
00291 }
00292
00293
00294
00295 template <class T, unsigned int n>
00296 inline void vpdt_fill(vpdt_eigen_sym_matrix<T,n>& m, const T& val)
00297 {
00298 typename vpdt_eigen_sym_matrix<T,n>::vector v;
00299 vpdt_set_size(v,m.dimension());
00300 vpdt_fill(v,val);
00301 m.set_eigenvalues(v);
00302 }
00303
00304
00305 #endif // vpdt_eigen_sym_matrix_h_