changeset 11010:9478b216752e

simplify more array tests
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 22 Sep 2010 07:06:25 +0200
parents 064aaf82222f
children a046d03e2417
files liboctave/Array.h liboctave/ChangeLog liboctave/dMatrix.cc liboctave/dNDArray.cc liboctave/fMatrix.cc liboctave/fNDArray.cc liboctave/lo-mappers.cc liboctave/lo-mappers.h liboctave/lo-utils.cc liboctave/lo-utils.h
diffstat 10 files changed, 155 insertions(+), 242 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array.h
+++ b/liboctave/Array.h
@@ -623,6 +623,58 @@
   map (U (&fcn) (const T&)) const
   { return map<U, U (&) (const T&)> (fcn); }
 
+  // Generic any/all test functionality with arbitrary predicate.
+  template <class F, bool zero>
+  bool test (F fcn) const
+  {
+    octave_idx_type len = length ();
+
+    const T *m = data ();
+
+    octave_idx_type i;
+    for (i = 0; i < len - 3; i += 4)
+      {
+        octave_quit ();
+
+        if (fcn (m[i]) != zero 
+            || fcn (m[i+1]) != zero
+            || fcn (m[i+2]) != zero
+            || fcn (m[i+3]) != zero)
+           return ! zero;
+
+      }
+
+    octave_quit ();
+
+    for (; i < len; i++)
+       if (fcn (m[i]) != zero)
+          return ! zero;
+
+    return zero;
+  }
+
+  // Simpler calls.
+  template <class F>
+  bool test_any (F fcn) const
+  { return test<F, false> (fcn); }
+
+  template <class F>
+  bool test_all (F fcn) const
+  { return test<F, true> (fcn); }
+
+  // Overloads for function references.
+  bool test_any (bool (&fcn) (T)) const
+  { return test<bool (&) (T), false> (fcn); }
+
+  bool test_any (bool (&fcn) (const T&)) const
+  { return test<bool (&) (const T&), false> (fcn); }
+
+  bool test_all (bool (&fcn) (T)) const
+  { return test<bool (&) (T), true> (fcn); }
+
+  bool test_all (bool (&fcn) (const T&)) const
+  { return test<bool (&) (const T&), true> (fcn); }
+
   template <class U> friend class Array;
 
   // Returns true if this->dims () == dv, and if so, replaces this->dimensions
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,28 @@
+2010-09-21  Jaroslav Hajek  <highegg@gmail.com>
+
+	* Array.h (Array::test, Array::test_all, Array::test_any): New
+	overloaded template methods.
+	* lo-mappers.h (xisinteger, xnegative_sign): New bool mappers.
+	* dNDArray.cc (NDArray::any_element_is_negative, 
+	NDArray::all_integers): Simplify.
+	* fNDArray.cc (FloatNDArray::any_element_is_negative, 
+	FloatNDArray::all_integers): Simplify.
+
+	* lo-utils.cc (xis_int_or_inf_or_nan, xis_one_or_zero,
+	xis_zero, xtoo_large_for_float): New utility functions.
+
+	* dNDArray.cc (NDArray::any_element_is_negative, 
+	NDArray::all_integers, NDArray::all_elements_are_zero,
+	NDArray::all_elements_are_int_or_inf_or_nan, 
+	NDArray::any_element_not_one_or_zero,
+	NDArray::too_large_for_float): Simplify.
+
+	* fNDArray.cc (FloatNDArray::any_element_is_negative, 
+	FloatNDArray::all_integers, FloatNDArray::all_elements_are_zero,
+	FloatNDArray::all_elements_are_int_or_inf_or_nan, 
+	FloatNDArray::any_element_not_one_or_zero,
+	FloatNDArray::too_large_for_float): Simplify.
+
 2010-09-21  Jaroslav Hajek  <highegg@gmail.com>
 
 	* dNDArray.cc (NDArray::any_element_is_negative, 
--- a/liboctave/dMatrix.cc
+++ b/liboctave/dMatrix.cc
@@ -2621,80 +2621,32 @@
 bool
 Matrix::any_element_is_negative (bool neg_zero) const
 {
-  octave_idx_type nel = nelem ();
-
-  if (neg_zero)
-    {
-      for (octave_idx_type i = 0; i < nel; i++)
-        if (lo_ieee_signbit (elem (i)))
-          return true;
-    }
-  else
-    return do_mx_check<double> (*this, mx_inline_any_negative);
-
-  return false;
+  return (neg_zero ? test_all (xnegative_sign)
+          : do_mx_check<double> (*this, mx_inline_any_negative));
 }
 
 bool
 Matrix::any_element_is_nan (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-      if (xisnan (val))
-        return true;
-    }
-
-  return false;
+  return do_mx_check<double> (*this, mx_inline_any_nan);
 }
 
 bool
 Matrix::any_element_is_inf_or_nan (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-      if (xisinf (val) || xisnan (val))
-        return true;
-    }
-
-  return false;
+  return ! do_mx_check<double> (*this, mx_inline_all_finite);
 }
 
 bool
 Matrix::any_element_not_one_or_zero (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-      if (val != 0 && val != 1)
-        return true;
-    }
-
-  return false;
+  return ! test_all (xis_one_or_zero);
 }
 
 bool
 Matrix::all_elements_are_int_or_inf_or_nan (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-      if (xisnan (val) || D_NINT (val) == val)
-        continue;
-      else
-        return false;
-    }
-
-  return true;
+  return test_all (xis_int_or_inf_or_nan);
 }
 
 // Return nonzero if any element of M is not an integer.  Also extract
