changeset 9550:3d6a9aea2aea

refactor binary & bool ops in liboctave
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 19 Aug 2009 22:55:15 +0200
parents ed34b1da0e26
children 19d298e6f7e5
files liboctave/CColVector.cc liboctave/CDiagMatrix.cc liboctave/CMatrix.cc liboctave/CNDArray.cc liboctave/CRowVector.cc liboctave/ChangeLog liboctave/boolMatrix.cc liboctave/boolMatrix.h liboctave/boolNDArray.cc liboctave/chMatrix.cc liboctave/chNDArray.cc liboctave/dColVector.cc liboctave/dDiagMatrix.cc liboctave/dMatrix.cc liboctave/dNDArray.cc liboctave/dRowVector.cc liboctave/fCColVector.cc liboctave/fCDiagMatrix.cc liboctave/fCMatrix.cc liboctave/fCNDArray.cc liboctave/fCRowVector.cc liboctave/fColVector.cc liboctave/fDiagMatrix.cc liboctave/fMatrix.cc liboctave/fNDArray.cc liboctave/fRowVector.cc liboctave/int16NDArray.cc liboctave/int32NDArray.cc liboctave/int64NDArray.cc liboctave/int8NDArray.cc liboctave/mk-ops.awk liboctave/mx-inlines.cc liboctave/mx-op-defs.h liboctave/uint16NDArray.cc liboctave/uint32NDArray.cc liboctave/uint64NDArray.cc liboctave/uint8NDArray.cc
diffstat 37 files changed, 509 insertions(+), 588 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/CColVector.cc
+++ b/liboctave/CColVector.cc
@@ -63,7 +63,7 @@
   octave_idx_type len = length ();
   if (len != a.length ())
     return 0;
-  return mx_inline_equal (data (), a.data (), len);
+  return mx_inline_equal (len, data (), a.data ());
 }
 
 bool
@@ -291,7 +291,7 @@
 
   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_add2 (d, a.data (), len);
+  mx_inline_add2 (len, d, a.data ());
   return *this;
 }
 
@@ -313,7 +313,7 @@
 
   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_subtract2 (d, a.data (), len);
+  mx_inline_sub2 (len, d, a.data ());
   return *this;
 }
 
--- a/liboctave/CDiagMatrix.cc
+++ b/liboctave/CDiagMatrix.cc
@@ -50,7 +50,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return 0;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
@@ -445,7 +445,7 @@
 
   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_add2 (d, a.data (), length ());
+  mx_inline_add2 (length (), d, a.data ());
   return *this;
 }
 
--- a/liboctave/CMatrix.cc
+++ b/liboctave/CMatrix.cc
@@ -304,7 +304,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return false;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
@@ -3025,7 +3025,7 @@
 
   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_add2 (d, a.data (), length ());
+  mx_inline_add2 (length (), d, a.data ());
   return *this;
 }
 
@@ -3049,7 +3049,7 @@
 
   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_subtract2 (d, a.data (), length ());
+  mx_inline_sub2 (length (), d, a.data ());
   return *this;
 }
 
@@ -4075,13 +4075,13 @@
 }
 
 MS_CMP_OPS(ComplexMatrix, std::real, Complex, std::real)
-MS_BOOL_OPS(ComplexMatrix, Complex, 0.0)
+MS_BOOL_OPS (ComplexMatrix, Complex)
 
 SM_CMP_OPS(Complex, std::real, ComplexMatrix, std::real)
-SM_BOOL_OPS(Complex, ComplexMatrix, 0.0)
+SM_BOOL_OPS (Complex, ComplexMatrix)
 
 MM_CMP_OPS(ComplexMatrix, std::real, ComplexMatrix, std::real)
