how to pass parameters by reference in matlab function - matlab

i'm a beginner in matlab and i want to calculate the sum of product of every possible combination of elements of a (3*n) matrix that are picked from different row.
for example if the matrix is x = [1 2 3 , 4 5 6] i want the result of
D = 1*4 + 1*5 + 1*6 + 2*4 + 2*5 + 2*6 + 3*4 + 3*5 + 3*6.
I wrote the following recursive code but i'm having problem with passing a variable by reference.
function combination(n,A,x) % n= number of rows ,A= empty array, x = the matrix
if n == 0
D = D + prod(A);
else
for i = 1:1:3
A = [A x(n,i)];
combination(n-1,A,x);
if length(A)>=1
A = A(1:length(A)-1);
end
end
end
end
i need the D parameter but when i declare D as global it doesn't help.
is there anyway in matlab that i could pass D by reference in function and get the result at the end?
thanks in advance.
sorry for my english.

Can you just use prod(sum(x,2))? I think if you rearrange the terms in your sum, you'll see that you can just multiply the sums of your rows together and you'll get the same thing. (But perhaps I've misunderstood exactly what you're looking for).
For example:
>> x=[1 2 3 ; 4 5 6; 7,8,9]
x =
1 2 3
4 5 6
7 8 9
>> prod(sum(x,2))
ans =
2160
>> 1*4*7 + 1*4*8 + 1*4*9 + 1*5*7 + 1*5*8 + 1*5*9 + 1*6*7 + 1*6*8 + 1*6*9 + 2*4*7 + 2*4*8 + 2*4*9 + 2*5*7 + 2*5*8 + 2*5*9 + 2*6*7 + 2*6*8 + 2*6*9 + 3*4*7 + 3*4*8 + 3*4*9 + 3*5*7 + 3*5*8 + 3*5*9 + 3*6*7 + 3*6*8 + 3*6*9
ans =
2160
If you really need to do this recursively, using a combinatory approach, you should be able to just pass in D as an input and also return it as an output of your function, something like this:
function D = combination(n,A,x, D) % n= number of rows ,A= empty array, x = the matrix
if n == 0
D = D + prod(A);
else
for i = 1:1:3
A = [A x(n,i)];
D = combination(n-1,A,x, D);
if length(A)>=1
A = A(1:length(A)-1);
end
end
end
end
and then call it initially with D equal to zero.
Don't worry about passing by reference here. MATLAB doesn't have pass by reference (it has variables that have reference semantics, but that's a different thing), but it uses copy-on-write, and has special optimizations for calculations that can be done in-place, as your calculation with D can here.

Declaring it as global does the job, however, you should pass it as input, and return it as output.
MATLAB will take care of not making a copy if your code does not need a copy of it.

If you write in the function definition:
function D = combination(n,A,x,D)
D = D + something
end
your function can be called by:
output = combination(n_in,A_in,x_in
the recursion follows the same so instead of calling
combination(n-1, A,x)
you write
D = combination(n-1,A,x,D)
and go on in your code.
I hope this helps you, and maybe there is a Matlab own function that can handle this task already but I am not sure.

Related

Generating the Fibonacci Sequence in Matlab using recursive function NOT using any loop

I am trying to write a recursive matlab function that takes one argument and generates the fibonacci sequence up to n. The codes I have found everywhere either output only the n-th term or use loops to output the whole sequence. Now I am not allowed to use any kind of loops, just pure recursive function. I will highly appreciate if anyone can share his/her thoughts. Thanks in advance.
I am copying the code that gives the n-th term only for convenience.
function f = fibor(n)
if n == 1 || n == 2
f = 1;
else
f = fibor(n-1) + fibor(n-2);
end
end
Maybe you can try the code below, which saves the outputs
function f = fibor(n)
if n <= 2
f = ones(1,n);
else
u = fibor(n-1);
f = [u,sum(u(end-1:end))];
end
end
which gives
>> fibor(5)
ans =
1 1 2 3 5
>> fibor(10)
ans =
1 1 2 3 5 8 13 21 34 55

Im looking for a single line operation to create this matrix: [duplicate]

This is code
for i = 1 : 5
b = i;
a=cumsum(b);
end
fprintf('%f \n', a);
I expected 1 + 2 + 3 + 4 + 5 = 15 so I would print 15 at the end.
But it output 5.000000.
If i code "a = cumsum (b)" outside the for loop, it will not be calculated
How can I get the value I want 1 + 2 + 3 + 4 + 5?
Thanks you
cumsum performs something like integration, where each element of the output is the sum of all elements up to that position (including) of the input vector.
Your code doesn't work because you pass a single value into cumsum and there is no mechanism by which the previous result is saved, so you end up having only a single value, which is the last one - 5.
You don't need a loop for this, nor even cumsum - just write sum(1:5) to get the desired result.
This is not how cumsum works. It takes the cumulative sum of an array the example below may explain better
a = 1:5;
b = cumsum(a); % b = [1, 3, 6, 10, 15]
c = sum(a) % add up all the elements c = 15
Does that help?

what is exactly the content of 'zf' in MATLAB function filter

I know that in order to filter large amount of data in chuncks, it it possible to use the function 'filter' with the appropriate filter coefficients,
and pass the final conditions 'zf' to the next chunk as its initial conditions 'zi'.
I am confused.
what is exactly the content of 'zf'?
does it hold the last relevant input samples? (in pure FIR filter)
the last relevant ouput samples? (in IIR)
what does it hold when both last inputs and last outputs are relevant?
thanks a lot
In case we have a large set of data or we are short in memory the zf and zi options will come in handy.
For example we can divide our data in two parts, x and newx, and use the filter function like,
[y,zf] = filter(b,a,x);
newy = filter(b,a,newx,zf);
For a filter with a and b as in,
we will be referring back to length(a) -1 samples of y and length(b) -1 samples of x.
So for continuing our filter over the second half we will need max(length(a),length(b)) -1 calls from the first half.
Example 1
y[n] = x[n] + 2 * x[n-1] + 3 * x[n-2];
which is,
a = 1;
b = [1 2 3];
example input and output are,
x = [1 2 3 4 5 6 7 8 9];
y = [1 4 10 16 22 28 34 40 46];
zf = [42 27]';
Implementing the filter over newx, for first two samples we have,
newy[1] = newx[1] + 2*9 + 3*8 = newx[1] + 42 = newx[1] + zf[1];
newy[2] = newx[2] + 2 * newx[1] + 3*9 = newx[2] + 2 * newx[1] + zf[2];
Example 2
x = 1 : 9;
b = [1 1 1];
a = [1 2];
[y,zf] = filter(b,a,x);
This corresponds to y[n] = x[n] + x[n-1] + x[n-2] - 2*y[n-1].
The inputs and outputs are:
x = [1 2 3 4 5 6 7 8 9];
y = [1 1 4 1 10 -5 28 -35 94];
zf = [-171 9]';
Now for the first value of second half:
newy[1] = newx[1] + 9 + 8 - 2 * 94 = newx[1] - 171 = newx[1] + zf(1);
newy[2] = newx[2] + newx[1] + 9 - 2*newy[1] = newx[2] + newx[1] + zf(2) - 2*newy[1];
So I think it's pretty obvious now, how zf works.
The values in zf contain the internal state of the IIR filter. There are various ways how these filters are implemented in practice, but in all of them there are some delay elements, which pass some values to the next iteration. See for example this section of the wikipedia entry about digital filters. In the 'direct form 1', there are some delay elements to hold the last few inputs and and some other delay elements to hold the last few outputs. In the 'direct form 2', the delay elements contain some intermediate results. Independent of the exact implementation, these memory locations should be restored to not cause any glitches in the output when processing the data in chunks.
When processing data in chunks, you should use the function filter like this:
filter_state = []; % start with empty state
for i = 1:num_chunks
input_chunk = get_chunk(i);
[output_chunk, filter_state] = filter(b, a, input_chunk, filter_state);
save_chunk(i, output_chunk)
end

Making a function sensitive for vector input

This is for my course in numerical methods. I am trying very hard to understand MATLAB and its syntax but I am 100% self-taught, so please bear with me if my attempts seem ridiculous.
I have written this very easy function to approximate the number e
function e= calcEulerLimit(n)
e = (1 + 1./n).^n;
end
This is the 'basic' definition of the number e using a limit n to infinity approach. For MATLAB I defined the following vector (when I am talking about n in the latter, I am always referring to this vector n)
n=[1:1:10]=[ 1 2 3 4 5 6 7 8 9 10 ]
and the output works just fine as I expected, it is sensitive towards the vector n input when I call my function in MATLAB.
>> calcEulerlimit(n)
ans =
2.0000 2.2500 2.3704 2.4414 2.4883 2.5216 2.5465 2.5658 2.5812 2.5937
Now I want to do the exact same as above with a Taylor Approach, using the infinite summation formula to describe e, here is where I am stuck, the following simple code works:
function e = calcEulerSum(n)
e=1; % base-case, start variable
for i=1:1:n % for loop with step size one
e=e+1/factorial(i)
end
end
but this input, of course, does not work when I want to enter a vector such as n that computes through all variables.
I tried something along the line with another for loop, and a while loop, but the while loop seems to never terminate:
function e = calcEulerSum3(n)
while n
e=1;
e = e + 1./cumprod(n);
end
end
Using cumprod(n) to get the factorial value of each column element of my vector n.
You're trying to vectorize your function. Your solution for scalars works so let's look at what it's doing as i is incremented:
e0 = 1;
i = 1: e(1) = e0 + 1/factorial(1)
i = 2: e(2) = e(1) + 1/factorial(2) = e0 + 1/factorial(1) + 1/factorial(2)
= e0 + sum(1./factorial(1:2))
i = 3: e(3) = e(2) + 1/factorial(3) = ...
= e0 + sum(1./factorial(1:3))
...
i = n: e(n) = e(n-1) + 1/factorial(n) = e0 + 1/factorial(1) + ... + 1/factorial(n)
= e0 + sum(1./factorial(1:n))
So can you come up with a general expression to calculate the vector e given n? The cumsum function will come in handy.
for i=whatsoever,statement(i);end executes the statement on every element of whatsoever. If it is a single number, then on this one, if it is a vector/array, then on every element of it.
1:1:n creates an array of integers from 1 to n on the spot (1:n would do, too). If n already is a vector with the elements you want to iterate over, you can use it directly: for i=n.
However, why did you use the dotted versions of operations in your first and third code block, but not your second? Because you read about MATLAB's vectorization? Then you seem to be on the right track, but remember that the point vectorization is to get rid of an explicit loop entirely.
function e = calcEulerSum(n)
e=nan(1,length(n)); % initialize to nan
for j=1:length(n) % for each element in the input
e(j)=sum(1./factorial(0:n(j))); %each entry is computed in this step, one at a time
end
In this code, each approximation has been vectorized, but I don't see an easy way to vectorize the entire program. There is also no error checking, like making sure the elements of n are non-negative integers, or that n is a vector and not an array.
In the original example, the while never terminates because n never changes.
This should be enough to help get you started.
Cheers!

Attempted to access index in vector

Here is part of a function that counts the Nyquist stability criterion. Function gives an error when vectors re or im do not have five elements:
Attempted to access im(5); index out of bounds because numel(im)=4.
Error in stability (line 27)
tran(w) = re(1) + re(2)*w.^1 + re(3)*w.^2 + re(4)*w.^3 +
re(5)w.^4 +1i(...
I want to assign 0 to the missing elements.
function answear=stability(re,im)
%% Function check stability of system
%re is real part of transmitation
%im is imagine part of transmitation
%% data
for n=1:length(re)
if(re(n) == [ ])
re(n) = 0;
end
end
for n=1:length(im)
if(im (n)== [ ])
im(n) = 0;
end
end
if( length(re) > length(im))
root = length(re);
else
root = length(im);
end
for w=1:root
tran(w) = re(1) + re(2)*w.^1 + re(3)*w.^2 + re(4)*w.^3 + re(5)*w.^4 +1i*(...
im(1) + im(2)*w.^1 + im(3)*w.^2 + im(4)*w.^3 +im(5)*w.^4);
end
Here are two ways to expand a vector to ensure it has at least 5 elements. Each working from a different thought but doing the same.
Most compact:
x = [1 2 3];
x(end+1:5) = 0;
Assigns zero to all elements behind the matrix till the fifth element.
However, if you already know the amount of elements, this is more compact:
x = [1 2 3];
if numel(x)<5
x(5) = 0;
end
Note that this will automatically expand with zeros untill it has 5 elements. The advantage of these methods it that it works, regardless of the orientation of your vector.
If you want to pad your vector with zeros to make certain it has at least 5 elements I suggest the following:
Make a vecotr of 5 zeros
Fill the first X elements of pad with your vector (lets call it A)
For examples with A begin less than 5 and A being more than 5 elements:
A= [1 2 3]
n=5
pad = zeros(1,n)
pad(1:length(A)) = A
clear
A = [5 6 7 8 9 4 3]
n=5
pad = zeros(1,n)
pad(1:length(A)) = A