Mercurial > octave-nkf
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 { |