-MM_BOOL_OPS(ComplexMatrix, ComplexMatrix, 0.0)
+MM_BOOL_OPS (ComplexMatrix, ComplexMatrix)
 
 /*
 ;;; Local Variables: ***
--- a/liboctave/CNDArray.cc
+++ b/liboctave/CNDArray.cc
@@ -1076,13 +1076,13 @@
 }
 
 NDS_CMP_OPS(ComplexNDArray, std::real, Complex, std::real)
-NDS_BOOL_OPS(ComplexNDArray, Complex, 0.0)
+NDS_BOOL_OPS (ComplexNDArray, Complex)
 
 SND_CMP_OPS(Complex, std::real, ComplexNDArray, std::real)
-SND_BOOL_OPS(Complex, ComplexNDArray, 0.0)
+SND_BOOL_OPS (Complex, ComplexNDArray)
 
 NDND_CMP_OPS(ComplexNDArray, std::real, ComplexNDArray, std::real)
-NDND_BOOL_OPS(ComplexNDArray, ComplexNDArray, 0.0)
+NDND_BOOL_OPS (ComplexNDArray, ComplexNDArray)
 
 ComplexNDArray& operator *= (ComplexNDArray& a, double s)
 {
--- a/liboctave/CRowVector.cc
+++ b/liboctave/CRowVector.cc
@@ -67,7 +67,7 @@
   octave_idx_type len = length ();
   if (len != a.length ())
     return 0;
-  return mx_inline_equal (data (), a.data (), len);
+  return mx_inline_equal (len, data (), a.data ());
 }
 
 bool
@@ -294,7 +294,7 @@
 
   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_add2 (d, a.data (), len);
+  mx_inline_add2 (len, d, a.data ());
   return *this;
 }
 
@@ -316,7 +316,7 @@
 
   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_subtract2 (d, a.data (), len);
+  mx_inline_sub2 (len, d, a.data ());
   return *this;
 }
 
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,71 @@
+2009-08-20  Jaroslav Hajek  <highegg@gmail.com>
+
+	* mx-inlines.cc (mx_inline_add, mx_inline_sub, mx_inline_mul,
+	mx_inline_div, mx_inline_uminus, mx_inline_not, mx_inline_add2,
+	mx_inline_sub2, mx_inline_mul2, mx_inline_div2, mx_inline_iszero,
+	mx_inline_notzero, mx_inline_and, mx_inline_or, mx_inline_not_and,
+	mx_inline_not_or, mx_inline_and_not, mx_inline_or_not, 
+	mx_inline_lt, mx_inline_le, mx_inline_gt, mx_inline_ge,
+	mx_inline_eq, mx_inline_ne): New templates.
+	(do_mx_unary_op, do_mm_binary_op, do_sm_binary_op,
+	do_ms_binary_op, do_mm_inplace_op,do_ms_inplace_op):
+	New templates.
+
+	* mx-op-defs.h (ND_LOGICAL_NAN_CHECK, SC_LOGICAL_NAN_CHECK):
+	New macros.
+	(NDND_BIN_OP, NDS_BIN_OP, SND_BIN_OP): Simplify.
+	(MM_BIN_OP, MS_BIN_OP, MM_BIN_OP): Simplify.
+	(NDND_BOOL_OP, NDS_BOOL_OP, SND_BOOL_OP): Simplify.
+	(MM_BOOL_OP, MS_BOOL_OP, MM_BOOL_OP): Simplify.
+	(NDND_BOOL_OPS2, NDS_BOOL_OPS2, SND_BOOL_OPS2,
+	MM_BOOL_OPS2, MS_BOOL_OPS2, SM_BOOL_OPS2): Remove.
+	* mx-op-decl.h (NDND_BOOL_OPX_DECLS, NDS_BOOL_OPX_DECLS,
+	SND_BOOL_OPX_DECLS): New macros.
+	* mk-ops.awk: use _BOOL_OPS rather than _BOOL_OPS2.
+
+	* boolMatrix.cc: Add missing bool op defs.
+	* boolMatrix.h: Add missing bool op decls.
+
+
+	* boolNDArray.cc: Remove unused arg to BOOL_OPS.
+	* CMatrix.cc: Ditto.
+	* CNDArray.cc: Ditto.
+	* ChangeLog: Ditto.
+	* chMatrix.cc: Ditto.
+	* chNDArray.cc: Ditto.
+	* dMatrix.cc: Ditto.
+	* dNDArray.cc: Ditto.
+	* fCMatrix.cc: Ditto.
+	* fCNDArray.cc: Ditto.
+	* fMatrix.cc: Ditto.
+	* fNDArray.cc: Ditto.
+	* int16NDArray.cc: Ditto.
+	* int32NDArray.cc: Ditto.
+	* int64NDArray.cc: Ditto.
+	* int8NDArray.cc: Ditto.
+	* uint16NDArray.cc: Ditto.
+	* uint32NDArray.cc: Ditto.
+	* uint64NDArray.cc: Ditto.
+	* uint8NDArray.cc: Ditto.
+
+	* CColVector.cc: Update syntax where needed.
+	* CDiagMatrix.cc: Ditto.
+	* CMatrix.cc: Ditto.
+	* CRowVector.cc: Ditto.
+	* chMatrix.cc: Ditto.
+	* dColVector.cc: Ditto.
+	* dDiagMatrix.cc: Ditto.
+	* dMatrix.cc: Ditto.
+	* dRowVector.cc: Ditto.
+	* fCColVector.cc: Ditto.
+	* fCDiagMatrix.cc: Ditto.
+	* fCMatrix.cc: Ditto.
+	* fCRowVector.cc: Ditto.
+	* fColVector.cc: Ditto.
+	* fDiagMatrix.cc: Ditto.
+	* fMatrix.cc: Ditto.
+	* fRowVector.cc: Ditto.
+
 2009-08-19  Jaroslav Hajek  <highegg@gmail.com>
 
 	* Array-util.cc (zero_dims_inquire): Add matching ndims case.
--- a/liboctave/boolMatrix.cc
+++ b/liboctave/boolMatrix.cc
@@ -43,7 +43,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return 0;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
@@ -99,6 +99,9 @@
   return do_mx_red_op<boolMatrix, bool> (*this, dim, mx_inline_any);
 }
 
+MM_BOOL_OPS (boolMatrix, boolMatrix)
+MS_BOOL_OPS (boolMatrix, bool)
+SM_BOOL_OPS (bool, boolMatrix)
 MM_CMP_OPS (boolMatrix, , boolMatrix, )
 
 /*
--- a/liboctave/boolMatrix.h
+++ b/liboctave/boolMatrix.h
@@ -83,6 +83,9 @@
   boolMatrix (bool *b, octave_idx_type r, octave_idx_type c) : Array2<bool> (b, r, c) { }
 };
 
+MM_BOOL_OP_DECLS (boolMatrix, boolMatrix, OCTAVE_API)
+MS_BOOL_OP_DECLS (boolMatrix, bool, OCTAVE_API)
+SM_BOOL_OP_DECLS (bool, boolMatrix, OCTAVE_API)
 MM_CMP_OP_DECLS (boolMatrix, boolMatrix, OCTAVE_API)
 
 #endif
--- a/liboctave/boolNDArray.cc
+++ b/liboctave/boolNDArray.cc
@@ -38,12 +38,7 @@
 boolNDArray
 boolNDArray::operator ! (void) const
 {
-  boolNDArray b (dims ());
-
-  for (octave_idx_type i = 0; i < length (); i++)
-    b.elem (i) = ! elem (i);
-
-  return b;
+  return do_mx_unary_op<boolNDArray> (*this, mx_inline_not);
 }
 
 // FIXME -- this is not quite the right thing.
@@ -146,13 +141,13 @@
   return ArrayN<bool>::diag (k);
 }
 
-NDND_BOOL_OPS (boolNDArray, boolNDArray, false)
+NDND_BOOL_OPS (boolNDArray, boolNDArray)
 NDND_CMP_OPS (boolNDArray, , boolNDArray, )
 
-NDS_BOOL_OPS (boolNDArray, bool, false)
+NDS_BOOL_OPS (boolNDArray, bool)
 NDS_CMP_OPS (boolNDArray, , bool, )
 
-SND_BOOL_OPS (bool, boolNDArray, false)
+SND_BOOL_OPS (bool, boolNDArray)
 SND_CMP_OPS (bool, , boolNDArray, )
 
 boolNDArray& 
--- a/liboctave/chMatrix.cc
+++ b/liboctave/chMatrix.cc
@@ -94,7 +94,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return 0;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
@@ -215,13 +215,13 @@
 }
 
 MS_CMP_OPS(charMatrix, , char, )
-MS_BOOL_OPS(charMatrix, char, 0)
+MS_BOOL_OPS (charMatrix, char)
 
 SM_CMP_OPS(char, , charMatrix, )
-SM_BOOL_OPS(char, charMatrix, 0)
+SM_BOOL_OPS (char, charMatrix)
 
 MM_CMP_OPS(charMatrix, , charMatrix, )
-MM_BOOL_OPS(charMatrix, charMatrix, 0)
+MM_BOOL_OPS (charMatrix, charMatrix)
 
 /*
 ;;; Local Variables: ***
--- a/liboctave/chNDArray.cc
+++ b/liboctave/chNDArray.cc
@@ -207,13 +207,13 @@
 }
 
 NDS_CMP_OPS(charNDArray, , char, )
-NDS_BOOL_OPS(charNDArray, char, 0)
+NDS_BOOL_OPS (charNDArray, char)
 
 SND_CMP_OPS(char, , charNDArray, )
-SND_BOOL_OPS(char, charNDArray, 0)
+SND_BOOL_OPS (char, charNDArray)
 
 NDND_CMP_OPS(charNDArray, , charNDArray, )
-NDND_BOOL_OPS(charNDArray, charNDArray, 0)
+NDND_BOOL_OPS (charNDArray, charNDArray)
 
 /*
 ;;; Local Variables: ***
--- a/liboctave/dColVector.cc
+++ b/liboctave/dColVector.cc
@@ -57,7 +57,7 @@
   octave_idx_type len = length ();
   if (len != a.length ())
     return 0;
-  return mx_inline_equal (data (), a.data (), len);
+  return mx_inline_equal (len, data (), a.data ());
 }
 
 bool
--- a/liboctave/dDiagMatrix.cc
+++ b/liboctave/dDiagMatrix.cc
@@ -42,7 +42,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return 0;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
--- a/liboctave/dMatrix.cc
+++ b/liboctave/dMatrix.cc
@@ -267,7 +267,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return false;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
@@ -3404,13 +3404,13 @@
 }
 
 MS_CMP_OPS(Matrix, , double, )
-MS_BOOL_OPS(Matrix, double, 0.0)
+MS_BOOL_OPS (Matrix, double)
 
 SM_CMP_OPS(double, , Matrix, )
-SM_BOOL_OPS(double, Matrix, 0.0)
+SM_BOOL_OPS (double, Matrix)
 
 MM_CMP_OPS(Matrix, , Matrix, )
-MM_BOOL_OPS(Matrix, Matrix, 0.0)
+MM_BOOL_OPS (Matrix, Matrix)
 
 /*
 ;;; Local Variables: ***
--- a/liboctave/dNDArray.cc
+++ b/liboctave/dNDArray.cc
@@ -1122,13 +1122,13 @@
 }
 
 NDS_CMP_OPS(NDArray, , double, )
-NDS_BOOL_OPS(NDArray, double, 0.0)
+NDS_BOOL_OPS (NDArray, double)
 
 SND_CMP_OPS(double, , NDArray, )
-SND_BOOL_OPS(double, NDArray, 0.0)
+SND_BOOL_OPS (double, NDArray)
 
 NDND_CMP_OPS(NDArray, , NDArray, )
-NDND_BOOL_OPS(NDArray, NDArray, 0.0)
+NDND_BOOL_OPS (NDArray, NDArray)
 
 /*
 ;;; Local Variables: ***
--- a/liboctave/dRowVector.cc
+++ b/liboctave/dRowVector.cc
@@ -59,7 +59,7 @@
   octave_idx_type len = length ();
   if (len != a.length ())
     return 0;
-  return mx_inline_equal (data (), a.data (), len);
+  return mx_inline_equal (len, data (), a.data ());
 }
 
 bool
--- a/liboctave/fCColVector.cc
+++ b/liboctave/fCColVector.cc
@@ -63,7 +63,7 @@
   octave_idx_type len = length ();
   if (len != a.length ())
     return 0;
-  return mx_inline_equal (data (), a.data (), len);
+  return mx_inline_equal (len, data (), a.data ());
 }
 
 bool
@@ -291,7 +291,7 @@
 
   FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_add2 (d, a.data (), len);
+  mx_inline_add2 (len, d, a.data ());
   return *this;
 }
 
@@ -313,7 +313,7 @@
 
   FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_subtract2 (d, a.data (), len);
+  mx_inline_sub2 (len, d, a.data ());
   return *this;
 }
 
--- a/liboctave/fCDiagMatrix.cc
+++ b/liboctave/fCDiagMatrix.cc
@@ -50,7 +50,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return 0;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
@@ -445,7 +445,7 @@
 
   FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_add2 (d, a.data (), length ());
+  mx_inline_add2 (length (), d, a.data ());
   return *this;
 }
 
--- a/liboctave/fCMatrix.cc
+++ b/liboctave/fCMatrix.cc
@@ -303,7 +303,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return false;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
@@ -3018,7 +3018,7 @@
 
   FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_add2 (d, a.data (), length ());
+  mx_inline_add2 (length (), d, a.data ());
   return *this;
 }
 
@@ -3042,7 +3042,7 @@
 
   FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_subtract2 (d, a.data (), length ());
+  mx_inline_sub2 (length (), d, a.data ());
   return *this;
 }
 
@@ -4068,13 +4068,13 @@
 }
 
 MS_CMP_OPS(FloatComplexMatrix, std::real, FloatComplex, std::real)
-MS_BOOL_OPS(FloatComplexMatrix, FloatComplex, static_cast<float> (0.0))
+MS_BOOL_OPS (FloatComplexMatrix, FloatComplex)
 
 SM_CMP_OPS(FloatComplex, std::real, FloatComplexMatrix, std::real)
-SM_BOOL_OPS(FloatComplex, FloatComplexMatrix, static_cast<float> (0.0))
+SM_BOOL_OPS (FloatComplex, FloatComplexMatrix)
 
 MM_CMP_OPS(FloatComplexMatrix, std::real, FloatComplexMatrix, std::real)
-MM_BOOL_OPS(FloatComplexMatrix, FloatComplexMatrix, static_cast<float> (0.0))
+MM_BOOL_OPS (FloatComplexMatrix, FloatComplexMatrix)
 
 /*
 ;;; Local Variables: ***
--- a/liboctave/fCNDArray.cc
+++ b/liboctave/fCNDArray.cc
@@ -1071,13 +1071,13 @@
 }
 
 NDS_CMP_OPS(FloatComplexNDArray, std::real, FloatComplex, std::real)
-NDS_BOOL_OPS(FloatComplexNDArray, FloatComplex, static_cast<float> (0.0))
+NDS_BOOL_OPS (FloatComplexNDArray, FloatComplex)
 
 SND_CMP_OPS(FloatComplex, std::real, FloatComplexNDArray, std::real)
-SND_BOOL_OPS(FloatComplex, FloatComplexNDArray, static_cast<float> (0.0))
+SND_BOOL_OPS (FloatComplex, FloatComplexNDArray)
 
 NDND_CMP_OPS(FloatComplexNDArray, std::real, FloatComplexNDArray, std::real)
-NDND_BOOL_OPS(FloatComplexNDArray, FloatComplexNDArray, static_cast<float> (0.0))
+NDND_BOOL_OPS (FloatComplexNDArray, FloatComplexNDArray)
 
 FloatComplexNDArray& operator *= (FloatComplexNDArray& a, float s)
 {
--- a/liboctave/fCRowVector.cc
+++ b/liboctave/fCRowVector.cc
@@ -67,7 +67,7 @@
   octave_idx_type len = length ();
   if (len != a.length ())
     return 0;
-  return mx_inline_equal (data (), a.data (), len);
+  return mx_inline_equal (len, data (), a.data ());
 }
 
 bool
@@ -294,7 +294,7 @@
 
   FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_add2 (d, a.data (), len);
+  mx_inline_add2 (len, d, a.data ());
   return *this;
 }
 
@@ -316,7 +316,7 @@
 
   FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
 
-  mx_inline_subtract2 (d, a.data (), len);
+  mx_inline_sub2 (len, d, a.data ());
   return *this;
 }
 
--- a/liboctave/fColVector.cc
+++ b/liboctave/fColVector.cc
@@ -57,7 +57,7 @@
   octave_idx_type len = length ();
   if (len != a.length ())
     return 0;
-  return mx_inline_equal (data (), a.data (), len);
+  return mx_inline_equal (len, data (), a.data ());
 }
 
 bool
--- a/liboctave/fDiagMatrix.cc
+++ b/liboctave/fDiagMatrix.cc
@@ -42,7 +42,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return 0;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
--- a/liboctave/fMatrix.cc
+++ b/liboctave/fMatrix.cc
@@ -266,7 +266,7 @@
   if (rows () != a.rows () || cols () != a.cols ())
     return false;
 
-  return mx_inline_equal (data (), a.data (), length ());
+  return mx_inline_equal (length (), data (), a.data ());
 }
 
 bool
@@ -3403,13 +3403,13 @@
 }
 
 MS_CMP_OPS(FloatMatrix, , float, )
-MS_BOOL_OPS(FloatMatrix, float, 0.0)
+MS_BOOL_OPS (FloatMatrix, float)
 
 SM_CMP_OPS(float, , FloatMatrix, )
-SM_BOOL_OPS(float, FloatMatrix, 0.0)
+SM_BOOL_OPS (float, FloatMatrix)
 
 MM_CMP_OPS(FloatMatrix, , FloatMatrix, )
-MM_BOOL_OPS(FloatMatrix, FloatMatrix, 0.0)
+MM_BOOL_OPS (FloatMatrix, FloatMatrix)
 
 /*
 ;;; Local Variables: ***
--- a/liboctave/fNDArray.cc
+++ b/liboctave/fNDArray.cc
@@ -1080,13 +1080,13 @@
 }
 
 NDS_CMP_OPS(FloatNDArray, , float, )
-NDS_BOOL_OPS(FloatNDArray, float, static_cast<float> (0.0))
+NDS_BOOL_OPS (FloatNDArray, float)
 
 SND_CMP_OPS(float, , FloatNDArray, )
-SND_BOOL_OPS(float, FloatNDArray, static_cast<float> (0.0))
+SND_BOOL_OPS (float, FloatNDArray)
 
 NDND_CMP_OPS(FloatNDArray, , FloatNDArray, )
-NDND_BOOL_OPS(FloatNDArray, FloatNDArray, static_cast<float> (0.0))
+NDND_BOOL_OPS (FloatNDArray, FloatNDArray)
 
 /*
 ;;; Local Variables: ***
--- a/liboctave/fRowVector.cc
+++ b/liboctave/fRowVector.cc
@@ -59,7 +59,7 @@
   octave_idx_type len = length ();
   if (len != a.length ())
     return 0;
-  return mx_inline_equal (data (), a.data (), len);
+  return mx_inline_equal (len, data (), a.data ());
 }
 
 bool
--- a/liboctave/int16NDArray.cc
+++ b/liboctave/int16NDArray.cc
@@ -40,13 +40,13 @@
 operator >> (std::istream& is, intNDArray<octave_int16>& a);
 
 NDS_CMP_OPS (int16NDArray, , octave_int16, )
-NDS_BOOL_OPS (int16NDArray, octave_int16, octave_int16 (0))
+NDS_BOOL_OPS (int16NDArray, octave_int16)
 
 SND_CMP_OPS (octave_int16, , int16NDArray, )
-SND_BOOL_OPS (octave_int16, int16NDArray, octave_int16 (0))
+SND_BOOL_OPS (octave_int16, int16NDArray)
 
 NDND_CMP_OPS (int16NDArray, , int16NDArray, )
-NDND_BOOL_OPS (int16NDArray, int16NDArray, octave_int16 (0))
+NDND_BOOL_OPS (int16NDArray, int16NDArray)
 
 MINMAX_FCNS (int16)
 
--- a/liboctave/int32NDArray.cc
+++ b/liboctave/int32NDArray.cc
@@ -40,13 +40,13 @@
 operator >> (std::istream& is, intNDArray<octave_int32>& a);
 
 NDS_CMP_OPS (int32NDArray, , octave_int32, )
-NDS_BOOL_OPS (int32NDArray, octave_int32, octave_int32 (0))
+NDS_BOOL_OPS (int32NDArray, octave_int32)
 
 SND_CMP_OPS (octave_int32, , int32NDArray, )
-SND_BOOL_OPS (octave_int32, int32NDArray, octave_int32 (0))
+SND_BOOL_OPS (octave_int32, int32NDArray)
 
 NDND_CMP_OPS (int32NDArray, , int32NDArray, )
-NDND_BOOL_OPS (int32NDArray, int32NDArray, octave_int32 (0))
+NDND_BOOL_OPS (int32NDArray, int32NDArray)
 
 MINMAX_FCNS (int32)
 
--- a/liboctave/int64NDArray.cc
+++ b/liboctave/int64NDArray.cc
@@ -40,13 +40,13 @@
 operator >> (std::istream& is, intNDArray<octave_int64>& a);
 
 NDS_CMP_OPS (int64NDArray, , octave_int64, )
-NDS_BOOL_OPS (int64NDArray, octave_int64, octave_int64 (0))
+NDS_BOOL_OPS (int64NDArray, octave_int64)
 
 SND_CMP_OPS (octave_int64, , int64NDArray, )
-SND_BOOL_OPS (octave_int64, int64NDArray, octave_int64 (0))
+SND_BOOL_OPS (octave_int64, int64NDArray)
 
 NDND_CMP_OPS (int64NDArray, , int64NDArray, )
-NDND_BOOL_OPS (int64NDArray, int64NDArray, octave_int64 (0))
+NDND_BOOL_OPS (int64NDArray, int64NDArray)
 
 MINMAX_FCNS (int64)
 
--- a/liboctave/int8NDArray.cc
+++ b/liboctave/int8NDArray.cc
@@ -40,13 +40,13 @@
 operator >> (std::istream& is, intNDArray<octave_int8>& a);
 
 NDS_CMP_OPS (int8NDArray, , octave_int8, )
-NDS_BOOL_OPS (int8NDArray, octave_int8, octave_int8 (0))
+NDS_BOOL_OPS (int8NDArray, octave_int8)
 
 SND_CMP_OPS (octave_int8, , int8NDArray, )
-SND_BOOL_OPS (octave_int8, int8NDArray, octave_int8 (0))
+SND_BOOL_OPS (octave_int8, int8NDArray)
 
 NDND_CMP_OPS (int8NDArray, , int8NDArray, )
-NDND_BOOL_OPS (int8NDArray, int8NDArray, octave_int8 (0))
+NDND_BOOL_OPS (int8NDArray, int8NDArray)
 
 MINMAX_FCNS (int8)
 
--- a/liboctave/mk-ops.awk
+++ b/liboctave/mk-ops.awk
@@ -256,9 +256,8 @@
 	    }
 
           if (bool_ops)
-            printf ("%s%s_BOOL_OPS2 (%s, %s, %s, %s)\n", lhs_class, rhs_class,
-	            lhs_type, rhs_type, lhs_scalar_zero_val,
-	            rhs_scalar_zero_val) >> cc_file
+            printf ("%s%s_BOOL_OPS (%s, %s)\n", lhs_class, rhs_class,
+	            lhs_type, rhs_type) >> cc_file
 
 
           close (cc_file);
--- a/liboctave/mx-inlines.cc
+++ b/liboctave/mx-inlines.cc
@@ -34,208 +34,270 @@
 #include "oct-cmplx.h"
 #include "oct-locbuf.h"
 #include "oct-inttypes.h"
+#include "Array-util.h"
+
+// Provides some commonly repeated, basic loop templates.
 
 template <class R, class S>
-inline void
-mx_inline_fill_vs (R *r, size_t n, S s)
-{
-  for (size_t i = 0; i < n; i++)
-    r[i] = s;
+inline void mx_inline_fill (size_t n, R *r, S s)
+{ for (size_t i = 0; i < n; i++) r[i] = s; }
+
+#define DEFMXUNOP(F, OP) \
+template <class R, class X> \
+inline void F (size_t n, R *r, const X *x) \
+{ for (size_t i = 0; i < n; i++) r[i] = OP x[i]; }
+
+DEFMXUNOP (mx_inline_uminus, -)
+DEFMXUNOP (mx_inline_not, !)
+
+#define DEFMXUNBOOLOP(F, OP) \
+template <class X> \
+inline void F (size_t n, bool *r, const X *x) \
+{ const X zero = X(); for (size_t i = 0; i < n; i++) r[i] = x[i] OP zero; }
+
+DEFMXUNBOOLOP (mx_inline_iszero, ==)
+DEFMXUNBOOLOP (mx_inline_notzero, !=)
+
+#define DEFMXBINOP(F, OP) \
+template <class R, class X, class Y> \
+inline void F (size_t n, R *r, const X *x, const Y *y) \
+{ for (size_t i = 0; i < n; i++) r[i] = x[i] OP y[i]; } \
+template <class R, class X, class Y> \
+inline void F (size_t n, R *r, const X *x, Y y) \
+{ for (size_t i = 0; i < n; i++) r[i] = x[i] OP y; } \
+template <class R, class X, class Y> \
+inline void F (size_t n, R *r, X x, const Y *y) \
+{ for (size_t i = 0; i < n; i++) r[i] = x OP y[i]; }
+
+DEFMXBINOP (mx_inline_add, +)
+DEFMXBINOP (mx_inline_sub, -)
+DEFMXBINOP (mx_inline_mul, *)
+DEFMXBINOP (mx_inline_div, /)
+
+#define DEFMXBINOPEQ(F, OP) \
+template <class R, class X> \
+inline void F (size_t n, R *r, const X *x) \
+{ for (size_t i = 0; i < n; i++) r[i] OP x[i]; } \
+template <class R, class X> \
+inline void F (size_t n, R *r, X x) \
+{ for (size_t i = 0; i < n; i++) r[i] OP x; }
+
+DEFMXBINOPEQ (mx_inline_add2, +=)
+DEFMXBINOPEQ (mx_inline_sub2, -=)
+DEFMXBINOPEQ (mx_inline_mul2, *=)
+DEFMXBINOPEQ (mx_inline_div2, /=)
+
+#define DEFMXCMPOP(F, OP) \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, const X *x, const Y *y) \
+{ for (size_t i = 0; i < n; i++) r[i] = x[i] OP y[i]; } \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, const X *x, Y y) \
+{ for (size_t i = 0; i < n; i++) r[i] = x[i] OP y; } \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, X x, const Y *y) \
+{ for (size_t i = 0; i < n; i++) r[i] = x OP y[i]; }
+
+DEFMXCMPOP (mx_inline_lt, <)
+DEFMXCMPOP (mx_inline_le, <=)
+DEFMXCMPOP (mx_inline_gt, >)
+DEFMXCMPOP (mx_inline_ge, >=)
+DEFMXCMPOP (mx_inline_eq, ==)
+DEFMXCMPOP (mx_inline_ne, !=)
+
+// For compatibility with certain loserware, cmp ops on complex nums only
+// compare real parts, although "sort" defines ordering on complex numbers!
+
+#define DEFCMPLXCMOP(F, OP) \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, const std::complex<X> *x, const Y *y) \
+{ for (size_t i = 0; i < n; i++) r[i] = real (x[i]) OP real (y[i]); } \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, const std::complex<X> *x, Y y) \
+{ for (size_t i = 0; i < n; i++) r[i] = real (x[i]) OP y; } \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, X x, const std::complex<Y> *y) \
+{ for (size_t i = 0; i < n; i++) r[i] = x OP real (y[i]); }
+
+#define DEFMXBOOLOP(F, EQ1, OP, EQ2) \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, const X *x, const Y *y) \
+{ \
+  const X xzero = X(); \
+  const Y yzero = Y(); \
+  for (size_t i = 0; i < n; i++) \
+    r[i] = (x[i] EQ1 xzero) OP (y[i] EQ2 yzero); \
+} \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, const X *x, Y y) \
+{ \
+  const X xzero = X(); \
+  const bool yy = y EQ2 Y(); \
+  for (size_t i = 0; i < n; i++) r[i] = (x[i] EQ1 xzero) OP yy; \
+} \
+template <class X, class Y> \
+inline void F (size_t n, bool *r, X x, const Y *y) \
+{ \
+  const bool xx = x EQ1 X(); \
+  const Y yzero = Y(); \
+  for (size_t i = 0; i < n; i++) r[i] = xx OP (y[i] EQ2 yzero); \
+}
+
+DEFMXBOOLOP (mx_inline_and, !=, &, !=)
+DEFMXBOOLOP (mx_inline_or, !=, |, !=)
+DEFMXBOOLOP (mx_inline_not_and, ==, &, !=)
+DEFMXBOOLOP (mx_inline_not_or, ==, |, !=)
+DEFMXBOOLOP (mx_inline_and_not, !=, &, ==)
+DEFMXBOOLOP (mx_inline_or_not, !=, |, ==)
+
+template <class T> 
+inline bool 
+mx_inline_any_nan (size_t, const T*) { return false; }
+
+#define DEFMXANYNAN(T) \
+inline bool \
+mx_inline_any_nan (size_t n, const T* t) \
+{ \
+  for (size_t i = 0; i < n; i++) \
+    if (xisnan (t[i])) return true; \
+  return false; \
 }
 
-#define VS_OP_FCN(F, OP) \
-  template <class R, class V, class S> \
-  inline void \
-  F ## _vs (R *r, const V *v, size_t n, S s) \
-  { \
-    for (size_t i = 0; i < n; i++) \
-      r[i] = v[i] OP s; \
-  }
+DEFMXANYNAN(double)
+DEFMXANYNAN(float)
+DEFMXANYNAN(Complex)
+DEFMXANYNAN(FloatComplex)
 
-VS_OP_FCN (mx_inline_add,      +)
-VS_OP_FCN (mx_inline_subtract, -)
-VS_OP_FCN (mx_inline_multiply, *)
-VS_OP_FCN (mx_inline_divide,   /)
+// Arbitrary unary/binary function mappers. Note the function reference is a
+// template parameter!
+template <class R, class X, R F(X)>
+void mx_inline_fun (size_t n, R *r, const X *x)
+{ for (size_t i = 0; i < n; i++) r[i] = F(x[i]); }
 
-#define VS_OP(F, OP, R, V, S) \
-  static inline R * \
-  F (const V *v, size_t n, S s) \
-  { \
-    R *r = 0; \
-    if (n > 0) \
-      { \
-	r = new R [n]; \
-	F ## _vs (r, v, n, s); \
-      } \
-    return r; \
-  }
+template <class R, class X, R F(const X&)>
+void mx_inline_fun (size_t n, R *r, const X *x)
+{ for (size_t i = 0; i < n; i++) r[i] = F(x[i]); }
 
-#define VS_OPS(R, V, S) \
-  VS_OP (mx_inline_add,      +, R, V, S) \
-  VS_OP (mx_inline_subtract, -, R, V, S) \
-  VS_OP (mx_inline_multiply, *, R, V, S) \
-  VS_OP (mx_inline_divide,   /, R, V, S)
+template <class R, class X, class Y, R F(X, Y)>
+void mx_inline_fun (size_t n, R *r, const X *x, const Y *y)
+{ for (size_t i = 0; i < n; i++) r[i] = F(x[i], y[i]); }
 
-VS_OPS (double,  double,  double)
-VS_OPS (Complex, double,  Complex)
-VS_OPS (Complex, Complex, double)
-VS_OPS (Complex, Complex, Complex)
-
-VS_OPS (float,  float,  float)
-VS_OPS (FloatComplex, float,  FloatComplex)
-VS_OPS (FloatComplex, FloatComplex, float)
-VS_OPS (FloatComplex, FloatComplex, FloatComplex)
+template <class R, class X, class Y, R F(X, Y)>
+void mx_inline_fun (size_t n, R *r, X x, const Y *y)
+{ for (size_t i = 0; i < n; i++) r[i] = F(x, y[i]); }
 
-#define SV_OP_FCN(F, OP) \
-  template <class R, class S, class V> \
-  inline void \
-  F ## _sv (R *r, S s, const V *v, size_t n) \
-  { \
-    for (size_t i = 0; i < n; i++) \
-      r[i] = s OP v[i]; \
-  } \
+template <class R, class X, class Y, R F(X, Y)>
+void mx_inline_fun (size_t n, R *r, const X *x, Y y)
+{ for (size_t i = 0; i < n; i++) r[i] = F(x[i], y); }
 
-SV_OP_FCN (mx_inline_add,      +)
-SV_OP_FCN (mx_inline_subtract, -)
-SV_OP_FCN (mx_inline_multiply, *)
-SV_OP_FCN (mx_inline_divide,   /)
+template <class R, class X, class Y, R F(const X&, const Y&)>
+void mx_inline_fun (size_t n, R *r, const X *x, const Y *y)
+{ for (size_t i = 0; i < n; i++) r[i] = F(x[i], y[i]); }
+
+template <class R, class X, class Y, R F(const X&, const Y&)>
+void mx_inline_fun (size_t n, R *r, X x, const Y *y)
+{ for (size_t i = 0; i < n; i++) r[i] = F(x, y[i]); }
 
-#define SV_OP(F, OP, R, S, V) \
-  static inline R * \
-  F (S s, const V *v, size_t n) \
-  { \
-    R *r = 0; \
-    if (n > 0) \
-      { \
-	r = new R [n]; \
-        F ## _sv (r, s, v, n); \
-      } \
-    return r; \
-  }
+template <class R, class X, class Y, R F(const X&, const Y&)>
+void mx_inline_fun (size_t n, R *r, const X *x, Y y)
+{ for (size_t i = 0; i < n; i++) r[i] = F(x[i], y); }
 
-#define SV_OPS(R, S, V) \
-  SV_OP (mx_inline_add,      +, R, S, V) \
-  SV_OP (mx_inline_subtract, -, R, S, V) \
-  SV_OP (mx_inline_multiply, *, R, S, V) \
-  SV_OP (mx_inline_divide,   /, R, S, V)
+// Appliers. Since these call the operation just once, we pass it as
+// a pointer, to allow the compiler reduce number of instances.
 
-SV_OPS (double,  double,  double)
-SV_OPS (Complex, double,  Complex)
-SV_OPS (Complex, Complex, double)
-SV_OPS (Complex, Complex, Complex)
-
-SV_OPS (float,  float,  float)
-SV_OPS (FloatComplex, float,  FloatComplex)
-SV_OPS (FloatComplex, FloatComplex, float)
-SV_OPS (FloatComplex, FloatComplex, FloatComplex)
-
-#define VV_OP_FCN(F, OP) \
-  template <class R, class T1, class T2> \
-  inline void \
-  F ## _vv (R *r, const T1 *v1, const T2 *v2, size_t n) \
-  { \
-    for (size_t i = 0; i < n; i++) \
-      r[i] = v1[i] OP v2[i]; \
-  } \
+template <class RNDA, class XNDA>
+inline RNDA 
+do_mx_unary_op (const XNDA& x,
+                void (*op) (size_t, typename RNDA::element_type *,
+                            const typename XNDA::element_type *))
+{
+  RNDA r (x.dims ());
+  op (r.nelem (), r.fortran_vec (), x.data ());
+  return r;
+}
 
-VV_OP_FCN (mx_inline_add,      +)
-VV_OP_FCN (mx_inline_subtract, -)
-VV_OP_FCN (mx_inline_multiply, *)
-VV_OP_FCN (mx_inline_divide,   /)
-
-#define VV_OP(F, OP, R, T1, T2) \
-  static inline R * \
-  F (const T1 *v1, const T2 *v2, size_t n) \
-  { \
-    R *r = 0; \
-    if (n > 0) \
-      { \
-	r = new R [n]; \
-	F ## _vv (r, v1, v2, n); \
-      } \
-    return r; \
-  }
+template <class RNDA, class XNDA, class YNDA>
+inline RNDA 
+do_mm_binary_op (const XNDA& x, const YNDA& y,
+                 void (*op) (size_t, typename RNDA::element_type *,
+                             const typename XNDA::element_type *,
+                             const typename YNDA::element_type *),
+                 const char *opname)
+{
+  dim_vector dx = x.dims (), dy = y.dims ();
+  if (dx == dy)
+    {
+      RNDA r (dx);
+      op (r.nelem (), r.fortran_vec (), x.data (), y.data ());
+      return r;
+    }
+  else
+    {
+      gripe_nonconformant (opname, dx, dy);
+      return RNDA ();
+    }
+}
 
-#define VV_OPS(R, T1, T2) \
-  VV_OP (mx_inline_add,      +, R, T1, T2) \
-  VV_OP (mx_inline_subtract, -, R, T1, T2) \
-  VV_OP (mx_inline_multiply, *, R, T1, T2) \
-  VV_OP (mx_inline_divide,   /, R, T1, T2)
-
-VV_OPS (double,  double,  double)
-VV_OPS (Complex, double,  Complex)
-VV_OPS (Complex, Complex, double)
-VV_OPS (Complex, Complex, Complex)
-
-VV_OPS (float,  float,  float)
-VV_OPS (FloatComplex, float,  FloatComplex)
-VV_OPS (FloatComplex, FloatComplex, float)
-VV_OPS (FloatComplex, FloatComplex, FloatComplex)
-
-#define VS_OP2(F, OP, V, S) \
-  static inline V * \
-  F (V *v, size_t n, S s) \
-  { \
-    for (size_t i = 0; i < n; i++) \
-      v[i] OP s; \
-    return v; \
-  }
+template <class RNDA, class XNDA, class YS>
+inline RNDA 
+do_ms_binary_op (const XNDA& x, const YS& y,
+                 void (*op) (size_t, typename RNDA::element_type *,
+                             const typename XNDA::element_type *, YS))
+{
+  RNDA r (x.dims ());
+  op (r.nelem (), r.fortran_vec (), x.data (), y);
+  return r;
+}
 
-#define VS_OP2S(V, S) \
-  VS_OP2 (mx_inline_add2,      +=, V, S) \
-  VS_OP2 (mx_inline_subtract2, -=, V, S) \
-  VS_OP2 (mx_inline_multiply2, *=, V, S) \
-  VS_OP2 (mx_inline_divide2,   /=, V, S) \
-  VS_OP2 (mx_inline_copy,       =, V, S)
-
-VS_OP2S (double,  double)
-VS_OP2S (Complex, double)
-VS_OP2S (Complex, Complex)
-
-VS_OP2S (float,  float)
-VS_OP2S (FloatComplex, float)
-VS_OP2S (FloatComplex, FloatComplex)
-
-#define VV_OP2(F, OP, T1, T2) \
-  static inline T1 * \
-  F (T1 *v1, const T2 *v2, size_t n) \
-  { \
-    for (size_t i = 0; i < n; i++) \
-      v1[i] OP v2[i]; \
-    return v1; \
-  }
+template <class RNDA, class XS, class YNDA>
+inline RNDA 
+do_sm_binary_op (const XS& x, const YNDA& y,
+                 void (*op) (size_t, typename RNDA::element_type *, XS,
+                             const typename YNDA::element_type *))
+{
+  RNDA r (y.dims ());
+  op (r.nelem (), r.fortran_vec (), x, y.data ());
+  return r;
+}
 
-#define VV_OP2S(T1, T2) \
-  VV_OP2 (mx_inline_add2,      +=, T1, T2) \
-  VV_OP2 (mx_inline_subtract2, -=, T1, T2) \
-  VV_OP2 (mx_inline_multiply2, *=, T1, T2) \
-  VV_OP2 (mx_inline_divide2,   /=, T1, T2) \
-  VV_OP2 (mx_inline_copy,       =, T1, T2)
-
-VV_OP2S (double,  double)
-VV_OP2S (Complex, double)
-VV_OP2S (Complex, Complex)
-
-VV_OP2S (float,  float)
-VV_OP2S (FloatComplex, float)
-VV_OP2S (FloatComplex, FloatComplex)
+template <class RNDA, class XNDA>
+inline RNDA& 
+do_mm_inplace_op (RNDA& r, const XNDA& x,
+                  void (*op) (size_t, typename RNDA::element_type *,
+                              const typename XNDA::element_type *),
+                  const char *opname)
+{
+  dim_vector dr = r.dims (), dx = x.dims ();
+  if (dr == dx)
+    {
+      op (r.nelem (), r.fortran_vec (), x.data ());
+      return r;
+    }
+  else
+    {
+      gripe_nonconformant (opname, dr, dx);
+      return RNDA ();
+    }
+}
 
-#define OP_EQ_FCN(T1, T2) \
-  static inline bool \
-  mx_inline_equal (const T1 *x, const T2 *y, size_t n) \
-  { \
-    for (size_t i = 0; i < n; i++) \
-      if (x[i] != y[i]) \
-	return false; \
-    return true; \
-  }
+template <class RNDA, class XS>
+inline RNDA& 
+do_ms_inplace_op (RNDA& r, const XS& x,
+                  void (*op) (size_t, typename RNDA::element_type *, XS))
+{
+  op (r.nelem (), r.fortran_vec (), x);
+  return r;
+}
 
-OP_EQ_FCN (bool,    bool)
-OP_EQ_FCN (char,    char)
-OP_EQ_FCN (double,  double)
-OP_EQ_FCN (Complex, Complex)
-OP_EQ_FCN (float,  float)
-OP_EQ_FCN (FloatComplex, FloatComplex)
+template <class T1, class T2>
+inline bool
+mx_inline_equal (size_t n, const T1 *x, const T2 *y)
+{
+  for (size_t i = 0; i < n; i++)
+    if (x[i] != y[i])
+      return false;
+  return true;
+}
 
 #define OP_DUP_FCN(OP, F, R, T) \
   static inline R * \
@@ -293,11 +355,6 @@
 inline T cabsq (const std::complex<T>& c) 
 { return c.real () * c.real () + c.imag () * c.imag (); }
 
-#define OP_RED_SUM(ac, el) ac += el
-#define OP_RED_PROD(ac, el) ac *= el
-#define OP_RED_SUMSQ(ac, el) ac += el*el
-#define OP_RED_SUMSQC(ac, el) ac += cabsq (el)
-
 // default. works for integers and bool.
 template <class T>
 inline bool xis_true (T x) { return x; }
@@ -319,6 +376,11 @@
 inline bool xis_true (const FloatComplex& x) { return ! xisnan (x) && x != 0.0f; }
 inline bool xis_false (const FloatComplex& x) { return x == 0.0f; }
 
+#define OP_RED_SUM(ac, el) ac += el
+#define OP_RED_PROD(ac, el) ac *= el
+#define OP_RED_SUMSQ(ac, el) ac += el*el
+#define OP_RED_SUMSQC(ac, el) ac += cabsq (el)
+
 // The following two implement a simple short-circuiting.
 #define OP_RED_ANYC(ac, el) if (xis_true (el)) { ac = true; break; } else continue
 #define OP_RED_ALLC(ac, el) if (xis_false (el)) { ac = false; break; } else continue
--- a/liboctave/mx-op-defs.h
+++ b/liboctave/mx-op-defs.h
@@ -28,6 +28,14 @@
 #include "mx-op-decl.h"
 #include "mx-inlines.cc"
 
+#define ND_LOGICAL_NAN_CHECK(X) \
+if (mx_inline_any_nan ((X).numel (), (X).data ())) \
+    gripe_nan_to_logical_conversion ()
+
+#define SC_LOGICAL_NAN_CHECK(X) \
+  if (xisnan(X)) \
+      gripe_nan_to_logical_conversion ()
+
 // vector by scalar operations.
 
 #define VS_BIN_OP(R, F, OP, V, S) \
@@ -108,22 +116,14 @@
   R \
   OP (const M& m, const S& s) \
   { \
-    octave_idx_type nr = m.rows (); \
-    octave_idx_type nc = m.cols (); \
- \
-    R r (nr, nc); \
- \
-    if (nr > 0 && nc > 0) \
-      F ## _vs (r.fortran_vec (), m.data (), nr * nc, s); \
- \
-    return r; \
+    return do_ms_binary_op<R, M, S> (m, s, F); \
   }
 
 #define MS_BIN_OPS(R, M, S) \
   MS_BIN_OP (R, operator +, M, S, mx_inline_add) \
-  MS_BIN_OP (R, operator -, M, S, mx_inline_subtract) \
-  MS_BIN_OP (R, operator *, M, S, mx_inline_multiply) \
-  MS_BIN_OP (R, operator /, M, S, mx_inline_divide)
+  MS_BIN_OP (R, operator -, M, S, mx_inline_sub) \
+  MS_BIN_OP (R, operator *, M, S, mx_inline_mul) \
+  MS_BIN_OP (R, operator /, M, S, mx_inline_div)
 
 #define MS_CMP_OP(F, OP, M, MC, S, SC) \
   boolMatrix \
@@ -154,45 +154,18 @@
   MS_CMP_OP (mx_el_eq, ==, M,   , S,   ) \
   MS_CMP_OP (mx_el_ne, !=, M,   , S,   )
 
-#define MS_BOOL_OP(F, OP, M, S, LHS_ZERO, RHS_ZERO) \
+#define MS_BOOL_OP(F, OP, M, S) \
   boolMatrix \
   F (const M& m, const S& s) \
   { \
-    boolMatrix r; \
- \
-    octave_idx_type nr = m.rows (); \
-    octave_idx_type nc = m.cols (); \
- \
-    if (nr != 0 && nc != 0) \
-      { \
-        r.resize (nr, nc); \
- \
-	if (xisnan (s)) \
-	  gripe_nan_to_logical_conversion (); \
-	else \
-	  { \
- \
-	    for (octave_idx_type j = 0; j < nc; j++) \
-	      for (octave_idx_type i = 0; i < nr; i++) \
-		if (xisnan (m.elem(i, j))) \
-		  { \
-		    gripe_nan_to_logical_conversion (); \
-		    return r; \
-		  } \
-		else \
-		  r.elem(i, j) = (m.elem(i, j) != LHS_ZERO) OP (s != RHS_ZERO); \
-	    } \
-      } \
- \
-    return r; \
+    ND_LOGICAL_NAN_CHECK (m); \
+    SC_LOGICAL_NAN_CHECK (s); \
+    return do_ms_binary_op<boolMatrix, M, S> (m, s, OP); \
   }
 
-#define MS_BOOL_OPS2(M, S, LHS_ZERO, RHS_ZERO) \
-  MS_BOOL_OP (mx_el_and, &&, M, S, LHS_ZERO, RHS_ZERO) \
-  MS_BOOL_OP (mx_el_or,  ||, M, S, LHS_ZERO, RHS_ZERO)
-
-#define MS_BOOL_OPS(M, S, ZERO) \
-  MS_BOOL_OPS2(M, S, ZERO, ZERO)
+#define MS_BOOL_OPS(M, S) \
+  MS_BOOL_OP (mx_el_and, mx_inline_and, M, S) \
+  MS_BOOL_OP (mx_el_or,  mx_inline_or,  M, S)
 
 // scalar by matrix operations.
 
@@ -200,22 +173,14 @@
   R \
   OP (const S& s, const M& m) \
   { \
-    octave_idx_type nr = m.rows (); \
-    octave_idx_type nc = m.cols (); \
- \
-    R r (nr, nc); \
- \
-    if (nr > 0 && nc > 0) \
-      F ## _sv (r.fortran_vec (), s, m.data (), nr * nc); \
- \
-    return r; \
+    return do_sm_binary_op<R, S, M> (s, m, F); \
   }
 
 #define SM_BIN_OPS(R, S, M) \
   SM_BIN_OP (R, operator +, S, M, mx_inline_add) \
-  SM_BIN_OP (R, operator -, S, M, mx_inline_subtract) \
-  SM_BIN_OP (R, operator *, S, M, mx_inline_multiply) \
-  SM_BIN_OP (R, operator /, S, M, mx_inline_divide)
+  SM_BIN_OP (R, operator -, S, M, mx_inline_sub) \
+  SM_BIN_OP (R, operator *, S, M, mx_inline_mul) \
+  SM_BIN_OP (R, operator /, S, M, mx_inline_div)
 
 #define SM_CMP_OP(F, OP, S, SC, M, MC) \
   boolMatrix \
@@ -246,44 +211,18 @@
   SM_CMP_OP (mx_el_eq, ==, S,   , M,   ) \
   SM_CMP_OP (mx_el_ne, !=, S,   , M,   )
 
-#define SM_BOOL_OP(F, OP, S, M, LHS_ZERO, RHS_ZERO) \
+#define SM_BOOL_OP(F, OP, S, M) \
   boolMatrix \
   F (const S& s, const M& m) \
   { \
-    boolMatrix r; \
- \
-    octave_idx_type nr = m.rows (); \
-    octave_idx_type nc = m.cols (); \
- \
-    if (nr != 0 && nc != 0) \
-      { \
-        r.resize (nr, nc); \
- \
-	if (xisnan (s)) \
-	  gripe_nan_to_logical_conversion (); \
-	else \
-	  { \
-	    for (octave_idx_type j = 0; j < nc; j++) \
-	      for (octave_idx_type i = 0; i < nr; i++) \
-		if (xisnan (m.elem(i, j))) \
-		  { \
-		    gripe_nan_to_logical_conversion (); \
-		    return r; \
-		  } \
-		else \
-		  r.elem(i, j) = (s != LHS_ZERO) OP (m.elem(i, j) != RHS_ZERO); \
-	  } \
-      } \
- \
-    return r; \
+    SC_LOGICAL_NAN_CHECK (s); \
+    ND_LOGICAL_NAN_CHECK (m); \
+    return do_sm_binary_op<boolMatrix, S, M> (s, m, OP); \
   }
 
-#define SM_BOOL_OPS2(S, M, LHS_ZERO, RHS_ZERO) \
-  SM_BOOL_OP (mx_el_and, &&, S, M, LHS_ZERO, RHS_ZERO) \
-  SM_BOOL_OP (mx_el_or,  ||, S, M, LHS_ZERO, RHS_ZERO)
-
-#define SM_BOOL_OPS(S, M, ZERO) \
-  SM_BOOL_OPS2(S, M, ZERO, ZERO)
+#define SM_BOOL_OPS(S, M) \
+  SM_BOOL_OP (mx_el_and, mx_inline_and, S, M) \
+  SM_BOOL_OP (mx_el_or,  mx_inline_or,  S, M)
 
 // matrix by matrix operations.
 
@@ -291,32 +230,14 @@
   R \
   OP (const M1& m1, const M2& m2) \
   { \
-    R r; \
- \
-    octave_idx_type m1_nr = m1.rows (); \
-    octave_idx_type m1_nc = m1.cols (); \
- \
-    octave_idx_type m2_nr = m2.rows (); \
-    octave_idx_type m2_nc = m2.cols (); \
- \
-    if (m1_nr != m2_nr || m1_nc != m2_nc) \
-      gripe_nonconformant (#OP, m1_nr, m1_nc, m2_nr, m2_nc); \
-    else \
-      { \
-	r.resize (m1_nr, m1_nc); \
- \
-	if (m1_nr > 0 && m1_nc > 0) \
-	  F ## _vv (r.fortran_vec (), m1.data (), m2.data (), m1_nr * m1_nc); \
-      } \
- \
-    return r; \
+    return do_mm_binary_op<R, M1, M2> (m1, m2, F, #OP); \
   }
 
 #define MM_BIN_OPS(R, M1, M2) \
   MM_BIN_OP (R, operator +, M1, M2, mx_inline_add) \
-  MM_BIN_OP (R, operator -, M1, M2, mx_inline_subtract) \
-  MM_BIN_OP (R, product,    M1, M2, mx_inline_multiply) \
-  MM_BIN_OP (R, quotient,   M1, M2, mx_inline_divide)
+  MM_BIN_OP (R, operator -, M1, M2, mx_inline_sub) \
+  MM_BIN_OP (R, product,    M1, M2, mx_inline_mul) \
+  MM_BIN_OP (R, quotient,   M1, M2, mx_inline_div)
 
 #define MM_CMP_OP(F, OP, M1, C1, M2, C2) \
   boolMatrix \
@@ -352,51 +273,18 @@
   MM_CMP_OP (mx_el_eq, ==, M1,   , M2,   ) \
   MM_CMP_OP (mx_el_ne, !=, M1,   , M2,   )
 
-#define MM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \
+#define MM_BOOL_OP(F, OP, M1, M2) \
   boolMatrix \
   F (const M1& m1, const M2& m2) \
   { \
-    boolMatrix r; \
- \
-    octave_idx_type m1_nr = m1.rows (); \
-    octave_idx_type m1_nc = m1.cols (); \
- \
-    octave_idx_type m2_nr = m2.rows (); \
-    octave_idx_type m2_nc = m2.cols (); \
- \
-    if (m1_nr == m2_nr && m1_nc == m2_nc) \
-      { \
-	if (m1_nr != 0 || m1_nc != 0) \
-	  { \
-	    r.resize (m1_nr, m1_nc); \
- \
-	    for (octave_idx_type j = 0; j < m1_nc; j++) \
-	      for (octave_idx_type i = 0; i < m1_nr; i++) \
-		if (xisnan (m1.elem(i, j)) || xisnan (m2.elem(i, j))) \
-		  { \
-		    gripe_nan_to_logical_conversion (); \
-		    return r; \
-		  } \
-		else \
-		  r.elem(i, j) = (m1.elem(i, j) != LHS_ZERO) \
-		    OP (m2.elem(i, j) != RHS_ZERO); \
-	  } \
-      } \
-    else \
-      { \
-	if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \
-	  gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
-      } \
- \
-    return r; \
+    ND_LOGICAL_NAN_CHECK(m1); \
+    ND_LOGICAL_NAN_CHECK(m2); \
+    return do_mm_binary_op<boolMatrix, M1, M2> (m1, m2, OP, #F); \
   }
 
-#define MM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO) \
-  MM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO) \
-  MM_BOOL_OP (mx_el_or,  ||, M1, M2, LHS_ZERO, RHS_ZERO)
-
-#define MM_BOOL_OPS(M1, M2, ZERO) \
-  MM_BOOL_OPS2(M1, M2, ZERO, ZERO)
+#define MM_BOOL_OPS(M1, M2) \
+  MM_BOOL_OP (mx_el_and, mx_inline_and, M1, M2) \
+  MM_BOOL_OP (mx_el_or,  mx_inline_or,  M1, M2)
 
 // N-d matrix by scalar operations.
 
@@ -404,21 +292,14 @@
   R \
   OP (const ND& m, const S& s) \
   { \
-    R r (m.dims ()); \
- \
-    octave_idx_type len = m.length (); \
- \
-    if (len > 0) \
-      F ## _vs (r.fortran_vec (), m.data (), len, s); \
- \
-    return r; \
+    return do_ms_binary_op<R, ND, S> (m, s, F); \
   }
 
 #define NDS_BIN_OPS(R, ND, S) \
   NDS_BIN_OP (R, operator +, ND, S, mx_inline_add) \
-  NDS_BIN_OP (R, operator -, ND, S, mx_inline_subtract) \
-  NDS_BIN_OP (R, operator *, ND, S, mx_inline_multiply) \
-  NDS_BIN_OP (R, operator /, ND, S, mx_inline_divide)
+  NDS_BIN_OP (R, operator -, ND, S, mx_inline_sub) \
+  NDS_BIN_OP (R, operator *, ND, S, mx_inline_mul) \
+  NDS_BIN_OP (R, operator /, ND, S, mx_inline_div)
 
 #define NDS_CMP_OP(F, OP, ND, NDC, S, SC) \
   boolNDArray \
@@ -496,42 +377,22 @@
   NDS_CMP_OP2 (mx_el_eq, ==, ND,    , S,   , SPEC1, SPEC2) \
   NDS_CMP_OP2 (mx_el_ne, !=, ND,    , S,   , SPEC1, SPEC2)
 
-#define NDS_BOOL_OP(F, EQ, OP, ND, S, LHS_ZERO, RHS_ZERO) \
+#define NDS_BOOL_OP(F, OP, ND, S) \
   boolNDArray \
   F (const ND& m, const S& s) \
   { \
-    boolNDArray r (m.dims ()); \
- \
-    octave_idx_type len = m.length (); \
- \
-    if (len > 0) \
-      { \
-	if (xisnan (s)) \
-	  gripe_nan_to_logical_conversion (); \
-	else \
-	  { \
-	    for (octave_idx_type i = 0; i < len; i++) \
-	      if (xisnan (m.elem(i))) \
-		{ \
-		  gripe_nan_to_logical_conversion (); \
-		  return r; \
-		} \
-	      else \
-		r.xelem(i) = (m.elem(i) EQ LHS_ZERO) OP (s != RHS_ZERO); \
-	  } \
-      } \
- \
-    return r; \
+    ND_LOGICAL_NAN_CHECK (m); \
+    SC_LOGICAL_NAN_CHECK (s); \
+    return do_ms_binary_op<boolNDArray, ND, S> (m, s, OP); \
   }
 
-#define NDS_BOOL_OPS2(ND, S, LHS_ZERO, RHS_ZERO) \
-  NDS_BOOL_OP (mx_el_and, !=, &&, ND, S, LHS_ZERO, RHS_ZERO) \
-  NDS_BOOL_OP (mx_el_or,  !=, ||, ND, S, LHS_ZERO, RHS_ZERO) \
-  NDS_BOOL_OP (mx_el_not_and, ==, &&, ND, S, LHS_ZERO, RHS_ZERO) \
-  NDS_BOOL_OP (mx_el_not_or,  ==, ||, ND, S, LHS_ZERO, RHS_ZERO)
-
-#define NDS_BOOL_OPS(ND, S, ZERO) \
-  NDS_BOOL_OPS2(ND, S, ZERO, ZERO)
+#define NDS_BOOL_OPS(ND, S) \
+  NDS_BOOL_OP (mx_el_and,     mx_inline_and,     ND, S) \
+  NDS_BOOL_OP (mx_el_or,      mx_inline_or,      ND, S) \
+  NDS_BOOL_OP (mx_el_not_and, mx_inline_not_and, ND, S) \
+  NDS_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  ND, S) \
+  NDS_BOOL_OP (mx_el_and_not, mx_inline_and_not, ND, S) \
+  NDS_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  ND, S)
 
 // scalar by N-d matrix operations.
 
@@ -539,21 +400,14 @@
   R \
   OP (const S& s, const ND& m) \
   { \
-    R r (m.dims ()); \
- \
-    octave_idx_type len = m.length (); \
- \
-    if (len > 0) \
-      F ## _sv (r.fortran_vec (), s, m.data (), len); \
- \
-    return r; \
+    return do_sm_binary_op<R, S, ND> (s, m, F); \
   }
 
 #define SND_BIN_OPS(R, S, ND) \
   SND_BIN_OP (R, operator +, S, ND, mx_inline_add) \
-  SND_BIN_OP (R, operator -, S, ND, mx_inline_subtract) \
-  SND_BIN_OP (R, operator *, S, ND, mx_inline_multiply) \
-  SND_BIN_OP (R, operator /, S, ND, mx_inline_divide)
+  SND_BIN_OP (R, operator -, S, ND, mx_inline_sub) \
+  SND_BIN_OP (R, operator *, S, ND, mx_inline_mul) \
+  SND_BIN_OP (R, operator /, S, ND, mx_inline_div)
 
 #define SND_CMP_OP(F, OP, S, SC, ND, NDC) \
   boolNDArray \
@@ -629,42 +483,22 @@
   SND_CMP_OP2 (mx_el_eq, ==, S,   , ND,    , SPEC1, SPEC2) \
   SND_CMP_OP2 (mx_el_ne, !=, S,   , ND,    , SPEC1, SPEC2)
 
-#define SND_BOOL_OP(F, OP, EQ, S, ND, LHS_ZERO, RHS_ZERO) \
+#define SND_BOOL_OP(F, OP, S, ND) \
   boolNDArray \
   F (const S& s, const ND& m) \
   { \
-    boolNDArray r (m.dims ()); \
- \
-    octave_idx_type len = m.length (); \
- \
-    if (len > 0) \
-      { \
-	if (xisnan (s)) \
-	  gripe_nan_to_logical_conversion (); \
-	else \
-	  { \
-	    for (octave_idx_type i = 0; i < len; i++) \
-	      if (xisnan (m.elem(i))) \
-		{ \
-	          gripe_nan_to_logical_conversion (); \
-		  return r; \
-		} \
-	      else \
-		r.xelem(i) = (s != LHS_ZERO) OP (m.elem(i) EQ RHS_ZERO); \
-	    } \
-      } \
- \
-    return r; \
+    SC_LOGICAL_NAN_CHECK (s); \
+    ND_LOGICAL_NAN_CHECK (m); \
+    return do_sm_binary_op<boolNDArray, S, ND> (s, m, OP); \
   }
 
-#define SND_BOOL_OPS2(S, ND, LHS_ZERO, RHS_ZERO) \
-  SND_BOOL_OP (mx_el_and, &&, !=, S, ND, LHS_ZERO, RHS_ZERO) \
-  SND_BOOL_OP (mx_el_or,  ||, !=, S, ND, LHS_ZERO, RHS_ZERO) \
-  SND_BOOL_OP (mx_el_and_not, &&, ==, S, ND, LHS_ZERO, RHS_ZERO) \
-  SND_BOOL_OP (mx_el_or_not,  ||, ==, S, ND, LHS_ZERO, RHS_ZERO)
-
-#define SND_BOOL_OPS(S, ND, ZERO) \
-  SND_BOOL_OPS2(S, ND, ZERO, ZERO)
+#define SND_BOOL_OPS(S, ND) \
+  SND_BOOL_OP (mx_el_and,     mx_inline_and,     S, ND) \
+  SND_BOOL_OP (mx_el_or,      mx_inline_or,      S, ND) \
+  SND_BOOL_OP (mx_el_not_and, mx_inline_not_and, S, ND) \
+  SND_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  S, ND) \
+  SND_BOOL_OP (mx_el_and_not, mx_inline_and_not, S, ND) \
+  SND_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  S, ND)
 
 // N-d matrix by N-d matrix operations.
 
@@ -672,31 +506,14 @@
   R \
   OP (const ND1& m1, const ND2& m2) \
   { \
-    R r; \
- \
-    dim_vector m1_dims = m1.dims (); \
-    dim_vector m2_dims = m2.dims (); \
- \
-    if (m1_dims != m2_dims) \
-      gripe_nonconformant (#OP, m1_dims, m2_dims); \
-    else \
-      { \
-	r = R (m1_dims); \
- \
-	octave_idx_type len = m1.length (); \
- \
-	if (len > 0) \
-	  F ## _vv (r.fortran_vec (), m1.data (), m2.data (), len); \
-      } \
- \
-    return r; \
+    return do_mm_binary_op<R, ND1, ND2> (m1, m2, F, #OP); \
   }
 
 #define NDND_BIN_OPS(R, ND1, ND2) \
   NDND_BIN_OP (R, operator +, ND1, ND2, mx_inline_add) \
-  NDND_BIN_OP (R, operator -, ND1, ND2, mx_inline_subtract) \
-  NDND_BIN_OP (R, product,    ND1, ND2, mx_inline_multiply) \
-  NDND_BIN_OP (R, quotient,   ND1, ND2, mx_inline_divide)
+  NDND_BIN_OP (R, operator -, ND1, ND2, mx_inline_sub) \
+  NDND_BIN_OP (R, product,    ND1, ND2, mx_inline_mul) \
+  NDND_BIN_OP (R, quotient,   ND1, ND2, mx_inline_div)
 
 #define NDND_CMP_OP(F, OP, ND1, C1, ND2, C2) \
   boolNDArray \
@@ -728,47 +545,22 @@
   NDND_CMP_OP (mx_el_eq, ==, ND1,   , ND2,   ) \
   NDND_CMP_OP (mx_el_ne, !=, ND1,   , ND2,   )
 
-#define NDND_BOOL_OP(F, EQ1, OP, EQ2, ND1, ND2, LHS_ZERO, RHS_ZERO) \
+#define NDND_BOOL_OP(F, OP, ND1, ND2) \
   boolNDArray \
   F (const ND1& m1, const ND2& m2) \
   { \
-    boolNDArray r; \
- \
-    dim_vector m1_dims = m1.dims (); \
-    dim_vector m2_dims = m2.dims (); \
- \
-    if (m1_dims == m2_dims) \
-      { \
-	if (! m1_dims.all_zero ()) \
-	  { \
-	    r = boolNDArray (m1_dims); \
- \
-	    for (octave_idx_type i = 0; i < m1.length (); i++) \
-	      if (xisnan (m1.elem(i)) || xisnan (m2.elem(i))) \
-		{ \
-	          gripe_nan_to_logical_conversion (); \
-		  return r; \
-		} \
-	      else \
-		r.xelem(i) = (m1.elem(i) EQ1 LHS_ZERO) OP (m2.elem(i) EQ2 RHS_ZERO); \
-	  } \
-      } \
-    else \
-      gripe_nonconformant (#F, m1_dims, m2_dims); \
- \
-    return r; \
+    ND_LOGICAL_NAN_CHECK(m1); \
+    ND_LOGICAL_NAN_CHECK(m2); \
+    return do_mm_binary_op<boolNDArray, ND1, ND2> (m1, m2, OP, #F); \
   }
 
-#define NDND_BOOL_OPS2(ND1, ND2, LHS_ZERO, RHS_ZERO) \
-  NDND_BOOL_OP (mx_el_and, !=, &&, !=, ND1, ND2, LHS_ZERO, RHS_ZERO) \
-  NDND_BOOL_OP (mx_el_or,  !=, ||, !=, ND1, ND2, LHS_ZERO, RHS_ZERO) \
-  NDND_BOOL_OP (mx_el_and_not, != , &&, ==, ND1, ND2, LHS_ZERO, RHS_ZERO) \
-  NDND_BOOL_OP (mx_el_or_not, !=, ||, ==, ND1, ND2, LHS_ZERO, RHS_ZERO) \
-  NDND_BOOL_OP (mx_el_not_and, ==, &&, !=, ND1, ND2, LHS_ZERO, RHS_ZERO) \
-  NDND_BOOL_OP (mx_el_not_or,  ==, ||, !=, ND1, ND2, LHS_ZERO, RHS_ZERO)
-
-#define NDND_BOOL_OPS(ND1, ND2, ZERO) \
-  NDND_BOOL_OPS2(ND1, ND2, ZERO, ZERO)
+#define NDND_BOOL_OPS(ND1, ND2) \
+  NDND_BOOL_OP (mx_el_and,     mx_inline_and,     ND1, ND2) \
+  NDND_BOOL_OP (mx_el_or,      mx_inline_or,      ND1, ND2) \
+  NDND_BOOL_OP (mx_el_not_and, mx_inline_not_and, ND1, ND2) \
+  NDND_BOOL_OP (mx_el_not_or,  mx_inline_not_or,  ND1, ND2) \
+  NDND_BOOL_OP (mx_el_and_not, mx_inline_and_not, ND1, ND2) \
+  NDND_BOOL_OP (mx_el_or_not,  mx_inline_or_not,  ND1, ND2)
 
 // scalar by diagonal matrix operations.
 
@@ -870,10 +662,10 @@
       octave_idx_type len = dm.length (); \
       for (octave_idx_type i = 0; i < len; i++) \
         { \
-          mx_inline_multiply_vs (rd, md, m_nr, dd[i]); \
+          mx_inline_mul (m_nr, rd, md, dd[i]); \
           rd += m_nr; md += m_nr; \
         } \
-      mx_inline_fill_vs (rd, m_nr * (dm_nc - len), R_ZERO); \
+      mx_inline_fill (m_nr * (dm_nc - len), rd, R_ZERO); \
     } \
  \
   return r; \
@@ -942,9 +734,9 @@
       octave_idx_type len = dm.length (); \
       for (octave_idx_type i = 0; i < m_nc; i++) \
         { \
-          mx_inline_multiply_vv (rd, md, dd, len); \
+          mx_inline_mul (len, rd, md, dd); \
           rd += len; md += m_nr; \
-          mx_inline_fill_vs (rd, dm_nr - len, R_ZERO); \
+          mx_inline_fill (dm_nr - len, rd, R_ZERO); \
           rd += dm_nr - len; \
         } \
     } \
@@ -978,8 +770,7 @@
 	r.resize (dm1_nr, dm1_nc); \
  \
 	if (dm1_nr > 0 && dm1_nc > 0) \
-	  F ## _vv (r.fortran_vec (), dm1.data (), dm2.data (), \
-		    dm1.length ()); \
+	  F (dm1.length (), r.fortran_vec (), dm1.data (), dm2.data ()); \
       } \
  \
     return r; \
@@ -987,8 +778,8 @@
 
 #define DMDM_BIN_OPS(R, DM1, DM2) \
   DMDM_BIN_OP (R, operator +, DM1, DM2, mx_inline_add) \
-  DMDM_BIN_OP (R, operator -, DM1, DM2, mx_inline_subtract) \
-  DMDM_BIN_OP (R, product,    DM1, DM2, mx_inline_multiply)
+  DMDM_BIN_OP (R, operator -, DM1, DM2, mx_inline_sub) \
+  DMDM_BIN_OP (R, product,    DM1, DM2, mx_inline_mul)
 
 // scalar by N-d array min/max ops
 
--- a/liboctave/uint16NDArray.cc
+++ b/liboctave/uint16NDArray.cc
@@ -40,13 +40,13 @@
 operator >> (std::istream& is, intNDArray<octave_uint16>& a);
 
 NDS_CMP_OPS (uint16NDArray, , octave_uint16, )
-NDS_BOOL_OPS (uint16NDArray, octave_uint16, octave_uint16 (0))
+NDS_BOOL_OPS (uint16NDArray, octave_uint16)
 
 SND_CMP_OPS (octave_uint16, , uint16NDArray, )
-SND_BOOL_OPS (octave_uint16, uint16NDArray, octave_uint16 (0))
+SND_BOOL_OPS (octave_uint16, uint16NDArray)
 
 NDND_CMP_OPS (uint16NDArray, , uint16NDArray, )
-NDND_BOOL_OPS (uint16NDArray, uint16NDArray, octave_uint16 (0))
+NDND_BOOL_OPS (uint16NDArray, uint16NDArray)
 
 MINMAX_FCNS (uint16)
 
--- a/liboctave/uint32NDArray.cc
+++ b/liboctave/uint32NDArray.cc
@@ -40,13 +40,13 @@
 operator >> (std::istream& is, intNDArray<octave_uint32>& a);
 
 NDS_CMP_OPS (uint32NDArray, , octave_uint32, )
-NDS_BOOL_OPS (uint32NDArray, octave_uint32, octave_uint32 (0))
+NDS_BOOL_OPS (uint32NDArray, octave_uint32)
 
 SND_CMP_OPS (octave_uint32, , uint32NDArray, )
-SND_BOOL_OPS (octave_uint32, uint32NDArray, octave_uint32 (0))
+SND_BOOL_OPS (octave_uint32, uint32NDArray)
 
 NDND_CMP_OPS (uint32NDArray, , uint32NDArray, )
-NDND_BOOL_OPS (uint32NDArray, uint32NDArray, octave_uint32 (0))
+NDND_BOOL_OPS (uint32NDArray, uint32NDArray)
 
 MINMAX_FCNS (uint32)
 
--- a/liboctave/uint64NDArray.cc
+++ b/liboctave/uint64NDArray.cc
@@ -40,13 +40,13 @@
 operator >> (std::istream& is, intNDArray<octave_uint64>& a);
 
 NDS_CMP_OPS (uint64NDArray, , octave_uint64, )
-NDS_BOOL_OPS (uint64NDArray, octave_uint64, octave_uint64 (0))
+NDS_BOOL_OPS (uint64NDArray, octave_uint64)
 
 SND_CMP_OPS (octave_uint64, , uint64NDArray, )
-SND_BOOL_OPS (octave_uint64, uint64NDArray, octave_uint64 (0))
+SND_BOOL_OPS (octave_uint64, uint64NDArray)
 
 NDND_CMP_OPS (uint64NDArray, , uint64NDArray, )
-NDND_BOOL_OPS (uint64NDArray, uint64NDArray, octave_uint64 (0))
+NDND_BOOL_OPS (uint64NDArray, uint64NDArray)
 
 MINMAX_FCNS (uint64)
 
--- a/liboctave/uint8NDArray.cc
+++ b/liboctave/uint8NDArray.cc
@@ -40,13 +40,13 @@
 operator >> (std::istream& is, intNDArray<octave_uint8>& a);
 
 NDS_CMP_OPS (uint8NDArray, , octave_uint8, )
-NDS_BOOL_OPS (uint8NDArray, octave_uint8, octave_uint8 (0))
+NDS_BOOL_OPS (uint8NDArray, octave_uint8)
 
 SND_CMP_OPS (octave_uint8, , uint8NDArray, )
-SND_BOOL_OPS (octave_uint8, uint8NDArray, octave_uint8 (0))
+SND_BOOL_OPS (octave_uint8, uint8NDArray)
 
 NDND_CMP_OPS (uint8NDArray, , uint8NDArray, )
-NDND_BOOL_OPS (uint8NDArray, uint8NDArray, octave_uint8 (0))
+NDND_BOOL_OPS (uint8NDArray, uint8NDArray)
 
 MINMAX_FCNS (uint8)