Main Content

Differences Between Generated Code and MATLAB Code

To convert MATLAB® code to efficient C/C++ code, the code generator introduces optimizations that intentionally cause the generated code to behave differently, and sometimes produce different results, than the original source code.

Here are some of the differences:

These differences are applicable for:

  • MEX and standalone C/C++ code generation by using the codegen (MATLAB Coder) command or the MATLAB Coder™ app.

  • Fixed-point code acceleration by generating MEX using the fiaccel (Fixed-Point Designer) command.

  • MATLAB Function block simulation using Simulink®.

When you run your generated fiaccel MEX, C/C++ MEX or standalone C/C++ code, run-time error checks can detect some of these differences. By default, run-time error checks are enabled for MEX code and disabled for standalone C/C++ code. To help you identify and address differences before you deploy code, the code generator reports a subset of the differences as potential differences (MATLAB Coder).

Functions that have Multiple Possible Outputs

Certain mathematical operations, such as singular value decomposition and eigenvalue decomposition of a matrix, can have multiple answers. Two different algorithms implementing such an operation can return different outputs for identical input values. Two different implementations of the same algorithm can also exhibit the same behavior.

For such mathematical operations, the corresponding functions in the generated code and MATLAB might return different outputs for identical input values. To see if a function has this behavior, in the corresponding function reference page, see the C/C++ Code Generation section under Extended Capabilities. Examples of such functions include svd and eig.

Passing Input Argument Name at Run Time

Suppose that foo is a function that uses name-value argument validation. When you call foo from another function bar, the code generator must be able to determine the names that you provide to foo at compile time.

If the argument names are passed at run time, code generation fails in most situations. See Names Must Be Compile-Time Constants (MATLAB Coder).

In certain situations, the code generator assigns the name that you passed to an optional positional or repeating input argument. In such situations, code generation succeeds with a warning and the generated code might produce results that are different from MATLAB execution. For example, consider this function:

function out = myNamedArg_warns(a,b)
out = local(a,b);
end

function out = local(varargin,args)
arguments (Repeating)
    varargin
end

arguments
    args.x
    args.y
end

if isfield(args,'x') && isfield(args,'y') 
    out = args.x / args.y;
elseif isfield(args,'x')
    out = args.x;
else
    out = varargin{1};
end
end

Behavior of MATLAB Execution

If you call myNamedArg_warns with 'x' as the first input argument, MATLAB matches it against the first name-value argument of the function local.

myNamedArg_warns('x',5)
ans =

     5

By contrast, if you call myNamedArg_warns with 'z' as the first input argument (that does not match with either name-value argument of local), MATLAB assigns the inputs into elements of varargin.

myNamedArg_warns('z',5)
ans =

    'z'

Behavior of Generated Code

Attempt to generate a MEX by running the codegen command. Specify the type of the first argument to be a character scalar and the second argument to be a double scalar. Code generation succeeds with a warning.

codegen myNamedArg_warns -args {'x',2}
Warning: This argument is not constant, and therefore does not match against a name-value argument inside 'myNamedArg_warns/local'
during code generation. Code generation might fail or produce results that do not agree with MATLAB if a name passed at a call site
is not known during code generation.

Warning in ==> myNamedArg_warns Line: 2 Column: 13
Code generation successful (with warnings): View report

Irrespective of whether you pass 'x' or 'z' as the first input argument, the generated MEX assigns it to the first cell of varargin.

myNamedArg_warns_mex('x',5)
ans =

    'x'
myNamedArg_warns_mex('z',5)
ans =

    'z'

Workaround.  To enable the code generator to match the first input against the name-value arguments of the function local, declare the first input to be a compile-time constant with value 'x'. You can do this by using the coder.Constant function with the -args option of the codegen command.

codegen myNamedArg_warns -args {coder.Constant('x'),2}
Code generation successful.

Now, the behavior of the generated MEX agrees with MATLAB, although the MEX is unable to accept any value other than 'x' for the first input.

