Hi. The last 7 months I have been working on the greatest release of AngouriMath. There is something I want to tell you.

### Briefly about the project

In November of 2019 I realized that it would be nice to have a symbolic algebra library for .NET, which could simplify expressions, solve equations, build latex code, and many more. That is how I decided to create one.

## But this already exists...

As long as I tell people about what I am working on, they suggest different solutions, be those to rewrite SymPy, make a wrapper over SageMath for .NET, pirate Wolfram|Alpha, use primitive mathnet.symbolics (about which they mention themselves).

All of those have limitations or difficulties. In contrast, what I am working on is a very lightweight library, made and optimized for .NET specifically. It is open-source (under MIT).

### Release 1.2

In August one of the main contributors, @HappyPig375, helped to rewrite a significant part of the library into a type hierarchy. Every operator/function has its own node (type). Thanks to it, the library now has a more obvious API, improved performance and security. Now, let us go over what has been done within these 7 months.

#### An expression is a record

For example, that is what `Sumf `

looks like

`public sealed partial record Sumf(Entity Augend, Entity Addend) : NumericNode`

Thanks to it, now we can apply pattern matching:

```
internal static Entity CommonRules(Entity x) => x switch
{
// (a * f(x)) * g(x) = a * (f(x) * g(x))
Mulf(Mulf(Number const1, Function func1), Function func2) => func1 * func2 * const1,
// (a/b) * (c/d) = (a*c)/(b*d)
Mulf(Divf(var any1, var any2), Divf(var any3, var any4)) => any1 * any3 / (any2 * any4),
// a / (b / c) = a * c / b
Divf(var any1, Divf(var any2, var any3)) => any1 * any3 / any2,
```

(it is a few examples of patterns used in the simplification algorithm)

### Math

Here I am going to over over features related to math itself.

#### New functions

`Secant`

, `cosecant`

, `arcsecant`

, `arccosecant `

were added as separate nodes.

12 hyperbolic functions were added. They do not have their own nodes and return their symbolic expression (`sinh(x)`

as`(e.Pow(x) - e.Pow(-x)) / 2`

).

`Abs `

and `Signum`

. The syntax of `Abs `

is the following: `(|x|)`

. It looks similar to how we write in on a paper while at the same time allows to avoid ambiguouty (because | is symmetric, there might be problems with it).

Euler's totient function was added.

```
WriteLine(@"phi(8)".EvalNumerical());
WriteLine(@"(|-3 + 4i|)".EvalNumerical());
WriteLine(@"sinh(3)".Simplify());
WriteLine(@"sec(0.5)".Simplify());
```

Prints

```
4
5
(e ^ 3 - 1 / e ^ 3) / 2
sec(1/2)
```

#### Domains

They allow to limit every node's range. If a node is out of its domain, it turns into a `NaN`

, which makes the entire expression undefined. `SpecialSet`

s are used as values of domains.

#### Booleans and logic

Logic operators were finally added. At the beginning, there was an idea to make those similar to what we use in programming; instead, it was decided to make them literal. That is why the syntax is: `not`

, `or`

, `xor`

, `and`

, `implies`

.

To check whether an expression is evaluable into a `Boolean`

, you need to use `EvaluableBoolean`

. Same way, we use `EvaluableNumerical `

to check whether an expression is evaluable into a `Number`

.

`WriteLine(@"(true or b) implies c".Simplify());`

(prints`c`

)

#### Equality and inequality signs

They might carry the `Boolean`

type, if their operands are computed. Of course, the following were added: `=`

, `<`

, `>`

, `<=`

, `>=`

.

You can also combine inequalities. For example, `a > b > c`

is interpreted as`a > b and b > c`

.

`WriteLine(@"a < b >= c".Simplify());`

(Prints`a < b and b >= c`

)

#### Sets

Sets were added. They are parsable and have their own nodes.

The most naive type of set is `FiniteSet`

