Main Content

end + 1 のインデックス付けを使用して配列と cell 配列を拡張するためのコード生成

コード生成では、end + 1 のインデックス付けを使用した MATLAB® コード内の配列または cell 配列の拡張がサポートされます。この機能を使用するには、コード生成構成プロパティ EnableVariableSizing または MATLAB Coder™ アプリにおける対応する設定 [可変サイズを有効化] が有効になっていることを確認します。

(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 の配列の拡張は、その配列を [] を使用して作成する場合のみサポートされます。

実行時にスカラーとして初期化される可変サイズの列配列の拡張

MATLAB の実行で、(end+1) のインデックス付けを使用してスカラー配列を拡張すると、配列は 2 番目の次元に沿って拡張され、行ベクトルが生成されます。たとえば、以下のような関数 grow を定義します。

function z = grow(n, m)
n(end+1) = m;
z = n;
end

次のサンプル入力を使用して grow を呼び出します。

grow(2,3)
ans =

     2     3

一方、コード生成では、以下を仮定します。

  • コンパイル時に配列を可変サイズの列タイプ (:Inf x 1 など) に指定し、"さらに"

  • 実行時にこの配列をスカラーとして初期化する。

このような場合、生成されたコードでは、スカラーの拡張が最初の次元に沿って試行されるため、ランタイム エラーが発生します。たとえば、grow の MEX コードを生成します。入力 n:Inf x 1 の double の配列に指定します。入力 m を double のスカラーに指定します。

codegen grow -args {coder.typeof(0, [Inf 1], [1 0]), 1}
Code generation successful.

前と同じ入力を使用して、生成された MEX を実行します。

grow_mex(2,3)
Attempted to grow a scalar along the first dimension using end+1 indexing. This
behavior differs from MATLAB execution which grows a scalar along the second
dimension.

Error in grow (line 2)
n(end+1) = m;

このエラーを回避する方法.  このエラーを回避し、生成されたコードと MATLAB の実行の両方で列の次元に沿って配列を拡張するには、次の "いずれか" の方法で MATLAB コードを書き換えます。

  • (end+1) を使用する代わりに、連結演算子を使用して配列を拡張します。たとえば、関数 grow を次のように書き換えます。

    function z = growCat(n, m)
    n = [n;m];
    z = n;
    end
  • 関数内で、拡張する変数を転置して一時変数を作成します。次に、(end+1) のインデックス付けを使用してこの一時変数を拡張します。最後に、この一時変数の 2 番目の転置を取ります。たとえば、関数 grow を次のように書き換えます。

    function z = growTransposed(n, m)
    temp = n';
    temp(end+1) = m;
    z = temp';
    end

{end + 1} のインデックス付けを使用した cell 配列の拡張

cell 配列 X を拡張するには、X{end + 1} を使用できます。次に例を示します。

...
X = {1 2};
X{end + 1} = 'a';
...

{end + 1} を使用して cell 配列を拡張する場合は、次の制限事項を考慮します。

  • MATLAB Function ブロックでは、for ループで {end + 1} を使用できません。

  • {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
    ...

  • 生成されたコードと MATLAB における動作の違いの原因となるコーディング パターンについては、実行時にスカラーとして初期化される可変サイズの列 cell 配列の拡張を参照してください。