Clear Filters
Clear Filters

Unexpected Matlab edge case behavior

5 views (last 30 days)
I recently stumbled upon an edge case in Matlab where indexing doesn't always work as expected (See answers below). What edges cases are are you aware of in Matlab where the behavior at the edge case is not as expected? An example of an expected edge case (i.e. not an answer) would be taking the mean of a set of numbers that happens to include a NaN value. Since this might not normally happen, it might be considered an edge case, but its answer is certainly expected.
This is somewhat related to:
but with the lack of focus on values that have "special" meaning.

Accepted Answer

Jim Hokanson
Jim Hokanson on 7 Oct 2013
This answer originally came from the following link, although I didn't really understand it until I actually ran into an error in my code with the unexpected behavior.
The question is, given A and B are N-D matrices, what is the size of:
C = A(B);
From memory, I would say that the size of C is the size of B.
This is mostly true, EXCEPT if A and B are both vectors , then size of C is the size of A.
I ran into this problem with the following code:
best_number_dimensions = someFunction();
C = A(B(:,1:best_number_dimensions)); %A happened to be a row vector
D = mean(C,2);
Normally, D will have the same length as the first dimension of B. However, if for some reason ' best_number_dimensions ' equals 1, then A determines the size of C. Since I've said A is a row vector, C is now a row vector, which means that D is now a scalar, which was not what I intended.
A simple example of this would be the following:
A = 1:10;
B1 = [3; 4]; %column vector
C1 = A(B1); %row vector
B2 = [3 5; 4 6;]; %non-vector matrix
C2 = A(B2); %matrix the size of B2
  2 Comments
Walter Roberson
Walter Roberson on 7 Oct 2013
This is known and was done deliberately (for reasons I do not recall, though they might have been mentioned at one point). Indexing a vector by a vector has a result whose orientation is according to the first vector rather than the second.
Jan
Jan on 8 Oct 2013
This is a nice example for the danger of Matlab's "smart" treatment of array dimensions. The results of logical indexing in arrays might be surprising also, but it is exactly defined and documented.

Sign in to comment.

More Answers (5)

Jan
Jan on 8 Oct 2013
Edited: Jan on 8 Oct 2013
sum(x)
This operates along the first non-singelton dimension. This is useful for short hacks in the command window, documented, well known, but it is still a pitfall, when the input is a row vector unexpectedly. Therefore specifying the dimension for sum, mean, std, max etc. is obligatory for reliable code.
Btw. sum(x) has been 20% faster than sum(x, 1) in older Matlab releases. But the necessary testing by if size(x, 1) > 1, ... reduced this benefit.
  1 Comment
Sean de Wolski
Sean de Wolski on 8 Oct 2013
I'd say this is necessary for many functions:
mean, std, min, max, diff, %etc.

Sign in to comment.


Jan
Jan on 8 Oct 2013
This might match the "edge case" definition, but belongs to Answers: Dumb mistakes also:
sum(X, 2) % Operate along the 2nd dimension
mean(X, 2) % Operate along the 2nd dimension
max(X, 2) % *Not* along the 2nd dimension, but the max of X and the value 2
std(X, 1); % *Not* along the 1st dimension
max(X, [], 2) % along the 2nd dimension
std(X, 0, 1) % along 1st dimension

Jan
Jan on 8 Oct 2013
acos(x) replies complex values, when the input is greater than 1.0 due to rounding errors. So either test abs(x) - 1 < 100*eps or a similar arbitrary limit, or use real(acos(x))

Jan
Jan on 8 Oct 2013
The non-functional form of commands is super edgy and the behavior changes with the Matlab versions:
fullfile * * % ok in Matlab 2009a, same as: fullfile('*', '*');
fullfile * p % fails in Matlab 2009a: '*' is assumed to be a multiplication
Both worked in older Matlab version and might work in 2013a again. There are many examples where numbers, operators and characters are treated differently depending on the command and the Matlab version.
While I use the non-functional form of commands in the command window, I avoid this strictly inside code, even for hold('on') to be consequent.

Jim Hokanson
Jim Hokanson on 10 Oct 2013
The dimensionality of a matrix is not always well specified. Using normal arrays, it is impossible to tell if a vector is really a vector or a 2d matrix (with one row or column), since all arrays carry with them two dimensions.
For example, the vector:
a = 1:5
has dimensions of 1x5. An equally valid assumption is that this is a 2d matrix. Scalars also suffer from this ambiguity, as they are a 2d matrix of size 1x1. This can lead to issues with file saving and interoperability.
What is perhaps not as obvious, is that higher order dimensions are not maintained explicitly in cases in which the dimension of interest, and all higher dimensions, have a size of 1. In this case all matrices implicity have 1 as the size for all higher order dimensions.
For example, the following indexing is completely valid:
a(1,3,1,1,1)
This would yield 3.
Consider however the following code: (NOTE: This is a very contrived example, but I've seen something like this before)
data = rand(5,4,6,7); %I'm obviously making this up
filter_dim = rand(1,7) > 0.5;
my_subset = data(:,:,1,filter_dim);
sz = size(my_subset);
%Do something with size ... temp = sz(3)*sz(4)
In this example, sz will either be of length 0, 2, or 4. Assuming that the real filter always kept one value, so that there is at least some data, then the surprising result is if only one value is kept from the last dimension, then:
size(data) => 5 4 6 7
goes to
size(my_subset) => 5 4
NOT
size(my_subset) => 5 4 1 1
  1 Comment
Jan
Jan on 10 Oct 2013
The trailing singelton dimensions vanish magically, such that ndims and size reply correct by unexpected results. Inside a MEX function you can create trailing singleton dimensions, which are not cleaned, when an array is provided as output.
Some functions accept and access of virtual trailing dimensions, some reject if the "dims" input is beyond ndims. I cannot test this currently, but try sum and filter.

Sign in to comment.

Categories

Find more on Programming in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!