fn_trace.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2009 NICTA
00002 // 
00003 // Authors:
00004 // - Conrad Sanderson (conradsand at ieee dot org)
00005 // 
00006 // This file is part of the Armadillo C++ library.
00007 // It is provided without any warranty of fitness
00008 // for any purpose. You can redistribute this file
00009 // and/or modify it under the terms of the GNU
00010 // Lesser General Public License (LGPL) as published
00011 // by the Free Software Foundation, either version 3
00012 // of the License or (at your option) any later version.
00013 // (see http://www.opensource.org/licenses for more info)
00014 
00015 
00016 //! \addtogroup fn_trace
00017 //! @{
00018 
00019 
00020 //! Immediate trace (sum of diagonal elements) of a square dense matrix
00021 template<typename T1>
00022 inline
00023 typename T1::elem_type
00024 trace(const Base<typename T1::elem_type,T1>& X)
00025   {
00026   arma_extra_debug_sigprint();
00027   
00028   typedef typename T1::elem_type eT;
00029   
00030   const unwrap<T1> A_tmp(X.get_ref());
00031   const Mat<eT>& A = A_tmp.M;
00032 
00033   arma_debug_check( !A.is_square(), "trace(): matrix must be square" );
00034   
00035   eT val = eT(0);
00036   
00037   for(u32 i=0; i<A.n_rows; ++i)
00038     {
00039     val += A.at(i,i);
00040     }
00041   
00042   return val;
00043   }
00044 
00045 
00046 
00047 #if defined(ARMA_GOOD_COMPILER)
00048 
00049 
00050 
00051 //! \brief
00052 //! Immediate trace (sum of diagonal elements) of A + B.
00053 //! A and B must be square and have the same dimensions.
00054 template<typename T1, typename T2>
00055 inline
00056 typename T1::elem_type
00057 trace(const Glue<T1,T2,glue_plus>& X)
00058   {
00059   arma_extra_debug_sigprint();
00060 
00061   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00062   
00063   const unwrap<T1> tmp1(X.A);
00064   const unwrap<T2> tmp2(X.B);
00065   
00066   typedef typename T1::elem_type eT;
00067   
00068   const Mat<eT>& A = tmp1.M;
00069   const Mat<eT>& B = tmp2.M;
00070   
00071   arma_debug_assert_same_size(A, B, "matrix addition");
00072   arma_debug_check( !A.is_square(), "trace(): matrices must be square");
00073   
00074   return trace(A) + trace(B);
00075   }
00076 
00077 
00078 
00079 //! \brief
00080 //! Immediate trace (sum of diagonal elements) of A - B.
00081 //! A and B must be square and have the same dimensions.
00082 template<typename T1, typename T2>
00083 inline
00084 typename T1::elem_type
00085 trace(const Glue<T1,T2,glue_minus>& X)
00086   {
00087   arma_extra_debug_sigprint();
00088 
00089   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00090   
00091   const unwrap<T1> tmp1(X.A);
00092   const unwrap<T2> tmp2(X.B);
00093   
00094   typedef typename T1::elem_type eT;
00095   
00096   const Mat<eT>& A = tmp1.M;
00097   const Mat<eT>& B = tmp2.M;
00098 
00099   arma_debug_assert_same_size(A, B, "matrix subtraction");
00100   arma_debug_check( !A.is_square(), "trace(): matrices must be square");
00101   
00102   return trace(A) - trace(B);
00103   }
00104 
00105 
00106 
00107 //! \brief
00108 //! Immediate trace (sum of diagonal elements) of A % B (where % is the element-wise multiplication operator).
00109 //! A and B must be square and have the same dimensions.
00110 template<typename T1, typename T2>
00111 inline
00112 typename T1::elem_type
00113 trace(const Glue<T1,T2,glue_schur>& X)
00114   {
00115   arma_extra_debug_sigprint();
00116   
00117   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00118 
00119   const unwrap<T1> tmp1(X.A);
00120   const unwrap<T2> tmp2(X.B);
00121   
00122   typedef typename T1::elem_type eT;
00123   
00124   const Mat<eT>& A = tmp1.M;
00125   const Mat<eT>& B = tmp2.M;
00126   
00127   arma_debug_assert_same_size(A, B, "matrix schur product");
00128   arma_debug_check( !A.is_square(), "trace(): matrices must be square" );
00129   
00130   eT val = eT(0);
00131   for(u32 i=0; i<A.n_rows; ++i)
00132     {
00133     val += A.at(i,i) * B.at(i,i);
00134     }
00135   
00136   return val;
00137   }
00138 
00139 
00140 
00141 //! \brief
00142 //! trace (sum of diagonal elements) of k * T1,
00143 //! where k is a scalar and T1 is converted to a dense matrix.
00144 template<typename T1>
00145 inline
00146 typename T1::elem_type
00147 trace(const Op<T1,op_scalar_times>& in)
00148   {
00149   arma_extra_debug_sigprint();
00150   
00151   typedef typename T1::elem_type eT;
00152   
00153   const unwrap<T1> tmp(in.m);
00154   const Mat<eT>& X = tmp.M;
00155   
00156   return trace(X) * in.aux;
00157   }
00158 
00159 
00160 
00161 //! trace (sum of diagonal elements) of a diagonal matrix
00162 template<typename eT>
00163 inline
00164 eT
00165 trace(const Op<Mat<eT>, op_diagmat>& X)
00166   {
00167   arma_extra_debug_sigprint();
00168   
00169   return trace(X.m);
00170   }
00171 
00172 
00173 
00174 template<typename eT>
00175 inline
00176 eT
00177 trace(const Op<Mat<eT>, op_diagmat_vec>& X)
00178   {
00179   arma_extra_debug_sigprint();
00180   
00181   const Mat<eT>& A = X.m;
00182   arma_debug_check( !A.is_vec(), "trace(): internal error: can't interpret as a vector" );
00183   
00184   
00185   return accu(X.m);
00186   }
00187 
00188 
00189 
00190 #endif
00191 
00192 
00193 
00194 //! @}