Cloning for thread safe operations

TO SUPPORT MY WORK, ORDER A COMMERCIAL LICENSE
THANK YOU!

The tutorial consists of more than 200 live examples from 50 sections. Each of the examples can be copied and run on your own environment. In addition, mXparser provides an extensive collection of over 500 built-in math functions, expressions and symbols. Familiarize yourself with the scope and the syntax. Live testing is the best way to learn. Good luck! 🙂

Tutorial Math Collection API spec Download

Below is the code for JAVA, the code for C# is almost identical. To copy the code, double-click inside the frame.

Why special cloning might be handy?

One of the main advantages of mXparser is the ability to define a number of non-trivial dependencies between user-defined objects. For example, a user argument depends on another user argument, and a user function depends on both. There are also many more such dependencies, because the underlying architecture also uses this flexibility. For example, a user function always uses arguments and an expression. This, in turn, raises a number of complications when the user, unaware of it, uses the same instances of objects, reaching them from different threads. The library does not provide synchronization here, because its mechanism would be quite complex and would significantly affect performance. Most usage scenarios boil down to running computations on the same object from different threads to speed up calculations, but the computations themselves are independent of each other. Based on this assumption, we have prepared methods for cloning objects 1-1 along with their entire contents and a tree of relations with other objects. Thanks to this, you can be sure that the cloned object will behave identically and operations on it will not affect the initial one.

List of available options

// JAVA: import org.mariuszgromada.math.mxparser.*;
// C#: using org.mariuszgromada.math.mxparser;
// ...

// Cloning Constant
Constant newConstant = initConstant.cloneForThreadSafe();

// Cloning Argument
Argument newArgument = initArgument.cloneForThreadSafe();

// Cloning RecursiveArgument
RecursiveArgument newRecursiveArgument = initRecursiveArgument.cloneForThreadSafe()

// Cloning Function
Function newFunction = initFunction.cloneForThreadSafe();

// Cloning Expression
Expression newExpression = initExpression.cloneForThreadSafe();

Case 1: Just cloning for a thread safe

// JAVA: import org.mariuszgromada.math.mxparser.*;
// C#: using org.mariuszgromada.math.mxparser;
// ...
Argument x = new Argument("x = 2");
Argument y = new Argument("y = 2x", x);

// Making a copy of y
Argument yc = y.cloneForThreadSafe();

// Let's observe the behaviour
mXparser.consolePrintln("x = " + x.getArgumentValue() + ", y = " + y.getArgumentValue() + ", yc = " + yc.getArgumentValue());

x.setArgumentValue(4);
mXparser.consolePrintln("x = " + x.getArgumentValue() + ", y = " + y.getArgumentValue() + ", yc = " + yc.getArgumentValue());
[mXparser-v.5.2.0] x = 2.0, y = 4.0, yc = 4.0
[mXparser-v.5.2.0] x = 4.0, y = 8.0, yc = 4.0

Case 2: Cloning for a thread safe + retrieving a clone of related object

// JAVA: import org.mariuszgromada.math.mxparser.*;
// C#: using org.mariuszgromada.math.mxparser;
// ...
Argument x = new Argument("x = 2");
Argument y = new Argument("y = 2x", x);

// Making a copy of y
Argument yc = y.cloneForThreadSafe();

// Retrieving a copy of x that was created when making a copy of y
Argument xc = yc.getArgument("x");

// Let's observe the behaviour
mXparser.consolePrintln("x = " + x.getArgumentValue() + ", y = " + y.getArgumentValue() + ", xc = " + xc.getArgumentValue() +  ", yc = " + yc.getArgumentValue());

x.setArgumentValue(4);
mXparser.consolePrintln("x = " + x.getArgumentValue() + ", y = " + y.getArgumentValue() + ", xc = " + xc.getArgumentValue() +  ", yc = " + yc.getArgumentValue());

xc.setArgumentValue(5);
mXparser.consolePrintln("x = " + x.getArgumentValue() + ", y = " + y.getArgumentValue() + ", xc = " + xc.getArgumentValue() +  ", yc = " + yc.getArgumentValue());
[mXparser-v.5.2.0] x = 2.0, y = 4.0, xc = 2.0, yc = 4.0
[mXparser-v.5.2.0] x = 4.0, y = 8.0, xc = 2.0, yc = 4.0
[mXparser-v.5.2.0] x = 4.0, y = 8.0, xc = 5.0, yc = 10.0

