コード生成のための可変サイズ データの定義
コード生成では、変数を演算で使用したり出力として返す前に、特定のクラス、サイズ、実数/複素数を割り当てなければなりません。一般的に、変数プロパティは最初に割り当てた後に再度割り当てることはできません。したがって、固定サイズを変数フィールドまたは構造体フィールドに割り当てた後、変数フィールドまたは構造体フィールドを拡張しようとすると、コンパイル エラーが発生する可能性があります。そのような場合、以下の方法のいずれかを使ってデータを明示的に可変サイズとして定義しなければなりません。
| 方法 | 参照先 |
|---|---|
以下のような可変サイズ行列コンストラクターから、データを代入する: | 行列コンストラクターでの不定次元の使用 |
| 同一の変数に対して、その変数を使う (読み取る) 前に複数種類の固定サイズを代入する。 | 同じ変数への複数のサイズの割り当て |
(end + 1) のインデックス付けを使用して配列を拡張する。 | (end + 1) のインデックス付けを使用した配列の拡張 |
| 1 つの変数のすべてのインスタンスを可変サイズとして定義する。 | coder.varsize を使用した可変サイズ データの明示的な定義 |
行列コンストラクターでの不定次元の使用
コンストラクターで不定次元を使用して可変サイズの行列を定義できます。以下に例を示します。
function s = var_by_assign(u) %#codegen y = ones(3,u); s = numel(y);
動的メモリ割り当てを使用しない場合は、assert ステートメントも追加して、次元の上限を指定しなければなりません。以下に例を示します。
function s = var_by_assign(u) %#codegen assert (u < 20); y = ones(3,u); s = numel(y);
同じ変数への複数のサイズの割り当て
コード内の変数を使用する (読み取る) 前に、複数の固定サイズを割り当てると可変サイズにすることができます。コード ジェネレーターがスタックで静的な割り当てを行う際に、各次元で指定されている最大サイズから上限を推測します。ある次元に対して、すべての割り当てで同じサイズを割り当てると、コード ジェネレーターは、その次元がそのサイズで固定であると仮定します。割り当てで、異なる形状およびサイズを指定できます。
コード ジェネレーターは動的メモリ割り当てを使用する場合、上限をチェックしません。可変サイズ データは制限なしと仮定します。
異なる形状が指定された複数の定義から上限を推測する
function s = var_by_multiassign(u) %#codegen if (u > 0) y = ones(3,4,5); else y = zeros(3,1); end s = numel(y);
コード ジェネレーターは静的割り当てを使用する場合、y が次の 3 つの次元を使用する行列であると推測します。
最初の次元はサイズ 3 で固定
2 番目の次元は可変サイズで上限が 4
3 番目の次元は可変サイズで上限が 5
コード ジェネレーターは動的割り当てを使用する場合、y の次元を次のように異なる方法で解析します。
最初の次元はサイズ 3 で固定。
2 番目と 3 番目の次元は制限なし。
(end + 1) のインデックス付けを使用した配列の拡張
MATLAB® の実行では、end を使用して配列の任意の次元を拡張できます。たとえば、各次元の (end + 1) 要素に値を代入することで、2 次元行列の両方の次元を拡張できます。
A = magic(5)
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9A(end + 1,end + 1) = 1
A =
17 24 1 8 15 0
23 5 7 14 16 0
4 6 13 20 22 0
10 12 19 21 3 0
11 18 25 2 9 0
0 0 0 0 0 1
コード生成のために MATLAB コード内で end を使用して配列を拡張するには、次の制限に従う必要があります。
endは、ベクトルの拡張にのみ使用できます。たとえば、Xはベクトルではなく行列であるため、この関数のコード生成は失敗します。function X = foo X = [1 2; 3 4]; X(end + 1,:) = 5; end
(end + 1)要素に値を代入するだけでベクトルを拡張できます。(end + 2)などの後続の要素への値の代入はサポートされていません。(end + 1)を使用すると、空の 1 行 0 列の配列を拡張できます。(end + 1)を使用した 0 行 1 列の配列の拡張はサポートされていません。[]を使用して配列を作成した場合にのみ、(end + 1)を使用して 0 行 0 列の配列を拡張できます。ドット表記を使用して定義された構造体配列の
(end + 1)による拡張は、サポートされていません。たとえば、次の MATLAB 関数のコード生成は失敗します。function growStruct s.field1 = 5; s.field2 = 2; s(end + 1) = s; end
(end + 1)を使用して構造体配列を拡張するには、structコンストラクターを使用して構造体のフィールドを定義します。function growStruct s = struct("field1",5,"field2",2); s(end + 1) = s; end
(end + 1)を使用した配列の拡張の詳細については、end + 1 のインデックス付けを使用して配列と cell 配列を拡張するためのコード生成 (MATLAB Coder)を参照してください。
coder.varsize を使用した可変サイズ データの明示的な定義
可変サイズ データを明示的に定義するには、関数 coder.varsize を使用します。オプションとして、どの次元が上限とともに変化するかを指定することもできます。以下に例を示します。
Bを、可変サイズの 2 次元配列で、各次元の上限が 64 であると定義します。coder.varsize('B', [64 64]);Bを可変サイズの配列として定義します。coder.varsize('B');最初の引数のみを指定すると、
coder.varsizeはBのすべての次元が可変であると仮定し、上限がsize(B)であると仮定します。
変化する次元の指定
関数 coder.varsize を使って、変化する次元を指定することができます。たとえば、次のステートメントは、B を最初の次元が 2 で固定されていて、2 つ目の次元がサイズ 16 まで拡大できる配列として定義しています。
coder.varsize('B',[2, 16],[0 1])3 つ目の引数は、どの次元が変化するかを指定しています。この引数は、logical ベクトルまたは double ベクトルで 0 と 1 のみを含むものでなければなりません。0 つまり false に対応する次元は固定サイズです。1 つまり true に対応する次元はサイズが可変です。coder.varsize は、通常、サイズが 1 の次元を固定として処理します。大きさが 1 の次元をもつ可変サイズの行列の定義を参照してください。
固定の次元を定義した後に変数の拡大を許可する
関数 var_by_if は、行列 Y を最初に使用する (ステートメント Y = Y + u で Y から読み取りを行う) 前に、固定の 2 行 2 列の次元をもつ行列として定義しています。しかし、coder.varsize は Y を可変サイズの行列として定義し、else 節の判定ロジックに基づいてサイズが変化することを許可しています。
function Y = var_by_if(u) %#codegen if (u > 0) Y = zeros(2,2); coder.varsize('Y'); if (u < 10) Y = Y + u; end else Y = zeros(5,5); end
coder.varsize を使用しない場合、コード ジェネレーターは Y を固定サイズの 2 行 2 列の行列であると推測します。これにより、サイズの不一致エラーが発生します。
大きさが 1 の次元をもつ可変サイズの行列の定義
大きさが 1 の次元とは、size(A,dim) = 1 の次元を指します。大きさが 1 の次元は、以下の場合にサイズが固定されます。
coder.varsizeの式で次元を上限 1 で指定した場合。たとえば、この関数では、
Yは可変サイズの次元を 1 つもつベクトルのような動作をします。function Y = dim_singleton(u) %#codegen Y = [1 2]; coder.varsize('Y', [1 10]); if (u > 0) Y = [Y 3]; else Y = [Y u]; end
行列コンストラクターまたは行列関数を使って可変サイズ データを大きさが 1 の次元で初期化する場合。
たとえば、この関数では、
XとYが、2 番目の次元のみ可変サイズであるベクトルのような動作をします。function [X,Y] = dim_singleton_vects(u) %#codegen Y = ones(1,3); X = [1 4]; coder.varsize('Y','X'); if (u > 0) Y = [Y u]; else X = [X u]; end
この動作は、coder.varsize を使って大きさが 1 の次元が変化することを明示的に指定することでオーバーライドできます。以下に例を示します。
function Y = dim_singleton_vary(u) %#codegen Y = [1 2]; coder.varsize('Y', [1 10], [1 1]); if (u > 0) Y = [Y Y+u]; else Y = [Y Y*u]; end
この例では、coder.varsize の 3 つ目の引数が 1 のベクトルになっており、Y の各次元のサイズが変化することを示しています。
可変サイズ構造体フィールドの定義
構造体フィールドを可変サイズの配列として定義するには、コロン (:) をインデックス式として使います。コロン (:) は、配列のすべての要素が可変サイズであることを示します。以下に例を示します。
function y=struct_example() %#codegen d = struct('values', zeros(1,0), 'color', 0); data = repmat(d, [3 3]); coder.varsize('data(:).values'); for i = 1:numel(data) data(i).color = rand-0.5; data(i).values = 1:i; end y = 0; for i = 1:numel(data) if data(i).color > 0 y = y + sum(data(i).values); end end
式 coder.varsize('data(:).values') が、行列 data の各要素内のフィールド values を可変サイズとして定義しています。
以下にその他の例を示します。
coder.varsize('data.A(:).B')この例では、
dataは、行列Aを含むスカラー変数です。行列Aの各要素に、可変サイズのフィールドBが含まれています。coder.varsize('data(:).A(:).B')この式は、行列
dataの各要素内の行列Aの各要素内のフィールドBを可変サイズとして定義しています。