changeset 20960:2a99b8b250cd

MArray macro removal without loss of functionality to improve maintainability. * boolNDArray.cc: removed unnecessary header inclusion. * CNDArray.cc: removed unnecessary header inclusion. * fCNDArray.cc: removed unnecessary header inclusion. * MArray.cc: removed unnecessary header inclusion. * MDiagArray2.cc: removed unnecessary header inclusion. * MArray.h: partially expanded macros and left three meaningful one alive. * MDiagArray2.h: partially expanded macros and left a meaningful one alive. * MArray-decl.h: removed preprocessor abuse. * MArray-defs.h: removed preprocessor abuse. * module.mk: removed MArray-{decl/defs}.h from build system.
author Kai T. Ohlhus <k.ohlhus@gmail.com>
date Tue, 22 Dec 2015 01:34:05 +0100
parents 3894a672799e
children f55251db0833
files liboctave/array/CNDArray.cc liboctave/array/MArray-decl.h liboctave/array/MArray-defs.h liboctave/array/MArray.cc liboctave/array/MArray.h liboctave/array/MDiagArray2.cc liboctave/array/MDiagArray2.h liboctave/array/boolNDArray.cc liboctave/array/fCNDArray.cc liboctave/array/module.mk
diffstat 10 files changed, 172 insertions(+), 363 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/array/CNDArray.cc	Mon Dec 21 13:27:53 2015 -0500
+++ b/liboctave/array/CNDArray.cc	Tue Dec 22 01:34:05 2015 +0100
@@ -36,7 +36,6 @@
 #include "functor.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
-#include "MArray-defs.h"
 #include "mx-base.h"
 #include "mx-op-defs.h"
 #include "mx-cnda-s.h"
