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 //! \brief
00048 //! Immediate trace (sum of diagonal elements) of A + B.
00049 //! A and B must be square and have the same dimensions.
00050 template<typename T1, typename T2>
00051 inline
00052 typename T1::elem_type
00053 trace(const Glue<T1,T2,glue_plus>& X)
00054   {
00055   arma_extra_debug_sigprint();
00056 
00057   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00058   
00059   const unwrap<T1> tmp1(X.A);
00060   const unwrap<T2> tmp2(X.B);
00061   
00062   typedef typename T1::elem_type eT;
00063   
00064   const Mat<eT>& A = tmp1.M;
00065   const Mat<eT>& B = tmp2.M;
00066   
00067   arma_debug_check( (A.n_rows != B.n_rows) || (A.n_cols != B.n_cols), "trace(): incompatible matrix dimensions");
00068   arma_debug_check( !A.is_square(), "trace(): matrices must be square");
00069   
00070   return trace(A) + trace(B);
00071   }
00072 
00073 
00074 
00075 //! \brief
00076 //! Immediate trace (sum of diagonal elements) of A - B.
00077 //! A and B must be square and have the same dimensions.
00078 template<typename T1, typename T2>
00079 inline
00080 typename T1::elem_type
00081 trace(const Glue<T1,T2,glue_minus>& X)
00082   {
00083   arma_extra_debug_sigprint();
00084 
00085   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00086   
00087   const unwrap<T1> tmp1(X.A);
00088   const unwrap<T2> tmp2(X.B);
00089   
00090   typedef typename T1::elem_type eT;
00091   
00092   const Mat<eT>& A = tmp1.M;
00093   const Mat<eT>& B = tmp2.M;
00094   
00095   arma_debug_check( (A.n_rows != B.n_rows) || (A.n_cols != B.n_cols), "trace(): incompatible matrix dimensions");
00096   arma_debug_check( !A.is_square(), "trace(): matrices must be square");
00097   
00098   return trace(A) - trace(B);
00099   }
00100 
00101 
00102 
00103 //! \brief
00104 //! Immediate trace (sum of diagonal elements) of A % B (where % is the element-wise multiplication operator).
00105 //! A and B must be square and have the same dimensions.
00106 template<typename T1, typename T2>
00107 inline
00108 typename T1::elem_type
00109 trace(const Glue<T1,T2,glue_schur>& X)
00110   {
00111   arma_extra_debug_sigprint();
00112   
00113   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00114 
00115   const unwrap<T1> tmp1(X.A);
00116   const unwrap<T2> tmp2(X.B);
00117   
00118   typedef typename T1::elem_type eT;
00119   
00120   const Mat<eT>& A = tmp1.M;
00121   const Mat<eT>& B = tmp2.M;
00122   
00123   arma_debug_check( (A.n_rows != B.n_rows) || (A.n_cols != B.n_cols), "trace(): incompatible matrix dimensions" );
00124   arma_debug_check( !A.is_square(), "trace(): matrices must be square" );
00125   
00126   eT val = eT(0);
00127   for(u32 i=0; i<A.n_rows; ++i)
00128     {
00129     val += A.at(i,i) * B.at(i,i);
00130     }
00131   
00132   return val;
00133   }
00134 
00135 
00136 
00137 //! \brief
00138 //! trace (sum of diagonal elements) of k * T1,
00139 //! where k is a scalar and T1 is converted to a dense matrix.
00140 template<typename T1>
00141 inline
00142 typename T1::elem_type
00143 trace(const Op<T1,op_scalar_times>& in)
00144   {
00145   arma_extra_debug_sigprint();
00146   
00147   typedef typename T1::elem_type eT;
00148   
00149   const unwrap<T1> tmp(in.m);
00150   const Mat<eT>& X = tmp.M;
00151   
00152   return trace(X) * in.aux;
00153   }
00154 
00155 
00156 
00157 //! trace (sum of diagonal elements) of a diagonal matrix
00158 template<typename eT>
00159 inline
00160 eT
00161 trace(const Op<Mat<eT>, op_diagmat>& X)
00162   {
00163   arma_extra_debug_sigprint();
00164   
00165   return trace(X.m);
00166   }
00167 
00168 
00169 
00170 template<typename eT>
00171 inline
00172 eT
00173 trace(const Op<Mat<eT>, op_diagmat_vec>& X)
00174   {
00175   arma_extra_debug_sigprint();
00176   
00177   const Mat<eT>& A = X.m;
00178   arma_debug_check( !A.is_vec(), "trace(): internal error: can't interpret as a vector" );
00179   
00180   
00181   return accu(X.m);
00182   }
00183 
00184 
00185 //! @}