**Fun With C# Expressions**

*Previously:*

Note: The latest code can be found at https://github.com/dogbiscuituk/Sid/.Differentiating f(x)^g(x)

Take a seat with Visual Studio and create a new solution - Console, Winforms, whatever - your choice. Now add a new class library

*FormulaBuilder*, and add to that a static class

*Differentiator*. This is going to let us manipulate objects of type

*System.Linq.Expression*, representing real-valued functions of a single real variable, and ultimately to plot the graph of any such function, as well as its

*n*th derivatives. It will use an easy-to-read fluent interface, while illustrating some key design tenets I'd like to highlight.

Back to the class, and here come our first three requirements. We will need ways to:

- represent constants and variables, and combine these fluently into compound expressions;
- display any such expression as an easy-to-read formula, and evaluate it for given values of
*x*; and - verify correctness of these combinations and conversions.

*ParameterExpression*for

*x*, and the following starter set of extension methods:

```
using System;
using System.Diagnostics;
using System.Linq.Expressions;
namespace FormulaBuilder
{
public static class Differentiator
{
public static ParameterExpression x = Expression.Variable(typeof(double));
public static ConstantExpression Constant(double c) => Expression.Constant(c);
public static string AsString(this Expression e, string variableName = "x") =>
e.ToString().Replace("Param_0", variableName);
public static Func<double, double> AsFunction(this Expression e) =>
Expression.Lambda<Func<double, double>>(e, x).Compile();
public static double AsDouble(this Expression e, double x) => AsFunction(e)(x);
public static void Check(double expected, double actual) =>
Check(expected.ToString(), actual.ToString());
public static void Check(string expected, string actual)
{
if (actual == expected)
Debug.WriteLine("OK: " + actual);
else
Debug.WriteLine("*** Comparison failed. Expected: {0}, Actual: {1}.", expected, actual);
}
```

On first look, the expression display requirement (1) seems to be met by the built-in

*ToString()*method, available to every type; but that spits out an ugly

*Param_0*instead of a nice tidy

*x*, so we supply a new

*AsString()*method to tidy that up.

The expression evaluation/iteration requirement (2) means converting our expression into a

*LambdaExpression*, compiling that into a function, and finally executing that function using our chosen values of

*x*. For efficiency I've split this process into two steps. The conversion to a compiled

*LambdaExpression*is performed by the

*ToFunction()*method. Once we have this function, we can call it a million times with different

*x*values, without having to perform a runtime lambda recompilation every time. The

*ToDouble()*method is also provided for those out-of-loop test cases, where we just want to obtain a single value using a single method call.

As for testing requirement (3), the overloaded

*Check*methods provide a line of debug output for each checked operation, beginning with either

*OK*or

**** Comparison failed*.

**Fluency First**

Now back to those compounds. Actually, the

*System.Linq.Expression*class already has some fine methods for compounding expressions into

*BinaryExpression*s, but I'm going to deviate a little from these. The target is a fluent syntax for building expressions on the fly, and to that end, I find the names

*Plus*,

*Minus*,

*Times*,

*Over*a little easier to scan than

*Add*,

*Subtract*,

*Multiply*,

*Divide*. So let's add these to the

*Differentiator*class:

```
public static BinaryExpression Plus(this Expression f, Expression g) => Expression.Add(f, g);
public static BinaryExpression Minus(this Expression f, Expression g) => Expression.Subtract(f, g);
public static BinaryExpression Times(this Expression f, Expression g) => Expression.Multiply(f, g);
public static BinaryExpression Over(this Expression f, Expression g) => Expression.Divide(f, g);
public static BinaryExpression Power(this Expression f, Expression g) => Expression.Power(f, g);
```

Actually I also considered replacing

*Power*with

*ToThe*, but maybe that's just a colloquial idiom too far!

The

*Constant()*syntax is quite clumsy, almost the opposite of the

