Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

生成されたコードと MATLAB コードの相違点

MATLAB® コードを効率良く動作する C/C++ コードに変換するため、コード ジェネレーターに、元のソース コードと生成後のコードの動作が意図的に異なる (場合によっては異なる結果が出る) ように最適化が導入されています。

次のような相違点があります。

これらの相違点は以下に適用されます。

  • codegen (MATLAB Coder) コマンドまたは MATLAB Coder™ アプリを使用した MEX コードおよびスタンドアロン C/C++ コードの生成。

  • fiaccel (Fixed-Point Designer) コマンドを使用して MEX を生成することによる固定小数点コードの高速化。

  • Simulink® を使用した MATLAB Function ブロックのシミュレーション。

生成された fiaccel MEX コード、C/C++ MEX コード、またはスタンドアロン C/C++ コードを実行すると、実行時エラー チェックで次の相違点が検出される可能性があります。既定では、実行時エラー チェックは MEX コードに対して有効化され、スタンドアロン C/C++ コードに対しては無効化されています。コードを展開する前に相違点を識別して解決できるように、コード ジェネレーターは、潜在的な相違 (MATLAB Coder)として相違点のサブセットを報告します。

可能な出力が複数ある関数

行列の特異値分解や固有値分解などの特定の数学演算では、複数の解が得られる場合があります。このような演算を実装する 2 つの異なるアルゴリズムは、同じ入力値に対して異なる出力を返す場合があります。同じアルゴリズムの 2 つの異なる実装でも同じ動作になることがあります。

このような数学演算では、生成されたコードと MATLAB の対応する関数が同じ入力値に対して異なる出力を返す場合があります。関数がこの動作を示すかどうかを確認するには、対応する関数のリファレンス ページで、「拡張機能」「C/C++ コードの生成」セクションを参照してください。このような関数の例には、svdeig などがあります。

実行時の入力引数名の引き渡し

関数 foo で名前と値の引数の検証を使用するとします。foo を別の関数 bar から呼び出す場合、コンパイル時に foo に指定する名前をコード ジェネレーターで特定できなければなりません。

引数の名前が実行時に渡される場合、ほとんどの状況でコード生成が失敗します。名前はコンパイル時の定数でなければならない (MATLAB Coder)を参照してください。

特定の状況では、オプションの位置入力引数または繰り返し入力引数に渡した名前がコード ジェネレーターで代入されます。このような状況では、コード生成は成功しますが警告が発生し、生成コードと MATLAB の実行で異なる結果になることがあります。たとえば、以下の関数を考えます。

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

MATLAB の実行の動作

'x' を最初の入力引数として myNamedArg_warns を呼び出すと、MATLAB では、それが関数 local の最初の名前と値の引数と照合されます。

myNamedArg_warns('x',5)
ans =

     5

一方、'z' (local のいずれの名前と値の引数とも一致しない) を最初の入力引数として myNamedArg_warns を呼び出すと、MATLAB では、その入力が varargin の要素に代入されます。

myNamedArg_warns('z',5)
ans =

    'z'

生成コードの動作

codegen コマンドを実行して MEX を生成してみます。最初の引数の型を文字スカラー、2 番目の引数の型を double のスカラーに指定します。コード生成は成功しますが警告が発生します。

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

最初の入力引数として 'x' を渡すか 'z' を渡すかに関係なく、生成された MEX では、それが varargin の最初の cell に代入されます。

myNamedArg_warns_mex('x',5)
ans =

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

    'z'

回避方法.  コード ジェネレーターで最初の入力を関数 local の名前と値の引数と照合できるようにするには、値 'x' のコンパイル時の定数として最初の入力を宣言します。これは、codegen コマンドの -args オプションで関数 coder.Constant を使用して実行できます。

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

これで、生成される MEX の動作が MATLAB と一致します。ただし、MEX では 'x' 以外の値は最初の入力として受け入れられません。

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

空の繰り返し入力引数

コード生成では、繰り返し入力引数 (arguments ブロックで宣言) が実行時に空の場合、その引数のサイズは 0x0 になります。一方、MATLAB の実行では、空の繰り返し入力引数のサイズは 1x0 です。

たとえば、以下の関数を考えます。

function out = testVararginSize
out = local;
end

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

MATLAB で testVararginSize を実行すると、[1 0] が返されます。testVararginSize の MEX を生成し、生成された MEX を実行した場合は [0 0] になります。ただし、length(varargin) または numel(varargin) を使用して varargin の要素を反復するときは、MATLAB とコード生成で同じ動作になります。

