コード生成における cell 配列の制限事項
コード生成用の MATLAB® コードで cell 配列を使用するときは、以下の制限に従わなければなりません。
一貫性のある要素型の代入
cell 配列の要素に代入する値の型は、すべての実行パスで同じでなければなりません。たとえば、関数 inconsistentTypeError
について考えます。ca{2}
がある実行パスでは double
、別の実行パスでは char
であるため、次の関数のコード生成は失敗します。
function out = inconsistentTypeError(n) %#codegen ca = cell(1,3); if n > 1 ca{1} = 1; ca{2} = 2; ca{3} = 3; else ca{1} = 10; ca{2} = 'a'; ca{3} = 30; end out = ca{1}; end
可変サイズの cell 配列は同種でなければならない
cell 配列を含む MATLAB 関数のコードを生成すると、コード ジェネレーターは各 cell 配列を "同種" または "異種混合" として分類します。一般に、コード ジェネレーターは同じ型の要素を含む cell 配列を同種として、異なる型の要素を含む cell 配列を異種混合として分類します。コード ジェネレーターが同種および異種混合の cell 配列を処理する方法の詳細については、cell 配列のコード生成を参照してください。
coder.varsize
(MATLAB Coder) を使用して同種の cell 配列を可変サイズとして定義し、可変サイズの cell 配列の上限を設定できます。たとえば、次のコードは caX
と caY
を固定サイズ 1x3
の cell 配列から、2 番目の次元が最大でサイズ 5 (1x:5
) まで変化できる可変サイズの cell 配列に変更します。
... caX = {1 2 3}; caY = cell(1,3); coder.varsize('caX',[1 5]) coder.varsize('caY',[1 5]) ...
すべての cell 配列要素への値の代入
cell 配列を使用する前に、すべての実行パスですべての cell 配列要素に値を代入しなければなりません。関数 cell
を使用して可変サイズの cell 配列を作成する場合、生成されるコードでは cell 配列の要素のサイズと型は未定義になります。そのため、コード生成用の MATLAB コードでは、関数 cell
を使用して作成した可変サイズのすべての cell 配列の全要素に必ず初期値を代入しなければなりません。たとえば、関数 incompleteAssignmentError
について考えます。この関数のコード生成は失敗します。これは、関数が返す要素 ca{2}
が、n
が 5
未満の実行パス上で未定義であるとコード ジェネレーターによって検出されるためです。
function out = incompleteAssignmentError(n) %#codegen ca = cell(1,2); if n < 5 ca{1} = 0; else ca{2} = 3; end out = ca{2}; end
MATLAB コードで cell 配列のすべての要素に値が代入されていても、cell 配列のすべての要素が代入されていることをコード ジェネレーターが認識できないため、コード生成が失敗することがあります。一般に、cellArrayPatternExample
で示されているコーディング パターンを使用して、cell
によって作成した可変サイズの cell 配列の要素に値を代入します。
function out = cellArrayPatternExample(n) %#codegen ca = cell(1,n); for i = 1:n ca{i} = i; end out = ca{n}; end
すべての cell 配列要素を確実に定義するために使用できるその他のパターンについては、問題の解決: cell 配列の要素は使用前に完全に定義する必要があるを参照してください。
関数 cell
と同じ実行パスでの初期値の代入
関数 cell
を使用して cell 配列を作成する場合、cell 配列を作成する関数 cell
と同じ一意の実行パスで cell 配列要素に初期値を代入するループを含めなければなりません。たとえば、関数 cellLoopError
のコード生成は失敗します。これは、cell 配列 ca
の要素に初期値を代入する for
ループが、cell 配列を作成する関数 cell
と共に一意の実行パス上にないためです。
function out = cellLoopError(n) %#codegen if n < 5 ca = cell(1,n); else ca = cell(n,1); end for i = 1:n ca{i} = i; end out = ca; end
この問題を解決するには、各 cell 配列を作成する関数 cell
を含むコード ブロック内で cell 配列要素に初期値を代入します。
function out = cellLoopExample(n) %#codegen if n < 5 ca = cell(1,n); for i = 1:n ca{i} = 0; end else ca = cell(n,1); for i = 1:n ca{i} = 0; end end for i = 1:n ca{i} = i; end out = ca{n}; end
オブジェクト プロパティまたは構造体フィールドで可変サイズの cell 配列に初期値を代入するには、一時変数を使用する
関数 cell
を使用して可変サイズの cell 配列を作成する場合、オブジェクト プロパティまたは構造体フィールドで使用する前に、cell 配列のすべての要素に初期値を代入しなければなりません。たとえば、関数 fieldAssignmentError
のコード生成は失敗します。これは、構造体フィールドの cell 配列要素に直接初期値を代入しているためです。
function out = fieldAssignmentError(n) %#codegen s.field = cell(1,n); for i = 1:n s.field{i} = i+1; end out = s.field{n}; end
function out = fieldAssignmentExample(n) %#codegen ca = cell(1,n); for i = 1:n ca{i} = 0; end s.field = ca; for i = 1:n s.field{i} = i+1; end out = s.field{n}; end
異種混合配列にインデックスを付けるには、定数のインデックスまたは定数境界をもつ for
ループを使用する
cell 配列を含む MATLAB 関数のコードを生成すると、コード ジェネレーターは各 cell 配列を "同種" または "異種混合" として分類します。一般に、コード ジェネレーターは同じ型の要素を含む cell 配列を同種として、異なる型の要素を含む cell 配列を異種混合として分類します。コード ジェネレーターが同種および異種混合の cell 配列を処理する方法の詳細については、cell 配列のコード生成を参照してください。
定数のインデックスまたは定数境界をもつ for
ループを使用して、異種混合 cell 配列にインデックスを付けなければなりません。たとえば、インデックスが定数ではないため、関数 cellIndexingError
のコード生成は失敗します。
function cellIndexingError(n) %#codegen ca = {1 "a" 2 5:7 3 "c"}; disp(ca{n}); end
コード ジェネレーターはループを展開するため、つまりループの反復ごとにループ本体の個別のコピーを作成するため、定数境界をもつ for
ループを使用して異種混合 cell 配列にインデックスを付けることができます。
function cellIndexingExample(n) %#codegen ca = {1 "a" 2 5:7 3 "c"}; for i = 1:6 if i == n disp(ca{i}); end end end
メモ
for
ループ本体が大きい場合や、反復数が多い場合、展開によってコンパイル時間が増加し、非効率的なコードが生成される可能性があります。
{end + 1} を使用して cell 配列を拡張するには、特定のコーディング パターンを使用する
コード生成は、コード生成用の MATLAB コードで {end + 1}
を使用した cell 配列の拡張をサポートしています。たとえば、{end + 1}
を使用して配列 ca
を拡張する関数 growCellArray
のコードを生成できます。
function out = growCellArrayExample(n) %#codegen ca = {1 2}; for i = 1:n ca{end+1} = 3+i; end out = ca{n}; end
コード生成用の MATLAB コードで cell 配列を拡張するために {end + 1}
を使用するときは、以下の制限に従わなければなりません。
{end + 1}
要素に値を代入することによってのみ cell 配列を拡張できます。{end + 2}
などの後続の要素への値の代入はサポートされていません。cell 配列ベクトルを拡張するには、
{end + 1}
のみ使用できます。たとえば、ca
はベクトルではなく行列であるため、関数growMatrixError
のコード生成は失敗します。function ca = growMatrixError %#codegen ca = {1 2; 3 4}; ca{1,end+1} = 5; end
{end + 1}
は変数の直後になければなりません。たとえば、growArraySubscriptError
のコード生成は失敗します。これは、{end + 1}
がca
の隣ではなくca{2}
の隣にあるためです。この問題を解決するには、変更する cell 配列の要素を一時変数に等しく設定します。その後、function out = growArraySubscriptError(x) %#codegen ca = {'a' { 1 2 3 }}; ca{2}{end+1} = x; out = ca{2}{4}; end
{end + 1}
を使用して、一時変数を拡張します。coder.varsize
を使用して、変更した cell 配列の要素のサイズを変更できるようにします。function out = growArrayExampleA(x) %#codegen ca = {'a' {1 2 3}}; coder.varsize('ca{2}') temp = ca{2}; temp{end+1} = x; ca{2} = temp; out = ca{2}{4}; end
または、
{end + 1}
の代わりに配列連結を使用して新しい要素を追加します。function out = growArrayExampleB(x) %#codegen ca = {'a' {1 2 3}}; coder.varsize('ca{2}') ca{2} = [ca{2} {x}]; out = ca{2}{4}; end
{end + 1}
を使用してループ内の cell 配列を拡張する場合、cell 配列は同種である必要があります。つまり、すべての cell 配列要素は同じ型でなければなりません。たとえば、関数growHeterogeneousError
のコード生成は失敗します。これは、cell 配列ca
にstring
型とdouble
型の要素が含まれているためです。コード ジェネレーターが同種および異種混合の cell 配列を処理する方法の詳細については、cell 配列のコード生成を参照してください。function out = growHeterogeneousError(n) %#codegen ca = {1 2 "a"}; for i = 1:n ca{end+1} = 3+i; end out = ca; end
cell 配列を直接反復処理するには、cell 配列の最初の次元が 1
でなければならない
MATLAB では、任意の次元数の cell 配列を直接反復処理することができます。たとえば、3 行 4 列の cell 配列を反復処理し、各列の内容を表示する関数 directIterationError
ついて考えます。配列 ca
の最初の次元が 1
ではないため、この関数のコード生成は失敗します。
function directIterationError ca = {1 2 3 4; "five" "six" "seven" "eight"; 9 10 11 12}; for i = ca disp(i); end end
コード生成用の MATLAB コードで、最初の次元が 1
でない cell 配列を反復処理するには、cell 配列自体ではなく、cell 配列の各次元のサイズをループ処理します。
function iterationExample %#codegen ca = {1 2 3 4; "five" "six" "seven" "eight"; 9 10 11 12}; for i = 1:size(ca,1) for j = 1:size(ca,2) disp(ca{i,j}); end end end
cell 配列へのインデックス付けに小かっこ ()
を使用しない
コード生成用の MATLAB コードでは、小かっこ ()
を使用して cell 配列にインデックスを付けることはできません。中かっこ {}
を使用して cell の内容にアクセスします。
cell 配列コンストラクター {}
内から関数 cell
を呼び出さない
コード生成は cell 配列コンストラクター {}
内での関数 cell
の使用をサポートしていません。このため、関数 cellCellError
のコード生成は失敗します。
function out = cellCellError(n) %#codegen ca = {cell(1,n) cell(1,n)}; for i = 1:n ca{1}{i} = i+1; ca{2}{i} = i+2; end out = ca; end
他の cell 配列を含む cell 配列を作成するには、外側配列を作成する前に各内側 cell 配列のすべての要素を初期化します。その後、内側配列の要素に直接アクセスできます。
function out = cellCellExample(n) %#codegen x = cell(1,n); y = cell(1,n); for i = 1:n x{i} = 0; y{i} = 0; end ca = {x y}; for i = 1:n ca{1}{i} = i+1; ca{2}{i} = i+2; end out = ca{1}{n}+ca{2}{n}; end
cell 配列に mxArray
データを格納しない
コード生成用の MATLAB コードでは、mxArray
とも呼ばれる MATLAB 配列を cell 配列に格納することはできません。coder.extrinsic
を使用して外部関数を呼び出すと、呼び出された関数の実行時の出力は mxArray
になります。そのため、最初に外部関数の出力を既知の型に変換せずに出力を cell 配列に格納することはできません。mxArrays の利用を参照してください。
coder.ceval
を使用して外部 C/C++ 関数に cell 配列を渡さない
コード生成は、coder.ceval
(MATLAB Coder) を使用して外部 C/C++ 関数に cell 配列を渡すことをサポートしていません。cell 配列が coder.ceval
への入力引数である場合、cell 配列を通常の配列または構造体として再定義します。
参考
トピック
- cell 配列のコード生成
- 問題の解決: cell 配列の要素は使用前に完全に定義する必要がある (MATLAB Coder)
- cell 配列を可変サイズにするかの制御 (MATLAB Coder)