operator_times_dot.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 operartor_times_dot
00017 //! @{
00018 
00019 
00020 
00021 //! Row vector multiplied by a column vector (i.e. a dot product)
00022 template<typename eT>
00023 arma_inline
00024 eT
00025 operator*
00026   (
00027   const Row<eT>& A,
00028   const Col<eT>& B
00029   )
00030   {
00031   arma_extra_debug_sigprint();
00032   
00033   arma_debug_check( (A.n_elem != B.n_elem), "incompatible matrix dimensions" );
00034   
00035   return op_dot::direct_dot(A.n_elem, A.mem, B.mem);
00036   
00037   }
00038 
00039 
00040 
00041 //! Transpose of a column vector multiplied by a column vector (i.e. a dot product)
00042 template<typename eT>
00043 arma_inline
00044 eT
00045 operator*
00046   (
00047   const Op<Col<eT>, op_trans>& X,
00048   const Col<eT>& Y
00049   )
00050   {
00051   arma_extra_debug_sigprint();
00052   
00053   const Col<eT>& A = X.m;
00054   const Col<eT>& B = Y;
00055   
00056   arma_debug_check( (A.n_elem != B.n_elem), "incompatible matrix dimensions" );
00057   
00058   return op_dot::direct_dot(A.n_elem, A.mem, B.mem);
00059   
00060   }
00061 
00062 
00063 
00064 //! Row vector multiplied by the transpose of a row vector (i.e. a dot product)
00065 template<typename eT>
00066 arma_inline
00067 eT
00068 operator*
00069   (
00070   const Row<eT>& X,
00071   const Op<Row<eT>, op_trans>& Y
00072   )
00073   {
00074   arma_extra_debug_sigprint();
00075   
00076   const Row<eT>& A = X;
00077   const Row<eT>& B = Y.m;
00078   
00079   arma_debug_check( (A.n_elem != B.n_elem), "incompatible matrix dimensions" );
00080   
00081   return op_dot::direct_dot(A.n_elem, A.mem, B.mem);
00082   }
00083   
00084 
00085   
00086 //! Transpose of a column vector multiplied by the transpose of a row vector (i.e. a dot product)
00087 template<typename eT>
00088 arma_inline
00089 eT
00090 operator*
00091   (
00092   const Op<Col<eT>, op_trans>& X,
00093   const Op<Row<eT>, op_trans>& Y
00094   )
00095   {
00096   arma_extra_debug_sigprint();
00097   
00098   const Col<eT>& A = X.m;
00099   const Row<eT>& B = Y.m;
00100   
00101   arma_debug_check( (A.n_elem != B.n_elem), "incompatible matrix dimensions" );
00102   
00103   return op_dot::direct_dot(A.n_elem, A.mem, B.mem);
00104   }
00105 
00106 
00107 
00108 //
00109 //
00110 //
00111 
00112 
00113 
00114 //! rowvec * mat * colvec 
00115 template<typename eT>
00116 inline
00117 eT
00118 operator*
00119   (
00120   const Glue<Row<eT>, Mat<eT>, glue_times_vec>& X,
00121   const Col<eT>& Y)
00122   {
00123   arma_extra_debug_sigprint();
00124   
00125   const Row<eT>& A = X.A;
00126   const Mat<eT>& B = X.B;
00127   const Col<eT>& C = Y;
00128   
00129   arma_debug_check( (A.n_cols != B.n_rows) || (B.n_cols != C.n_rows), "operator*(): incompatible matrix dimensions" );
00130   
00131   return glue_times::direct_rowvec_mat_colvec(A.mem, B, C.mem);
00132   }
00133 
00134 
00135 
00136 //! trans(colvec) * mat * colvec 
00137 template<typename eT>
00138 inline
00139 eT
00140 operator*
00141   (
00142   const Glue< Op<Col<eT>,op_trans>, Mat<eT>, glue_times>& X,
00143   const Col<eT>& Y
00144   )
00145   {
00146   arma_extra_debug_sigprint();
00147   
00148   const Col<eT>& A = X.A.m;
00149   const Mat<eT>& B = X.B;
00150   const Col<eT>& C = Y;
00151   
00152   arma_debug_check( (A.n_rows != B.n_rows) || (B.n_cols != C.n_rows), "operator*(): incompatible matrix dimensions" );
00153   
00154   return glue_times::direct_rowvec_mat_colvec(A.mem, B, C.mem);
00155   }
00156 
00157 
00158 
00159 //! rowvec * mat * trans(rowvec)
00160 template<typename eT>
00161 inline
00162 eT
00163 operator*
00164   (
00165   const Glue<Row<eT>, Mat<eT>, glue_times_vec>& X,
00166   const Op<Row<eT>,op_trans>& Y
00167   )
00168   {
00169   arma_extra_debug_sigprint();
00170   
00171   const Row<eT>& A = X.A;
00172   const Mat<eT>& B = X.B;
00173   const Row<eT>& C = Y.m;
00174   
00175   arma_debug_check( (A.n_cols != B.n_rows) || (B.n_cols != C.n_cols), "operator*(): incompatible matrix dimensions" );
00176   
00177   return glue_times::direct_rowvec_mat_colvec(A.mem, B, C.mem);
00178   }
00179 
00180 
00181 
00182 //! trans(colvec) * mat * trans(rowvec)
00183 template<typename eT>
00184 inline
00185 eT
00186 operator*
00187   (
00188   const Glue< Op<Col<eT>,op_trans>, Mat<eT>, glue_times>& X,
00189   const Op<Row<eT>,op_trans>& Y
00190   )
00191   {
00192   arma_extra_debug_sigprint();
00193   
00194   const Col<eT>& A = X.A.m;
00195   const Mat<eT>& B = X.B;
00196   const Row<eT>& C = Y.m;
00197   
00198   arma_debug_check( (A.n_rows != B.n_rows) || (B.n_cols != C.n_cols), "operator*(): incompatible matrix dimensions" );
00199   
00200   return glue_times::direct_rowvec_mat_colvec(A.mem, B, C.mem);
00201   }
00202 
00203 
00204 
00205 //
00206 //
00207 // 
00208 
00209 
00210 //! rowvec * diagmat(mat) * colvec 
00211 template<typename eT>
00212 inline
00213 eT
00214 operator*
00215   (
00216   const Glue<Row<eT>, Op<Mat<eT>,op_diagmat>, glue_times_diag>& X,
00217   const Col<eT>& Y
00218   )
00219   {
00220   arma_extra_debug_sigprint();
00221   
00222   const Row<eT>& A = X.A;
00223   const Mat<eT>& B = X.B.m;
00224   const Col<eT>& C = Y;
00225   
00226   arma_debug_check( (A.n_cols != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_rows), "operator*(): incompatible matrix dimensions" );
00227   
00228   return glue_times::direct_rowvec_diagmat_colvec(A.mem, B, C.mem);
00229   }
00230 
00231 
00232 
00233 //! trans(colvec) * diagmat(mat) * colvec 
00234 template<typename eT>
00235 inline
00236 eT
00237 operator*
00238   (
00239   const Glue< Op<Col<eT>,op_trans>, Op<Mat<eT>,op_diagmat>, glue_times_diag>& X,
00240   const Col<eT>& Y
00241   )
00242   {
00243   arma_extra_debug_sigprint();
00244   
00245   const Col<eT>& A = X.A.m;
00246   const Mat<eT>& B = X.B.m;
00247   const Col<eT>& C = Y;
00248   
00249   arma_debug_check( (A.n_rows != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_rows), "operator*(): incompatible matrix dimensions" );
00250   
00251   return glue_times::direct_rowvec_diagmat_colvec(A.mem, B, C.mem);
00252   }
00253 
00254 
00255 
00256 //! rowvec * diagmat(mat) * trans(rowvec)
00257 template<typename eT>
00258 inline
00259 eT
00260 operator*
00261   (
00262   const Glue<Row<eT>, Op<Mat<eT>,op_diagmat>, glue_times_diag>& X,
00263   const Op<Row<eT>,op_trans>& Y
00264   )
00265   {
00266   arma_extra_debug_sigprint();
00267   
00268   const Row<eT>& A = X.A;
00269   const Mat<eT>& B = X.B.m;
00270   const Row<eT>& C = Y.m;
00271   
00272   arma_debug_check( (A.n_cols != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_cols), "operator*(): incompatible matrix dimensions" );
00273   
00274   return glue_times::direct_rowvec_diagmat_colvec(A.mem, B, C.mem);
00275   }
00276 
00277 
00278 
00279 //! trans(colvec) * diagmat(mat) * trans(rowvec)
00280 template<typename eT>
00281 inline
00282 eT
00283 operator*
00284   (
00285   const Glue< Op<Col<eT>,op_trans>, Op<Mat<eT>,op_diagmat>, glue_times_diag>& X,
00286   const Op<Row<eT>,op_trans>& Y
00287   )
00288   {
00289   arma_extra_debug_sigprint();
00290   
00291   const Col<eT>& A = X.A.m;
00292   const Mat<eT>& B = X.B.m;
00293   const Row<eT>& C = Y.m;
00294   
00295   arma_debug_check( (A.n_rows != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_cols), "operator*(): incompatible matrix dimensions" );
00296   
00297   return glue_times::direct_rowvec_diagmat_colvec(A.mem, B, C.mem);
00298   }
00299 
00300 
00301 
00302 //
00303 //
00304 //
00305 
00306 //! rowvec * diagmat(colvec or rowvec) * colvec
00307 template<typename eT>
00308 inline
00309 eT
00310 operator*
00311   (
00312   const Glue< Row<eT>, Op<Mat<eT>,op_diagmat_vec>, glue_times_vec>& X,
00313   const Col<eT>& Y
00314   )
00315   {
00316   arma_extra_debug_sigprint();
00317 
00318   const Row<eT>& A = X.A;
00319   const Mat<eT>& B = X.B.m;
00320   const Col<eT>& C = Y;
00321   
00322   arma_debug_check( (A.n_cols != B.n_elem) || (B.n_elem != C.n_rows), "operator*(): incompatible matrix dimensions" );
00323   
00324   return op_dot::direct_dot(A.n_cols, A.mem, B.mem, C.mem);
00325   }
00326 
00327 
00328 
00329 //! trans(colvec) * diagmat(colvec or rowvec) * colvec
00330 template<typename eT>
00331 inline
00332 eT
00333 operator*
00334   (
00335   const Glue< Op<Col<eT>, op_trans>, Op<Mat<eT>,op_diagmat_vec>, glue_times>& X,
00336   const Col<eT>& Y
00337   )
00338   {
00339   arma_extra_debug_sigprint();
00340 
00341   const Col<eT>& A = X.A.m;
00342   const Mat<eT>& B = X.B.m;
00343   const Col<eT>& C = Y;
00344   
00345   arma_debug_check( (A.n_rows != B.n_elem) || (B.n_elem != C.n_rows), "operator*(): incompatible matrix dimensions" );
00346   
00347   return op_dot::direct_dot(A.n_cols, A.mem, B.mem, C.mem);
00348   }
00349 
00350 
00351 
00352 //! rowvec * diagmat(colvec or rowvec) * trans(rowvec)
00353 template<typename eT>
00354 inline
00355 eT
00356 operator*
00357   (
00358   const Glue< Row<eT>, Op<Mat<eT>,op_diagmat_vec>, glue_times_vec>& X,
00359   const Op<Row<eT>, op_trans>& Y
00360   )
00361   {
00362   arma_extra_debug_sigprint();
00363 
00364   const Row<eT>& A = X.A;
00365   const Mat<eT>& B = X.B.m;
00366   const Row<eT>& C = Y.m;
00367   
00368   arma_debug_check( (A.n_cols != B.n_elem) || (B.n_elem != C.n_cols), "operator*(): incompatible matrix dimensions" );
00369   
00370   return op_dot::direct_dot(A.n_cols, A.mem, B.mem, C.mem);
00371   }
00372 
00373 
00374 
00375 //! trans(colvec) * diagmat(colvec or rowvec) * trans(rowvec)
00376 template<typename eT>
00377 inline
00378 eT
00379 operator*
00380   (
00381   const Glue< Op<Col<eT>, op_trans>, Op<Mat<eT>,op_diagmat_vec>, glue_times>& X,
00382   const Op<Row<eT>, op_trans>& Y
00383   )
00384   {
00385   arma_extra_debug_sigprint();
00386   
00387   const Col<eT>& A = X.A.m;
00388   const Mat<eT>& B = X.B.m;
00389   const Row<eT>& C = Y.m;
00390   
00391   arma_debug_check( (A.n_rows != B.n_elem) || (B.n_elem != C.n_cols), "operator*(): incompatible matrix dimensions" );
00392   
00393   return op_dot::direct_dot(A.n_cols, A.mem, B.mem, C.mem);
00394   }
00395 
00396 
00397 
00398 //
00399 // 
00400 // 
00401 
00402 
00403 
00404 //! rowvec * inv(T1) * colvec
00405 template<typename T1>
00406 inline
00407 typename T1::elem_type
00408 operator*
00409   (
00410   const Glue< Row<typename T1::elem_type>, Op<T1, op_inv>, glue_times_vec>& X,
00411   const Col<typename T1::elem_type>& Y
00412   )
00413   {
00414   arma_extra_debug_sigprint();
00415   
00416   typedef typename T1::elem_type eT;
00417   
00418   const Row<eT>& A = X.A;
00419         Mat<eT>  B; op_inv::apply(B, X.B.m);
00420   const Col<eT>& C = Y;
00421   
00422   arma_debug_check( (A.n_cols != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_rows), "operator*(): incompatible matrix dimensions" );
00423   
00424   return glue_times::direct_rowvec_mat_colvec(A.mem, B, C.mem);
00425   }
00426 
00427 
00428 
00429 //! trans(colvec) * inv(T1) * colvec
00430 template<typename T1>
00431 inline
00432 typename T1::elem_type
00433 operator*
00434   (
00435   const Glue< Op<Col<typename T1::elem_type>, op_trans>, Op<T1, op_inv>, glue_times>& X,
00436   const Col<typename T1::elem_type>& Y
00437   )
00438   {
00439   arma_extra_debug_sigprint();
00440 
00441   typedef typename T1::elem_type eT;
00442   
00443   const Col<eT>& A = X.A.m;
00444         Mat<eT>  B; op_inv::apply(B, X.B.m);
00445   const Col<eT>& C = Y;
00446   
00447   arma_debug_check( (A.n_rows != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_rows), "operator*(): incompatible matrix dimensions" );
00448   
00449   return glue_times::direct_rowvec_mat_colvec(A.mem, B, C.mem);
00450   }
00451 
00452 
00453 
00454 //! rowvec * inv(T1) * trans(rowvec)
00455 template<typename T1>
00456 inline
00457 typename T1::elem_type
00458 operator*
00459   (
00460   const Glue< Row<typename T1::elem_type>, Op<T1, op_inv>, glue_times_vec>& X,
00461   const Op<Row<typename T1::elem_type>, op_trans>& Y
00462   )
00463   {
00464   arma_extra_debug_sigprint();
00465   
00466   typedef typename T1::elem_type eT;
00467 
00468   const Row<eT>& A = X.A;
00469         Mat<eT>  B;  op_inv::apply(B, X.B.m);
00470   const Row<eT>& C = Y.m;
00471   
00472   arma_debug_check( (A.n_cols != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_cols), "operator*(): incompatible matrix dimensions" );
00473   
00474   return glue_times::direct_rowvec_mat_colvec(A.mem, B, C.mem);
00475   }
00476 
00477 
00478 
00479 //! trans(colvec) * inv(T1) * trans(rowvec)
00480 template<typename T1>
00481 inline
00482 typename T1::elem_type
00483 operator*
00484   (
00485   const Glue< Op<Col<typename T1::elem_type>, op_trans>, Op<T1, op_inv>, glue_times>& X,
00486   const Op<Row<typename T1::elem_type>, op_trans>& Y
00487   )
00488   {
00489   arma_extra_debug_sigprint();
00490   
00491   typedef typename T1::elem_type eT;
00492   
00493   const Col<eT>& A = X.A.m;
00494         Mat<eT>  B;  op_inv::apply(B, X.B.m);
00495   const Row<eT>& C = Y.m;
00496   
00497   arma_debug_check( (A.n_rows != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_cols), "operator*(): incompatible matrix dimensions" );
00498   
00499   return glue_times::direct_rowvec_mat_colvec(A.mem, B, C.mem);
00500   }
00501 
00502 
00503 
00504 // 
00505 //
00506 //
00507 
00508 
00509 
00510 //! rowvec * inv(diagmat(mat)) * colvec
00511 template<typename eT>
00512 inline
00513 eT
00514 operator*
00515   (
00516   const Glue< Row<eT>, Op< Op<Mat<eT>,op_diagmat>, op_inv>, glue_times_vec>& X,
00517   const Col<eT>& Y
00518   )
00519   {
00520   arma_extra_debug_sigprint();
00521   
00522   const Row<eT>& A = X.A;
00523   const Mat<eT>& B = X.B.m.m;
00524   const Col<eT>& C = Y;
00525   
00526   arma_debug_check( (A.n_cols != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_rows), "operator*(): incompatible matrix dimensions" );
00527   
00528   return glue_times::direct_rowvec_invdiagmat_colvec(A.mem, B, C.mem);
00529   }
00530 
00531 
00532 
00533 //! trans(colvec) * inv(diagmat(mat)) * colvec
00534 template<typename eT>
00535 inline
00536 eT
00537 operator*
00538   (
00539   const Glue< Op<Col<eT>, op_trans>, Op< Op<Mat<eT>,op_diagmat>, op_inv>, glue_times>& X,
00540   const Col<eT>& Y
00541   )
00542   {
00543   arma_extra_debug_sigprint();
00544   
00545   const Col<eT>& A = X.A.m;
00546   const Mat<eT>& B = X.B.m.m;
00547   const Col<eT>& C = Y;
00548   
00549   arma_debug_check( (A.n_rows != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_rows), "operator*(): incompatible matrix dimensions" );
00550   
00551   return glue_times::direct_rowvec_invdiagmat_colvec(A.mem, B, C.mem);
00552   }
00553 
00554 
00555 
00556 //! rowvec * inv(diagmat(mat)) * trans(rowvec)
00557 template<typename eT>
00558 inline
00559 eT
00560 operator*
00561   (
00562   const Glue< Row<eT>, Op< Op<Mat<eT>,op_diagmat>, op_inv>, glue_times_vec>& X,
00563   const Op<Row<eT>, op_trans>& Y
00564   )
00565   {
00566   arma_extra_debug_sigprint();
00567 
00568   const Row<eT>& A = X.A;
00569   const Mat<eT>& B = X.B.m.m;
00570   const Row<eT>& C = Y.m;
00571   
00572   arma_debug_check( (A.n_cols != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_cols), "operator*(): incompatible matrix dimensions" );
00573   
00574   return glue_times::direct_rowvec_invdiagmat_colvec(A.mem, B, C.mem);
00575   }
00576 
00577 
00578 
00579 //! trans(colvec) * inv(diagmat(mat)) * trans(rowvec)
00580 template<typename eT>
00581 inline
00582 eT
00583 operator*
00584   (
00585   const Glue< Op<Col<eT>, op_trans>, Op< Op<Mat<eT>,op_diagmat>, op_inv>, glue_times>& X,
00586   const Op<Row<eT>, op_trans>& Y
00587   )
00588   {
00589   arma_extra_debug_sigprint();
00590   
00591   const Col<eT>& A = X.A.m;
00592   const Mat<eT>& B = X.B.m.m;
00593   const Row<eT>& C = Y.m;
00594   
00595   arma_debug_check( (A.n_rows != B.n_rows) || (B.n_rows != B.n_cols) || (B.n_cols != C.n_cols), "operator*(): incompatible matrix dimensions" );
00596   
00597   return glue_times::direct_rowvec_invdiagmat_colvec(A.mem, B, C.mem);
00598   }
00599 
00600 
00601 
00602 //
00603 //
00604 //
00605 
00606 
00607 
00608 //! rowvec * inv(diagmat(colvec or rowvec)) * colvec
00609 template<typename eT>
00610 inline
00611 eT
00612 operator*
00613   (
00614   const Glue< Row<eT>, Op< Op<Mat<eT>,op_diagmat_vec>, op_inv>, glue_times_vec>& X,
00615   const Col<eT>& Y
00616   )
00617   {
00618   arma_extra_debug_sigprint();
00619 
00620   const Row<eT>& A = X.A;
00621   const Mat<eT>& B = X.B.m.m;
00622   const Col<eT>& C = Y;
00623   
00624   arma_debug_check( (A.n_cols != B.n_elem) || (B.n_elem != C.n_rows), "operator*(): incompatible matrix dimensions" );
00625   
00626   return glue_times::direct_rowvec_invdiagvec_colvec(A.mem, B, C.mem);
00627   }
00628 
00629 
00630 
00631 //! trans(colvec) * inv(diagmat(colvec or rowvec)) * colvec
00632 template<typename eT>
00633 inline
00634 eT
00635 operator*
00636   (
00637   const Glue< Op<Col<eT>, op_trans>, Op< Op<Mat<eT>,op_diagmat_vec>, op_inv>, glue_times>& X,
00638   const Col<eT>& Y
00639   )
00640   {
00641   arma_extra_debug_sigprint();
00642 
00643   const Col<eT>& A = X.A.m;
00644   const Mat<eT>& B = X.B.m.m;
00645   const Col<eT>& C = Y;
00646   
00647   arma_debug_check( (A.n_rows != B.n_elem) || (B.n_elem != C.n_rows), "operator*(): incompatible matrix dimensions" );
00648   
00649   return glue_times::direct_rowvec_invdiagvec_colvec(A.mem, B, C.mem);
00650   }
00651 
00652 
00653 
00654 //! rowvec * inv(diagmat(colvec or rowvec)) * trans(rowvec)
00655 template<typename eT>
00656 inline
00657 eT
00658 operator*
00659   (
00660   const Glue< Row<eT>, Op< Op<Mat<eT>,op_diagmat_vec>, op_inv>, glue_times_vec>& X,
00661   const Op<Row<eT>, op_trans>& Y
00662   )
00663   {
00664   arma_extra_debug_sigprint();
00665 
00666   const Row<eT>& A = X.A;
00667   const Mat<eT>& B = X.B.m.m;
00668   const Row<eT>& C = Y.m;
00669   
00670   arma_debug_check( (A.n_cols != B.n_elem) || (B.n_elem != C.n_cols), "operator*(): incompatible matrix dimensions" );
00671   
00672   return glue_times::direct_rowvec_invdiagvec_colvec(A.mem, B, C.mem);
00673   }
00674 
00675 
00676 
00677 //! trans(colvec) * inv(diagmat(colvec or rowvec)) * trans(rowvec)
00678 template<typename eT>
00679 inline
00680 eT
00681 operator*
00682   (
00683   const Glue< Op<Col<eT>, op_trans>, Op< Op<Mat<eT>,op_diagmat_vec>, op_inv>, glue_times>& X,
00684   const Op<Row<eT>, op_trans>& Y
00685   )
00686   {
00687   arma_extra_debug_sigprint();
00688   
00689   const Col<eT>& A = X.A.m;
00690   const Mat<eT>& B = X.B.m.m;
00691   const Row<eT>& C = Y.m;
00692   
00693   arma_debug_check( (A.n_rows != B.n_elem) || (B.n_elem != C.n_cols), "operator*(): incompatible matrix dimensions" );
00694   
00695   return glue_times::direct_rowvec_invdiagvec_colvec(A.mem, B, C.mem);
00696   }
00697 
00698 
00699 
00700 //
00701 //
00702 //
00703 
00704 
00705 
00706 //! trans(colvec-colvec) * inv(diagmat(colvec or rowvec)) * (colvec-colvec)
00707 template<typename eT>
00708 inline
00709 eT
00710 operator*
00711   (
00712   const Glue
00713     <
00714     Op< Glue<Col<eT>, Col<eT>, glue_minus>, op_trans>,
00715     Op< Op<Mat<eT>,op_diagmat_vec>, op_inv>,
00716     glue_times
00717     >& X,
00718   const Glue<Col<eT>, Col<eT>, glue_minus>& Y
00719   )
00720   {
00721   arma_extra_debug_sigprint();
00722   
00723   const Col<eT>& A1 = X.A.m.A;
00724   const Col<eT>& A2 = X.A.m.B;
00725   
00726   const Mat<eT>& B  = X.B.m.m;
00727   
00728   const Col<eT>& C1 = Y.A;
00729   const Col<eT>& C2 = Y.B;
00730   
00731   arma_debug_check
00732     (
00733     (A1.n_rows != A2.n_rows)
00734     ||
00735     (A2.n_rows != B.n_rows)
00736     ||
00737     (B.n_elem != C1.n_rows)
00738     ||
00739     (C1.n_rows != C2.n_rows)
00740     ,
00741     "operator*(): incompatible matrix dimensions"
00742     );
00743   
00744   
00745   if( (&A1 == &C1) && (&A2 == &C2) )
00746     {
00747     eT val = eT(0);
00748     for(u32 i=0; i<A1.n_rows; ++i)
00749       {
00750       const eT tmp = (A1.mem[i] - A2.mem[i]);
00751       val += (tmp*tmp) / B.mem[i];
00752       }
00753     return val;
00754     }
00755   else
00756     {
00757     eT val = eT(0);
00758     for(u32 i=0; i<A1.n_rows; ++i)
00759       {
00760       val += ( (A1.mem[i] - A2.mem[i]) * (C1.mem[i] - C2.mem[i]) ) / B.mem[i];
00761       }
00762     return val;
00763     }
00764 
00765   }
00766 
00767 
00768 
00769 //! @}