条件付きで代入される出力の出力引数の検証

コード ジェネレーターでは、出力引数に型が代入されているかどうかをコード生成時に検証します。一方、MATLAB では、出力引数に値が代入されているかどうかを MATLAB 関数から戻るときに検証します。

ほとんどの状況では、この根本的な動作の違いによって生成コードが MATLAB と異なる動作になることはありません。この違いが現れる関数の例を次に示します。

function outerFunc(in)
innerFunc(in);
end

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

MATLAB では、すべての double の入力で func の実行が成功します。入力が正の場合、その正の値が out に代入され、検証関数 mustBePositive がアサーションなしで実行されます。入力が負またはゼロの場合は out に代入されず、検証は行われません。

func のコードを生成してみます。入力の型を double のスカラーに指定します。

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

1 つの実行パスで変数 out に double のスカラー値が代入されているため、コード生成ではコンパイル時の out に double のスカラー型が代入されます。その後、コード ジェネレーターで out の検証が試行され、if 条件を満たさないと完全に定義されないことが検出されます。

変数 ans への書き込み

出力引数を指定せずに出力を返す MATLAB コードを実行すると、MATLAB は変数 ans に出力を暗黙的に書き込みます。変数 ans が既にワークスペースに存在する場合、MATLAB はその値を返された出力に更新します。

このような MATLAB コードから生成されたコードは、変数 ans に出力を暗黙的に書き込みません。

たとえば、1 行目で変数 ans を明示的に作成する MATLAB 関数 foo を定義します。この関数は、2 行目が実行されると ans の値を暗黙的に更新します。

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

コマンド ラインで foo を実行します。ans の最終値 2 がコマンド ラインに表示されます。

foo
2

foo から MEX 関数を生成します。

codegen foo

生成された MEX 関数 foo_mex を実行します。この関数は変数 ans を明示的に作成し、その変数に値 1 を代入します。ただし、foo_mexans の値を 2 に暗黙的に更新しません。

foo_mex
1

論理ショートサーキット

MATLAB コードで論理演算子 & および | が大かっこ ([]) 内に配置されているとします。このようなコード パターンの場合、生成コードではこれらの論理演算子のショートサーキットの動作は使用されませんが、一部の MATLAB の実行ではショートサーキットの動作が使用されます。ヒントおよびヒントを参照してください。

たとえば、if...end ブロックの条件式の大かっこ内で & 演算子を使用する MATLAB 関数 foo を定義します。

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

function out = returnsFalse
out = false;
end

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

& 演算子の最初の引数は常に false で、条件式の値を決定します。そのため、MATLAB の実行ではショートサーキットが使用され、2 番目の引数は評価されません。したがって、foo では実行時に関数 hasSideEffects は呼び出されず、コマンド ラインに何も表示されません。

foo の MEX 関数を生成します。生成された MEX 関数 foo_mex を呼び出します。

foo_mex
This is my string

生成コードでは、ショートサーキットは使用されません。したがって、関数 hasSideEffects が呼び出され、コマンド ラインに文字列が表示されます。

ループ インデックスのオーバーフロー

for ループの終了値がループ インデックスのデータ型の最大値または最小値と等しいか近いと仮定します。生成コードでは、ループ インデックスの最後のインクリメントまたはデクリメントによって、インデックス変数のオーバーフローが発生する可能性があります。インデックスのオーバーフローの結果、無限ループが発生する可能性があります。

メモリの整合性チェックが有効になっている場合、ループ インデックスのオーバーフローが発生する可能性があることをコード ジェネレーターが検出すると、エラーが報告されます。ソフトウェアのエラー チェックは保守的です。ループ インデックスのオーバーフローを誤って報告する可能性があります。既定では、メモリの整合性チェックは MEX コードに対して有効化され、スタンドアロン C/C++ コードに対しては無効化されています。MATLAB で MEX 関数をテストする理由 (MATLAB Coder)および実行時エラーを検出および報告するスタンドアロン C/C++ コードの生成 (MATLAB Coder)を参照してください。

ループ インデックスのオーバーフローを回避するには、次の表の回避方法を使用してください。

オーバーフローを引き起こす可能性のあるループ条件回避方法
  • ループ インデックスが 1 ずつインクリメント

  • 終了値が整数データ型の最大値

ループがあらゆる整数データ型に対応する必要がない場合、終了値が整数データ型の最大値と等しくならないようにループを書き換えます。たとえば、

