In Matlab, I often have to work with matrices coming from another person's code, and there's not always a clear convention on the orientation of the matrices (transposed or not) and if a certain row/column is added. Therefore I spend much of my time debugging the following error
Error using *
Inner matrix dimensions must agree.
And similar errors for +
,.*
,-
,etc.
It would save me a lot of time if I could modify this error message to include the dimensions, so that I know which one to switch, and potentially guess where the wrong dimension got into. Hence, I would like to somehow modify the error message to include the dimensions at hand:
Error using *
Inner matrix dimensions must agree: 243 x 23 and 98 x 23.
Is this possible, and if so, how can I do it? I currently spend a lot of time adding/removing/testing debug code that prints out this info, so any solution that brings this any closer would be helpful!
You can use a try-catch
block:
a = rand(12);
b = rand(10);
try
c = a*b;
catch err
% Because err is read-only, generate new error structure
% We can copy most of old one
newerr.identifier = err.identifier;
newerr.cause = err.cause;
newerr.stack = err.stack;
newerr.message = sprintf('%s size(a): [%u, %u] size(b): [%u, %u]', err.message, size(a), size(b));
error(newerr) % Throw new error
end
Now we get:
Error using testcode (line 5)
Inner matrix dimensions must agree. size(a): [12, 12] size(b): [10, 10]
Each arithmetic operator in Matlab has an associated method that gets called when you invoke that operator. For example, the method corresponding to *
(matrix multiplication) is called mtimes
.
For each operator, you can define a method for variables of type double
that shadows the builtin method and modifies its behaviour: in your case, include custom error checking and then call the builtin method.
The advantages of this approach are:
No modification in your code is neccessary: you will use *
, *.
, +
etc normally; but their (error-checking) behaviour will change.
When (you think) you're done debugging, you only need to remove your custom methods from the path. This will restore normal behaviour and thus avoid any speed penalty. Later, if you need to debug again, all you need to do is place the modified methods back on the path.
In the following I use *
and its associated mtimes
as an example. Your new mtimes
method should be placed in Matlab's path, in an appropriate folder so that it has precedence over the bulitin mtimes
. That means the folder should be up in Matlab's path
. Or you can use the current folder, which has precedence over all others.
Within the selected folder create a folder called @double
, and in it create a file called mtimes.m
. This tells Matlab that your mtimes.m
file should be used whenever the *
is invoked with double
inputs.
The contents of mtimes.m
whould be something along the following lines:
function C = mtimes(A,B)
if ndims(A)~=2 || ndims(B)~=2
%// number of dimensions is incorrect
error('MATLAB:mtimes_modified:ndims', ...
'One of the arrays is not a matrix: numbers of dimensions are %i and %i',...
ndims(A), ndims(B));
elseif max(size(A))>1 & max(size(B))>1 size(A,2)~=size(B,1)
%// dimensions are not appropriate for matrix multiplication,
%// or for multiplying by a matrix by a scalar
error('MATLAB:plus_modified:dimagree',...
'Sizes do not match: %i x %i and %i x %i', ...
size(A,1), size(A,2), size(B,1), size(B,2));
else
C = builtin('mtimes', A, B); %// call actual mtimes to multiply matrices
end
Example results:
>> rand(3,4,5)*rand(6,7)
Error using * (line 3)
One of the arrays is not a matrix: numbers of dimensions are 3 and 2
>> rand(3,4)*rand(2,5)
Error using * (line 7)
Sizes do not match: 3 x 4 and 2 x 5
>> rand(3,4)*rand(4,2)
ans =
0.3162 0.3009
1.2628 0.7552
1.2488 0.8559
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With