changeset 8743:1bd918cfb6e2

reimplement any & all using the new reduction code
author Jaroslav Hajek <highegg@gmail.com>
date Sat, 14 Feb 2009 19:50:43 +0100
parents d2b06871afac
children 4142982c66c6
files liboctave/CMatrix.cc liboctave/CNDArray.cc liboctave/ChangeLog liboctave/boolMatrix.cc liboctave/boolNDArray.cc liboctave/dMatrix.cc liboctave/dNDArray.cc liboctave/fCMatrix.cc liboctave/fCNDArray.cc liboctave/fMatrix.cc liboctave/fNDArray.cc liboctave/intNDArray.cc liboctave/mx-inlines.cc
diffstat 13 files changed, 123 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/CMatrix.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/CMatrix.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -3252,13 +3252,13 @@
 boolMatrix
 ComplexMatrix::all (int dim) const
 {
-  MX_ALL_OP (dim);
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_all);
 }
 
 boolMatrix
 ComplexMatrix::any (int dim) const
 {
-  MX_ANY_OP (dim);
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_any);
 }
 
 ComplexMatrix
--- a/liboctave/CNDArray.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/CNDArray.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -622,18 +622,13 @@
 boolNDArray
 ComplexNDArray::all (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION
-    (MX_ND_ALL_EVAL (elem (iter_idx) == Complex (0, 0)), true);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_all);
 }
 
 boolNDArray
 ComplexNDArray::any (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION
-    (MX_ND_ANY_EVAL (elem (iter_idx) != Complex (0, 0)
-		     && ! (lo_ieee_isnan (std::real (elem (iter_idx)))
-			   || lo_ieee_isnan (std::imag (elem (iter_idx))))),
-		     false);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_any);
 }
 
 ComplexNDArray
--- a/liboctave/ChangeLog	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/ChangeLog	Sat Feb 14 19:50:43 2009 +0100
@@ -1,3 +1,38 @@
+2009-02-14  Jaroslav Hajek  <highegg@gmail.com>
+
+	* mx-inlines.cc (OP_RED_FCN, OP_RED_FCN2, OP_RED_FCNN, OP_CUM_FCN,
+	OP_CUM_FCN2, OP_CUM_FCNN): Include TRET parameter.
+	(OP_RED_ANYC, OP_RED_ANYR, OP_RED_ALLC, OP_RED_ALLR): New macros.
+	(is_true, is_false): New template functions.
+	(mx_inline_any, mx_inline_all): New template functions.
+
+	* dMatrix.cc (Matrix::any, Matrix::all): Use do_mx_red_op and
+	do_mx_cum_op.
+	* fMatrix.cc (FloatMatrix::any, FloatMatrix::all): Use do_mx_red_op
+	and do_mx_cum_op.
+	* CMatrix.cc (ComplexMatrix::any, ComplexMatrix::all): Use
+	do_mx_red_op and do_mx_cum_op.
+	* fCMatrix.cc (FloatComplexMatrix::any, FloatComplexMatrix::all): Use
+	do_mx_red_op and do_mx_cum_op.
+
+	* dNDArray.cc (NDArray::any, NDArray::all): Use do_mx_red_op and
+	do_mx_cum_op.
+	* fNDArray.cc (FloatNDArray::any, FloatNDArray::all): Use do_mx_red_op
+	and do_mx_cum_op.
+	* CNDArray.cc (ComplexNDArray::any, ComplexNDArray::all): Use
+	do_mx_red_op and do_mx_cum_op.
+	* fCNDArray.cc (FloatComplexNDArray::any, FloatComplexNDArray::all):
+	Use do_mx_red_op and do_mx_cum_op.
+
+	* intNDArray.cc (intNDArray::any, intNDArray::all): Use do_mx_red_op and
+	do_mx_cum_op.
+
+	* boolNDArray.cc (boolNDArray::any, boolNDArray::all): Use do_mx_red_op and
+	do_mx_cum_op.
+
+	* boolMatrix.cc (boolMatrix::any, boolMatrix::all): Use do_mx_red_op and
+	do_mx_cum_op.
+
 2009-02-14  Jaroslav Hajek  <highegg@gmail.com>
 
 	* intNDArray.cc: include mx-inlines.cc.
