# Cloning for thread safe operations

## 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.*;
// ...

// Cloning Constant

// Cloning Argument

// Cloning RecursiveArgument

// Cloning Function

// Cloning Expression


## Case 1: Just cloning for a thread safe

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

// Making a copy of y

// 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.*;
// ...
Argument x = new Argument("x = 2");
Argument y = new Argument("y = 2x", x);

// Making a copy of y

// 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.*;
// ...
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

// 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.*;
// ...

// 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
*/

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

// 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 5.2.1

Nuget – .NET CLI

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

Nuget – Package Reference

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

###### Maven – Dependency

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

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

implementation("org.mariuszgromada.math:MathParser.org-mXparser:5.2.1")
git clone https://github.com/mariuszgromada/MathParser.org-mXparser