Main Content

Cell Array Limitations for Code Generation

When you use cell arrays in MATLAB® code that is intended for code generation, you must adhere to these restrictions:

Cell Array Element Assignment

You must assign a cell array element on all execution paths before you use it. For example:

function z = foo(n)
%#codegen
c = cell(1,3);
if n < 1
    c{2} = 1;
    
else
    c{2} = n;
end
z = c{2};
end

The code generator considers passing a cell array to a function or returning it from a function as a use of all elements of the cell array. Therefore, before you pass a cell array to a function or return it from a function, you must assign all of its elements. For example, the following code is not allowed because it does not assign a value to c{2} and c is a function output.

function c = foo()
%#codegen
c = cell(1,3);
c{1} = 1;
c{3} = 3;
end

The assignment of values to elements must be consistent on all execution paths. The following code is not allowed because y{2} is double on one execution path and char on the other execution path.

function y = foo(n)
y = cell(1,3)
if n > 1;
    y{1} = 1
    y{2} = 2;
    y{3} = 3;
else
    y{1} = 10;
    y{2} = 'a';
    y{3} = 30;
end

Variable-Size Cell Arrays

  • coder.varsize is not supported for heterogeneous cell arrays.

  • If you use the cell function to define a fixed-size cell array, you cannot use coder.varsize to specify that the cell array has a variable size. For example, this code causes a code generation error because x = cell(1,3) makes x a fixed-size,1-by-3 cell array.

    ...
    x = cell(1,3);           
    coder.varsize('x',[1 5])
    ...

    You can use coder.varsize with a cell array that you define by using curly braces. For example:

    ...
    x = {1 2 3}; 
    coder.varsize('x',[1 5])
    ...

  • To create a variable-size cell array by using the cell function, use this code pattern:

    function mycell(n)
    %#codegen
    x = cell(1,n);   
    for i = 1:n
        x{i} = i;
    end
    end

    See Definition of Variable-Size Cell Array by Using cell.

    To specify upper bounds for the cell array, use coder.varsize.

    function mycell(n)
    %#codegen
    x = cell(1,n);   
    for i = 1:n
        x{i} = i;
    coder.varsize('x',[1,20]);
    end
    end

Definition of Variable-Size Cell Array by Using cell

For code generation, before you use a cell array element, you must assign a value to it. When you use cell to create a variable-size cell array, for example, cell(1,n), MATLAB assigns an empty matrix to each element. However, for code generation, the elements are unassigned. For code generation, after you use cell to create a variable-size cell array, you must assign all elements of the cell array before any use of the cell array. For example:

function z = mycell(n, j)
%#codegen
x = cell(1,n);   
for i = 1:n
    x{i} = i;
end
z = x{j};
end

The code generator analyzes your code to determine whether all elements are assigned before the first use of the cell array. If the code generator detects that some elements are not assigned, code generation fails with an error message. For example, modify the upper bound of the for-loop to j.

function z = mycell(n, j)
%#codegen
x = cell(1,n);   
for i = 1:j %<- Modified here
    x{i} = i;
end
z = x{j};
end

With this modification and with inputs j less than n, the function does not assign values to all of the cell array elements. Code generation produces the error:

Unable to determine that every element of 'x{:}' is assigned
before this line.

Sometimes, even though your code assigns all elements of the cell array, the code generator reports this message because the analysis does not detect that all elements are assigned. See Unable to Determine That Every Element of Cell Array Is Assigned.

