Incompatibilities with MATLAB in Variable-Size Support for Code Generation - MATLAB & Simulink (original) (raw)

Incompatibility with MATLAB for Scalar Expansion

Scalar expansion is a method of converting scalar data to match the dimensions of vector or matrix data. If one operand is a scalar and the other is not, scalar expansion applies the scalar to every element of the other operand.

During code generation, 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. Therefore, when run-time error checks are enabled, a run-time error can occur.

Consider this function:

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 thatz is variable size with an upper bound of 3.

This image shows the report for the function scalar_exp_test_err1. z is variable-size with an upper bound of 3, as indicated in the size column. The semicolon next to each dimension indicates that the dimension is variable-size.

If you run the MEX function with u equal to 0 or 1, the generated code does not perform scalar expansion, even though z is scalar at run time. Therefore, when run-time error checks are enabled, a run-time error can occur.

scalar_exp_test_err1_mex(0) Subscripted assignment dimension mismatch: [9] ~= [1].

Error in scalar_exp_test_err1 (line 11) y(:) = z;

To avoid this issue, 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);

Incompatibility with MATLAB in Determining Size of Variable-Size N-D Arrays

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:

Workarounds

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:

Incompatibility with MATLAB for Default Dimension Selection

For some MATLAB functions, such as fft, mean, and sum, you can specify the array dimension along which MATLAB operates. If you do not specify a dimension, MATLAB selects the first dimension whose size does not equal 1. In contrast, the code generator selects the first dimension whose size does not equal 1 or that is variable size at code generation time. If the dimension selected by the code generator is variable size at code generation time and has a size of 1 at run time, the generated code produces this run-time error:

Generated code expects a variable-size matrix but receives a variable-length vector. Specify the operating dimension explicitly or specify a variable-length vector at code generation time.

For example, consider this function:

function out = getMean(A) out = mean(A); end

Generate MEX code for this function. Use coder.typeof to specify that A is a variable-size 1-by-10 array of doubles. Because the first dimension of this array is variable size, the code generator selects it as the operating dimension.

codegen getMean -args {coder.typeof(0,[1,10],[1,1])}

If you call the generated MEX function with a row vector input, the function produces the run-time error above.

Workaround

To resolve the run-time error, try one of these solutions:

Incompatibility with MATLAB in Determining Size of Empty Arrays

The size of an empty array in generated code might be different from its size in MATLAB source code. The size might be 1x0 or0x1 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 size0x0. 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 is1x0 instead of 0x0.

This behavior persists while determining the size of empty character vectors which are denoted as ''. For example, consider the following code:

function out = string_size out = size(''); end

Here, the value of out might be 1x0 or0x1 in generated code, but 0x0 in MATLAB.

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.

Workaround

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

Incompatibility with MATLAB in Determining Class of Empty Arrays

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 statementn > 1 is false, MATLAB does not execute x = ['a' x]. The class ofx 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.

Workaround

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

Incompatibility with MATLAB Due to Resizing of Empty Arrays by MEX, SIL, and PIL Functions

If you generate a MEX, SIL, or PIL function that can accept an empty array, the generated function accepts empty arrays of any size. Empty arrays are arrays with at least one dimension equal to0. At run time, the generated function resizes empty input arrays to be compatible with the size of the array that was specified at code generation time. Therefore, the size of an empty array in a generated MEX, SIL, or PIL function can differ from the size of the empty array in the corresponding MATLAB function.

For example, consider the simple function testResize, which returns the size of the input arrayx.

function out = testResize(x) out = size(x); end

Generate a MEX function from this MATLAB function and specify the input as a matrix of doubles with size4x:inf.

codegen testResize -args {coder.typeof(0,[4 inf])}

In addition to accepting non-empty arrays of size 4x:inf, the generated function testResize_mex also accepts empty arrays of any size. BecausetestResize_mex resizes empty run-time inputs to be compatible with the size of the input array specified at code generation time, the size ofx is 4x0 for all empty run-time inputs.

