tys
tys

Reputation: 699

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!

Upvotes: 1

Views: 178

Answers (3)

rayryeng
rayryeng

Reputation: 104535

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 :)

Upvotes: 2

Luis Mendo
Luis Mendo

Reputation: 112749

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

Upvotes: 2

Divakar
Divakar

Reputation: 221614

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

Upvotes: 2

Related Questions