Iteration without any loop.

I am working on B-spline, this code is to get a matrix as an output.
function [M] = Iterations(N) % N is an input variable
I=eye(N+1);M=zeros(N+1,N+1); % I is a diagnal matrix and M is inicially a zero matrix
for i=0:N/2 % interations
n=i:N-i;
b=(-1).^(N-n-i).*factorial(N-i)./factorial(n)./factorial(N-n-i).*(factorial(N)./factorial(N-i)./factorial(i));
M(i+1,i+1:N+1-i)=b;
end
M = rot90(fliplr(M),1)+M-diag(M).*I; % Output matrix
end
Ans
M =
-1 3 -3 1
3 -6 3 0
-3 3 0 0
1 0 0 0
I was wondering is there anyway i can remove a loop from inside the function here?

Antworten (2)

Walter Roberson
Walter Roberson am 4 Feb. 2021

0 Stimmen

[M] = Iterations(3)
M = 4×4
-1 3 -3 1 3 -6 3 0 -3 3 0 0 1 0 0 0
function [M] = Iterations(N) % N is an input variable
I=eye(N+1);M=zeros(N+1,N+1); % I is a diagnal matrix and M is inicially a zero matrix
i=0:N/2; % interations
n=(0:N).';
b = (-1).^(N-n-i).*gamma(N-i+1)./factorial(n)./gamma(N-n-i+1).*(factorial(N)./gamma(N-i+1)./factorial(i));
M = [tril(b).'; zeros(size(b.'))];
M = rot90(fliplr(M),1)+M-diag(M).*I;
end

1 Kommentar

Jan
Jan am 5 Feb. 2021
This fails for even N:
Matrix dimensions must agree.
Error in kjh>Iterations_4 (line 84)
M = rot90(fliplr(M),1)+M-diag(M).*I;

Melden Sie sich an, um zu kommentieren.

Jan
Jan am 5 Feb. 2021
Bearbeitet: Jan am 5 Feb. 2021

0 Stimmen

Why do you want to do this without a loop? When the purpose is an acceleration, omit the expensive factorial and power operations at first:
function M = Iterations(N)
F = [1, cumprod(1:21)]; % Emulated factorial()
sF = F;
sF(2:2:22) = -sF(2:2:22); % Include expensive power operation -1^(N-n-i)
FN = F(N+1);
M = zeros(N+1, N+1);
for i = 0:N/2
t = N - i + 1;
b = F(t) ./ F(i+1:t) ./ sF(t-i:-1:1) .* (FN ./ F(t) ./ F(i+1));
M(i+1, i+1:t) = b;
M(i+1:t, i+1) = b;
end
end
For N = 10 this is needs 16% of the runtime of the original.
But due to the factorial the output will be accurate for N <= 21. If you need such a small set of inputs only, it would be more efficient, to create a list of possible values once and store it in a persistent varibale.
function M = IterationsX(N)
persistent List
if isempty(List)
List = cell(1, 21);
for k = 1:21
List{k} = Iterations(k);
end
end
M = List{N};
end

7 Kommentare

hyder abedi
hyder abedi am 5 Feb. 2021
Thanks for improving the code and giving me a different way of writing it. I was just curious whether this or any iteration can be done without a loop at all. yet the question remains.
And how did you calculate the runtime?
Image Analyst
Image Analyst am 5 Feb. 2021
You can use tic and toc to measure elasped seconds.
For loops are not always slow. How big is your N? Unless your N is like hundreds of millions, I doubt the loop will take more than a fraction of a second. For N = 10 or 21, you're looking at an elapsed time of like microseconds.
hyder abedi
hyder abedi am 5 Feb. 2021
It depends on number of variables in my dataset, right now its 8 but it can be 100 or more.
Jan
Jan am 5 Feb. 2021
factorial(100) is 9.3e157. BSplines with so many points cannot be calculated accurately anymore, because the double values contain the first 16 digits only.
Walter Roberson
Walter Roberson am 5 Feb. 2021
When you have factorial divided by factorial, consider using pochhammer; https://www.mathworks.com/help/symbolic/pochhammer.html
hyder abedi
hyder abedi am 5 Feb. 2021
Thanks again Jan i wasn't aware that double values contain the first 16 digits only.
hyder abedi
hyder abedi am 5 Feb. 2021
Thanks Walter Roberson.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Elementary Math finden Sie in Hilfe-Center und File Exchange

Produkte

Version

R2020a

Gefragt:

am 4 Feb. 2021

Kommentiert:

am 5 Feb. 2021

Community Treasure Hunt

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

Start Hunting!

Translated by