When you enable potential differences reporting, the code generator reports potential differences between the behavior of the generated code and the behavior of the MATLAB® code. Reviewing and addressing potential differences before you generate standalone code helps you to avoid errors and incorrect answers in generated code.
Here are some of the potential differences messages:
In the generated code, the dimension to operate along is selected automatically, and might be different from MATLAB. Consider specifying the working dimension explicitly as a constant value.
This restriction applies to functions that take the working dimension (the dimension along which to operate) as input. In MATLAB and in code generation, if you do not supply the working dimension, the function selects it. In MATLAB, the function selects the first dimension whose size does not equal 1. For code generation, the function selects the first dimension that has a variable size or that has a fixed size that does not equal 1. If the working dimension has a variable size and it becomes 1 at run time, then the working dimension is different from the working dimension in MATLAB. Therefore, when run-time error checks are enabled, an error can occur.
For example, suppose that X
is a variable-size
matrix with dimensions 1x:3x:5
. In the generated
code, sum(X)
behaves like sum(X,2)
.
In MATLAB, sum(X)
behaves like sum(X,2)
unless size(X,2)
is
1. In MATLAB, when size(X,2)
is 1, sum(X)
behaves
like sum(X,3)
.
To avoid this issue, specify the intended working dimension
explicitly as a constant value. For example, sum(X,2)
.
The generated code performs a general matrix multiplication. If a variable-size matrix operand becomes a scalar at run time, dimensions must still agree. There will not be an automatic switch to scalar multiplication.
Consider the multiplication A*B
. If the code
generator is aware that A
is scalar and B
is
a matrix, the code generator produces code for scalar-matrix multiplication.
However, if the code generator is aware that A
and B
are
variable-size matrices, it produces code for a general matrix multiplication.
At run time, if A
turns out to be scalar, the generated
code does not change its behavior. Therefore, when run-time error
checks are enabled, a size mismatch error can occur.
For indexing a matrix with a matrix, matrix1(matrix2), the code generator assumed that the result would have the same size as matrix2. If matrix1 and matrix2 are vectors at run time, their orientations must match.
In matrix-matrix indexing, you use one matrix to index into
another matrix. In MATLAB, the general rule for matrix-matrix
indexing is that the size and orientation of the result match the
size and orientation of the index matrix. For example, if A
and B
are
matrices, size(A(B))
equals size(B)
.
When A
and B
are vectors, MATLAB applies
a special rule. The special vector-vector indexing rule is that the
orientation of the result is the orientation of the data matrix. For
example, iA
is 1-by-5 and B
is
3-by-1, then A(B)
is 1-by-3.
The code generator applies the same matrix-matrix indexing rules
as MATLAB. If A
and B
are
variable-size matrices, to apply the matrix-matrix indexing rules,
the code generator assumes that the size(A(B))
equals size(B)
.
If, at run time, A
and B
become
vectors and have different orientations, then the assumption is incorrect.
Therefore, when run-time error checks are enabled, an error can occur.
To avoid this issue, force your data to be a vector by using the colon operator for indexing. For example, suppose that 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. Therefore, the code generator applies the indexing
rule for indexing one vector with another vector. The orientation
of the result is the orientation of the data vector, C
.
For indexing a vector with a vector, vector1(vector2), the code generator assumed that the result would have the same orientation as vector1. If vector1 is a scalar at run time, the orientation of vector2 must match vector1.
In MATLAB, the special rule for vector-vector indexing
is that the orientation of the result is 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. If, however, the data
vector A
is a scalar, then the orientation of A(B)
is
the orientation of the index vector B
.
The code generator applies the same vector-vector indexing
rules as MATLAB. If A
and B
are
variable-size vectors, to apply the indexing rules, the code generator
assumes that the orientation of B
matches the
orientation of A
. At run time, if A
is
scalar and the orientation of A
and B
do
not match, then the assumption is incorrect. Therefore, when run-time
error checks are enabled, a run-time error can occur.
To avoid this issue, make the orientations of the vectors match.
Alternatively, index single elements by specifying the row and column.
For example, A(row, column)
.
The generated code assumes that the sizes on the left and right sides match.
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 that z
is variable size with an upper
bound of 3
.
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);
The generated code assumes the loop index does not overflow on the last iteration of the loop. If the loop index overflows, an infinite loop can occur.
Suppose that a for
-loop end value is equal to or close to
the maximum or minimum value for the loop index data type. In the generated code, the last
increment or decrement of the loop index might cause the index variable to overflow. The
index overflow might result in an infinite loop.
When memory integrity checks are enabled, if the code generator detects that the loop index might overflow, it reports an error. The software error checking is conservative. It might incorrectly report a loop index overflow. By default, memory-integrity checks are enabled for MEX code and disabled for standalone C/C++ code. See Why Test MEX Functions in MATLAB? and Run-Time Error Detection and Reporting in Standalone C/C++ Code.
To avoid a loop index overflow, use the workarounds in this table.
Loop Conditions Causing the Potential Overflow | Workaround |
---|---|
| If the loop does not have to cover the full range of the integer type, rewrite the loop so that the end value is not equal to the maximum value of the integer type. For example, replace: N=intmax('int16') for k=N-10:N for k=1:10 |
| If the loop does not have to cover the full range of the integer type, rewrite the loop so that the end value is not equal to the minimum value of the integer type. For example, replace: N=intmin('int32') for k=N+10:-1:N for k=10:-1:1 |
| If the loop must cover the full range of the integer type, cast the type of the loop start, step, and end values to a bigger integer or to double. For example, rewrite: M= intmin('int16'); N= intmax('int16'); for k=M:N % Loop body end M= intmin('int16'); N= intmax('int16'); for k=int32(M):int32(N) % Loop body end |
| Rewrite the loop so that the loop index in the last loop iteration is equal to the end value. |