Define Variable-Size Data for Code Generation - MATLAB & Simulink (original) (raw)
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.
Use a Matrix Constructor with Nonconstant Dimensions
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 anassert
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);
Assign Multiple Sizes to the Same Variable
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.
Inferring Upper Bounds from Multiple Definitions with Different Shapes
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 thaty
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 ofy
differently:
- The first dimension is fixed at size 3.
- The second and third dimensions are unbounded.
Grow an Array Using (end + 1)
Indexing
In MATLABĀ® execution, you can grow any dimension of an array using end. For example, you can grow both dimensions of a two-dimensional matrix by assigning a value to the(end + 1)
element of each dimension.
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
A =
17 24 1 8 15 0
23 5 7 14 16 0
4 6 13 20 22 0
10 12 19 21 3 0
11 18 25 2 9 0
0 0 0 0 0 1
To grow arrays using end
in MATLAB code for code generation, you must adhere to these restrictions:
- You can only use
end
to grow vectors. For example, code generation fails for this function becauseX
is a matrix, not a vector.
function X = foo
X = [1 2; 3 4];
X(end + 1,:) = 5;
end - You can grow a vector only by assigning a value to the
(end + 1)
element. Assigning a value to subsequent elements, such as(end + 2)
, is not supported. - You can grow an empty 1-by-0 array by using
(end + 1)
. Growing a 0-by-1 array using(end + 1)
is not supported. You can grow a 0-by-0 array using(end + 1)
only if you create the array using[]
. - Using
(end + 1)
to grow a structure array that has been defined using dot notation is not supported. For example, code generation fails for this MATLAB function.
function growStruct
s.field1 = 5;
s.field2 = 2;
s(end + 1) = s;
end
To grow a structure array using(end + 1)
, define the fields of the structure using the struct constructor.
function growStruct
s = struct("field1",5,"field2",2);
s(end + 1) = s;
end
To learn more about growing arrays using(end + 1)
, see Generate Code for Growing Arrays and Cell Arrays with end + 1 Indexing (MATLAB Coder).
Define Variable-Size Data Explicitly by Using coder.varsize
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:
When you supply only the first argument,coder.varsize
assumes that all dimensions ofB
can vary and that the upper bound issize(B)
.
If a MATLAB Function block output signal is variable-size, in the Property Inspector, you must specify that the signal is variable-size. You can specify the upper bounds or define the variable as unbounded (since R2023b). You do not have to usecoder.varsize
with the corresponding output variable inside the MATLAB Function block. However, if you specify upper bounds withcoder.varsize
, they must match the upper bounds in the Property Inspector.
Specify Which Dimensions Vary
You can use the function coder.varsize to specify which dimensions vary. For example, the following statement definesB
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.
Allow a Variable to Grow After Defining Fixed 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 theelse
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 infersY
to be a fixed-size, 2-by-2 matrix. It generates a size mismatch error.
Define Variable-Size Matrices with Singleton Dimensions
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
andY
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.
Define Variable-Size Structure Fields
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 matrixdata
to be variable-size.
Here are other examples:
coder.varsize('data.A(:).B')
In this example,data
is a scalar variable that contains matrixA
. Each element of matrixA
contains a variable-size fieldB
.coder.varsize('data(:).A(:).B')
This expression defines fieldB
inside each element of matrixA
inside each element of matrixdata
to be variable-size.