Reputation: 3752
Can this for-loop be vectorized further?
for i = 1:length(formula)
ttable(i,abs(formula(i,:))) = -1*formula(i,:);
end
Where formula
is a matrix and ttable = NaN(length(formula),max(max(abs(formula))))
. Thanks!
Upvotes: 1
Views: 144
Reputation: 112659
Another approach, which usesbsxfun
to generate the linear indices:
ind = bsxfun(@plus, (1:size(ttable,1)).' , (abs(formula)-1)*size(ttable,1));
ttable(ind) = -formula;
Upvotes: 0
Reputation: 104464
Judging from the code, what you are doing is that for each row of ttable
, you wish to use the indices accessed by abs(formula(i,:))
and set each of these locations to -1*formula(i,:)
.
Noting @Divakar's clever spot, I am going to assume that each row has unique absolute values. In other words, each row should not have instances where you could have a
or -a
in a row, where a
is any number from 1
up to size(formula,2)
. The reason why is because in your computation of abs(formula(i,:))
, -a
and a
will then map to the same column. This will conflict and allow for overwriting into the same entry (Thanks @Divakar!)
What we can do is for each row of formula
, convert these locations into column-major indices to access ttable
. After, assign the corresponding values of -1*formula
into ttable
. In other words:
%// Find those columns that should be accessed
columnIndices = reshape(abs(formula).', 1, []);
%// For each column we are accessing, find the corresponding row
rowIndices = reshape(repmat(1:size(formula,2), size(formula, 1), 1), 1, []);
%// Find the column major indices we need to access overall
indices = sub2ind(size(formula), rowIndices, columnIndices);
%// Take those indices that we have computed above, and map them
%// to those columns we found earlier
ttable(indices) = -1*formula.';
Here is a small test I created. This is also based on the same assumption of unique absolute values that I made before:
formula = [1 2 -3 4; 4 -2 3 1; 3 2 4 -1; -4 1 2 3];
ttable = NaN(length(formula),max(max(abs(formula))));
formula =
1 2 -3 4
4 -2 3 1
3 2 4 -1
-4 1 2 3
ttable =
NaN NaN NaN NaN
NaN NaN NaN NaN
NaN NaN NaN NaN
NaN NaN NaN NaN
Using your approach, we get:
for i = 1:length(formula)
ttable(i,abs(formula(i,:))) = -1*formula(i,:);
end
ttable =
-1 -2 3 -4
-1 2 -3 -4
1 -2 -3 -4
-1 -2 -3 4
Using my approach, we get:
columnIndices = reshape(abs(formula).', 1, []);
rowIndices = reshape(repmat(1:size(formula,2), size(formula, 1), 1), 1, []);
indices = sub2ind(size(formula), rowIndices, columnIndices);
ttable(indices) = -1*formula.';
ttable =
-1 -2 3 -4
-1 2 -3 -4
1 -2 -3 -4
-1 -2 -3 4
If your matrix is small, then the computational overhead by doing this instead of the for
loop may be larger and so this will be inefficient. However, if your matrix is larger, then this code may be faster. Either way, I think your for
loop approach is still good. The JIT should kick in for for
loops. If you take a look at this post here when doing some timing tests for an algorithm where a for
loop was used as one of the algorithms, the for
loop was one of the algorithms that was the fastest. Check here: MATLAB: Subtracting matrix subsets by specific rows
Upvotes: 3