I am using Matlab R2014a.
I have a 3-dimensional M x N x M matrix A. I would like a vectorized way to extract a 2 dimensional matrix B from it, such that for each i,j I have
B(i,j)=A(i,j,g(i,j))
where g is a 2-dimensional index matrix of size M x N, i.e. with integral values in {1,2,...,M}.
The context is that I am representing a function A(k,z,k') as a 3-dimensional matrix, the function g(k,z) as a 2-dimensional matrix, and I would like to compute the function
h(k,z)=f(k,z,g(k,z))
This seems like a simple and common thing to try to do but I really can't find anything online. Thank you so much to whoever can help!
My first thought was to try something like B = A(:,:,g) or B=A(g) but neither of these works, unsurprisingly. Is there something similar?
Try using
sub2ind
. This assumesg
is defined as anM
xN
matrix with possible values1
, ...,M
:You can employ the best tool for vectorization,
bsxfun
here -Explanation: Breaking it down to two steps
Step #1: Calculate the indices corresponding to the first two dimensions (rows and columns) of
A
-Step #2: Add the offset needed to include the dim-3 indices being supplied by
g
and index into A with those indices to get our desired output -Benchmarking
Here's a quick benchmark test to compare this
bsxfun
based approach against thendgrid + sub2ind
based solution as presented in Luis's solution withM
andN
as100
.The benchmarking code using
tic-toc
would look something like this -Here's the runtime results -
Conclusions
As you can see
bsxfun
based approach works really well, both as a vectorized approach and good with performance too.Why is
bsxfun
better here -bsxfun
does replication of offsetted elements and adding them, both on-the-fly.In the other solution,
ndgrid
internally makes two function calls torepmat
, thus incurring the function call overheads. At the next step,sub2ind
spends time in adding the offsets to get the linear indices, bringing in another function call overhead.