uBLASmatrix.hpp

Go to the documentation of this file.
00001 /*
00002  * Bayes++ the Bayesian Filtering Library
00003  * Copyright (c) 2002 Michael Stevens
00004  * See accompanying Bayes++.htm for terms and conditions of use.
00005  *
00006  * $Id: uBLASmatrix.hpp 562 2006-04-05 20:46:23 +0200 (Wed, 05 Apr 2006) mistevens $
00007  */
00008 
00009 /*
00010  * Common type independant uBlas interface
00011  *  Should be include after base types have been defined
00012  *
00013  * Everything in namespace Bayes_filter_matrix is intended to support the matrix storage
00014  * and algebra requirements of the library. Therefore the interfaces and implementation is
00015  * not intended to be stable. Nor is this a general purpose adapator for uBLAS
00016  *
00017  * Note on row_major matrices
00018  *  The implementation uses row major extensively. The computation of symetric products P*P' is 
00019  *  most efficient with row operations. These products are used extensively so the default
00020  *  is to use row_major matrices
00021  */
00022 
00023 /* Filter Matrix Namespace */
00024 namespace Bayesian_filter_matrix
00025 {
00026                         // Allow use a few functions in own namespace (particular useful for compilers with Konig lookup)
00027 using ublas::row;
00028 using ublas::column;
00029 using ublas::trans;
00030 using ublas::prod;      // These do not apply to the templated prod<temp> funtions
00031 using ublas::inner_prod;
00032 using ublas::outer_prod;
00033 
00034 enum EmptyTag {Empty};  // Tag type used for empty matrix constructor
00035 
00036                         // Old compiler workaround removed from new uBLAS
00037 #ifndef BOOST_UBLAS_TYPENAME
00038 #define BOOST_UBLAS_TYPENAME typename
00039 #endif
00040 
00041 #if (BOOST_VERSION >= 103100)
00042 using ublas::noalias;
00043 #else
00044 namespace detail
00045 {
00046     // Assignment proxy.
00047     // Provides temporary free assigment when LHS has no alias on RHS
00048     template<class C>
00049     class noalias_proxy {
00050     public:
00051         BOOST_UBLAS_INLINE
00052         noalias_proxy (C& lval):
00053             lval_ (lval) {}
00054 
00055         template <class E>
00056         BOOST_UBLAS_INLINE
00057         void operator= (const E& e) {
00058             lval_.assign (e);
00059         }
00060 
00061         template <class E>
00062         BOOST_UBLAS_INLINE
00063         void operator+= (const E& e) {
00064             lval_.plus_assign (e);
00065         }
00066 
00067         template <class E>
00068         BOOST_UBLAS_INLINE
00069         void operator-= (const E& e) {
00070             lval_.minus_assign (e);
00071         }
00072 
00073     private:  // nonassignable
00074         void operator=( const noalias_proxy& );
00075     private:
00076         C& lval_;
00077     };
00078 
00079 }//namespace detail
00080 
00081 // Improve syntax of effcient assignment where no aliases of LHS appear on the RHS
00082 //  noalias(lhs) = rhs_expression
00083 template <class E>
00084 BOOST_UBLAS_INLINE
00085 detail::noalias_proxy<E> noalias (ublas::matrix_expression<E>& lvalue) {
00086     return detail::noalias_proxy<E> (lvalue() );
00087 }
00088 template <class E>
00089 BOOST_UBLAS_INLINE
00090 detail::noalias_proxy<E> noalias (ublas::vector_expression<E>& lvalue) {
00091     return detail::noalias_proxy<E> (lvalue() );
00092 }
00093 
00094 #endif
00095 
00096 
00097 namespace detail        // Lots of implementation detail
00098 {
00099 
00100 /*
00101  * Filter Vec type
00102  */
00103 template <class VecBase>
00104 class FMVec : public VecBase
00105 {
00106 public:
00107     typedef typename VecBase::value_type value_type;
00108     typedef typename VecBase::vector_temporary_type vector_temporary_type;
00109 
00110     // No Default Constructor. Empty creation is very error prone
00111     explicit FMVec(EmptyTag) : VecBase()
00112     {}  // Empty constructor
00113     explicit FMVec(std::size_t size) : VecBase(size)
00114     {}  // Normal sized constructor
00115     FMVec(const FMVec& c) : VecBase(static_cast<const VecBase&>(c))
00116     {}  // Copy constructor
00117     template <class E>
00118     explicit FMVec(const ublas::vector_expression<E>& e) : VecBase(e)
00119     {}  // vector_expression copy constructor
00120     template <class E>
00121     FMVec(const ublas::matrix_column<E>& e) : VecBase(e)
00122     {}  // conversion copy constructor, hides the implict copy required for matrix column access
00123 
00124     template <class E>
00125     FMVec& operator= (const ublas::vector_expression<E>& r)
00126     {   // Expression assignment; may be dependant on r
00127         VecBase::operator=(r);
00128         return *this;
00129     }
00130     FMVec& operator= (const FMVec& r)
00131     {   // Vector assignment; independant
00132         VecBase::assign(r);
00133         return *this;
00134     }
00135 
00136     // Sub-range selection operators
00137     const ublas::vector_range<const VecBase> sub_range(std::size_t b, std::size_t e) const
00138     {
00139         return ublas::vector_range<const VecBase>(*this, ublas::range(b,e));
00140     }
00141     ublas::vector_range<VecBase> sub_range(std::size_t b, std::size_t e)
00142     {
00143         return ublas::vector_range<VecBase>(*this, ublas::range(b,e));
00144     }
00145 };
00146 
00147 
00148 /*
00149  * Filter Matrix class template. Augmentation for uBlas MatrixBase
00150  */
00151 template <class MatrixBase>
00152 class FMMatrix : public MatrixBase
00153 {
00154 public:
00155     typedef typename MatrixBase::value_type value_type;
00156     typedef typename MatrixBase::vector_temporary_type vector_temporary_type;
00157     typedef typename MatrixBase::matrix_temporary_type matrix_temporary_type;
00158 
00159     // No Default Constructor. Empty creation is very error prone
00160     explicit FMMatrix(EmptyTag) : MatrixBase()
00161     {}  // Empty constructor
00162     FMMatrix(std::size_t size1, std::size_t size2) : MatrixBase(size1,size2)
00163     {}  // Normal sized constructor
00164     FMMatrix(const FMMatrix& c) : MatrixBase(static_cast<const MatrixBase&>(c))
00165     {}  // Copy constructor
00166     template <class E>
00167     explicit FMMatrix(const ublas::matrix_expression<E>& e) : MatrixBase(e)
00168     {}  // matrix_expression copy constructor
00169 
00170     template <class E>
00171     FMMatrix& operator= (const ublas::matrix_expression<E>& r)
00172     {   // Expression assignment; may be dependant on r
00173         MatrixBase::operator=(r);
00174         return *this;
00175     }
00176     FMMatrix& operator= (const FMMatrix& r)
00177     {   // Matrix assignment; independant
00178         MatrixBase::assign (r);
00179         return *this;
00180     }
00181 
00182     // Row,Column vector proxies
00183     typedef ublas::matrix_row<FMMatrix> Row;
00184     typedef const ublas::matrix_row<const FMMatrix> const_Row;
00185     typedef ublas::matrix_column<FMMatrix> Column;
00186     typedef const ublas::matrix_column<const FMMatrix> const_Column;
00187 
00188     // Vector proxies from iterators - static members dependant on MatrixBase type
00189     // ri() returns container associated with iterator. static_cast required as typeof(ri()) may not be typeof(MM)
00190     static Row rowi(const typename MatrixBase::iterator1& ri)
00191     {
00192         return Row(static_cast<FMMatrix&>(ri()), ri.index1());
00193     }
00194     static const_Row rowi(const typename MatrixBase::const_iterator1& ri)
00195     {
00196         return const_Row(static_cast<const FMMatrix&>(ri()), ri.index1());
00197     }
00198     static Column columni(const typename MatrixBase::iterator2& ci)
00199     {
00200         return Column(static_cast<FMMatrix&>(ci()), ci.index2());
00201     }
00202     static const_Column columni(const typename MatrixBase::const_iterator2& ci)
00203     {
00204         return const_Column(static_cast<const FMMatrix&>(ci()), ci.index2());
00205     }
00206 
00207     // Sub-range selection operators
00208     ublas::matrix_range<const MatrixBase>
00209     sub_matrix(std::size_t s1, std::size_t e1, std::size_t s2, std::size_t e2) const
00210     {
00211         return ublas::matrix_range<const MatrixBase> (*this, ublas::range(s1,e1), ublas::range(s2,e2));
00212     }
00213     ublas::matrix_range<MatrixBase>
00214     sub_matrix(std::size_t s1, std::size_t e1, std::size_t s2, std::size_t e2)
00215     {
00216         return ublas::matrix_range<MatrixBase> (*this, ublas::range(s1,e1), ublas::range(s2,e2));
00217     }
00218 
00219     // Requires boost_1.30.0 which has a generalised matrix_vector_slice
00220     ublas::matrix_vector_slice<const MatrixBase>
00221     sub_column(std::size_t s1, std::size_t e1, std::size_t s2) const 
00222     // Column vector s2 with rows [s1,e1)
00223     {
00224         return ublas::matrix_vector_slice<const MatrixBase> (*this, ublas::slice(s1,1,e1-s1), ublas::slice(s2,0,e1-s1));
00225     }
00226     ublas::matrix_vector_slice<MatrixBase>
00227     sub_column(std::size_t s1, std::size_t e1, std::size_t s2)
00228     // Column vector s2 with rows [s1,e1)
00229     {
00230         return ublas::matrix_vector_slice<MatrixBase> (*this, ublas::slice(s1,1,e1-s1), ublas::slice(s2,0,e1-s1));
00231     }
00232 };
00233 
00234 
00235 /*
00236  * Helper template to allow member construction before base class
00237  *  Boost version does not work as it passes by value
00238  */
00239 template <typename MemberType>
00240 class BaseFromMember
00241 {
00242 protected:
00243     MemberType member;
00244     explicit BaseFromMember() : member()
00245     {}
00246 
00247     template <typename T1>
00248     explicit BaseFromMember( const T1& x1 ) : member( x1 )
00249     {}
00250 
00251     template <typename T1, typename T2>
00252     explicit BaseFromMember( const T1& x1, const T2& x2 ) : member( x1, x2 )
00253     {}
00254 };
00255 
00256 
00257 /*
00258  * We require static type conversion between Symmetric matrices and equivilent row major matrices
00259  * Therefore we create symmetric matrix types, using a MatrixBase for storage
00260  * and wraps this in a symmetric_adaptor
00261  */
00262 template <class MatrixBase>
00263 class SymMatrixWrapper :
00264     private BaseFromMember<MatrixBase>,  // allow construction of MatrixBase member before symmetric_adaptor
00265     public ublas::symmetric_adaptor<MatrixBase, ublas::upper>
00266 {
00267     typedef BaseFromMember<MatrixBase> matrix_type;
00268     typedef ublas::symmetric_adaptor<MatrixBase, ublas::upper> symadaptor_type;
00269 public:
00270     typedef typename MatrixBase::value_type value_type;
00271     typedef typename MatrixBase::vector_temporary_type vector_temporary_type;
00272     typedef typename MatrixBase::matrix_temporary_type matrix_temporary_type;
00273 
00274     SymMatrixWrapper () : matrix_type(), symadaptor_type(matrix_type::member)
00275     {}
00276     SymMatrixWrapper (std::size_t size1, std::size_t size2) : matrix_type(size1,size2), symadaptor_type(matrix_type::member)
00277     {}  // Normal sized constructor
00278     explicit SymMatrixWrapper (const SymMatrixWrapper& r) : matrix_type(reinterpret_cast<const MatrixBase&>(r)), symadaptor_type(matrix_type::member)
00279     {}  // Explict copy construction referencing the copy reinterpreted as a MatrixBase
00280     template <class E>
00281     explicit SymMatrixWrapper (const ublas::matrix_expression<E>& e) : matrix_type(e), symadaptor_type(matrix_type::member)
00282     {}  // Explict matrix_expression conversion constructor
00283 
00284     template <class E>
00285     SymMatrixWrapper& operator=(const ublas::matrix_expression<E>& r)
00286     {
00287         symadaptor_type::operator=(r);
00288         return *this;
00289     }
00290 
00291     // Conversions straight to a FMMatrix, equivilent to a RowMatrix types
00292     const FMMatrix<MatrixBase>& asRowMatrix() const
00293     {
00294         return static_cast<const FMMatrix<MatrixBase>& >(matrix_type::member);
00295     }
00296     FMMatrix<MatrixBase>& asRowMatrix()
00297     {
00298         return static_cast<FMMatrix<MatrixBase>& >(matrix_type::member);
00299     }
00300 
00301     // Matrix storage members
00302     void clear()
00303     {   matrix_type::member.clear();
00304     }
00305     void resize(std::size_t nsize1, std::size_t nsize2, bool preserve = true)
00306     {
00307         matrix_type::member.resize(nsize1, nsize2, preserve);
00308     }
00309 };
00310 
00311 }//namespace detail
00312 
00313 
00314 
00315 /*
00316  * Vector / Matrix types
00317  *  Finally the definitions !
00318  */
00319 using detail::FMVec;        // Template class for template parameter matching
00320 using detail::FMMatrix;
00321 
00322                             // Default types
00323 typedef FMVec<detail::BaseVector> Vec;
00324 typedef FMMatrix<detail::BaseRowMatrix> RowMatrix;
00325 typedef RowMatrix Matrix;
00326 typedef FMMatrix<detail::BaseColMatrix> ColMatrix;
00327 typedef FMMatrix<detail::SymMatrixWrapper<detail::BaseRowMatrix> > SymMatrix;
00328 typedef FMMatrix<detail::BaseUpperTriMatrix> UTriMatrix;
00329 typedef FMMatrix<detail::BaseLowerTriMatrix> LTriMatrix;
00330 typedef FMMatrix<detail::BaseDiagMatrix> DiagMatrix;
00331 
00332                             // Explicitly dense types
00333 typedef FMVec<detail::BaseDenseVector> DenseVec;
00334 typedef FMMatrix<detail::BaseDenseRowMatrix> DenseRowMatrix;
00335 typedef DenseRowMatrix DenseMatrix;
00336 typedef FMMatrix<detail::BaseDenseColMatrix> DenseColMatrix;
00337 typedef FMMatrix<detail::SymMatrixWrapper<detail::BaseDenseRowMatrix> > DenseSymMatrix;
00338 typedef FMMatrix<detail::BaseDenseUpperTriMatrix> DenseUTriMatrix;
00339 typedef FMMatrix<detail::BaseDenseLowerTriMatrix> DenseLTriMatrix;
00340 typedef FMMatrix<detail::BaseDenseDiagMatrix> DenseDiagMatrix;
00341 
00342                             // Explicitly sparse types (any of the gappy types)
00343 #ifdef BAYES_FILTER_GAPPY
00344 typedef FMVec<detail::BaseSparseVector> SparseVec;
00345 typedef FMMatrix<detail::BaseDenseRowMatrix> SparseRowMatrix;
00346 typedef SparseRowMatrix SparseMatrix;
00347 typedef FMMatrix<detail::BaseSparseColMatrix> SparseColMatrix;
00348 typedef FMMatrix<detail::SymMatrixWrapper<detail::BaseSparseRowMatrix> > SparseSymMatrix;
00349 #endif
00350 
00351 
00352 /*
00353  * Matrix Adaptors, simply hide the uBLAS details
00354  */
00355 template <class M>
00356 const ublas::triangular_adaptor<const M, ublas::upper>
00357  UpperTri(const M& m)
00358 /*
00359  * View Upper triangle of m
00360  * ISSUE VC7 cannot cope with UTriMatrix::functor1_type
00361  */
00362 {
00363     return ublas::triangular_adaptor<const M, ublas::upper>(m);
00364 }
00365 
00366 template <class M>
00367 const ublas::triangular_adaptor<const M, ublas::lower>
00368  LowerTri(const M& m)
00369 /*
00370  * View Lower triangle of m
00371  */
00372 {
00373     return ublas::triangular_adaptor<const M, ublas::lower>(m);
00374 }
00375 
00376 
00377 
00378 /*
00379  * Matrix Support Operations
00380  */
00381 template <class Base>
00382 ublas::matrix_vector_range<FMMatrix<Base> >
00383  diag(FMMatrix<Base>& M, std::size_t n)
00384 {   // Return a vector proxy to the first n diagonal elements of M
00385     return ublas::matrix_vector_range<FMMatrix<Base> >(M, ublas::range(0,n), ublas::range(0,n));
00386 }
00387 
00388 template <class Base>
00389 const ublas::matrix_vector_range<const FMMatrix<Base> >
00390  diag(const FMMatrix<Base>& M, std::size_t n)
00391 {   // Return a vector proxy to the first n diagonal elements of M
00392     return ublas::matrix_vector_range<const FMMatrix<Base> >(M, ublas::range(0,n), ublas::range(0,n));
00393 }
00394 
00395 template <class Base>
00396 ublas::matrix_vector_range<FMMatrix<Base> >
00397  diag(FMMatrix<Base>& M)
00398 {   // Return a vector proxy to the diagonal elements of M
00399     const std::size_t common_size = std::min(M.size1(),M.size2());
00400     return ublas::matrix_vector_range<FMMatrix<Base> >(M, ublas::range(0,common_size), ublas::range(0,common_size));
00401 }
00402 
00403 template <class Base>
00404 const ublas::matrix_vector_range<const FMMatrix<Base> >
00405  diag(const FMMatrix<Base>& M)
00406 {   // Return a vector proxy to the diagonal elements of M
00407     const std::size_t common_size = std::min(M.size1(),M.size2());
00408     return ublas::matrix_vector_range<const FMMatrix<Base> >(M, ublas::range(0,common_size), ublas::range(0,common_size));
00409 }
00410 
00411 template <class Base>
00412 void identity(FMMatrix<Base>& I)
00413 {   // Set I to generalised Identity matrix. Clear I and set diag(I) to one
00414     I.clear();
00415                             // Set common diagonal elements
00416     std::size_t common_size = std::min(I.size1(),I.size2());
00417     typedef typename Base::value_type Base_value_type;
00418     diag(I).assign (ublas::scalar_vector<Base_value_type>(common_size, Base_value_type(1)));
00419 }
00420 
00421 
00422 
00423 /*
00424  * Symmetric Positive (Semi) Definate multiplication: X*S*X' and X'*S*X
00425  *  The name is slightly misleading. The result is actually only PD if S is PD
00426  *  Algorithms are intended to exploit the symmerty of the result
00427  *  and also where possible the row by row multiplication inherent in X*X'
00428  */
00429 
00430 namespace detail {      // mult_SPD now an implementation detail
00431     
00432 template <class MatrixX>
00433 void mult_SPD (const MatrixX& X, const Vec& s, SymMatrix& P)
00434 /*
00435  * Symmetric Positive (Semi) Definate multiply: P += X*diag_matrix(s)*X'
00436  */
00437 {
00438     Vec::const_iterator si, send = s.end();
00439     typename MatrixX::const_iterator1 Xa = X.begin1();
00440     const typename MatrixX::const_iterator1 Xend = X.end1();
00441     typename MatrixX::const_iterator1 Xb;
00442 
00443     // P(a,b) = X.row(a) * X.row(b)
00444     for (; Xa != Xend; ++Xa)                // Iterate Rows
00445     {
00446         typename MatrixX::const_Row Xav = MatrixX::rowi(Xa);
00447         Xb = Xa;                            // Start at the row Xa only one triangle of symetric result required
00448         for (; Xb != Xend; ++Xb)
00449         {
00450             SymMatrix::value_type p = 0;    // Tripple vector inner product
00451             typename MatrixX::const_Row Xbv = MatrixX::rowi(Xb);
00452             for (si = s.begin(); si != send; ++si) {
00453                 Vec::size_type i = si.index();
00454                 p += Xav[i] * (*si) * Xbv[i];
00455             }
00456             P(Xa.index1(),Xb.index1()) += p;
00457         }
00458     }
00459 }
00460 
00461 template <class MatrixX>
00462 void mult_SPDT (const MatrixX& X, const Vec& s, SymMatrix& P)
00463 /*
00464  * Symmetric Positive (Semi) Definate multiply: P += X'*diag_matrix(s)*X
00465  */
00466 {
00467     Vec::const_iterator si, send = s.end();
00468     typename MatrixX::const_iterator2 Xa = X.begin2();
00469     const typename MatrixX::const_iterator2 Xend = X.end2();
00470     typename MatrixX::const_iterator2 Xb;
00471 
00472     // P(a,b) = X.col(a) * X.col(b)
00473     for (; Xa != Xend; ++Xa)                // Iterate vectors
00474     {
00475         typename MatrixX::const_Column Xav = MatrixX::columni(Xa);
00476         Xb = Xa;                            // Start at the row Xa only one triangle of symertric result required
00477         for (; Xb != Xend; ++Xb)
00478         {                                   // Tripple vector inner product
00479             SymMatrix::value_type p = 0;
00480             typename MatrixX::const_Column Xbv = MatrixX::columni(Xb);
00481             for (si = s.begin(); si != send; ++si) {
00482                 Vec::size_type i = si.index();
00483                 p += Xav[i] * (*si) * Xbv[i];
00484             }
00485             P(Xa.index2(),Xb.index2()) += p;
00486         }
00487     }
00488 }
00489 
00490 }//namespace detail
00491 
00492 
00493 /*
00494  * prod_SPD - uBLAS Expression templates for X*X' and X*X'
00495  * Functions are only defined for the type for which the operation is efficient
00496  * ISSUE Although numerically symmetric, uBlas has no expression type to represent this property
00497  *  The result must be assigned to a symmetric container to exploit the symmetry
00498  */
00499 
00500 template <class E1, class E2>
00501 struct prod_expression_result
00502 {   // Provide ET result E1E2T_type of prod(matrix_expression<E1>,trans(matrix_expression<E2>)
00503     typedef BOOST_UBLAS_TYPENAME ublas::matrix_unary2_traits<E2, ublas::scalar_identity<BOOST_UBLAS_TYPENAME E2::value_type> >::result_type  E2T_type;
00504     typedef BOOST_UBLAS_TYPENAME ublas::matrix_matrix_binary_traits<BOOST_UBLAS_TYPENAME E1::value_type, E1,
00505                                         BOOST_UBLAS_TYPENAME E2T_type::value_type, E2T_type>::result_type  E1E2T_type;
00506 
00507     // Provide ET result E1TE2_type of prod(trans(matrix_expression<E1>),matrix_expression<E2>)
00508     typedef BOOST_UBLAS_TYPENAME ublas::matrix_unary2_traits<E1, ublas::scalar_identity<BOOST_UBLAS_TYPENAME E1::value_type> >::result_type  E1T_type;
00509     typedef BOOST_UBLAS_TYPENAME ublas::matrix_matrix_binary_traits<BOOST_UBLAS_TYPENAME E1T_type::value_type, E1T_type,
00510                                         BOOST_UBLAS_TYPENAME E2::value_type, E2>::result_type  E1TE2_type;
00511 };
00512 
00513  
00514 template<class E> inline
00515 typename prod_expression_result<E,E>::E1E2T_type
00516  prod_SPD (const ublas::matrix_expression<E>& X)
00517 /*
00518  * Symmetric Positive (Semi) Definate product: X*X'
00519  */
00520 {
00521     // ISSUE: uBLAS post Boost 1_31_0 introduces a trans(const matrix_expression<E>& e) which propogates the const expression type
00522     // Bypass this to avoid having to detect the Boost version
00523     return prod( X, trans(const_cast<ublas::matrix_expression<E>&>(X) ));
00524 }
00525 
00526 template<class EX, class ES, class ET> inline
00527 typename prod_expression_result<EX,ET>::E1E2T_type
00528  prod_SPD (const ublas::matrix_expression<EX>& X, const ublas::matrix_expression<ES>& S, ublas::matrix_expression<ET>& XStemp)
00529 /*
00530  * Symmetric Positive (Semi) Definate product: X*(X*S)', XStemp = X*S
00531  *  Result symmetric if S is symmetric
00532  */
00533 {
00534     return prod( X, trans(prod(X,S,XStemp())) );
00535 }
00536 
00537 template<class EX, class ES, class ET> inline
00538 ET prod_SPD (const ublas::matrix_expression<EX>& X, const ublas::vector_expression<ES>& s, ublas::matrix_expression<ET>& Ptemp)
00539 /*
00540  * Symmetric Positive (Semi) Definate product: X*diag_matrix(s)*X'
00541  * Precond: Ptemp must be size conformant with the product
00542  *  DEPRECATED With explicit Ptemp, do not rely on it's value
00543  */
00544 {
00545     Vec::const_iterator si, send = s().end();
00546     const EX& XX = X();
00547     typename EX::const_iterator1 Xa = XX.begin1();
00548     const typename EX::const_iterator1 Xend = XX.end1();
00549     typename EX::const_iterator1 Xb;
00550 
00551     // P(a,b) = sum(X.row(a) * s * X.row(b))
00552     for (; Xa != Xend; ++Xa)        // Iterate rows
00553     {
00554         typedef const ublas::matrix_row<const EX> EX_row;
00555         EX_row Xav (ublas::row(XX, Xa.index1()));
00556         Xb = Xa;                            // Start at the row Xa only one triangle of symetric result required
00557         for (; Xb != Xend; ++Xb)
00558         {
00559             typename EX::value_type p = 0;  // Triple vector inner product
00560             EX_row Xbv (ublas::row(XX, Xb.index1()));
00561             for (si = s().begin(); si != send; ++si) {
00562                 Vec::size_type i = si.index();
00563                 p += Xav[i] * (*si) * Xbv[i];
00564             }
00565             Ptemp()(Xa.index1(),Xb.index1()) = p;
00566             Ptemp()(Xb.index1(),Xa.index1()) = p;
00567         }
00568     }
00569     return Ptemp();
00570 }
00571 
00572 template<class EX, class ES> inline
00573 SymMatrix prod_SPD (const ublas::matrix_expression<EX>& X, const ublas::vector_expression<ES>& s)
00574 /*
00575  * Symmetric Positive (Semi) Definate product: X*diag_matrix(s)*X'
00576  * TODO requires a prod_diag(X,s)
00577  */
00578 {
00579     SymMatrix Ptemp(X().size1(),X().size1());
00580     Ptemp.clear();
00581 
00582     (void) prod_SPD (X(),s(), Ptemp);
00583     return Ptemp;
00584 }
00585 
00586 
00587 template<class E> inline
00588 typename prod_expression_result<E,E>::E1TE2_type
00589  prod_SPDT (const ublas::matrix_expression<E>& X)
00590 /*
00591  * Symmetric Positive (Semi) Definate product: X'*X
00592  */
00593 {
00594     // ISSUE: See prod_SPD
00595     return prod( trans(const_cast<ublas::matrix_expression<E>&>(X) ), X);
00596 }
00597 
00598 template<class EX, class ES, class ET> inline
00599 typename prod_expression_result<ET,EX>::E1TE2_type
00600  prod_SPDT (const ublas::matrix_expression<EX>& X, const ublas::matrix_expression<ES>& S, ublas::matrix_expression<ET>& SXtemp)
00601 /*
00602  * Symmetric Positive (Semi) Definate product: (S*X)'*X, SXtemp = S*X
00603  *  Result symmetric if S is symmetric
00604  */
00605 {
00606     return prod( trans(prod(S,X,SXtemp())), X);
00607 }
00608 
00609 template<class EX, class ES, class ET> inline
00610 ET prod_SPDT (const ublas::matrix_expression<EX>& X, const ublas::vector_expression<ES>& s, ublas::matrix_expression<ET>& Ptemp)
00611 /*
00612  * Symmetric Positive (Semi) Definate product: X'*diag_matrix(s)*X, Ptemp = return value
00613  * Precond: Ptemp must be size conformant with the product
00614  *  DEPRECATED With explicit Ptemp, do not rely on it's value
00615  */
00616 {
00617     const EX& XX = X();
00618     Vec::const_iterator si, send = s().end();
00619     typename EX::const_iterator2 Xa = X.begin2();
00620     const typename EX::const_iterator2 Xend = X.end2();
00621     typename EX::const_iterator2 Xb;
00622 
00623     // P(a,b) = sum(X.col(a) * s * X.col(b))
00624     for (; Xa != Xend; ++Xa)        // Iterate columns
00625     {
00626         typedef const ublas::matrix_column<const EX> EX_column;
00627         EX_column Xav = ublas::column(XX, Xa.index2());
00628         Xb = Xa;                            // Start at the column Xa only one triangle of symetric result required
00629         for (; Xb != Xend; ++Xb)
00630         {
00631             typename EX::value_type p = 0;  // Triple vector inner product
00632             EX_column Xbv = ublas::column(XX, Xb.index2());
00633             for (si = s().begin(); si != send; ++si) {
00634                 Vec::size_type i = si.index();
00635                 p += Xav[i] * (*si) * Xbv[i];
00636             }
00637             Ptemp()(Xa.index2(),Xb.index2()) = p;
00638             Ptemp()(Xb.index2(),Xa.index2()) = p;
00639         }
00640     }
00641     return Ptemp();
00642 }
00643 
00644 template<class EX, class ES> inline
00645 SymMatrix prod_SPDT (const ublas::matrix_expression<EX>& X, const ublas::vector_expression<ES>& s)
00646 /*
00647  * Symmetric Positive (Semi) Definate product: X'*diag_matrix(s)*X
00648  * TODO requires a prod_diag(X,s)
00649  */
00650 {
00651     SymMatrix Ptemp(X().size1(),X().size1());
00652     Ptemp.clear();
00653 
00654     (void) prod_SPDT (X(),s(), Ptemp);
00655     return Ptemp;
00656 }
00657 
00658 inline Vec::value_type prod_SPDT (const Vec& x, const Vec& s)
00659 /*
00660  * Symmetric Positive (Semi) Definate product: x'*diag_matrix(s)*x
00661  */
00662 {
00663     const Vec::const_iterator xi_end = x.end();
00664     Vec::const_iterator si = s.begin();
00665     Vec::const_iterator xi=x.begin();
00666     Vec::value_type p = Vec::value_type(0);
00667     while (xi != xi_end)
00668     {
00669         p += (*xi) * (*si) * (*xi);
00670         ++xi; ++ si;
00671     }
00672     
00673     return p;
00674 }
00675 
00676 inline Vec::value_type prod_SPDT (const Vec& x, const SymMatrix& S)
00677 /*
00678  * Symmetric Positive (Semi) Definate multiply: p = x'*S*x
00679  */
00680 {
00681     return inner_prod (x, prod(S,x) );
00682 }
00683 
00684 }//namespace

Generated on Wed Oct 4 22:57:23 2006 for Bayes++ Bayesian Filtering Classes by  doxygen 1.4.6