コード ジェネレーターで実行時の再帰を強制的に使用させる
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 つ生成します (それぞれが各呼び出しに対応)。コードを生成した後に、コード生成レポートで特殊化を確認できます。
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 つの特殊化のみ表示されます。
再帰関数への入力を可変サイズにする
たとえば、以下のコードについて考えます。
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 = n
を if
ブロックに配置し、再帰呼び出しを 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