AngouriMath
Navigation
Compilation
← Back to the main page
We will consider ways to improve the performance of computations via compiling functions.
Compilation into a native delegate
Here we will consider a bunch of methods, which all are overloads of one:
Compile.
This method compiles a given symbolic expression into a native delegate, which then
can be executed with a very high speed. This time, we first consider the way
you highly likely need it to be compiled.
Let us start with a simple example:
Entity expr = "sin(x)";
Func mySin = expr.Compile("x");
Console.WriteLine(mySin(4.2f));
Output:
-0.87157565
The variable
mySin has type
Func. Its type parameters accurately correspond
to the type parameters of method
Compile. Let us consider a more complicated example:
Entity expr = "sqrt(sin(x) + 3)";
var f = expr.Compile("x");
Console.WriteLine(f(4.2f));
Output:
1.458912
The number
3, although integer, is upcasted to
float automatically. But if only you passed
an integer as type params,
sin will return an
int as well. Example:
Entity expr = "sqrt(sin(x) + 3)";
var f = expr.Compile("x");
Console.WriteLine(f(4));
Output:
1
You can also pass multiple parameters, as well as multiple parameters of different types. Example:
Entity expr = "sin(x) + y";
var f = expr.Compile("x", "y");
Console.WriteLine(f(4.3f, 7.8d));
Output:
6.883834
The supported types are:
int,
long,
float,
double,
Complex,
BigInteger. Let us consider
an example, where
int is upcasted to a
Complex:
using System.Numerics;
Entity expr = "x + y";
var f = expr.Compile("x", "y");
Console.WriteLine(f(new(4, 5), 5));
Output:
<9; 5>
Complex here is
System.Numerics.Complex, and the printed form is that type's own —
it was
(9, 5) before .NET 8 changed it.
You can pass up to 8 type parameters excluding the one for output.
Extensions include the same set of methods, but for string.
If needed to pass more than 8 parameters, or other types than the ones listed, or
custom rules for types, consider declaring your own
CompilationProtocol.
CompilationProtocol
Since
the way AM compiles an expression is through
Linq.Expression, it requires provided rules for constants to be converted into a constant,
unary/binary/n-ary nodes to be converted into calls or operators.
That is why AM has class
CompilationProtocol which defines a number of rules for every such
operation.
Its property
ConstantConverter is responsible for converting a given constant
expression of type
Entity into a Linq.Expression.
BinaryNodeConverter takes two arguments of type
Linq.Expression and one argument of type
Entity. Although allowed, it is not recommended to rely on the third argument's value. Instead,
we encourage to use it as a type holder and switch over it when looking for a good node. For example,
that is a fragment of code for this ruleset:
...
return typeHolder switch
{
Sumf => Expression.Add(left, right),
Minusf => Expression.Subtract(left, right),
Mulf => Expression.Multiply(left, right),
Divf => Expression.Divide(left, right),
...
Same way it is recommended to define
UnaryNodeConverter and
AnyArgumentConverter (the latter
for n-ary nodes).
Now, after you defined your own compilation protocol, you need to pass your delegate and parameters
of the final function:
Entity expr = "x + y";
var f = expr.Compile>(
new(), typeof(float),
new[] { (typeof(float), Var("x")), (typeof(float), Var("y")) }
);
Console.WriteLine(f(4, 5));
Here we use
new() instead of an instance of
CompilationProtocol, but instead of it a custom
protocol can be passed.
Compilation into FastExpression
It is highly recommend to compile a given expression the way it is described above.
FastExpression is a special type. It contains instructions for every node and works as a stack
machine. When compiled into it, it translates a given expression into a number of instructions,
which are then sequentially executed.
It does not accept any arguments, as it unconditionally work with
Complex. Example:
Entity expr = "x + y";
var f = expr.Compile("x", "y");
Console.WriteLine(f.Call(4, 5));
Output:
<9; 0>
It is not as fast and flexible as
Compile<>.
Angouri © 2019-2023 ·
Project's repo ·
Site's repo ·
Octicons ·
Transparency ·
1953 pages online