Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

コード生成のための可変サイズ データの定義

コード生成では、変数を演算で使用したり出力として返す前に、特定のクラス、サイズ、実数/複素数を割り当てなければなりません。一般的に、変数プロパティは最初に割り当てた後に再度割り当てることはできません。したがって、固定サイズを変数フィールドまたは構造体フィールドに割り当てた後、変数フィールドまたは構造体フィールドを拡張しようとすると、コンパイル エラーが発生する可能性があります。そのような場合、以下の方法のいずれかを使ってデータを明示的に可変サイズとして定義しなければなりません。

方法参照先

以下のような可変サイズ行列コンストラクターから、データを代入する:

行列コンストラクターでの不定次元の使用
同一の変数に対して、その変数を使う (読み取る) 前に複数種類の固定サイズを代入する。同じ変数への複数のサイズの割り当て
(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) を使用した配列の拡張

配列 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.varsizeB のすべての次元が可変であると仮定し、上限が 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 + uY から読み取りを行う) 前に、固定の 2 行 2 列の次元をもつ行列として定義しています。しかし、coder.varsizeY を可変サイズの行列として定義し、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 の次元で初期化する場合。

    たとえば、この関数では、XY が、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 を可変サイズとして定義しています。

参考

|

関連するトピック