mx-op-defs.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2008-2009 Jaroslav Hajek
00005 Copyright (C) 2009-2010 VZLU Prague, a.s.
00006 
00007 This file is part of Octave.
00008 
00009 Octave is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as published by the
00011 Free Software Foundation; either version 3 of the License, or (at your
00012 option) any later version.
00013 
00014 Octave is distributed in the hope that it will be useful, but WITHOUT
00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00017 for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with Octave; see the file COPYING.  If not, see
00021 <http://www.gnu.org/licenses/>.
00022 
00023 */
00024 
00025 #if !defined (octave_mx_op_defs_h)
00026 #define octave_mx_op_defs_h 1
00027 
00028 #include "mx-op-decl.h"
00029 #include "mx-inlines.cc"
00030 
00031 #define SNANCHK(s) \
00032   if (xisnan (s)) \
00033     gripe_nan_to_logical_conversion ()
00034 
00035 #define MNANCHK(m, MT) \
00036   if (do_mx_check (m, mx_inline_any_nan<MT>)) \
00037     gripe_nan_to_logical_conversion ()
00038 
00039 // vector by scalar operations.
00040 
00041 #define VS_BIN_OP(R, F, OP, V, S) \
00042   R \
00043   F (const V& v, const S& s) \
00044   { \
00045     return do_ms_binary_op<R::element_type, V::element_type, S> (v, s, OP); \
00046   }
00047 
00048 #define VS_BIN_OPS(R, V, S) \
00049   VS_BIN_OP (R, operator +, mx_inline_add, V, S) \
00050   VS_BIN_OP (R, operator -, mx_inline_sub, V, S) \
00051   VS_BIN_OP (R, operator *, mx_inline_mul, V, S) \
00052   VS_BIN_OP (R, operator /, mx_inline_div, V, S)
00053 
00054 // scalar by vector by operations.
00055 
00056 #define SV_BIN_OP(R, F, OP, S, V) \
00057   R \
00058   F (const S& s, const V& v) \
00059   { \
00060     return do_sm_binary_op<R::element_type, S, V::element_type> (s, v, OP); \
00061   }
00062 
00063 #define SV_BIN_OPS(R, S, V) \
00064   SV_BIN_OP (R, operator +, mx_inline_add, S, V) \
00065   SV_BIN_OP (R, operator -, mx_inline_sub, S, V) \
00066   SV_BIN_OP (R, operator *, mx_inline_mul, S, V) \
00067   SV_BIN_OP (R, operator /, mx_inline_div, S, V)
00068 
00069 // vector by vector operations.
00070 
00071 #define VV_BIN_OP(R, F, OP, V1, V2) \
00072   R \
00073   F (const V1& v1, const V2& v2) \
00074   { \
00075     return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, OP, OP, #F); \
00076   }
00077 
00078 #define VV_BIN_OPS(R, V1, V2) \
00079   VV_BIN_OP (R, operator +, mx_inline_add, V1, V2) \
00080   VV_BIN_OP (R, operator -, mx_inline_sub, V1, V2) \
00081   VV_BIN_OP (R, product,    mx_inline_mul, V1, V2) \
00082   VV_BIN_OP (R, quotient,   mx_inline_div, V1, V2)
00083 
00084 // matrix by scalar operations.
00085 
00086 #define MS_BIN_OP(R, OP, M, S, F) \
00087   R \
00088   OP (const M& m, const S& s) \
00089   { \
00090     return do_ms_binary_op<R::element_type, M::element_type, S> (m, s, F); \
00091   }
00092 
00093 #define MS_BIN_OPS(R, M, S) \
00094   MS_BIN_OP (R, operator +, M, S, mx_inline_add) \
00095   MS_BIN_OP (R, operator -, M, S, mx_inline_sub) \
00096   MS_BIN_OP (R, operator *, M, S, mx_inline_mul) \
00097   MS_BIN_OP (R, operator /, M, S, mx_inline_div)
00098 
00099 #define MS_CMP_OP(F, OP, M, S) \
00100   boolMatrix \
00101   F (const M& m, const S& s) \
00102   { \
00103     return do_ms_binary_op<bool, M::element_type, S> (m, s, OP); \
00104   }
00105 
00106 #define MS_CMP_OPS(M, S) \
00107   MS_CMP_OP (mx_el_lt, mx_inline_lt, M, S) \
00108   MS_CMP_OP (mx_el_le, mx_inline_le, M, S) \
00109   MS_CMP_OP (mx_el_ge, mx_inline_ge, M, S) \
00110   MS_CMP_OP (mx_el_gt, mx_inline_gt, M, S) \
00111   MS_CMP_OP (mx_el_eq, mx_inline_eq, M, S) \
00112   MS_CMP_OP (mx_el_ne, mx_inline_ne, M, S)
00113 
00114 #define MS_BOOL_OP(F, OP, M, S) \
00115   boolMatrix \
00116   F (const M& m, const S& s) \
00117   { \
00118     MNANCHK (m, M::element_type); \
00119     SNANCHK (s); \
00120     return do_ms_binary_op<bool, M::element_type, S> (m, s, OP); \
00121   }
00122 
00123 #define MS_BOOL_OPS(M, S) \
00124   MS_BOOL_OP (mx_el_and, mx_inline_and, M, S) \
00125   MS_BOOL_OP (mx_el_or,  mx_inline_or,  M, S)
00126 
00127 // scalar by matrix operations.
00128 
00129 #define SM_BIN_OP(R, OP, S, M, F) \
00130   R \
00131   OP (const S& s, const M& m) \
00132   { \
00133     return do_sm_binary_op<R::element_type, S, M::element_type> (s, m, F); \
00134   }
00135 
00136 #define SM_BIN_OPS(R, S, M) \
00137   SM_BIN_OP (R, operator +, S, M, mx_inline_add) \
00138   SM_BIN_OP (R, operator -, S, M, mx_inline_sub) \
00139   SM_BIN_OP (R, operator *, S, M, mx_inline_mul) \
00140   SM_BIN_OP (R, operator /, S, M, mx_inline_div)
00141 
00142 #define SM_CMP_OP(F, OP, S, M) \
00143   boolMatrix \
00144   F (const S& s, const M& m) \
00145   { \
00146     return do_sm_binary_op<bool, S, M::element_type> (s, m, OP); \
00147   }
00148 
00149 #define SM_CMP_OPS(S, M) \
00150   SM_CMP_OP (mx_el_lt, mx_inline_lt, S, M) \
00151   SM_CMP_OP (mx_el_le, mx_inline_le, S, M) \
00152   SM_CMP_OP (mx_el_ge, mx_inline_ge, S, M) \
00153   SM_CMP_OP (mx_el_gt, mx_inline_gt, S, M) \
00154   SM_CMP_OP (mx_el_eq, mx_inline_eq, S, M) \
00155   SM_CMP_OP (mx_el_ne, mx_inline_ne, S, M)
00156 
00157 #define SM_BOOL_OP(F, OP, S, M) \
00158   boolMatrix \
00159   F (const S& s, const M& m) \
00160   { \
00161     SNANCHK (s); \
00162     MNANCHK (m, M::element_type); \
00163     return do_sm_binary_op<bool, S, M::element_type> (s, m, OP); \
00164   }
00165 
00166 #define SM_BOOL_OPS(S, M) \
00167   SM_BOOL_OP (mx_el_and, mx_inline_and, S, M) \
00168   SM_BOOL_OP (mx_el_or,  mx_inline_or,  S, M)
00169 
00170 // matrix by matrix operations.
00171 
00172 #define MM_BIN_OP(R, OP, M1, M2, F) \
00173   R \
00174   OP (const M1& m1, const M2& m2) \
00175   { \
00176     return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, F, F, #OP); \
00177   }
00178 
00179 #define MM_BIN_OPS(R, M1, M2) \
00180   MM_BIN_OP (R, operator +, M1, M2, mx_inline_add) \
00181   MM_BIN_OP (R, operator -, M1, M2, mx_inline_sub) \
00182   MM_BIN_OP (R, product,    M1, M2, mx_inline_mul) \
00183   MM_BIN_OP (R, quotient,   M1, M2, mx_inline_div)
00184 
00185 #define MM_CMP_OP(F, OP, M1, M2) \
00186   boolMatrix \
00187   F (const M1& m1, const M2& m2) \
00188   { \
00189     return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
00190   }
00191 
00192 #define MM_CMP_OPS(M1, M2) \
00193   MM_CMP_OP (mx_el_lt, mx_inline_lt, M1, M2) \
00194   MM_CMP_OP (mx_el_le, mx_inline_le, M1, M2) \
00195   MM_CMP_OP (mx_el_ge, mx_inline_ge, M1, M2) \
00196   MM_CMP_OP (mx_el_gt, mx_inline_gt, M1, M2) \
00197   MM_CMP_OP (mx_el_eq, mx_inline_eq, M1, M2) \
00198   MM_CMP_OP (mx_el_ne, mx_inline_ne, M1, M2)
00199 
00200 #define MM_BOOL_OP(F, OP, M1, M2) \
00201   boolMatrix \
00202   F (const M1& m1, const M2& m2) \
00203   { \
00204     MNANCHK (m1, M1::element_type); \
00205     MNANCHK (m2, M2::element_type); \
00206     return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
00207   }
00208 
00209 #define MM_BOOL_OPS(M1, M2) \
00210   MM_BOOL_OP (mx_el_and, mx_inline_and, M1, M2) \
00211   MM_BOOL_OP (mx_el_or,  mx_inline_or,  M1, M2)
00212 
00213 // N-d matrix by scalar operations.
00214 
00215 #define NDS_BIN_OP(R, OP, ND, S, F) \
00216   R \
00217   OP (const ND& m, const S& s) \
00218   { \
00219     return do_ms_binary_op<R::element_type, ND::element_type, S> (m, s, F); \
00220   }
00221 
00222 #define NDS_BIN_OPS(R, ND, S) \
00223   NDS_BIN_OP (R, operator +, ND, S, mx_inline_add) \
00224   NDS_BIN_OP (R, operator -, ND, S, mx_inline_sub) \
00225   NDS_BIN_OP (R, operator *, ND, S, mx_inline_mul) \
00226   NDS_BIN_OP (R, operator /, ND, S, mx_inline_div)
00227 
00228 #define NDS_CMP_OP(F, OP, ND, S) \
00229   boolNDArray \
00230   F (const ND& m, const S& s) \
00231   { \
00232     return do_ms_binary_op<bool, ND::element_type, S> (m, s, OP); \
00233   }
00234 
00235 #define NDS_CMP_OPS(ND, S) \
00236   NDS_CMP_OP (mx_el_lt, mx_inline_lt, ND, S) \
00237   NDS_CMP_OP (mx_el_le, mx_inline_le, ND, S) \
00238   NDS_CMP_OP (mx_el_ge, mx_inline_ge, ND, S) \
00239   NDS_CMP_OP (mx_el_gt, mx_inline_gt, ND, S) \
00240   NDS_CMP_OP (mx_el_eq, mx_inline_eq, ND, S) \
00241   NDS_CMP_OP (mx_el_ne, mx_inline_ne, ND, S)
00242 
00243 #define NDS_BOOL_OP(F, OP, ND, S) \
00244   boolNDArray \
00245   F (const ND& m, const S& s) \
00246   { \
00247     MNANCHK (m, ND::element_type); \
00248     SNANCHK (s); \
00249     return do_ms_binary_op<bool, ND::element_type, S> (m, s, OP); \
00250   }
00251 
00252 #define NDS_BOOL_OPS(ND, S) \
00253   NDS_BOOL_OP (mx_el_and,     mx_inline_and,     ND, S) \
00254   NDS_BOOL_OP (mx_el_or,      mx_inline_or,      ND, S) \
00255   NDS_BOOL_OP (mx_el_not_and, mx_inline_not_and, ND, S) \
00256   NDS_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  ND, S) \
00257   NDS_BOOL_OP (mx_el_and_not, mx_inline_and_not, ND, S) \
00258   NDS_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  ND, S)
00259 
00260 // scalar by N-d matrix operations.
00261 
00262 #define SND_BIN_OP(R, OP, S, ND, F) \
00263   R \
00264   OP (const S& s, const ND& m) \
00265   { \
00266     return do_sm_binary_op<R::element_type, S, ND::element_type> (s, m, F); \
00267   }
00268 
00269 #define SND_BIN_OPS(R, S, ND) \
00270   SND_BIN_OP (R, operator +, S, ND, mx_inline_add) \
00271   SND_BIN_OP (R, operator -, S, ND, mx_inline_sub) \
00272   SND_BIN_OP (R, operator *, S, ND, mx_inline_mul) \
00273   SND_BIN_OP (R, operator /, S, ND, mx_inline_div)
00274 
00275 #define SND_CMP_OP(F, OP, S, ND) \
00276   boolNDArray \
00277   F (const S& s, const ND& m) \
00278   { \
00279     return do_sm_binary_op<bool, S, ND::element_type> (s, m, OP); \
00280   }
00281 
00282 #define SND_CMP_OPS(S, ND) \
00283   SND_CMP_OP (mx_el_lt, mx_inline_lt, S, ND) \
00284   SND_CMP_OP (mx_el_le, mx_inline_le, S, ND) \
00285   SND_CMP_OP (mx_el_ge, mx_inline_ge, S, ND) \
00286   SND_CMP_OP (mx_el_gt, mx_inline_gt, S, ND) \
00287   SND_CMP_OP (mx_el_eq, mx_inline_eq, S, ND) \
00288   SND_CMP_OP (mx_el_ne, mx_inline_ne, S, ND)
00289 
00290 #define SND_BOOL_OP(F, OP, S, ND) \
00291   boolNDArray \
00292   F (const S& s, const ND& m) \
00293   { \
00294     SNANCHK (s); \
00295     MNANCHK (m, ND::element_type); \
00296     return do_sm_binary_op<bool, S, ND::element_type> (s, m, OP); \
00297   }
00298 
00299 #define SND_BOOL_OPS(S, ND) \
00300   SND_BOOL_OP (mx_el_and,     mx_inline_and,     S, ND) \
00301   SND_BOOL_OP (mx_el_or,      mx_inline_or,      S, ND) \
00302   SND_BOOL_OP (mx_el_not_and, mx_inline_not_and, S, ND) \
00303   SND_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  S, ND) \
00304   SND_BOOL_OP (mx_el_and_not, mx_inline_and_not, S, ND) \
00305   SND_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  S, ND)
00306 
00307 // N-d matrix by N-d matrix operations.
00308 
00309 #define NDND_BIN_OP(R, OP, ND1, ND2, F) \
00310   R \
00311   OP (const ND1& m1, const ND2& m2) \
00312   { \
00313     return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, F, F, #OP); \
00314   }
00315 
00316 #define NDND_BIN_OPS(R, ND1, ND2) \
00317   NDND_BIN_OP (R, operator +, ND1, ND2, mx_inline_add) \
00318   NDND_BIN_OP (R, operator -, ND1, ND2, mx_inline_sub) \
00319   NDND_BIN_OP (R, product,    ND1, ND2, mx_inline_mul) \
00320   NDND_BIN_OP (R, quotient,   ND1, ND2, mx_inline_div)
00321 
00322 #define NDND_CMP_OP(F, OP, ND1, ND2) \
00323   boolNDArray \
00324   F (const ND1& m1, const ND2& m2) \
00325   { \
00326     return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
00327   }
00328 
00329 #define NDND_CMP_OPS(ND1, ND2) \
00330   NDND_CMP_OP (mx_el_lt, mx_inline_lt, ND1, ND2) \
00331   NDND_CMP_OP (mx_el_le, mx_inline_le, ND1, ND2) \
00332   NDND_CMP_OP (mx_el_ge, mx_inline_ge, ND1, ND2) \
00333   NDND_CMP_OP (mx_el_gt, mx_inline_gt, ND1, ND2) \
00334   NDND_CMP_OP (mx_el_eq, mx_inline_eq, ND1, ND2) \
00335   NDND_CMP_OP (mx_el_ne, mx_inline_ne, ND1, ND2)
00336 
00337 #define NDND_BOOL_OP(F, OP, ND1, ND2) \
00338   boolNDArray \
00339   F (const ND1& m1, const ND2& m2) \
00340   { \
00341     MNANCHK (m1, ND1::element_type); \
00342     MNANCHK (m2, ND2::element_type); \
00343     return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
00344   }
00345 
00346 #define NDND_BOOL_OPS(ND1, ND2) \
00347   NDND_BOOL_OP (mx_el_and,     mx_inline_and,     ND1, ND2) \
00348   NDND_BOOL_OP (mx_el_or,      mx_inline_or,      ND1, ND2) \
00349   NDND_BOOL_OP (mx_el_not_and, mx_inline_not_and, ND1, ND2) \
00350   NDND_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  ND1, ND2) \
00351   NDND_BOOL_OP (mx_el_and_not, mx_inline_and_not, ND1, ND2) \
00352   NDND_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  ND1, ND2)
00353 
00354 // scalar by diagonal matrix operations.
00355 
00356 #define SDM_BIN_OP(R, OP, S, DM) \
00357   R \
00358   operator OP (const S& s, const DM& dm) \
00359   { \
00360     R r (dm.rows (), dm.cols ()); \
00361  \
00362     for (octave_idx_type i = 0; i < dm.length (); i++) \
00363       r.dgxelem (i) = s OP dm.dgelem (i); \
00364  \
00365     return r; \
00366 }
00367 
00368 #define SDM_BIN_OPS(R, S, DM) \
00369   SDM_BIN_OP (R, *, S, DM)
00370 
00371 // diagonal matrix by scalar operations.
00372 
00373 #define DMS_BIN_OP(R, OP, DM, S) \
00374   R \
00375   operator OP (const DM& dm, const S& s) \
00376   { \
00377     R r (dm.rows (), dm.cols ()); \
00378  \
00379     for (octave_idx_type i = 0; i < dm.length (); i++) \
00380       r.dgxelem (i) = dm.dgelem (i) OP s; \
00381  \
00382     return r; \
00383   }
00384 
00385 #define DMS_BIN_OPS(R, DM, S) \
00386   DMS_BIN_OP (R, *, DM, S) \
00387   DMS_BIN_OP (R, /, DM, S)
00388 
00389 // matrix by diagonal matrix operations.
00390 
00391 #define MDM_BIN_OP(R, OP, M, DM, OPEQ) \
00392 R \
00393 OP (const M& m, const DM& dm) \
00394 { \
00395   R r; \
00396  \
00397   octave_idx_type m_nr = m.rows (); \
00398   octave_idx_type m_nc = m.cols (); \
00399  \
00400   octave_idx_type dm_nr = dm.rows (); \
00401   octave_idx_type dm_nc = dm.cols (); \
00402  \
00403   if (m_nr != dm_nr || m_nc != dm_nc) \
00404     gripe_nonconformant (#OP, m_nr, m_nc, dm_nr, dm_nc); \
00405   else \
00406     { \
00407       r.resize (m_nr, m_nc); \
00408  \
00409       if (m_nr > 0 && m_nc > 0) \
00410         { \
00411           r = R (m); \
00412  \
00413           octave_idx_type len = dm.length (); \
00414  \
00415           for (octave_idx_type i = 0; i < len; i++) \
00416             r.elem(i, i) OPEQ dm.elem(i, i); \
00417         } \
00418     } \
00419  \
00420   return r; \
00421 }
00422 
00423 #define MDM_MULTIPLY_OP(R, M, DM, R_ZERO) \
00424 R \
00425 operator * (const M& m, const DM& dm) \
00426 { \
00427   R r; \
00428  \
00429   octave_idx_type m_nr = m.rows (); \
00430   octave_idx_type m_nc = m.cols (); \
00431  \
00432   octave_idx_type dm_nr = dm.rows (); \
00433   octave_idx_type dm_nc = dm.cols (); \
00434  \
00435   if (m_nc != dm_nr) \
00436     gripe_nonconformant ("operator *", m_nr, m_nc, dm_nr, dm_nc); \
00437   else \
00438     { \
00439       r = R (m_nr, dm_nc); \
00440       R::element_type *rd = r.fortran_vec (); \
00441       const M::element_type *md = m.data (); \
00442       const DM::element_type *dd = dm.data (); \
00443  \
00444       octave_idx_type len = dm.length (); \
00445       for (octave_idx_type i = 0; i < len; i++) \
00446         { \
00447           mx_inline_mul (m_nr, rd, md, dd[i]); \
00448           rd += m_nr; md += m_nr; \
00449         } \
00450       mx_inline_fill (m_nr * (dm_nc - len), rd, R_ZERO); \
00451     } \
00452  \
00453   return r; \
00454 }
00455 
00456 #define MDM_BIN_OPS(R, M, DM, R_ZERO) \
00457   MDM_BIN_OP (R, operator +, M, DM, +=) \
00458   MDM_BIN_OP (R, operator -, M, DM, -=) \
00459   MDM_MULTIPLY_OP (R, M, DM, R_ZERO)
00460 
00461 // diagonal matrix by matrix operations.
00462 
00463 #define DMM_BIN_OP(R, OP, DM, M, OPEQ, PREOP) \
00464 R \
00465 OP (const DM& dm, const M& m) \
00466 { \
00467   R r; \
00468  \
00469   octave_idx_type dm_nr = dm.rows (); \
00470   octave_idx_type dm_nc = dm.cols (); \
00471  \
00472   octave_idx_type m_nr = m.rows (); \
00473   octave_idx_type m_nc = m.cols (); \
00474  \
00475   if (dm_nr != m_nr || dm_nc != m_nc) \
00476     gripe_nonconformant (#OP, dm_nr, dm_nc, m_nr, m_nc); \
00477   else \
00478     { \
00479       if (m_nr > 0 && m_nc > 0) \
00480         { \
00481           r = R (PREOP m); \
00482  \
00483           octave_idx_type len = dm.length (); \
00484  \
00485           for (octave_idx_type i = 0; i < len; i++) \
00486             r.elem(i, i) OPEQ dm.elem(i, i); \
00487         } \
00488       else \
00489         r.resize (m_nr, m_nc); \
00490     } \
00491  \
00492   return r; \
00493 }
00494 
00495 #define DMM_MULTIPLY_OP(R, DM, M, R_ZERO) \
00496 R \
00497 operator * (const DM& dm, const M& m) \
00498 { \
00499   R r; \
00500  \
00501   octave_idx_type dm_nr = dm.rows (); \
00502   octave_idx_type dm_nc = dm.cols (); \
00503  \
00504   octave_idx_type m_nr = m.rows (); \
00505   octave_idx_type m_nc = m.cols (); \
00506  \
00507   if (dm_nc != m_nr) \
00508     gripe_nonconformant ("operator *", dm_nr, dm_nc, m_nr, m_nc); \
00509   else \
00510     { \
00511       r = R (dm_nr, m_nc); \
00512       R::element_type *rd = r.fortran_vec (); \
00513       const M::element_type *md = m.data (); \
00514       const DM::element_type *dd = dm.data (); \
00515  \
00516       octave_idx_type len = dm.length (); \
00517       for (octave_idx_type i = 0; i < m_nc; i++) \
00518         { \
00519           mx_inline_mul (len, rd, md, dd); \
00520           rd += len; md += m_nr; \
00521           mx_inline_fill (dm_nr - len, rd, R_ZERO); \
00522           rd += dm_nr - len; \
00523         } \
00524     } \
00525  \
00526   return r; \
00527 }
00528 
00529 #define DMM_BIN_OPS(R, DM, M, R_ZERO) \
00530   DMM_BIN_OP (R, operator +, DM, M, +=, ) \
00531   DMM_BIN_OP (R, operator -, DM, M, +=, -) \
00532   DMM_MULTIPLY_OP (R, DM, M, R_ZERO)
00533 
00534 // diagonal matrix by diagonal matrix operations.
00535 
00536 #define DMDM_BIN_OP(R, OP, DM1, DM2, F) \
00537   R \
00538   OP (const DM1& dm1, const DM2& dm2) \
00539   { \
00540     R r; \
00541  \
00542     octave_idx_type dm1_nr = dm1.rows (); \
00543     octave_idx_type dm1_nc = dm1.cols (); \
00544  \
00545     octave_idx_type dm2_nr = dm2.rows (); \
00546     octave_idx_type dm2_nc = dm2.cols (); \
00547  \
00548     if (dm1_nr != dm2_nr || dm1_nc != dm2_nc) \
00549       gripe_nonconformant (#OP, dm1_nr, dm1_nc, dm2_nr, dm2_nc); \
00550     else \
00551       { \
00552         r.resize (dm1_nr, dm1_nc); \
00553  \
00554         if (dm1_nr > 0 && dm1_nc > 0) \
00555           F (dm1.length (), r.fortran_vec (), dm1.data (), dm2.data ()); \
00556       } \
00557  \
00558     return r; \
00559   }
00560 
00561 #define DMDM_BIN_OPS(R, DM1, DM2) \
00562   DMDM_BIN_OP (R, operator +, DM1, DM2, mx_inline_add) \
00563   DMDM_BIN_OP (R, operator -, DM1, DM2, mx_inline_sub) \
00564   DMDM_BIN_OP (R, product,    DM1, DM2, mx_inline_mul)
00565 
00566 // scalar by N-d array min/max ops
00567 
00568 #define SND_MINMAX_FCN(FCN, OP, T, S) \
00569 T \
00570 FCN (S d, const T& m) \
00571 { \
00572   return do_sm_binary_op<T::element_type, S, T::element_type> (d, m, mx_inline_x##FCN); \
00573 }
00574 
00575 #define NDS_MINMAX_FCN(FCN, OP, T, S) \
00576 T \
00577 FCN (const T& m, S d) \
00578 { \
00579   return do_ms_binary_op<T::element_type, T::element_type, S> (m, d, mx_inline_x##FCN); \
00580 }
00581 
00582 #define NDND_MINMAX_FCN(FCN, OP, T, S) \
00583 T \
00584 FCN (const T& a, const T& b) \
00585 { \
00586   return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, mx_inline_x##FCN, mx_inline_x##FCN, #FCN); \
00587 }
00588 
00589 #define MINMAX_FCNS(T, S) \
00590   SND_MINMAX_FCN (min, <, T, S) \
00591   NDS_MINMAX_FCN (min, <, T, S) \
00592   NDND_MINMAX_FCN (min, <, T, S) \
00593   SND_MINMAX_FCN (max, >, T, S) \
00594   NDS_MINMAX_FCN (max, >, T, S) \
00595   NDND_MINMAX_FCN (max, >, T, S)
00596 
00597 // permutation matrix by matrix ops and vice versa
00598 
00599 #define PMM_MULTIPLY_OP(PM, M) \
00600 M operator * (const PM& p, const M& x) \
00601 { \
00602   octave_idx_type nr = x.rows (), nc = x.columns (); \
00603   M result; \
00604   if (p.columns () != nr) \
00605     gripe_nonconformant ("operator *", p.rows (), p.columns (), nr, nc); \
00606   else \
00607     { \
00608       if (p.is_col_perm ()) \
00609         { \
00610           result = M (nr, nc); \
00611           result.assign (p.pvec (), idx_vector::colon, x); \
00612         } \
00613       else \
00614         result = x.index (p.pvec (), idx_vector::colon); \
00615     } \
00616   \
00617   return result; \
00618 }
00619 
00620 #define MPM_MULTIPLY_OP(M, PM) \
00621 M operator * (const M& x, const PM& p) \
00622 { \
00623   octave_idx_type nr = x.rows (), nc = x.columns (); \
00624   M result; \
00625   if (p.rows () != nc) \
00626     gripe_nonconformant ("operator *", nr, nc, p.rows (), p.columns ()); \
00627   else \
00628     { \
00629       if (p.is_col_perm ()) \
00630         result = x.index (idx_vector::colon, p.pvec ()); \
00631       else \
00632         { \
00633           result = M (nr, nc); \
00634           result.assign (idx_vector::colon, p.pvec (), x); \
00635         } \
00636     } \
00637   \
00638   return result; \
00639 }
00640 
00641 #define PMM_BIN_OPS(R, PM, M) \
00642   PMM_MULTIPLY_OP(PM, M);
00643 
00644 #define MPM_BIN_OPS(R, M, PM) \
00645   MPM_MULTIPLY_OP(M, PM);
00646 
00647 #define NDND_MAPPER_BODY(R, NAME) \
00648   R retval (dims ()); \
00649   octave_idx_type n = numel (); \
00650   for (octave_idx_type i = 0; i < n; i++) \
00651     retval.xelem (i) = NAME (elem (i)); \
00652   return retval;
00653 
00654 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines