This method should return a function which can evaluate the scalar product of two vectors of the same size:
public static Func<T[], T[], T> GetVectorMultiplyFunction<T>() where T : struct
{
var x = Expression.Parameter(typeof(T[]), "x");
var y = Expression.Parameter(typeof(T[]), "y");
var body = Enumerable
.Range(0, 3 /*Expression.ArrayLength(x)*/)
.Select(i => Expression.Multiply(
Expression.ArrayIndex(x, Expression.Constant(i)),
Expression.ArrayIndex(y, Expression.Constant(i))
))
.Aggregate(Expression.Add);
var lambda = Expression.Lambda<Func<T[], T[], T>>(body, x, y);
return lambda.Compile();
}
But in order to do that, I need to know the length of an array. There's a method Expression.ArrayLength()
which returns UnaryExpression
instead of the int
and the expression cannot be cast explicitly to int. Is there a way of evaluating the array length as int
beforehand?
UPD
Here's a unit test showing how this method should work:
[Test]
public void GetVectorMultiplyFunctionReturnsFunctionForInt()
{
var first = new int[] { 1, 2, 3 };
var second = new int[] { 2, 2, 2 };
var expected = 1 * 2 2 * 2 3 * 2;
var func = GetVectorMultiplyFunction<int>();
var actual = func(first, second);
Assert.AreEqual(expected, actual);
}
CodePudding user response:
This may not be what you want but seems to solve your problem if all you need to retain is the signature:
public static Func<T[], T[], T> GetVectorMultiplyFunction<T>() where T : struct
{
return (T[] x, T[] y) => {
T result = default(T);
for(var i = 0; i < x.Length; i )
{
var xd = (dynamic)x[i];
var yd = (dynamic)y[i];
result = (xd * yd);
}
return result;
};
CodePudding user response:
The length of an array is not part of the type definition, it's a value you can only obtain at runtime.
With the recent introduction of Generic Math, you can multiply and add values using generics without needing to build an expression tree;
public static T Calc<T>(T[] x, T[] y)
where T : struct, IMultiplyOperators<T,T,T>, IAdditionOperators<T,T,T>
{
T result = default(T);
for(var i = 0; i < x.Length && i < y.Length; i )
result = x[i] * y[i];
return result;
}
But I assume that for your assignment you are expected to build an expression tree equivalent to the above method, then compile it.