From 374b25212eb3135fc0e808f7206eae7a541d9287 Mon Sep 17 00:00:00 2001 From: Hamlet Tanyavong <34531738+HamletTanyavong@users.noreply.github.com> Date: Sun, 28 Jun 2026 19:10:24 -0500 Subject: [PATCH 1/4] Update Samples.GradientTape.cs --- samples/Samples.GradientTape.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/Samples.GradientTape.cs b/samples/Samples.GradientTape.cs index 8eebf9bf..c591dc1b 100644 --- a/samples/Samples.GradientTape.cs +++ b/samples/Samples.GradientTape.cs @@ -1,9 +1,9 @@ #:package Mathematics.NET +using Mathematics.NET; using Mathematics.NET.AutoDiff; -using Mathematics.NET.Core; -GradientTape tape = new(); +GradientTape, double> tape = new(); var x = tape.CreateVariable(1.0); var y = tape.CreateVariable(2.0); From 68ff6cbfa410eda164b482c28ae82a50b49856c7 Mon Sep 17 00:00:00 2001 From: Hamlet Tanyavong <34531738+HamletTanyavong@users.noreply.github.com> Date: Sun, 28 Jun 2026 19:10:27 -0500 Subject: [PATCH 2/4] Update Samples.OpenCLService.CompMatMul.cs --- samples/Samples.OpenCLService.CompMatMul.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/Samples.OpenCLService.CompMatMul.cs b/samples/Samples.OpenCLService.CompMatMul.cs index 337555db..9d829e12 100644 --- a/samples/Samples.OpenCLService.CompMatMul.cs +++ b/samples/Samples.OpenCLService.CompMatMul.cs @@ -4,7 +4,7 @@ #pragma warning disable EXP0001 using CommunityToolkit.HighPerformance; -using Mathematics.NET.Core; +using Mathematics.NET; using Mathematics.NET.GPU.OpenCL; using Mathematics.NET.LinearAlgebra; using Microsoft.Extensions.Logging; @@ -27,7 +27,7 @@ public static void Compute() var matB = GetMatB(); var result = openCL.CompMatMul(openCL.Devices[0], new(2, 2), new(2, 2), matA, matB); - Console.WriteLine(result.ToDisplayString()); + Console.WriteLine(result.ToString, double, double>()); } private static ILogger CreateLogger() @@ -39,9 +39,9 @@ private static ILogger CreateLogger() return loggerFactory.CreateLogger(); } - private static Span2D GetMatA() + private static Span2D> GetMatA() { - Span2D mat = new Complex[2, 4]; + Span2D> mat = new Complex[2, 4]; for (int i = 0; i < 2; i++) { for (int j = 0; j < 4; j++) @@ -52,9 +52,9 @@ private static Span2D GetMatA() return mat; } - private static Span2D GetMatB() + private static Span2D> GetMatB() { - Span2D mat = new Complex[4, 2]; + Span2D> mat = new Complex[4, 2]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 2; j++) From 24b1aa7d4993fe2189962561fd93612410e5004a Mon Sep 17 00:00:00 2001 From: Hamlet Tanyavong <34531738+HamletTanyavong@users.noreply.github.com> Date: Sun, 28 Jun 2026 20:45:17 -0500 Subject: [PATCH 3/4] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c864a751..f1c874de 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The examples below highlight some of the features of Mathematics.NET. Rational numbers can be created using ```csharp -Rational number = new(4, 6); +Rational number = new(4, 6); ``` Besides the basic arithmetic operations, operations on rational numbers include, but are not limited to, the following: @@ -45,7 +45,7 @@ Support for automatic differentiation (autodiff) is provided by gradient tapes, Reverse-mode automatic differentiation can be performed using gradient tapes. To create a gradient tape, use ```csharp -GradientTape tape = new(); +GradientTape, double> tape = new(); ``` Variables can be created using the `CreateVariable` method. To work with functions of three variables with intial values $x=1.23$, $y=0.66$, and $z=2.34$, write @@ -96,7 +96,7 @@ Console.WriteLine($"df/dz = {gradient[2]}"); We can use Hessian tapes to perform second-order, reverse-mode automatic differentiation. To create a Hessian tape, use ```csharp -HessianTape tape = new(); +HessianTape, double> tape = new(); ``` Then, we can use the `CreateAutoDiffVector` method to create a vector with initial values. Write @@ -139,11 +139,11 @@ tape.ReverseAccumulate(out var gradient, our var hessian); Finally, use those values to compute our Laplacian. ```csharp -var u = Real.One / (x.X1.Value * Real.Sin(x.X2.Value)); // 1 / (r * Sin(θ)) +var u = Real.One / (x.X1.Value * Real.Sin(x.X2.Value)); // 1 / (r * Sin(θ)) var laplacian = 2.0 * gradient[0] / x.X1.Value + hessian[0, 0] + - u * Real.Cos(x.X2.Value) * gradient[1] / x.X1.Value + + u * Real.Cos(x.X2.Value) * gradient[1] / x.X1.Value + hessian[1, 1] / (x.X1.Value * x.X1.Value) + u * u * hessian[2, 2]; From 319503c883d2c9c3d4cacb002e64e7229062d298 Mon Sep 17 00:00:00 2001 From: Hamlet Tanyavong <34531738+HamletTanyavong@users.noreply.github.com> Date: Sun, 28 Jun 2026 23:47:51 -0500 Subject: [PATCH 4/4] Update pages --- .../autodiff/forward-mode-autodiff/page.mdx | 36 ++++++++------ .../autodiff/reverse-mode-autodiff/page.mdx | 48 ++++++++----------- docs/src/app/fundamentals/page.mdx | 22 ++++++--- .../package/autodiff/gradienttape/page.mdx | 25 +++++----- docs/src/app/package/core/complex/page.mdx | 31 ++++++------ .../app/package/solvers/rungekutta4/page.mdx | 18 +++---- 6 files changed, 96 insertions(+), 84 deletions(-) diff --git a/docs/src/app/autodiff/forward-mode-autodiff/page.mdx b/docs/src/app/autodiff/forward-mode-autodiff/page.mdx index f4ba88ca..b6612308 100644 --- a/docs/src/app/autodiff/forward-mode-autodiff/page.mdx +++ b/docs/src/app/autodiff/forward-mode-autodiff/page.mdx @@ -18,14 +18,14 @@ First-order, forward-mode autodiff can be performed using [dual numbers](https:/ Forward-mode autodiff can be performed through the use of dual numbers which keep track of derivatives from our calculations. To create a dual number in Mathematics.NET, we provide a *primal* and *tangent* part; if no tangent part is provided, it will automatically be set to zero. ```csharp -Dual x = new(1.23, 1.0); -Dual y = new(2.34); +Dual, double> x = new(1.23, 1.0); +Dual, double> y = new(2.34); ``` The primal part represents the point at which we want to compute our derivative, while the tangent part holds the information about our derivative. When we create a dual number with a tangent part, we specify a value that will be used as the seed. (It is important to know that the value of the derivative changes proportionally with this value.) We can also write, equivalently, ```csharp -using static Mathematics.NET.AutoDiff.Dual; +using static Mathematics.NET.AutoDiff.Dual, double>; var x = CreateVariable(1.23, 1.0); var y = CreateVariable(2.34); @@ -40,8 +40,8 @@ $$ at the points $ x=1.23 $ and $ y=2.34 $ with respect to $ x $. We write ```csharp -Dual x = CreateVariable(1.23, 1.0); -Dual y = CreateVariable(2.34); +Dual, double> x = CreateVariable(1.23, 1.0); +Dual, double> y = CreateVariable(2.34); var result = Sin(x + y) * Exp(-y) / (x * x + y * y + 1); @@ -51,8 +51,8 @@ Console.WriteLine("∂f/∂x: {0}", result); Notice that we set the seed for the variable of interest, $ x $, to 1 while the seed for the variable we do not care about, $ y $, was set to 0. If we had set both to 1.0, then we would have computed the total derivative of the function instead. To compute the partial derivative of our function with respect to $ y $, we write ```csharp -Dual x = CreateVariable(1.23); -Dual y = CreateVariable(2.34, 1.0); +Dual, double> x = CreateVariable(1.23); +Dual, double> y = CreateVariable(2.34, 1.0); ``` with the tangent part of the variable of interest set to 1 and the other to 0. Doing this will print the following to the console: @@ -67,8 +67,8 @@ with the tangent part of the variable of interest set to 1 and the other to 0. D To get the total derivate of a function, set the seeds for each variable to `1.0`: ```csharp -Dual x = CreateVariable(1.23, 1.0); -Dual y = CreateVariable(2.34, 1.0); +Dual, double> x = CreateVariable(1.23, 1.0); +Dual, double> y = CreateVariable(2.34, 1.0); // Repeat for each variable present ``` @@ -77,7 +77,10 @@ Dual y = CreateVariable(2.34, 1.0); We can create autodiff vectors to help us keep track of multiple dual numbers. ```csharp -AutoDiffVector3 x = new(CreateVariable(1.23), CreateVariable(0.66), CreateVariable(2.34)); +AutoDiffVector3, double>, Real, double> x = new( + CreateVariable(1.23), + CreateVariable(0.66), + CreateVariable(2.34)); ``` We can use this to compute the vector-Jacobian product of the vector functions @@ -95,10 +98,13 @@ $$ with the vector $ v=(0.23,1.57,-1.71) $ at our points $ x_1=1.23 $, $ x_2=0.66 $, and $ x_3=2.34 $ by writing ```csharp -AutoDiffVector3 x = new(CreateVariable(1.23), CreateVariable(0.66), CreateVariable(2.34)); -Vector3 v = new(0.23, 1.57, -1.71); +AutoDiffVector3, double>, Real, double> x = new( + CreateVariable(1.23), + CreateVariable(0.66), + CreateVariable(2.34)); +Vector3, double> v = new(0.23, 1.57, -1.71); -var result = AutoDiffVector3.VJP( +var result = AutoDiffVector3, double>, Real, double>.VJP( v, x => Sin(x.X1) * (Cos(x.X2) + Sqrt(x.X3)), x => Sqrt(x.X1 + x.X2 + x.X3), @@ -125,9 +131,9 @@ $$ with respect to $ z $, at the points $ z=1.23+i0.66 $ and $ w=2.34-i0.25 $. We can do so by writing ```csharp +using Mathematics.NET; using Mathematics.NET.AutoDiff; -using Mathematics.NET.Core; -using static Mathematics.NET.AutoDiff.HyperDual; +using static Mathematics.NET.AutoDiff.HyperDual, double>; var z = CreateVariable(new(1.23, 0.66), 1.0, 1.0); var w = CreateVariable(new(2.34, -0.25)); diff --git a/docs/src/app/autodiff/reverse-mode-autodiff/page.mdx b/docs/src/app/autodiff/reverse-mode-autodiff/page.mdx index e8a3ef90..43c9a3a5 100644 --- a/docs/src/app/autodiff/reverse-mode-autodiff/page.mdx +++ b/docs/src/app/autodiff/reverse-mode-autodiff/page.mdx @@ -20,14 +20,14 @@ Gradient tapes keep track of operations and their contributions to the gradient; First, import the following namespaces: ```csharp {{ title: 'Imports' }} +using Mathematics.NET; using Mathematics.NET.AutoDiff; -using Mathematics.NET.Core; ``` Then, we can create the tape with ```csharp -GradientTape tape = new(); +GradientTape, double> tape = new(); var x = tape.CreateVariable(1.23); ``` @@ -42,7 +42,7 @@ var z = tape.CreateVariable(2.34); To simplify this process, we may instead choose to create a vector of variables. ```csharp -AutoDiffVector3 x = tape.CreateAutoDiffVector(1.23, 0.66, 2.34); +var x = tape.CreateAutoDiffVector(1.23, 0.66, 2.34); ``` Once we are satisfied, we may use these in our equations. @@ -63,7 +63,7 @@ at the point $ x=1.23 $. We can write var result = tape.Divide( tape.Multiply(tape.Sin(x), tape.Ln(x)), tape.Exp( - tape.Multiply(-Real.One, x))); + tape.Multiply(-Real.One, x))); ``` which will give us the value of the function at our specified point. At this moment, the derivative has not been calculated, but we are, however, able to examine the nodes that have been added to our tape. We can use [`LogNodes`](https://github.com/HamletTanyavong/Mathematics.NET/blob/42cb7ec544baafeca6bd842dfb5ddd8634179593/src/Mathematics.NET/AutoDiff/GradientTape.cs#L118) to do so, provided we have a logger. @@ -220,7 +220,7 @@ As before, we can use `ReverseAccumulate` to get our gradients and write them to ```csharp tape.ReverseAccumulate(out var gradient); -Console.WriteLine(gradient.ToDisplayString()); // [-0.8243135949243512, -0.13023459678281554, 0.2382974299363868 ] +Console.WriteLine(gradient.ToString, double, double>()); // [-0.8243135949243512, -0.13023459678281554, 0.2382974299363868 ] ``` which, for clarity, represents the following equations: @@ -258,16 +258,14 @@ $$ and the vector $ \textbf{v} = (0.23, 1.57, -1.71) $ for $ x_1,x_2,x_3>0 $. Here is the code: ```csharp -using Mathematics.NET.AutoDiff; - -GradientTape tape = new(); +GradientTape, double> tape = new(); var x = tape.CreateAutoDiffVector(1.23, 0.66, 2.34); Vector3 v = new(0.23, 1.57, -1.71); _ = tape.JVP(F1, F2, F3, x, v); // f(x, y, z) = Sin(x) * (Cos(y) + Sqrt(z)) -static Variable F1(GradientTape tape, AutoDiffVector3 x) +static Variable F1(GradientTape, double> tape, AutoDiffVector3, double> x) { return tape.Multiply( tape.Sin(x.X1), @@ -275,7 +273,7 @@ static Variable F1(GradientTape tape, AutoDiffVector3 x) } // f(x, y, z) = Sqrt(x + y + z) -static Variable F2(GradientTape tape, AutoDiffVector3 x) +static Variable F2(GradientTape, double> tape, AutoDiffVector3, double> x) { return tape.Sqrt( tape.Add( @@ -284,7 +282,7 @@ static Variable F2(GradientTape tape, AutoDiffVector3 x) } // f(x, y, z) = Sinh(Exp(x) * y / z) -static Variable F3(GradientTape tape, AutoDiffVector3 x) +static Variable F3(GradientTape, double> tape, AutoDiffVector3, double> x) { return tape.Sinh( tape.Multiply( @@ -306,10 +304,7 @@ $$ at the points $ z=1.23+i2.34 $ and $ w=-0.66+i0.23 $. We can write ```csharp -using Mathematics.NET.AutoDiff; -using Mathematics.NET.Core; - -GradientTape tape = new(); +GradientTape, double> tape = new(); var z = tape.CreateVariable(new(1.23, 2.34)); var w = tape.CreateVariable(new(-0.66, 0.23)); @@ -327,7 +322,7 @@ tape.ReverseAccumulate(out var gradient); // The value of the function at the point z = 1.23 + i2.34 and w = -0.66 + i0.23 Console.WriteLine("Value: {0}", result); // The gradient of the function: ∂f/∂z and ∂f/∂w, respectively -Console.WriteLine("Gradient: {0}", gradient.ToDisplayString()); +Console.WriteLine("Gradient: {0}", gradient.ToString, double, double>()); ``` This is similar to the code we would have written in the real number case. (Note that some methods such as `Atan2` are not available for complex gradient tapes.) This outputs the following to the console: @@ -361,17 +356,17 @@ Gradient: [(126.28638563049401, -98.74954259806483), (-38.801295827094066, -109 If there is a function we need that is not provided in the class, we are still able to use it for our gradient tape provided we know its derivative. Suppose, for example, we did not have the `Sin` method. Since we know its derivative is `Cos`, we could write the following: ```csharp -GradientTape tape = new(); +GradientTape, double> tape = new(); var x = tape.CreateVariable(1.23); var result = tape.Operation( - x, // A variable - x => Real.Sin(x), // The function - x => Real.Cos(x)); // The derivative of the function + x, // A variable + x => Real.Sin(x), // The function + x => Real.Cos(x)); // The derivative of the function tape.ReverseAccumulate(out var gradient); Console.WriteLine("Value: {0}", result); -Console.WriteLine("Gradient: {0}", gradient.ToDisplayString()); +Console.WriteLine("Gradient: {0}", gradient.ToString, double, double>()); ``` For custom binary operations in general, we can write @@ -401,7 +396,7 @@ Second-order, reverse-mode autodiff can be performed using [Hessian tapes](https The steps needed to perform second-order, reverse-mode autodiff is similar to the steps needed to perform the first-order case. This time, however, we have access to the following overloads and/or versions of [ReverseAccumulate](https://github.com/HamletTanyavong/Mathematics.NET/blob/42cb7ec544baafeca6bd842dfb5ddd8634179593/src/Mathematics.NET/AutoDiff/HessianTape.cs#L165): ```csharp -HessianTape tape = new(); +HessianTape, double> tape = new(); // Do some math... @@ -433,10 +428,7 @@ $$ we can write ```csharp -using Mathematics.NET.AutoDiff; -using Mathematics.NET.Core; - -HessianTape tape = new(); +HessianTape, double> tape = new(); var x = tape.CreateAutoDiffVector(1.23, 0.66, 0.23); // f(r, θ, ϕ) = cos(r) / ((r + θ) * sin(ϕ)) @@ -449,11 +441,11 @@ _ = tape.Divide( tape.ReverseAccumulate(out var gradient, out var hessian); // Manual Laplacian computation -var u = Real.One / (x.X1.Value * Real.Sin(x.X2.Value)); // 1 / (r * sin(θ)) +var u = Real.One / (x.X1.Value * Real.Sin(x.X2.Value)); // 1 / (r * sin(θ)) var laplacian = 2.0 * gradient[0] / x.X1.Value + hessian[0, 0] + - u * Real.Cos(x.X2.Value) * gradient[1] / x.X1.Value + + u * Real.Cos(x.X2.Value) * gradient[1] / x.X1.Value + hessian[1, 1] / (x.X1.Value * x.X1.Value) + u * u * hessian[2, 2]; diff --git a/docs/src/app/fundamentals/page.mdx b/docs/src/app/fundamentals/page.mdx index 2f2c90f2..a2322a2f 100644 --- a/docs/src/app/fundamentals/page.mdx +++ b/docs/src/app/fundamentals/page.mdx @@ -9,18 +9,16 @@ Learn about the fundamentals of Mathematics.NET below. {{ className: 'lead' }} ## Numeric Types -All numeric types in Mathematics.NET implement the [`IComplex`](https://github.com/HamletTanyavong/Mathematics.NET/blob/main/src/Mathematics.NET/Core/IComplex.cs) interface. Unlike [`INumberBase`](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs), this interface defines the method `Conjugate`, which makes operations that accept either complex or real numbers as parameters more robust. +All numeric types in Mathematics.NET implement the [`IComplex`](https://github.com/HamletTanyavong/Mathematics.NET/blob/main/src/Mathematics.NET/Core/IComplex.cs) interface. Unlike [`INumberBase`](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Numerics/INumberBase.cs), this interface defines the method `Conjugate`, which makes operations that accept either complex or real numbers as parameters more robust. To create a numeric type, users must also specify a backing type that implements the `IBinaryNumber` interface. This means `int`, `BigInteger`, and `double` are all valid backing types. ### Complex Numbers -Because the [complex number type](https://github.com/HamletTanyavong/Mathematics.NET/blob/main/src/Mathematics.NET/Core/Complex.cs) in this library shares the name with .NET's own implementation, use the following statement to avoid conflicts: +Complex numbers are represented by the [Complex](https://github.com/HamletTanyavong/Mathematics.NET/blob/main/src/Mathematics.NET/Core/Complex.cs) type. Basic methods and properties made available include `Conjugate`, `Magnitude`, and `Phase`. To create a complex number, write ```csharp -using Complex = Mathematics.NET.Core.Complex; +Complex z = new(1.23, 4.56); ``` -Basic methods and properties made available include `Conjugate`, `Magnitude`, and `Phase`. -