testResize(zeros(3,0,6))

ans =

 3     0     6

testResize_mex(zeros(3,0,6))

ans =

 4     0

Incompatibility with MATLAB in Matrix-Matrix Indexing

In matrix-matrix indexing, you use one matrix (the index matrix) to index into another matrix (the data matrix). In MATLAB, the general rule for matrix-matrix indexing is that the dimensions of the result are the same as the dimensions of the index matrix. For example, ifA and B are matrices,size(A(B)) equals size(B). However, whenA and B are vectors, MATLAB applies a different rule. When performing vector-vector indexing, the orientation of the result is the same as the orientation of the data matrix. For example, ifA is 1-by-5 and B is 3-by-1, thenA(B) is 1-by-3.

The code generator attempts to apply the same matrix-matrix indexing rules as MATLAB. If A and B are variable-size matrices at code generation time, the code generator follows the general MATLAB indexing rule and assumes that size(A(B)) equalssize(B). At run time, if A andB are vectors with different orientations, then this assumption is incorrect. Therefore, when run-time error checks are enabled, an error can occur.

To avoid this run-time error, try one of these solutions:

Incompatibility with MATLAB in Vector-Vector Indexing

In vector-vector indexing, you use one vector (the index vector) to index into another vector (the data vector). In MATLAB, the rule for vector-vector indexing is that the orientation of the result vector is the same as the orientation of the data vector. For example, if A is 1-by-5 and B is 3-by-1, then A(B) is 1-by-3. However, this rule does not apply if A is a scalar. If A is scalar, then the orientation of A(B) is the same as the orientation of the index vectorB.

The code generator attempts to apply the same vector-vector indexing rules as MATLAB. If A is a variable-size vector at code generation time, the code generator assumes that the orientation of A(B) is the same as the orientation of A. However, this assumption is false and a run time error occurs if both of these conditions are true:

To avoid this run-time error, try one of these solutions:

Incompatibility with MATLAB in Logical Indexing

In logical indexing, you use an array of logical values (the index array) to index into another array (the data array). In MATLAB execution, the shape of the resulting array depends on whether the index and data arrays are matrices, vectors, or scalars. When you generate C/C++ code for MATLAB code that performs logical indexing using variable-size arrays, the code generator can make assumptions about the shape of the indexing result that are false for some run-time inputs, causing a run-time error.

If the index and data arrays are fixed-size at run time, you can avoid this run-time error by defining both of these arrays as fixed-size at code generation time.

If either or both arrays must be defined as variable-size at code generation time, this table shows some possible solutions for the run-time errors that can occur for certain inputs. In this table, A is the data array andB is the logical index array.

Definition at Code Generation Time Input at Run Time Possible Solution
A is a fixed-size matrix andB is a variable-size matrix. B is a row vector. Force B to be a column vector at run time using the colon operator.
A is a variable-size matrix andB is a fixed-size matrix. A is a row vector. Force A to be a column vector at run time using the colon operator.
A is a variable-size matrix andB is a variable-size matrix. A is a row vector. Force A to be a column vector at run time using the colon operator.
A is a variable-size matrix andB is a variable-size matrix. A is a matrix and B is a row vector. Force B to be a column vector at run time using the colon operator.
A is a variable-size matrix andB is a vector. A and B are vectors, and the orientations of A andB are different. Force A and B to have the same orientation at run time.

Incompatibility with MATLAB in Matrix Indexing Operations for Code Generation

The following limitation applies to matrix indexing operations for code generation:

The following limitation applies to matrix indexing operations for code generation when dynamic memory allocation is disabled:

Incompatibility with MATLAB in Concatenating Variable-Size Matrices

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

Differences When Curly-Brace Indexing of Variable-Size Cell Array Inside Concatenation Returns No Elements

Suppose that:

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:

Suppose that c has a base type with classint8 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: