changeset 10645:8645b7087859

abstract scalar index checking off Array<T> (prep for struct optimizations)
author Jaroslav Hajek <highegg@gmail.com>
date Thu, 20 May 2010 15:10:34 +0200
parents 45b72e631cb5
children 6c50b56824aa
files liboctave/Array-util.cc liboctave/Array-util.h liboctave/Array.cc liboctave/Array.h liboctave/ChangeLog liboctave/dim-vector.h
diffstat 6 files changed, 124 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array-util.cc	Thu May 20 07:27:45 2010 +0200
+++ b/liboctave/Array-util.cc	Thu May 20 15:10:34 2010 +0200
@@ -174,29 +174,60 @@
   return retval;
 }
 
-octave_idx_type
+octave_idx_type 
+compute_index (octave_idx_type n, const dim_vector& dims)
+{
+  if (n < 0)
+    gripe_invalid_index ();
+  if (n >= dims.numel ())
+    gripe_index_out_of_range (1, 1, n+1, dims.numel ());
+
+  return n;
+}
+
+octave_idx_type 
+compute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims)
+{
+  if (i < 0 || j < 0)
+    gripe_invalid_index ();
+  if (i >= dims(0))
+    gripe_index_out_of_range (2, 1, i+1, dims(0));
+  if (j >= dims.numel (1))
+    gripe_index_out_of_range (2, 2, j+1, dims.numel (1));
+
+  return j*dims(0) + i;
+}
+
+octave_idx_type 
+compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k,
+               const dim_vector& dims)
+{
+  if (i < 0 || j < 0 || k < 0)
+    gripe_invalid_index ();
+  if (i >= dims(0))
+    gripe_index_out_of_range (3, 1, i+1, dims(0));
+  if (j >= dims(1))
+    gripe_index_out_of_range (3, 2, j+1, dims(1));
+  if (k >= dims.numel (2))
+    gripe_index_out_of_range (3, 3, k+1, dims.numel (2));
+
+  return (k*dims(1) + j)*dims(0) + i;
+}
+
+octave_idx_type 
 compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims)
 {
-  octave_idx_type retval = -1;
-
-  int n = dims.length ();
-
-  if (n > 0 && n == ra_idx.length ())
+  int nd = ra_idx.length ();
+  const dim_vector dv = dims.redim (nd);
+  for (int d = 0; d < nd; d++)
     {
-      retval = ra_idx(--n);
+      if (ra_idx(d) < 0)
+        gripe_invalid_index ();
+      if (ra_idx(d) >= dv(d))
+        gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d));
+    }
 
-      while (--n >= 0)
-        {
-          retval *= dims(n);
-        
-          retval += ra_idx(n);
-        }
-    }
-  else
-    (*current_liboctave_error_handler)
-      ("ArrayN<T>::compute_index: invalid ra_idxing operation");
-
-  return retval;
+  return dv.compute_index (ra_idx.data ());
 }
 
 Array<octave_idx_type>
--- a/liboctave/Array-util.h	Thu May 20 07:27:45 2010 +0200
+++ b/liboctave/Array-util.h	Thu May 20 15:10:34 2010 +0200
@@ -47,7 +47,20 @@
 
 extern OCTAVE_API bool any_ones (const Array<octave_idx_type>& arr);
 
-extern OCTAVE_API octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims);
+// These four compute a linear index for given dimensions, throwing
+// exceptions on invalid indices.
+extern OCTAVE_API octave_idx_type 
+compute_index (octave_idx_type n, const dim_vector& dims);
+
+extern OCTAVE_API octave_idx_type 
+compute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims);
+
+extern OCTAVE_API octave_idx_type 
+compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k,
+               const dim_vector& dims);
+
+extern OCTAVE_API octave_idx_type 
+compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims);
 
 extern OCTAVE_API Array<octave_idx_type> conv_to_int_array (const Array<idx_vector>& a);
 
--- a/liboctave/Array.cc	Thu May 20 07:27:45 2010 +0200
+++ b/liboctave/Array.cc	Thu May 20 15:10:34 2010 +0200
@@ -187,28 +187,30 @@
 
 template <class T>
 octave_idx_type