*fluent*design goal. It would be great to have an implicit operator for converting constants such as

*2.0*or

*Math.PI*into

*ConstantExpression*s as required - just as it would be equally great to be able to overload the standard arithmetic operators for

*Expression*s, and be finished with fluent method calls! Sadly, C# restrictions on overloaded operators make both of these dreams impossible, but at least in the

*Constant()*case, what we can do instead is overload the calling methods at the point(s) of invocation. For example, we'd like to be able to write

*x.Power(2)*or

*x.Power(2.0)*instead of

*x.Power(Constant(2))*. This can be achieved by overloading the

*Power()*method, supplying a

*double*in place of an

*Expression*for its second argument, and similarly for the other

*BinaryExpression*methods:

```
public static BinaryExpression Plus(this Expression f, double g) => f.Plus(Constant(g));
public static BinaryExpression Minus(this Expression f, double g) => f.Minus(Constant(g));
public static BinaryExpression Times(this Expression f, double g) => f.Times(Constant(g));
public static BinaryExpression Over(this Expression f, double g) => f.Over(Constant(g));
public static BinaryExpression Power(this Expression f, double g) => f.Power(Constant(g));
```

This almost gets us where we want to go, but we still have to write e.g.

*Constant(3).Times(x)*, when we'd prefer just

*3.Times(x)*. Here it's the

*first*argument of the

*Times()*extension method that needs overloading, and there's a spanner thrown in by C#'s rules of method resolution. Sure, we can supply alternate methods with a

*double*in that position, but where previously we could rely on an

*int*argument being promoted to

*double*, no such luck this time. If we insist

*(and we do!)*upon being able to write

*3.Times(x)*, as opposed to workarounds like

*x.Times(3)*,

*3.0.Times(x)*, or worst of all

*((double)3).Times(x)*- which seems hardly an improvement! - then we must supply separate

*double*and

*int*versions.

```
public static BinaryExpression Plus(this double f, Expression g) => Constant(f).Plus(g);
public static BinaryExpression Minus(this double f, Expression g) => Constant(f).Minus(g);
public static BinaryExpression Times(this double f, Expression g) => Constant(f).Times(g);
public static BinaryExpression Over(this double f, Expression g) => Constant(f).Over(g);
public static BinaryExpression Power(this double f, Expression g) => Constant(f).Power(g);
public static BinaryExpression Plus(this int f, Expression g) => Constant(f).Plus(g);
public static BinaryExpression Minus(this int f, Expression g) => Constant(f).Minus(g);
public static BinaryExpression Times(this int f, Expression g) => Constant(f).Times(g);
public static BinaryExpression Over(this int f, Expression g) => Constant(f).Over(g);
public static BinaryExpression Power(this int f, Expression g) => Constant(f).Power(g);
public static UnaryExpression Negate(this Expression e) => Expression.Negate(e);
public static BinaryExpression Reciprocal(this Expression e) => e.Power(-1);
public static BinaryExpression Squared(this Expression e) => e.Power(2);
public static BinaryExpression Cubed(this Expression e) => e.Power(3);
public static void TestCompoundExpression()
{
var f = x.Squared().Plus(3.Times(x)).Minus(5); // f(x) = x²+3x-5
Check("(((x ^ 2) + (3 * x)) - 5)", f.AsString()); // Check the built expression formula
Check(Math.Pow(7, 2) + 3 * 7 - 5, f.AsDouble(7)); // Check the expression value at x = 7 (should be 65)
}
```

With the addition of these few minor utilities, we now have the means to build polynomials and other arithmetic expressions in

*x*. Give your app a project reference to

*FormulaBuilder*, add it to your

*using*clauses, then add a call to

*Differentiator.TestCompoundExpression()*somewhere in your main code and run it. You should see the following two lines of reassurance in your debug output:

OK: (((x ^ 2) + (3 * x)) - 5)These show that the quadratic expression

