MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

### Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

# Simple Question about Optimization of Nested IF-FOR loops

Asked by Mohsen on 17 Jun 2013

Does any one know how to optimize this code so that it runs faster:

```    for i=1:iNZ;
if iPointsinSlice>0;
for m=1:iNX;
for l=1:iNY;
DoseCubeU(m+(l-1)*iNX+i*iNX*iNY)=100*SumDose(m,l,i)/RX_Dose;
end
end
end
end
end```

Your help is much appreciated! Thanks a lot!

## Products

Answer by Roger Stafford on 17 Jun 2013

Is 'iPointsinSlice' a scalar? If so and if it is not positive, nothing will happen here.

Next, don't you mean "m+(l-1)*iNX+(i-1)*iNX*iNY" as the index to 'DoseCubeU'? As it stands it will vary from 1+iNX*iNY to iNX*iNY*iNZ+iNX*iNY. Assuming my guess is correct, do this:

``` if iPointsinSlice > 0
DoseCubeU(t) = (100/RX_Dose)*SumDose(t);
end```

In case 'iPointsinSlice' is not a scalar you will have to correct your code before we can see how to handle it.

## 1 Comment

Mohsen on 17 Jun 2013

'iPointsinSlice' is a scalar. "m+(l-1)*iNX+(i-1)*iNX*iNY" is used as the index to 'DoseCubeU. But your code gives the error that REPMAT has too many arguments. How should I fix it?

Answer by Roger Stafford on 17 Jun 2013

Sorry! It should have been:

` t = repmat(SliceMaskUr==1,[1,1,iNZ]);`

## 1 Comment

Mohsen on 18 Jun 2013

I changed

DoseCubeU(m+(l-1)*iNX+i*iNY*iNX)=100*SumDose(m,l,i)/RX_Dose;

to

DoseCubeU(double(m)+double((l-1))*double(iNX)+double((i-1))*double(iNY)*double(iNX))=100*SumDose(m,l,i)/RX_Dose;

Otherwise the indexing will not be correct. For example, iNX*iNY*iNZ (which is 120*120*11) becomes equal to 65535 (which is wrong). We should write it as double(iNX)*double(iNY)*double(iNZ) in order to get the correct results (ie. 158400).

By making this change, both the indexing (the initial) method and the subscription method (below) give the same results. But these results are different than any of the other proposed methods.

So, how can I optimize:

```    for i=1:iNZ;
if iPointsinSlice>0;
for m=1:iNX;
for l=1:iNY;
DoseCubeU(m,l,i)=100*SumDose(m,l,i)/RX_Dose;
end
end
end
end
end```
Answer by Mohsen on 17 Jun 2013

This code doesn't give me the same result as my initial code. Please note that the purpose of "m+(l-1)*iNX+i*iNX*iNY" is to reshape the SumDose array which is (iNX by iNY by iNZ) to a one dimensional array (1 by iNX*iNY*iNZ).

I tried also

```                    if SliceMaskUr==1;
DoseCubeU= reshape(SumDose,1,[iNX iNY iNZ])*(100/RX_Dose);
end```

but it didn't work neither...

Any insight?

Mohsen on 18 Jun 2013

Thank you for your reply. In my original code, I changed "m+(l-1)*iNX+i*iNX*iNY" to "m+(l-1)*iNX+(i-1)*iNX*iNY" so that the index of DoseCubeU is from 1 to iNX*iNY*iNZ.

Both DoseCubeU and SumDose are of sizes iNX-by-iNY-by-iNZ.

However, your code still gives me a different answer than my original code.

As a test, in order to use the subscription notation instead of indexing, I just modified my code to the following and surprisingly the results are again different from the two previous methods:

```    for i=1:iNZ;
if iPointsinSlice>0;
for m=1:iNX;
for l=1:iNY;
DoseCubeU(m,l,i)=100*SumDose(m,l,i)/RX_Dose;
end
end
end
end
end```

This is confusing!!

Mohsen on 18 Jun 2013

I think that the function poly2mask is in charge of these discrepancies. Any idea why? Here is the entire code:

iNNX=double(iNX);

iNNY=double(iNY);

`    for i=1:iNZ;`
`        iPointsinSlice=1;`
```        for j=1:iNCUr;
if UrContourZ(j)==ZSlice(i);
iPointsinSlice = iPointsinSlice+1;
UrPointX(iPointsinSlice-1)=1 + (UrContourX(j)-Offset(1,1));
UrPointY(iPointsinSlice-1)=1 + (UrContourY(j)-Offset(2,1));
end
end```
```        if iPointsinSlice>0;
indx=round(iPointsinSlice);
indy=round(iPointsinSlice);```
```            indx(1:iPointsinSlice-1)=UrPointX(1:iPointsinSlice-1)/DresX;
indy(1:iPointsinSlice-1)=UrPointY(1:iPointsinSlice-1)/DresY;```
`            SliceMaskUr = poly2mask(indx,indy,iNNX,iNNY);`
```            for m=1:iNX;
for l=1:iNY;
DoseCubeU(m+(l-1)*iNX+(i-1)*iNY*iNX)=100*SumDose(m,l,i)/RX_Dose;
end
end
end
end
end```

