diff liboctave/Array.cc @ 10366:e5ae13b8b2c2

improve Array indexing error messages
author Jaroslav Hajek <highegg@gmail.com>
date Sat, 27 Feb 2010 08:37:34 +0100
parents a3635bc1ea19
children 9c4daf174387
line wrap: on
line diff
--- a/liboctave/Array.cc
+++ b/liboctave/Array.cc
@@ -206,60 +206,102 @@
 }
 
 template <class T>
-T&
-Array<T>::range_error (const char *fcn, octave_idx_type n) const
+T& 
+Array<T>::checkelem (octave_idx_type n)
 {
-  (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n);
-  static T foo;
-  return foo;
+  if (n < 0 || n >= slice_len)
+    gripe_index_out_of_range (1, 1, n+1, slice_len);
+
+  return elem (n);
 }
 
 template <class T>
-T&
-Array<T>::range_error (const char *fcn, octave_idx_type i, octave_idx_type j) const
+T& 
+Array<T>::checkelem (octave_idx_type i, octave_idx_type j)
 {
-  (*current_liboctave_error_handler)
-    ("%s (%d, %d): range error", fcn, i, j);
-  static T foo;
-  return foo;
+  if (i < 0 || i >= dim1 ())
+    gripe_index_out_of_range (2, 1, i+1, dim1 ());
+  if (j < 0 || j >= dimensions.numel (1))
+    gripe_index_out_of_range (2, 2, j+1, dimensions.numel (1));
+
+  return elem (i, j);
+}
+
+template <class T>
+T& 
+Array<T>::checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k)
+{
+  if (i < 0 || i >= dim1 ())
+    gripe_index_out_of_range (3, 1, i+1, dim1 ());
+  if (j < 0 || j >= dim2 ())
+    gripe_index_out_of_range (3, 2, j+1, dim2 ());
+  if (k < 0 || k >= dimensions.numel (2))
+    gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2));
+
+  return elem (i, j, k);
 }
 
 template <class T>
-T&
-Array<T>::range_error (const char *fcn, octave_idx_type i, octave_idx_type j, octave_idx_type k) const
+T& 
+Array<T>::checkelem (const Array<octave_idx_type>& ra_idx)
 {
-  (*current_liboctave_error_handler)
-    ("%s (%d, %d, %d): range error", fcn, i, j, k);
-  static T foo;
-  return foo;
+  int nd = ra_idx.length ();
+  const dim_vector dv = dimensions.redim (nd);
+  for (int d = 0; d < nd; d++)
+    if (ra_idx(d) < 0 || ra_idx(d) >= dv(d))
+      gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d));
+
+  return elem (ra_idx);
+}
+
+template <class T>
+typename Array<T>::crefT
+Array<T>::checkelem (octave_idx_type n) const
+{
+  if (n < 0 || n >= slice_len)
+    gripe_index_out_of_range (1, 1, n+1, slice_len);
+
+  return elem (n);
 }
 
 template <class T>
-T&
-Array<T>::range_error (const char *fcn, const Array<octave_idx_type>& ra_idx) const
+typename Array<T>::crefT
+Array<T>::checkelem (octave_idx_type i, octave_idx_type j) const
+{
+  if (i < 0 || i >= dim1 ())
+    gripe_index_out_of_range (2, 1, i+1, dim1 ());
+  if (j < 0 || j >= dimensions.numel (1))
+    gripe_index_out_of_range (2, 2, j+1, dimensions.numel (1));
+
+  return elem (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
 {
-  std::ostringstream buf;
-
-  buf << fcn << " (";
-
-  octave_idx_type n = ra_idx.length ();
-
-  if (n > 0)
-    buf << ra_idx(0);
-
-  for (octave_idx_type i = 1; i < n; i++)
-    buf << ", " << ra_idx(i);
-
-  buf << "): range error";
-
-  std::string buf_str = buf.str ();
-
-  (*current_liboctave_error_handler) (buf_str.c_str ());
-
-  static T foo;
-  return foo;
+  if (i < 0 || i >= dim1 ())
+    gripe_index_out_of_range (3, 1, i+1, dim1 ());
+  if (j < 0 || j >= dim2 ())
+    gripe_index_out_of_range (3, 2, j+1, dim2 ());
+  if (k < 0 || k >= dimensions.numel (2))
+    gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2));
+
+  return elem (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 || ra_idx(d) >= dv(d))
+      gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d));
+
+  return elem (ra_idx);
+}
 
 template <class T>
 Array<T>