myNamedArg_warns_mex('x',5)
ans =

     5
myNamedArg_warns_mex('z',5)
Constant function parameter 'a' has a different run-time value than the compile-time value.

Error in myNamedArg_warns_mex

Empty Repeating Input Argument

In code generation, if a repeating input argument (that is declared in an arguments block) is empty at run time, the size of that argument is 0x0. By contrast, in MATLAB execution, the size of an empty repeating input argument is 1x0.

For example, consider this function:

function out = testVararginSize
out = local;
end

function out = local(varargin)
arguments (Repeating)
    varargin
end
out = size(varargin);
end

Running testVararginSize in MATLAB returns [1 0]. If you generate a MEX for testVararginSize and run the generated MEX, you get [0 0]. However, iterating over elements of varargin by using length(varargin) or numel(varargin) produces the same behavior across MATLAB and code generation.

Output Argument Validation of Conditionally-Assigned Outputs

The code generator validates an output argument if the argument is assigned a type during code generation. By contrast, MATLAB execution validates an output argument if the argument is assigned a value when the MATLAB function returns.

In most situations, this underlying behavioral difference does not cause your generated code to behave differently than MATLAB. Here is an example function for which you do see this difference:

function outerFunc(in)
innerFunc(in);
end

function out = innerFunc(inputVal)
arguments (Output)
    out {mustBePositive}
end
if inputVal
    out = inputVal;
end
end

In MATLAB, the execution of func succeeds for all double inputs. If the input is positive, out is assigned this positive value and the validator mustBePositive runs without assertion. If the input is negative or zero, out is not assigned and is not validated.

Attempt to generate code for func. Specify the input type to be a double scalar.

codegen outerFunc -args 0
Variable 'out' is not fully defined on some execution paths.

Error in ==> outerFunc Line: 7 Column: 5
Code generation failed: View Error Report

Because the variable out is assigned a double scalar value on one execution path, code generation assigns a double scalar type to out at compile time. The code generator then attempts to perform validation on out and discovers that it is not fully defined if the if condition fails.

Writing to ans Variable

When you run MATLAB code that returns an output without specifying an output argument, MATLAB implicitly writes the output to the ans variable. If the variable ans already exists in the workspace, MATLAB updates its value to the output returned.

The code generated from such MATLAB code does not implicitly write the output to an ans variable.

For example, define the MATLAB function foo that explicitly creates an ans variable in the first line. The function then implicitly updates the value of ans when the second line executes.

function foo %#codegen
ans = 1;
2;
disp(ans);
end

Run foo at the command line. The final value of ans, which is 2, is displayed at the command line.

foo
2

Generate a MEX function from foo.

codegen foo

Run the generated MEX function foo_mex. This function explicitly creates the ans variable and assigns the value 1 to it. But foo_mex does not implicitly update the value of ans to 2.

foo_mex
1

Logical Short-Circuiting

Suppose that your MATLAB code has the logical operators & and | placed inside square brackets ([ and ]). For such code patterns, the generated code does not employ short-circuiting behavior for these logical operators, but some MATLAB execution employs short-circuiting behavior. See Tips and Tips.

For example, define the MATLAB function foo that uses the & operator inside square brackets in the conditional expression of an if...end block.

function foo
if [returnsFalse() & hasSideEffects()]
end
end

function out = returnsFalse
out = false;
end

function out = hasSideEffects
out = true;
disp('This is my string');
end

The first argument of the & operator is always false and determines the value of the conditional expression. So, in MATLAB execution, short-circuiting is employed and the second argument is not evaluated. So, foo does not call the hasSideEffects function during execution and does not display anything at the command line.

Generate a MEX function for foo. Call the generated MEX function foo_mex.

foo_mex
This is my string

In the generated code, short-circuiting is not employed. So, the hasSideEffects function is called and the string is displayed at the command line.