OK: 65

*x² + 3x - 5*was built successfully, and that it correctly evaluates to

*65*at

*x = 7*.

**Function Calls**

Arithmetic operations are one way of building out our expressions, but what about invoking functions? What use a differentiator that can't tell you the derivative of

*sin*is

*cos*, while that of

*cos*is

*-sin*?

Elementary functions in the

*System.Linq.Expression*hierarchy are represented by the

*MethodCallExpression*class. The

*Function()*code below generates such an expression from the correspondingly named method of the

*Math*class, obtained via reflection. Below it are listed a generous dozen or so concrete functions, all which happen to be implemented in

*Math*; and below these, a further group showing how functions "missing" from

*Math*, such as the reciprocal trigonometrics and hyperbolics, as well as their inverses, can be built out of expressions in the elementary ones.

Naturally, the input to any functional expression can itself be an arbitrary expression tree, maybe containing further nested function calls, etc.

```
public static MethodCallExpression Function(string functionName, Expression e) =>
Expression.Call(typeof(Math).GetMethod(functionName, new[] { typeof(double) }), e);
public static MethodCallExpression Abs(this Expression e) => Function("Abs", e);
public static MethodCallExpression Sqrt(this Expression e) => Function("Sqrt", e);
public static MethodCallExpression Exp(this Expression e) => Function("Exp", e);
public static MethodCallExpression Log(this Expression e) => Function("Log", e);
public static MethodCallExpression Log10(this Expression e) => Function("Log10", e);
public static MethodCallExpression Sin(this Expression e) => Function("Sin", e);
public static MethodCallExpression Cos(this Expression e) => Function("Cos", e);
public static MethodCallExpression Tan(this Expression e) => Function("Tan", e);
public static MethodCallExpression Asin(this Expression e) => Function("Asin", e);
public static MethodCallExpression Acos(this Expression e) => Function("Acos", e);
public static MethodCallExpression Atan(this Expression e) => Function("Atan", e);
public static MethodCallExpression Sinh(this Expression e) => Function("Sinh", e);
public static MethodCallExpression Cosh(this Expression e) => Function("Cosh", e);
public static MethodCallExpression Tanh(this Expression e) => Function("Tanh", e);
public static BinaryExpression Sec(this Expression e) => Reciprocal(Cos(e));
public static BinaryExpression Csc(this Expression e) => Reciprocal(Sin(e));
public static BinaryExpression Cot(this Expression e) => Reciprocal(Tan(e));
public static MethodCallExpression Asec(this Expression e) => Acos(Reciprocal(e));
public static MethodCallExpression Acsc(this Expression e) => Asin(Reciprocal(e));
public static MethodCallExpression Acot(this Expression e) => Atan(Reciprocal(e));
public static BinaryExpression Sech(this Expression e) => Reciprocal(Cosh(e));
public static BinaryExpression Csch(this Expression e) => Reciprocal(Sinh(e));
public static BinaryExpression Coth(this Expression e) => Reciprocal(Tanh(e));
public static MethodCallExpression ArcSinh(this Expression e) => Log(e.Plus(Sqrt(e.Squared().Plus(1))));
public static MethodCallExpression ArcCosh(this Expression e) => Log(e.Plus(Sqrt(e.Squared().Minus(1))));
public static BinaryExpression ArcTanh(this Expression e) => Log(1.Plus(e).Over(1.Minus(e))).Over(2);
public static MethodCallExpression ArcSech(this Expression e) => Log(1.Plus(Sqrt(1.Minus(e.Squared()))).Over(e));
public static MethodCallExpression ArcCsch(this Expression e) => Log(1.Plus(Sqrt(1.Plus(e.Squared()))).Over(e));
public static BinaryExpression ArcCoth(this Expression e) => Log(e.Plus(1).Over(e.Minus(1))).Over(2);
public static void TestTrigonometricExpression()
{
var f = Sin(x).Squared().Plus(Cos(x).Squared()); // f(x) = sin²x+cos²x
Check("((Sin(x) ^ 2) + (Cos(x) ^ 2))", f.AsString()); // Check the built expression formula
double p3 = Math.PI / 3, s = Math.Sin(p3), c = Math.Cos(p3); // Check the expression value at x = π/3
Check(Math.Pow(s, 2) + Math.Pow(c, 2), f.AsDouble(p3)); // (should be 1)
}
```