+Array<T>::compute_index (octave_idx_type i, octave_idx_type j) const
+{
+  return ::compute_index (i, j, dimensions);
+}
+
+template <class T>
+octave_idx_type
+Array<T>::compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k) const
+{
+  return ::compute_index (i, j, k, dimensions);
+}
+
+template <class T>
+octave_idx_type
 Array<T>::compute_index (const Array<octave_idx_type>& ra_idx) const
 {
-  octave_idx_type retval = 0;
-
-  int n = dimensions.length (), ni = ra_idx.length ();
-
-  while (ni > n)
-    retval += ra_idx(--ni);
-
-  while (ni > 0)
-    {
-      retval *= dimensions(--ni);
-      retval += ra_idx(ni);
-    }
-
-  return retval;
+  return ::compute_index (ra_idx, dimensions);
 }
 
 template <class T>
 T& 
 Array<T>::checkelem (octave_idx_type n)
 {
+  // Do checks directly to avoid recomputing slice_len.
   if (n < 0)
     gripe_invalid_index ();
   if (n >= slice_len)
@@ -221,53 +223,28 @@
 T& 
 Array<T>::checkelem (octave_idx_type i, octave_idx_type j)
 {
-  if (i < 0 || j < 0)
-    gripe_invalid_index ();
-  if (i >= dim1 ())
-    gripe_index_out_of_range (2, 1, i+1, dim1 ());
-  if (j >= dimensions.numel (1))
-    gripe_index_out_of_range (2, 2, j+1, dimensions.numel (1));
-
-  return elem (i, j);
+  return elem (compute_index (i, j));
 }
 
 template <class T>
 T& 
 Array<T>::checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k)
 {
-  if (i < 0 || j < 0 || k < 0)
-    gripe_invalid_index ();
-  if (i >= dim1 ())
-    gripe_index_out_of_range (3, 1, i+1, dim1 ());
-  if (j >= dim2 ())
-    gripe_index_out_of_range (3, 2, j+1, dim2 ());
-  if (k >= dimensions.numel (2))
-    gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2));
-
-  return elem (i, j, k);
+  return elem (compute_index (i, j, k));
 }
 
 template <class T>
 T& 
 Array<T>::checkelem (const Array<octave_idx_type>& ra_idx)
 {
-  int nd = ra_idx.length ();
-  const dim_vector dv = dimensions.redim (nd);
-  for (int d = 0; d < nd; d++)
-    {
-      if (ra_idx(d) < 0)
-        gripe_invalid_index ();
-      if (ra_idx(d) >= dv(d))
-        gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d));
-    }
-
-  return elem (ra_idx);
+  return elem (compute_index (ra_idx));
 }
 
 template <class T>
 typename Array<T>::crefT
 Array<T>::checkelem (octave_idx_type n) const
 {
+  // Do checks directly to avoid recomputing slice_len.
   if (n < 0)
     gripe_invalid_index ();
   if (n >= slice_len)
@@ -280,47 +257,21 @@
 typename Array<T>::crefT
 Array<T>::checkelem (octave_idx_type i, octave_idx_type j) const
 {
-  if (i < 0 || j < 0)
-    gripe_invalid_index ();
-  if (i >= dim1 ())
-    gripe_index_out_of_range (2, 1, i+1, dim1 ());
-  if (j >= dimensions.numel (1))
-    gripe_index_out_of_range (2, 2, j+1, dimensions.numel (1));
-
-  return elem (i, j);
+  return elem (compute_index (i, j));
 }
 
 template <class T>
 typename Array<T>::crefT
 Array<T>::checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const
 {
-  if (i < 0 || j < 0 || k < 0)
-    gripe_invalid_index ();
-  if (i >= dim1 ())
-    gripe_index_out_of_range (3, 1, i+1, dim1 ());
-  if (j >= dim2 ())
-    gripe_index_out_of_range (3, 2, j+1, dim2 ());
-  if (k >= dimensions.numel (2))
-    gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2));
-
-  return elem (i, j, k);
+  return elem (compute_index (i, j, k));
 }
 
 template <class T>
 typename Array<T>::crefT
 Array<T>::checkelem (const Array<octave_idx_type>& ra_idx) const
 {
-  int nd = ra_idx.length ();
-  const dim_vector dv = dimensions.redim (nd);
-  for (int d = 0; d < nd; d++)
-    {
-      if (ra_idx(d) < 0)
-        gripe_invalid_index ();
-      if (ra_idx(d) >= dv(d))
-        gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d));
-    }
-
-  return elem (ra_idx);
+  return elem (compute_index (ra_idx));
 }
 
 template <class T>
--- a/liboctave/Array.h	Thu May 20 07:27:45 2010 +0200
+++ b/liboctave/Array.h	Thu May 20 15:10:34 2010 +0200
@@ -336,6 +336,9 @@
   octave_idx_type compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k) const;
   octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx) const;
 
