Mercurial > hg > octave-nkf
changeset 17642:7ed397c8ca68
improve compatibility of null assignment (bug #31287)
* Array.cc (Array<T>::delete_elements (const Array<idx_vector>&)):
Improve compatibility when indices references an empty slice.
* Sparse.cc (Sparse<T>::delete_elements (const idx_vector&, const
idx_vector&)): Likewise.
(Sparse<T>::delete_elements (const idx_vector&)): Likewise.
* index.tst: New tests.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 11 Oct 2013 23:39:54 -0400 |
parents | cd5a6008ae72 |
children | d0a197b9962a |
files | liboctave/array/Array.cc liboctave/array/Sparse.cc test/index.tst |
diffstat | 3 files changed, 343 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/array/Array.cc +++ b/liboctave/array/Array.cc @@ -1460,12 +1460,14 @@ void Array<T>::delete_elements (const Array<idx_vector>& 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<T> (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"); } }
--- a/liboctave/array/Sparse.cc +++ b/liboctave/array/Sparse.cc @@ -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<T> (); + 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 <class T>
--- a/test/index.tst +++ b/test/index.tst @@ -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);