# HG changeset patch # User John W. Eaton # Date 1381549194 14400 # Node ID 7ed397c8ca68e6258fca2f46d1e86d90ced44f1b # Parent cd5a6008ae72f1b7bd2dcacba95a789d25b9ee4c improve compatibility of null assignment (bug #31287) * Array.cc (Array::delete_elements (const Array&)): Improve compatibility when indices references an empty slice. * Sparse.cc (Sparse::delete_elements (const idx_vector&, const idx_vector&)): Likewise. (Sparse::delete_elements (const idx_vector&)): Likewise. * index.tst: New tests. diff -r cd5a6008ae72 -r 7ed397c8ca68 liboctave/array/Array.cc --- a/liboctave/array/Array.cc Fri Oct 11 21:21:50 2013 -0700 +++ b/liboctave/array/Array.cc Fri Oct 11 23:39:54 2013 -0400 @@ -1460,12 +1460,14 @@ void Array::delete_elements (const Array& ia) { - if (ia.length () == 1) + int ial = ia.length (); + + if (ial == 1) delete_elements (ia(0)); else { - int len = ia.length (), k, dim = -1; - for (k = 0; k < len; k++) + int k, dim = -1; + for (k = 0; k < ial; k++) { if (! ia(k).is_colon ()) { @@ -1481,14 +1483,51 @@ dv(0) = 0; *this = Array (dv); } - else if (k == len) + else if (k == ial) { delete_elements (dim, ia(dim)); } else { - (*current_liboctave_error_handler) - ("a null assignment can only have one non-colon index"); + // Allow the null assignment to succeed if it won't change + // anything because the indices reference an empty slice, + // provided that there is at most one non-colon (or + // equivalent) index. So, we still have the requirement of + // deleting a slice, but it is OK if the slice is empty. + + // For compatibility with Matlab, stop checking once we see + // more than one non-colon index or an empty index. Matlab + // considers "[]" to be an empty index but not "false". We + // accept both. + + bool empty_assignment = false; + + int num_non_colon_indices = 0; + + int nd = ndims (); + + for (int i = 0; i < ial; i++) + { + octave_idx_type dim_len = i >= nd ? 1 : dimensions(i); + + if (ia(i).length (dim_len) == 0) + { + empty_assignment = true; + break; + } + + if (! ia(i).is_colon_equiv (dim_len)) + { + num_non_colon_indices++; + + if (num_non_colon_indices == 2) + break; + } + } + + if (! empty_assignment) + (*current_liboctave_error_handler) + ("a null assignment can only have one non-colon index"); } } diff -r cd5a6008ae72 -r 7ed397c8ca68 liboctave/array/Sparse.cc --- a/liboctave/array/Sparse.cc Fri Oct 11 21:21:50 2013 -0700 +++ b/liboctave/array/Sparse.cc Fri Oct 11 23:39:54 2013 -0400 @@ -1215,11 +1215,16 @@ else *this = index (idx.complement (nc)); } - else + else if (idx.length (nel) != 0) { - *this = index (idx_vector::colon); - delete_elements (idx); - *this = transpose (); // We want a row vector. + if (idx.is_colon_equiv (nel)) + *this = Sparse (); + else + { + *this = index (idx_vector::colon); + delete_elements (idx); + *this = transpose (); // We want a row vector. + } } } @@ -1324,8 +1329,21 @@ } } else - (*current_liboctave_error_handler) - ("a null assignment can only have one non-colon index"); + { + // Empty assignment (no elements to delete) is OK if there is at + // least one zero-length index and at most one other index that is + // non-colon (or equivalent) index. Since we only have two + // indices, we just need to check that we have at least one zero + // length index. Matlab considers "[]" to be an empty index but + // not "false". We accept both. + + bool empty_assignment + = (idx_i.length (nr) == 0 || idx_j.length (nc) == 0); + + if (! empty_assignment) + (*current_liboctave_error_handler) + ("a null assignment can only have one non-colon index"); + } } template diff -r cd5a6008ae72 -r 7ed397c8ca68 test/index.tst --- a/test/index.tst Fri Oct 11 21:21:50 2013 -0700 +++ b/test/index.tst Fri Oct 11 23:39:54 2013 -0400 @@ -227,3 +227,277 @@ %!error d(3,6); %!error dd(3,6); +## bug 31287 +%!test +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false,[]) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false,[],false) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false, 1) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2, 2); +%! x = ones (2, 2, 2); +%! x(false, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], []) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x([], []) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, []) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], 1, []) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, [], 1, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], 1, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! ea2 = ones (3, 2, 0, 2); +%! x(1, ea2) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! ea2 = ones (3, 2, 0, 2); +%! x(1, ea2) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! ea2 = ones (3, 2, 0, 2); +%! x([], 1, ea2) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! ea2 = ones (3, 2, 0, 2); +%! x(1, ea2, ea2) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! ea2 = ones (3, 2, 0, 2); +%! x(1, ea2, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, 1) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(false, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, [], false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, false) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(false, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, [], false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], false, false, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, [], false, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(:, false) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(:, false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, :) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(false, :) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, :, [], 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(:, [], false) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%!error x(1, 1, []) = []; + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, false, 1) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, false, []) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false, false, [], false) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(1, false, [], false) = []; +%! assert (x, y); + +%!shared x, y +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(:, false, 1) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([]) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x([]) = []; +%! assert (x, y); + +%!test +%! y = []; +%! x = ones (2, 2); +%! x(:) = []; +%! assert (x, y); + +%!test +%! y = sparse ([]); +%! x = sparse (ones (2, 2)); +%! x(:) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x(false) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x(false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], false) = []; +%! assert (x, y); + +%!test +%! y = sparse (ones (2, 2)); +%! x = sparse (ones (2, 2)); +%! x([], false) = []; +%! assert (x, y); + +%!test +%! y = ones (2, 2); +%! x = ones (2, 2); +%! x([], false, :) = []; +%! assert (x, y);