+  octave_idx_type compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const
+    { return dimensions.compute_index (ra_idx.data (), ra_idx.length ()); }
+
   // No checking, even for multiple references, ever.
 
   T& xelem (octave_idx_type n) { return slice_data [n]; }
@@ -350,10 +353,10 @@
     { return xelem (i, dim2()*k+j); }
 
   T& xelem (const Array<octave_idx_type>& ra_idx)
-    { return xelem (compute_index (ra_idx)); }
+    { return xelem (compute_index_unchecked (ra_idx)); }
 
   crefT xelem (const Array<octave_idx_type>& ra_idx) const
-    { return xelem (compute_index (ra_idx)); }
+    { return xelem (compute_index_unchecked (ra_idx)); }
 
   // FIXME -- would be nice to fix this so that we don't
   // unnecessarily force a copy, but that is not so easy, and I see no
@@ -375,7 +378,7 @@
   T& elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) { return elem (i, dim2()*k+j); }
 
   T& elem (const Array<octave_idx_type>& ra_idx)
-    { return Array<T>::elem (compute_index (ra_idx)); }
+    { return Array<T>::elem (compute_index_unchecked (ra_idx)); }
 
 #if defined (BOUNDS_CHECKING)
   T& operator () (octave_idx_type n) { return checkelem (n); }
@@ -401,7 +404,7 @@
   crefT elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { return xelem (i, j, k); }
 
   crefT elem (const Array<octave_idx_type>& ra_idx) const
-    { return Array<T>::xelem (compute_index (ra_idx)); }
+    { return Array<T>::xelem (compute_index_unchecked (ra_idx)); }
 
 #if defined (BOUNDS_CHECKING)
   crefT operator () (octave_idx_type n) const { return checkelem (n); }
--- a/liboctave/ChangeLog	Thu May 20 07:27:45 2010 +0200
+++ b/liboctave/ChangeLog	Thu May 20 15:10:34 2010 +0200
@@ -1,3 +1,19 @@
+2010-05-20  Jaroslav Hajek  <highegg@gmail.com>
+
+	* dim-vector.h (dim_vector::compute_index (const octave_idx_type *,
+	int)): New method overload.
+	(dim_vector::compute_index, dim_vector::cum_compute_index,
+	dim_vector::increment_index): Add missing const qualifiers.
+
+	* Array-util.cc (compute_index (..., const dim_vector&)): Rewrite,
+	add new overloads. Move code from Array<T>::checkelem here.
+	* Array-util.h: Update decls.
+	* Array.h (Array<T>::compute_index): Forward to the above.
+	(Array<T>::compute_index_unchecked): New method.
+	(Array<T>::elem, Array<T>::xelem): Call it here.
+
+	* Array.cc (Array<T>::checkelem): Use compute_index where suitable.
+
 2010-05-19  Jaroslav Hajek  <highegg@gmail.com>
 
 	* mx-inlines.cc (mx_inline_cumcount): Fix 2D version instantiation.
--- a/liboctave/dim-vector.h	Thu May 20 07:27:45 2010 +0200
+++ b/liboctave/dim-vector.h	Thu May 20 15:10:34 2010 +0200
@@ -612,7 +612,7 @@
 
   // Compute a linear index from an index tuple.
 
-  octave_idx_type compute_index (const octave_idx_type *idx)
+  octave_idx_type compute_index (const octave_idx_type *idx) const
     {
       octave_idx_type k = 0;
       for (int i = length () - 1; i >= 0; i--)
@@ -621,11 +621,22 @@
       return k;
     }
 
+  // Ditto, but the tuple may be incomplete (nidx < length ()).
+
+  octave_idx_type compute_index (const octave_idx_type *idx, int nidx) const
+    {
+      octave_idx_type k = 0;
+      for (int i = nidx - 1; i >= 0; i--)
+        k = k * rep[i] + idx[i];
+
+      return k;
+    }
+
   // Increment a multi-dimensional index tuple, optionally starting
   // from an offset position and return the index of the last index
   // position that was changed, or length () if just cycled over.
 
-  int increment_index (octave_idx_type *idx, int start = 0)
+  int increment_index (octave_idx_type *idx, int start = 0) const
     {
       int i;
       for (i = start; i < length (); i++)
@@ -655,7 +666,7 @@
   // Compute a linear index from an index tuple.  Dimensions are
   // required to be cumulative.
 
-  octave_idx_type cum_compute_index (const octave_idx_type *idx)
+  octave_idx_type cum_compute_index (const octave_idx_type *idx) const
     {
       octave_idx_type k = idx[0];