Mercurial > octave-nkf
comparison libinterp/octave-value/ov-base-mat.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 | b2100e1659ac |
children | 1a0a433c8263 |
comparison
equal
deleted
inserted
replaced
20573:e3c0fee87493 | 20574:dd6345fd8a97 |
---|---|
34 #include "oct-map.h" | 34 #include "oct-map.h" |
35 #include "ov-base.h" | 35 #include "ov-base.h" |
36 #include "ov-base-mat.h" | 36 #include "ov-base-mat.h" |
37 #include "ov-base-scalar.h" | 37 #include "ov-base-scalar.h" |
38 #include "pr-output.h" | 38 #include "pr-output.h" |
39 | 39 |
40 template <class MT> | 40 template <class MT> |
41 octave_value | 41 octave_value |
42 octave_base_matrix<MT>::subsref (const std::string& type, | 42 octave_base_matrix<MT>::subsref (const std::string& type, |
43 const std::list<octave_value_list>& idx) | 43 const std::list<octave_value_list>& idx) |
44 { | 44 { |
138 octave_idx_type n_idx = idx.length (); | 138 octave_idx_type n_idx = idx.length (); |
139 | 139 |
140 int nd = matrix.ndims (); | 140 int nd = matrix.ndims (); |
141 const MT& cmatrix = matrix; | 141 const MT& cmatrix = matrix; |
142 | 142 |
143 switch (n_idx) | 143 // If we catch an indexing error in index_vector, we flag an error in |
144 { | 144 // index k. Ensure it is the right value befor each idx_vector call. |
145 case 0: | 145 // Same variable as used in the for loop in the default case. |
146 retval = matrix; | 146 |
147 break; | 147 octave_idx_type k = 0; |
148 | 148 |
149 case 1: | 149 try |
150 { | 150 { |
151 idx_vector i = idx (0).index_vector (); | 151 switch (n_idx) |
152 | 152 { |
153 if (! error_state) | 153 case 0: |
154 { | 154 retval = matrix; |
155 // optimize single scalar index. | 155 break; |
156 if (! resize_ok && i.is_scalar ()) | 156 |
157 retval = cmatrix.checkelem (i(0)); | 157 case 1: |
158 else | 158 { |
159 retval = MT (matrix.index (i, resize_ok)); | 159 idx_vector i = idx (0).index_vector (); |
160 } | |
161 } | |
162 break; | |
163 | |
164 case 2: | |
165 { | |
166 idx_vector i = idx (0).index_vector (); | |
167 | |
168 if (! error_state) | |
169 { | |
170 idx_vector j = idx (1).index_vector (); | |
171 | 160 |
172 if (! error_state) | 161 if (! error_state) |
173 { | 162 { |
174 // optimize two scalar indices. | 163 // optimize single scalar index. |
175 if (! resize_ok && i.is_scalar () && j.is_scalar ()) | 164 if (! resize_ok && i.is_scalar ()) |
176 retval = cmatrix.checkelem (i(0), j(0)); | 165 retval = cmatrix.checkelem (i(0)); |
177 else | 166 else |
178 retval = MT (matrix.index (i, j, resize_ok)); | 167 retval = MT (matrix.index (i, resize_ok)); |
179 } | 168 } |
180 } | 169 } |
181 } | 170 break; |
182 break; | 171 |
183 | 172 case 2: |
184 default: | 173 { |
185 { | 174 idx_vector i = idx (0).index_vector (); |
186 Array<idx_vector> idx_vec (dim_vector (n_idx, 1)); | 175 |
187 bool scalar_opt = n_idx == nd && ! resize_ok; | 176 if (! error_state) |
188 const dim_vector dv = matrix.dims (); | 177 { |
189 | 178 k=1; |
190 for (octave_idx_type i = 0; i < n_idx; i++) | 179 idx_vector j = idx (1).index_vector (); |
191 { | 180 |
192 idx_vec(i) = idx(i).index_vector (); | 181 if (! error_state) |
193 | 182 { |
194 if (error_state) | 183 // optimize two scalar indices. |
195 break; | 184 if (! resize_ok && i.is_scalar () && j.is_scalar ()) |
196 | 185 retval = cmatrix.checkelem (i(0), j(0)); |
197 scalar_opt = (scalar_opt && idx_vec(i).is_scalar ()); | 186 else |
198 } | 187 retval = MT (matrix.index (i, j, resize_ok)); |
199 | 188 } |
200 if (! error_state) | 189 } |
201 { | 190 } |
202 if (scalar_opt) | 191 break; |
203 retval = cmatrix.checkelem (conv_to_int_array (idx_vec)); | 192 |
204 else | 193 default: |
205 retval = MT (matrix.index (idx_vec, resize_ok)); | 194 { |
206 } | 195 Array<idx_vector> idx_vec (dim_vector (n_idx, 1)); |
207 } | 196 bool scalar_opt = n_idx == nd && ! resize_ok; |
208 break; | 197 const dim_vector dv = matrix.dims (); |
198 | |
199 for (k = 0; k < n_idx; k++) | |
200 { | |
201 idx_vec(k) = idx(k).index_vector (); | |
202 | |
203 if (error_state) | |
204 break; | |
205 | |
206 scalar_opt = (scalar_opt && idx_vec(k).is_scalar ()); | |
207 } | |
208 | |
209 if (! error_state) | |
210 { | |
211 if (scalar_opt) | |
212 retval = cmatrix.checkelem (conv_to_int_array (idx_vec)); | |
213 else | |
214 retval = MT (matrix.index (idx_vec, resize_ok)); | |
215 } | |
216 } | |
217 break; | |
218 } | |
219 } | |
220 catch (index_exception& e) | |
221 { | |
222 // Rethrow to allow more info to be reported later. | |
223 e.set_pos_if_unset (n_idx, k+1); | |
224 throw; | |
209 } | 225 } |
210 | 226 |
211 return retval; | 227 return retval; |
212 } | 228 } |
213 | 229 |
215 void | 231 void |
216 octave_base_matrix<MT>::assign (const octave_value_list& idx, const MT& rhs) | 232 octave_base_matrix<MT>::assign (const octave_value_list& idx, const MT& rhs) |
217 { | 233 { |
218 octave_idx_type n_idx = idx.length (); | 234 octave_idx_type n_idx = idx.length (); |
219 | 235 |
220 switch (n_idx) | 236 // If we catch an indexing error in index_vector, we flag an error in |
221 { | 237 // index k. Ensure it is the right value befor each idx_vector call. |
222 case 0: | 238 // Same variable as used in the for loop in the default case. |
223 panic_impossible (); | 239 |
224 break; | 240 octave_idx_type k = 0; |
225 | 241 |
226 case 1: | 242 try |
227 { | 243 { |
228 idx_vector i = idx (0).index_vector (); | 244 switch (n_idx) |
229 | 245 { |
230 if (! error_state) | 246 case 0: |
231 matrix.assign (i, rhs); | 247 panic_impossible (); |
232 } | 248 break; |
233 break; | 249 |
234 | 250 case 1: |
235 case 2: | 251 { |
236 { | 252 idx_vector i = idx (0).index_vector (); |
237 idx_vector i = idx (0).index_vector (); | 253 |
238 | 254 if (! error_state) |
239 if (! error_state) | 255 matrix.assign (i, rhs); |
240 { | 256 } |
241 idx_vector j = idx (1).index_vector (); | 257 break; |
242 | 258 |
243 if (! error_state) | 259 case 2: |
244 matrix.assign (i, j, rhs); | 260 { |
245 } | 261 idx_vector i = idx (0).index_vector (); |
246 } | 262 |
247 break; | 263 if (! error_state) |
248 | 264 { |
249 default: | 265 k = 1; |
250 { | 266 idx_vector j = idx (1).index_vector (); |
251 Array<idx_vector> idx_vec (dim_vector (n_idx, 1)); | 267 |
252 | 268 if (! error_state) |
253 for (octave_idx_type i = 0; i < n_idx; i++) | 269 matrix.assign (i, j, rhs); |
254 { | 270 } |
255 idx_vec(i) = idx(i).index_vector (); | 271 } |
256 | 272 break; |
257 if (error_state) | 273 |
258 break; | 274 default: |
259 } | 275 { |
260 | 276 Array<idx_vector> idx_vec (dim_vector (n_idx, 1)); |
261 if (! error_state) | 277 |
262 matrix.assign (idx_vec, rhs); | 278 for (k = 0; k < n_idx; k++) |
263 } | 279 { |
264 break; | 280 idx_vec(k) = idx(k).index_vector (); |
281 | |
282 if (error_state) | |
283 break; | |
284 } | |
285 | |
286 if (! error_state) | |
287 matrix.assign (idx_vec, rhs); | |
288 } | |
289 break; | |
290 } | |
291 } | |
292 catch (index_exception& e) | |
293 { | |
294 gripe_invalid_index (e.idx(), n_idx, k+1); | |
265 } | 295 } |
266 | 296 |
267 // Clear cache. | 297 // Clear cache. |
268 clear_cached_info (); | 298 clear_cached_info (); |
269 } | 299 } |
286 | 316 |
287 int nd = matrix.ndims (); | 317 int nd = matrix.ndims (); |
288 | 318 |
289 MT mrhs (dim_vector (1, 1), rhs); | 319 MT mrhs (dim_vector (1, 1), rhs); |
290 | 320 |
291 switch (n_idx) | 321 // If we catch an indexing error in index_vector, we flag an error in |
292 { | 322 // index k. Ensure it is the right value befor each idx_vector call. |
293 case 0: | 323 // Same variable as used in the for loop in the default case. |
294 panic_impossible (); | 324 |
295 break; | 325 octave_idx_type k = 0; |
296 | 326 |
297 case 1: | 327 try |
298 { | 328 { |
299 idx_vector i = idx (0).index_vector (); | 329 switch (n_idx) |
300 | 330 { |
301 if (! error_state) | 331 case 0: |
302 { | 332 panic_impossible (); |
303 // optimize single scalar index. | 333 break; |
304 if (i.is_scalar () && i(0) < matrix.numel ()) | 334 |
305 matrix(i(0)) = rhs; | 335 case 1: |
306 else | 336 { |
307 matrix.assign (i, mrhs); | 337 idx_vector i = idx (0).index_vector (); |
308 } | |
309 } | |
310 break; | |
311 | |
312 case 2: | |
313 { | |
314 idx_vector i = idx (0).index_vector (); | |
315 | |
316 if (! error_state) | |
317 { | |
318 idx_vector j = idx (1).index_vector (); | |
319 | 338 |
320 if (! error_state) | 339 if (! error_state) |
321 { | 340 { |
322 // optimize two scalar indices. | 341 // optimize single scalar index. |
323 if (i.is_scalar () && j.is_scalar () && nd == 2 | 342 if (i.is_scalar () && i(0) < matrix.numel ()) |
324 && i(0) < matrix.rows () && j(0) < matrix.columns ()) | 343 matrix(i(0)) = rhs; |
325 matrix(i(0), j(0)) = rhs; | |
326 else | 344 else |
327 matrix.assign (i, j, mrhs); | 345 matrix.assign (i, mrhs); |
328 } | 346 } |
329 } | 347 } |
330 } | 348 break; |
331 break; | 349 |
332 | 350 case 2: |
333 default: | 351 { |
334 { | 352 idx_vector i = idx (0).index_vector (); |
335 Array<idx_vector> idx_vec (dim_vector (n_idx, 1)); | 353 |
336 bool scalar_opt = n_idx == nd; | 354 if (! error_state) |
337 const dim_vector dv = matrix.dims ().redim (n_idx); | 355 { |
338 | 356 k = 1; |
339 for (octave_idx_type i = 0; i < n_idx; i++) | 357 idx_vector j = idx (1).index_vector (); |
340 { | 358 |
341 idx_vec(i) = idx(i).index_vector (); | 359 if (! error_state) |
342 | |
343 if (error_state) | |
344 break; | |
345 | |
346 scalar_opt = (scalar_opt && idx_vec(i).is_scalar () | |
347 && idx_vec(i)(0) < dv(i)); | |
348 } | |
349 | |
350 if (! error_state) | |
351 { | |
352 if (scalar_opt) | |
353 { | |
354 // optimize all scalar indices. Don't construct an index array, | |
355 // but rather calc a scalar index directly. | |
356 octave_idx_type k = 1; | |
357 octave_idx_type j = 0; | |
358 for (octave_idx_type i = 0; i < n_idx; i++) | |
359 { | 360 { |
360 j += idx_vec(i)(0) * k; | 361 // optimize two scalar indices. |
361 k *= dv(i); | 362 if (i.is_scalar () && j.is_scalar () && nd == 2 |
363 && i(0) < matrix.rows () && j(0) < matrix.columns ()) | |
364 matrix(i(0), j(0)) = rhs; | |
365 else | |
366 matrix.assign (i, j, mrhs); | |
362 } | 367 } |
363 matrix(j) = rhs; | 368 } |
364 } | 369 } |
365 else | 370 break; |
366 matrix.assign (idx_vec, mrhs); | 371 |
367 } | 372 default: |
368 } | 373 { |
369 break; | 374 Array<idx_vector> idx_vec (dim_vector (n_idx, 1)); |
370 } | 375 bool scalar_opt = n_idx == nd; |
376 const dim_vector dv = matrix.dims ().redim (n_idx); | |
377 | |
378 for (k = 0; k < n_idx; k++) | |
379 { | |
380 idx_vec(k) = idx(k).index_vector (); | |
381 | |
382 if (error_state) | |
383 break; | |
384 | |
385 scalar_opt = (scalar_opt && idx_vec(k).is_scalar () | |
386 && idx_vec(k)(0) < dv(k)); | |
387 } | |
388 | |
389 if (! error_state) | |
390 { | |
391 if (scalar_opt) | |
392 { | |
393 // optimize all scalar indices. Don't construct | |
394 // an index array, but rather calc a scalar index directly. | |
395 octave_idx_type n = 1; | |
396 octave_idx_type j = 0; | |
397 for (octave_idx_type i = 0; i < n_idx; i++) | |
398 { | |
399 j += idx_vec(i)(0) * n; | |
400 n *= dv (i); | |
401 } | |
402 matrix(j) = rhs; | |
403 } | |
404 else | |
405 matrix.assign (idx_vec, mrhs); | |
406 } | |
407 } | |
408 break; | |
409 } | |
410 } | |
411 catch (const index_exception& e) | |
412 { | |
413 gripe_invalid_index (e.idx(), n_idx, k+1); | |
414 } | |
371 | 415 |
372 // Clear cache. | 416 // Clear cache. |
373 clear_cached_info (); | 417 clear_cached_info (); |
374 } | 418 } |
375 | 419 |