# 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) = []", ".*");
+