Scalar expansion is a method of converting scalar data to match
the dimensions of vector or matrix data. Except for some matrix operators, MATLAB^{®} arithmetic
operators work on corresponding elements of arrays with equal dimensions.
For vectors and rectangular arrays, both operands must be the same
size unless one is a scalar. If one operand is a scalar and the other
is not, MATLAB applies the scalar to every element of the other
operand—this property is known as *scalar expansion*.

During code generation, the standard MATLAB scalar expansion rules apply except when operating on two variable-size expressions. In this case, both operands must be the same size. The generated code does not perform scalar expansion even if one of the variable-size expressions turns out to be scalar at run time. Instead, it generates a size mismatch error at run time for MEX functions. Run-time error checking does not occur for non-MEX builds; the generated code will have unspecified behavior.

For example, in the following function, `z`

is
scalar for the `switch`

statement `case 0`

and ```
case
1
```

. MATLAB applies scalar expansion when evaluating ```
y(:)
= z;
```

for these two cases.

function y = scalar_exp_test_err1(u) %#codegen y = ones(3); switch u case 0 z = 0; case 1 z = 1; otherwise z = zeros(3); end y(:) = z;

When you generate code for this function, the code generator
determines that `z`

is variable size with an upper
bound of `3`

.

If you run the MEX function with `u`

equal
to zero or one, even though `z`

is scalar at run
time, the generated code does not perform scalar expansion and a run-time
error occurs.

scalar_exp_test_err1_mex(0) Sizes mismatch: 9 ~= 1. Error in scalar_exp_test_err1 (line 11) y(:) = z;

Use indexing to force `z`

to be a scalar value:

function y = scalar_exp_test_err1(u) %#codegen y = ones(3); switch u case 0 z = 0; case 1 z = 1; otherwise z = zeros(3); end y(:) = z(1);

For variable-size N-D arrays, the `size`

function
can return a different result in generated code than in MATLAB.
In generated code, `size(A)`

returns a fixed-length
output because it does not drop trailing singleton dimensions of variable-size
N-D arrays. By contrast, `size(A)`

in MATLAB returns
a variable-length output because it drops trailing singleton dimensions.

For example, if the shape of array `A`

is `:?x:?x:?`

and `size(A,3)==1`

, `size(A)`

returns:

Three-element vector in generated code

Two-element vector in MATLAB code

If your application requires generated code to return the same size of variable-size N-D arrays as MATLAB code, consider one of these workarounds:

Use the two-argument form of

`size`

.For example,

`size(A,n)`

returns the same answer in generated code and MATLAB code.Rewrite

`size(A)`

:B = size(A); X = B(1:ndims(A));

This version returns

`X`

with a variable-length output. However, you cannot pass a variable-size`X`

to matrix constructors such as`zeros`

that require a fixed-size argument.

The size of an empty array in generated code might be different
from its size in MATLAB source code. The size might be `1x0`

or `0x1`

in
generated code, but `0x0`

in MATLAB. Therefore,
you should not write code that relies on the specific size of empty
matrices.

For example, consider the following code:

function y = foo(n) %#codegen x = []; i = 0; while (i < 10) x = [5 x]; i = i + 1; end if n > 0 x = []; end y = size(x); end

Concatenation requires its operands to match on the size of
the dimension that is not being concatenated. In the preceding concatenation
the scalar value has size `1x1`

and `x`

has
size `0x0`

. To support this use case, the code generator
determines the size for `x`

as `[1 x :?]`

.
Because there is another assignment `x = []`

after
the concatenation, the size of `x`

in the generated
code is `1x0`

instead of `0x0`

.

For incompatibilities with MATLAB in determining the size of an empty array that results from deleting elements of an array, see Size of Empty Array That Results from Deleting Elements of an Array.

If your application checks whether a matrix is empty, use one of these workarounds:

Rewrite your code to use the

`isempty`

function instead of the`size`

function.Instead of using

`x=[]`

to create empty arrays, create empty arrays of a specific size using`zeros`

. For example:function y = test_empty(n) %#codegen x = zeros(1,0); i=0; while (i < 10) x = [5 x]; i = i + 1; end if n > 0 x = zeros(1,0); end y=size(x); end

The class of an empty array in generated code can be different from its class in MATLAB source code. Therefore, do not write code that relies on the class of empty matrices.

For example, consider the following code:

function y = fun(n) x = []; if n > 1 x = ['a' x]; end y=class(x); end

`fun(0)`

returns `double`

in MATLAB,
but `char`

in the generated code. When the statement ```
n
> 1
```

is false, MATLAB does not execute ```
x
= ['a' x]
```

. The class of `x`

is `double`

,
the class of the empty array. However, the code generator considers
all execution paths. It determines
that based on the statement `x = ['a' x]`

, the class
of `x`

is `char`

.Instead of using `x=[]`

to create an empty
array, create an empty array of a specific class. For example, use `blanks(0)`

to
create an empty array of characters.

function y = fun(n) x = blanks(0); if n > 1 x = ['a' x]; end y=class(x); end