N=intmax('int16')
for k=N-10:N
次に置き換えます。
for k=1:10

  • ループ インデックスが 1 ずつデクリメント

  • 終了値が整数データ型の最小値

ループがあらゆる整数データ型に対応する必要がない場合、終了値が整数データ型の最小値と等しくならないようにループを書き換えます。たとえば、

N=intmin('int32')
for k=N+10:-1:N
次に置き換えます。
for k=10:-1:1

  • ループ インデックスが 1 ずつインクリメントまたはデクリメント

  • 開始値が整数データ型の最小値または最大値

  • 終了値が整数データ型の最大値または最小値

ループがあらゆる整数データ型に対応しなければならない場合は、ループの開始値、ステップ、および終了値の型をより大きな整数または double の値にキャストします。たとえば、次のコードを書き換えます。

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

  • ループ インデックスが 1 以外の値でインクリメントまたはデクリメント

  • 最後のループ反復において、ループ インデックスが終了値と等しくならない

ループを書き直し、最後のループ反復におけるループ インデックスが終了値と等しくなるようにします。

単精度オペランドを使用した for ループのインデックス付け

MATLAB コードで、コロン演算子がある for ループのインデックス付けを行うとします。ここでは、コロン オペランドの少なくとも 1 つが single 型のオペランドで、反復回数は flintmax('single') = 16777216 を超えます。これらすべての条件が満たされている場合、コード生成でランタイム エラーまたはコンパイル時エラーが発生する可能性があります。これは、生成されたコードで計算されるループ インデックス変数の値が MATLAB で計算される値とは異なることが原因です。

たとえば、以下の MATLAB コードについて考えます。

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

このコードの抜粋は MATLAB で実行されていますが、生成されたコードではループ インデックス変数 i に対する値が異なる方法で計算されているため、コンパイル時エラーまたはランタイム エラーが発生します。コード ジェネレーターでコンパイル時エラーまたはランタイム エラーが表示され、この不一致を回避するためにコードの生成または実行が停止します。

この不一致を回避するには、single 型のオペランドを double 型または整数型のオペランドに置き換えます。

ランタイム エラーの詳細については、実行時エラーを検出および報告するスタンドアロン C/C++ コードの生成 (MATLAB Coder)を参照してください。

未入力の for ループのインデックス

MATLAB コードと生成されたコードでは、for ループの実行が完了した後、インデックス変数の値は for ループの最終反復時の値と等しくなります。

MATLAB でループが実行されない場合、インデックス変数の値は [ ] (空行列) として保存されます。生成されたコードでループが実行されない場合、インデックス変数の値は MATLAB のインデックス変数とは異なります。

  • for ループの開始変数と終了変数を実行時に指定する場合、インデックス変数の値は範囲の開始値と等しくなります。たとえば、以下の MATLAB コードについて考えます。

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

    ab1-1 として渡されると仮定します。for ループは実行されません。MATLAB では、out に [ ] が代入されます。生成されたコードでは、outa の値 1 が代入されます。

  • for ループの開始値と終了値をコンパイルの前に指定する場合、MATLAB と生成されたコードの両方でインデックス変数の値に [ ] が代入されます。以下の MATLAB コードについて考えます。

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

    MATLAB と生成されたコードの両方で、out に [ ] が代入されます。

文字サイズ

MATLAB は 16 ビットの文字をサポートしていますが、生成されたコードでは文字を C 言語などの多くの埋め込み型言語の標準サイズである 8 ビットで表現します。コード生成での文字のエンコードを参照してください。

式の評価順番

生成されたコードは、式の評価順番を強制しません。ほとんどの式において、評価の順序は重要な意味をもちません。副作用を含む式では、生成コードと元の MATLAB コードとで副作用が異なる順序で生成される場合があります。副作用を伴う式には、以下のようなものがあります。

  • 永続変数またはグローバル変数を変更する

  • 画面にデータを表示する

  • データをファイルに書き込む

  • ハンドル クラスのオブジェクトのプロパティを変更する

また、生成されたコードは、ショートサーキットしない論理演算子の実行順番を強制しません。

結果を予測しやすくするために、実行順序に依存する式を複数のステートメントに分割してコードを書くことをお勧めします。

  • たとえば、次のコードを書き換えます。

    A = f1() + f2();

    以下のように書き換えます。

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

    こうすると、生成されたコードは f1 を呼び出してから、f2 を呼び出します。

  • 多出力関数呼び出し出力を、相互に依存していない複数の変数に代入します。たとえば、次のコードを書き換えます。

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

    これは、次のように書き換えられます。

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

  • cell 配列の複数のセルの内容にアクセスする場合、その結果を相互に依存していない変数に代入します。たとえば、次のコードを書き換えます。

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

    以下のように書き換えます。

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