--- a/liboctave/boolMatrix.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/boolMatrix.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -89,13 +89,13 @@
 boolMatrix
 boolMatrix::all (int dim) const
 {
-  MX_ALL_OP (dim);
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_all);
 }
 
 boolMatrix
 boolMatrix::any (int dim) const
 {
-  MX_ANY_OP (dim);
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_any);
 }
 
 MM_CMP_OPS (boolMatrix, , boolMatrix, )
--- a/liboctave/boolNDArray.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/boolNDArray.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -48,13 +48,13 @@
 boolNDArray
 boolNDArray::all (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION (MX_ND_ALL_EVAL (MX_ND_ALL_EXPR), true);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_all);
 }
 
 boolNDArray
 boolNDArray::any (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION (MX_ND_ANY_EVAL (MX_ND_ANY_EXPR), false);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_any);
 }
 
 boolNDArray 
--- a/liboctave/dMatrix.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/dMatrix.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -2786,13 +2786,13 @@
 boolMatrix
 Matrix::all (int dim) const
 {
-  MX_ALL_OP (dim);
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_all);
 }
 
 boolMatrix
 Matrix::any (int dim) const
 {
-  MX_ANY_OP (dim);
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_any);
 }
 
 Matrix
--- a/liboctave/dNDArray.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/dNDArray.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -689,15 +689,13 @@
 boolNDArray
 NDArray::all (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION (MX_ND_ALL_EVAL (MX_ND_ALL_EXPR), true);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_all);
 }
 
 boolNDArray
 NDArray::any (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION
-    (MX_ND_ANY_EVAL (elem (iter_idx) != 0
-		     && ! lo_ieee_isnan (elem (iter_idx))), false);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_any);
 }
 
 NDArray
--- a/liboctave/fCMatrix.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/fCMatrix.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -3246,53 +3246,13 @@
 boolMatrix
 FloatComplexMatrix::all (int dim) const
 {
-  // FIXME Can't use MX_ALL_OP as need to static cast to float to the ROW 
-  // and COL expressions
-
-#define ROW_EXPR \
-  if (elem (i, j) == static_cast<float> (0.0)) \
-    { \
-      retval.elem (i, 0) = false; \
-      break; \
-    }
-
-#define COL_EXPR \
-  if (elem (i, j) == static_cast<float> (0.0)) \
-    { \
-      retval.elem (0, j) = false; \
-      break; \
-    }
-  
-  MX_BASE_REDUCTION_OP (boolMatrix, ROW_EXPR, COL_EXPR, true, true);
-
-#undef ROW_EXPR
-#undef COL_EXPR
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_all);
 }
 
 boolMatrix
 FloatComplexMatrix::any (int dim) const
 {
-  // FIXME Can't use MX_ANY_OP as need to static cast to float to the ROW 
-  // and COL expressions
-
-#define ROW_EXPR \
-  if (elem (i, j) != static_cast<float> (0.0)) \
-    { \
-      retval.elem (i, 0) = true; \
-      break; \
-    }
-
-#define COL_EXPR \
-  if (elem (i, j) != static_cast<float> (0.0)) \
-    { \
-      retval.elem (0, j) = true; \
-      break; \
-    }
-  
-  MX_BASE_REDUCTION_OP (boolMatrix, ROW_EXPR, COL_EXPR, false, false);
-
-#undef ROW_EXPR
-#undef COL_EXPR
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_any);
 }
 
 FloatComplexMatrix
--- a/liboctave/fCNDArray.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/fCNDArray.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -617,18 +617,13 @@
 boolNDArray
 FloatComplexNDArray::all (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION
-    (MX_ND_ALL_EVAL (elem (iter_idx) == FloatComplex (0, 0)), true);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_all);
 }
 
 boolNDArray
 FloatComplexNDArray::any (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION
-    (MX_ND_ANY_EVAL (elem (iter_idx) != FloatComplex (0, 0)
-		     && ! (lo_ieee_isnan (std::real (elem (iter_idx)))
-			   || lo_ieee_isnan (std::imag (elem (iter_idx))))),
-		     false);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_any);
 }
 
 FloatComplexNDArray
