Main Content

コード ジェネレーターで実行時の再帰を強制的に使用させる

MATLAB® コードに再帰的関数呼び出しが含まれる場合、コード ジェネレーターはコンパイル時または実行時の再帰を使用します。コンパイル時の再帰では、コード ジェネレーターによって生成されたコードに複数のバージョンの再帰関数が作成されます。これらのバージョンは、関数の特殊化として知られています。実行時の再帰では、コード ジェネレーターによって再帰関数が生成されます。コンパイル時の再帰によって作成される関数の特殊化が多すぎる場合や、実行時の再帰を使用する場合は、コード ジェネレーターに対して実行時の再帰の強制を試みることができます。次のいずれかの方法を試みます。

再帰関数への入力を非定数として処理

次の関数を考えてみます。

function y = call_recfcn(n)
A = ones(1,n);
x = 5;
y = recfcn(A,x);
end

function y = recfcn(A,x)
if size(A,2) == 1 || x == 1
    y = A(1);
else
    y = A(1)+recfcn(A(2:end),x-1);
end
end

call_recfcn は、2 番目の引数の値を 5 として recfcn を呼び出します。recfcn は、x が 1 になるまで自身を再帰的に呼び出します。recfcn の呼び出しでは、入力引数 x の値はそれぞれ異なります。コード ジェネレーターは recfcn の特殊化を 5 つ生成します (それぞれが各呼び出しに対応)。コードを生成した後に、コード生成レポートで特殊化を確認できます。

This image shows the specializations for recfcn in the report. The report shows the five specializations associated with the function.

call_recfcn つまり recfcn の呼び出しにおいて実行時の再帰を強制的に行うには、coder.ignoreConst を使用して入力引数 x の値を非定数値として扱うようにコード ジェネレーターに指示します。

function y = call_recfcn(n)
A = ones(1,n);
x = coder.ignoreConst(5);
y = recfcn(A,x);
end

function y = recfcn(A,x)
if size(A,2) == 1 || x == 1
    y = A(1);
else
    y = A(1)+recfcn(A(2:end),x-1);
end
end

コードを生成した後、コード生成レポートに、1 つの特殊化のみ表示されます。

This image shows recfcn after the input argument x is treated as a nonconstant value with coder.ignoreConst. The function specializations do not appear in the report anymore.

再帰関数への入力を可変サイズにする

たとえば、以下のコードについて考えます。

function z = call_mysum(A)
%#codegen
z = mysum(A);
end

function y = mysum(A)
coder.inline('never');
if size(A,2) == 1
    y = A(1);
else
    y = A(1)+ mysum(A(2:end));
end
end

mysum への入力が固定サイズの場合、コード ジェネレーターはコンパイル時の再帰を使用します。コード ジェネレーターに強制的に実行時の変換を使用させるには、coder.varsize を使用して mysum への入力を可変サイズにします。

function z = call_mysum(A)
%#codegen
B = A;
coder.varsize('B');
z = mysum(B);
end

function y = mysum(A)
coder.inline('never');
if size(A,2) == 1
    y = A(1);
else
    y = A(1)+ mysum(A(2:end));
end
end

再帰呼び出しの前に出力変数を代入する

コード ジェネレーターは次のコードでコンパイル時の再帰を使用します。

function y = callrecursive(n)
x = 10;
y = myrecursive(x,n);
end

function y = myrecursive(x,n)
coder.inline('never')
if x > 1
    y = n + myrecursive(x-1,n-1);    
else
    y = n;
end
end

コード ジェネレーターに強制的に実行時の再帰を使用させるには、再帰呼び出しの前に出力 y が代入されるように、myrecursive を修正します。代入 y = nif ブロックに配置し、再帰呼び出しを else ブロックに配置します。

function y = callrecursive(n)
x = 10;
y = myrecursive(x,n);
end

function y = myrecursive(x,n)
coder.inline('never')
if x == 1
    y = n;  
else
    y = n + myrecursive(x-1,n-1);
end
end

参考

関連するトピック