Last week I received email from a blog reader asking about extending the meaning of the arithmetic operators to do more than scalar expansion, and instead extend the expansion to singleton dimensions. In this post, I discuss the evolution of scalar expansion in MATLAB, talk about possible future designs, and open up the discussion to your input. In that spirit, please add your comments on this topic here.
In very early versions of MATLAB, you could rely on scalars expanding when you were performing element-wise arithmetic. In the following code, for example,
A = magic(3); B = 2; C = A + B;
the scalar B is added to each element of A.
It wasn't until MATLAB version 5 and the introduction of N-dimensional arrays, that scalar expansion extended to assignment, e.g.,
D(3:5,1:2) = 17
D = 0 0 0 0 17 17 17 17 17 17
replacing the need for forming a right-hand side exactly the same size as the left-hand side.
Judging from the number of newsgroup posts (see a few at these links: 1 2 3 4 5 ), there is a lot of interest in having way to express calculations concisely that don't involve scalars or arrays that match completely but for which there is a reasonable interpretation, for example, calculating A - mean(A) where A is a matrix.
Let's suppose we want to add a constant value to each column of a matrix. Here are some ways we might do it today, all of which require at least some temporary extra memory from MATLAB. If the matrix is large, then the temporary of the second variable will also be large, and may consume a substantial additional amount of memory.
row = 1:4; mat = [magic(3) (10:12)']
mat = 8 1 6 10 3 5 7 11 4 9 2 12
Loop over columns of matrix, adding a scalar value to each one
out = mat; for c = 1:length(row) out(:,c) = out(:,c) + row(c); end
Expand the rows into a larger matrix the size of mat 3 different ways.
The first way is via indexing into the row vector, a technique known as Tony's trick because a customer, Tony, showed it to me at the ICASSP conference in Albuquerque in 1990
out1 = mat + row(ones(1,size(mat,1)),:);
The second way it to use repmat which essentially uses Tony's trick in most cases.
out2 = mat + repmat(row, size(mat,1),1);
The third variant is to use an outer product to duplicate the rows.
out3 = mat + ones(size(mat,1),1) * row;
Let's make sure our answers are all the same.
ans = 1
Doug Schwarz, a longtime MATLAB user, has developed a library of generalized operators which could also be used to solve this class of problem (and more).
There are four alternatives I can think of for dealing with expansion beyond scalars.
- Keep the status quo since there are already many ways to accomplish what users want.
- Create new functions to flexibly deal with combining different size arrays for elementwise (and perhaps matrix) operations.
- Change the basic operators in MATLAB such as + to accomodate commensurate but not identically sized arrays.
- Invent new operator notation to accomodate the sort of binary elementwise operations we've discussed so far.
Each of the above ideas has pros and cons. We've talked to some users in the past about this topic and their reactions generally fell into three buckets:
- loved the idea of changing the meaning of the elementwise operators so, for example, row+column would do an "outer" sum.
- hated the idea of changing the meaning of existing operators, for reasons of both readability and backward compatibility.
- indifferent (this was, by far, the smallest group!).
Now it's your turn to chime in. Please leave your thoughts on this topic here.