--- a/liboctave/fMatrix.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/fMatrix.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -2785,13 +2785,13 @@
 boolMatrix
 FloatMatrix::all (int dim) const
 {
-  MX_ALL_OP (dim);
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_all);
 }
 
 boolMatrix
 FloatMatrix::any (int dim) const
 {
-  MX_ANY_OP (dim);
+  return do_mx_red_op<boolMatrix> (*this, dim, mx_inline_any);
 }
 
 FloatMatrix
--- a/liboctave/fNDArray.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/fNDArray.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -644,15 +644,13 @@
 boolNDArray
 FloatNDArray::all (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION (MX_ND_ALL_EVAL (MX_ND_ALL_EXPR), true);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_all);
 }
 
 boolNDArray
 FloatNDArray::any (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION
-    (MX_ND_ANY_EVAL (elem (iter_idx) != 0
-		     && ! lo_ieee_isnan (elem (iter_idx))), false);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_any);
 }
 
 FloatNDArray
--- a/liboctave/intNDArray.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/intNDArray.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -74,14 +74,14 @@
 boolNDArray
 intNDArray<T>::all (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION (MX_ND_ALL_EVAL (this->elem (iter_idx) == T (0)), true);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_all);
 }
 
 template <class T>
 boolNDArray
 intNDArray<T>::any (int dim) const
 {
-  MX_ND_ANY_ALL_REDUCTION (MX_ND_ANY_EVAL (this->elem (iter_idx) != T (0)), false);
+  return do_mx_red_op<boolNDArray> (*this, dim, mx_inline_any);
 }
 
 template <class T>
--- a/liboctave/mx-inlines.cc	Sat Feb 14 07:27:34 2009 +0100
+++ b/liboctave/mx-inlines.cc	Sat Feb 14 19:50:43 2009 +0100
@@ -284,7 +284,7 @@
 
 // NOTE: std::norm is NOT equivalent
 template <class T>
-T cabsq (const std::complex<T>& c) 
+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
@@ -292,26 +292,64 @@
 #define OP_RED_SUMSQ(ac, el) ac += el*el
 #define OP_RED_SUMSQC(ac, el) ac += cabsq (el)
 
-#define OP_RED_FCN(F, TSRC, OP, ZERO) \
+// default. works for integers and bool.
+template <class T>
+inline bool xis_true (T x) { return x; }
+template <class T>
+inline bool xis_false (T x) { return ! x; }
+// for octave_ints
+template <class T>
+inline bool xis_true (const octave_int<T>& x) { return x.value (); }
+template <class T>
+inline bool xis_false (const octave_int<T>& x) { return ! x.value (); }
+// for reals, we want to ignore NaNs.
+inline bool xis_true (double x) { return ! xisnan (x) && x != 0.0; }
+inline bool xis_false (double x) { return x == 0.0; }
+inline bool xis_true (float x) { return ! xisnan (x) && x != 0.0f; }
+inline bool xis_false (float x) { return x == 0.0f; }
+// Ditto for complex.
+inline bool xis_true (const Complex& x) { return ! xisnan (x) && x != 0.0; }
+inline bool xis_false (const Complex& x) { return x == 0.0; }
+inline bool xis_true (const FloatComplex& x) { return ! xisnan (x) && x != 0.0f; }
+inline bool xis_false (const FloatComplex& x) { return x == 0.0f; }
+
+// 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
+
+// Row any/all reductions are a tradeoff - we traverse the array by
+// columns to gain cache coherence, but sacrifice short-circuiting for that.
+// For certain logical arrays, this could mean a significant loss.
+// A more sophisticated implementation could introduce a buffer of active
+// row indices to achieve both. Right now, I don't see the operation as
+// important enough.
+
+#define OP_RED_ANYR(ac, el) if (xis_true (el)) ac = true
+#define OP_RED_ALLR(ac, el) if (xis_false (el)) ac = false
+
+#define OP_RED_FCN(F, TSRC, TRES, OP, ZERO) \
 template <class T> \
