Mercurial > octave
changeset 21405:120bb822c6f4
Handle empty vectors for size of ones(), zeros(), inf(), etc... (bug #47298)
* utils.cc (get_dimensions): handle empty vectors for size. Bug is that
empty vectors of size 0x1, 1x0, and 0x1x1, would return a single element.
Origin of the bug is that dim.redim(n) would still leave 2 dimensions even
if n<2. When n=0 (n=1 had a separate path), dim would still have 2 but the
loop over the dimensions vector would then never run, leaving dim_vector
intact, i.e., of size 1x1.
* data.cc: add tests for ones(), zeros(), inf(), nan(), and other functions
that follow the same code path.
author | Carnë Draug <carandraug@octave.org> |
---|---|
date | Sun, 28 Feb 2016 19:07:24 +0000 |
parents | 0daaca299102 |
children | 1f69fc65539e |
files | libinterp/corefcn/data.cc libinterp/corefcn/utils.cc |
diffstat | 2 files changed, 37 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/data.cc Sat Mar 05 02:35:31 2016 +0000 +++ b/libinterp/corefcn/data.cc Sun Feb 28 19:07:24 2016 +0000 @@ -4237,6 +4237,23 @@ %!assert (size (ones (3, 4, 5, "int8")), [3, 4, 5]) */ +/* +## Tests for bug #47298 +## Matlab requires the size to be a row vector. In that logic, it supports +## n to be a 1x0 vector (returns 0x0) but not a 0x1 vector. Octave supports +## any vector and therefore must support 0x1, 1x0, and 0x0x1 (but not 0x1x1). +%!test +%! funcs = {@zeros, @ones, @inf, @nan, @NA, @i, @pi, @e}; +%! for idx = 1:numel (funcs) +%! func = funcs{idx}; +%! assert (func (zeros (1, 0)), zeros (0, 0)) +%! assert (func (zeros (0, 1)), zeros (0, 0)) +%! assert (func (zeros (0, 1, 1)), zeros (0, 0)) +%! fail ([func2str(func) " ([])"]) +%! fail ([func2str(func) " (zeros (0, 0, 1))"]) +%! endfor +*/ + DEFUN (zeros, args, , "-*- texinfo -*-\n\ @deftypefn {} {} zeros (@var{n})\n\
--- a/libinterp/corefcn/utils.cc Sat Mar 05 02:35:31 2016 +0000 +++ b/libinterp/corefcn/utils.cc Sun Feb 28 19:07:24 2016 +0000 @@ -1118,26 +1118,29 @@ get_dimensions (const octave_value& a, const char *warn_for, dim_vector& dim) { - if (a.is_scalar_type ()) + // We support dimensions to be specified by any vector, even if it's a + // vector of dimensions 0x1, 1x0, 1x1x0, or 1x1x6. If the vector ends + // up being empty, the final dimensions end up being 0x0. + if (! a.dims ().is_vector ()) + error ("%s (A): use %s (size (A)) instead", warn_for, warn_for); + + const Array<int> v = a.int_vector_value (); + const octave_idx_type n = v.numel (); + + dim.resize (n); // even if n < 2, resize sets it back to 2 + if (n == 0) { - dim.resize (2); - dim(0) = a.idx_type_value (); - dim(1) = dim(0); + dim(0) = 0; + dim(1) = 0; + } + else if (n == 1) + { + dim(0) = v(0); + dim(1) = v(0); } else - { - octave_idx_type nr = a.rows (); - octave_idx_type nc = a.columns (); - - if (nr != 1 && nc != 1) - error ("%s (A): use %s (size (A)) instead", warn_for, warn_for); - - Array<double> v = a.vector_value (); - octave_idx_type n = v.numel (); - dim.resize (n); - for (octave_idx_type i = 0; i < n; i++) - dim(i) = static_cast<int> (fix (v(i))); - } + for (octave_idx_type i = 0; i < n; i++) + dim(i) = v(i); check_dimensions (dim, warn_for); }