1
$\begingroup$

In my (admittedly brief) experience, there have been instances in which the code got uglier because []*[] == [], and it would be possible to write more elegant code if it was defined to be 0 instead.

For an example of such a piece of code, this part is supposed to compute x in L*x=b (L being a lower triangular matrix):

x(1) = b(1)/A(1,1);
for i=2:n
   x(i) = (b(i) - A(i,1:i-1)*x(1:i-1))/A(i,i);
end

The problem is that I have to make it by two separate cases. I do not think I am obsessed with code beauty, but this is not pleasant for me.

My question is: is there a way to make this work in a single for loop (not using isempty)? Also, I'd love to know if there is a reason I am unaware of for this particular choice the developers made.

Thank you.

$\endgroup$
4
  • 1
    $\begingroup$ Where are you using isempty? There are two places I could see it being checked, either before you current loop or inside the loop. $\endgroup$ – Godric Seer Oct 15 '14 at 15:37
  • 1
    $\begingroup$ What would you suggest that []*[] should return? It seems to me that the only sensible result of multiplying empty matrices is an empty matrix. Perhaps a more puzzling result is that ones(2,0)*ones(0,3) == zeros(2,3). $\endgroup$ – Doug Lipinski Oct 15 '14 at 18:50
  • 1
    $\begingroup$ At the risk of stating the obvious, you can (and should) compute x=L\b. An example where you vectorize the inner of two nested loops seems strange; is there another example you had in mind? The design decision in MATLAB seems to be that an $m$ by $n$ matrix times an $n$ by $k$ matrix is always an $m$ by $k$ matrix, even if some of $n$,$m$,and $k$ are zero. $\endgroup$ – Patrick Sanan Oct 15 '14 at 21:02
  • $\begingroup$ As @DougLipinski's answer points out, your code has a problem: it returns a row vector rather than a column vector; the two are quite different objects in Matlab, although in some points the syntax tries to hide it. When you fix it, everything works as expected. Also, note that your code never really uses [] (which is a $0\times 0$ empty matrix), but only $n\times 0$ and $0\times n$ matrices. These are also different things in Matlab, although in some points the syntax tries to hide it. $\endgroup$ – Federico Poloni Oct 16 '14 at 12:10
6
$\begingroup$

One option would be to initialize x = zeros(n,1) before you start your loop which should then go from 1 to n. In that case, the first time through the loop evaluates the term A(1,1:0)*x(1:0) would mean multiplying a 1x0 matrix by a 0x1 which MATLAB evaluates as 0.

This is relying on (in my opinion) a very non-intuitive behavior and I'm not sure the perceived benefit of "beauty" is worth the increased level of opacity in what's happening. I would file this under ' "optimizations" that are likely to bite you later'. On another note, you should probably be initializing x anyway so MATLAB doesn't have to keep growing the array.

The following code should work as expected:

x = zeros(n,1);
for i=1:n
    x(i) = (b(i) - L(i,1:i-1)*x(1:i-1))/L(i,i);
end

Edit:
Upon thinking about this a bit more. This behavior likely translates to many similar situations in MATLAB which is probably why the designers chose to make matrix multiplication a valid operation for any conformable matrices, even if the some of the array dimensions are zero. By defining the result of this matrix multiplication to be an appropriately sized array of zeros when the inner dimensions are both zero it is likely that the code just works as expected, even if the programmer doesn't think about the details of this corner case.

I'm still not sure this a great thing to rely on. It will likely confuse people and it will almost certainly fail if ported to other languages.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.