To avoid this error, follow these guidelines:

  • When you use cell to define a variable-size cell array, write code that follows this pattern:

    function z = mycell(n, j)
    %#codegen
    x = cell(1,n);   
    for i = 1:n
        x{i} = i;
    end
    z = x{j};
    end
    

    Here is the pattern for a multidimensional cell array:

    function z = mycell(m,n,p)
    %#codegen
    x = cell(m,n,p);
    for i = 1:m
        for j =1:n
            for k = 1:p
                x{i,j,k} = i+j+k;
            end
        end
    end
    z = x{m,n,p};
    end

  • Increment or decrement the loop counter by 1.

  • Define the cell array within one loop or one set of nested loops. For example, this code is not allowed:

    function z = mycell(n, j)
    x = cell(1,n);
    for i = 1:5
        x{i} = 5;
    end
    for i = 6:n
        x{i} = 5;
    end
    z = x{j};
    end            

  • Use the same variables for the cell dimensions and loop initial and end values. For example, code generation fails for the following code because the cell creation uses n and the loop end value uses m:

    function z = mycell(n, j)
    x = cell(1,n);
    m = n;
    for i = 1:m
        x{i} = 2;
    end
    z = x{j};
    end               

    Rewrite the code to use n for the cell creation and the loop end value:

    function z = mycell(n, j)
    x = cell(1,n);
    for i = 1:n
        x{i} = 2;
    end
    z = x{j};
    end

  • Create the cell array with this pattern:

    x = cell(1,n)

    Assign the cell array to a field of a structure or a property of an object by initializing a temporary variable with the required cell. For example:

    t = cell(1,n)
    for i = 1:n
        t{i} = i+1;
    end
    myObj.prop = t;
    Do not assign a cell array to a field of a structure or a property of an object directly. For example, this code is not allowed:

    myObj.prop = cell(1,n);
    for i = 1:n
        myObj.prop{i} = i+1;
    end

    Do not use the cell function inside the cell array constructor {}. For example, this code is not allowed:

    x = {cell(1,n)};

  • The cell array creation and the loop that assigns values to the cell array elements must be together in a unique execution path. For example, the following code is not allowed.

    function z = mycell(n)
    if n > 3
        c = cell(1,n);
    else
        c = cell(n,1);
    end
    for i = 1:n
        c{i} = i;
    end
    z = c{n};
    end

    To fix this code, move the assignment loop inside the code block that creates the cell array.

    function z = cellerr(n)
    if n > 3
        c = cell( 1,n);
        for i = 1:n
            c{i} = i;
        end
    else
        c = cell(n,1);
        for i = 1:n
            c{i} = i;
        end
    end
    z = c{n};
    end

Cell Array Indexing

  • You cannot index cell arrays by using smooth parentheses(). Consider indexing cell arrays by using curly braces{} to access the contents of the cell.

  • You must index into heterogeneous cell arrays by using constant indices or by using for-loops with constant bounds.

    For example, the following code is not allowed.

    x = {1, 'mytext'};
    disp(x{randi});

    You can index into a heterogeneous cell array in a for-loop with constant bounds because the code generator unrolls the loop. Unrolling creates a separate copy of the loop body for each loop iteration, which makes the index in each loop iteration constant. However, if the for-loop has a large body or it has many iterations, the unrolling can increase compile time and generate inefficient code.

    If A and B are constant, the following code shows indexing into a heterogeneous cell array in a for-loop with constant bounds.

    x = {1, 'mytext'};
    for i = A:B
    	 disp(x{i});
    end

Growing a Cell Array by Using {end + 1}

To grow a cell array X, you can use X{end + 1}. For example:

...
X = {1 2};
X{end + 1} = 'a';
...

When you use {end + 1} to grow a cell array, follow these restrictions:

  • Use only {end + 1}. Do not use {end + 2}, {end + 3}, and so on.

  • Use {end + 1} with vectors only. For example, the following code is not allowed because X is a matrix, not a vector:

    ...
    X = {1 2; 3 4};
    X{end + 1} = 5;
    
    ...

  • Use {end + 1} only with a variable. In the following code, {end + 1} does not cause {1 2 3} to grow. In this case, the code generator treats {end + 1} as an out-of-bounds index into X{2}.

    ...
    X = {'a' { 1 2 3 }};
    X{2}{end + 1} = 4;
    ...

  • When {end + 1} grows a cell array in a loop, the cell array must be variable-size. Therefore, the cell array must be homogeneous.

    This code is allowed because X is homogeneous.

    ...
    X = {1  2};
    for i=1:n
        X{end + 1} = 3;
    end
    ...

    This code is not allowed because X is heterogeneous.

    ...
    X = {1 'a' 2 'b'};
    for i=1:n
        X{end + 1} = 3;
    end
    ...

Cell Array Contents

Cell arrays cannot contain mxarrays. In a cell array, you cannot store a value that an extrinsic function returns.

Passing Cell Arrays to External C/C++ Functions

You cannot pass a cell array to coder.ceval. If a variable is an input argument to coder.ceval, define the variable as an array or structure instead of as a cell array.

Related Topics