Loop Index Overflow

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 Check for Issues in MATLAB Code Using MEX Functions (MATLAB Coder) and Generate Standalone C/C++ Code That Detects and Reports Run-Time Errors (MATLAB Coder).

To avoid a loop index overflow, use the workarounds in this table.

Loop Conditions Causing the Potential OverflowWorkaround
  • The loop index increments by 1.

  • The end value equals the maximum value of the integer type.

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
with:
for k=1:10

  • The loop index decrements by 1.

  • The end value equals the minimum value of the integer type.

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
with:
for k=10:-1:1

  • The loop index increments or decrements by 1.

  • The start value equals the minimum or maximum value of the integer type.

  • The end value equals the maximum or minimum value of the integer type.

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
as:
M= intmin('int16');
N= intmax('int16');
for k=int32(M):int32(N)
	% Loop body
end

  • The loop index increments or decrements by a value not equal to 1.

  • On the last loop iteration, the loop index is not equal to the end value.

Rewrite the loop so that the loop index in the last loop iteration is equal to the end value.

Indexing for Loops by Using Single Precision Operands

Suppose in your MATLAB code, you are indexing a for loop that has a colon operator, where at least one of the colon operands is a single type operand and the number of iterations is greater than flintmax('single') = 16777216. When all these conditions are true, code generation might generate run-time or compile-time errors because the generated code calculates different values for the loop index variable than the values that MATLAB calculates.

For example, consider this MATLAB code:

function j = singlePIndex
n = flintmax('single') + 2;
j = single(0);
for i = single(1):single(n)
    j = i;
end
end

This code snippet executes in MATLAB, but it causes a compile-time or run-time error because the value of the loop index variable, i, is calculated differently in the generated code. The code generator displays a compile-time or run-time error and stops code generation or execution to prevent this discrepancy.

To avoid this discrepancy, replace the single type operands with double type or integer type operands.

For more information on run-time errors, see Generate Standalone C/C++ Code That Detects and Reports Run-Time Errors (MATLAB Coder).

Index of an Unentered for Loop

In your MATLAB code and generated code, after a for loop execution is complete, the value of the index variable is equal to its value during the final iteration of the for loop.

In MATLAB, if the loop does not execute, the value of the index variable is stored as [ ] (empty matrix). In generated code, if the loop does not execute, the value of the index variable is different than the MATLAB index variable.

  • If you provide the for loop start and end variables at run time, the value of the index variable is equal to the start of the range. For example, consider this MATLAB code:

    function out = indexTest(a,b)
    for i = a:b
    end
    out = i;
    end

    Suppose that a and b are passed as 1 and -1. The for loop does not execute. In MATLAB, out is assigned [ ]. In the generated code, out is assigned the value of a, which is 1.

  • If you provide the for loop start and end values before compile time, the value of the index variable is assigned [ ] in both MATLAB and the generated code. Consider this MATLAB code:

    function out = indexTest
    for i = 1:-1
    end
    out = i;
    end

    In both MATLAB and the generated code, out is assigned [ ].

Character Size

MATLAB supports 16-bit characters, but the generated code represents characters in 8 bits, the standard size for most embedded languages like C. See Encoding of Characters in Code Generation.

Order of Evaluation in Expressions

Generated code does not enforce the order of evaluation in expressions. For most expressions, the order of evaluation is not significant. For expressions that have side effects, the generated code might produce the side effects in a different order from the original MATLAB code. Expressions that produce side effects include those that:

  • Modify persistent or global variables

  • Display data to the screen

  • Write data to files

  • Modify the properties of handle class objects

In addition, the generated code does not enforce order of evaluation of logical operators that do not short circuit.

For more predictable results, it is good coding practice to split expressions that depend on the order of evaluation into multiple statements.

  • Rewrite

    A = f1() + f2();

    as

    A = f1();
    A = A + f2();

    so that the generated code calls f1 before f2.

  • Assign the outputs of a multi-output function call to variables that do not depend on one another. For example, rewrite

    [y, y.f, y.g] = foo;

    as

    [y, a, b] = foo;
    y.f = a;
    y.g = b;
    

  • When you access the contents of multiple cells of a cell array, assign the results to variables that do not depend on one another. For example, rewrite

    [y, y.f, y.g] = z{:};
    

    as

    [y, a, b] = z{:};
    y.f = a;
    y.g = b;
    