関数ハンドルの作成中の名前解決

MATLAB とコード生成では、記号 @ の後の名前を解決する際に異なる優先順位規則に従います。これらの規則は無名関数には適用されません。優先順位規則を次の表にまとめます。

MATLAB での優先順位コード生成での優先順位
ピリオドを含まない式 (@x など)

入れ子関数、ローカル関数、プライベート関数、パス関数

ローカル変数、入れ子関数、ローカル関数、プライベート関数、パス関数

ピリオドを 1 つだけ含む式 (@x.y など)

ローカル変数、パス関数

ローカル変数、パス関数 (MATLAB と同じ)

複数のピリオドを含む式 (@x.y.z など)

パス関数

ローカル変数、パス関数

x がそれ自体が関数ハンドルとなるローカル変数である場合、生成されたコードと MATLAB では式 @x の解釈が異なります。

  • MATLAB ではエラーが発生します。

  • 生成されたコードでは @xx 自体の関数ハンドルとして解釈されます。

次の例では、2 つのピリオドを含む式の動作におけるこの相違点を示します。

現在の作業フォルダーにパッケージ x が含まれ、これに関数 z を含む別のパッケージ y が含まれていると仮定します。また、現在の作業フォルダーには、コードの生成対象となるエントリポイント関数 foo も含まれています。

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

ファイル 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

関数 z の定義は次のとおりです。

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

foo の MEX 関数を生成します。生成された MEX 関数 foo_mex と MATLAB 関数 foo の両方を個別に呼び出します。

codegen foo
foo_mex
foo
ans =

    'x.y.z is an anonymous function'


ans =

    'x.y.z is a package function'

生成されたコードによって最初の出力が生成されます。MATLAB によって 2 番目の出力が生成されます。コード生成では、@x.y.zfoo で定義されているローカル変数 x に解決されます。MATLAB では、@x.y.z はパッケージ x.y 内の z に解決されます。

終了動作

生成されたコードの終了動作は、MATLAB ソース コードの動作と一致しません。たとえば、無限ループに副次的影響がない場合、無限ループは最適化によって生成されたコードから除去されます。その結果、対応する MATLAB コードが終了しなくても生成コードは終了する場合があります。

可変サイズ N 次元配列のサイズ

可変サイズの N 次元配列では、関数 size で返す結果が、生成されたコードと MATLAB ソース コードで異なる場合があります。関数 size は、生成されたコードでは後に 1 を続けて返すことがありますが (大きさが 1 の次元)、MATLAB では後続する 1 は常に切り捨てられます。たとえば、N 次元の配列 X が次元 [4 2 1 1] をもっている場合、size(X) は、生成されたコードでは [4 2 1 1] を返す場合がありますが、MATLAB では常に [4 2] を返します。可変サイズの N 次元配列のサイズを判定する上での MATLAB との非互換性を参照してください。

空配列のサイズ

空の配列のサイズは、生成コードと MATLAB ソース コードでは異なる場合があります。空配列のサイズを判定する際の MATLAB との非互換性を参照してください。

配列の要素を削除した結果として生じる空配列のサイズ

配列のすべての要素を削除することで、空の配列が生成されます。この空の配列のサイズは、生成コードと MATLAB ソース コードでは異なる場合があります。

ケースコード例MATLAB での空配列のサイズ生成コードでの空配列のサイズ
colon 演算子 (:) を使用して m 行 n 列の配列のすべての要素を削除する。
coder.varsize('X',[4,4],[1,1]);
X = zeros(2);
X(:) = [];
0-by-01-by-0
colon 演算子 (:) を使用して行ベクトルのすべての要素を削除する。
coder.varsize('X',[1,4],[0,1]);
X = zeros(1,4);
X(:) = [];
0-by-01-by-0
colon 演算子 (:) を使用して列ベクトルのすべての要素を削除する。
coder.varsize('X',[4,1],[1,0]);
X = zeros(4,1);
X(:) = [];
0-by-00-by-1
一度に 1 つずつ要素を削除して列ベクトルのすべての要素を削除する。
coder.varsize('X',[4,1],[1,0]);
X = zeros(4,1);
for i = 1:4
    X(1)= [];
end
1-by-00-by-1