. Its syntax: `{ 1, 2, 3 }`

.

`Intervals `

also have familiar syntax: `[1; 2]`

for both points included, `(1; 2)`

for both excluded, `[1; 2)`

for the right one excluded, and `(1; 2]`

for the left one excluded. Complex intervals were removed because of their clumsiness.

`SpecialSet `

are preset sets. Now we have `CC`

, `RR`

, `QQ`

, `ZZ`

, `BB`

for complex, real, rational, integer and boolean values.

`ConditionalSet `

is written in set-builder notation, for example: `{ x : x > 0 and x^2 = y }`

(any `x`

such that greater than 0 and equals`y`

).

`WriteLine(@"({ 1, 2 } \/ { 5 }) /\ { x : x in [2; 3] and x > 0 } ".Simplify());`

(Prints`{ 2 }`

)

#### Limits improved

First remarkable, second remarkable limits transformation rules were added, as well as the l'Hopital's rule.

```
WriteLine("tan(a x) / (b x)".Limit("x", 0));
WriteLine("(sin(t) - t) / t3".Limit("t", 0));
```

(Prints`a / b`

and `-1/6`

respectively)

#### "Provided" node

Allows to set constraints on an expression. For example, square root on real numbers we can define as `sqrt(x) provided x >= 0`

. It will turn into `NaN `

if you substitute negative `x`

.

If an expression being turned into `NaN `

is an element of a finite set, it will be excluded, instead of turning the whole expression into `NaN`

. It is the only exception for `NaN`

.

#### Piecewise

`Piecewise `

is a sequence of`Provided`

s. Unlike the classical piecewise-defined function, here the order of elements matters, and when computing`Piecewise`

, the first`Provided`

is returned such that its predicate is true.

That is an example of how we can define the absolute value function for real numbers via `Piecewise`

:

```
Entity abs = "piecewise(x provided x > 0, -x provided x <= 0)";
WriteLine(abs.Substitute("x", 3).EvalNumerical());
WriteLine(abs.Substitute("x", -3).EvalNumerical());
```

(Prints 3 in both cases)

## Ease and convenience of use

This part of the article about features making the use of AngouriMath more comfortable.

#### Exceptions were reconsidered and refactored

Now all exceptions thrown by the library are somehow inherited from `AngouriMathBaseException`

. Because there is no`p/invoke`

or IO, you can be assured that any exception assignable to `AngouriMathBaseException `

does not bring any direct harm to the system or user's data. In other words, when catching exceptions, now you can catch this exception in the last instance of `Catch`

.

#### Performance improved

To be precise, the performance has been fluctuating throughout this all time. Nonetheless, it is still by far better than that of 1.1.0.5. Here you can find a performance report by every key commit.

#### F# is now supported

With this release, the API for AngouriMath is now supported natively for wonderful language F#. It might be not as functional as the main API, so in especially complicated cases, you still can call methods from the core library itself.

#### Interactive

I wrote an article some time ago about AngouriMath in Jupyter. AngouriMath.Interactive itself simplify converts `ILatexiseable `

into a LaTeX-code and renders it with MathJax (read more about it in the mentioned article).

#### Multithreading

All computations happen strictly in one thread. The library is not responsible for your threading problems. Moreover, all methods are thread-safe. The settings are local for every thread(`[ThreadStatic]`

).

The main feature of this update is that you can interrupt computations of `Solve `

or`Simplify`

.

#### New settings

It is their third version. Even though I am not a big fan of the new solution, it is the best I could achieve. To set a new value of a setting, let us write

```
using var _ = MaxExpansionTermCount.Set(10);
// some code
```

Then this setting will be automatically rolled back to the previous value once the end of the scope is reached (the return type of `Set`

is`IDisposable`

).

### That is about it

Thank you for your attention. I will be pleased to answer your questions.

Anybody willing to contribute is welcome (contact me or fork and make your changes directly).