To constrain array size for variable-size arrays, do one of the following:
Constrain Array Size Using assert Statements
If the variable specifying array size is not a compile-time
constant, use an assert
statement
with relational operators to constrain the variable. Doing so helps
the code generator to determine a maximum size for the array.
The following examples constrain array size using assert
statements:
When Array Size Is Specified by Input Variables
Define a function array_init
which initializes
an array y
with input variable N
:
function y = array_init (N) assert(N <= 25); % Generates exception if N > 25 y = zeros(1,N);
The assert
statement constrains input N
to
a maximum size of 25. In the absence of the assert
statement, y
is
assigned a pointer to an array in the generated code, thus allowing
dynamic memory allocation.
When Array Size Is Obtained from Computation Using
Input Variables
Define a function, array_init_from_prod
,
which takes two input variables, M
and N
,
and uses their product to specify the maximum size of an array, y
.
function y = array_init_from_prod (M,N) size=M*N; assert(size <= 25); % Generates exception if size > 25 y=zeros(1,size);
The assert
statement constrains the product
of M
and N
to a maximum of 25.
Alternatively, if you restrict M
and N
individually,
it leads to dynamic memory allocation:
function y = array_init_from_prod (M,N)
assert(M <= 5);
assert(N <= 5);
size=M*N;
y=zeros(1,size);
This code causes dynamic memory allocation because M
and N
can
both have unbounded negative values. Therefore, their product can
be unbounded and positive even though, individually, their positive
values are bounded.
Tip
Place the assert statement on a variable immediately before it is used to specify array size.
Tip
You can use assert
statements to restrict
array sizes in most cases. When expanding an array inside a loop,
this strategy does not work if the number of loop runs is known only
at run time.
Restrict Concatenations in a Loop Using coder.varsize
with Upper Bounds
You can expand arrays beyond their initial size by concatenation. When you concatenate additional elements inside a loop, there are two syntax rules for expanding arrays.
Array size during initialization is not a compile-time
constant
If the size of an array during initialization is not a compile-time constant, you can expand it by concatenating additional elements:
function out=ExpandArray(in) % Expand an array by five elements out = zeros(1,in); for i=1:5 out = [out 0]; end
Array size during initialization is a compile-time
constant
Before concatenating elements, you have to declare
the array as variable-size using coder.varsize
:
function out=ExpandArray() % Expand an array by five elements out = zeros(1,5); coder.varsize('out'); for i=1:5 out = [out 0]; end
Either case leads to dynamic memory allocation. To prevent dynamic
memory allocation in such cases, use coder.varsize
with
explicit upper bounds. This example shows how to use coder.varsize
with
explicit upper bounds:
Define a function, RunningAverage
,
that calculates the running average of an N
-element
subset of an array:
function avg=RunningAverage(N) % Array whose elements are to be averaged NumArray=[1 6 8 2 5 3]; % Initialize average: % These will also be the first two elements of the function output avg=[0 0]; % Place a bound on the argument coder.varsize('avg',[1 8]); % Loop to calculate running average for i=1:N s=0; s=s+sum(NumArray(1:i)); avg=[avg s/i]; % Increase the size of avg as required by concatenation end
The output, avg
, is an array
that you can expand as required to accommodate the running averages.
As a new running average is calculated, it is added to the array avg
through
concatenation, thereby expanding the array.
Because the maximum number of running averages is equal to the
number of elements in NumArray
, you
can supply an explicit upper bound for avg
in
the coder.varsize
statement. In this
example, the upper bound is 8 (the two initial elements plus the six
elements of NumArray
).
Generate code for RunningAverage
with
input argument of type double
:
codegen -config:lib -report RunningAverage -args 2
In the generated code, avg
is
assigned an array of size 8 (static memory allocation). The function
definition for RunningAverage
appears
as follows (using built-in C types):
void RunningAverage (double N, double avg_data[8], int avg_size[2])
By contrast, if you remove the explicit upper bound,
the generated code dynamically allocates avg
.
Replace the statement
coder.varsize('avg',[1 8]);
with:
coder.varsize('avg');
Generate code for RunningAverage
with
input argument of type double
:
codegen -config:lib -report RunningAverage -args 2
In the generated code, avg
is
assigned a pointer to an array, thereby allowing dynamic memory allocation.
The function definition for RunningAverage
appears
as follows (using built-in C types):
void Test(double N, emxArray_real_T *avg)
Note
Dynamic memory allocation also occurs if you precede coder.varsize('avg')
with
the following assert statement:
assert(N < 6);
assert
statement
does not restrict the number of concatenations within the loop. Constrain Array Size When Rearranging a Matrix
The statement out = reshape(in,m,n,...)
takes
an array, in
, as an argument and returns
array, out
, having the same elements
as in
, but reshaped as an m
-by-n
-by-...
matrix.
If one of the size variables m,n,...
.
is not a compile-time constant, then dynamic memory allocation of out
takes
place.
To avoid dynamic memory allocation, use an assert
statement
before the reshape
statement to restrict
the size variables m,n,...
to numel(in)
.
This example shows how to use an assert
statement
before a reshape
statement:
Define a function, ReshapeMatrix
,
which takes an input variable, N
, and
reshapes a matrix, mat
, to have N
rows:
function [out1,out2] = ReshapeMatrix(N) mat = [1 2 3 4 5; 4 5 6 7 8] % Since mat has 10 elements, N must be a factor of 10 % to pass as argument to reshape out1 = reshape(mat,N,[]); % N is not restricted assert(N < numel(mat)); % N is restricted to number of elements in mat out2 = reshape(mat,N,[]);
Generate code for ReshapeArray
using
the codegen
command (the input argument
does not have to be a factor of 10):
codegen -config:lib -report ReshapeArray -args 3
While out1
is dynamically allocated, out2
is
assigned an array with size 100 (=10 X 10) in the generated code.
Tip
If your system has limited memory, do not use the assert
statement
in this way. For an n
-element matrix,
the assert
statement creates an n
-by-n
matrix,
which might be large.