scmg
scmg

Reputation: 1894

matlab - unfixed dimension matrix, set value to multiple fields of struct at once, avoid loop

I have 2 (not very small) 3-dimension structs with matrices as fields:

sz1 = 200;
sz2 = 9;
sz3 = [20, 40, 80, 160, 320, 640, 1280, 2560, 5120]
% actually the structs have 12 fields, each has size 200x9x5120
mat.p1(sz1, sz2, sz3(sz2)) = uint8(0);
mat.p2(sz1, sz2, sz3(sz2)) = uint8(0);
mat.p3(sz1, sz2, sz3(sz2)) = 0;
mat.p4(sz1, sz2, sz3(sz2)) = 0;
old_mat.p1(sz1, sz2, sz3(sz2)) = uint8(0);
old_mat.p2(sz1, sz2, sz3(sz2)) = uint8(0);
old_mat.p3(sz1, sz2, sz3(sz2)) = 0;
old_mat.p4(sz1, sz2, sz3(sz2)) = 0;

And i need to write a reset function, where i will re-assign the values to 3 of 4 (actually 10 of 12) fields in both matrices as follows:

for i = 1:sz1
  for j = 1:sz2
    for k = 1:sz3(j)
      mat.p1(i,j,k) = uint8(255);
      mat.p3(i,j,k) = -1;
      mat.p4(i,j,k) = 0.01;
      old_mat.p1(i,j,k) = uint8(255);
      old_mat.p3(i,j,k) = -1;
      old_mat.p4(i,j,k) = 0.01;
    end
  end
end

Note that actually what i need in the matrices is the same as the reset function, means i only need the 5120th index of the 3rd-dimension when 2nd-dimension is 9, if 2nd-dimension = 4, i only need up to 160 indices at 3rd-dimension etc.

The questions are:

  1. Is there anyway to assign values to the fields at the same time (not 1 line 1 field) since i actually have to do with 10 fields?
  2. Is there anyway to avoid the for-loops? I tried like this:

    mat.p1(:) = uint8(255);
    mat.p3(:) = -1;
    mat.p4(:) = 0.01;
    old_mat.p1(:) = uint8(255);
    old_mat.p3(:) = -1;
    old_mat.p4(:) = 0.01;
    

    but here all the matrices are filled with max 3rd-dimension = 5120 so i expect someone can show me how to use the vectorizing function like arrayfun, bsxfun, cellfun etc., which can apply for just the "half-cubic" like the for-loops above.

UPDATE: Thanks horchler for the video, it seems the problem with big size (in bytes) of the matrices is solved when i change the matrix of struct to a struct with matrices as fields. This also clears the timing problem even with nested for-loops. So i updated the questions and the input as well, please see above.

Upvotes: 1

Views: 89

Answers (1)

horchler
horchler

Reputation: 18504

Yes, I think that using a structure of arrays will work better for you here. You should be able to allocate using zeros just as if mat.p1, mat.p2, etc. were regular arrays. I'd do something like this (note that you didn't indicate any values for mat.p2) using a single for loop:

sz1 = 200;
sz2 = 9;
sz3 = [20, 40, 80, 160, 320, 640, 1280, 2560, 5120];
% Be careful with this form of pre-allocation if your sz arrays change
% Clear your struct or make sure to use the code in a function 
mat.p1(sz1,sz2,sz3(sz2)) = uint8(0);
mat.p3(sz1,sz2,sz3(sz2)) = 0;
mat.p4(sz1,sz2,sz3(sz2)) = 0;
for i = 1:sz2
    mat.p1(:,i,1:sz3(i)) = uint8(255);
    mat.p3(:,i,1:sz3(i)) = -1;
    mat.p4(:,i,1:sz3(i)) = 0.01;
end
old_mat.p1 = mat.p1;
old_mat.p3 = mat.p3;
old_mat.p4 = mat.p4;

Alternatively, you could do something like this:

sz1 = 200;
sz2 = 9;
sz3 = [20, 40, 80, 160, 320, 640, 1280, 2560, 5120];
mat = struct('p1',zeros(sz1,sz2,sz3(sz2),'uint8'),...
             'p3',zeros(sz1,sz2,sz3(sz2)),...
             'p4',zeros(sz1,sz2,sz3(sz2)));
for i = 1:sz2
    mat.p1(:,i,1:sz3(i)) = uint8(255);
    mat.p3(:,i,1:sz3(i)) = -1;
    mat.p4(:,i,1:sz3(i)) = 0.01;
end
old_mat = struct('p1',mat.p1,'p3',mat.p3,'p4',mat.p4);

Upvotes: 1

Related Questions