このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
コード生成のための可変サイズ データの定義
コード生成では、変数を演算で使用したり出力として返す前に、特定のクラス、サイズ、実数/複素数を割り当てなければなりません。一般的に、変数プロパティは最初に割り当てた後に再度割り当てることはできません。したがって、固定サイズを変数フィールドまたは構造体フィールドに割り当てた後、変数フィールドまたは構造体フィールドを拡張しようとすると、コンパイル エラーが発生する可能性があります。そのような場合、以下の方法のいずれかを使ってデータを明示的に可変サイズとして定義しなければなりません。
方法 | 参照先 |
---|---|
以下のような可変サイズ行列コンストラクターから、データを代入する: | 行列コンストラクターでの不定次元の使用 |
同一の変数に対して、その変数を使う (読み取る) 前に複数種類の固定サイズを代入する。 | 同じ変数への複数のサイズの割り当て |
(end + 1) のインデックス付けを使用して配列を拡張する。 | (end + 1) を使用した配列の拡張 |
1 つの変数のすべてのインスタンスを可変サイズとして定義する。 | coder.varsize を使用した可変サイズ データの明示的な定義 |
メモ
いずれかの変数がエイリアス タイプを使用していて可変サイズである場合、MATLAB Function ブロックではコード生成はサポートされません。この制限は入力変数または出力変数には適用されません。MATLAB Function ブロックの可変サイズ変数の定義の詳細については、MATLAB Function ブロックの変数の作成と定義および可変サイズの MATLAB Function ブロック変数の宣言を参照してください。
行列コンストラクターでの不定次元の使用
コンストラクターで不定次元を使用して可変サイズの行列を定義できます。次に例を示します。
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) を使用した配列の拡張
配列 X
を拡張する場合、値を X(end + 1)
に代入できます。この代入を MATLAB® コードで行うと、拡張する次元がコード ジェネレーターで可変サイズとして扱われます。
たとえば、次のコードの抜粋についてのコードを生成できます。
... a = [1 2 3 4 5 6]; a(end + 1) = 7; b = [1 2]; for i = 3:10 b(end + 1) = i; end ...
(end + 1)
を使用して配列を拡張する場合は、次の制限事項を考慮します。
(end + 1)
のみ使用します。(end + 2)
や(end + 3)
などは使用しません。(end + 1)
はベクトルでのみ使用します。たとえば、次のコードはX
が行列であり、ベクトルではないため許可されません。... X = [1 2; 3 4]; X(end + 1) = 5; ...
サイズが
1x0
の空の配列は(end + 1)
を使用して拡張できます。サイズが0x1
の配列の拡張はサポートされていません。サイズが0x0
の配列の拡張は、その配列を[]
を使用して作成する場合のみサポートされます。
coder.varsize を使用した可変サイズ データの明示的な定義
可変サイズ データを明示的に定義するには、関数 coder.varsize
を使用します。オプションとして、どの次元が上限とともに変化するかを指定することもできます。次に例を示します。
B
を、可変サイズの 2 次元配列で、各次元の上限が 64 であると定義します。coder.varsize('B', [64 64]);
B
を可変サイズの配列として定義します。coder.varsize('B');
最初の引数のみを指定すると、
coder.varsize
はB
のすべての次元が可変であると仮定し、上限がsize(B)
であると仮定します。
MATLAB Function ブロックの出力信号が可変サイズである場合、プロパティ インスペクターで、信号が可変サイズであると指定しなければなりません。制限も指定しなければなりません。MATLAB Function ブロック内で、対応する出力変数とともに coder.varsize
を使用する必要はありません。ただし、coder.varsize
で上限を指定する場合、それらはプロパティ インスペクターの上限に一致しなければなりません。
変化する次元の指定
関数 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
を可変サイズとして定義しています。