comparison liboctave/array/Array-util.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
176 176
177 octave_idx_type 177 octave_idx_type
178 compute_index (octave_idx_type n, const dim_vector& dims) 178 compute_index (octave_idx_type n, const dim_vector& dims)
179 { 179 {
180 if (n < 0) 180 if (n < 0)
181 gripe_invalid_index (); 181 gripe_invalid_index (n, 1, 1);
182 if (n >= dims.numel ()) 182 if (n >= dims.numel ())
183 gripe_index_out_of_range (1, 1, n+1, dims.numel ()); 183 gripe_index_out_of_range (1, 1, n+1, dims.numel (), dims);
184 184
185 return n; 185 return n;
186 } 186 }
187 187
188 octave_idx_type 188 octave_idx_type
189 compute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims) 189 compute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims)
190 { 190 {
191 if (i < 0 || j < 0) 191 if (i < 0)
192 gripe_invalid_index (); 192 gripe_invalid_index (i, 2, 1);
193 else if (j < 0)
194 gripe_invalid_index (j, 2, 2);
193 if (i >= dims(0)) 195 if (i >= dims(0))
194 gripe_index_out_of_range (2, 1, i+1, dims(0)); 196 gripe_index_out_of_range (2, 1, i+1, dims(0), dims);
195 if (j >= dims.numel (1)) 197 if (j >= dims.numel (1))
196 gripe_index_out_of_range (2, 2, j+1, dims.numel (1)); 198 gripe_index_out_of_range (2, 2, j+1, dims.numel (1), dims);
197 199
198 return j*dims(0) + i; 200 return j*dims(0) + i;
199 } 201 }
200 202
201 octave_idx_type 203 octave_idx_type
202 compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k, 204 compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k,
203 const dim_vector& dims) 205 const dim_vector& dims)
204 { 206 {
205 if (i < 0 || j < 0 || k < 0) 207 if (i < 0)
206 gripe_invalid_index (); 208 gripe_invalid_index (i, 3, 1);
209 else if (j < 0)
210 gripe_invalid_index (j, 3, 2);
211 else if (k < 0)
212 gripe_invalid_index (k, 3, 3);
207 if (i >= dims(0)) 213 if (i >= dims(0))
208 gripe_index_out_of_range (3, 1, i+1, dims(0)); 214 gripe_index_out_of_range (3, 1, i+1, dims(0), dims);
209 if (j >= dims(1)) 215 if (j >= dims(1))
210 gripe_index_out_of_range (3, 2, j+1, dims(1)); 216 gripe_index_out_of_range (3, 2, j+1, dims(1), dims);
211 if (k >= dims.numel (2)) 217 if (k >= dims.numel (2))
212 gripe_index_out_of_range (3, 3, k+1, dims.numel (2)); 218 gripe_index_out_of_range (3, 3, k+1, dims.numel (2), dims);
213 219
214 return (k*dims(1) + j)*dims(0) + i; 220 return (k*dims(1) + j)*dims(0) + i;
215 } 221 }
216 222
217 octave_idx_type 223 octave_idx_type
220 int nd = ra_idx.numel (); 226 int nd = ra_idx.numel ();
221 const dim_vector dv = dims.redim (nd); 227 const dim_vector dv = dims.redim (nd);
222 for (int d = 0; d < nd; d++) 228 for (int d = 0; d < nd; d++)
223 { 229 {
224 if (ra_idx(d) < 0) 230 if (ra_idx(d) < 0)
225 gripe_invalid_index (); 231 gripe_invalid_index (ra_idx(d), nd, d+1);
226 if (ra_idx(d) >= dv(d)) 232 if (ra_idx(d) >= dv(d))
227 gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d)); 233 gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d), dims);
228 } 234 }
229 235
230 return dv.compute_index (ra_idx.data ()); 236 return dv.compute_index (ra_idx.data ());
231 } 237 }
232 238
538 bool all_ranges = true; 544 bool all_ranges = true;
539 octave_idx_type clen = -1; 545 octave_idx_type clen = -1;
540 546
541 for (octave_idx_type i = 0; i < len; i++) 547 for (octave_idx_type i = 0; i < len; i++)
542 { 548 {
543 idx_vector idx = idxa(i); 549 try
544 octave_idx_type n = dvx(i); 550 {
545 551 idx_vector idx = idxa(i);
546 all_ranges = all_ranges && idx.is_range (); 552 octave_idx_type n = dvx(i);
547 if (clen < 0) 553
548 clen = idx.length (n); 554 all_ranges = all_ranges && idx.is_range ();
549 else if (clen != idx.length (n)) 555 if (clen < 0)
550 current_liboctave_error_handler ("sub2ind: lengths of indices must match"); 556 clen = idx.length (n);
551 557 else if (clen != idx.length (n))
552 if (idx.extent (n) > n) 558 current_liboctave_error_handler ("sub2ind: lengths of indices must match");
553 current_liboctave_error_handler ("sub2ind: index out of range"); 559
554 } 560 if (idx.extent (n) > n)
561 gripe_index_out_of_range (len, i+1, idx.extent (n), n);
562 }
563 catch (index_exception& e)
564 {
565 e.set_pos_if_unset (len, i+1);
566 e.set_var (""); // no particular variable
567 (*current_liboctave_error_with_id_handler) (e.id(), e.err());
568 }
569 }
570 // idxa known to be valid. Shouldn't need to catch index_exception below here.
571
555 572
556 if (len == 1) 573 if (len == 1)
557 retval = idxa(0); 574 retval = idxa(0);
558 else if (clen == 1) 575 else if (clen == 1)
559 { 576 {