-inline T \
+inline TRES \
 F (const TSRC* v, octave_idx_type n) \
 { \
-  T ac = ZERO; \
+  TRES ac = ZERO; \
   for (octave_idx_type i = 0; i < n; i++) \
     OP(ac, v[i]); \
   return ac; \
 }
 
-OP_RED_FCN (mx_inline_sum, T, OP_RED_SUM, 0)
-OP_RED_FCN (mx_inline_prod, T, OP_RED_PROD, 1)
-OP_RED_FCN (mx_inline_sumsq, T, OP_RED_SUMSQ, 0)
-OP_RED_FCN (mx_inline_sumsq, std::complex<T>, OP_RED_SUMSQC, 0)
+OP_RED_FCN (mx_inline_sum, T, T, OP_RED_SUM, 0)
+OP_RED_FCN (mx_inline_prod, T, T, OP_RED_PROD, 1)
+OP_RED_FCN (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
+OP_RED_FCN (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
+OP_RED_FCN (mx_inline_any, T, bool, OP_RED_ANYC, false)
+OP_RED_FCN (mx_inline_all, T, bool, OP_RED_ALLC, true)
 
-#define OP_RED_FCN2(F, TSRC, OP, ZERO) \
+
+#define OP_RED_FCN2(F, TSRC, TRES, OP, ZERO) \
 template <class T> \
 inline void \
-F (const TSRC* v, T *r, octave_idx_type m, octave_idx_type n) \
+F (const TSRC* v, TRES *r, octave_idx_type m, octave_idx_type n) \
 { \
   for (octave_idx_type i = 0; i < m; i++) \
     r[i] = ZERO; \
@@ -323,15 +361,17 @@
     } \
 }
 
-OP_RED_FCN2 (mx_inline_sum, T, OP_RED_SUM, 0)
-OP_RED_FCN2 (mx_inline_prod, T, OP_RED_PROD, 1)
-OP_RED_FCN2 (mx_inline_sumsq, T, OP_RED_SUMSQ, 0)
-OP_RED_FCN2 (mx_inline_sumsq, std::complex<T>, OP_RED_SUMSQC, 0)
+OP_RED_FCN2 (mx_inline_sum, T, T, OP_RED_SUM, 0)
+OP_RED_FCN2 (mx_inline_prod, T, T, OP_RED_PROD, 1)
+OP_RED_FCN2 (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
+OP_RED_FCN2 (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
+OP_RED_FCN2 (mx_inline_any, T, bool, OP_RED_ANYR, false)
+OP_RED_FCN2 (mx_inline_all, T, bool, OP_RED_ALLR, true)
 
-#define OP_RED_FCNN(F, TSRC) \
+#define OP_RED_FCNN(F, TSRC, TRES) \
 template <class T> \
 inline void \
-F (const TSRC *v, T *r, octave_idx_type l, \
+F (const TSRC *v, TRES *r, octave_idx_type l, \
    octave_idx_type n, octave_idx_type u) \
 { \
   if (l == 1) \
@@ -353,10 +393,12 @@
     } \
 }
 
-OP_RED_FCNN (mx_inline_sum, T)
-OP_RED_FCNN (mx_inline_prod, T)
-OP_RED_FCNN (mx_inline_sumsq, T)
-OP_RED_FCNN (mx_inline_sumsq, std::complex<T>)
+OP_RED_FCNN (mx_inline_sum, T, T)
+OP_RED_FCNN (mx_inline_prod, T, T)
+OP_RED_FCNN (mx_inline_sumsq, T, T)
+OP_RED_FCNN (mx_inline_sumsq, std::complex<T>, T)
+OP_RED_FCNN (mx_inline_any, T, bool)
+OP_RED_FCNN (mx_inline_all, T, bool)
 
 #define OP_CUM_FCN(F, OP) \
 template <class T> \
@@ -467,6 +509,10 @@
 {
   octave_idx_type l, n, u;
   dim_vector dims = src.dims ();
+  // M*b inconsistency: sum([]) = 0 etc.
+  if (dims.length () == 2 && dims(0) == 0 && dims(1) == 0)
+    dims (1) = 1;
+
   get_extent_triplet (dims, dim, l, n, u);
 
   // Reduction operation reduces the array size.