Case 3: Cloning for a thread safe + retrieving many clones of related objects

// JAVA: import org.mariuszgromada.math.mxparser.*;
// C#: using org.mariuszgromada.math.mxparser;
// ...
Constant a = new Constant("a = 2");
Argument x = new Argument("x = 2a", a);
Argument y = new Argument("y = 2x", x);
Function f = new Function("f(u,v) = u^2 + v^2 + a", a);
Expression e = new Expression("f(1,2) + y", f, y);

// Making a copy of e
Expression ec = e.cloneForThreadSafe();

// Let's test the behaviour
mXparser.consolePrintln("e = " + e.calculate() + ", ec = " + ec.calculate());

// Retrieving a copy of a via different paths
Constant ac1 = ec.getFunction("f").getConstant("a");
Constant ac2 = ec.getArgument("y").getArgument("x").getConstant("a");

// ac1 and ac2 will point to the same object,
// but different for the initial one
mXparser.consolePrint("(ac1 == ac2) = " + (ac1 == ac2) + ", (a == ac1) = " + (a == ac1) + ", (a == ac2) = " + (a == ac2));
[mXparser-v.5.2.0] e = 15.0, ec = 15.0
[mXparser-v.5.2.0] (ac1 == ac2) = true, (a == ac1) = false, (a == ac2) = false

Case 4: Cloning a sophisticated user objects with recursive dependencies

// JAVA: import org.mariuszgromada.math.mxparser.*;
// C#: using org.mariuszgromada.math.mxparser;
// ...

// Indirect recursion – approximating sin(x) and cos(x)
Constant a = new Constant("a = 0.001");
Function s = new Function("s(x) = if( abs(x) < a, x, 2*s(x/2)*c(x/2) )", a);
Function c = new Function("c(x) = if( abs(x) < a, 1, c(x/2)^2-s(x/2)^2 )", a);
/*
 * Functions s and c must point to each other,
 * i.e. references should be added only after
 * they have been created
 */
s.addDefinitions(c);
c.addDefinitions(s);

Expression e1 = new Expression("sin(5)-s(5)", s);
Expression e2 = new Expression("cos(5)-c(5)", c);

// Making a copy of e1 and e2
Expression e1c = e1.cloneForThreadSafe();
Expression e2c = e2.cloneForThreadSafe();

// Let's test the behaviour
mXparser.consolePrintln("e1 = " + e1.calculate() + ", e1c = " + e1c.calculate());
mXparser.consolePrintln("e2 = " + e2.calculate() + ", e2c = " + e2c.calculate());
[mXparser-v.5.2.0] e1 = 0.0014644953428659, e1c = 0.0014644953428659
[mXparser-v.5.2.0] e2 = -4.3256817125695E-4, e2c = -4.3256817125695E-4
Nuget – Package Manager

Install-Package MathParser.org-mXparser -Version 6.0.0

Nuget – .NET CLI

dotnet add package MathParser.org-mXparser --version 6.0.0

Nuget – Package Reference

<PackageReference Include="MathParser.org-mXparser" Version="6.0.0"/>

Maven – Dependency

<dependency>
<groupid>
org.mariuszgromada.math</groupid>
<artifactid>
MathParser.org-mXparser</artifactid>
<version>
6.0.0</version>
</dependency>

Maven – Gradle

implementation 'org.mariuszgromada.math:MathParser.org-mXparser:6.0.0'

Maven – Gradle (Kotlin)

implementation("org.mariuszgromada.math:MathParser.org-mXparser:6.0.0")

GitHub

git clone https://github.com/mariuszgromada/MathParser.org-mXparser

OTHER DOWNLOAD OPTIONS

Download latest release – v.6.0.0 Picon: .NET bin onlyDownload latest release – v.6.0.0 Picon: JAVA bin onlyDownload latest release – v.6.0.0 Picon: bin + doc

NEWS FROM MATHPARSER.ORG
SOURCE CODE

Source code .zipSource code .tar.gz
View on GitHubMathSpace.pl

My other creative spaces

DONATION
Did you find the software useful?
Please consider donation 🙂
DONATE