私は Oleg Kiselyov のチュートリアルReconciling Abstraction with High Performance: A MetaOCaml approach に取り組んでいます。1 つの演習 (演習 23) では、ローカル変数への配列インデックス アクセスをバインドするために、let 挿入が要求されます。問題の関数は でvmult_ca
、複素数の配列を乗算するためのコードを生成します。
let vmult_ca :
(float_complex array -> float_complex array -> float_complex array -> unit)
code =
.<fun vout v1 v2 ->
let n = Array.length vout in
(* vector representations *)
.~(let vout = OVec (.<n>., fun i v ->
.<vout.(.~i) <- .~(of_code_complex v)>.) in
let v1 = Vec (.<n>., fun i ->
of_complex_code .<v1.(.~i)>.) in
let v2 = Vec (.<n>., fun i ->
of_complex_code .<v2.(.~i)>.) in
let module V = VMULT(FloatCodeComplex)(VecDyn) in
V.vmult vout v1 v2)
>.
;;
vout
結果を格納する出力ベクトルは
どこにありますか。Vec (n, fun i -> v)
は抽象ベクトルで、n
は長さで、fun i -> v
各インデックスを値にマップします。
OVec (n, fun i v -> body)
は抽象的な「出力ベクトル」でn
あり、 は長さでありfun i v -> body
、各インデックスi
および の関連する出力要素v
で実行されi
ます。
値を値にof_complex_code
変換します。たとえば、 に変換します。このモジュールは、(点ごとの) ベクトル乗算を定義します (詳細については、こちらのコードを参照してください)。complex code
code complex
.<{real=1.0, imag=0.0}>.
{real=.<1.0>., imag=.<0.0>.}
VMULT
実行するとvmult_ca
、次のコードが生成されます。
val vmult_ca :
(float_complex array -> float_complex array -> float_complex array -> unit)
code = .<
fun vout_4 ->
fun v1_5 ->
fun v2_6 ->
let n_7 = Array.length vout_4 in
for i_8 = 0 to n_7 - 1 do
vout_4.(i_8) <-
{
Cmplx.im =
(((v1_5.(i_8)).Cmplx.re *. (v2_6.(i_8)).Cmplx.im) +.
((v1_5.(i_8)).Cmplx.im *. (v2_6.(i_8)).Cmplx.re));
Cmplx.re =
(((v1_5.(i_8)).Cmplx.re *. (v2_6.(i_8)).Cmplx.re) -.
((v1_5.(i_8)).Cmplx.im *. (v2_6.(i_8)).Cmplx.im))
}
done>.
注記v1_5.(i_8)
は 4 回繰り返されます。課題は、繰り返しを避けるためにローカル変数にバインドするためにlet
どこかに挿入することです。を呼び出すだけで「ごまかす」ことができましたが、なしでどこに挿入すればよいかわかりません。ヒントをいただければ幸いです。vmult_ca
v1_5.(i_8)
genlet
.<v1.(~i)>.
let
genlet