Name Resolution While Constructing Function Handles

MATLAB and code generation follow different precedence rules for resolving names that follow the symbol @. These rules do not apply to anonymous functions. The precedence rules are summarized in this table.

ExpressionPrecedence Order in MATLABPrecedence Order in Code Generation
An expression that does not contain periods, for example @x

Nested function, local function, private function, path function

Local variable, nested function, local function, private function, path function

An expression that contains exactly one period, for example @x.y

Local variable, path function

Local variable, path function (Same as MATLAB)

An expression that contains more than one period, for example @x.y.z

Path function

Local variable, path function

If x is a local variable that is itself a function handle, generated code and MATLAB interpret the expression @x differently:

  • MATLAB produces an error.

  • Generated code interprets @x as the function handle of x itself.

Here is an example that shows this difference in behavior for an expression that contains two periods.

Suppose that your current working folder contains a MATLAB namespace x, which contains another namespace y, which contains the function z. The current working folder also contains the entry-point function foo for which you want to generate code.

Image of current folder showing the files z.m and foo.m with respect to the namespaces x and y.

This is the definition for the file foo:

function out = foo
    x.y.z = @()'x.y.z is an anonymous function';
    out = g(x);
end

function out = g(x)
    f = @x.y.z;
    out = f();
end

This is the definition for function z:

function out = z
    out = 'x.y.z is a namespace function';
end

Generate a MEX function for foo. Separately call both the generated MEX function foo_mex and the MATLAB function foo.

codegen foo
foo_mex
foo
ans =

    'x.y.z is an anonymous function'


ans =

    'x.y.z is a namespace function'

The generated code produces the first output. MATLAB produces the second output. Code generation resolves @x.y.z to the local variable x that is defined in foo. MATLAB resolves @x.y.z to z, which is within the namespace x.y.

Termination Behavior

Generated code does not match the termination behavior of MATLAB source code. For example, if infinite loops do not have side effects, optimizations remove them from generated code. As a result, the generated code can possibly terminate even though the corresponding MATLAB code does not.

Size of Variable-Size N-D Arrays

For variable-size N-D arrays, the size function might return a different result in generated code than in MATLAB source code. The size function sometimes returns trailing ones (singleton dimensions) in generated code, but always drops trailing ones in MATLAB. For example, for an N-D array X with dimensions [4 2 1 1], size(X) might return [4 2 1 1] in generated code, but always returns [4 2] in MATLAB. See Incompatibility with MATLAB in Determining Size of Variable-Size N-D Arrays.

Size of Empty Arrays

The size of an empty array in generated code might be different from its size in MATLAB source code. See Incompatibility with MATLAB in Determining Size of Empty Arrays.

Size of Empty Array That Results from Deleting Elements of an Array

Deleting all elements of an array results in an empty array. The size of this empty array in generated code might differ from its size in MATLAB source code.

CaseExample CodeSize of Empty Array in MATLABSize of Empty Array in Generated Code
Delete all elements of an m-by-n array by using the colon operator (:).
coder.varsize('X',[4,4],[1,1]);
X = zeros(2);
X(:) = [];
0-by-01-by-0
Delete all elements of a row vector by using the colon operator (:).
coder.varsize('X',[1,4],[0,1]);
X = zeros(1,4);
X(:) = [];
0-by-01-by-0
Delete all elements of a column vector by using the colon operator (:).
coder.varsize('X',[4,1],[1,0]);
X = zeros(4,1);
X(:) = [];
0-by-00-by-1
Delete all elements of a column vector by deleting one element at a time.
coder.varsize('X',[4,1],[1,0]);
X = zeros(4,1);
for i = 1:4
    X(1)= [];
