# HG changeset patch # User Jaroslav Hajek # Date 1221732872 -7200 # Node ID 287a159bd4b96f5fd50f6c3893a555dad1343f8b # Parent 31e86163b7529285a16092625c3ae8ec0d986f92 make null assignment more Matlab-compatible diff --git a/liboctave/Array.cc b/liboctave/Array.cc --- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -1535,12 +1535,19 @@ octave_idx_type nr = dim1 (); octave_idx_type nc = dim2 (); + if (idx_arg.is_colon ()) + { + // A(:) = [] always gives 0-by-0 matrix, even if A was empty. + resize_no_fill (0, 0); + return; + } + octave_idx_type n; if (nr == 1) n = nc; else if (nc == 1) n = nr; - else + else if (! idx_arg.orig_empty ()) { // Reshape to row vector for Matlab compatibility. @@ -1549,18 +1556,16 @@ nc = n; } - if (nr > 0 && nc > 0 && idx_arg.is_colon_equiv (n, 1)) + idx_arg.sort (true); + + if (idx_arg.is_colon_equiv (n, 1)) { - // Either A(:) = [] or A(idx) = [] with idx enumerating all - // elements, so we delete all elements and return [](0x0). To - // preserve the orientation of the vector, you have to use - // A(idx,:) = [] (delete rows) or A(:,idx) (delete columns). - - resize_no_fill (0, 0); + if (nr == 1) + resize_no_fill (1, 0); + else if (nc == 1) + resize_no_fill (0, 1); return; } - - idx_arg.sort (true); octave_idx_type num_to_delete = idx_arg.length (n); @@ -1631,166 +1636,132 @@ octave_idx_type nr = dim1 (); octave_idx_type nc = dim2 (); - if (nr == 0 && nc == 0) - return; - - if (idx_i.is_colon ()) + if (idx_i.is_colon () && idx_j.is_colon ()) { - if (idx_j.is_colon ()) - { - // A(:,:) -- We are deleting columns and rows, so the result - // is [](0x0). - - resize_no_fill (0, 0); - return; - } + // A special case: A(:,:). Matlab gives 0-by-nc here, but perhaps we + // should not? + resize_no_fill (0, nc); + } + else if (idx_i.is_colon ()) + { + idx_j.sort (true); // sort in advance to speed-up the following check if (idx_j.is_colon_equiv (nc, 1)) - { - // A(:,j) -- We are deleting columns by enumerating them, - // If we enumerate all of them, we should have zero columns - // with the same number of rows that we started with. - - resize_no_fill (nr, 0); - return; - } - } - - if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1)) - { - // A(i,:) -- We are deleting rows by enumerating them. If we - // enumerate all of them, we should have zero rows with the - // same number of columns that we started with. - - resize_no_fill (0, nc); - return; - } - - if (idx_i.is_colon_equiv (nr, 1)) - { - if (idx_j.is_colon_equiv (nc, 1)) - resize_no_fill (0, 0); + resize_no_fill (nr, 0); else { - idx_j.sort (true); - octave_idx_type num_to_delete = idx_j.length (nc); if (num_to_delete != 0) - { - if (nr == 1 && num_to_delete == nc) - resize_no_fill (0, 0); - else - { - octave_idx_type new_nc = nc; + { + octave_idx_type new_nc = nc; - octave_idx_type iidx = 0; + octave_idx_type iidx = 0; - for (octave_idx_type j = 0; j < nc; j++) - if (j == idx_j.elem (iidx)) - { - iidx++; - new_nc--; + for (octave_idx_type j = 0; j < nc; j++) + if (j == idx_j.elem (iidx)) + { + iidx++; + new_nc--; - if (iidx == num_to_delete) - break; - } + if (iidx == num_to_delete) + break; + } - if (new_nc > 0) - { - T *new_data = new T [nr * new_nc]; + if (new_nc > 0) + { + T *new_data = new T [nr * new_nc]; - octave_idx_type jj = 0; - iidx = 0; - for (octave_idx_type j = 0; j < nc; j++) - { - if (iidx < num_to_delete && j == idx_j.elem (iidx)) - iidx++; - else - { - for (octave_idx_type i = 0; i < nr; i++) - new_data[nr*jj+i] = xelem (i, j); - jj++; - } - } + octave_idx_type jj = 0; + iidx = 0; + for (octave_idx_type j = 0; j < nc; j++) + { + if (iidx < num_to_delete && j == idx_j.elem (iidx)) + iidx++; + else + { + for (octave_idx_type i = 0; i < nr; i++) + new_data[nr*jj+i] = xelem (i, j); + jj++; + } + } - if (--(Array::rep)->count <= 0) - delete Array::rep; + if (--(Array::rep)->count <= 0) + delete Array::rep; - Array::rep = new typename Array::ArrayRep (new_data, nr * new_nc); + Array::rep = new typename Array::ArrayRep (new_data, nr * new_nc); - dimensions.resize (2); - dimensions(1) = new_nc; - } - else - (*current_liboctave_error_handler) - ("A(idx) = []: index out of range"); - } - } + dimensions.resize (2); + dimensions(1) = new_nc; + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } } } - else if (idx_j.is_colon_equiv (nc, 1)) + else if (idx_j.is_colon ()) { + idx_i.sort (true); // sort in advance to speed-up the following check + if (idx_i.is_colon_equiv (nr, 1)) - resize_no_fill (0, 0); + resize_no_fill (0, nc); else { - idx_i.sort (true); - octave_idx_type num_to_delete = idx_i.length (nr); if (num_to_delete != 0) - { - if (nc == 1 && num_to_delete == nr) - resize_no_fill (0, 0); - else - { - octave_idx_type new_nr = nr; + { + octave_idx_type new_nr = nr; - octave_idx_type iidx = 0; + octave_idx_type iidx = 0; - for (octave_idx_type i = 0; i < nr; i++) - if (i == idx_i.elem (iidx)) - { - iidx++; - new_nr--; + for (octave_idx_type i = 0; i < nr; i++) + if (i == idx_i.elem (iidx)) + { + iidx++; + new_nr--; - if (iidx == num_to_delete) - break; - } + if (iidx == num_to_delete) + break; + } - if (new_nr > 0) - { - T *new_data = new T [new_nr * nc]; + if (new_nr > 0) + { + T *new_data = new T [new_nr * nc]; - octave_idx_type ii = 0; - iidx = 0; - for (octave_idx_type i = 0; i < nr; i++) - { - if (iidx < num_to_delete && i == idx_i.elem (iidx)) - iidx++; - else - { - for (octave_idx_type j = 0; j < nc; j++) - new_data[new_nr*j+ii] = xelem (i, j); - ii++; - } - } + octave_idx_type ii = 0; + iidx = 0; + for (octave_idx_type i = 0; i < nr; i++) + { + if (iidx < num_to_delete && i == idx_i.elem (iidx)) + iidx++; + else + { + for (octave_idx_type j = 0; j < nc; j++) + new_data[new_nr*j+ii] = xelem (i, j); + ii++; + } + } - if (--(Array::rep)->count <= 0) - delete Array::rep; + if (--(Array::rep)->count <= 0) + delete Array::rep; - Array::rep = new typename Array::ArrayRep (new_data, new_nr * nc); + Array::rep = new typename Array::ArrayRep (new_data, new_nr * nc); - dimensions.resize (2); - dimensions(0) = new_nr; - } - else - (*current_liboctave_error_handler) - ("A(idx) = []: index out of range"); - } - } + dimensions.resize (2); + dimensions(0) = new_nr; + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } } + } + else + { + (*current_liboctave_error_handler) + ("a null assignment can have only one non-colon index"); } } diff --git a/liboctave/Array.h b/liboctave/Array.h --- a/liboctave/Array.h +++ b/liboctave/Array.h @@ -502,6 +502,8 @@ void maybe_delete_elements (Array& ra_idx, const T& rfv); + void maybe_delete_elements (octave_idx_type dim, idx_vector& i); + Array value (void) const; Array index (idx_vector& i, int resize_ok = 0, diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -0,0 +1,7 @@ +2008-09-18 Jaroslav Hajek + + * Array.cc (maybe_delete_elements_2 (idx_vector&)): Fix tests to get + better Matlab compatibility. + (maybe_delete_elements (idx_vector&, idx_vector&)): Fix tests to get + better Matlab compatibility, simplify, gripe on invalid 2-D deletion. + diff --git a/test/ChangeLog b/test/ChangeLog --- a/test/ChangeLog +++ b/test/ChangeLog @@ -0,0 +1,4 @@ +2008-09-18 Jaroslav Hajek + + * test_null_assign.m: New tests. + diff --git a/test/test_null_assign.m b/test/test_null_assign.m new file mode 100644 --- /dev/null +++ b/test/test_null_assign.m @@ -0,0 +1,35 @@ +## Copyright (C) 2008 Jaroslav Hajek +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +%!test +%! a = 1:3; a(:) = []; assert (size (a), [0, 0]) +%!test +%! a = 1:3; a(1:3) = []; assert (size (a), [1, 0]) +%!test +%! a = (1:3).'; a(1:3) = []; assert (size (a), [0, 1]) +%!test +%! a = ones (3); a(:,:) = []; assert (size (a), [0, 3]) +%!test +%! a = ones (3); a(1:3,:) = []; assert (size (a), [0, 3]) +%!test +%! a = ones (3); a(:,1:3) = []; assert (size (a), [3, 0]) +%!test +%! a = ones (3); fail ("a(1:2,1:2) = []", ".*"); +%!test +%! a = ones (3); fail ("a(1:3,1:3) = []", ".*"); +