glue_minus_meat.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 glue_minus
00017 //! @{
00018 
00019 
00020 //! Immediate out = A-B
00021 template<typename eT>
00022 inline
00023 void
00024 glue_minus::apply(Mat<eT>& out, const Mat<eT>& A, const Mat<eT>& B)
00025   {
00026   arma_extra_debug_sigprint();
00027   
00028   arma_debug_assert_same_size(A, B, "matrix subtraction");
00029   
00030   // no aliasing problem
00031   out.set_size(A.n_rows,A.n_cols);
00032     
00033         eT* out_mem = out.memptr();
00034   const eT* A_mem   = A.mem;
00035   const eT* B_mem   = B.mem;
00036   
00037   const u32 n_elem  = A.n_elem;
00038   
00039   for(u32 i=0; i<n_elem; ++i)
00040     {
00041     out_mem[i] = A_mem[i] - B_mem[i];
00042     }
00043     
00044   }
00045 
00046 
00047 
00048 //! Immediate out = A-B-C
00049 template<typename eT>
00050 inline
00051 void
00052 glue_minus::apply(Mat<eT>& out, const Mat<eT>& A, const Mat<eT>& B, const Mat<eT>& C)
00053   {
00054   arma_extra_debug_sigprint();
00055   
00056   arma_debug_assert_same_size(A, B, "matrix subtraction");
00057   arma_debug_assert_same_size(A, C, "matrix subtraction");
00058   
00059   // no aliasing problem
00060   out.set_size(A.n_rows, A.n_cols);
00061     
00062         eT* out_mem = out.memptr();
00063   const eT* A_mem   = A.mem;
00064   const eT* B_mem   = B.mem;
00065   const eT* C_mem   = C.mem;
00066   
00067   const u32 n_elem = A.n_elem;
00068   
00069   for(u32 i=0; i<n_elem; ++i)
00070     {
00071     out_mem[i] = A_mem[i] - B_mem[i] - C_mem[i];
00072     }
00073   
00074   }
00075 
00076 
00077 
00078 //! Immediate out = A-B  (operands obtained from Glue)
00079 template<typename eT>
00080 inline
00081 void
00082 glue_minus::apply(Mat<eT>& out, const Glue<Mat<eT>,Mat<eT>,glue_minus>& X)
00083   {
00084   glue_minus::apply(out, X.A, X.B);
00085   }
00086 
00087 
00088 
00089 //! Immediate out = A-B-C  (operands obtained from Glue)
00090 template<typename eT>
00091 inline
00092 void
00093 glue_minus::apply(Mat<eT>& out, const Glue< Glue<Mat<eT>,Mat<eT>,glue_minus>, Mat<eT>, glue_minus> &X)
00094   {
00095   glue_minus::apply(out, X.A.A, X.A.B, X.B);
00096   }
00097 
00098 
00099 
00100 //! Immediate out = A-B-...-Z  (operands obtained from Glue)
00101 template<typename T1, typename T2>
00102 inline
00103 void
00104 glue_minus::apply(Mat<typename T1::elem_type>& out, const Glue<T1,T2,glue_minus>& X)
00105   {
00106   arma_extra_debug_sigprint();
00107   
00108   typedef typename T1::elem_type eT;
00109   
00110   const u32 N_mat = 1 + depth_lhs< glue_minus, Glue<T1,T2,glue_minus> >::num;
00111   arma_extra_debug_print( arma_boost::format("N_mat = %d") % N_mat );
00112 
00113 
00114   if(N_mat == 2)
00115     {
00116     const unwrap<T1> tmp1(X.A);
00117     const unwrap<T2> tmp2(X.B);
00118     
00119     glue_minus::apply(out, tmp1.M, tmp2.M);
00120     }
00121   else
00122     {
00123     const Mat<eT>* ptrs[N_mat];
00124     bool            del[N_mat];
00125 
00126     mat_ptrs<glue_minus, Glue<T1,T2,glue_minus> >::get_ptrs(ptrs, del, X);
00127     //mat_ptrs_outcheck<glue_minus, Glue<T1,T2,glue_minus> >::get_ptrs(ptrs, del, X, &out);
00128 
00129     for(u32 i=0; i<N_mat; ++i)  arma_extra_debug_print( arma_boost::format("ptrs[%d] = %x")  % i % ptrs[i] );
00130     for(u32 i=0; i<N_mat; ++i)  arma_extra_debug_print( arma_boost::format(" del[%d] = %d")  % i %  del[i] );
00131 
00132     const Mat<eT>& tmp_mat = *(ptrs[0]);
00133     
00134     for(u32 i=1; i<N_mat; ++i)
00135       {
00136       arma_debug_assert_same_size(tmp_mat, *(ptrs[i]), "matrix subtraction");
00137       }
00138   
00139     const u32 n_rows = ptrs[0]->n_rows;
00140     const u32 n_cols = ptrs[0]->n_cols;
00141     
00142     // no aliasing problem
00143     out.set_size(n_rows,n_cols);
00144     
00145     const u32 n_elem = ptrs[0]->n_elem;
00146     
00147     for(u32 j=0; j<n_elem; ++j)
00148       {
00149       eT acc = ptrs[0]->mem[j];
00150       
00151       for(u32 i=1; i<N_mat; ++i)
00152         {
00153         acc -= ptrs[i]->mem[j];
00154         }
00155       
00156       out[j] = acc;
00157       }
00158 
00159     for(u32 i=0; i<N_mat; ++i)
00160       {
00161       if(del[i] == true)
00162         {
00163         arma_extra_debug_print( arma_boost::format("delete ptrs[%d]") % i );
00164         delete ptrs[i];
00165         }
00166       }
00167 
00168     }
00169   }
00170 
00171 
00172 //! Immediate out -= B
00173 template<typename eT>
00174 inline
00175 void
00176 glue_minus::apply_inplace(Mat<eT>& out, const Mat<eT>& B)
00177   {
00178   arma_extra_debug_sigprint();
00179   
00180   arma_debug_assert_same_size(out, B, "matrix subtraction");
00181 
00182         eT* out_mem = out.memptr();
00183   const eT* B_mem   = B.mem;
00184   
00185   const u32 n_elem  = out.n_elem;
00186   
00187   for(u32 i=0; i<n_elem; ++i)
00188     {
00189     out_mem[i] -= B_mem[i];
00190     }
00191     
00192   }
00193 
00194 
00195 
00196 template<typename T1, typename op_type>
00197 inline
00198 void
00199 glue_minus::apply_inplace(Mat<typename T1::elem_type>& out, const Op<T1, op_type>& X)
00200   {
00201   arma_extra_debug_sigprint();
00202   
00203   typedef typename T1::elem_type eT;
00204   
00205   const Mat<eT> tmp(X);
00206   glue_minus::apply(out, out, tmp);
00207   }
00208   
00209 
00210 
00211 template<typename T1, typename T2, typename glue_type>
00212 inline
00213 void
00214 glue_minus::apply_inplace(Mat<typename T1::elem_type>& out, const Glue<T1, T2, glue_type>& X)
00215   {
00216   arma_extra_debug_sigprint();
00217   
00218   typedef typename T1::elem_type eT;
00219   
00220   out = out - X;
00221   }
00222 
00223 
00224 
00225 //
00226 // matrix subtraction with different element types
00227 
00228 template<typename eT1, typename eT2>
00229 inline
00230 void
00231 glue_minus::apply_mixed(Mat<typename promote_type<eT1,eT2>::result>& out, const Mat<eT1>& X, const Mat<eT2>& Y)
00232   {
00233   arma_extra_debug_sigprint();
00234   
00235   typedef typename promote_type<eT1,eT2>::result out_eT;
00236   
00237   arma_debug_assert_same_size(X,Y, "matrix subtraction");
00238   
00239   out.set_size(X.n_rows, X.n_cols);
00240   
00241         out_eT* out_mem = out.memptr();
00242   const eT1*    X_mem   = X.mem;
00243   const eT2*    Y_mem   = Y.mem;
00244   
00245   const u32 n_elem = out.n_elem;
00246   
00247   for(u32 i=0; i<n_elem; ++i)
00248     {
00249     out_mem[i] = upgrade_val<eT1,eT2>::apply(X_mem[i]) - upgrade_val<eT1,eT2>::apply(Y_mem[i]);
00250     }
00251   }
00252 
00253 
00254 
00255 //
00256 // glue_minus_diag
00257 
00258 
00259 template<typename T1, typename T2>
00260 inline
00261 void
00262 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const T1& A_orig, const Op<T2,op_diagmat>& B_orig)
00263   {
00264   arma_extra_debug_sigprint();
00265   
00266   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00267   
00268   const unwrap<T1> tmp1(A_orig);
00269   const unwrap<T2> tmp2(B_orig.m);
00270   
00271   typedef typename T1::elem_type eT;
00272   
00273   const Mat<eT>& A = tmp1.M;
00274   const Mat<eT>& B = tmp2.M;
00275   
00276   arma_debug_check( !B.is_square(), "glue_minus_diag::apply(): matrices must be square" );
00277   arma_debug_assert_same_size(A, B, "matrix subtraction");
00278 
00279   
00280   // no aliasing problem
00281   out.set_size(A.n_rows, A.n_cols);
00282   
00283   for(u32 col=0; col<A.n_cols; ++col)
00284     {
00285     for(u32 row=0; row<A.n_rows; ++row)
00286       {
00287       if(col != row)
00288         {
00289         out.at(row,col) = A.at(row,col);
00290         }
00291       else
00292         {
00293         out.at(row,col) = A.at(row,col) - B.at(row,col);
00294         }
00295       }
00296     }
00297   
00298   }
00299 
00300 
00301 
00302 template<typename T1, typename T2>
00303 inline
00304 void
00305 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_diagmat>& A_orig, const T2& B_orig)
00306   {
00307   arma_extra_debug_sigprint();
00308   
00309   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00310   
00311   const unwrap<T1> tmp1(A_orig.m);
00312   const unwrap<T2> tmp2(B_orig);
00313   
00314   typedef typename T1::elem_type eT;
00315   
00316   const Mat<eT>& A = tmp1.M;
00317   const Mat<eT>& B = tmp2.M;
00318   
00319   arma_debug_check( !A.is_square(), "glue_minus_diag::apply(): matrices must be square" );
00320   arma_debug_assert_same_size(A, B, "matrix subtraction");
00321   
00322   
00323   // no aliasing problem
00324   out.set_size(A.n_rows, A.n_cols);
00325   
00326   for(u32 col=0; col<A.n_cols; ++col)
00327     {
00328     for(u32 row=0; row<A.n_rows; ++row)
00329       {
00330       if(col != row)
00331         {
00332         out.at(row,col) = -B.at(row,col);
00333         }
00334       else
00335         {
00336         out.at(row,col) = A.at(row,col) - B.at(row,col);
00337         }
00338       }
00339     }
00340   
00341   }
00342 
00343 
00344 
00345 template<typename T1, typename T2>
00346 inline
00347 void
00348 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_diagmat>& A_orig, const Op<T2,op_diagmat>& B_orig)
00349   {
00350   arma_extra_debug_sigprint();
00351   
00352   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00353   
00354   const unwrap<T1> tmp1(A_orig.m);
00355   const unwrap<T2> tmp2(B_orig.m);
00356   
00357   typedef typename T1::elem_type eT;
00358   
00359   const Mat<eT>& A = tmp1.M;
00360   const Mat<eT>& B = tmp2.M;
00361     
00362   arma_debug_check( !A.is_square(), "glue_minus_diag::apply(): matrices must be square" );
00363   arma_debug_assert_same_size(A, B, "matrix subtraction");
00364   
00365   
00366   if( (&out != &A) && (&out != &B) )
00367     {
00368     out.zeros(A.n_rows, A.n_cols);
00369     
00370     for(u32 i=0; i<A.n_rows; ++i)
00371       {
00372       out.at(i,i) = A.at(i,i) - B.at(i,i);
00373       }
00374     }
00375   else
00376     {
00377     for(u32 col=0; col<A.n_cols; ++col)
00378       {
00379       for(u32 row=0; row<A.n_rows; ++row)
00380         {
00381         if(col != row)
00382           {
00383           out.at(row,col) = 0.0;
00384           }
00385         else
00386           {
00387           out.at(row,col) = A.at(row,col) - B.at(row,col);
00388           }
00389         }
00390       }
00391     }
00392   
00393   }
00394 
00395 
00396 
00397 template<typename T1, typename T2>
00398 inline
00399 void
00400 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Glue<T1, Op<T2,op_diagmat>, glue_minus_diag>& X)
00401   {
00402   glue_minus_diag::apply(out, X.A, X.B);
00403   }
00404 
00405 
00406 
00407 template<typename T1, typename T2>
00408 inline
00409 void
00410 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Glue< Op<T1,op_diagmat>, T2, glue_minus_diag>& X)
00411   {
00412   glue_minus_diag::apply(out, X.A, X.B);
00413   }
00414 
00415 
00416 
00417 template<typename T1, typename T2>
00418 inline
00419 void
00420 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Glue<Op<T1,op_diagmat>, Op<T2,op_diagmat>, glue_minus_diag>& X)
00421   {
00422   glue_minus_diag::apply(out, X.A, X.B);
00423   }
00424 
00425 
00426 //! @}