end
1-by-00-by-1

Growing Variable-Size Column Cell Array That is Initialized as Scalar at Run Time

In MATLAB execution, if you grow a scalar cell array by using {end+1} indexing, the cell array grows along the second dimension and produces a row cell array. For example, define the function growCell:

function z = growCell(n, m)
for i = 1:m
    n{end+1} = m;
end
z = n;
end

Call growCell with example inputs:

growCell({2}, 3)
ans =

  1×4 cell array

    {[2]}    {[3]}    {[3]}    {[3]}

By contrast, in code generation, suppose that:

  • You specify the cell array to be of variable-size column type (for example, :Inf x 1) at compile time, and

  • Initialize this cell array as a scalar at run time.

In such situations, the generated code grows the scalar cell array along the first dimension and produces a column cell array. For example, generate MEX code for growCell. Specify the input n to be a :Inf x 1 cell array with double as the underlying type. Specify the input m to be of double scalar type.

codegen growCell -args {coder.typeof({0}, [Inf 1], [1 0]), 1}
Code generation successful.

Run the generated MEX with the same inputs as before.

growCell_mex({2}, 3)
ans =

  4×1 cell array

    {[2]}
    {[3]}
    {[3]}
    {[3]}

Binary Element-Wise Operations with Single and Double Operands

If your MATLAB code contains a binary element-wise operation that involves a single type operand and a double type operand, the generated code might not produce the same result as MATLAB.

For such an operation, MATLAB casts both operands to double type and performs the operation with the double types. MATLAB then casts the result to single type and returns it.

The generated code casts the double type operand to single type. It then performs the operation with the two single types and returns the result.

For example, define a MATLAB function foo that calls the binary element-wise operation plus.

function out = foo(a,b)
out = a + b;
end

Define a variable s1 of single type and a variable d1 of double type. Generate a MEX function for foo that accepts a single type input and a double type input.

s1 = single(1.4e32); 
d1 = -5.305e+32; 
codegen foo -args {s1, d1} 

Call both foo and foo_mex with inputs s1 and d1. Compare the two results.

ml = foo(s1,d1); 
mlc = foo_mex(s1,d1);
ml == mlc
ans =

  logical

   0

The output of the comparison is a logical 0, which indicates that the generated code and MATLAB produces different results for these inputs.

Floating-Point Numerical Results

The generated code might not produce the same floating-point numerical results as MATLAB in these:

 When computer hardware uses extended precision registers

 For certain advanced library functions

 For implementation of BLAS library functions

NaN and Infinity

The generated code might not produce exactly the same pattern of NaN and Inf values as MATLAB code when these values are mathematically meaningless. For example, if MATLAB output contains a NaN, output from the generated code should also contain a NaN, but not necessarily in the same place.

The bit pattern for NaN can differ between MATLAB code output and generated code output because the C99 language standard that is used to generate code does not specify a unique bit pattern for NaN across all implementations. Avoid comparing bit patterns across different implementations, for example, between MATLAB output and SIL or PIL output.

Negative Zero

In a floating-point type, the value 0 has either a positive sign or a negative sign. Arithmetically, 0 is equal to -0, but some operations are sensitive to the sign of a 0 input. Examples include rdivide, atan2, atan2d, and angle. Division by 0 produces Inf, but division by -0 produces -Inf. Similarly, atan2d(0,-1) produces 180, but atan2d (-0,-1) produces -180.

If the code generator detects that a floating-point variable takes only integer values of a suitable range, then the code generator can use an integer type for the variable in the generated code. If the code generator uses an integer type for the variable, then the variable stores -0 as +0 because an integer type does not store a sign for the value 0. If the generated code casts the variable back to a floating-point type, the sign of 0 is positive. Division by 0 produces Inf, not -Inf. Similarly, atan2d(0,-1) produces 180, not -180.