In your app level code, add a call to

*Differentiator.TestTrigonometricExpression()*, which builds the expression

*sin²x + cos²x*: the LHS of the most famous trigonometric identity, whose RHS is

*1*for all values of

*x*. The new test method checks, first using

*AsString()*, that the correct expression has in fact been built; then, using

*AsDouble()*, that it evaluates to

*1*as expected, in this case when supplied with

*π/3*as a parameter. At runtime, your debug window should display a further two comforting lines of verification:

OK: ((Sin(x) ^ 2) + (Cos(x) ^ 2))

OK: 1

**Finally, A Derivative**

Can't finish this article without a look at some actual differentiation, so let's add the function

*D()*that differentiates expressions. It needs to handle just these four cases:

- a constant;
*x*itself;- a function call;
- an artithmetic operation (unary or binary).

```
public static Expression D(this Expression e)
{
if (e is ConstantExpression) return Constant(0); // d(c)/dx = 0
if (e is ParameterExpression) return Constant(1); // d(x)/dx = 1
if (e is MethodCallExpression m)
{
var f = m.Arguments[0];
return DifferentiateFunction(m.Method.Name, f).Times(D(f)); // Chain Rule
}
if (e is UnaryExpression u)
{
var f = D(u.Operand);
return u.NodeType == ExpressionType.UnaryPlus ? f : Negate(f);
}
if (e is BinaryExpression b)
{
Expression f = b.Left, g = b.Right;
switch (b.NodeType)
{
case ExpressionType.Add: // (f+g)' = f'+g'
return D(f).Plus(D(g));
case ExpressionType.Subtract: // (f-g)' = f'-g'
return D(f).Minus(D(g));
case ExpressionType.Multiply: // (fg)' = f'g+fg'
return D(f).Times(g).Plus(f.Times(D(g)));
case ExpressionType.Divide: // (f÷g)' = (f'g-fg')÷(g^2) = f'÷g-fg'÷(g^2)
return D(f).Over(g).Minus(f.Times(D(g)).Over(g.Squared()));
case ExpressionType.Power: // (f^g)' = (f^g)*(f'g÷f+g'Log(f)) = (f'g+fg'Log(f))f^(g-1)
return D(f).Times(g).Plus(f.Times(D(g)).Times(Log(f))).Times(f.Power(g.Minus(1)));
}
}
throw new InvalidOperationException();
}
private static Expression DifferentiateFunction(string methodName, Expression x)
{
switch (methodName)
{
case "Abs": return x.Over(Abs(x)); // d(|x|)/dx = x/|x|
case "Sqrt": return x.Power(-0.5).Over(2); // d(√x)/dx = 1/(2√x)
case "Exp": return Exp(x); // d(eˣ)/dx = eˣ
case "Log": return Reciprocal(x); // d(ln(x))/dx = 1/x
case "Log10": return Reciprocal(x).Times(Math.Log10(Math.E)); // d(log₁₀(x))/dx = log₁₀(e)/x
case "Sin": return Cos(x); // d(sin(x))/dx = cos(x)
case "Cos": return Negate(Sin(x)); // d(cos(x))/dx = -sin(x)
case "Tan": return Cos(x).Power(-2); // d(tan(x))/dx = sec²(x)
case "Asin": return 1.Minus(x.Squared()).Power(-0.5); // d(arcsin(x))/dx = 1/√(1-x²)
case "Acos": return Negate(1.Minus(x.Squared()).Power(-0.5)); // d(arccos(x))/dx = -1/√(1-x²)
case "Atan": return 1.Over(1.Plus(x.Squared())); // d(arctan(x))/dx = 1/(1+x²)
case "Sinh": return Cosh(x); // d(sinh(x))/dx = cosh(x)
case "Cosh": return Sinh(x); // d(cosh(x))/dx = sinh(x)
case "Tanh": return 1.Minus(Tanh(x).Squared()); // d(tanh(x))/dx = 1-tanh²(x)
}
throw new InvalidOperationException();
}
```

