Function returns only one output at time - matlab

I have a problem with this function (I have very little experience with Matlab). The function is supposed to return 3 different arguments but always returns only one. I mean, to get Y out I have to remove Tot and Z from the output arguments! As it is now only Tot is returned.
function [Tot, Z, Y] = something( A )
%A = [1 2 3; 4 5 6; 7 8 9; 10 11 12];
Z=cumsum(A); %cumulative sum of columns
Y=cumsum(A,2); %cumulative sum of rows
Tot = sum(Z(:))+sum(Y(:)); %Total sum of Z+Y
end
Why is doing that ? What am I doing wrong, I need all 3 arguments out.

The proper call to receive all three arguments would be: [A, B, C] = something (X), where Tot would be placed into A, Z into B, and Y into C. If you just want Y, you can use the "tilde" operator to ignore other outputs: [~,~,C] = something(X).

Related

Get the values of an array from indices in another array: Matlab

I have a 20x1 double array A, and a 1000x1 double array B.
I want to get array C, where array C will be 1000x1 double where the values in B are used to index the values in A like so:
C(1) = A(B(1))
C(2) = A(B(2))
...
C(i) = A(B(i))
...
c(1000) = A(B(1000))
How this can be done?
You don't need a loop for this, you can directly use:
C = A(B)
This takes advantage of MATLAB's matrix indexing, which is the way indexing is handled in MATLAB when an array is used instead of an integer.
Take a look at the docs: https://uk.mathworks.com/help/matlab/math/matrix-indexing.html
For example:
A = [11 12 13];
B = [1 2 3 1 2 3 3 2 1];
C = A(B)
C =
11 12 13 11 12 13 13 12 11
Ensure that B only contains integers which are valid indices of A (not less than 1 or greater than the length of A).
I did it using for loop as shown below, not sure if this is the ideal solution:
C = zeros(1000,1);
for i = 1:1000
C(i,1) = A(B(i));
end

How to elegantly sum into repeated indices of a vector in matlab

