FIND on a 0x0 returns a 0x1

Carsten Clark tantumquantum+gnuoctave at gmail.com
Wed Mar 25 16:23:45 CDT 2009


2009/3/25 John W. Eaton <jwe at octave.org>
>
> On 25-Mar-2009, Carsten Clark wrote:
>
> | --------
> | Bug report for Octave 3.0.3 configured for i686-pc-cygwin
> |
> | Description:
> | -----------
> |
> |   * When FIND is called on a 0x0 matrix, it returns a 0x1
> |     empty matrix.  This is inconvenient because a FOR loop
> |     will be entered when given a 0x1 empty matrix to
> |     iterate over.
> |
> |     For reference, FIND in MATLAB R2007b returns a 0x0
> |     empty matrix in the same situation, and a FOR loop
> |     over the result is not entered.
> |
> |     My vote would be that it would make more sense for FIND
> |     to return a 0x0 when given a 0x0.  However, on some other
> |     inputs, both Octave's and MATLAB's FIND functions will
> |     return a 0x1, which a FOR loop will enter.  So perhaps
> |     the proper behavior is up for debate, and I should change
> |     my code ;-)
> |
> | Repeat-By:
> | ---------
> |
> | Here are trivial and a practical examples in Octave and MATLAB:
> |
> | (In Octave 3.0.3)
> |
> | $ octave -qf
> | octave:1> find ( [] )
> | ans = [](0x1)
> | octave:2> for c = find ( [] ), c, end
> | c = [](0x1)
> |
> | $ octave -qf
> | octave:1> tracks = repmat ( struct ('active', 0), 1, 0 );
> | octave:2> w = [tracks.active]
> | w = [](0x0)
> | octave:3> for inx = find(w), inx, end
> | inx = [](0x1)
> |
> |
> | (In MATLAB R2007b)
> |
> | >> find ( [] )
> | ans =
> |      []
> | >> size(ans)
> | ans =
> |      0     0
> | >> for c = find ( [] ), c, end
> | >>
> |
> | >> tracks = repmat ( struct ('active', 0), 1, 0 );
> | >> w = [tracks.active]
> | w =
> |      []
> | >> size(w)
> | ans =
> |      0     0
> | >> for inx = find(w), inx, end
> | >>
>
> I don't see a problem with catching matrices that have all dimensions
> zero and returning [] in those cases.  But I'm not sure about other
> cases where one (or more) of the dimensions of the empty matrix is not
> zero.
>
> What does Matlab do for the following?
>
>  find (zeros (0, 0))
>  find (zeros (1, 0))
>  find (zeros (0, 1))
>
>  find (zeros (0, 0, 0))
>  find (zeros (1, 0, 0))
>  find (zeros (0, 1, 0))
>  find (zeros (1, 1, 0))
>  find (zeros (0, 0, 1))
>  find (zeros (1, 0, 1))
>  find (zeros (0, 1, 1))
>
> Is it consistent in some way?
>
> jwe


Here's a synopsis of some testing in MATLAB (monospaced display will help):

ZEROS          Input  Input    FIND  Output
               type  ISVECTOR Output  type
0x0           0xOther  0       0x0     []
1x0             RV     1       1x0   basic RV
0x1             CV     1       0x1   basic CV

0x0x0         0xOther  0       0x0     []
1x0x0         1xOther  0       0x1   basic CV
0x1x0         0xOther  0       0x0     []
1x1x0         1xOther  0       0x1   basic CV
0x0x1         0xOther  0       0x0     []
1x0x1           RV     1       1x0   basic RV
0x1x1           CV     1       0x1   basic CV

1x0x1x1x1x1x1   RV     1       1x0   basic RV
1x0x1x1x1x0x1 1xOther  0       0x1   basic CV

0x1x1x1x1x1x1   CV     1       0x1   basic CV
0x1x1x1x1x0x1 0xOther  0       0x0     []


RV = row vector (1xN, 1xNx1, 1xNx1x1, ...)
CV = col vector (Nx1, Nx1x1, Nx1x1x1, ...)


Here's the raw MATLAB FIND output (note that [] is always 0x0 in MATLAB):

>> find(zeros(0,0))
ans =
     []
>> find(zeros(1,0))
ans =
   Empty matrix: 1-by-0
>> find(zeros(0,1))
ans =
   Empty matrix: 0-by-1
>> find(zeros(0,0,0))
ans =
     []
>> find(zeros(1,0,0))
ans =
   Empty matrix: 0-by-1
>> find(zeros(0,1,0))
ans =
     []
>> find(zeros(1,1,0))
ans =
   Empty matrix: 0-by-1
>> find(zeros(0,0,1))
ans =
     []
>> find(zeros(1,0,1))
ans =
   Empty matrix: 1-by-0
>> find(zeros(0,1,1))
ans =
   Empty matrix: 0-by-1
>> find(zeros(1,0,1,1,1,1,1))
ans =
   Empty matrix: 1-by-0
>> find(zeros(1,0,1,1,1,0,1))
ans =
   Empty matrix: 0-by-1
>> find(zeros(0,1,1,1,1,1,1))
ans =
   Empty matrix: 0-by-1
>> find(zeros(0,1,1,1,1,0,1))
ans =
     []


Here's the result of MATLAB ISVECTOR on the same inputs:

>> isvector(zeros(0,0))
ans =
     0
>> isvector(zeros(1,0))
ans =
     1
>> isvector(zeros(0,1))
ans =
     1
>> isvector(zeros(0,0,0))
ans =
     0
>> isvector(zeros(1,0,0))
ans =
     0
>> isvector(zeros(0,1,0))
ans =
     0
>> isvector(zeros(1,1,0))
ans =
     0
>> isvector(zeros(0,0,1))
ans =
     0
>> isvector(zeros(1,0,1))
ans =
     1
>> isvector(zeros(0,1,1))
ans =
     1
>> isvector(zeros(1,0,1,1,1,1,1))
ans =
     1
>> isvector(zeros(1,0,1,1,1,0,1))
ans =
     0
>> isvector(zeros(0,1,1,1,1,1,1))
ans =
     1
>> isvector(zeros(0,1,1,1,1,0,1))
ans =
     0


Here's a set of rules deduced from the above for find(X), where X is
empty.  Given the following definitions:

- a row vector is any matrix with size >= 0 down the 2nd dimension,
and all other dimensions of size 1;

- a column vector is any matrix with size >= 0 down the 1st dimension,
and all other dimensions of size 1;

the following rules seem to apply when X is empty:

1. If X is a row vector, return the basic empty row vector (1x0).
2. If X's 1st dim is 0 and X is *not* a column vector, return [] (0x0).
3. Return the basic empty column vector (0x1).


This comes close to agreeing with the MATLAB doc entry for ind = find(X):

- "If X is a row vector, then ind is a row vector; otherwise, ind is a
column vector."
 (True only if you consider 0x0 [] a "column vector")

- "If X contains no nonzero elements or is an empty array, then ind is
an empty array."
 (True, but not specific.)

Later in the docs:

Example 7
If X is a vector of all zeros, find(X) returns an empty matrix. For example,
indices = find([0;0;0])
indices =
  Empty matrix: 0-by-1

This is my basis for the above generalized definitions of "row vector"
and "column vector."  The input was a column vector, so, according to
their rules, the 0x1 empty matrix must be a column vector.  Logically,
then, a 1x0 empty matrix is a row vector.


Going back to the 3 rules I deduced, it almost seems like they added
the 2nd rule as a special case, perhaps for reasons similar to why I
reported this in the first place.

Carsten Clark


More information about the Bug-octave mailing list