Your help is much appreciated! :)

Mohsen on 18 Jun 2013

I changed

DoseCubeU(m+(l-1)*iNX+i*iNY*iNX)=100*SumDose(m,l,i)/RX_Dose;

to

DoseCubeU(double(m)+double((l-1))*double(iNX)+double((i-1))*double(iNY)*double(iNX))=100*SumDose(m,l,i)/RX_Dose;

Otherwise the indexing will not be correct. For example, iNX*iNY*iNZ (which is 120*120*11) becomes equal to 65535 (which is wrong). We should write it as double(iNX)*double(iNY)*double(iNZ) in order to get the correct results (ie. 158400).

By making this change, both the indexing (the initial) method and the subscription method (below) give the same results. But these results are different than any of the other proposed methods.

So, how can I optimize:

```    for i=1:iNZ;
if iPointsinSlice>0;
for m=1:iNX;
for l=1:iNY;
DoseCubeU(m,l,i)=100*SumDose(m,l,i)/RX_Dose;
end
end
end
end
end```
Answer by Andrei Bobrov on 18 Jun 2013
Edited by Andrei Bobrov on 19 Jun 2013
```DoseCubeU = bsxfun(@times,100*SumDose/RX,SliceMaskUr==1);
```

```s = SliceMaskUr(end:-1:1,end:-1:1);
tt = cumsum(cumsum(s),2);
t1 = flipud(any(tt,2));
t2 = fliplr(any(tt));
```

Mohsen on 18 Jun 2013

I think that the function poly2mask is in charge of these discrepancies. Any idea why? Here is the entire code:

iNNX=double(iNX);

iNNY=double(iNY);

`    for i=1:iNZ;`
`        iPointsinSlice=1;`
```        for j=1:iNCUr;
if UrContourZ(j)==ZSlice(i);
iPointsinSlice = iPointsinSlice+1;
UrPointX(iPointsinSlice-1)=1 + (UrContourX(j)-Offset(1,1));
UrPointY(iPointsinSlice-1)=1 + (UrContourY(j)-Offset(2,1));
end
end```
```        if iPointsinSlice>0;
indx=round(iPointsinSlice);
indy=round(iPointsinSlice);```
```            indx(1:iPointsinSlice-1)=UrPointX(1:iPointsinSlice-1)/DresX;
indy(1:iPointsinSlice-1)=UrPointY(1:iPointsinSlice-1)/DresY;```
`            SliceMaskUr = poly2mask(indx,indy,iNNX,iNNY);`
```            for m=1:iNX;
for l=1:iNY;
DoseCubeU(m+(l-1)*iNX+(i-1)*iNY*iNX)=100*SumDose(m,l,i)/RX_Dose;
end
end
end
end
end```

Your help is much appreciated! :)

Mohsen on 18 Jun 2013

I changed

DoseCubeU(m+(l-1)*iNX+i*iNY*iNX)=100*SumDose(m,l,i)/RX_Dose;

to

DoseCubeU(double(m)+double((l-1))*double(iNX)+double((i-1))*double(iNY)*double(iNX))=100*SumDose(m,l,i)/RX_Dose;

Otherwise the indexing will not be correct. For example, iNX*iNY*iNZ (which is 120*120*11) becomes equal to 65535 (which is wrong). We should write it as double(iNX)*double(iNY)*double(iNZ) in order to get the correct results (ie. 158400).

By making this change, both the indexing (the initial) method and the subscription method (below) give the same results. But these results are different than any of the other proposed methods.

So, how can I optimize:

```    for i=1:iNZ;
if iPointsinSlice>0;
for m=1:iNX;
for l=1:iNY;
DoseCubeU(m,l,i)=100*SumDose(m,l,i)/RX_Dose;
end
end
end
end
end```
Andrei Bobrov on 19 Jun 2013

Corrected. See ADD part in my answer.

Answer by Iain on 18 Jun 2013

Try:

``` DoseCubeU(NY,NX,NZ) = 0; % or any suitable initialisation
if iPointsinSlice>0;
end```

Mohsen on 18 Jun 2013

This gives me a different answer than all the other four methods!

Mohsen on 18 Jun 2013

I changed

DoseCubeU(m+(l-1)*iNX+i*iNY*iNX)=100*SumDose(m,l,i)/RX_Dose;

to

DoseCubeU(double(m)+double((l-1))*double(iNX)+double((i-1))*double(iNY)*double(iNX))=100*SumDose(m,l,i)/RX_Dose;

Otherwise the indexing will not be correct. For example, iNX*iNY*iNZ (which is 120*120*11) becomes equal to 65535 (which is wrong). We should write it as double(iNX)*double(iNY)*double(iNZ) in order to get the correct results (ie. 158400).

By making this change, both the indexing (the initial) method and the subscription method (below) give the same results. But these results are different than any of the other proposed methods.

So, how can I optimize:

```    for i=1:iNZ;
if iPointsinSlice>0;
for m=1:iNX;
for l=1:iNY;