MATLAB: Circshift columns and rows with different shifting units

alternate method for circshiftcircshiftfaster versions of circshiftperformance

how to vectorise this code to reduce the runtime:
clear;
clc;
profile on
tic
A=magic(5);
x=[5 2 1 4 3];
I=zeros(length(x));
for u=1:length(x)
I(:,u)=circshift(A(:,u),[x(u) 0]);
end
toc

Best Answer

A vectorization would not be very efficient: Instead of creating the output directly, you'd have to create an index matrix in addition. Try to accelerate the code by inlining circshift:

A = magic(5);
x = [5 2 1 4 3];
tic
I = zeros(size(A));
R = size(A, 1);
for u = 1:length(x)
    % I(:,u) = circshift(A(:, u), [x(u) 0]);
    % Inlined CIRCSHIFT:
    index   = mod(-x(u):R-1-x(u), R) + 1;
    I(:, u) = A(index, u);
end
toc

If A is a 1000x1000 matrix, this takes 0.0276 seconds instead of 0.0812 seconds with circshift.

Now mod is the bottleneck. We can move it out of the loop, or even omit it, if all x are inside [1, size(A,1)]:

I = zeros(size(A));
R = size(A, 1);
x = mod(x - 1, R) + 1;  % X -> [1, R], omit this line if not required
for u = 1:length(x)
    index   = [R-x(u)+1:R, 1:R-x(u)];
    I(:, u) = A(index, u);
end

This runs in 0.0138 seconds.