comparison liboctave/array/Array.cc @ 20574:dd6345fd8a97

use exceptions for better invalid index error reporting (bug #45957) * lo-array-gripes.h, lo-array-gripes.cc (index_exception): New base class for indexing errors. (invalid_index, out_of_range): New classes. (gripe_index_out_of_range): New overloaded function. (gripe_invalid_index): New overloaded functions. Delete version with no arguments. (gripe_invalid_assignment_size, gripe_assignment_dimension_mismatch): Delete. Change uses of gripe functions as needed. * Cell.cc (Cell::index, Cell::assign, Cell::delete_elements): Use exceptions to collect error info about and handle indexing errors. * data.cc (Fnth_element, do_accumarray_sum, F__accumarray_sum__, do_accumarray_minmax, do_accumarray_minmax_fun, F__accumdim_sum__): Likewise. * oct-map.cc (octave_map::index, octave_map::assign, octave_map::delete_elements): Likewise. * sparse.cc (Fsparse): Likewise. * sub2ind.cc (Fsub2ind, Find2sub): Likewise. New tests. * utils.cc (dims_to_numel): Likewise. * ov-base-diag.cc (octave_base_diag<DMT, MT>::do_index_op, octave_base_diag<DMT, MT>::subsasgn): Likewise. * ov-base-mat.cc (octave_base_matrix<MT>::subsref, octave_base_matrix<MT>::assign): Likewise. * ov-base-sparse.cc (octave_base_sparse<T>::do_index_op, octave_base_sparse<T>::assign, octave_base_sparse<MT>::delete_elements): Likewise. * ov-classdef.cc (cdef_object_array::subsref, cdef_object_array::subsasgn): Likewise. * ov-java.cc (make_java_index): Likewise. * ov-perm.cc (octave_perm_matrix::do_index_op): Likewise. * ov-range.cc (octave_range::do_index_op): Likewise. * ov-re-diag.cc (octave_diag_matrix::do_index_op): Likewise. * ov-str-mat.cc (octave_char_matrix_str::do_index_op_internal): Likewise. * pt-assign.cc (tree_simple_assignment::rvalue1): Likewise. * pt-idx.cc (tree_index_expression::rvalue, tree_index_expression::lvalue): Likewise. * Array-util.cc (sub2ind): Likewise. * toplev.cc (main_loop): Also catch unhandled index_exception exceptions. * ov-base.cc (octave_base_value::index_vector): Improve error message. * ov-re-sparse.cc (octave_sparse_matrix::index_vector): Likewise. * ov-complex.cc (complex_index): New class. (gripe_complex_index): New function. (octave_complex::index_vector): Use it. * pt-id.h, pt-id.cc (tree_identifier::is_variable, tree_black_hole::is_variable): Now const. * pt-idx.cc (final_index_error): New static function. (tree_index_expression::rvalue, tree_index_expression::lvalue): Use it. * index.tst: New tests.
author Lachlan Andrew <lachlanbis@gmail.com>
date Fri, 02 Oct 2015 15:07:37 -0400
parents 41d19a6ef55a
children
comparison
equal deleted inserted replaced
20573:e3c0fee87493 20574:dd6345fd8a97
188 T& 188 T&
189 Array<T>::checkelem (octave_idx_type n) 189 Array<T>::checkelem (octave_idx_type n)
190 { 190 {
191 // Do checks directly to avoid recomputing slice_len. 191 // Do checks directly to avoid recomputing slice_len.
192 if (n < 0) 192 if (n < 0)
193 gripe_invalid_index (); 193 gripe_invalid_index (n);
194 if (n >= slice_len) 194 if (n >= slice_len)
195 gripe_index_out_of_range (1, 1, n+1, slice_len); 195 gripe_index_out_of_range (1, 1, n+1, slice_len, dimensions);
196 196
197 return elem (n); 197 return elem (n);
198 } 198 }
199 199
200 template <class T> 200 template <class T>
222 typename Array<T>::crefT 222 typename Array<T>::crefT
223 Array<T>::checkelem (octave_idx_type n) const 223 Array<T>::checkelem (octave_idx_type n) const
224 { 224 {
225 // Do checks directly to avoid recomputing slice_len. 225 // Do checks directly to avoid recomputing slice_len.
226 if (n < 0) 226 if (n < 0)
227 gripe_invalid_index (); 227 gripe_invalid_index (n);
228 if (n >= slice_len) 228 if (n >= slice_len)
229 gripe_index_out_of_range (1, 1, n+1, slice_len); 229 gripe_index_out_of_range (1, 1, n+1, slice_len, dimensions);
230 230
231 return elem (n); 231 return elem (n);
232 } 232 }
233 233
234 template <class T> 234 template <class T>
258 Array<T>::column (octave_idx_type k) const 258 Array<T>::column (octave_idx_type k) const
259 { 259 {
260 octave_idx_type r = dimensions(0); 260 octave_idx_type r = dimensions(0);
261 #ifdef BOUNDS_CHECKING 261 #ifdef BOUNDS_CHECKING
262 if (k < 0 || k > dimensions.numel (1)) 262 if (k < 0 || k > dimensions.numel (1))
263 gripe_index_out_of_range (2, 2, k+1, dimensions.numel (1)); 263 gripe_index_out_of_range (2, 2, k+1, dimensions.numel (1), dimensions);
264 #endif 264 #endif
265 265
266 return Array<T> (*this, dim_vector (r, 1), k*r, k*r + r); 266 return Array<T> (*this, dim_vector (r, 1), k*r, k*r + r);
267 } 267 }
268 268
273 octave_idx_type r = dimensions(0); 273 octave_idx_type r = dimensions(0);
274 octave_idx_type c = dimensions(1); 274 octave_idx_type c = dimensions(1);
275 octave_idx_type p = r*c; 275 octave_idx_type p = r*c;
276 #ifdef BOUNDS_CHECKING 276 #ifdef BOUNDS_CHECKING
277 if (k < 0 || k > dimensions.numel (2)) 277 if (k < 0 || k > dimensions.numel (2))
278 gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2)); 278 gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2), dimensions);
279 #endif 279 #endif
280 280
281 return Array<T> (*this, dim_vector (r, c), k*p, k*p + p); 281 return Array<T> (*this, dim_vector (r, c), k*p, k*p + p);
282 } 282 }
283 283
285 Array<T> 285 Array<T>
286 Array<T>::linear_slice (octave_idx_type lo, octave_idx_type up) const 286 Array<T>::linear_slice (octave_idx_type lo, octave_idx_type up) const
287 { 287 {
288 #ifdef BOUNDS_CHECKING 288 #ifdef BOUNDS_CHECKING
289 if (lo < 0) 289 if (lo < 0)
290 gripe_index_out_of_range (1, 1, lo+1, numel ()); 290 gripe_index_out_of_range (1, 1, lo+1, numel (), dimensions);
291 if (up > numel ()) 291 if (up > numel ())
292 gripe_index_out_of_range (1, 1, up, numel ()); 292 gripe_index_out_of_range (1, 1, up, numel (), dimensions);
293 #endif 293 #endif
294 if (up < lo) up = lo; 294 if (up < lo) up = lo;
295 return Array<T> (*this, dim_vector (up - lo, 1), lo, up); 295 return Array<T> (*this, dim_vector (up - lo, 1), lo, up);
296 } 296 }
297 297
724 retval = Array<T> (*this, dim_vector (n, 1)); 724 retval = Array<T> (*this, dim_vector (n, 1));
725 } 725 }
726 else 726 else
727 { 727 {
728 if (i.extent (n) != n) 728 if (i.extent (n) != n)
729 gripe_index_out_of_range (1, 1, i.extent (n), n); // throws 729 gripe_index_out_of_range (1, 1, i.extent (n), n, dimensions); // throws
730 730
731 // FIXME: this is the only place where orig_dimensions are used. 731 // FIXME: this is the only place where orig_dimensions are used.
732 dim_vector rd = i.orig_dimensions (); 732 dim_vector rd = i.orig_dimensions ();
733 octave_idx_type il = i.length (n); 733 octave_idx_type il = i.length (n);
734 734
791 retval = Array<T> (*this, dv); 791 retval = Array<T> (*this, dv);
792 } 792 }
793 else 793 else
794 { 794 {
795 if (i.extent (r) != r) 795 if (i.extent (r) != r)
796 gripe_index_out_of_range (2, 1, i.extent (r), r); // throws 796 gripe_index_out_of_range (2, 1, i.extent (r), r, dimensions); // throws
797 if (j.extent (c) != c) 797 if (j.extent (c) != c)
798 gripe_index_out_of_range (2, 2, j.extent (c), c); // throws 798 gripe_index_out_of_range (2, 2, j.extent (c), c, dimensions); // throws
799 799
800 octave_idx_type n = numel (); 800 octave_idx_type n = numel ();
801 octave_idx_type il = i.length (r); 801 octave_idx_type il = i.length (r);
802 octave_idx_type jl = j.length (c); 802 octave_idx_type jl = j.length (c);
803 803
853 // Check for out of bounds conditions. 853 // Check for out of bounds conditions.
854 bool all_colons = true; 854 bool all_colons = true;
855 for (int i = 0; i < ial; i++) 855 for (int i = 0; i < ial; i++)
856 { 856 {
857 if (ia(i).extent (dv(i)) != dv(i)) 857 if (ia(i).extent (dv(i)) != dv(i))
858 gripe_index_out_of_range (ial, i+1, ia(i).extent (dv(i)), dv(i)); // throws 858 gripe_index_out_of_range (ial, i+1, ia(i).extent (dv(i)), dv(i), dimensions); // throws
859 859
860 all_colons = all_colons && ia(i).is_colon (); 860 all_colons = all_colons && ia(i).is_colon ();
861 } 861 }
862 862
863 863
1178 else 1178 else
1179 i.assign (rhs.data (), n, fortran_vec ()); 1179 i.assign (rhs.data (), n, fortran_vec ());
1180 } 1180 }
1181 } 1181 }
1182 else 1182 else
1183 gripe_invalid_assignment_size (); 1183 gripe_nonconformant ("=", dim_vector(i.length(n),1), rhs.dims());
1184 } 1184 }
1185 1185
1186 // Assignment to a 2-dimensional array 1186 // Assignment to a 2-dimensional array
1187 template <class T> 1187 template <class T>
1188 void 1188 void
1282 } 1282 }
1283 } 1283 }
1284 } 1284 }
1285 // any empty RHS can be assigned to an empty LHS 1285 // any empty RHS can be assigned to an empty LHS
1286 else if ((il != 0 && jl != 0) || (rhdv(0) != 0 && rhdv(1) != 0)) 1286 else if ((il != 0 && jl != 0) || (rhdv(0) != 0 && rhdv(1) != 0))
1287 gripe_assignment_dimension_mismatch (); 1287 gripe_nonconformant ("=", il, jl, rhs.dim1 (), rhs.dim2 ());
1288 } 1288 }
1289 1289
1290 // Assignment to a multi-dimensional array 1290 // Assignment to a multi-dimensional array
1291 template <class T> 1291 template <class T>
1292 void 1292 void
1396 octave_idx_type l = ia(i).length (rdv(i)); 1396 octave_idx_type l = ia(i).length (rdv(i));
1397 lhsempty = lhsempty || (l == 0); 1397 lhsempty = lhsempty || (l == 0);
1398 rhsempty = rhsempty || (rhdv(j++) == 0); 1398 rhsempty = rhsempty || (rhdv(j++) == 0);
1399 } 1399 }
1400 if (! lhsempty || ! rhsempty) 1400 if (! lhsempty || ! rhsempty)
1401 gripe_assignment_dimension_mismatch (); 1401 gripe_nonconformant ("=", dv, rhdv);
1402 } 1402 }
1403 } 1403 }
1404 } 1404 }
1405
1406 /*
1407 %!shared a
1408 %! a = [1 2; 3 4];
1409 %!error <op1 is 1x2, op2 is 1x3> a(1,:) = [1 2 3]
1410 %!error <op1 is 2x1, op2 is 1x3> a(:,1) = [1 2 3]
1411 %!error <op1 is 2x2, op2 is 2x1> a(1:2,2:3) = [1;2]
1412 */
1405 1413
1406 template <class T> 1414 template <class T>
1407 void 1415 void
1408 Array<T>::delete_elements (const idx_vector& i) 1416 Array<T>::delete_elements (const idx_vector& i)
1409 { 1417 {