TooN 2.0.0-beta8
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 
00036 /**
00037 @class DiagonalMatrix 
00038 A diagonal matrix
00039 
00040 Support is limited but diagonal matrices can be multiplied by vectors, matrices
00041 or diagonal matrices on either side.
00042 
00043 Diagonal matrices can be created from vectors by using the <code> as_diagonal() 
00044 </code> member function:
00045 
00046 @code
00047 Vector<3> v = makeVector(1,2,3);
00048 Vector<3> v2 = v.as_diagonal() * v;   // v2 = (1,4,9)
00049 @endcode
00050 
00051 A vector can be obtained from the diagonal matrix by using the
00052 <code> diagonal_slice() </code> member function.
00053 @ingroup gLinAlg
00054  **/
00055 template<int Size=Dynamic, typename Precision=DefaultPrecision, typename Base=Internal::VBase>
00056 struct DiagonalMatrix {
00057 public:
00058     ///@name Constructors
00059     ///@{
00060     
00061     inline DiagonalMatrix() {}
00062     inline DiagonalMatrix(int size_in) : my_vector(size_in) {}
00063     inline DiagonalMatrix(Precision* data) : my_vector(data) {}
00064     inline DiagonalMatrix(Precision* data, int size_in) : my_vector(data,size_in) {}
00065     inline DiagonalMatrix(Precision* data_in, int size_in, int stride_in, Internal::Slicing)
00066         : my_vector(data_in, size_in, stride_in, Internal::Slicing() ) {}
00067 
00068     // constructors to allow return value optimisations
00069     // construction from 0-ary operator
00070     ///my_vector constructed from a TooN::Operator 
00071     template <class Op>
00072     inline DiagonalMatrix(const Operator<Op>& op)
00073         : my_vector (op)
00074     {
00075         op.eval(my_vector);
00076     }
00077     
00078     // constructor from arbitrary vector
00079     template<int Size2, typename Precision2, typename Base2>
00080     inline DiagonalMatrix(const Vector<Size2,Precision2,Base2>& from)
00081         : my_vector(from.size())
00082     {
00083         my_vector=from;
00084     }
00085     ///@}
00086 
00087 
00088 
00089     ///Index the leading elements on the diagonal 
00090     Precision& operator[](int i){return my_vector[i];}
00091     ///Index the leading elements on the diagonal 
00092     const Precision& operator[](int i) const {return my_vector[i];}
00093     
00094     ///Return the leading diagonal as a vector.
00095     typename Vector<Size, Precision, Base>::as_slice_type diagonal_slice() {
00096         return my_vector.as_slice();
00097     }
00098 
00099     ///Return the leading diagonal as a vector.
00100     const typename Vector<Size, Precision, Base>::as_slice_type diagonal_slice() const {
00101         return my_vector.as_slice();
00102     }
00103     
00104     ///The vector used to hold the leading diagonal.
00105     Vector<Size,Precision,Base> my_vector;
00106 };
00107 
00108 
00109 template<int S1, typename P1, typename B1, int S2, typename P2, typename B2>
00110 inline Vector<Internal::Sizer<S1,S2>::size, typename Internal::MultiplyType<P1,P2>::type>
00111 operator*(const DiagonalMatrix<S1,P1,B1>& d, const Vector<S2,P2,B2>& v){
00112     return diagmult(d.my_vector,v);
00113 }
00114 
00115 template<int S1, typename P1, typename B1, int S2, typename P2, typename B2>
00116 inline Vector<Internal::Sizer<S1,S2>::size, typename Internal::MultiplyType<P1,P2>::type>
00117 operator*( const Vector<S1,P1,B1>& v, const DiagonalMatrix<S2,P2,B2>& d){
00118     return diagmult(v,d.my_vector);
00119 }
00120 
00121 // perhaps not the safest way to do this as we're returning the same operator used to normally make vectors
00122 template<int S1, typename P1, typename B1, int S2, typename P2, typename B2>
00123 inline DiagonalMatrix<Internal::Sizer<S1,S2>::size, typename Internal::MultiplyType<P1,P2>::type>
00124 operator*( const DiagonalMatrix<S1,P1,B1>& d1, const DiagonalMatrix<S2,P2,B2>& d2){
00125     SizeMismatch<S1,S2>::test(d1.my_vector.size(),d2.my_vector.size());
00126     return Operator<Internal::VPairwise<Internal::Multiply,S1,P1,B1,S2,P2,B2> >(d1.my_vector,d2.my_vector);
00127 }
00128 
00129 template<int R, int C, int Size, typename P1, typename P2, typename B1, typename B2>
00130 Matrix<R, C, typename Internal::MultiplyType<P1,P2>::type>
00131 operator* (const Matrix<R, C, P1, B1>& m, const DiagonalMatrix<Size, P2, B2>& d){
00132     return diagmult(m,d.my_vector);
00133 }
00134 
00135 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00136 Matrix<R, C, typename Internal::MultiplyType<P1,P2>::type>
00137 operator* (const DiagonalMatrix<Size,P1,B1>& d, const Matrix<R,C,P2,B2>& m)
00138 {
00139     return diagmult(d.my_vector, m);
00140 }
00141 
00142 }