comparison libinterp/octave-value/ov-base-sparse.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 c6224b4e7774
children f90c8372b7ba
comparison
equal deleted inserted replaced
20573:e3c0fee87493 20574:dd6345fd8a97
42 #include "boolSparse.h" 42 #include "boolSparse.h"
43 #include "ov-base-sparse.h" 43 #include "ov-base-sparse.h"
44 #include "pager.h" 44 #include "pager.h"
45 #include "utils.h" 45 #include "utils.h"
46 46
47 #include "lo-array-gripes.h"
48
47 template <class T> 49 template <class T>
48 octave_value 50 octave_value
49 octave_base_sparse<T>::do_index_op (const octave_value_list& idx, 51 octave_base_sparse<T>::do_index_op (const octave_value_list& idx,
50 bool resize_ok) 52 bool resize_ok)
51 { 53 {
52 octave_value retval; 54 octave_value retval;
53 55
54 octave_idx_type n_idx = idx.length (); 56 octave_idx_type n_idx = idx.length ();
55 57
56 switch (n_idx) 58 // If we catch an indexing error in index_vector, we flag an error in
57 { 59 // index k. Ensure it is the right value befor each idx_vector call.
58 case 0: 60 // Same variable as used in the for loop in the default case.
59 retval = matrix; 61
60 break; 62 octave_idx_type k = 0;
61 63
62 case 1: 64 try
63 { 65 {
64 idx_vector i = idx (0).index_vector (); 66 switch (n_idx)
65 67 {
66 if (! error_state) 68 case 0:
67 retval = octave_value (matrix.index (i, resize_ok)); 69 retval = matrix;
68 } 70 break;
69 break; 71
70 72 case 1:
71 case 2: 73 {
72 { 74 idx_vector i = idx (0).index_vector ();
73 idx_vector i = idx (0).index_vector ();
74
75 if (! error_state)
76 {
77 idx_vector j = idx (1).index_vector ();
78 75
79 if (! error_state) 76 if (! error_state)
80 retval = octave_value (matrix.index (i, j, resize_ok)); 77 retval = octave_value (matrix.index (i, resize_ok));
81 } 78 }
82 } 79 break;
83 break; 80
84 default: 81 case 2:
85 error ("sparse indexing needs 1 or 2 indices"); 82 {
83 idx_vector i = idx (0).index_vector ();
84
85 if (! error_state)
86 {
87 k = 1;
88 idx_vector j = idx (1).index_vector ();
89
90 if (! error_state)
91 retval = octave_value (matrix.index (i, j, resize_ok));
92 }
93 }
94 break;
95 default:
96 error ("sparse indexing needs 1 or 2 indices");
97 }
98 }
99 catch (index_exception& e)
100 {
101 // Rethrow to allow more info to be reported later.
102 e.set_pos_if_unset (n_idx, k+1);
103 throw;
86 } 104 }
87 105
88 return retval; 106 return retval;
89 } 107 }
90 108
168 octave_base_sparse<T>::assign (const octave_value_list& idx, const T& rhs) 186 octave_base_sparse<T>::assign (const octave_value_list& idx, const T& rhs)
169 { 187 {
170 188
171 octave_idx_type len = idx.length (); 189 octave_idx_type len = idx.length ();
172 190
173 switch (len) 191 // If we catch an indexing error in index_vector, we flag an error in
174 { 192 // index k. Ensure it is the right value befor each idx_vector call.
175 case 1: 193 // Same variable as used in the for loop in the default case.
176 { 194
177 idx_vector i = idx (0).index_vector (); 195 octave_idx_type k = 0;
178 196
179 if (! error_state) 197 try
180 matrix.assign (i, rhs); 198 {
181 199 switch (len)
182 break; 200 {
183 } 201 case 1:
184 202 {
185 case 2: 203 idx_vector i = idx (0).index_vector ();
186 {
187 idx_vector i = idx (0).index_vector ();
188
189 if (! error_state)
190 {
191 idx_vector j = idx (1).index_vector ();
192 204
193 if (! error_state) 205 if (! error_state)
194 matrix.assign (i, j, rhs); 206 matrix.assign (i, rhs);
195 } 207
196 208 break;
197 break; 209 }
198 } 210
199 211 case 2:
200 default: 212 {
201 error ("sparse indexing needs 1 or 2 indices"); 213 idx_vector i = idx (0).index_vector ();
214
215 if (! error_state)
216 {
217 k = 1;
218 idx_vector j = idx (1).index_vector ();
219
220 if (! error_state)
221 matrix.assign (i, j, rhs);
222 }
223 break;
224 }
225
226 default:
227 error ("sparse indexing needs 1 or 2 indices");
228 }
229 }
230 catch (index_exception& e)
231 {
232 // Rethrow to allow more info to be reported later.
233 e.set_pos_if_unset (len, k+1);
234 throw;
202 } 235 }
203 236
204 237
205 // Invalidate matrix type. 238 // Invalidate matrix type.
206 typ.invalidate_type (); 239 typ.invalidate_type ();
210 void 243 void
211 octave_base_sparse<MT>::delete_elements (const octave_value_list& idx) 244 octave_base_sparse<MT>::delete_elements (const octave_value_list& idx)
212 { 245 {
213 octave_idx_type len = idx.length (); 246 octave_idx_type len = idx.length ();
214 247
215 switch (len) 248 // If we catch an indexing error in index_vector, we flag an error in
216 { 249 // index k. Ensure it is the right value befor each idx_vector call.
217 case 1: 250 // Same variable as used in the for loop in the default case.
218 { 251
219 idx_vector i = idx (0).index_vector (); 252 octave_idx_type k = 0;
220 253
221 if (! error_state) 254 try
222 matrix.delete_elements (i); 255 {
223 256 switch (len)
224 break; 257 {
225 } 258 case 1:
226 259 {
227 case 2: 260 idx_vector i = idx (0).index_vector ();
228 {
229 idx_vector i = idx (0).index_vector ();
230
231 if (! error_state)
232 {
233 idx_vector j = idx (1).index_vector ();
234 261
235 if (! error_state) 262 if (! error_state)
236 matrix.delete_elements (i, j); 263 matrix.delete_elements (i);
237 } 264
238 265 break;
239 break; 266 }
240 } 267
241 268 case 2:
242 default: 269 {
243 error ("sparse indexing needs 1 or 2 indices"); 270 idx_vector i = idx (0).index_vector ();
271
272 if (! error_state)
273 {
274 k = 1;
275 idx_vector j = idx (1).index_vector ();
276
277 if (! error_state)
278 matrix.delete_elements (i, j);
279 }
280
281 break;
282 }
283
284 default:
285 error ("sparse indexing needs 1 or 2 indices");
286 }
287 }
288 catch (index_exception& e)
289 {
290 // Rethrow to allow more info to be reported later.
291 e.set_pos_if_unset (len, k+1);
292 throw;
244 } 293 }
245 294
246 // Invalidate the matrix type 295 // Invalidate the matrix type
247 typ.invalidate_type (); 296 typ.invalidate_type ();
248 } 297 }