*DifferentiateFunction()*provides the basic template for a function's derivative, without actually applying the chain rule to its argument

*Expression*. That's why it has been implemented as a private helper function; calling it out of context could result in incorrect results if chain rule application was omitted by mistake.

**Algebraic Simplification**

Still we're not quite ready to supply the final batch of unit tests, stick a fork in it and call it done. While the

*D()*method may be returning strictly correct results, good enough for numeric applications such as graphing, algebraically they are a bit of a mess. For example, differentiating any candidate containing a function call, even one as simple as

*Sin(x)*, results in a clumsy

**1*becoming appended to the output expression. Some level of simplification is clearly needed to provide visually acceptable results. For this reason,

*D()*gets called not directly, but from within a wrapper function

*Differentiate()*which applies a layer of simplification before returning the resultant

*Expression*:

```
public static Expression Differentiate(this Expression e) => Simplify(D(e));
public static Expression Simplify(this Expression e)
{
if (e is MethodCallExpression m) return SimplifyMethodCall(m);
if (e is UnaryExpression u) return SimplifyUnary(u);
if (e is BinaryExpression b) return SimplifyBinary(b);
return e;
}
public static Expression SimplifyMethodCall(MethodCallExpression m)
{
var operand = Simplify(m.Arguments[0]);
if (operand is ConstantExpression ce)
{
var c = (double)ce.Value;
return Constant(Function(m.Method.Name, x).AsDouble(c));
}
return Function(m.Method.Name, operand);
}
public static Expression SimplifyUnary(UnaryExpression u)
{
var operand = Simplify(u.Operand);
if (operand is ConstantExpression ce)
{
var c = (double)ce.Value;
return Constant(u.NodeType == ExpressionType.UnaryPlus ? c : -c);
}
return u.NodeType == ExpressionType.UnaryPlus ? operand : Negate(operand);
}
public static Expression SimplifyBinary(BinaryExpression b)
{
b = Expression.MakeBinary(b.NodeType, Simplify(b.Left), Simplify(b.Right));
if (b.Left is ConstantExpression ce1)
{
var c1 = (double)ce1.Value;
if (b.Right is ConstantExpression ce2)
return Constant(b.NodeType, c1, (double)ce2.Value);
switch (b.NodeType)
{
case ExpressionType.Add: // c + x → x + c
case ExpressionType.Multiply: // c * x → x * c
b = Expression.MakeBinary(b.NodeType, b.Right, b.Left);
break;
case ExpressionType.Subtract:
if (c1 == 0) return Negate(b.Right); // 0 - x → -x
break;
case ExpressionType.Divide:
if (c1 == 0) return Constant(0); // 0 ÷ x → 0
break;
case ExpressionType.Power:
if (c1 == 0) return Constant(0); // 0 ^ x → 0
if (c1 == 1) return Constant(1); // 1 ^ x → 1
break;
}
}
if (b.Right is ConstantExpression ce3)
{
var c3 = (double)ce3.Value;
switch (b.NodeType)
{
case ExpressionType.Add:
case ExpressionType.Subtract:
if (c3 == 0) return b.Left; // x ± 0 → x
break;
case ExpressionType.Multiply:
if (c3 == 0) return Constant(0); // x * 0 → 0
if (c3 == 1) return b.Left; // x * 1 → x
if (c3 == -1) return Negate(b.Left); // x * -1 → -x
break;
case ExpressionType.Divide:
if (c3 == 0)
throw new DivideByZeroException();
if (c3 == 1) return b.Left; // x ÷ 1 → x
if (c3 == -1) return Negate(b.Left); // x ÷ -1 → -x
break;
case ExpressionType.Power:
if (c3 == 0) return Constant(1); // x ^ 0 → 1
if (c3 == 1) return b.Left; // x ^ 1 → x
break;
}
switch (b.NodeType)
{
case ExpressionType.Add: // (x + c1) ± c2 → x + (c1 ± c2)
case ExpressionType.Subtract: // (x - c1) ± c2 → x - (c1 ∓ c2)
case ExpressionType.Multiply: // (x * c1) */ c2 → x * (c1 */ c2)
case ExpressionType.Divide: // (x / c1) */ c2 → x / (c1 /* c2)
if (!(b.Left is BinaryExpression c && c.Right is ConstantExpression ce4))
break;
bool same = c.NodeType == b.NodeType, opps = c.NodeType == Invert(b.NodeType);
if (!(same || opps))
break;
var c4 = (double)ce4.Value;
var nodeType = c.NodeType == ExpressionType.Add || c.NodeType == ExpressionType.Subtract
? ExpressionType.Add
: ExpressionType.Multiply;
if (opps) nodeType = Invert(nodeType);
return Expression.MakeBinary(c.NodeType, c.Left, Constant(nodeType, c4, c3));
}
}
return b;
}
public static ExpressionType Invert(this ExpressionType nodeType)
{
switch (nodeType)
{
case ExpressionType.Add: return ExpressionType.Subtract;
case ExpressionType.Subtract: return ExpressionType.Add;
case ExpressionType.Multiply: return ExpressionType.Divide;
case ExpressionType.Divide: return ExpressionType.Multiply;
}
throw new InvalidOperationException();
}
public static ConstantExpression Constant(ExpressionType nodeType, double c, double d) =>
Constant(Apply(nodeType, c, d));
public static double Apply(ExpressionType nodeType, double c, double d)
{
switch (nodeType)
{
case ExpressionType.Add: return c + d;
case ExpressionType.Subtract: return c - d;
case ExpressionType.Multiply: return c * d;
case ExpressionType.Divide:
if (d == 0)
throw new DivideByZeroException();
return c / d;
case ExpressionType.Power:
if (c == 0 && d == 0)
throw new InvalidOperationException();
return Math.Pow(c, d);
}
throw new InvalidOperationException();
}
```