There are other contexts in which the generated code might treat -0 differently than MATLAB. For example, suppose that your MATLAB code computes the minimum of two scalar doubles x and y by using z = min(x,y). The corresponding line in the generated C code might be z = fmin(x,y). The function fmin is defined in the runtime math library of the C compiler. Because the comparison operation 0.0 == -0.0 returns true in C/C++, the compiler's implementation of fmin might return either 0.0 or -0.0 for fmin(0.0,-0.0).

Code Generation Target

The coder.target function returns different values in MATLAB than in the generated code. The intent is to help you determine whether your function is executing in MATLAB or has been compiled for a simulation or code generation target. See coder.target.

MATLAB Class Property Initialization

Before code generation, at class loading time, MATLAB computes class default values. The code generator uses the values that MATLAB computes. It does not recompute default values. If the property definition uses a function call to compute the initial value, the code generator does not execute this function. If the function has side effects, such as modifying a global variable or a persistent variable, then the generated code can produce different results than MATLAB. For more information, see Defining Class Properties for Code Generation.

MATLAB Classes in Nested Property Assignments That Have Set Methods

When you assign a value to a handle object property, which is itself a property of another object, and so on, then the generated code can call set methods for handle classes that MATLAB does not call.

For example, suppose that you define a set of variables such that x is a handle object, pa is an object, pb is a handle object, and pc is a property of pb. Then you make a nested property assignment, such as:

x.pa.pb.pc = 0;

In this case, the generated code calls the set method for the object pb and the set method for x. MATLAB calls only the set method for pb.

MATLAB Handle Class Destructors

The behavior of handle class destructors in the generated code can be different from the behavior in MATLAB in these situations:

  • The order of destruction of several independent objects might be different in MATLAB than in the generated code.

  • The lifetime of objects in the generated code can be different from their lifetime in MATLAB.

  • The generated code does not destroy partially constructed objects. If a handle object is not fully constructed at run time, the generated code produces an error message but does not call the delete method for that object. For a System object™, if there is a run-time error in setupImpl, the generated code does not call releaseImpl for that object.

    MATLAB does call the delete method to destroy a partially constructed object.

For more information, see Code Generation for Handle Class Destructors.

Variable-Size Data

See Incompatibilities with MATLAB in Variable-Size Support for Code Generation.

Complex Numbers

See Code Generation for Complex Data.

Converting Strings with Consecutive Unary Operators to double

Converting a string that contains multiple, consecutive unary operators to double can produce different results between MATLAB and the generated code. Consider this function:

function out = foo(op)
out = double(op + 1);
end

For an input value "--", the function converts the string "--1" to double. In MATLAB, the answer is NaN. In the generated code, the answer is 1.

Display Function

Statements and expressions in MATLAB code that omit the semicolon implicitly invoke the display function. You can also explicitly invoke display as shown here:

display(2+3);
     5

The MEX code generated for MATLAB code that invokes the display function preserves calls to this function and shows the output. In standalone code generated for targets that do not have access to MATLAB Runtime, implicit and explicit calls to display are removed. This includes calls to overridden class methods of display.

To display text in code generated for other targets, override the disp function in your MATLAB classes. For example:

%MATLAB Class

classdef foo
    methods
        function obj = foo
        end
        function disp(self)
            disp("Overridden disp");
        end
    end
end

%Entry-point Function

function callDisp
a = foo;
disp(a);
end

The generated code for the entry-point function is shown here:

/* Include Files */
#include "callDisp.h"
#include <stdio.h>

/* Function Definitions */
/*
 * Arguments    : void
 * Return Type  : void
 */
void callDisp(void)
{
  printf("%s\n", "Overridden disp");
  fflush(stdout);
}

Function Handle Difference

Invoking display through a function handle in MATLAB prints the name of the variable as well. For example, running this function in MATLAB results in the following output:

function displayDiff
z = 10;
f = @display;
f(z)
end
z =

    10

However, the generated code for this snippet only outputs the value 10.