matrix of circulating vectors without loop

hi all , I want to built a matrix of circulating vectors without using loops
for example
input:
1 2 3 4
4 5 6 7
3 8 4 6
output :
1 2 3 4
4 1 2 3
3 4 1 2
2 3 4 1
4 5 6 7
7 4 5 6
6 7 4 5
5 6 7 4
3 8 4 6
6 3 8 4
4 6 3 8
8 4 6 3
I use the code
v =[1,2,3,4;4,5,6,7;3,8,4,6]
%notice the length of each vector in v is equal
len_rows=length(v(:,1));
len_cols=length(v(1,:));
mat_shifted=zeros(len_rows*len_cols,len_cols);
j=1;
for i=1:len_rows
vec=v(i,:);
mat=toeplitz([vec(1) fliplr(vec(2:end))], vec)
mat_shifted(j:j+len_cols-1,:)=mat
j=j+len_cols;
end
is there a smart way to do it without using loops , thanks in advance

 Accepted Answer

Not necessarily better in performance, but if you really want to avoid explicitly calling a loop, try
y = arrayfun(@(r)gallery('circul',x(r,:)),1:size(x,1),'UniformOutput',false);
cat(1,y{:})
HTH

4 Comments

hi , thanks :) , I want to avoid using loops since I want to work with huge matrix so I want matlab to use all the possible processors of the computer , so for my purpose do you think that the way you suggested would be better ?
"do you think that the way you suggested would be better ?"
Using arrayfun will be slower than using a for loop. The main advantage of arrayfun / cellfun is more compact code. For a large array you probably would not want to swap a fast loop for slow arrayfun.
Here is another way which should be more efficient and without explicit loop usage. But overall you want to find a tradeoff between time and memory when you deal with large data set.
x = [1 2 3 4;4 5 6 7;3 8 4 6];
[M,N] = size(x);
r = kron((1:M)',ones(N));
c = repmat(gallery('circul',1:N),M,1);
x(sub2ind([M,N],r,c))
HTH

Sign in to comment.

More Answers (2)

Stephen23
Stephen23 on 4 May 2018
Edited: Stephen23 on 4 May 2018
I think your concept is quite reasonable You could simplify the code a bit by using a cell array for the output, rather than keeping track of the rows:
M = [1,2,3,4;4,5,6,7;3,8,4,6];
N = size(M,1);
C = cell(N,1);
for k = 1:N
V = M(k,:);
C{k} = toeplitz([V(1),V(end:-1:2)],V);
end
Z = vertcat(C{:})
Still with a for loop, but somewhat more readable...
input = [1 2 3 4; ...
4 5 6 7; ...
3 8 4 6];
[m, n] = size(input);
output = zeros(m * n, n);
for s = 0:n-1
output((0:m-1) * n + s + 1, :) = circshift(input, s, 2);
end
expected = [1 2 3 4; 4 1 2 3; 3 4 1 2; 2 3 4 1; ...
4 5 6 7; 7 4 5 6; 6 7 4 5; 5 6 7 4; ...
3 8 4 6; 6 3 8 4; 4 6 3 8; 8 4 6 3];
assert(isequal(output, expected));

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!