Row-wise individual circshift of a 3D-matrix without using a loop

Hello dear MATLAB community,
I'm looking for an alternative to perform "circshift" without using a loop to optimize code process time.
Let me first explain you what I want to do. I have several 3D data matrices "A(i,j,k)", that have to be circular shifted row by row for every dimension "k". The individual shift indices "RowsShift" for every single row in each dimension "k" are not equal.
% Input data matrix (3D): every single row should be shifted individually
% with its shifting index "RowsShift"; for example:
% - A(2,:,1) should be shifted by 3 (RowsShift(2,:,1))
% - A(4,:,3) should be shifted by -4 (RowsShift(4,:,3))
A(:,:,1) = [0 0 0 1 0 0 0 0;
1 0 0 0 0 0 0 0;
0 0 0 0 0 1 0 0;
0 1 0 0 0 0 0 0;
1 0 0 0 0 0 0 0];
A(:,:,2) = [0 0 0 1 0 0 0 0;
1 0 0 0 0 0 0 0;
0 0 0 0 0 1 0 0;
0 0 0 0 0 0 0 1;
0 0 0 0 0 0 1 0];
A(:,:,3) = [1 0 0 0 0 0 0 0;
1 0 0 0 0 0 0 0;
0 0 0 0 0 0 1 0;
0 0 0 0 1 0 0 0;
0 0 0 0 0 1 0 0];
% Matrix with circular shift indices
RowsShift(:,:,1) = [0;3;-2;2;3];
RowsShift(:,:,2) = [0;3;-2;-4;-3];
RowsShift(:,:,3) = [0;0;-6;-4;-5];
I can perform the matrix reordering using a loop and the "circshift" function and get the right result "B(i,j,k)":
% Old version with for looI canp and circular shift
for j = 1:size(A,3)
for i = 1:size(A,1)
B(i,:,j) = circshift(A(i,:,j),RowsShift(i,:,j));
end
end
B(:,:,1) =
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
B(:,:,2) =
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
B(:,:,3) =
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
My problem is that I have to circshift more than one 3D matrix with these dimension ("i" & "j" remains the same size) and the dimension "k" can be up to millions. My current version (loop & circshift) takes way to much time, so I'm looking for an alternative way.
Thanks in advance and best regards,
Pascal

4 Commenti

My problem is that I have to circshift more than one 3D matrix with these dimension ("i" & "j" remains the same size)
What about RowsShift? Does it vary with every different A?
Yes, it can vary with every different A(:,:,k).
Matt J
Matt J il 17 Giu 2021
Modificato: Matt J il 17 Giu 2021
No, I meant, do you reuse the same 3D RowsShift for every different 3D array A that you process? If so, you can just compute idx once in my answer below and reuse it. There is no need to redo any of the computations.
That's right. "RowsShift" is the same for all different 3D arrays. I already integrated your code snippet and calculate "idx" only once and reuse it for all 3D input matrices.

Accedi per commentare.

 Risposta accettata

Matt J
Matt J il 16 Giu 2021
Modificato: Matt J il 16 Giu 2021
%%% Precomputations - do this block only once
[m,n,p]=size(A);
[I,J,K]=ndgrid(1:m,1:n,1:p);
%%%
Jshift=mod(J-RowsShift-1,n)+1;
idx=sub2ind([m,n,p], I,Jshift,K);
B=A(idx);

Più risposte (0)

Categorie

Prodotti

Release

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by