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