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 }