実行時にスカラーとして初期化される可変サイズの列 cell 配列の拡張

MATLAB の実行で、{end+1} のインデックス付けを使用してスカラー cell 配列を拡張すると、cell 配列は 2 番目の次元に沿って拡張され、行 cell 配列が生成されます。たとえば、以下のような関数 growCell を定義します。

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

次のサンプル入力を使用して growCell を呼び出します。

growCell({2}, 3)
ans =

  1×4 cell array

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

一方、コード生成では、以下を仮定します。

  • コンパイル時に cell 配列を可変サイズの列タイプ (:Inf x 1 など) に指定し、"さらに"

  • 実行時にこの cell 配列をスカラーとして初期化する。

このような場合、生成されたコードでは、スカラー cell 配列は最初の次元に沿って拡張され、列 cell 配列が生成されます。たとえば、growCell の MEX コードを生成します。入力 n を基となる型が double の :Inf x 1 の cell 配列に指定します。入力 m を double のスカラー型に指定します。

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

前と同じ入力を使用して、生成された MEX を実行します。

growCell_mex({2}, 3)
ans =

  4×1 cell array

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

single 型と double 型のオペランドをもつ要素単位の二項演算

MATLAB コードに single 型と double 型のオペランドをもつ要素単位の二項演算が含まれる場合、生成コードの結果が MATLAB の結果と同じにならないことがあります。

このような演算について、MATLAB では、両オペランドを double 型にキャストし、double 型で演算を実行します。MATLAB は実行結果を single 型にキャストし、その結果を返します。

生成コードでは、double 型のオペランドを single 型にキャストします。そして 2 つの single 型で演算を実行し、その結果を返します。

たとえば、要素単位の二項演算 plus を呼び出す MATLAB 関数 foo を定義します。

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

single 型の変数 s1 と、double 型の変数 v1 を定義します。single 型の入力と double 型の入力を受け入れる foo の MEX 関数を生成します。

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

入力 s1 および d1 を指定して、foofoo_mex の両方を呼び出します。2 つの結果を比較します。

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

  logical

   0

比較の出力は logical 0 になります。これは、これらの入力について、生成コードと MATLAB で異なる結果を生成することを示しています。

浮動小数点の数値結果

生成されたコードは、以下の場合の MATLAB における浮動小数点の数値結果とは、異なる可能性があります。

 コンピューター ハードウェアが拡張精度レジスタを使用する

 特定の高度なライブラリ機能

 BLAS ライブラリ関数の実装

NaN と無限大

生成されたコードでは、NaN および Inf の値が数学的に無意味の場合、値のパターンが MATLAB コードと異なる場合があります。たとえば、MATLAB 出力に NaN が含まれる場合、生成されたコードの出力にも NaN が含まれますが、必ずしも同じ場所に含まれるとは限りません。

NaN のビット パターンが MATLAB コードの出力と生成されたコードで異なる場合があります。それは、コードの生成に使用される C99 言語標準が、すべての実装で NaN に一意のビット パターンを指定しないからです。MATLAB 出力と SIL 出力または PIL 出力など異なる実装でビット パターンを比較しないでください。

負のゼロ

浮動小数点型の場合、値 0 は正の記号または負の記号のいずれかをもちます。算術的に、0-0 と等価ですが、一部の演算では 0 入力の符号が区別されます。たとえば、rdivideatan2atan2dangle がこれに該当します。0 で除算すると Inf が生成されますが、-0 で除算すると -Inf が生成されます。同様に、atan2d(0,-1) では 180 が生成されますが、atan2d (-0,-1) では -180 が生成されます。

浮動小数点変数が適切な範囲の整数値のみを取得することが、コード ジェネレーターによって検出される場合、コード ジェネレーターでは生成されたコード内の変数に整数型を使用できます。コード ジェネレーターで変数に整数型が使用されると、その変数は -0+0 として保存します。これは、整数型には値 0 の記号が保存されないためです。生成されたコードで変数が浮動小数点型にキャストし直されると、0 の記号は正になります。0 で除算すると -Inf ではなく Inf が生成されます。同様に、atan2d(0,-1) では -180 ではなく、180 が生成されます。

生成されたコードで -0 が MATLAB とは異なる方法で扱われる他のコンテキストがあります。たとえば、MATLAB コードで、z = min(x,y) を使用して 2 つの double 型のスカラー xy の最小値を計算するとします。生成された C コードの対応する行は z = fmin(x,y) となる可能性があります。関数 fmin は、C コンパイラのランタイム数学ライブラリで定義されています。比較演算子 0.0 == -0.0true を C/C++ で返すため、fmin のコンパイラの実装では fmin(0.0,-0.0) に対して 0.0 または -0.0 のいずれかが返される可能性があります。