@@ -2723,7 +2675,7 @@
       if (val < min_val)
         min_val = val;
 
-      if (D_NINT (val) != val)
+      if (! xisinteger (val))
         return false;
     }
 
@@ -2733,18 +2685,7 @@
 bool
 Matrix::too_large_for_float (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-
-      if (! (xisnan (val) || xisinf (val))
-          && fabs (val) > FLT_MAX)
-        return true;
-    }
-
-  return false;
+  return test_all (xtoo_large_for_float);
 }
 
 // FIXME Do these really belong here?  Maybe they should be
--- a/liboctave/dNDArray.cc
+++ b/liboctave/dNDArray.cc
@@ -547,18 +547,8 @@
 bool
 NDArray::any_element_is_negative (bool neg_zero) const
 {
-  octave_idx_type nel = nelem ();
-
-  if (neg_zero)
-    {
-      for (octave_idx_type i = 0; i < nel; i++)
-        if (lo_ieee_signbit (elem (i)))
-          return true;
-    }
-  else
-    return do_mx_check<double> (*this, mx_inline_any_negative);
-
-  return false;
+  return (neg_zero ? test_all (xnegative_sign)
+          : do_mx_check<double> (*this, mx_inline_any_negative));
 }
 
 bool
@@ -576,45 +566,19 @@
 bool
 NDArray::any_element_not_one_or_zero (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-      if (val != 0 && val != 1)
-        return true;
-    }
-
-  return false;
+  return ! test_all (xis_one_or_zero);
 }
 
 bool
 NDArray::all_elements_are_zero (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    if (elem (i) != 0)
-      return false;
-
-  return true;
+  return test_all (xis_zero);
 }
 
 bool
 NDArray::all_elements_are_int_or_inf_or_nan (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-      if (xisnan (val) || D_NINT (val) == val)
-        continue;
-      else
-        return false;
-    }
-
-  return true;
+  return test_all (xis_int_or_inf_or_nan);
 }
 
 // Return nonzero if any element of M is not an integer.  Also extract
@@ -643,7 +607,7 @@
       if (val < min_val)
         min_val = val;
 
-      if (D_NINT (val) != val)
+      if (! xisinteger (val))
         return false;
     }
 
