Main Content

可変サイズ データ エラーの診断と修正

サイズ不一致エラーの診断と修正

問題: 可変サイズ行列を固定サイズ行列に代入している

生成コードでは、可変サイズの行列を固定サイズの行列に代入することができません。以下の例を考えてみます。

function Y = example_mismatch1(n) %#codegen
assert(n < 10);
B = ones(n,n);
A = magic(3);
A(1) = mean(A(:));
if (n == 3)
    A = B;
end
Y = A;

この関数をコンパイルすると次のエラーが発生します。

??? Dimension 1 is fixed on the left-hand side 
but varies on the right ...

このエラーを回避するにはいくつかの方法があります。

  • coder.varsize コンストラクトを追加することにより、行列 A の拡大を許可します。

    function Y = example_mismatch1_fix1(n) %#codegen
    coder.varsize('A');
    assert(n < 10);
    B = ones(n,n);
    A = magic(3);
    A(1) = mean(A(:));
    if (n == 3)
        A = B;
    end
    Y = A;

  • assert ステートメントを変更することで、行列 B のサイズを明示的に 3 行 3 列に制限します。

    function Y = example_mismatch1_fix2(n) %#codegen
    coder.varsize('A');
    assert(n == 3)
    B = ones(n,n);
    A = magic(3);
    A(1) = mean(A(:));
    if (n == 3)
        A = B;
    end
    Y = A;
  • 明示的なインデックスを使い、B のサイズを A と同じにします。

    function Y = example_mismatch1_fix3(n) %#codegen
    assert(n < 10);
    B = ones(n,n);
    A = magic(3);
    A(1) = mean(A(:));
    if (n == 3)
        A = B(1:3, 1:3);
    end
    Y = A;

問題: 可変サイズ指定に合わせて空行列が形状変更されている

空行列 [] を可変サイズのデータに代入すると、MATLAB®coder.varsize の指定に合わせて生成コードの中でデータを暗黙的に形状変更する場合があります。例:

function Y = test(u) %#codegen
Y = [];
coder.varsize('Y', [1 10]);
if u < 0
    Y = [Y u];
end

この例では、coder.varsizeY を最大 10 個の要素をもつ列ベクトルとして定義しているため、第 1 次元はサイズが 1 で固定されています。ステートメント Y = [] は、Y の最初の次元を 0 として指定し、不一致が起こります。この代入は、右辺は空行列で、左辺が可変サイズのベクトルになっています。この場合、MATLAB は、生成されたコードで空行列 Y = []Y = zeros(1,0) に形状変更し、coder.varsize の指定に一致させます。

問題: 暗黙的に拡張される出力を固定サイズの変数に代入している

暗黙的に拡張される二項演算または二項関数の出力を異なるサイズの変数に代入すると、コード ジェネレーターでエラーが発生することがあります。次に例を示します。

function out = test(n) %#codegen
x = ones(n,1);
if mod(n,2) == 1
	y = ones(n,n);
	x = y + x;
end 
out = out + x(2);
end

この例では、x は非有界のベクトルです。暗黙的な拡張により、xy の加算演算の結果は非有界の行列 (Inf 行 Inf 列) になります。非有界の行列を非有界のベクトルである x に代入するとエラーが発生します。

暗黙的に拡張される出力を使用する場合は、出力と同じサイズの新しい変数に出力を代入します。

生成コードで x のサイズを維持し、暗黙的な拡張を適用しない場合は、coder.sameSizeBinaryOp (MATLAB Coder) を使用して演算を適用します。関数本体で coder.noImplicitExpansionInFunction (MATLAB Coder) を呼び出すことで、その関数に対して生成されるコードで暗黙的な拡張を無効にすることもできます。

暗黙的な拡張では、互換性のあるサイズの配列で二項演算を適用するためにオペランドが自動的に拡張されます。暗黙的な拡張を有効にしたコードの生成 (MATLAB Coder)生成コードでの暗黙的な拡張の最適化 (MATLAB Coder)、および基本的な演算で互換性のある配列サイズを参照してください。

上限検出のエラー診断と修正

問題: 行列コンストラクターにおける不定次元の使用

変数を不定次元の行列に代入して、可変サイズのデータを定義できます。次に例を示します。

function y = dims_vary(u) %#codegen
if (u > 0)
    y = ones(3,u);
else
    y = zeros(3,1);
end

ただし、この関数をコンパイルすると、u の上限が指定されていないため、エラーが生成されます。

この問題の修正には、いくつかの方法があります。

  • 動的メモリ割り当てを有効にし、再コンパイルします。可変サイズ データの動的メモリ割り当てを使用する場合は、コードの生成時に、MATLAB は上限をチェックしません。

  • 動的メモリ割り当てを使用しない場合は、u を最初に使用する前に、assert ステートメントを追加します。

    function y = dims_vary_fix(u) %#codegen
    assert (u < 20);
    if (u > 0)
        y = ones(3,u);
    else
        y = zeros(3,1);
    end