--- a/liboctave/array/MArray-decl.h	Mon Dec 21 13:27:53 2015 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,269 +0,0 @@
-/*
-
-Copyright (C) 1996-2015 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_MArray_decl_h)
-#define octave_MArray_decl_h 1
-
-// A macro that can be used to declare and instantiate OP= operators.
-#define MARRAY_OP_ASSIGN_DECL(A_T, E_T, OP, PFX, API, LTGT, RHS_T) \
-  PFX API A_T<E_T>& \
-  operator OP LTGT (A_T<E_T>&, const RHS_T&)
-
-#define MARRAY_OP_ASSIGN_DECLX(A_T, E_T, OP, PFX, API, LTGT, RHS_T) \
-  PFX API A_T<E_T>& \
-  OP LTGT (A_T<E_T>&, const RHS_T&)
-
-// All the OP= operators that we care about.
-#define MARRAY_OP_ASSIGN_DECLS(A_T, E_T, PFX, API, LTGT, RHS_T) \
-  MARRAY_OP_ASSIGN_DECL (A_T, E_T, +=, PFX, API, LTGT, RHS_T); \
-  MARRAY_OP_ASSIGN_DECL (A_T, E_T, -=, PFX, API, LTGT, RHS_T); \
-  MARRAY_OP_ASSIGN_DECLX (A_T, E_T, product_eq, PFX, API, LTGT, RHS_T); \
-  MARRAY_OP_ASSIGN_DECLX (A_T, E_T, quotient_eq, PFX, API, LTGT, RHS_T);
-
-#define MARRAY_OP_ASSIGN_DECLS1(A_T, E_T, PFX, API, LTGT, RHS_T) \
-  MARRAY_OP_ASSIGN_DECL (A_T, E_T, +=, PFX, API, LTGT, RHS_T); \
-  MARRAY_OP_ASSIGN_DECL (A_T, E_T, -=, PFX, API, LTGT, RHS_T); \
-  MARRAY_OP_ASSIGN_DECL (A_T, E_T, *=, PFX, API, LTGT, RHS_T); \
-  MARRAY_OP_ASSIGN_DECL (A_T, E_T, /=, PFX, API, LTGT, RHS_T);
-
-// Generate forward declarations for OP= operators.
-#define MARRAY_OP_ASSIGN_FWD_DECLS(A_T, RHS_T, API) \
-  MARRAY_OP_ASSIGN_DECLS (A_T, T, template <typename T>, API, , RHS_T)
-
-#define MARRAY_OP_ASSIGN_FWD_DECLS1(A_T, RHS_T, API) \
-  MARRAY_OP_ASSIGN_DECLS1 (A_T, T, template <typename T>, API, , RHS_T)
-
-// Generate friend declarations for the OP= operators.
-#define MARRAY_OP_ASSIGN_FRIENDS(A_T, RHS_T, API) \
-  MARRAY_OP_ASSIGN_DECLS (A_T, T, friend, API, <>, RHS_T)
-
-#define MARRAY_OP_ASSIGN_FRIENDS1(A_T, RHS_T, API) \
-  MARRAY_OP_ASSIGN_DECLS1 (A_T, T, friend, API, <>, RHS_T)
-
-// A function that can be used to forward OP= operations from derived
-// classes back to us.
-#define MARRAY_OP_ASSIGN_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T) \
-  inline R \
-  F (X_T& x, const Y_T& y) \
-  { \
-    return R (F (C_X (x), C_Y (y))); \
-  }
-
-// All the OP= operators that we care about forwarding.
-#define MARRAY_OP_ASSIGN_FWD_DEFS(R, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_OP_ASSIGN_FWD_FCN (R, operator +=, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_OP_ASSIGN_FWD_FCN (R, operator -=, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_OP_ASSIGN_FWD_FCN (R, product_eq, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_OP_ASSIGN_FWD_FCN (R, quotient_eq, T, C_X, X_T, C_Y, Y_T)
-
-#define MARRAY_OP_ASSIGN_FWD_DEFS1(R, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_OP_ASSIGN_FWD_FCN (R, operator +=, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_OP_ASSIGN_FWD_FCN (R, operator -=, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_OP_ASSIGN_FWD_FCN (R, operator *=, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_OP_ASSIGN_FWD_FCN (R, operator /=, T, C_X, X_T, C_Y, Y_T)
-
-// A macro that can be used to declare and instantiate unary operators.
-#define MARRAY_UNOP(A_T, E_T, F, PFX, API, LTGT) \
-  PFX API A_T<E_T> \
-  F LTGT (const A_T<E_T>&)
-
-// All the unary operators that we care about.
-#define MARRAY_UNOP_DECLS(A_T, E_T, PFX, API, LTGT) \
-  MARRAY_UNOP (A_T, E_T, operator +, PFX, API, LTGT); \
-  MARRAY_UNOP (A_T, E_T, operator -, PFX, API, LTGT);
-
-// Generate forward declarations for unary operators.
-#define MARRAY_UNOP_FWD_DECLS(A_T, API) \
-  MARRAY_UNOP_DECLS (A_T, T, template <typename T>, API, )
-
-// Generate friend declarations for the unary operators.
-#define MARRAY_UNOP_FRIENDS(A_T, API) \
-  MARRAY_UNOP_DECLS (A_T, T, friend, API, <>)
-
-// A function that can be used to forward unary operations from derived
-// classes back to us.
-#define MARRAY_UNOP_FWD_FCN(R, F, T, C_X, X_T) \
-  inline R \
-  F (const X_T& x) \
-  { \
-    return R (F (C_X (x))); \
-  }
-
-// All the unary operators that we care about forwarding.
-#define MARRAY_UNOP_FWD_DEFS(R, T, C_X, X_T) \
-  MARRAY_UNOP_FWD_FCN (R, operator +, T, C_X, X_T) \
-  MARRAY_UNOP_FWD_FCN (R, operator -, T, C_X, X_T)
-
-// A macro that can be used to declare and instantiate binary operators.
-#define MARRAY_BINOP_DECL(A_T, E_T, F, PFX, API, LTGT, X_T, Y_T) \
-  PFX API A_T<E_T> \
-  F LTGT (const X_T&, const Y_T&)
-
-// All the binary operators that we care about.  We have two
-// sets of macros since the MArray OP MArray operations use functions
-// (product and quotient) instead of operators (*, /).
-#define MARRAY_BINOP_DECLS(A_T, E_T, PFX, API, LTGT, X_T, Y_T) \
-  MARRAY_BINOP_DECL (A_T, E_T, operator +, PFX, API, LTGT, X_T, Y_T); \
-  MARRAY_BINOP_DECL (A_T, E_T, operator -, PFX, API, LTGT, X_T, Y_T); \
-  MARRAY_BINOP_DECL (A_T, E_T, operator *, PFX, API, LTGT, X_T, Y_T); \
-  MARRAY_BINOP_DECL (A_T, E_T, operator /, PFX, API, LTGT, X_T, Y_T);
-
-#define MARRAY_AA_BINOP_DECLS(A_T, E_T, PFX, API, LTGT) \
-  MARRAY_BINOP_DECL (A_T, E_T, operator +, PFX, API, LTGT, A_T<E_T>, A_T<E_T>); \
-  MARRAY_BINOP_DECL (A_T, E_T, operator -, PFX, API, LTGT, A_T<E_T>, A_T<E_T>); \
-  MARRAY_BINOP_DECL (A_T, E_T, quotient,   PFX, API, LTGT, A_T<E_T>, A_T<E_T>); \
-  MARRAY_BINOP_DECL (A_T, E_T, product,    PFX, API, LTGT, A_T<E_T>, A_T<E_T>);
-
-#define MDIAGARRAY2_DAS_BINOP_DECLS(A_T, E_T, PFX, API, LTGT, X_T, Y_T) \
-  MARRAY_BINOP_DECL (A_T, E_T, operator *, PFX, API, LTGT, X_T, Y_T); \
-  MARRAY_BINOP_DECL (A_T, E_T, operator /, PFX, API, LTGT, X_T, Y_T);
-
-#define MDIAGARRAY2_SDA_BINOP_DECLS(A_T, E_T, PFX, API, LTGT, X_T, Y_T) \
-  MARRAY_BINOP_DECL (A_T, E_T, operator *, PFX, API, LTGT, X_T, Y_T);
-
-#define MDIAGARRAY2_DADA_BINOP_DECLS(A_T, E_T, PFX, API, LTGT) \
-  MARRAY_BINOP_DECL (A_T, E_T, operator +, PFX, API, LTGT, A_T<E_T>, A_T<E_T>); \
-  MARRAY_BINOP_DECL (A_T, E_T, operator -, PFX, API, LTGT, A_T<E_T>, A_T<E_T>); \
-  MARRAY_BINOP_DECL (A_T, E_T, product,    PFX, API, LTGT, A_T<E_T>, A_T<E_T>);
-
-// Generate forward declarations for binary operators.
-#define MARRAY_BINOP_FWD_DECLS(A_T, API) \
-  MARRAY_BINOP_DECLS (A_T, T, template <typename T>, API, , A_T<T>, T) \
-  MARRAY_BINOP_DECLS (A_T, T, template <typename T>, API, , T, A_T<T>) \
-  MARRAY_AA_BINOP_DECLS (A_T, T, template <typename T>, API, )
-
-#define MDIAGARRAY2_BINOP_FWD_DECLS(A_T, API) \
-  MDIAGARRAY2_DAS_BINOP_DECLS (A_T, T, template <typename T>, API, , A_T<T>, T) \
-  MDIAGARRAY2_SDA_BINOP_DECLS (A_T, T, template <typename T>, API, , T, A_T<T>) \
-  MDIAGARRAY2_DADA_BINOP_DECLS (A_T, T, template <typename T>, API, )
-
-// Generate friend declarations for the binary operators.
-#define MARRAY_BINOP_FRIENDS(A_T, API) \
-  MARRAY_BINOP_DECLS (A_T, T, friend, API, <>, A_T<T>, T) \
-  MARRAY_BINOP_DECLS (A_T, T, friend, API, <>, T, A_T<T>) \
-  MARRAY_AA_BINOP_DECLS (A_T, T, friend, API, <>)
-
-#define MDIAGARRAY2_BINOP_FRIENDS(A_T, API) \
-  MDIAGARRAY2_DAS_BINOP_DECLS (A_T, T, friend, API, <>, A_T<T>, T) \
-  MDIAGARRAY2_SDA_BINOP_DECLS (A_T, T, friend, API, <>, T, A_T<T>) \
-  MDIAGARRAY2_DADA_BINOP_DECLS (A_T, T, friend, API, <>)
-
-// A function that can be used to forward binary operations from derived
-// classes back to us.
-#define MARRAY_BINOP_FWD_FCN(R, F, T, C_X, X_T, C_Y, Y_T) \
-  inline R \
-  F (const X_T& x, const Y_T& y) \
-  { \
-    return R (F (C_X (x), C_Y (y))); \
-  }
-
-// The binary operators that we care about forwarding.  We have two
-// sets of macros since the MArray OP MArray operations use functions
-// (product and quotient) instead of operators (*, /).
-#define MARRAY_BINOP_FWD_DEFS(R, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator +, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator -, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator *, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator /, T, C_X, X_T, C_Y, Y_T)
-
-#define MARRAY_AA_BINOP_FWD_DEFS(R, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator +, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator -, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, product,    T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, quotient,   T, C_X, X_T, C_Y, Y_T)
-
-#define MDIAGARRAY2_DAS_BINOP_FWD_DEFS(R, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator *, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator /, T, C_X, X_T, C_Y, Y_T)
-
-#define MDIAGARRAY2_SDA_BINOP_FWD_DEFS(R, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator *, T, C_X, X_T, C_Y, Y_T)
-
-#define MDIAGARRAY2_DADA_BINOP_FWD_DEFS(R, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator +, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, operator -, T, C_X, X_T, C_Y, Y_T) \
-  MARRAY_BINOP_FWD_FCN (R, product,    T, C_X, X_T, C_Y, Y_T)
-
-// Forward declarations for the MArray operators.
-#define MARRAY_OPS_FORWARD_DECLS(A_T, API) \
-  template <class T> \
-  class A_T; \
- \
-  MARRAY_OP_ASSIGN_FWD_DECLS1 (A_T, T, API) \
-  MARRAY_OP_ASSIGN_FWD_DECLS (A_T, A_T<T>, API) \
-  MARRAY_UNOP_FWD_DECLS (A_T, API) \
-  MARRAY_BINOP_FWD_DECLS (A_T, API)
-
-#define MDIAGARRAY2_OPS_FORWARD_DECLS(A_T, API) \
-  template <class T> \
-  class A_T; \
- \
-  MARRAY_UNOP_FWD_DECLS (A_T, API) \
-  MDIAGARRAY2_BINOP_FWD_DECLS (A_T, API)
-
-// Friend declarations for the MArray operators.
-#define MARRAY_OPS_FRIEND_DECLS(A_T, API) \
-  MARRAY_OP_ASSIGN_FRIENDS1 (A_T, T, API) \
-  MARRAY_OP_ASSIGN_FRIENDS (A_T, A_T<T>, API) \
-  MARRAY_UNOP_FRIENDS (A_T, API) \
-  MARRAY_BINOP_FRIENDS (A_T, API)
-
-#define MDIAGARRAY2_OPS_FRIEND_DECLS(A_T, API) \
-  MARRAY_UNOP_FRIENDS (A_T, API) \
-  MDIAGARRAY2_BINOP_FRIENDS (A_T, API)
-
-// Define all the MArray forwarding functions for return type R and
-// MArray element type T
-#define MARRAY_FORWARD_DEFS(B, R, T) \
-  MARRAY_OP_ASSIGN_FWD_DEFS1 \
-    (R, T, dynamic_cast<B<T>&>, R, , T) \
- \
-  MARRAY_OP_ASSIGN_FWD_DEFS \
-    (R, T, \
-     dynamic_cast<B<T>&>, R, dynamic_cast<const B<T>&>, R) \
- \
-  MARRAY_UNOP_FWD_DEFS \
-    (R, T, dynamic_cast<const B<T>&>, R) \
- \
-  MARRAY_BINOP_FWD_DEFS \
-    (R, T, dynamic_cast<const B<T>&>, R, , T) \
- \
-  MARRAY_BINOP_FWD_DEFS \
-    (R, T, , T, dynamic_cast<const B<T>&>, R) \
- \
-  MARRAY_AA_BINOP_FWD_DEFS \
-    (R, T, dynamic_cast<const B<T>&>, R, dynamic_cast<const B<T>&>, R)
-
-#define MDIAGARRAY2_FORWARD_DEFS(B, R, T) \
-  MARRAY_UNOP_FWD_DEFS \
-    (R, T, dynamic_cast<const B<T>&>, R) \
- \
-  MDIAGARRAY2_DAS_BINOP_FWD_DEFS \
-    (R, T, dynamic_cast<const B<T>&>, R, , T) \
- \
-  MDIAGARRAY2_SDA_BINOP_FWD_DEFS \
-    (R, T, , T, dynamic_cast<const B<T>&>, R) \
- \
-  MDIAGARRAY2_DADA_BINOP_FWD_DEFS \
-    (R, T, dynamic_cast<const B<T>&>, R, dynamic_cast<const B<T>&>, R)
-
-#endif
--- a/liboctave/array/MArray-defs.h	Mon Dec 21 13:27:53 2015 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
-
-Copyright (C) 1996-2015 John W. Eaton
-Copyright (C) 2009 VZLU Prague, a.s.
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_MArray_defs_h)
-#define octave_MArray_defs_h 1
-
-#include "mx-inlines.cc"
-
-// Instantiate the OP= operators.
-#define MARRAY_OP_ASSIGN_DEFS(A_T, E_T, RHS_T, API) \
-  MARRAY_OP_ASSIGN_DECLS (A_T, E_T, template, API, , RHS_T)
-
-#define MARRAY_OP_ASSIGN_DEFS1(A_T, E_T, RHS_T, API) \
-  MARRAY_OP_ASSIGN_DECLS1 (A_T, E_T, template, API, , RHS_T)
-
-// Instantiate the unary operators.
-#define MARRAY_UNOP_DEFS(A_T, E_T, API) \
-  MARRAY_UNOP_DECLS (A_T, E_T, template, API, )
-
-// Instantiate the binary operators.
-#define MARRAY_BINOP_DEFS(A_T, E_T, API) \
-  MARRAY_BINOP_DECLS (A_T, E_T, template, API, , A_T<E_T>, E_T) \
-  MARRAY_BINOP_DECLS (A_T, E_T, template, API, , E_T, A_T<E_T>) \
-  MARRAY_AA_BINOP_DECLS (A_T, E_T, template, API, )
-
-#define MDIAGARRAY2_BINOP_DEFS(A_T, E_T, API) \
-  MDIAGARRAY2_DAS_BINOP_DECLS (A_T, E_T, template, API, , A_T<E_T>, E_T) \
-  MDIAGARRAY2_SDA_BINOP_DECLS (A_T, E_T, template, API, , E_T, A_T<E_T>) \
-  MDIAGARRAY2_DADA_BINOP_DECLS (A_T, E_T, template, API, )
-
-// The following macros are for external use.
-
-// Instantiate all the MArray friends for MArray element type T.
-#define INSTANTIATE_MARRAY_FRIENDS(T, API) \
-  MARRAY_OP_ASSIGN_DEFS1 (MArray, T, T, API) \
-  MARRAY_OP_ASSIGN_DEFS (MArray, T, MArray<T>, API) \
-  MARRAY_UNOP_DEFS (MArray, T, API) \
-  MARRAY_BINOP_DEFS (MArray, T, API)
-
-// Instantiate all the MDiagArray2 friends for MDiagArray2 element type T.
-#define INSTANTIATE_MDIAGARRAY2_FRIENDS(T, API) \
-  MARRAY_UNOP_DEFS (MDiagArray2, T, API) \
-  MDIAGARRAY2_BINOP_DEFS (MDiagArray2, T, API)
-
-// Now we have all the definitions we need.
-
-#endif
--- a/liboctave/array/MArray.cc	Mon Dec 21 13:27:53 2015 -0500
+++ b/liboctave/array/MArray.cc	Tue Dec 22 01:34:05 2015 +0100
@@ -29,9 +29,6 @@
 #include "Array-util.h"
 #include "lo-error.h"
 
-#include "MArray-defs.h"
-#include "mx-inlines.cc"
-
 template <class T>
 struct _idxadds_helper
 {
--- a/liboctave/array/MArray.h	Mon Dec 21 13:27:53 2015 -0500
+++ b/liboctave/array/MArray.h	Tue Dec 22 01:34:05 2015 +0100
@@ -1,4 +1,3 @@
-// Template array classes with like-type math ops
 /*
 
 Copyright (C) 1993-2015 John W. Eaton
@@ -26,15 +25,34 @@
 #define octave_MArray_h 1
 
 #include "Array.h"
+#include "mx-inlines.cc"
 
-// N-dimensional array with math ops.
-
-// But first, some preprocessor abuse...
+template <class T> class MArray;
 
-#include "MArray-decl.h"
+template <typename T> MArray<T>& operator += (MArray<T>&, const T&);
+template <typename T> MArray<T>& operator -= (MArray<T>&, const T&);
+template <typename T> MArray<T>& operator *= (MArray<T>&, const T&);
+template <typename T> MArray<T>& operator /= (MArray<T>&, const T&);
+template <typename T> MArray<T>& operator += (MArray<T>&, const MArray<T>&);
+template <typename T> MArray<T>& operator -= (MArray<T>&, const MArray<T>&);
+template <typename T> MArray<T>& product_eq (MArray<T>&, const MArray<T>&);
+template <typename T> MArray<T>& quotient_eq (MArray<T>&, const MArray<T>&);
+template <typename T> MArray<T> operator + (const MArray<T>&);
+template <typename T> MArray<T> operator - (const MArray<T>&);
+template <typename T> MArray<T> operator + (const MArray<T>&, const T&);
+template <typename T> MArray<T> operator - (const MArray<T>&, const T&);
+template <typename T> MArray<T> operator * (const MArray<T>&, const T&);
+template <typename T> MArray<T> operator / (const MArray<T>&, const T&);
+template <typename T> MArray<T> operator + (const T&, const MArray<T>&);
+template <typename T> MArray<T> operator - (const T&, const MArray<T>&);
+template <typename T> MArray<T> operator * (const T&, const MArray<T>&);
+template <typename T> MArray<T> operator / (const T&, const MArray<T>&);
+template <typename T> MArray<T> operator + (const MArray<T>&, const MArray<T>&);
+template <typename T> MArray<T> operator - (const MArray<T>&, const MArray<T>&);
+template <typename T> MArray<T> quotient (const MArray<T>&, const MArray<T>&);
+template <typename T> MArray<T> product (const MArray<T>&, const MArray<T>&);
 
-MARRAY_OPS_FORWARD_DECLS (MArray, )
-
+//! Template for N-dimensional array classes with like-type math operators.
 template <class T>
 class
 MArray : public Array<T>
@@ -86,11 +104,11 @@
   MArray<T> hermitian (T (*fcn) (const T&) = 0) const
   { return Array<T>::hermitian (fcn); }
 
-  // Performs indexed accumulative addition.
-
+  //! Performs indexed accumulative addition.
+  //@{
   void idx_add (const idx_vector& idx, T val);
-
   void idx_add (const idx_vector& idx, const MArray<T>& vals);
+  //@}
 
   void idx_min (const idx_vector& idx, const MArray<T>& vals);
 
@@ -101,4 +119,100 @@
   void changesign (void);
 };
 
+// Define all the MArray forwarding functions for return type R and
+// MArray element type T
+#define MARRAY_FORWARD_DEFS(B, R, T) \
+  inline R operator += (R& x, const T& y) \
+    { return R (operator += (dynamic_cast<B<T>&> (x), (y))); } \
+  inline R operator -= (R& x, const T& y) \
+    { return R (operator -= (dynamic_cast<B<T>&> (x), (y))); } \
+  inline R operator *= (R& x, const T& y) \
+    { return R (operator *= (dynamic_cast<B<T>&> (x), (y))); } \
+  inline R operator /= (R& x, const T& y) \
+    { return R (operator /= (dynamic_cast<B<T>&> (x), (y))); } \
+  inline R operator += (R& x, const R& y) \
+    { return R (operator += (dynamic_cast<B<T>&> (x), \
+                             dynamic_cast<const B<T>&> (y))); } \
+  inline R operator -= (R& x, const R& y) \
+    { return R (operator -= (dynamic_cast<B<T>&> (x), \
+                             dynamic_cast<const B<T>&> (y))); } \
+  inline R product_eq (R& x, const R& y) \
+    { return R (product_eq (dynamic_cast<B<T>&> (x), \
+                            dynamic_cast<const B<T>&> (y))); } \
+  inline R quotient_eq (R& x, const R& y) \
+    { return R (quotient_eq (dynamic_cast<B<T>&> (x), \
+                             dynamic_cast<const B<T>&> (y))); } \
+  inline R operator + (const R& x) \
+    { return R (operator + (dynamic_cast<const B<T>&> (x))); } \
+  inline R operator - (const R& x) \
+    { return R (operator - (dynamic_cast<const B<T>&> (x))); } \
+  inline R operator + (const R& x, const T& y) \
+    { return R (operator + (dynamic_cast<const B<T>&> (x), (y))); } \
+  inline R operator - (const R& x, const T& y) \
+    { return R (operator - (dynamic_cast<const B<T>&> (x), (y))); } \
+  inline R operator * (const R& x, const T& y) \
+    { return R (operator * (dynamic_cast<const B<T>&> (x), (y))); } \
+  inline R operator / (const R& x, const T& y) \
+    { return R (operator / (dynamic_cast<const B<T>&> (x), (y))); } \
+  inline R operator + (const T& x, const R& y) \
+    { return R (operator + ( (x), dynamic_cast<const B<T>&> (y))); } \
+  inline R operator - (const T& x, const R& y) \
+    { return R (operator - ( (x), dynamic_cast<const B<T>&> (y))); } \
+  inline R operator * (const T& x, const R& y) \
+    { return R (operator * ( (x), dynamic_cast<const B<T>&> (y))); } \
+  inline R operator / (const T& x, const R& y) \
+    { return R (operator / ( (x), dynamic_cast<const B<T>&> (y))); } \
+  inline R operator + (const R& x, const R& y) \
+    { return R (operator + (dynamic_cast<const B<T>&> (x), \
+                            dynamic_cast<const B<T>&> (y))); } \
+  inline R operator - (const R& x, const R& y) \
+    { return R (operator - (dynamic_cast<const B<T>&> (x), \
+                            dynamic_cast<const B<T>&> (y))); } \
+  inline R product (const R& x, const R& y) \
+    { return R (product (dynamic_cast<const B<T>&> (x), \
+                         dynamic_cast<const B<T>&> (y))); } \
+  inline R quotient (const R& x, const R& y) \
+    { return R (quotient (dynamic_cast<const B<T>&> (x), \
+                          dynamic_cast<const B<T>&> (y))); }
+
+// Instantiate all the MArray friends for MArray element type T.
+#define INSTANTIATE_MARRAY_FRIENDS(T, API) \
+  template API MArray<T>& operator += (MArray<T>&, const T&); \
+  template API MArray<T>& operator -= (MArray<T>&, const T&); \
+  template API MArray<T>& operator *= (MArray<T>&, const T&); \
+  template API MArray<T>& operator /= (MArray<T>&, const T&); \
+  template API MArray<T>& operator += (MArray<T>&, const MArray<T>&); \
+  template API MArray<T>& operator -= (MArray<T>&, const MArray<T>&); \
+  template API MArray<T>& product_eq (MArray<T>&, const MArray<T>&); \
+  template API MArray<T>& quotient_eq (MArray<T>&, const MArray<T>&); \
+  template API MArray<T> operator + (const MArray<T>&); \
+  template API MArray<T> operator - (const MArray<T>&); \
+  template API MArray<T> operator + (const MArray<T>&, const T&); \
+  template API MArray<T> operator - (const MArray<T>&, const T&); \
+  template API MArray<T> operator * (const MArray<T>&, const T&); \
+  template API MArray<T> operator / (const MArray<T>&, const T&); \
+  template API MArray<T> operator + (const T&, const MArray<T>&); \
+  template API MArray<T> operator - (const T&, const MArray<T>&); \
+  template API MArray<T> operator * (const T&, const MArray<T>&); \
+  template API MArray<T> operator / (const T&, const MArray<T>&); \
+  template API MArray<T> operator + (const MArray<T>&, const MArray<T>&); \
+  template API MArray<T> operator - (const MArray<T>&, const MArray<T>&); \
+  template API MArray<T> quotient (const MArray<T>&, const MArray<T>&); \
+  template API MArray<T> product (const MArray<T>&, const MArray<T>&);
+
+// Instantiate all the MDiagArray2 friends for MDiagArray2 element type T.
+#define INSTANTIATE_MDIAGARRAY2_FRIENDS(T, API) \
+  template API MDiagArray2<T> operator + (const MDiagArray2<T>&); \
+  template API MDiagArray2<T> operator - (const MDiagArray2<T>&); \
+  template API MDiagArray2<T> operator * (const MDiagArray2<T>&, const T&); \
+  template API MDiagArray2<T> operator / (const MDiagArray2<T>&, const T&); \
+  template API MDiagArray2<T> operator * (const T&, const MDiagArray2<T>&); \
+  template API MDiagArray2<T> operator + (const MDiagArray2<T>&, \
+                                          const MDiagArray2<T>&); \
+  template API MDiagArray2<T> operator - (const MDiagArray2<T>&, \
+                                          const MDiagArray2<T>&); \
+  template API MDiagArray2<T> product (const MDiagArray2<T>&, \
+                                       const MDiagArray2<T>&);
+
 #endif
+
--- a/liboctave/array/MDiagArray2.cc	Mon Dec 21 13:27:53 2015 -0500
+++ b/liboctave/array/MDiagArray2.cc	Tue Dec 22 01:34:05 2015 +0100
@@ -29,8 +29,6 @@
 #include "Array-util.h"
 #include "lo-error.h"
 
-#include "MArray-defs.h"
-
 template <class T>
 bool
 MDiagArray2<T>::is_multiple_of_identity (T val) const
--- a/liboctave/array/MDiagArray2.h	Mon Dec 21 13:27:53 2015 -0500
+++ b/liboctave/array/MDiagArray2.h	Tue Dec 22 01:34:05 2015 +0100
@@ -28,14 +28,24 @@
 #include "DiagArray2.h"
 #include "MArray.h"
 
-// Two dimensional diagonal array with math ops.
-
-// But first, some preprocessor abuse...
+template <class T> class MDiagArray2;
 
-#include "MArray-decl.h"
+template <typename T> MDiagArray2<T> operator + (const MDiagArray2<T>&);
+template <typename T> MDiagArray2<T> operator - (const MDiagArray2<T>&);
+template <typename T> MDiagArray2<T> operator * (const MDiagArray2<T>&,
+                                                 const T&);
+template <typename T> MDiagArray2<T> operator / (const MDiagArray2<T>&,
+                                                 const T&);
+template <typename T> MDiagArray2<T> operator * (const T&,
+                                                 const MDiagArray2<T>&);
+template <typename T> MDiagArray2<T> operator + (const MDiagArray2<T>&,
+                                                 const MDiagArray2<T>&);
+template <typename T> MDiagArray2<T> operator - (const MDiagArray2<T>&,
+                                                 const MDiagArray2<T>&);
+template <typename T> MDiagArray2<T> product (const MDiagArray2<T>&,
+                                              const MDiagArray2<T>&);
 
-MDIAGARRAY2_OPS_FORWARD_DECLS (MDiagArray2, )
-
+//! Template for two dimensional diagonal array with math operators.
 template <class T>
 class
 MDiagArray2 : public DiagArray2<T>
@@ -103,8 +113,39 @@
   // Currently, the OPS functions don't need to be friends, but that
   // may change.
 
-  MDIAGARRAY2_OPS_FRIEND_DECLS (MDiagArray2, )
+  friend MDiagArray2<T> operator + <> (const MDiagArray2<T>&);
+  friend MDiagArray2<T> operator - <> (const MDiagArray2<T>&);
+  friend MDiagArray2<T> operator * <> (const MDiagArray2<T>&, const T&);
+  friend MDiagArray2<T> operator / <> (const MDiagArray2<T>&, const T&);
+  friend MDiagArray2<T> operator * <> (const T&, const MDiagArray2<T>&);
+  friend MDiagArray2<T> operator + <> (const MDiagArray2<T>&,
+                                       const MDiagArray2<T>&);
+  friend MDiagArray2<T> operator - <> (const MDiagArray2<T>&,
+                                       const MDiagArray2<T>&);
+  friend MDiagArray2<T> product <> (const MDiagArray2<T>&,
+                                    const MDiagArray2<T>&);
 
 };
 
+#define MDIAGARRAY2_FORWARD_DEFS(B, R, T) \
+  inline R operator + (const R& x) \
+    { return R (operator + (dynamic_cast<const B<T>&> (x))); } \
+  inline R operator - (const R& x) \
+    { return R (operator - (dynamic_cast<const B<T>&> (x))); } \
+  inline R operator * (const R& x, const T& y) \
+    { return R (operator * (dynamic_cast<const B<T>&> (x), (y))); } \
+  inline R operator / (const R& x, const T& y) \
+    { return R (operator / (dynamic_cast<const B<T>&> (x), (y))); } \
+  inline R operator * (const T& x, const R& y) \
+    { return R (operator * ( (x), dynamic_cast<const B<T>&> (y))); } \
+  inline R operator + (const R& x, const R& y) \
+    { return R (operator + (dynamic_cast<const B<T>&> (x), \
+                            dynamic_cast<const B<T>&> (y))); } \
+  inline R operator - (const R& x, const R& y) \
+    { return R (operator - (dynamic_cast<const B<T>&> (x), \
+                            dynamic_cast<const B<T>&> (y))); } \
+  inline R product (const R& x, const R& y) \
+    { return R (product (dynamic_cast<const B<T>&> (x), \
+                         dynamic_cast<const B<T>&> (y))); }
+
 #endif
--- a/liboctave/array/boolNDArray.cc	Mon Dec 21 13:27:53 2015 -0500
+++ b/liboctave/array/boolNDArray.cc	Tue Dec 22 01:34:05 2015 +0100
@@ -32,7 +32,6 @@
 #include "mx-base.h"
 #include "lo-ieee.h"
 #include "mx-op-defs.h"
-#include "MArray-defs.h"
 
 #include "bsxfun-defs.cc"
 
--- a/liboctave/array/fCNDArray.cc	Mon Dec 21 13:27:53 2015 -0500
+++ b/liboctave/array/fCNDArray.cc	Tue Dec 22 01:34:05 2015 +0100
@@ -36,7 +36,6 @@
 #include "functor.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
-#include "MArray-defs.h"
 #include "mx-base.h"
 #include "mx-op-defs.h"
 #include "mx-fcnda-fs.h"
--- a/liboctave/array/module.mk	Mon Dec 21 13:27:53 2015 -0500
+++ b/liboctave/array/module.mk	Tue Dec 22 01:34:05 2015 +0100
@@ -36,8 +36,6 @@
   liboctave/array/int64NDArray.h \
   liboctave/array/int8NDArray.h \
   liboctave/array/intNDArray.h \
-  liboctave/array/MArray-decl.h \
-  liboctave/array/MArray-defs.h \
   liboctave/array/MArray.h \
   liboctave/array/Matrix.h \
   liboctave/array/MatrixType.h \