TL;DR
How can I build up the expression using an array of coefficients and turn it into a Func<int, double>
? Is there a better way than expression trees?
I have an immutable Sequence type that is constructed using a Func<int, double> formula
that is used to generate the term An for a sequence A. I started building a helper class to construct common math formulas with some simple parameters:
public static Sequence CreateLinearSequence (double m, double b)
{ return new Sequence (n => m * n + b); }
I built standard methods for constant sequences, logarithms, and simple polynomials (linear, quadratic, cubic, and quartic) but I want to extend it to support an arbitrary number of terms using the params
keyword.
Here's the method I have:
public static Sequence CreatePolynomialSequence (params double[] coeff)
{
Expression<Func<int, double>> e = x => 0;
double pow = 0;
for (int i = coeff.Length - 1; i >= 0; i--)
{
double c = coeff[i];
var p = Expression.Parameter (typeof (int), "x");
e = Expression.Lambda<Func<int, double>> (
Expression.Add (
e,
(Expression<Func<int, double>>)(x => c * Math.Pow (x, pow))
),
p);
pow++;
}
return new Sequence (e.Compile ());
}
It might be obvious to you guys what I'm doing wrong; I messed around a bit until I got something that I felt like should work, but it doesn't.
The goal is for the Sequence to work like this for an array double[] coeff = {a,b,c,d,e,f,g,h}
x => h + gx + fx^2 + ex^3 + dx^4 + cx^5 + bx^6 + ax^7
using the appropriate Math.Pow(x, exponent)
calls.
Running
var s2 = SequenceHelper.CreatePolynomialSequence (new[] { 1d, 2 });
Console.WriteLine ("s2: " + s2);
results in
Unhandled Exception: System.InvalidOperationException: The binary operator Add is not defined for the types 'System.Func
2[System.Int32,System.Double]' and 'System.Func
2[System.Int32,System.Double]'. at System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow (ExpressionType binaryType, System.String name, System.Linq.Expressions.Expression left, System.Linq.Expressions.Expression right, Boolean liftToNull) [0x0004a] in /private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:658 at System.Linq.Expressions.Expression.Add (System.Linq.Expressions.Expression left, System.Linq.Expressions.Expression right, System.Reflection.MethodInfo method) [0x00057] in /private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:1409 at System.Linq.Expressions.Expression.Add (System.Linq.Expressions.Expression left, System.Linq.Expressions.Expression right) [0x00000] in /private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:1390 at Sequence.SequenceHelper.CreatePolynomialSequence (System.Double[] coeff) [0x00110] in /Users/Knoble/MonoProjects/Sequences/Sequence/SequenceHelper.cs:88
at Sequence.Test.Main () [0x0001f] in /Users/Knoble/MonoProjects/Sequences/Sequence/Test.cs:53 [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: The binary operator Add is not defined for the types 'System.Func2[System.Int32,System.Double]' and 'System.Func
2[System.Int32,System.Double]'. at System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow (ExpressionType binaryType, System.String name, System.Linq.Expressions.Expression left, System.Linq.Expressions.Expression right, Boolean liftToNull) [0x0004a] in /private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:658 at System.Linq.Expressions.Expression.Add (System.Linq.Expressions.Expression left, System.Linq.Expressions.Expression right, System.Reflection.MethodInfo method) [0x00057] in /private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:1409 at System.Linq.Expressions.Expression.Add (System.Linq.Expressions.Expression left, System.Linq.Expressions.Expression right) [0x00000] in /private/tmp/source-mono-mac-4.2.0-branch/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.1/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs:1390 at Sequence.SequenceHelper.CreatePolynomialSequence (System.Double[] coeff) [0x00110] in /Users/Knoble/MonoProjects/Sequences/Sequence/SequenceHelper.cs:88
at Sequence.Test.Main () [0x0001f] in /Users/Knoble/MonoProjects/Sequences/Sequence/Test.cs:53 The application was terminated by a signal: SIGHUP