For code generation, before using variables in operations or returning them as outputs, you must assign them a specific class, size, and complexity. Generally, after the initial assignment, you cannot reassign variable properties. Therefore, after assigning a fixed size to a variable or structure field, attempts to grow the variable or structure field might cause a compilation error. In these cases, you must explicitly define the data as variable-size by using one of these methods.
Method | See |
---|---|
Assign the data from a variable-size matrix constructor such as: | Use a Matrix Constructor with Nonconstant Dimensions |
Assign multiple, constant sizes to the same variable before using (reading) the variable. | Assign Multiple Sizes to the Same Variable |
Define all instances of a variable to be variable-size. | Define Variable-Size Data Explicitly by Using coder.varsize |
You can define a variable-size matrix by using a constructor with nonconstant dimensions. For example:
function s = var_by_assign(u) %#codegen y = ones(3,u); s = numel(y);
If you are not using dynamic memory allocation, you must also
add an assert
statement to provide upper bounds
for the dimensions. For example:
function s = var_by_assign(u) %#codegen assert (u < 20); y = ones(3,u); s = numel(y);
Before you use (read) a variable in your code, you can make it variable-size by assigning multiple, constant sizes to it. When the code generator uses static allocation on the stack, it infers the upper bounds from the largest size specified for each dimension. When you assign the same size to a given dimension across all assignments, the code generator assumes that the dimension is fixed at that size. The assignments can specify different shapes and sizes.
When the code generator uses dynamic memory allocation, it does not check for upper bounds. It assumes that the variable-size data is unbounded.
function s = var_by_multiassign(u) %#codegen if (u > 0) y = ones(3,4,5); else y = zeros(3,1); end s = numel(y);
When the code generator uses static allocation, it infers that y
is
a matrix with three dimensions:
The first dimension is fixed at size 3
The second dimension is variable-size with an upper bound of 4
The third dimension is variable-size with an upper bound of 5
When the code generator uses dynamic allocation, it analyzes
the dimensions of y
differently:
The first dimension is fixed at size 3.
The second and third dimensions are unbounded.
To explicitly define variable-size data, use the function coder.varsize
.
Optionally, you can also specify which dimensions vary along with
their upper bounds. For example:
Define B
as a variable-size 2-dimensional
array, where each dimension has an upper bound of 64.
coder.varsize('B', [64 64]);
Define B
as a variable-size array:
coder.varsize('B');
When you supply only the first argument, coder.varsize
assumes
that all dimensions of B
can
vary and that the upper bound is size(B)
.
You can use the function coder.varsize
to
specify which dimensions vary. For example, the following statement
defines B
as an array whose first dimension is
fixed at 2, but whose second dimension can grow to a size of 16:
coder.varsize('B',[2, 16],[0 1])
The third argument specifies which dimensions vary. This argument
must be a logical vector or a double vector containing only zeros
and ones. Dimensions that correspond to zeros or false
have
fixed size. Dimensions that correspond to ones or true
vary
in size. coder.varsize
usually treats dimensions
of size 1 as fixed. See Define Variable-Size Matrices with Singleton Dimensions.
Function var_by_if
defines matrix Y
with
fixed 2-by-2 dimensions before the first use (where the statement Y
= Y + u
reads from Y
). However, coder.varsize
defines Y
as
a variable-size matrix, allowing it to change size based on decision
logic in the else
clause:
function Y = var_by_if(u) %#codegen if (u > 0) Y = zeros(2,2); coder.varsize('Y'); if (u < 10) Y = Y + u; end else Y = zeros(5,5); end
Without coder.varsize
, the code generator
infers Y
to be a fixed-size, 2-by-2 matrix. It
generates a size mismatch error.
A singleton dimension is a dimension for which size(A,dim)
=
1. Singleton dimensions are fixed in size when:
You specify a dimension with an upper bound of 1 in coder.varsize
expressions.
For example, in this function, Y
behaves
like a vector with one variable-size dimension:
function Y = dim_singleton(u) %#codegen Y = [1 2]; coder.varsize('Y', [1 10]); if (u > 0) Y = [Y 3]; else Y = [Y u]; end
You initialize variable-size data with singleton dimensions by using matrix constructor expressions or matrix functions.
For example, in this function, X
and Y
behave
like vectors where only their second dimensions are variable-size.
function [X,Y] = dim_singleton_vects(u) %#codegen Y = ones(1,3); X = [1 4]; coder.varsize('Y','X'); if (u > 0) Y = [Y u]; else X = [X u]; end
You can override this behavior by using coder.varsize
to
specify explicitly that singleton dimensions vary. For example:
function Y = dim_singleton_vary(u) %#codegen Y = [1 2]; coder.varsize('Y', [1 10], [1 1]); if (u > 0) Y = [Y Y+u]; else Y = [Y Y*u]; end
In this example, the third argument of coder.varsize
is
a vector of ones, indicating that each dimension of Y
varies
in size.
To define structure fields as variable-size arrays, use a colon
(:
) as the index expression. The colon (:
)
indicates that all elements of the
array are variable-size. For example:
function y=struct_example() %#codegen d = struct('values', zeros(1,0), 'color', 0); data = repmat(d, [3 3]); coder.varsize('data(:).values'); for i = 1:numel(data) data(i).color = rand-0.5; data(i).values = 1:i; end y = 0; for i = 1:numel(data) if data(i).color > 0 y = y + sum(data(i).values); end end
The expression coder.varsize('data(:).values')
defines
the field values
inside each element of matrix data
to
be variable-size.
Here are other examples:
coder.varsize('data.A(:).B')
In this example, data
is a scalar variable
that contains matrix A
. Each element of matrix A
contains
a variable-size field B
.
coder.varsize('data(:).A(:).B')
This expression defines field B
inside each
element of matrix A
inside each element of matrix data
to
be variable-size.