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 
00021 //! Immediate out = A-B-...-Z  (operands obtained from Glue)
00022 template<typename T1, typename T2>
00023 inline
00024 void
00025 glue_minus::apply(Mat<typename T1::elem_type>& out, const Glue<T1,T2,glue_minus>& X)
00026   {
00027   arma_extra_debug_sigprint();
00028   
00029   typedef typename T1::elem_type eT;
00030   
00031   const u32 N_mat = 1 + depth_lhs< glue_minus, Glue<T1,T2,glue_minus> >::num;
00032   arma_extra_debug_print( arma_boost::format("N_mat = %d") % N_mat );
00033 
00034 
00035   if(N_mat == 2)
00036     {
00037     if(is_Mat<T1>::value == false)
00038       {
00039       out = X.A;
00040       glue_minus::apply_inplace(out, X.B);
00041       }
00042     else
00043       {
00044       const unwrap<T1> tmp1(X.A);
00045       const unwrap<T2> tmp2(X.B);
00046       
00047       glue_minus::apply(out, tmp1.M, tmp2.M);
00048       }
00049     }
00050   else
00051     {
00052     const Mat<eT>* ptrs[N_mat];
00053     bool            del[N_mat];
00054 
00055     mat_ptrs<glue_minus, Glue<T1,T2,glue_minus> >::get_ptrs(ptrs, del, X);
00056     //mat_ptrs_outcheck<glue_minus, Glue<T1,T2,glue_minus> >::get_ptrs(ptrs, del, X, &out);
00057 
00058     for(u32 i=0; i<N_mat; ++i)  arma_extra_debug_print( arma_boost::format("ptrs[%d] = %x")  % i % ptrs[i] );
00059     for(u32 i=0; i<N_mat; ++i)  arma_extra_debug_print( arma_boost::format(" del[%d] = %d")  % i %  del[i] );
00060 
00061     const Mat<eT>& tmp_mat = *(ptrs[0]);
00062     
00063     for(u32 i=1; i<N_mat; ++i)
00064       {
00065       arma_debug_assert_same_size(tmp_mat, *(ptrs[i]), "matrix subtraction");
00066       }
00067   
00068     const u32 n_rows = ptrs[0]->n_rows;
00069     const u32 n_cols = ptrs[0]->n_cols;
00070     
00071     // no aliasing problem
00072     out.set_size(n_rows,n_cols);
00073     
00074     const u32 n_elem = ptrs[0]->n_elem;
00075     
00076     for(u32 j=0; j<n_elem; ++j)
00077       {
00078       eT acc = ptrs[0]->mem[j];
00079       
00080       for(u32 i=1; i<N_mat; ++i)
00081         {
00082         acc -= ptrs[i]->mem[j];
00083         }
00084       
00085       out[j] = acc;
00086       }
00087     
00088     for(u32 i=0; i<N_mat; ++i)
00089       {
00090       if(del[i] == true)
00091         {
00092         arma_extra_debug_print( arma_boost::format("delete ptrs[%d]") % i );
00093         delete ptrs[i];
00094         }
00095       }
00096 
00097     }
00098   }
00099 
00100 
00101 
00102 //! Immediate out -= B
00103 template<typename T1>
00104 inline
00105 void
00106 glue_minus::apply_inplace(Mat<typename T1::elem_type>& out, const T1& X)
00107   {
00108   arma_extra_debug_sigprint();
00109   
00110   typedef typename T1::elem_type eT;
00111   
00112   const unwrap<T1>   tmp(X);
00113   const Mat<eT>& B = tmp.M;
00114   
00115   arma_debug_assert_same_size(out, B, "matrix subtraction");
00116   
00117         eT* out_mem = out.memptr();
00118   const eT* B_mem   = B.mem;
00119   
00120   const u32 n_elem  = out.n_elem;
00121   
00122   for(u32 i=0; i<n_elem; ++i)
00123     {
00124     out_mem[i] -= B_mem[i];
00125     }
00126   
00127   }
00128 
00129 
00130 
00131 //! matrix subtraction with different element types
00132 template<typename eT1, typename eT2>
00133 inline
00134 void
00135 glue_minus::apply_mixed(Mat<typename promote_type<eT1,eT2>::result>& out, const Mat<eT1>& X, const Mat<eT2>& Y)
00136   {
00137   arma_extra_debug_sigprint();
00138   
00139   typedef typename promote_type<eT1,eT2>::result out_eT;
00140   
00141   arma_debug_assert_same_size(X,Y, "matrix subtraction");
00142   
00143   //out.set_size(X.n_rows, X.n_cols);
00144   out.copy_size(X);
00145   
00146         out_eT* out_mem = out.memptr();
00147   const eT1*    X_mem   = X.mem;
00148   const eT2*    Y_mem   = Y.mem;
00149   
00150   const u32 n_elem = out.n_elem;
00151   
00152   for(u32 i=0; i<n_elem; ++i)
00153     {
00154     out_mem[i] = upgrade_val<eT1,eT2>::apply(X_mem[i]) - upgrade_val<eT1,eT2>::apply(Y_mem[i]);
00155     }
00156   }
00157 
00158 
00159 
00160 //! Immediate out = A-B
00161 template<typename eT>
00162 inline
00163 void
00164 glue_minus::apply(Mat<eT>& out, const Mat<eT>& A, const Mat<eT>& B)
00165   {
00166   arma_extra_debug_sigprint();
00167   
00168   arma_debug_assert_same_size(A, B, "matrix subtraction");
00169   
00170   // no aliasing problem
00171   //out.set_size(A.n_rows,A.n_cols);
00172   out.copy_size(A);
00173     
00174         eT* out_mem = out.memptr();
00175   const eT* A_mem   = A.mem;
00176   const eT* B_mem   = B.mem;
00177   
00178   const u32 n_elem  = A.n_elem;
00179   
00180   for(u32 i=0; i<n_elem; ++i)
00181     {
00182     out_mem[i] = A_mem[i] - B_mem[i];
00183     }
00184     
00185   }
00186 
00187 
00188 
00189 //! Immediate out = A-B-C
00190 template<typename eT>
00191 inline
00192 void
00193 glue_minus::apply(Mat<eT>& out, const Mat<eT>& A, const Mat<eT>& B, const Mat<eT>& C)
00194   {
00195   arma_extra_debug_sigprint();
00196   
00197   arma_debug_assert_same_size(A, B, "matrix subtraction");
00198   arma_debug_assert_same_size(A, C, "matrix subtraction");
00199   
00200   // no aliasing problem
00201   //out.set_size(A.n_rows, A.n_cols);
00202   out.copy_size(A);
00203     
00204         eT* out_mem = out.memptr();
00205   const eT* A_mem   = A.mem;
00206   const eT* B_mem   = B.mem;
00207   const eT* C_mem   = C.mem;
00208   
00209   const u32 n_elem = A.n_elem;
00210   
00211   for(u32 i=0; i<n_elem; ++i)
00212     {
00213     out_mem[i] = A_mem[i] - B_mem[i] - C_mem[i];
00214     }
00215   
00216   }
00217 
00218 
00219 
00220 #if defined(ARMA_GOOD_COMPILER)
00221 
00222 
00223 
00224 template<typename T1>
00225 inline
00226 void
00227 glue_minus::apply_inplace(Mat<typename T1::elem_type>& out, const Op<T1, op_scalar_times>& X)
00228   {
00229   arma_extra_debug_sigprint();
00230   
00231   typedef typename T1::elem_type eT;
00232   
00233   const unwrap<T1>   tmp(X.m);
00234   const Mat<eT>& A = tmp.M;
00235   
00236   arma_debug_assert_same_size(out, A, "matrix subtraction");
00237   
00238         eT* out_mem = out.memptr();
00239   const eT* A_mem   = A.mem;
00240   
00241   const eT  k       = X.aux;
00242   const u32 n_elem  = out.n_elem;
00243   
00244   for(u32 i=0; i<n_elem; ++i)
00245     {
00246     out_mem[i] -= k * A_mem[i];
00247     }
00248   }
00249 
00250 
00251 
00252 template<typename T1>
00253 inline
00254 void
00255 glue_minus::apply_inplace(Mat<typename T1::elem_type>& out, const Op<T1, op_scalar_div_pre>& X)
00256   {
00257   arma_extra_debug_sigprint();
00258   
00259   typedef typename T1::elem_type eT;
00260   
00261   const unwrap<T1>   tmp(X.m);
00262   const Mat<eT>& A = tmp.M;
00263   
00264   arma_debug_assert_same_size(out, A, "matrix subtraction");
00265   
00266         eT* out_mem = out.memptr();
00267   const eT* A_mem   = A.mem;
00268   
00269   const eT  k       = X.aux;
00270   const u32 n_elem  = out.n_elem;
00271   
00272   for(u32 i=0; i<n_elem; ++i)
00273     {
00274     out_mem[i] -= k / A_mem[i];
00275     }
00276   }
00277 
00278 
00279 
00280 template<typename T1>
00281 inline
00282 void
00283 glue_minus::apply_inplace(Mat<typename T1::elem_type>& out, const Op<T1, op_scalar_div_post>& X)
00284   {
00285   arma_extra_debug_sigprint();
00286   
00287   typedef typename T1::elem_type eT;
00288   
00289   const unwrap<T1>   tmp(X.m);
00290   const Mat<eT>& A = tmp.M;
00291   
00292   arma_debug_assert_same_size(out, A, "matrix subtraction");
00293   
00294         eT* out_mem = out.memptr();
00295   const eT* A_mem   = A.mem;
00296   
00297   const eT  k       = X.aux;
00298   const u32 n_elem  = out.n_elem;
00299   
00300   for(u32 i=0; i<n_elem; ++i)
00301     {
00302     out_mem[i] -= A_mem[i] / k;
00303     }
00304   }
00305 
00306 
00307 
00308 //! Immediate out = A-B  (operands obtained from Glue)
00309 template<typename eT>
00310 inline
00311 void
00312 glue_minus::apply(Mat<eT>& out, const Glue<Mat<eT>,Mat<eT>,glue_minus>& X)
00313   {
00314   glue_minus::apply(out, X.A, X.B);
00315   }
00316 
00317 
00318 
00319 //! Immediate out = A-B-C  (operands obtained from Glue)
00320 template<typename eT>
00321 inline
00322 void
00323 glue_minus::apply(Mat<eT>& out, const Glue< Glue<Mat<eT>,Mat<eT>,glue_minus>, Mat<eT>, glue_minus> &X)
00324   {
00325   glue_minus::apply(out, X.A.A, X.A.B, X.B);
00326   }
00327 
00328 
00329 
00330 template<typename T1, typename T2>
00331 inline
00332 void
00333 glue_minus::apply_inplace(Mat<typename T1::elem_type>& out, const Glue<T1, T2, glue_minus>& X)
00334   {
00335   arma_extra_debug_sigprint();
00336   
00337   typedef typename T1::elem_type eT;
00338   
00339   out = out - X;
00340   }
00341 
00342 
00343 
00344 #endif
00345 
00346 
00347 
00348 //
00349 // glue_minus_diag
00350 
00351 
00352 template<typename T1, typename T2>
00353 inline
00354 void
00355 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const T1& A_orig, const Op<T2,op_diagmat>& B_orig)
00356   {
00357   arma_extra_debug_sigprint();
00358   
00359   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00360   
00361   const unwrap<T1> tmp1(A_orig);
00362   const unwrap<T2> tmp2(B_orig.m);
00363   
00364   typedef typename T1::elem_type eT;
00365   
00366   const Mat<eT>& A = tmp1.M;
00367   const Mat<eT>& B = tmp2.M;
00368   
00369   arma_debug_check( !B.is_square(), "glue_minus_diag::apply(): matrices must be square" );
00370   arma_debug_assert_same_size(A, B, "matrix subtraction");
00371 
00372   
00373   // no aliasing problem
00374   //out.set_size(A.n_rows, A.n_cols);
00375   out.copy_size(A);
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) = A.at(row,col);
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 template<typename T1, typename T2>
00397 inline
00398 void
00399 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_diagmat>& A_orig, const T2& B_orig)
00400   {
00401   arma_extra_debug_sigprint();
00402   
00403   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00404   
00405   const unwrap<T1> tmp1(A_orig.m);
00406   const unwrap<T2> tmp2(B_orig);
00407   
00408   typedef typename T1::elem_type eT;
00409   
00410   const Mat<eT>& A = tmp1.M;
00411   const Mat<eT>& B = tmp2.M;
00412   
00413   arma_debug_check( !A.is_square(), "glue_minus_diag::apply(): matrices must be square" );
00414   arma_debug_assert_same_size(A, B, "matrix subtraction");
00415   
00416   
00417   // no aliasing problem
00418   //out.set_size(A.n_rows, A.n_cols);
00419   out.copy_size(A);
00420   
00421   for(u32 col=0; col<A.n_cols; ++col)
00422     {
00423     for(u32 row=0; row<A.n_rows; ++row)
00424       {
00425       if(col != row)
00426         {
00427         out.at(row,col) = -B.at(row,col);
00428         }
00429       else
00430         {
00431         out.at(row,col) = A.at(row,col) - B.at(row,col);
00432         }
00433       }
00434     }
00435   
00436   }
00437 
00438 
00439 
00440 template<typename T1, typename T2>
00441 inline
00442 void
00443 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_diagmat>& A_orig, const Op<T2,op_diagmat>& B_orig)
00444   {
00445   arma_extra_debug_sigprint();
00446   
00447   isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check();
00448   
00449   const unwrap<T1> tmp1(A_orig.m);
00450   const unwrap<T2> tmp2(B_orig.m);
00451   
00452   typedef typename T1::elem_type eT;
00453   
00454   const Mat<eT>& A = tmp1.M;
00455   const Mat<eT>& B = tmp2.M;
00456     
00457   arma_debug_check( !A.is_square(), "glue_minus_diag::apply(): matrices must be square" );
00458   arma_debug_assert_same_size(A, B, "matrix subtraction");
00459   
00460   
00461   if( (&out != &A) && (&out != &B) )
00462     {
00463     out.zeros(A.n_rows, A.n_cols);
00464     
00465     for(u32 i=0; i<A.n_rows; ++i)
00466       {
00467       out.at(i,i) = A.at(i,i) - B.at(i,i);
00468       }
00469     }
00470   else
00471     {
00472     for(u32 col=0; col<A.n_cols; ++col)
00473       {
00474       for(u32 row=0; row<A.n_rows; ++row)
00475         {
00476         if(col != row)
00477           {
00478           out.at(row,col) = 0.0;
00479           }
00480         else
00481           {
00482           out.at(row,col) = A.at(row,col) - B.at(row,col);
00483           }
00484         }
00485       }
00486     }
00487   
00488   }
00489 
00490 
00491 
00492 template<typename T1, typename T2>
00493 inline
00494 void
00495 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Glue<T1, Op<T2,op_diagmat>, glue_minus_diag>& X)
00496   {
00497   glue_minus_diag::apply(out, X.A, X.B);
00498   }
00499 
00500 
00501 
00502 template<typename T1, typename T2>
00503 inline
00504 void
00505 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Glue< Op<T1,op_diagmat>, T2, glue_minus_diag>& X)
00506   {
00507   glue_minus_diag::apply(out, X.A, X.B);
00508   }
00509 
00510 
00511 
00512 template<typename T1, typename T2>
00513 inline
00514 void
00515 glue_minus_diag::apply(Mat<typename T1::elem_type>& out, const Glue<Op<T1,op_diagmat>, Op<T2,op_diagmat>, glue_minus_diag>& X)
00516   {
00517   glue_minus_diag::apply(out, X.A, X.B);
00518   }
00519 
00520 
00521 //! @}