@@ -267,8 +309,8 @@
 {
   octave_idx_type r = dimensions(0);
 #ifdef BOUNDS_CHECKING
-  if (k < 0 || k * r >= numel ())
-    range_error ("column", k);
+  if (k < 0 || k > dimensions.numel (1))
+    gripe_index_out_of_range (2, 2, k+1, dimensions.numel (1));
 #endif
 
   return Array<T> (*this, dim_vector (r, 1), k*r, k*r + r);
@@ -280,8 +322,8 @@
 {
   octave_idx_type r = dimensions(0), c = dimensions (1), p = r*c;
 #ifdef BOUNDS_CHECKING
-  if (k < 0 || k * p >= numel ())
-    range_error ("page", k);
+  if (k < 0 || k > dimensions.numel (2))
+    gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2));
 #endif
 
   return Array<T> (*this, dim_vector (r, c), k*p, k*p + p);
@@ -300,8 +342,10 @@
 Array<T>::linear_slice (octave_idx_type lo, octave_idx_type up) const
 {
 #ifdef BOUNDS_CHECKING
-  if (lo < 0 || up > numel ())
-    range_error ("linear_slice", lo, up);
+  if (lo < 0)
+    gripe_index_out_of_range (1, 1, lo+1, numel ());
+  if (up > numel ())
+    gripe_index_out_of_range (1, 1, up, numel ());
 #endif
   if (up < lo) up = lo;
   return Array<T> (*this, dim_vector (up - lo, 1), lo, up);
@@ -688,12 +732,6 @@
 
 };
 
-static void gripe_index_out_of_range (void)
-{
-  (*current_liboctave_error_handler)
-    ("A(I): Index exceeds matrix dimension.");
-}
-
 template <class T>
 Array<T>
 Array<T>::index (const idx_vector& i) const
@@ -706,12 +744,11 @@
       // A(:) produces a shallow copy as a column vector.
       retval = Array<T> (*this, dim_vector (n, 1));
     }
-  else if (i.extent (n) != n)
-    {
-      gripe_index_out_of_range ();
-    }
   else
     {
+      if (i.extent (n) != n)
+        gripe_index_out_of_range (1, 1, i.extent (n), n); // throws
+
       // FIXME -- this is the only place where orig_dimensions are used.
       dim_vector rd = i.orig_dimensions ();
       octave_idx_type il = i.length (n);
@@ -773,12 +810,13 @@
       // A(:,:) produces a shallow copy.
       retval = Array<T> (*this, dv);
     }
-  else if (i.extent (r) != r || j.extent (c) != c)
-    {
-      gripe_index_out_of_range ();
-    }
   else
     {
+      if (i.extent (r) != r)
+        gripe_index_out_of_range (2, 1, i.extent (r), r); // throws
+      if (j.extent (c) != c)
+        gripe_index_out_of_range (2, 2, i.extent (c), c); // throws
+
       octave_idx_type n = numel (), il = i.length (r), jl = j.length (c);
 
       idx_vector ii (i);
@@ -831,24 +869,17 @@
       dim_vector dv = dimensions.redim (ial);
 
       // Check for out of bounds conditions.
-      bool all_colons = true, mismatch = false;
+      bool all_colons = true;
       for (int i = 0; i < ial; i++)
         {
           if (ia(i).extent (dv(i)) != dv(i))
-            {
-              mismatch = true;
-              break;
-            }
-          else
-            all_colons = all_colons && ia(i).is_colon ();
+            gripe_index_out_of_range (ial, i+1, ia(i).extent (dv(i)), dv(i)); // throws
+
+          all_colons = all_colons && ia(i).is_colon ();
         }
 
 
-      if (mismatch)
-        {
-          gripe_index_out_of_range ();
-        }
-      else if (all_colons)
+      if (all_colons)
         {
           // A(:,:,...,:) produces a shallow copy.
           dv.chop_trailing_singletons ();
@@ -1387,12 +1418,11 @@
     { 
       *this = Array<T> ();
     }
-  else if (i.extent (n) != n)
-    {
-      gripe_index_out_of_range ();
-    }
   else if (i.length (n) != 0)
     {
+      if (i.extent (n) != n)
+        gripe_del_index_out_of_range (true, i.extent (n), n);
+
       octave_idx_type l, u;
       bool col_vec = ndims () == 2 && columns () == 1 && rows () != 1;
       if (i.is_scalar () && i(0) == n-1)
@@ -1435,12 +1465,11 @@
     { 
       *this = Array<T> ();
     }
-  else if (i.extent (n) != n)
-    {
-      gripe_index_out_of_range ();
-    }
   else if (i.length (n) != 0)
     {
+      if (i.extent (n) != n)
+        gripe_del_index_out_of_range (false, i.extent (n), n);
+
       octave_idx_type l, u;
 
       if (i.is_cont_range (n, l, u))