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