TooN 2.1
internal/diagmatrix.h
00001 //-*- c++ -*-
00002 //
00003 // Copyright (C) 2009 Tom Drummond (twd20@cam.ac.uk),
00004 // Ed Rosten (er258@cam.ac.uk)
00005 //
00006 // This file is part of the TooN Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 
00032 
00033 namespace TooN {
00034 
00035     namespace Internal
00036     {
00037         //Dummy struct for Diagonal operator
00038         template<int Size, typename Precision, typename Base>
00039         struct DiagMatrixOp;
00040     }
00041 
00042     template<int Size, typename Precision, typename Base>
00043     struct Operator<Internal::DiagMatrixOp<Size, Precision, Base> >
00044     {
00045         public:
00046         ///@name Constructors
00047         ///@{
00048 
00049 
00050         inline Operator() {}
00051         inline Operator(int size_in) : my_vector(size_in) {}
00052         inline Operator(Precision* data) : my_vector(data) {}
00053         inline Operator(Precision* data, int size_in) : my_vector(data,size_in) {}
00054         inline Operator(Precision* data_in, int size_in, int stride_in, Internal::Slicing)
00055             : my_vector(data_in, size_in, stride_in, Internal::Slicing() ) {}
00056 
00057         // constructors to allow return value optimisations
00058         // construction from 0-ary operator
00059         ///my_vector constructed from a TooN::Operator 
00060         template <class Op>
00061         inline Operator(const Operator<Op>& op)
00062             : my_vector (op)
00063         {
00064             op.eval(my_vector);
00065         }
00066         
00067         // constructor from arbitrary vector
00068         template<int Size2, typename Precision2, typename Base2>
00069         inline Operator(const Vector<Size2,Precision2,Base2>& from)
00070             : my_vector(from.size())
00071         {
00072             my_vector=from;
00073         }
00074         ///@}
00075 
00076 
00077         ///@name Operator members
00078         ///@{
00079         template<int R, int C, class P, class B>
00080         void eval(Matrix<R,C,P,B>& m) const {
00081             SizeMismatch<Size, Size>::test(m.num_rows(), m.num_cols());
00082             m = Zeros;
00083             m.diagonal_slice() = my_vector;
00084         }
00085 
00086         ///The vector used to hold the leading diagonal.
00087         Vector<Size,Precision,Base> my_vector;
00088     };
00089 
00090 /**
00091 @class DiagonalMatrix 
00092 A diagonal matrix
00093 
00094 Support is limited but diagonal matrices can be multiplied by vectors, matrices
00095 or diagonal matrices on either side.
00096 
00097 Diagonal matrices can be created from vectors by using the <code> as_diagonal() 
00098 </code> member function:
00099 
00100 @code
00101 Vector<3> v = makeVector(1,2,3);
00102 Vector<3> v2 = v.as_diagonal() * v;   // v2 = (1,4,9)
00103 @endcode
00104 
00105 A vector can be obtained from the diagonal matrix by using the
00106 <code> diagonal_slice() </code> member function.
00107 @ingroup gLinAlg
00108  **/
00109 template<int Size=Dynamic, typename Precision=DefaultPrecision, typename Base=Internal::VBase>
00110 struct DiagonalMatrix: public Operator<Internal::DiagMatrixOp<Size, Precision, Base> > {
00111 public:
00112     ///@name Constructors
00113     ///@{
00114     
00115     inline DiagonalMatrix() {}
00116     inline DiagonalMatrix(int size_in) : Operator<Internal::DiagMatrixOp<Size, Precision, Base> >(size_in) {}
00117     inline DiagonalMatrix(Precision* data) : Operator<Internal::DiagMatrixOp<Size, Precision, Base> >(data) {}
00118     inline DiagonalMatrix(Precision* data, int size_in) : Operator<Internal::DiagMatrixOp<Size, Precision, Base> >(data,size_in) {}
00119     inline DiagonalMatrix(Precision* data_in, int size_in, int stride_in, Internal::Slicing)
00120         : Operator<Internal::DiagMatrixOp<Size, Precision, Base> >(data_in, size_in, stride_in, Internal::Slicing() ) {}
00121 
00122     // constructors to allow return value optimisations
00123     // construction from 0-ary operator
00124     ///my_vector constructed from a TooN::Operator 
00125     template <class Op>
00126     inline DiagonalMatrix(const Operator<Op>& op)
00127         : Operator<Internal::DiagMatrixOp<Size, Precision, Base> > (op)
00128     {
00129         op.eval(this->my_vector);
00130     }
00131     
00132     // constructor from arbitrary vector
00133     template<int Size2, typename Precision2, typename Base2>
00134     inline DiagonalMatrix(const Vector<Size2,Precision2,Base2>& from)
00135         : Operator<Internal::DiagMatrixOp<Size, Precision, Base> >(from.size())
00136     {
00137         this->my_vector=from;
00138     }
00139     ///@}
00140 
00141 
00142 
00143     ///Index the leading elements on the diagonal 
00144     Precision& operator[](int i){return this->my_vector[i];}
00145     ///Index the leading elements on the diagonal 
00146     const Precision& operator[](int i) const {return this->my_vector[i];}
00147     
00148     ///Return the leading diagonal as a vector.
00149     typename Vector<Size, Precision, Base>::as_slice_type diagonal_slice() {
00150         return this->my_vector.as_slice();
00151     }
00152 
00153     ///Return the leading diagonal as a vector.
00154     const typename Vector<Size, Precision, Base>::as_slice_type diagonal_slice() const {
00155         return this->my_vector.as_slice();
00156     }
00157 
00158     DiagonalMatrix<Size, Precision> operator-() const
00159     {
00160         return -this->my_vector;
00161     }
00162 };
00163 
00164 
00165 template<int S1, typename P1, typename B1, int S2, typename P2, typename B2>
00166 inline Vector<Internal::Sizer<S1,S2>::size, typename Internal::MultiplyType<P1,P2>::type>
00167 operator*(const DiagonalMatrix<S1,P1,B1>& d, const Vector<S2,P2,B2>& v){
00168     return diagmult(d.my_vector,v);
00169 }
00170 
00171 template<int S1, typename P1, typename B1, int S2, typename P2, typename B2>
00172 inline Vector<Internal::Sizer<S1,S2>::size, typename Internal::MultiplyType<P1,P2>::type>
00173 operator*( const Vector<S1,P1,B1>& v, const DiagonalMatrix<S2,P2,B2>& d){
00174     return diagmult(v,d.my_vector);
00175 }
00176 
00177 // perhaps not the safest way to do this as we're returning the same operator used to normally make vectors
00178 template<int S1, typename P1, typename B1, int S2, typename P2, typename B2>
00179 inline DiagonalMatrix<Internal::Sizer<S1,S2>::size, typename Internal::MultiplyType<P1,P2>::type>
00180 operator*( const DiagonalMatrix<S1,P1,B1>& d1, const DiagonalMatrix<S2,P2,B2>& d2){
00181     SizeMismatch<S1,S2>::test(d1.my_vector.size(),d2.my_vector.size());
00182     return Operator<Internal::VPairwise<Internal::Multiply,S1,P1,B1,S2,P2,B2> >(d1.my_vector,d2.my_vector);
00183 }
00184 
00185 template<int R, int C, int Size, typename P1, typename P2, typename B1, typename B2>
00186 Matrix<R, C, typename Internal::MultiplyType<P1,P2>::type>
00187 operator* (const Matrix<R, C, P1, B1>& m, const DiagonalMatrix<Size, P2, B2>& d){
00188     return diagmult(m,d.my_vector);
00189 }
00190 
00191 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00192 Matrix<R, C, typename Internal::MultiplyType<P1,P2>::type>
00193 operator* (const DiagonalMatrix<Size,P1,B1>& d, const Matrix<R,C,P2,B2>& m)
00194 {
00195     return diagmult(d.my_vector, m);
00196 }
00197 
00198 }