cell 配列のすべての要素が代入されるか判別できない
問題
次のいずれかのメッセージが表示されます。
この行の前に 'y' の各要素が代入されることを 判別できません。
関数の終了前に 'y' の各要素が代入されることを 判別できません。
再帰呼び出し関数の終了前に 'y' の各要素が代入 されることを判別できません。
原因
コード生成では、cell 配列要素を使用する前に、値を cell 配列要素に代入しなければなりません。cell
を使用して可変サイズの cell 配列 (cell(1,n)
など) を作成すると、MATLAB® は空の行列を各要素に代入します。ただし、コード生成でそれらの要素は代入されません。コード生成では、cell
を使用して可変サイズの cell 配列を作成した後、cell 配列を使用する前に cell 配列のすべての要素を代入しなければなりません。
コード ジェネレーターはコードを解析し、cell 配列を最初に使用する前にすべての要素が代入されているかどうかを判別します。コード ジェネレーターは、コードが次のパターンに従っている場合、すべての要素が代入されていることを検出します。
function z = CellVarSize1D(n, j) %#codegen x = cell(1,n); for i = 1:n x{i} = i; end z = x{j}; end
多次元 cell 配列のパターンは次のとおりです。
function z = CellAssign3D(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
コード ジェネレーターが一部の要素が代入されていないことを検出した場合、コード生成は失敗します。コードで cell 配列のすべての要素が代入されていても、解析ですべての要素が代入されていることが検出されないためにコード生成が失敗することがあります。
以下に、コード ジェネレーターで要素が代入されていることが検出できない例を示します。
要素が別のループで代入されている
... x = cell(1,n) for i = 1:5 x{i} = 5; end for i = 6:n x{i} = 7; end ...
ループ終了値を定義する変数が、セルの次元を定義する変数と同じではない。
... x = cell(1,n); m = n; for i = 1:m x{i} = 2; end ...
詳細については、cell を使用した可変サイズの cell 配列の定義を参照してください。
解決法
次のいずれかの解決法を試してください。
認識された要素代入パターンを使用する
可能な場合は、次のパターンに従ってコードを書き換えます。
... x = cell(1,n); for i = 1:n x{i} = i; end z = x{j}; ...
repmat
の使用
repmat
を使用して可変サイズの cell 配列を定義できる場合があります。
可変サイズの cell 配列を定義する以下のコードを検討してください。値 1 が奇数要素に代入され、値 2 が偶数要素に代入されます。
function z = repDefine(n, j) %#codegen c =cell(1,n); for i = 1:2:n-1 c{i} = 1; end for i = 2:2:n c{i} = 2; end z = c{j};
コード生成では次の理由からこのコードは使用できません。
複数のループで要素が代入されている。
ループ カウンターが 1 ずつインクリメントされない。
最初に cell
を使用して 1 番目の要素が 1 で、2 番目の要素が 2 の 1 行 2 列の cell 配列が作成されるようコードを書き換えます。次に、repmat
を使用して、要素値が 1 と 2 に交互に切り替わる可変サイズの cell 配列を作成します。
function z = repVarSize(n, j) %#codegen c = cell(1,2); c{1} = 1; c{2} = 2; c1= repmat(c,1,n); z = c1{j}; end
repmat
を使用して、最初は空であり可変サイズである cell 配列を関数の内部または外部に渡すことができます。次のパターンを使用します。
function x = emptyVarSizeCellArray x = repmat({'abc'},0,0); coder.varsize('x'); end
このコードは、x
が空であり、1x3
の文字の可変サイズの cell 配列であり、関数の内部または外部に渡すことが可能であると示します。
coder.nullcopy
の使用
最後の方法として、coder.nullcopy
を使用して、コード ジェネレーターがメモリを初期化せずに cell 配列にメモリを割り当てることができることを示すことができます。以下に例を示します。
function z = nulcpyCell(n, j) %#codegen c =cell(1,n); c1 = coder.nullcopy(c); for i = 1:4 c1{i} = 1; end for i = 5:n c1{i} = 2; end z = c1{j}; end
coder.nullcopy
は注意して使用してください。初期化されていないメモリにアクセスすると、予測できない結果になります。
参考
cell
| repmat
| coder.nullcopy