@@ -653,34 +617,13 @@
 bool
 NDArray::all_integers (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-
-      if (D_NINT (val) != val)
-        return false;
-    }
-
-  return true;
+  return test_all (xisinteger);
 }
 
 bool
 NDArray::too_large_for_float (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-
-      if (! (xisnan (val) || xisinf (val))
-          && fabs (val) > FLT_MAX)
-        return true;
-    }
-
-  return false;
+  return test_all (xtoo_large_for_float);
 }
 
 // FIXME -- this is not quite the right thing.
--- a/liboctave/fMatrix.cc
+++ b/liboctave/fMatrix.cc
@@ -2620,18 +2620,8 @@
 bool
 FloatMatrix::any_element_is_negative (bool neg_zero) const
 {
-  octave_idx_type nel = nelem ();
-
-  if (neg_zero)
-    {
-      for (octave_idx_type i = 0; i < nel; i++)
-        if (lo_ieee_signbit (elem (i)))
-          return true;
-    }
-  else
-    return do_mx_check<float> (*this, mx_inline_any_negative);
-
-  return false;
+  return (neg_zero ? test_all (xnegative_sign)
+          : do_mx_check<float> (*this, mx_inline_any_negative));
 }
 
 bool
@@ -2649,33 +2639,13 @@
 bool
 FloatMatrix::any_element_not_one_or_zero (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      float val = elem (i);
-      if (val != 0 && val != 1)
-        return true;
-    }
-
-  return false;
+  return ! test_all (xis_one_or_zero);
 }
 
 bool
 FloatMatrix::all_elements_are_int_or_inf_or_nan (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      float val = elem (i);
-      if (xisnan (val) || D_NINT (val) == val)
-        continue;
-      else
-        return false;
-    }
-
-  return true;
+  return test_all (xis_int_or_inf_or_nan);
 }
 
 // Return nonzero if any element of M is not an integer.  Also extract
@@ -2704,7 +2674,7 @@
       if (val < min_val)
         min_val = val;
 
-      if (D_NINT (val) != val)
+      if (! xisinteger (val))
         return false;
     }
 
@@ -2714,17 +2684,6 @@
 bool
 FloatMatrix::too_large_for_float (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      float val = elem (i);
-
-      if (! (xisnan (val) || xisinf (val))
-          && fabs (val) > FLT_MAX)
-        return true;
-    }
-
   return false;
 }
 
--- a/liboctave/fNDArray.cc
+++ b/liboctave/fNDArray.cc
@@ -505,18 +505,8 @@
 bool
 FloatNDArray::any_element_is_negative (bool neg_zero) const
 {
-  octave_idx_type nel = nelem ();
-
-  if (neg_zero)
-    {
-      for (octave_idx_type i = 0; i < nel; i++)
-        if (lo_ieee_signbit (elem (i)))
-          return true;
-    }
-  else
-    return do_mx_check<float> (*this, mx_inline_any_negative);
-
-  return false;
+  return (neg_zero ? test_all (xnegative_sign)
+          : do_mx_check<float> (*this, mx_inline_any_negative));
 }
 
 bool
@@ -534,45 +524,19 @@
 bool
 FloatNDArray::any_element_not_one_or_zero (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      float val = elem (i);
-      if (val != 0 && val != 1)
-        return true;
-    }
-
-  return false;
+  return ! test_all (xis_one_or_zero);
 }
 
 bool
 FloatNDArray::all_elements_are_zero (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    if (elem (i) != 0)
-      return false;
-
-  return true;
+  return test_all (xis_zero);
 }
 
 bool
 FloatNDArray::all_elements_are_int_or_inf_or_nan (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      float val = elem (i);
-      if (xisnan (val) || D_NINT (val) == val)
-        continue;
-      else
-        return false;
-    }
-
-  return true;
+  return test_all (xis_int_or_inf_or_nan);
 }
 
 // Return nonzero if any element of M is not an integer.  Also extract