I am trying to figure out a way to do the following without a loop:
Lets say I have a vector x where I sum some elements e into. I also have a vector of indices ids which say to which elements of x to send the values to. i.e.
x = zeros(1,4);
e = [ 1 10 100 1e3 1e4];
ids = [1 1 2 4 3];
I would like to do something like
x(ids) = x(ids) + e
That will return
x =
11 100 10000 1000
because we refer to x(1) twice, while instead it returns
x =
10 100 10000 1000
accumaray is a really useful function for doing such tricks. In your case:
accumarray(ids',e)
will do the job.

Assign values to multiple symbolic variables at the same time [duplicate]

This question already has answers here:
Define multiple variables at the same time in MATLAB
(2 answers)
Closed 7 years ago.
I wanna assign values to multiple symbolic variables at the same time.
For example,
syms a b c
% for several reasons, I have to define a, b, c as symbolic variables.
x = [a, b, c];
y = [1, 2, 3];
When I define matrix x and y like above,
I wanna get following answer.
a = 1
b = 2
c = 3
% Assign values to symbolic variables.
Of course, simply I can get this answer by using following code.
[a, b, c] = deal(1, 2, 3);
But I have to use matrix x and y instead of [a, b, c] and (1, 2, 3).
Because actually there are so many symbolic variables in matrix x when I calculate.
So I wanna use matrix.
In this case, if I use matrix x and y
x = deal(y);
The answer is just
x = 1 2 3
But I wanna get the answer,
a = 1
b = 2
c = 3
What should I do to assign values to variables by using matrix x and y?
Please answer my question.
Thank you.
I don't think you should be trying to do this, I am sure there must be some other choices you could make earlier to avoid this problem. But it can be done, probably more nicely than I have done.
syms a b c
x=[a b c]
y=[1 2 3]
%// We want to get the name of the variable from x, and the value from y
arrayfun(#(i) assignin('caller',char(x(i)),y(i)),1:length(x))

Recurring Function with Matrix Input

I believe most functions in MATLAB should be able to receive matrix input and return the output in the form of matrix.
For example sqrt([1 4 9]) would return [1 2 3].
However, when I tried this recurring factorial function:
function k = fact(z)
if z ~= 0
k = z * fact(z-1);
else
k = 1;
end
end
It works perfectly when a number is input into fact. However, when a matrix is input into fact, it returns the matrix itself, without performing the factorial function.
E.g.
fact(3) returns 6
fact([1 2 3]) returns [1 2 3] instead of [1 2 6].
Any help is appreciated. Thank you very much!
Since MATLAB is not known to be good with recursive functions, how about a vectorized approach? Try this for a vector input -
mat1 = repmat([1:max(z)],[numel(z) 1])
mat1(bsxfun(#gt,1:max(z),z'))=1
output1 = prod(mat1,2)
Sample run -
z =
1 2 7
output1 =
1
2
5040
For the sake of answering your original question, here's the annoying loopy code for a vector or 2D matrix as input -
function k1 = fact1(z1)
k1 = zeros(size(z1));
for ii = 1:size(z1,1)
for jj = 1:size(z1,2)
z = z1(ii,jj);
if z ~= 0
k1(ii,jj) = z .* fact1(z-1);
else
k1(ii,jj) = 1;
end
end
end
return
Sample run -
>> fact1([1 2 7;3 2 1])
ans =
1 2 5040
6 2 1
You can use the gamma function to compute the factorial without recursion:
function k = fact(z)
k = gamma(z+1);
Example:
>> fact([1 2 3 4])
ans =
1 2 6 24
Not sure if all of you know, but there is an actual factorial function defined in MATLAB that can take in arrays / matrices of any size, and computes the factorial element-wise. For example:
k = factorial([1 2 3 4; 5 6 7 8])
k =
1 2 6 24
120 720 5040 40320
Even though this post is looking for a recursive implementation, and Divakar has provided a solution, I'd still like to put my two cents in and suggest an alternative. Also, let's say that we don't have access to factorial, and we want to compute this from first principles. What I would personally do is create a cell array that's the same size as the input matrix, but each element in this cell array would be a linear index array from 1 up to the number defined for each location in the original matrix. You would then apply prod to each cell element to compute the factorial. A precondition is that no number is less than 1, and that all elements are integers. As such:
z1 = ... ; %// Define input matrix here
z1_matr = arrayfun(#(x) 1:x, z1, 'uni', 0);
out = cellfun(#prod, z1_matr);
If z1 = [1 2 3 4; 5 6 7 8];, from my previous example, we get the same output with the above code:
out =
1 2 6 24
120 720 5040 40320
This will obviously be slower as there is an arrayfun then cellfun call immediately after, but I figured I'd add another method for the sake of just adding in another method :) Not sure how constructive this is, but I figured I'd add my own method and join Divakar and Luis Mendo :)

Creating a matrix from a function handle (MATLAB)

What I intend to do is very simple but yet I haven't found a proper way to do it. I have a function handle which depends on two variables, for example:
f = #(i,j) i+j
(mine is quite more complicated, though)
What I'd like to do is to create a matrix M such that
M(i,j) = f(i,j)
Of course I could use a nested loop but I'm trying to avoid those. I've already managed to do this in Maple in a quite simple way:
f:=(i,j)->i+j;
M:=Matrix(N,f);
(Where N is the dimension of the matrix) But I need to use MATLAB for this. For now I'm sticking to the nested loops but I'd really appreciate your help!
Use bsxfun:
>> [ii jj] = ndgrid(1:4 ,1:5); %// change i and j limits as needed
>> M = bsxfun(f, ii, jj)
M =
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
If your function f satisfies the following condition:
C = fun(A,B) accepts arrays A and B of arbitrary, but equal size and returns output of the same size. Each element in the output array C is the result of an operation on the corresponding elements of A and B only. fun must also support scalar expansion, such that if A or B is a scalar, C is the result of applying the scalar to every element in the other input array.
you can dispose of ndgrid. Just add a transpose (.') to the first (i) vector:
>> M = bsxfun(f, (1:4).', 1:5)
Function handles can accept matrices as inputs. Simply pass a square matrix of size N where the values corresponds to the row number for i, and a square matrix of size N where the values correspond to the column number for j.
N = 5;
f = #(i,j) i+j;
M = f(meshgrid(1:N+1), meshgrid(1:N+1)')