コード生成における cell 配列の制限事項
コード生成用の MATLAB® コードで cell 配列を使用するときは、以下の制限に従わなければなりません。
cell 配列要素の代入
cell 配列要素は、使用する前にすべての実行パスに代入しなければなりません。以下に例を示します。
function z = foo(n) %#codegen c = cell(1,3); if n < 1 c{2} = 1; else c{2} = n; end z = c{2}; end
コード ジェネレーターでは、cell 配列を関数に渡したり関数から返したりすることを、cell 配列のすべての要素の使用とみなします。したがって、cell 配列を関数に渡すか関数から返す前に、そのすべての要素を代入しなければなりません。たとえば、次のコードは値を c{2}
に代入せず、c
は関数出力であるため、許可されません。
function c = foo() %#codegen c = cell(1,3); c{1} = 1; c{3} = 3; end
要素への値の代入はすべての実行パスで一貫していなければなりません。y{2}
はある実行パスでは double、別の実行パスでは char であるため、次のコードは許可されません。
function y = foo(n) y = cell(1,3) if n > 1; y{1} = 1 y{2} = 2; y{3} = 3; else y{1} = 10; y{2} = 'a'; y{3} = 30; end
可変サイズの cell 配列
coder.varsize
は異種混合 cell 配列でサポートされません。関数
cell
を使用して固定サイズの cell 配列を定義する場合、coder.varsize
を使用して、cell 配列が可変サイズであることを指定することはできません。たとえば、以下のコードでは、x = cell(1,3)
によりx
が固定サイズの 1 行 3 列の cell 配列になるため、コード生成エラーが発生します。... x = cell(1,3); coder.varsize('x',[1 5]) ...
中かっこを使用して定義した cell 配列と共に
coder.varsize
を使用できます。以下に例を示します。... x = {1 2 3}; coder.varsize('x',[1 5]) ...
関数
cell
を使用して可変サイズの cell 配列を作成するには、以下のコード パターンを使用します。function mycell(n) %#codegen x = cell(1,n); for i = 1:n x{i} = i; end end
cell を使用した可変サイズの cell 配列の定義を参照してください。
cell 配列の上限を指定するには、
coder.varsize
を使用します。function mycell(n) %#codegen x = cell(1,n); for i = 1:n x{i} = i; coder.varsize('x',[1,20]); end end
cell
を使用した可変サイズの cell 配列の定義
コード生成では、cell 配列要素を使用する前に、値を cell 配列要素に代入しなければなりません。cell
を使用して可変サイズの cell 配列 (cell(1,n)
など) を作成すると、MATLAB は空の行列を各要素に代入します。ただし、コード生成でそれらの要素は代入されません。コード生成では、cell
を使用して可変サイズの cell 配列を作成した後、cell 配列を使用する前に cell 配列のすべての要素を代入しなければなりません。以下に例を示します。
function z = mycell(n, j) %#codegen x = cell(1,n); for i = 1:n x{i} = i; end z = x{j}; end
コード ジェネレーターはコードを解析し、cell 配列を最初に使用する前にすべての要素が代入されているかどうかを判別します。コード ジェネレーターが一部の要素が代入されていないことを検出した場合、コード生成はエラー メッセージを表示して失敗します。たとえば、for
ループの上限を j
に変更します。
function z = mycell(n, j) %#codegen x = cell(1,n); for i = 1:j %<- Modified here x{i} = i; end z = x{j}; end
この変更と n
未満の入力 j
によって、この関数では値がすべての cell 配列要素に代入されません。コード生成で次のエラーが発生します。
この行の前に 'x{:}' の各要素が代入されることを 判別できません。
cell 配列のすべての要素がコードで代入されている場合でも、解析ではすべての要素が代入されたことが検出されないため、コード ジェネレーターはこのメッセージを報告します。cell 配列のすべての要素が代入されるか判別できないを参照してください。
このエラーを回避するには、次のガイドラインに従います。
cell
を使用して可変サイズの cell 配列を定義する場合、次のパターンに従ってコードを記述します。function z = mycell(n, j) %#codegen x = cell(1,n); for i = 1:n x{i} = i; end z = x{j}; end
多次元 cell 配列のパターンは次のとおりです。
function z = mycell(m,n,p) %#codegen x = cell(m,n,p); for i = 1:m for j =1:n for k = 1:p x{i,j,k} = i+j+k; end end end z = x{m,n,p}; end
ループ カウンターを
1
ずつインクリメントまたはデクリメントします。1 つのループ内または 1 セットの入れ子ループで cell 配列を定義します。たとえば、次のコードは許可されません。
function z = mycell(n, j) x = cell(1,n); for i = 1:5 x{i} = 5; end for i = 6:n x{i} = 5; end z = x{j}; end
セルの次元およびループの初期値と終了値に同じ変数を使用します。たとえば、セルの作成で
n
を使用し、ループの終了値でm
を使用するため、次のコードのコード生成は失敗します。function z = mycell(n, j) x = cell(1,n); m = n; for i = 1:m x{i} = 2; end z = x{j}; end
セルの作成とループの終了値で
n
を使用するようにコードを書き換えます。function z = mycell(n, j) x = cell(1,n); for i = 1:n x{i} = 2; end z = x{j}; end
次のパターンで cell 配列を作成します。
x = cell(1,n)
必要な cell で一時変数を初期化して、cell 配列を構造体のフィールドまたはオブジェクトのプロパティに代入します。次に例を示します。
cell 配列を構造体のフィールドまたはオブジェクトのプロパティに直接代入しないでください。たとえば、次のコードは許可されません。t = cell(1,n) for i = 1:n t{i} = i+1; end myObj.prop = t;
myObj.prop = cell(1,n); for i = 1:n myObj.prop{i} = i+1; end
関数
cell
を cell 配列コンストラクター{}
内で使用しないでください。たとえば、次のコードは許可されません。x = {cell(1,n)};
cell 配列の作成と、cell 配列要素に値を代入するループは一意の実行パスで一緒にしなければなりません。たとえば、次のコードは許可されません。
function z = mycell(n) if n > 3 c = cell(1,n); else c = cell(n,1); end for i = 1:n c{i} = i; end z = c{n}; end
このコードを修正するには、cell 配列を作成するコード ブロックに代入のループを移動します。
function z = cellerr(n) if n > 3 c = cell( 1,n); for i = 1:n c{i} = i; end else c = cell(n,1); for i = 1:n c{i} = i; end end z = c{n}; end
cell 配列のインデックス付け
小かっこ
()
を使用して cell 配列にインデックスを付けることはできません。中かっこ{}
を使用して cell 配列にインデックスを付け、セルの内容にアクセスすることを検討してください。定数のインデックスまたは定数境界をもつ
for
ループを使用して、異種混合 cell 配列にインデックスを付けなければなりません。たとえば、次のコードは許可されません。
x = {1, 'mytext'}; disp(x{randi});
コード ジェネレーターによってループが展開されるため、定数境界をもつ
for
ループで異種混合 cell 配列にインデックスを付けることができます。展開することによりループの反復ごとにループ本体のコピーが個別に作成されるため、ループ反復の定数にインデックスが作成されます。ただし、for
ループ本体が大きい場合や、反復数が多い場合、展開によってコンパイル時間が増加し、非効率的なコードが生成される可能性があります。A
とB
が定数の場合、次のコードは、定数境界をもつfor
ループで異種混合 cell 配列にインデックスを付ける方法を示します。x = {1, 'mytext'}; for i = A:B disp(x{i}); end
{end + 1} を使用した cell 配列の拡張
cell 配列 X
を拡張するには、X{end + 1}
を使用できます。次に例を示します。
... X = {1 2}; X{end + 1} = 'a'; ...
{end + 1}
を使用して cell 配列を拡張する場合は、次の制限事項を考慮します。
{end + 1}
のみ使用します。{end + 2}
や{end + 3}
などは使用しません。{end + 1}
はベクトルでのみ使用します。たとえば、次のコードはX
が行列であり、ベクトルではないため許可されません。... X = {1 2; 3 4}; X{end + 1} = 5; ...
{end + 1}
を変数でのみ使用します。以下のコードでは、{end + 1}
は{1 2 3}
を拡張しません。この場合、コード ジェネレーターは{end + 1}
をX{2}
への範囲外のインデックスとして扱います。... X = {'a' { 1 2 3 }}; X{2}{end + 1} = 4; ...
{end + 1}
でループ内の cell 配列を拡張する場合、cell 配列は可変サイズでなければなりません。したがって、cell 配列は同種でなければなりません。このコードは
X
が同種であるため許可されます。... X = {1 2}; for i=1:n X{end + 1} = 3; end ...
このコードは
X
が異種混合であるため許可されません。... X = {1 'a' 2 'b'}; for i=1:n X{end + 1} = 3; end ...
cell 配列の内容
cell 配列に mxarrays
を含めることはできません。cell 配列では、外部関数から返される値は格納できません。
外部 C/C++ 関数への cell 配列の受け渡し
cell 配列を coder.ceval
に渡すことはできません。変数が coder.ceval
への入力引数の場合、cell 配列としてではなく配列または構造体として変数を定義します。