@@ -601,7 +565,7 @@
       if (val < min_val)
         min_val = val;
 
-      if (D_NINT (val) != val)
+      if (! xisinteger (val))
         return false;
     }
 
@@ -611,33 +575,12 @@
 bool
 FloatNDArray::all_integers (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-
-      if (D_NINT (val) != val)
-        return false;
-    }
-
-  return true;
+  return test_all (xisinteger);
 }
 
 bool
 FloatNDArray::too_large_for_float (void) const
 {
-  octave_idx_type nel = nelem ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      float val = elem (i);
-
-      if (! (xisnan (val) || xisinf (val))
-          && fabs (val) > FLT_MAX)
-        return true;
-    }
-
   return false;
 }
 
--- a/liboctave/lo-mappers.cc
+++ b/liboctave/lo-mappers.cc
@@ -702,3 +702,9 @@
 {
   return x < 0.0f ? FloatComplex (0.0f, sqrtf (-x)) : FloatComplex (sqrtf (x));
 }
+
+bool xnegative_sign (double x)
+{ return __lo_ieee_signbit (x); }
+
+bool xnegative_sign (float x)
+{ return __lo_ieee_float_signbit (x); }
--- a/liboctave/lo-mappers.h
+++ b/liboctave/lo-mappers.h
@@ -211,4 +211,16 @@
 extern OCTAVE_API Complex rc_sqrt (double);
 extern OCTAVE_API FloatComplex rc_sqrt (float);
 
+// Some useful tests, that are commonly repeated.
+// Test for a finite integer.
+inline bool xisinteger (double x)
+{ return xfinite (x) && x == xround (x); }
+inline bool xisinteger (float x)
+{ return xfinite (x) && x == xround (x); }
+
+// Test for negative sign. 
+extern OCTAVE_API bool xnegative_sign (double x);
+extern OCTAVE_API bool xnegative_sign (float x);
+
+
 #endif
--- a/liboctave/lo-utils.cc
+++ b/liboctave/lo-utils.cc
@@ -30,6 +30,7 @@
 #include <cstdlib>
 #include <cstdio>
 #include <cstring>
+#include <cfloat>
 
 #include <limits>
 #include <string>
@@ -111,6 +112,27 @@
     return floor (x + 0.5);
 }
 
+bool xis_int_or_inf_or_nan (double x)
+{ return ! (xisnan (x) || D_NINT (x) == x); }
+
+bool xis_one_or_zero (double x)
+{ return x == 0 || x == 1; }
+
+bool xis_zero (double x)
+{ return x == 0; }
+
+bool xtoo_large_for_float (double x)
+{ return (! (xisnan (x) || xisinf (x)) && fabs (x) > FLT_MAX); }
+
+bool xis_int_or_inf_or_nan (float x)
+{ return ! (xisnan (x) || D_NINT (x) == x); }
+
+bool xis_one_or_zero (float x)
+{ return x == 0 || x == 1; }
+
+bool xis_zero (float x)
+{ return x == 0; }
+
 // Save a string.
 
 char *
--- a/liboctave/lo-utils.h
+++ b/liboctave/lo-utils.h
@@ -39,6 +39,16 @@
 extern OCTAVE_API double D_NINT (double x);
 extern OCTAVE_API float F_NINT (float x);
 
+extern OCTAVE_API bool xis_int_or_inf_or_nan (double x);
+extern OCTAVE_API bool xis_one_or_zero (double x);
+extern OCTAVE_API bool xis_zero (double x);
+extern OCTAVE_API bool xtoo_large_for_float (double x);
+
+extern OCTAVE_API bool xis_int_or_inf_or_nan (float x);
+extern OCTAVE_API bool xis_one_or_zero (float x);
+extern OCTAVE_API bool xis_zero (float x);
+extern OCTAVE_API bool xtoo_large_for_float (float x);
+
 extern OCTAVE_API char *strsave (const char *);
 
 extern OCTAVE_API void