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

조회 수: 34 (최근 30일)
Pascal Wielsch
Pascal Wielsch 2021년 6월 16일
댓글: Pascal Wielsch 2021년 6월 17일
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
Matt J
Matt J 2021년 6월 17일
편집: Matt J 2021년 6월 17일
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.
Pascal Wielsch
Pascal Wielsch 2021년 6월 17일
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.

댓글을 달려면 로그인하십시오.

채택된 답변

Matt J
Matt J 2021년 6월 16일
편집: Matt J 2021년 6월 16일
%%% 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);

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

제품


릴리스

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by