This

*Simplify()*method does little more than apply some arithmetic identity, associativity and commutativity results, to remove some of the redundancy littering the differentiator's output. That's why I've implemented it here as simple, direct logic. There are many more simplification rules to consider, and as such rules are added, it becomes clear that a rule application engine is needed, allowing extension of the list without spaghettification of the logic.

Now we can at least start writing an acceptable suite of unit tests. Here are some examples:

```
public static void TestSimplify(Expression e, string expected) => Check(expected, Simplify(e).AsString());
public static void TestSimplifications()
{
TestSimplify(x.Plus(6).Plus(2), "(x + 8)");
TestSimplify(6.Plus(x).Plus(2), "(x + 8)");
TestSimplify(6.Plus(x.Plus(2)), "(x + 8)");
TestSimplify(x.Plus(6).Minus(2), "(x + 4)");
TestSimplify(6.Plus(x).Minus(2), "(x + 4)");
TestSimplify(x.Minus(6).Plus(2), "(x - 4)");
TestSimplify(x.Minus(6).Minus(2), "(x - 8)");
TestSimplify(x.Times(6).Times(2), "(x * 12)");
TestSimplify(6.Times(x).Times(2), "(x * 12)");
TestSimplify(6.Times(x.Times(2)), "(x * 12)");
TestSimplify(x.Times(6).Over(2), "(x * 3)");
TestSimplify(6.Times(x).Over(2), "(x * 3)");
TestSimplify(x.Over(2).Times(8), "(x / 0.25)");
TestSimplify(x.Over(2).Over(8), "(x / 16)");
}
public static void TestDerivative(Expression e, string expected) => Check(expected, Differentiate(e).AsString());
public static void TestFunctionDerivatives()
{
TestDerivative(Abs(x), "(x / Abs(x))"); // d(|x|)/dx = x/|x|
TestDerivative(Sqrt(x), "((x ^ -0.5) / 2)"); // d(√x)/dx = 1/(2√x)
TestDerivative(Exp(x), "Exp(x)"); // d(eˣ)/dx = eˣ
TestDerivative(Log(x), "(x ^ -1)"); // d(ln(x))/dx = 1/x
TestDerivative(Log10(x), "((x ^ -1) * 0.434294481903252)"); // d(log₁₀(x))/dx = log₁₀(e)/x
TestDerivative(Sin(x), "Cos(x)"); // d(sin(x))/dx = cos(x)
TestDerivative(Cos(x), "-Sin(x)"); // d(cos(x))/dx = -sin(x)
TestDerivative(Tan(x), "(Cos(x) ^ -2)"); // d(tan(x))/dx = sec²(x)
TestDerivative(Asin(x), "((1 - (x ^ 2)) ^ -0.5)"); // d(arcsin(x))/dx = 1/√(1-x²)
TestDerivative(Acos(x), "-((1 - (x ^ 2)) ^ -0.5)"); // d(arccos(x))/dx = -1/√(1-x²)
TestDerivative(Atan(x), "(1 / ((x ^ 2) + 1))"); // d(arctan(x))/dx = 1/(x²+1)
TestDerivative(Sinh(x), "Cosh(x)"); // d(sinh(x))/dx = cosh(x)
TestDerivative(Cosh(x), "Sinh(x)"); // d(cosh(x))/dx = sinh(x)
TestDerivative(Tanh(x), "(1 - (Tanh(x) ^ 2))"); // d(tanh(x))/dx = 1-tanh²(x)
}
public static void TestPolynomialDerivative()
{
TestDerivative(x.Power(4).Minus(3.Times(x.Cubed())).Plus(6.Times(x.Squared())).Minus(3.Times(x)).Plus(1),
"(((((x ^ 3) * 4) - ((x ^ 2) * 9)) + (x * 12)) - 3)"); // d(x⁴-3x³+6x²-3x+1)/dx = 4x³-9x²+12x-3
}
public static void TestChainRule()
{
TestDerivative(Exp(x.Squared()), "(Exp((x ^ 2)) * (x * 2))"); // d(exp(x²))/dx = exp(x²)*2x
TestDerivative(Log(Sin(x)), "((Sin(x) ^ -1) * Cos(x))"); // d(ln(sin(x)))/dx = cot(x)
TestDerivative(Tan(x.Cubed().Plus(8.Times(x))), // d(tan(x³+8x))/dx = sec²(x³+8x)*(3x²+8)
"((Cos(((x ^ 3) + (x * 8))) ^ -2) * (((x ^ 2) * 3) + 8))");
}
public static void TestAll()
{
TestSimplifications();
TestCompoundExpression();
TestTrigonometricExpression();
TestFunctionDerivatives();
TestPolynomialDerivative();
TestChainRule();
}
}
}
```

Next time, by overwhelming public demand (one request has flooded in), I'll be exercising these extension methods in a simple differential graphing application.

**Acknowledgements**

- Thanks are due to my colleague Stuart Stein for his code review with useful comments, particularly the suggestion that I should
*embrace the expression body syntax*. - Thanks also to Pavel Vladov for the free use of his C# Syntax Highlighter to format the code snippets in this article.

## No comments:

## Post a Comment