コード生成ターゲット

関数 coder.target は、生成されたコードと MATLAB で異なる値を返します。これは、関数が MATLAB で実行されているのか、シミュレーションあるいはコード生成ターゲット用にコンパイルされたのかを判断できるようにするためです。coder.target を参照してください。

MATLAB クラス プロパティの初期化

MATLAB では、クラスの読み込み時にクラスの既定値を計算してからコード生成を行います。コード ジェネレーターでは、MATLAB で計算される値が使用されます。既定値は再計算されません。プロパティ定義で関数呼び出しを使って初期値を計算する場合、コード ジェネレーターはこの関数を実行しません。関数にグローバル変数や永続変数の変更といった副作用がある場合、生成されたコードから得られる結果が MATLAB の結果とは異なる可能性があります。詳細については、コード生成のためのクラス プロパティの定義を参照してください。

set メソッドをもつ入れ子のプロパティ割り当てにおける MATLAB クラス

ハンドル オブジェクトのプロパティに値を割り当てるときに、そのプロパティ自体が別のオブジェクトのプロパティでもある場合、生成されたコードは、MATLAB が呼び出さないハンドル クラスの set メソッドを呼び出すことができます。

たとえば、x がハンドル オブジェクト、pa がオブジェクト、pb がハンドル オブジェクト、pcpb のプロパティになるように、一連の変数を定義すると仮定します。以下のように、入れ子にされたプロパティの割り当てを行います。

x.pa.pb.pc = 0;

この場合、生成されたコードはオブジェクト pb の set メソッドと x の set メソッドを呼び出します。MATLAB は pb の set メソッドのみを呼び出します。

MATLAB ハンドル クラスのデストラクター

生成されたコードでのハンドル クラスのデストラクターの動作は、次の状況では MATLAB での動作とは異なる場合があります。

  • 複数の独立したオブジェクトを破棄する順序は、生成されたコードと MATLAB では異なる場合があります。

  • 生成されたコードでのオブジェクトの存続期間は、MATLAB での存続期間と異なる可能性があります。

  • 生成されたコードは、部分的に作成されたオブジェクトを破棄しません。ハンドル オブジェクトが実行時に完全に作成されていない場合、生成されたコードはエラー メッセージを作成しますが、そのオブジェクトの delete メソッドは呼び出しません。System object™ について、setupImpl で実行時エラーがある場合、生成されたコードは、そのオブジェクトの releaseImpl は呼び出しません。

    MATLAB は、delete メソッドを呼び出して、部分的に作成されたオブジェクトを破棄します。

詳細については、ハンドル クラス デストラクターのコード生成を参照してください。

可変サイズ データ

コード生成時の可変サイズのサポートに関する MATLAB との非互換性を参照してください。

複素数

複素数データのコード生成を参照してください。

連続する単項演算子をもつ string の double への変換

複数の連続する単項演算子を含む string を double に変換すると、MATLAB と生成されたコードで結果が異なる場合があります。次の関数を考えてみます。

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

入力値 "--" の場合、関数によって string "--1"double に変換されます。MATLAB では、回答が NaN になります。生成されたコードの回答は 1 です。

関数 display

MATLAB コード内のステートメントや式でセミコロンを省略すると、関数 display が暗黙的に呼び出されます。また、次に示すように display を明示的に呼び出すこともできます。

display(2+3);
     5

関数 display を呼び出す MATLAB コードに対して生成された MEX コードは、この関数の呼び出しを保持して出力を表示します。MATLAB Runtime にアクセスできないターゲットに対して生成されたスタンドアロン コードでは、display の暗黙的な呼び出しと明示的な呼び出しは削除されます。これには、display のオーバーライドされたクラス メソッドの呼び出しが含まれます。

その他のターゲットに対して生成されたコードでテキストを表示するには、MATLAB クラスで関数 disp をオーバーライドします。次に例を示します。

%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

エントリポイント関数に対して生成されたコードは次のとおりです。

/* 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);
}

関数ハンドルの相違点

MATLAB で関数ハンドルを介して display を呼び出すと、変数の名前も出力されます。たとえば、MATLAB で次の関数を実行すると、出力は以下のようになります。

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

    10

ただし、このスニペットに対して生成されたコードは、値 10 のみを出力します。