Mercurial > octave-nkf
comparison libinterp/corefcn/data.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 | 4bb41929286b |
children | a05a0432dff4 |
comparison
equal
deleted
inserted
replaced
20573:e3c0fee87493 | 20574:dd6345fd8a97 |
---|---|
7242 error ("nth_element: DIM must be a valid dimension"); | 7242 error ("nth_element: DIM must be a valid dimension"); |
7243 } | 7243 } |
7244 if (dim < 0) | 7244 if (dim < 0) |
7245 dim = argx.dims ().first_non_singleton (); | 7245 dim = argx.dims ().first_non_singleton (); |
7246 | 7246 |
7247 idx_vector n = args(1).index_vector (); | 7247 try |
7248 | 7248 { |
7249 if (error_state) | 7249 idx_vector n = args(1).index_vector (); |
7250 return retval; | 7250 |
7251 | 7251 if (error_state) |
7252 switch (argx.builtin_type ()) | 7252 return retval; |
7253 { | 7253 |
7254 case btyp_double: | 7254 switch (argx.builtin_type ()) |
7255 retval = argx.array_value ().nth_element (n, dim); | |
7256 break; | |
7257 case btyp_float: | |
7258 retval = argx.float_array_value ().nth_element (n, dim); | |
7259 break; | |
7260 case btyp_complex: | |
7261 retval = argx.complex_array_value ().nth_element (n, dim); | |
7262 break; | |
7263 case btyp_float_complex: | |
7264 retval = argx.float_complex_array_value ().nth_element (n, dim); | |
7265 break; | |
7266 #define MAKE_INT_BRANCH(X) \ | |
7267 case btyp_ ## X: \ | |
7268 retval = argx.X ## _array_value ().nth_element (n, dim); \ | |
7269 break; | |
7270 | |
7271 MAKE_INT_BRANCH (int8); | |
7272 MAKE_INT_BRANCH (int16); | |
7273 MAKE_INT_BRANCH (int32); | |
7274 MAKE_INT_BRANCH (int64); | |
7275 MAKE_INT_BRANCH (uint8); | |
7276 MAKE_INT_BRANCH (uint16); | |
7277 MAKE_INT_BRANCH (uint32); | |
7278 MAKE_INT_BRANCH (uint64); | |
7279 #undef MAKE_INT_BRANCH | |
7280 default: | |
7281 if (argx.is_cellstr ()) | |
7282 retval = argx.cellstr_value ().nth_element (n, dim); | |
7283 else | |
7284 gripe_wrong_type_arg ("nth_element", argx); | |
7285 } | |
7286 } | |
7287 else | |
7288 print_usage (); | |
7289 | |
7290 return retval; | |
7291 } | |
7292 | |
7293 template <class NDT> | |
7294 static NDT | |
7295 do_accumarray_sum (const idx_vector& idx, const NDT& vals, | |
7296 octave_idx_type n = -1) | |
7297 { | |
7298 typedef typename NDT::element_type T; | |
7299 if (n < 0) | |
7300 n = idx.extent (0); | |
7301 else if (idx.extent (n) > n) | |
7302 error ("accumarray: index out of range"); | |
7303 | |
7304 NDT retval (dim_vector (n, 1), T ()); | |
7305 | |
7306 if (vals.numel () == 1) | |
7307 retval.idx_add (idx, vals (0)); | |
7308 else if (vals.numel () == idx.length (n)) | |
7309 retval.idx_add (idx, vals); | |
7310 else | |
7311 error ("accumarray: dimensions mismatch"); | |
7312 | |
7313 return retval; | |
7314 } | |
7315 | |
7316 DEFUN (__accumarray_sum__, args, , | |
7317 "-*- texinfo -*-\n\ | |
7318 @deftypefn {Built-in Function} {} __accumarray_sum__ (@var{idx}, @var{vals}, @var{n})\n\ | |
7319 Undocumented internal function.\n\ | |
7320 @end deftypefn") | |
7321 { | |
7322 octave_value retval; | |
7323 int nargin = args.length (); | |
7324 if (nargin >= 2 && nargin <= 3 && args(0).is_numeric_type ()) | |
7325 { | |
7326 idx_vector idx = args(0).index_vector (); | |
7327 octave_idx_type n = -1; | |
7328 if (nargin == 3) | |
7329 n = args(2).idx_type_value (true); | |
7330 | |
7331 if (! error_state) | |
7332 { | |
7333 octave_value vals = args(1); | |
7334 if (vals.is_range ()) | |
7335 { | |
7336 Range r = vals.range_value (); | |
7337 if (r.inc () == 0) | |
7338 vals = r.base (); | |
7339 } | |
7340 | |
7341 if (vals.is_single_type ()) | |
7342 { | |
7343 if (vals.is_complex_type ()) | |
7344 retval = do_accumarray_sum (idx, | |
7345 vals.float_complex_array_value (), | |
7346 n); | |
7347 else | |
7348 retval = do_accumarray_sum (idx, vals.float_array_value (), n); | |
7349 } | |
7350 else if (vals.is_numeric_type () || vals.is_bool_type ()) | |
7351 { | |
7352 if (vals.is_complex_type ()) | |
7353 retval = do_accumarray_sum (idx, | |
7354 vals.complex_array_value (), | |
7355 n); | |
7356 else | |
7357 retval = do_accumarray_sum (idx, vals.array_value (), n); | |
7358 } | |
7359 else | |
7360 gripe_wrong_type_arg ("accumarray", vals); | |
7361 } | |
7362 } | |
7363 else | |
7364 print_usage (); | |
7365 | |
7366 return retval; | |
7367 } | |
7368 | |
7369 template <class NDT> | |
7370 static NDT | |
7371 do_accumarray_minmax (const idx_vector& idx, const NDT& vals, | |
7372 octave_idx_type n, bool ismin, | |
7373 const typename NDT::element_type& zero_val) | |
7374 { | |
7375 typedef typename NDT::element_type T; | |
7376 if (n < 0) | |
7377 n = idx.extent (0); | |
7378 else if (idx.extent (n) > n) | |
7379 error ("accumarray: index out of range"); | |
7380 | |
7381 NDT retval (dim_vector (n, 1), zero_val); | |
7382 | |
7383 // Pick minimizer or maximizer. | |
7384 void (MArray<T>::*op) (const idx_vector&, const MArray<T>&) = | |
7385 ismin ? (&MArray<T>::idx_min) : (&MArray<T>::idx_max); | |
7386 | |
7387 octave_idx_type l = idx.length (n); | |
7388 if (vals.numel () == 1) | |
7389 (retval.*op) (idx, NDT (dim_vector (l, 1), vals(0))); | |
7390 else if (vals.numel () == l) | |
7391 (retval.*op) (idx, vals); | |
7392 else | |
7393 error ("accumarray: dimensions mismatch"); | |
7394 | |
7395 return retval; | |
7396 } | |
7397 | |
7398 static octave_value_list | |
7399 do_accumarray_minmax_fun (const octave_value_list& args, | |
7400 bool ismin) | |
7401 { | |
7402 octave_value retval; | |
7403 int nargin = args.length (); | |
7404 if (nargin >= 3 && nargin <= 4 && args(0).is_numeric_type ()) | |
7405 { | |
7406 idx_vector idx = args(0).index_vector (); | |
7407 octave_idx_type n = -1; | |
7408 if (nargin == 4) | |
7409 n = args(3).idx_type_value (true); | |
7410 | |
7411 if (! error_state) | |
7412 { | |
7413 octave_value vals = args(1); | |
7414 octave_value zero = args(2); | |
7415 | |
7416 switch (vals.builtin_type ()) | |
7417 { | 7255 { |
7418 case btyp_double: | 7256 case btyp_double: |
7419 retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin, | 7257 retval = argx.array_value ().nth_element (n, dim); |
7420 zero.double_value ()); | |
7421 break; | 7258 break; |
7422 case btyp_float: | 7259 case btyp_float: |
7423 retval = do_accumarray_minmax (idx, vals.float_array_value (), n, | 7260 retval = argx.float_array_value ().nth_element (n, dim); |
7424 ismin, zero.float_value ()); | |
7425 break; | 7261 break; |
7426 case btyp_complex: | 7262 case btyp_complex: |
7427 retval = do_accumarray_minmax (idx, vals.complex_array_value (), | 7263 retval = argx.complex_array_value ().nth_element (n, dim); |
7428 n, ismin, zero.complex_value ()); | |
7429 break; | 7264 break; |
7430 case btyp_float_complex: | 7265 case btyp_float_complex: |
7431 retval = do_accumarray_minmax (idx, | 7266 retval = argx.float_complex_array_value ().nth_element (n, dim); |
7432 vals.float_complex_array_value (), | |
7433 n, ismin, | |
7434 zero.float_complex_value ()); | |
7435 break; | 7267 break; |
7436 #define MAKE_INT_BRANCH(X) \ | 7268 #define MAKE_INT_BRANCH(X) \ |
7437 case btyp_ ## X: \ | 7269 case btyp_ ## X: \ |
7438 retval = do_accumarray_minmax (idx, vals.X ## _array_value (), \ | 7270 retval = argx.X ## _array_value ().nth_element (n, dim); \ |
7439 n, ismin, \ | |
7440 zero.X ## _scalar_value ()); \ | |
7441 break; | 7271 break; |
7442 | 7272 |
7443 MAKE_INT_BRANCH (int8); | 7273 MAKE_INT_BRANCH (int8); |
7444 MAKE_INT_BRANCH (int16); | 7274 MAKE_INT_BRANCH (int16); |
7445 MAKE_INT_BRANCH (int32); | 7275 MAKE_INT_BRANCH (int32); |
7447 MAKE_INT_BRANCH (uint8); | 7277 MAKE_INT_BRANCH (uint8); |
7448 MAKE_INT_BRANCH (uint16); | 7278 MAKE_INT_BRANCH (uint16); |
7449 MAKE_INT_BRANCH (uint32); | 7279 MAKE_INT_BRANCH (uint32); |
7450 MAKE_INT_BRANCH (uint64); | 7280 MAKE_INT_BRANCH (uint64); |
7451 #undef MAKE_INT_BRANCH | 7281 #undef MAKE_INT_BRANCH |
7452 case btyp_bool: | |
7453 retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin, | |
7454 zero.bool_value ()); | |
7455 break; | |
7456 default: | 7282 default: |
7457 gripe_wrong_type_arg ("accumarray", vals); | 7283 if (argx.is_cellstr ()) |
7284 retval = argx.cellstr_value ().nth_element (n, dim); | |
7285 else | |
7286 gripe_wrong_type_arg ("nth_element", argx); | |
7458 } | 7287 } |
7459 } | 7288 } |
7289 catch (index_exception& e) | |
7290 { | |
7291 error ("nth_element: invalid N value %s. %s", e.idx (), e.explain ()); | |
7292 } | |
7293 } | |
7294 else | |
7295 print_usage (); | |
7296 | |
7297 return retval; | |
7298 } | |
7299 | |
7300 template <class NDT> | |
7301 static NDT | |
7302 do_accumarray_sum (const idx_vector& idx, const NDT& vals, | |
7303 octave_idx_type n = -1) | |
7304 { | |
7305 typedef typename NDT::element_type T; | |
7306 if (n < 0) | |
7307 n = idx.extent (0); | |
7308 else if (idx.extent (n) > n) | |
7309 error ("accumarray: index out of range"); | |
7310 | |
7311 NDT retval (dim_vector (n, 1), T ()); | |
7312 | |
7313 if (vals.numel () == 1) | |
7314 retval.idx_add (idx, vals (0)); | |
7315 else if (vals.numel () == idx.length (n)) | |
7316 retval.idx_add (idx, vals); | |
7317 else | |
7318 error ("accumarray: dimensions mismatch"); | |
7319 | |
7320 return retval; | |
7321 } | |
7322 | |
7323 DEFUN (__accumarray_sum__, args, , | |
7324 "-*- texinfo -*-\n\ | |
7325 @deftypefn {Built-in Function} {} __accumarray_sum__ (@var{idx}, @var{vals}, @var{n})\n\ | |
7326 Undocumented internal function.\n\ | |
7327 @end deftypefn") | |
7328 { | |
7329 octave_value retval; | |
7330 int nargin = args.length (); | |
7331 if (nargin >= 2 && nargin <= 3 && args(0).is_numeric_type ()) | |
7332 { | |
7333 try | |
7334 { | |
7335 idx_vector idx = args(0).index_vector (); | |
7336 octave_idx_type n = -1; | |
7337 if (nargin == 3) | |
7338 n = args(2).idx_type_value (true); | |
7339 | |
7340 if (! error_state) | |
7341 { | |
7342 octave_value vals = args(1); | |
7343 if (vals.is_range ()) | |
7344 { | |
7345 Range r = vals.range_value (); | |
7346 if (r.inc () == 0) | |
7347 vals = r.base (); | |
7348 } | |
7349 | |
7350 if (vals.is_single_type ()) | |
7351 { | |
7352 if (vals.is_complex_type ()) | |
7353 retval = do_accumarray_sum (idx, | |
7354 vals.float_complex_array_value (), | |
7355 n); | |
7356 else | |
7357 retval = do_accumarray_sum (idx, vals.float_array_value (), n); | |
7358 } | |
7359 else if (vals.is_numeric_type () || vals.is_bool_type ()) | |
7360 { | |
7361 if (vals.is_complex_type ()) | |
7362 retval = do_accumarray_sum (idx, | |
7363 vals.complex_array_value (), | |
7364 n); | |
7365 else | |
7366 retval = do_accumarray_sum (idx, vals.array_value (), n); | |
7367 } | |
7368 else | |
7369 gripe_wrong_type_arg ("accumarray", vals); | |
7370 } | |
7371 } | |
7372 catch (index_exception& e) | |
7373 { | |
7374 error ("__accumarray_sum__: invalid IDX %s. %s", | |
7375 e.idx(), e.explain ()); | |
7376 } | |
7377 } | |
7378 else | |
7379 print_usage (); | |
7380 | |
7381 return retval; | |
7382 } | |
7383 | |
7384 template <class NDT> | |
7385 static NDT | |
7386 do_accumarray_minmax (const idx_vector& idx, const NDT& vals, | |
7387 octave_idx_type n, bool ismin, | |
7388 const typename NDT::element_type& zero_val) | |
7389 { | |
7390 typedef typename NDT::element_type T; | |
7391 if (n < 0) | |
7392 n = idx.extent (0); | |
7393 else if (idx.extent (n) > n) | |
7394 error ("accumarray: index out of range"); | |
7395 | |
7396 NDT retval (dim_vector (n, 1), zero_val); | |
7397 | |
7398 // Pick minimizer or maximizer. | |
7399 void (MArray<T>::*op) (const idx_vector&, const MArray<T>&) = | |
7400 ismin ? (&MArray<T>::idx_min) : (&MArray<T>::idx_max); | |
7401 | |
7402 octave_idx_type l = idx.length (n); | |
7403 if (vals.numel () == 1) | |
7404 (retval.*op) (idx, NDT (dim_vector (l, 1), vals(0))); | |
7405 else if (vals.numel () == l) | |
7406 (retval.*op) (idx, vals); | |
7407 else | |
7408 error ("accumarray: dimensions mismatch"); | |
7409 | |
7410 return retval; | |
7411 } | |
7412 | |
7413 static octave_value_list | |
7414 do_accumarray_minmax_fun (const octave_value_list& args, | |
7415 bool ismin) | |
7416 { | |
7417 octave_value retval; | |
7418 int nargin = args.length (); | |
7419 if (nargin >= 3 && nargin <= 4 && args(0).is_numeric_type ()) | |
7420 { | |
7421 try | |
7422 { | |
7423 idx_vector idx = args(0).index_vector (); | |
7424 octave_idx_type n = -1; | |
7425 if (nargin == 4) | |
7426 n = args(3).idx_type_value (true); | |
7427 | |
7428 if (! error_state) | |
7429 { | |
7430 octave_value vals = args(1); | |
7431 octave_value zero = args(2); | |
7432 | |
7433 switch (vals.builtin_type ()) | |
7434 { | |
7435 case btyp_double: | |
7436 retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin, | |
7437 zero.double_value ()); | |
7438 break; | |
7439 case btyp_float: | |
7440 retval = do_accumarray_minmax (idx, vals.float_array_value (), n, | |
7441 ismin, zero.float_value ()); | |
7442 break; | |
7443 case btyp_complex: | |
7444 retval = do_accumarray_minmax (idx, vals.complex_array_value (), | |
7445 n, ismin, zero.complex_value ()); | |
7446 break; | |
7447 case btyp_float_complex: | |
7448 retval = do_accumarray_minmax (idx, | |
7449 vals.float_complex_array_value (), | |
7450 n, ismin, | |
7451 zero.float_complex_value ()); | |
7452 break; | |
7453 #define MAKE_INT_BRANCH(X) \ | |
7454 case btyp_ ## X: \ | |
7455 retval = do_accumarray_minmax (idx, vals.X ## _array_value (), \ | |
7456 n, ismin, \ | |
7457 zero.X ## _scalar_value ()); \ | |
7458 break; | |
7459 | |
7460 MAKE_INT_BRANCH (int8); | |
7461 MAKE_INT_BRANCH (int16); | |
7462 MAKE_INT_BRANCH (int32); | |
7463 MAKE_INT_BRANCH (int64); | |
7464 MAKE_INT_BRANCH (uint8); | |
7465 MAKE_INT_BRANCH (uint16); | |
7466 MAKE_INT_BRANCH (uint32); | |
7467 MAKE_INT_BRANCH (uint64); | |
7468 #undef MAKE_INT_BRANCH | |
7469 case btyp_bool: | |
7470 retval = do_accumarray_minmax (idx, vals.array_value (), n, ismin, | |
7471 zero.bool_value ()); | |
7472 break; | |
7473 default: | |
7474 gripe_wrong_type_arg ("accumarray", vals); | |
7475 } | |
7476 } | |
7477 } | |
7478 catch (index_exception& e) | |
7479 { | |
7480 error ("do_accumarray_minmax_fun: invalid index %s. %s", | |
7481 e.idx (), e.explain ()); | |
7482 } | |
7483 | |
7460 } | 7484 } |
7461 else | 7485 else |
7462 print_usage (); | 7486 print_usage (); |
7463 | 7487 |
7464 return retval; | 7488 return retval; |
7521 { | 7545 { |
7522 octave_value retval; | 7546 octave_value retval; |
7523 int nargin = args.length (); | 7547 int nargin = args.length (); |
7524 if (nargin >= 2 && nargin <= 4 && args(0).is_numeric_type ()) | 7548 if (nargin >= 2 && nargin <= 4 && args(0).is_numeric_type ()) |
7525 { | 7549 { |
7526 idx_vector idx = args(0).index_vector (); | 7550 try |
7527 int dim = -1; | 7551 { |
7528 if (nargin >= 3) | 7552 idx_vector idx = args(0).index_vector (); |
7529 dim = args(2).int_value () - 1; | 7553 int dim = -1; |
7530 | 7554 if (nargin >= 3) |
7531 octave_idx_type n = -1; | 7555 dim = args(2).int_value () - 1; |
7532 if (nargin == 4) | 7556 |
7533 n = args(3).idx_type_value (true); | 7557 octave_idx_type n = -1; |
7534 | 7558 if (nargin == 4) |
7535 if (! error_state) | 7559 n = args(3).idx_type_value (true); |
7536 { | 7560 |
7537 octave_value vals = args(1); | 7561 if (! error_state) |
7538 | |
7539 if (vals.is_single_type ()) | |
7540 { | 7562 { |
7541 if (vals.is_complex_type ()) | 7563 octave_value vals = args(1); |
7542 retval = do_accumdim_sum (idx, | 7564 |
7543 vals.float_complex_array_value (), | 7565 if (vals.is_single_type ()) |
7544 dim, n); | 7566 { |
7567 if (vals.is_complex_type ()) | |
7568 retval = do_accumdim_sum (idx, | |
7569 vals.float_complex_array_value (), | |
7570 dim, n); | |
7571 else | |
7572 retval = do_accumdim_sum (idx, vals.float_array_value (), | |
7573 dim, n); | |
7574 } | |
7575 else if (vals.is_numeric_type () || vals.is_bool_type ()) | |
7576 { | |
7577 if (vals.is_complex_type ()) | |
7578 retval = do_accumdim_sum (idx, vals.complex_array_value (), | |
7579 dim, n); | |
7580 else | |
7581 retval = do_accumdim_sum (idx, vals.array_value (), dim, n); | |
7582 } | |
7545 else | 7583 else |
7546 retval = do_accumdim_sum (idx, vals.float_array_value (), | 7584 gripe_wrong_type_arg ("accumdim", vals); |
7547 dim, n); | |
7548 } | 7585 } |
7549 else if (vals.is_numeric_type () || vals.is_bool_type ()) | 7586 } |
7550 { | 7587 catch (index_exception& e) |
7551 if (vals.is_complex_type ()) | 7588 { |
7552 retval = do_accumdim_sum (idx, vals.complex_array_value (), | 7589 error ("__accumdim_sum__: invalid IDX %s. %s", e.idx(), e.explain ()); |
7553 dim, n); | |
7554 else | |
7555 retval = do_accumdim_sum (idx, vals.array_value (), dim, n); | |
7556 } | |
7557 else | |
7558 gripe_wrong_type_arg ("accumdim", vals); | |
7559 } | 7590 } |
7560 } | 7591 } |
7561 else | 7592 else |
7562 print_usage (); | 7593 print_usage (); |
7563 | 7594 |