In vector-vector indexing, you use one vector as an index into
another vector. When either vector is variable sized, you might get
a run-time error during code generation. Consider the index expression `A(B)`

.
The general rule for indexing is that `size(A(B)) == size(B)`

.
However, when both `A`

and `B`

are
vectors, MATLAB applies a special rule: use the orientation of
A as the orientation of the output. For example, if ```
size(A)
== [1 5]
```

and `size(B) == [3 1]`

, then ```
size(A(B))
== [1 3]
```

.

In this situation, if the code generator detects that both `A`

and `B`

are
vectors at compile time, it applies the special rule and gives the
same result as MATLAB. However, if either `A`

or `B`

is
a variable-size matrix (has shape `?x?`

) at compile
time, the code generator applies only the general indexing rule. Then,
if both `A`

and `B`

become vectors
at run time, the code generator reports a run-time error when you
run the MEX function. Run-time error checking does not occur for non-MEX
builds; the generated code will have unspecified behavior. It is best
practice to generate and test a MEX function before generating C code.

Force your data to be a vector by using the colon operator for
indexing: `A(B(:))`

. For example, suppose your code
intentionally toggles between vectors and regular matrices at run
time. You can do an explicit check for vector-vector indexing:

... if isvector(A) && isvector(B) C = A(:); D = C(B(:)); else D = A(B); end ...

The indexing in the first branch specifies that `C`

and `B(:)`

are
compile-time vectors. As a result, the code generator applies the
standard vector-vector indexing rule.

The following limitations apply to matrix indexing operations for code generation:

Initialization of the following style:

for i = 1:10 M(i) = 5; end

In this case, the size of

`M`

changes as the loop is executed. Code generation does not support increasing the size of an array over time.For code generation, preallocate

`M`

as highlighted in the following code.M = zeros(1,10); for i = 1:10 M(i) = 5; end

`M(i:j)`

where`i`

and`j`

change in a loopDuring code generation, memory is not dynamically allocated for the size of the expressions that change as the program executes. To implement this behavior, use

`for-`

loops as shown in the following example:... M = ones(10,10); for i = 1:10 for j = i:10 M(i,j) = 2*M(i,j); end end ...

**Note:**The matrix`M`

must be defined before entering the loop, as shown in the highlighted code.

For code generation, when you concatenate variable-size arrays, the dimensions that are not being concatenated must match exactly.

Suppose that:

`c`

is a variable-size cell array.You access the contents of

`c`

by using curly braces. For example,`c{2:4}`

.You include the results in concatenation. For example,

`[a c{2:4} b]`

.`c{I}`

returns no elements. Either`c`

is empty or the indexing inside the curly braces produces an empty result.

For these conditions, MATLAB omits `c{I}`

from
the concatenation. For example, `[a c{I} b]`

becomes ```
[a
b]
```

. The code generator treats `c{I}`

as
the empty array `[c{I}]`

. The concatenation becomes `[...[c{i}]...]`

.
This concatenation then omits the array `[c{I}]`

.
So that the properties of `[c{I}]`

are compatible
with the concatenation `[...[c{i}]...]`

, the code
generator assigns the class, size, and complexity of `[c{I}]`

according
to these rules:

The class and complexity are the same as the base type of the cell array.

The size of the second dimension is always 0.

For the rest of the dimensions, the size of

`Ni`

depends on whether the corresponding dimension in the base type is fixed or variable size.If the corresponding dimension in the base type is variable size, the dimension has size 0 in the result.

If the corresponding dimension in the base type is fixed size, the dimension has that size in the result.

Suppose that `c`

has a base type with class `int8`

and
size`:10x7x8x:?`

. In the generated code, the class
of `[c{I}]`

is `int8`

. The size
of `[c{I}]`

is `0x0x8x0`

. The second
dimension is 0. The first and last dimensions are 0 because those
dimensions are variable size in the base type. The third dimension
is 8 because the size of the third dimension of the base type is a
fixed size 8.

Inside concatenation, if curly-brace indexing of a variable-size cell array returns no elements, the generated code can have the following differences from MATLAB:

The class of

`[...c{i}...]`

in the generated code can differ from the class in MATLAB.When

`c{I}`

returns no elements, MATLAB removes`c{I}`

from the concatenation. Therefore,`c{I}`

does not affect the class of the result. MATLAB determines the class of the result based on the classes of the remaining arrays, according to a precedence of classes. See Valid Combinations of Unlike Classes. In the generated code, the class of`[c{I}]`

affects the class of the result of the overall concatenation`[...[c{I}]...]`

because the code generator treats`c{I}`

as`[c{I}]`

. The previously described rules determine the class of`[c{I}]`

.In the generated code, the size of

`[c{I}]`

can differ from the size in MATLAB.In MATLAB, the concatenation

`[c{I}]`

is a 0x0 double. In the generated code, the previously described rules determine the size of`[c{I}]`

.

You cannot use dynamic memory allocation for variable-size data in MATLAB Function blocks. Use bounded instead of unbounded variable-size data.

Was this topic helpful?