I am trying to implement a function that returns functions that calculate the vectors' scalar product. It should be implemented via generics, but it seems possible only by generating code in the run time. Read several docs about code generation by building expression trees and this is what I have written so far:
public static Func<T[], T[], T> GetVectorMultiplyFunction<T>()
where T : struct
{
ParameterExpression first = Expression.Parameter(typeof(T[]), "first" );
ParameterExpression second = Expression.Parameter(typeof(T[]), "second");
ParameterExpression result = Expression.Parameter(typeof(T) , "result");
ParameterExpression index = Expression.Parameter(typeof(int), "index" );
LabelTarget label = Expression.Label(typeof(T));
BlockExpression block = Expression.Block(
new[] { result, index },
Expression.Assign( result, Expression.Constant(0) ),
Expression.Assign( index , Expression.Constant(0) ),
Expression.Loop(
Expression.IfThenElse(
Expression.LessThan( index, Expression.ArrayLength( first ) ),
Expression.Block(
Expression.AddAssign( result, Expression.Multiply( Expression.ArrayIndex( first, index ), Expression.ArrayIndex( second, index ) ) ),
Expression.Increment( index )
),
Expression.Break( label, result )
),
label
)
);
return Expression
.Lambda<Func<T[], T[], T>>( block, first, second )
.Compile();
}
This builds without problem but takes forever to run tests. I have a hard time wrapping my head around the subject. So I don't know what exactly went wrong.
This is a piece of tests that this method is used:
[Test]
public void GetVectorMultiplyFunctionReturnsFunctionForLong()
{
var first = new long[] { 1L, 2L, 3L };
var second = new long[] { 2L, 2L, 2L };
var expected = 1L * 2L + 2L * 2L + 3L * 2L;
var func = CodeGeneration.GetVectorMultiplyFunction<long>();
var actual = func(first, second);
Assert.AreEqual(expected, actual);
}

