Mercurial > octave-nkf
comparison liboctave/array/idx-vector.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 | a9574e3c6e9e |
children |
comparison
equal
deleted
inserted
replaced
20573:e3c0fee87493 | 20574:dd6345fd8a97 |
---|---|
111 if (len < 0) | 111 if (len < 0) |
112 { | 112 { |
113 gripe_invalid_range (); | 113 gripe_invalid_range (); |
114 err = true; | 114 err = true; |
115 } | 115 } |
116 else if (start < 0 || (step < 0 && start + (len-1)*step < 0)) | 116 else if (start < 0) |
117 { | 117 { |
118 gripe_invalid_index (); | 118 gripe_invalid_index (start); |
119 err = true; | |
120 } | |
121 else if (step < 0 && start + (len-1)*step < 0) | |
122 { | |
123 gripe_invalid_index (start + (len-1)*step); | |
119 err = true; | 124 err = true; |
120 } | 125 } |
121 } | 126 } |
122 | 127 |
123 idx_vector::idx_range_rep::idx_range_rep (const Range& r) | 128 idx_vector::idx_range_rep::idx_range_rep (const Range& r) |
132 { | 137 { |
133 if (r.all_elements_are_ints ()) | 138 if (r.all_elements_are_ints ()) |
134 { | 139 { |
135 start = static_cast<octave_idx_type> (r.base ()) - 1; | 140 start = static_cast<octave_idx_type> (r.base ()) - 1; |
136 step = static_cast<octave_idx_type> (r.inc ()); | 141 step = static_cast<octave_idx_type> (r.inc ()); |
137 if (start < 0 || (step < 0 && start + (len-1)*step < 0)) | 142 if (start < 0) |
138 { | 143 { |
139 gripe_invalid_index (); | 144 gripe_invalid_index (start); |
145 err = true; | |
146 } | |
147 else if (step < 0 && start + (len-1)*step < 0) | |
148 { | |
149 gripe_invalid_index (start + (len-1)*step); | |
140 err = true; | 150 err = true; |
141 } | 151 } |
142 } | 152 } |
143 else | 153 else |
144 { | 154 { |
145 gripe_invalid_index (); | 155 // find first non-integer, then gripe about it |
156 double b = r.base(); | |
157 double inc = r.inc(); | |
158 gripe_invalid_index (b != floor(b) ? b : b+inc); | |
146 err = true; | 159 err = true; |
147 } | 160 } |
148 } | 161 } |
149 } | 162 } |
150 | 163 |
219 inline octave_idx_type | 232 inline octave_idx_type |
220 convert_index (octave_idx_type i, bool& conv_error, | 233 convert_index (octave_idx_type i, bool& conv_error, |
221 octave_idx_type& ext) | 234 octave_idx_type& ext) |
222 { | 235 { |
223 if (i <= 0) | 236 if (i <= 0) |
224 conv_error = true; | 237 { |
238 if (!conv_error) // only gripe once, for things like A(-10000:0) | |
239 gripe_invalid_index (i-1); | |
240 conv_error = true; | |
241 } | |
225 | 242 |
226 if (ext < i) | 243 if (ext < i) |
227 ext = i; | 244 ext = i; |
228 | 245 |
229 return i - 1; | 246 return i - 1; |
233 convert_index (double x, bool& conv_error, octave_idx_type& ext) | 250 convert_index (double x, bool& conv_error, octave_idx_type& ext) |
234 { | 251 { |
235 octave_idx_type i = static_cast<octave_idx_type> (x); | 252 octave_idx_type i = static_cast<octave_idx_type> (x); |
236 | 253 |
237 if (static_cast<double> (i) != x) | 254 if (static_cast<double> (i) != x) |
238 conv_error = true; | 255 { |
256 gripe_invalid_index (x-1); | |
257 conv_error = true; | |
258 } | |
239 | 259 |
240 return convert_index (i, conv_error, ext); | 260 return convert_index (i, conv_error, ext); |
241 } | 261 } |
242 | 262 |
243 inline octave_idx_type | 263 inline octave_idx_type |
262 : data (0) | 282 : data (0) |
263 { | 283 { |
264 octave_idx_type dummy = 0; | 284 octave_idx_type dummy = 0; |
265 | 285 |
266 data = convert_index (x, err, dummy); | 286 data = convert_index (x, err, dummy); |
267 | |
268 if (err) | |
269 gripe_invalid_index (); | |
270 } | 287 } |
271 | 288 |
272 idx_vector::idx_scalar_rep::idx_scalar_rep (octave_idx_type i) | 289 idx_vector::idx_scalar_rep::idx_scalar_rep (octave_idx_type i) |
273 : data (i) | 290 : data (i) |
274 { | 291 { |
275 if (data < 0) | 292 if (data < 0) |
276 { | 293 { |
277 gripe_invalid_index (); | 294 gripe_invalid_index (data); |
278 err = true; | 295 err = true; |
279 } | 296 } |
280 } | 297 } |
281 | 298 |
282 octave_idx_type | 299 octave_idx_type |
325 for (octave_idx_type i = 0; i < len; i++) | 342 for (octave_idx_type i = 0; i < len; i++) |
326 d[i] = convert_index (nda.xelem (i), err, ext); | 343 d[i] = convert_index (nda.xelem (i), err, ext); |
327 data = d; | 344 data = d; |
328 | 345 |
329 if (err) | 346 if (err) |
330 { | 347 delete [] data; |
331 delete [] data; | |
332 gripe_invalid_index (); | |
333 } | |
334 } | 348 } |
335 } | 349 } |
336 | 350 |
337 // Note that this makes a shallow copy of the index array. | 351 // Note that this makes a shallow copy of the index array. |
338 | 352 |
345 octave_idx_type max = -1; | 359 octave_idx_type max = -1; |
346 for (octave_idx_type i = 0; i < len; i++) | 360 for (octave_idx_type i = 0; i < len; i++) |
347 { | 361 { |
348 octave_idx_type k = inda.xelem (i); | 362 octave_idx_type k = inda.xelem (i); |
349 if (k < 0) | 363 if (k < 0) |
350 err = true; | 364 { |
365 if (!err) // only report first error, in case 1000s. | |
366 gripe_invalid_index (k); | |
367 err = true; | |
368 } | |
351 else if (k > max) | 369 else if (k > max) |
352 max = k; | 370 max = k; |
353 } | 371 } |
354 | 372 |
355 ext = max + 1; | 373 ext = max + 1; |
356 | |
357 if (err) | |
358 gripe_invalid_index (); | |
359 } | 374 } |
360 } | 375 } |
361 | 376 |
362 idx_vector::idx_vector_rep::idx_vector_rep (const Array<octave_idx_type>& inda, | 377 idx_vector::idx_vector_rep::idx_vector_rep (const Array<octave_idx_type>& inda, |
363 octave_idx_type _ext, direct) | 378 octave_idx_type _ext, direct) |
457 octave_idx_type | 472 octave_idx_type |
458 idx_vector::idx_vector_rep::checkelem (octave_idx_type n) const | 473 idx_vector::idx_vector_rep::checkelem (octave_idx_type n) const |
459 { | 474 { |
460 if (n < 0 || n >= len) | 475 if (n < 0 || n >= len) |
461 { | 476 { |
462 gripe_invalid_index (); | 477 gripe_invalid_index (n); |
463 return 0; | 478 return 0; |
464 } | 479 } |
465 | 480 |
466 return xelem (n); | 481 return xelem (n); |
467 } | 482 } |
707 octave_idx_type | 722 octave_idx_type |
708 idx_vector::idx_mask_rep::checkelem (octave_idx_type n) const | 723 idx_vector::idx_mask_rep::checkelem (octave_idx_type n) const |
709 { | 724 { |
710 if (n < 0 || n >= len) | 725 if (n < 0 || n >= len) |
711 { | 726 { |
712 gripe_invalid_index (); | 727 gripe_invalid_index (n); |
713 return 0; | 728 return 0; |
714 } | 729 } |
715 | 730 |
716 return xelem (n); | 731 return xelem (n); |
717 } | 732 } |