M2
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
/packages/
|
||||||
|
riderModule.iml
|
||||||
|
/_ReSharper.Caches/
|
||||||
9
Skeleton.csproj
Normal file
9
Skeleton.csproj
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
16
Skeleton.sln
Normal file
16
Skeleton.sln
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Skeleton", "Skeleton.csproj", "{C073F473-21EF-4B03-8CED-253124F292A1}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C073F473-21EF-4B03-8CED-253124F292A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C073F473-21EF-4B03-8CED-253124F292A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C073F473-21EF-4B03-8CED-253124F292A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C073F473-21EF-4B03-8CED-253124F292A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
7
global.json
Normal file
7
global.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"rollForward": "latestMinor",
|
||||||
|
"allowPrerelease": false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.DimensionProviders;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.AdditionalProperties.Extensions;
|
||||||
|
using C22 = CategoryOf<IDim2>.OnField<Complex>.FMatrix;
|
||||||
|
using C33 = CategoryOf<IDim3>.OnField<Complex>.FMatrix;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// extensions for complex matrix
|
||||||
|
/// </summary>
|
||||||
|
public static class ComplexMatrixExtension
|
||||||
|
{
|
||||||
|
|
||||||
|
private struct C22B
|
||||||
|
{
|
||||||
|
public C22B(Complex a, Complex b, Complex c, Complex d)
|
||||||
|
{
|
||||||
|
X11 = a;
|
||||||
|
X12 = b;
|
||||||
|
X21 = c;
|
||||||
|
X22 = d;
|
||||||
|
}
|
||||||
|
public Complex X11;
|
||||||
|
public Complex X12;
|
||||||
|
public Complex X21;
|
||||||
|
public Complex X22;
|
||||||
|
|
||||||
|
public static C22B operator +(C22B a, C22B b) =>
|
||||||
|
new(a.X11 + b.X11, a.X12 + b.X12, a.X21 + b.X21, a.X22 + b.X22);
|
||||||
|
public static C22B operator -(C22B a, C22B b) =>
|
||||||
|
new(a.X11 - b.X11, a.X12 - b.X12, a.X21 - b.X21, a.X22 - b.X22);
|
||||||
|
|
||||||
|
public string PythonString => new C22(X11, X12, X21, X22).PythonRepresentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static C22 FastMul(C22 self, C22 other)
|
||||||
|
{
|
||||||
|
C22 res = new();
|
||||||
|
Complex a = self[1, 1];
|
||||||
|
Complex b = self[1, 2];
|
||||||
|
Complex c = self[2, 1];
|
||||||
|
Complex d = self[2, 2];
|
||||||
|
Complex A = other[1, 1];
|
||||||
|
Complex B = other[2, 1];
|
||||||
|
Complex C = other[1, 2];
|
||||||
|
Complex D = other[2, 2];
|
||||||
|
|
||||||
|
Complex CsD = C - D;
|
||||||
|
Complex cSa = c - a;
|
||||||
|
Complex t = a * A;
|
||||||
|
Complex u = cSa * CsD;
|
||||||
|
Complex v = (c + d) * (C - A);
|
||||||
|
Complex w = t + (cSa + d) * (A - CsD);
|
||||||
|
Complex wPv = w + v;
|
||||||
|
res[1, 1] = t + b* B;
|
||||||
|
res[1, 2] = wPv + (b - d - cSa) * D;
|
||||||
|
Complex wPu = w + u;
|
||||||
|
Complex r21f = B - A + CsD;
|
||||||
|
res[2, 1] = wPu + d * r21f;
|
||||||
|
res[2, 2] = wPu + v;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static C22B FastFullMul(C22B a, C22B b)
|
||||||
|
{
|
||||||
|
Complex CsD = b.X12 - b.X22;
|
||||||
|
Complex cSa = a.X21 - a.X11;
|
||||||
|
Complex t = a.X11 * b.X11;
|
||||||
|
Complex u = cSa * CsD;
|
||||||
|
Complex v = (a.X21 + a.X22) * (b.X12 - b.X11);
|
||||||
|
Complex w = t + (cSa + a.X22) * (b.X11 - CsD);
|
||||||
|
Complex wPv = w + v;
|
||||||
|
Complex wPu = w + u;
|
||||||
|
Complex r21f = b.X21 - b.X11 + CsD;
|
||||||
|
return new(t + a.X12 * b.X21, wPv + (a.X12 - a.X22 - cSa) * b.X22, wPu + a.X22 * r21f, wPu + v);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static C22B FastMulP1(C22B a, C22B b) =>
|
||||||
|
new(a.X11 * b.X11 + a.X12 * b.X21, 0, a.X21 * b.X11 + a.X22 * b.X21, 0);
|
||||||
|
|
||||||
|
private static C22B FastMulP2(C22B a, C22B b) =>
|
||||||
|
new(a.X11 * b.X11 + a.X12 * b.X21, a.X11 * b.X12 + a.X12 * b.X22, 0, 0);
|
||||||
|
|
||||||
|
internal static C33 FastMul(C33 self, C33 other)
|
||||||
|
{
|
||||||
|
C22B a = new(self[1, 1], self[1, 2], self[2, 1], self[2, 2]);
|
||||||
|
C22B A = new(other[1, 1], other[1, 2], other[2, 1], other[2, 2]);
|
||||||
|
C22B CsD = new(other[1, 3] - other[3, 3], 0, other[2, 3], 0);
|
||||||
|
C22B cSa = new(self[3, 1] - self[1, 1], self[3, 2] - self[1, 2], -self[2, 1], -self[2, 2]);
|
||||||
|
C22B CsA = new(other[1, 3] - other[1, 1], -other[1, 2], other[2, 3] - other[2, 1], -other[2, 2]);
|
||||||
|
C22B cPd = new(self[3, 1] + self[3, 3], self[3, 2], 0, 0);
|
||||||
|
C22B Ds_CsA = new(other[3, 3] - other[1, 3] + other[1, 1], other[1, 2], other[2, 1] - other[2, 3], other[2, 2]);
|
||||||
|
C22B t = FastFullMul(a, A);
|
||||||
|
C22B u = FastMulP1(cSa, CsD);
|
||||||
|
C22B v = FastMulP2(cPd, CsA);
|
||||||
|
C22B w = t + FastFullMul(cPd - a, Ds_CsA);
|
||||||
|
C22B wPv = w + v;
|
||||||
|
|
||||||
|
C33 res = new();
|
||||||
|
res[1, 1] = t.X11 + self[1, 3] * other[3, 1];
|
||||||
|
res[1, 2] = t.X12 + self[1, 3] * other[3, 2];
|
||||||
|
res[2, 1] = t.X21 + self[2, 3] * other[3, 1];
|
||||||
|
res[2, 2] = t.X22 + self[2, 3] * other[3, 2];
|
||||||
|
|
||||||
|
res[1, 3] = wPv.X11 + (self[1, 3] - self[3, 3] - cSa.X11) * other[3, 3];
|
||||||
|
res[2, 3] = wPv.X21 + (self[2, 3] - cSa.X21) * other[3, 3];
|
||||||
|
C22B wPu = w + u;
|
||||||
|
res[3, 1] = wPu.X11 + self[3, 3] * (other[3, 1] - other[1, 1] + CsD.X11);
|
||||||
|
res[3, 2] = wPu.X12 + self[3, 3] * (other[3, 2] - other[1, 2] + CsD.X12);
|
||||||
|
res[3, 3] = wPu.X11 + v.X11;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void FastSelfMul(C33 self, C33 other)
|
||||||
|
{
|
||||||
|
C22B a = new(self[1, 1], self[1, 2], self[2, 1], self[2, 2]);
|
||||||
|
C22B A = new(other[1, 1], other[1, 2], other[2, 1], other[2, 2]);
|
||||||
|
C22B CsD = new(other[1, 3] - other[3, 3], 0, other[2, 3], 0);
|
||||||
|
C22B cSa = new(self[3, 1] - self[1, 1], self[3, 2] - self[1, 2], -self[2, 1], -self[2, 2]);
|
||||||
|
C22B CsA = new(other[1, 3] - other[1, 1], -other[1, 2], other[2, 3] - other[2, 1], -other[2, 2]);
|
||||||
|
C22B cPd = new(self[3, 1] + self[3, 3], self[3, 2], 0, 0);
|
||||||
|
C22B Ds_CsA = new(other[3, 3] - other[1, 3] + other[1, 1], other[1, 2], other[2, 1] - other[2, 3], other[2, 2]);
|
||||||
|
C22B t = FastFullMul(a, A);
|
||||||
|
C22B u = FastMulP1(cSa, CsD);
|
||||||
|
C22B v = FastMulP2(cPd, CsA);
|
||||||
|
C22B w = t + FastFullMul(cPd - a, Ds_CsA);
|
||||||
|
C22B wPv = w + v;
|
||||||
|
self[1, 1] = t.X11 + self[1, 3] * other[3, 1];
|
||||||
|
self[1, 2] = t.X12 + self[1, 3] * other[3, 2];
|
||||||
|
self[2, 1] = t.X21 + self[2, 3] * other[3, 1];
|
||||||
|
self[2, 2] = t.X22 + self[2, 3] * other[3, 2];
|
||||||
|
|
||||||
|
self[1, 3] = wPv.X11 + (self[1, 3] - self[3, 3] - cSa.X11) * other[3, 3];
|
||||||
|
self[2, 3] = wPv.X21 + (self[2, 3] - cSa.X21) * other[3, 3];
|
||||||
|
C22B wPu = w + u;
|
||||||
|
self[3, 1] = wPu.X11 + self[3, 3] * (other[3, 1] - other[1, 1] + CsD.X11);
|
||||||
|
self[3, 2] = wPu.X12 + self[3, 3] * (other[3, 2] - other[1, 2] + CsD.X12);
|
||||||
|
self[3, 3] = wPu.X11 + v.X11;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void FastSelfLMul(C33 self, C33 other)
|
||||||
|
{
|
||||||
|
C22B a = new(self[1, 1], self[1, 2], self[2, 1], self[2, 2]);
|
||||||
|
C22B A = new(other[1, 1], other[1, 2], other[2, 1], other[2, 2]);
|
||||||
|
C22B CsD = new(other[1, 3] - other[3, 3], 0, other[2, 3], 0);
|
||||||
|
C22B cSa = new(self[3, 1] - self[1, 1], self[3, 2] - self[1, 2], -self[2, 1], -self[2, 2]);
|
||||||
|
C22B CsA = new(other[1, 3] - other[1, 1], -other[1, 2], other[2, 3] - other[2, 1], -other[2, 2]);
|
||||||
|
C22B cPd = new(self[3, 1] + self[3, 3], self[3, 2], 0, 0);
|
||||||
|
C22B Ds_CsA = new(other[3, 3] - other[1, 3] + other[1, 1], other[1, 2], other[2, 1] - other[2, 3], other[2, 2]);
|
||||||
|
C22B t = FastFullMul(a, A);
|
||||||
|
C22B u = FastMulP1(cSa, CsD);
|
||||||
|
C22B v = FastMulP2(cPd, CsA);
|
||||||
|
C22B w = t + FastFullMul(cPd - a, Ds_CsA);
|
||||||
|
C22B wPv = w + v;
|
||||||
|
|
||||||
|
other[1, 1] = t.X11 + self[1, 3] * other[3, 1];
|
||||||
|
other[1, 2] = t.X12 + self[1, 3] * other[3, 2];
|
||||||
|
other[2, 1] = t.X21 + self[2, 3] * other[3, 1];
|
||||||
|
other[2, 2] = t.X22 + self[2, 3] * other[3, 2];
|
||||||
|
|
||||||
|
other[1, 3] = wPv.X11 + (self[1, 3] - self[3, 3] - cSa.X11) * other[3, 3];
|
||||||
|
other[2, 3] = wPv.X21 + (self[2, 3] - cSa.X21) * other[3, 3];
|
||||||
|
C22B wPu = w + u;
|
||||||
|
other[3, 1] = wPu.X11 + self[3, 3] * (other[3, 1] - A.X11 + CsD.X11);
|
||||||
|
other[3, 2] = wPu.X12 + self[3, 3] * (other[3, 2] - A.X12 + CsD.X12);
|
||||||
|
other[3, 3] = wPu.X11 + v.X11;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void UnitaryFix<TDim>(this CategoryOf<TDim>.OnField<Complex>.FMatrix a)
|
||||||
|
{
|
||||||
|
if (a.Property.IsDiagonal)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= a.Dim; i++)
|
||||||
|
a[i, i] /= (a[i, i] * Complex.Conjugate(a[i, i]));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a[1] = a[1].Normalize;
|
||||||
|
for (int i = 2; i <= a.Dim; i++)
|
||||||
|
{
|
||||||
|
for (int j = 1; j < i; j++)
|
||||||
|
a[i] -= a[i].ProjectionOn(a[j]);
|
||||||
|
a[i] = a[i].Normalize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.DataStructure.Packs.MatrixDecompositions;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.AdditionalProperties.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// additional methods for complex normal matrix
|
||||||
|
/// </summary>
|
||||||
|
public static class ComplexNormalMatrixExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// unitary decomposition of complex normal matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <typeparam name="TDim"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static JDPair<CategoryOf<TDim>.OnField<Complex>.FMatrix> UnitaryDecomposition<TDim>
|
||||||
|
(this CategoryOf<TDim>.OnField<Complex>.FNormalMatrix a, bool order = false)
|
||||||
|
|
||||||
|
{
|
||||||
|
JDPair<CategoryOf<TDim>.OnField<Complex>.FMatrix> res = a.InternalUnitaryDecomposition();
|
||||||
|
if (!order)
|
||||||
|
return res;
|
||||||
|
bool sorted = false;
|
||||||
|
while (!sorted)
|
||||||
|
{
|
||||||
|
sorted = true;
|
||||||
|
for (int i = 1; i < a.Dim; i++)
|
||||||
|
{
|
||||||
|
if (res.D[i, i].Imaginary > res.D[i + 1, i + 1].Imaginary)
|
||||||
|
{
|
||||||
|
sorted = false;
|
||||||
|
res.D.SwapRow(i, i + 1);
|
||||||
|
res.D.SwapColumn(i, i + 1);
|
||||||
|
res.J.SwapColumn(i, i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.AdditionalProperties.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// additional methods for real diagonal matrices
|
||||||
|
/// </summary>
|
||||||
|
public static class RealDiagonalMatrixExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// rayleigh quotient of real diagonal matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double Rayleigh<TDim>
|
||||||
|
(this CategoryOf<TDim>.OnField<double>.FDiagonalMatrix a, CategoryOf<TDim>.OnField<Complex>.FVector b) =>
|
||||||
|
a
|
||||||
|
.ComplexCast<CategoryOf<TDim>.OnField<Complex>.FVector, CategoryOf<TDim>.OnField<Complex>.FMatrix>()
|
||||||
|
.MatrixCast<CategoryOf<TDim>.FHermitianMatrix>()
|
||||||
|
.Rayleigh(b);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.AdditionalProperties.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// additional methods for unitary invariant matrices
|
||||||
|
/// </summary>
|
||||||
|
public static class UnitaryInvariantMatrixExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Conjugated by
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <typeparam name="TDim"></typeparam>
|
||||||
|
/// <typeparam name="TInv"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TInv
|
||||||
|
ConjugatedBy<TDim, TInv>(this IUnitaryInvariantMatrix<TInv> a, CategoryOf<TDim>.FUnitaryMatrix b)
|
||||||
|
where TInv : CategoryOf<TDim>.OnField<Complex>.FMatrix, IUnitaryInvariantMatrix<TInv>, new()
|
||||||
|
=> b.ConjugateOn((a as TInv)!);
|
||||||
|
|
||||||
|
}
|
||||||
11
src/Algebra/AdditionalProperties/IUnitaryInvariantMatrix.cs
Normal file
11
src/Algebra/AdditionalProperties/IUnitaryInvariantMatrix.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Skeleton.Algebra.AdditionalProperties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// matrix property invariant under unitary similarity
|
||||||
|
/// </summary>
|
||||||
|
public interface IUnitaryInvariantMatrix { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public interface IUnitaryInvariantMatrix<TUnitaryInvariant> :
|
||||||
|
IUnitaryInvariantMatrix
|
||||||
|
where TUnitaryInvariant : IUnitaryInvariantMatrix<TUnitaryInvariant>,new() { }
|
||||||
163
src/Algebra/AffineSpaces/AffineSpace.cs
Normal file
163
src/Algebra/AffineSpaces/AffineSpace.cs
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
using Skeleton.Algebra.Matrices;
|
||||||
|
using Skeleton.Algebra.Vectors;
|
||||||
|
using Skeleton.Algebra.VectorSpaces;
|
||||||
|
using Skeleton.DataStructure.Packs;
|
||||||
|
using Skeleton.DataStructure.Packs.LinearSystems;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.AffineSpaces;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// general affine space
|
||||||
|
/// </summary>
|
||||||
|
public abstract class AffineSpace : FixableTensor
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class AffineSpace<TAffine> : AffineSpace
|
||||||
|
where TAffine : AffineSpace<TAffine>, new()
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// intersection of two affine space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="otherSpace"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TAffine Intersection(TAffine otherSpace);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class AffineSpace<TSpace, TAffine> : AffineSpace<TAffine>
|
||||||
|
where TSpace : VectorSpace<TSpace>, new()
|
||||||
|
where TAffine : AffineSpace<TSpace, TAffine>, new()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// underlying vector space
|
||||||
|
/// </summary>
|
||||||
|
public TSpace BaseSpace { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class AffineSpace<TMatrix, TSpace, TAffine> : AffineSpace<TSpace, TAffine>
|
||||||
|
where TMatrix : Matrix<TMatrix>, new()
|
||||||
|
where TSpace : VectorSpace<TMatrix, TSpace>, new()
|
||||||
|
where TAffine : AffineSpace<TMatrix, TSpace, TAffine>, new()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class AffineSpace<TVector, TMatrix, TSpace, TAffine> : AffineSpace<TMatrix, TSpace, TAffine>
|
||||||
|
where TVector : Vector<TVector>, new()
|
||||||
|
where TMatrix : Matrix<TVector, TMatrix>, new()
|
||||||
|
where TSpace : VectorSpace<TVector, TMatrix, TSpace>, new()
|
||||||
|
where TAffine : AffineSpace<TVector, TMatrix, TSpace, TAffine>, new()
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// bias vector
|
||||||
|
/// </summary>
|
||||||
|
public TVector Bias { get; set; } = new();
|
||||||
|
/// <summary>
|
||||||
|
/// if a point is container in the space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool ContainsPoint(TVector p) => BaseSpace.ContainsVector(p - Bias);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// construct
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="s"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
public void Fill(TSpace s, TVector b)
|
||||||
|
{
|
||||||
|
BaseSpace = s;
|
||||||
|
Bias = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// generate affine space from a space and a bias vector
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="s"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TAffine Dispatch(TSpace s, TVector b)
|
||||||
|
{
|
||||||
|
TAffine res = new ();
|
||||||
|
res.Fill(s, b);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// generate affine space from a set of basis and a bias vector
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="basis"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TAffine Dispatch(IEnumerable<TVector> basis, TVector b)
|
||||||
|
{
|
||||||
|
TSpace s = VectorSpace<TVector, TMatrix, TSpace>.Dispatch(basis);
|
||||||
|
return Dispatch(s, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class AffineSpace<TScalar, TVector, TMatrix, TSpace, TAffine> : AffineSpace<TVector, TMatrix, TSpace, TAffine>
|
||||||
|
where TVector : Vector<TScalar, TVector>, new()
|
||||||
|
where TMatrix : Matrix<TScalar, TVector, TMatrix>, new()
|
||||||
|
where TSpace : VectorSpace<TScalar, TVector, TMatrix, TSpace>, new()
|
||||||
|
where TAffine : AffineSpace<TScalar, TVector, TMatrix, TSpace, TAffine>, new()
|
||||||
|
where TScalar : notnull
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public LinearSystem<TScalar, TVector, TMatrix> InverseSystem {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
TSpace otc = BaseSpace.OrthogonalComplementSpace;
|
||||||
|
List<TVector> bs = otc.ToList();
|
||||||
|
while(bs.Count < Dim)
|
||||||
|
bs.Add(new TVector());
|
||||||
|
TMatrix mA = Matrix<TVector, TMatrix>.Dispatch(bs);
|
||||||
|
TVector rs = mA * Bias;
|
||||||
|
return new LinearSystem<TScalar, TVector, TMatrix>(mA, rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override TAffine Intersection(TAffine otherSpace)
|
||||||
|
{
|
||||||
|
LinearSystem<TScalar, TVector, TMatrix> sa = InverseSystem;
|
||||||
|
LinearSystem<TScalar, TVector, TMatrix> sb = otherSpace.InverseSystem;
|
||||||
|
|
||||||
|
ReducedRowEchelonForm<TMatrix> brref = sb.A.RowReduce();
|
||||||
|
TMatrix sam = sa.A;
|
||||||
|
TVector say = sa.Y;
|
||||||
|
TVector sby = brref.RowOperation * sb.Y;
|
||||||
|
TMatrix sbm = brref.ReducedForm;
|
||||||
|
for (int i = 1; i <= sbm.Dim; i++)
|
||||||
|
if (sbm[i].IsEqualApprox(sbm[i].VarZero))
|
||||||
|
{
|
||||||
|
sam[sam.Dim] = sbm[i];
|
||||||
|
say[sam.Dim] = sby[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TVector x = sam.Inv() * say;
|
||||||
|
if ((sbm * x).IsEqualApprox(sby))
|
||||||
|
break;
|
||||||
|
return new TAffine();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReducedRowEchelonForm<TMatrix> rref = sam.RowReduce();
|
||||||
|
say = rref.RowOperation * say;
|
||||||
|
sam = rref.ReducedForm;
|
||||||
|
return sam.SolutionSpace<TSpace, TAffine>(say);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/Algebra/AffineSpaces/FAffineSpace.cs
Normal file
19
src/Algebra/AffineSpaces/FAffineSpace.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Skeleton.Algebra.AffineSpaces;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
public static partial class OnField<TScalar>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class FAffineSpace : AffineSpace<TScalar, FVector, FMatrix, FVectorSpace, FAffineSpace>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FAffineSpace() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => FDim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/Algebra/CategoryOf.cs
Normal file
29
src/Algebra/CategoryOf.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using Skeleton.Algebra.DimensionProviders;
|
||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TDimension"></typeparam>
|
||||||
|
public static partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
private static readonly int FDim = typeof(TDimension).GetCustomAttribute<OfDimension>()!.Dim;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
public static partial class OnField<TScalar> where TScalar : notnull
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Field Structure
|
||||||
|
/// </summary>
|
||||||
|
public static readonly FieldStructure<TScalar> FieldStructure = FieldStructure<TScalar>.Dispatch();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
6
src/Algebra/DimensionProviders/IDim2.cs
Normal file
6
src/Algebra/DimensionProviders/IDim2.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Skeleton.Algebra.DimensionProviders;
|
||||||
|
[OfDimension(2)]
|
||||||
|
public interface IDim2
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
6
src/Algebra/DimensionProviders/IDim3.cs
Normal file
6
src/Algebra/DimensionProviders/IDim3.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Skeleton.Algebra.DimensionProviders;
|
||||||
|
[OfDimension(3)]
|
||||||
|
public interface IDim3
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
6
src/Algebra/DimensionProviders/IDim4.cs
Normal file
6
src/Algebra/DimensionProviders/IDim4.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Skeleton.Algebra.DimensionProviders;
|
||||||
|
[OfDimension(4)]
|
||||||
|
public interface IDim4
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
18
src/Algebra/DimensionProviders/OfDimension.cs
Normal file
18
src/Algebra/DimensionProviders/OfDimension.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Skeleton.Algebra.DimensionProviders;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// provide dimension information for objects
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
|
||||||
|
public class OfDimension : Attribute
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public OfDimension(int dim)
|
||||||
|
{
|
||||||
|
Dim = dim;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// dimension of this class
|
||||||
|
/// </summary>
|
||||||
|
public int Dim { get; }
|
||||||
|
}
|
||||||
256
src/Algebra/Extensions/GeneralExt.cs
Normal file
256
src/Algebra/Extensions/GeneralExt.cs
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
using Skeleton.Utils.Helpers;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static class GeneralExt
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
private static readonly ThreadLocal<Stack<double>> TolCache = new(() => new Stack<double>());
|
||||||
|
|
||||||
|
[ThreadStatic] private static double TolValue;
|
||||||
|
|
||||||
|
private static double Tol => TolCache.Value!.TryPeek(out TolValue) ? TolValue : 1E-8D;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t"></param>
|
||||||
|
public static void SetTol(double t)
|
||||||
|
{
|
||||||
|
TolCache.Value!.Push(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static void ResetTol()
|
||||||
|
{
|
||||||
|
TolCache.Value!.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CZero(this float x)
|
||||||
|
{
|
||||||
|
return Math.Abs(x) < Tol;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CZero(this double x)
|
||||||
|
{
|
||||||
|
return Math.Abs(x) < Tol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool CZero(this Complex x)
|
||||||
|
{
|
||||||
|
return x.Real.CZero() && x.Imaginary.CZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="r"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsEqualApprox(this float l, float r)
|
||||||
|
{
|
||||||
|
return (l - r).CZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="r"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsSignificantlyGreaterThen(this double l, double r)
|
||||||
|
{
|
||||||
|
if (l.IsEqualApprox(r))
|
||||||
|
return false;
|
||||||
|
return l > r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="r"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsSignificantlyLessThen(this double l, double r)
|
||||||
|
{
|
||||||
|
if (l.IsEqualApprox(r))
|
||||||
|
return false;
|
||||||
|
return l < r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="r"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsEqualApprox(this double l, double r)
|
||||||
|
{
|
||||||
|
return (l - r).CZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="r"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsEqualApprox(this Complex l, Complex r)
|
||||||
|
=> l.Real.IsEqualApprox(r.Real) && l.Imaginary.IsEqualApprox(r.Imaginary);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Complex LSum(this IEnumerable<Complex> l)
|
||||||
|
{
|
||||||
|
Complex res = Complex.Zero;
|
||||||
|
foreach (Complex x in l)
|
||||||
|
res += x;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static float LSum(this IEnumerable<float> l)
|
||||||
|
{
|
||||||
|
float res = 0;
|
||||||
|
foreach (float x in l)
|
||||||
|
res += x;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double LSum(this IEnumerable<double> l)
|
||||||
|
{
|
||||||
|
double res = 0;
|
||||||
|
foreach (double x in l)
|
||||||
|
res += x;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Complex LProd(this IEnumerable<Complex> l)
|
||||||
|
{
|
||||||
|
Complex res = Complex.One;
|
||||||
|
foreach (Complex x in l)
|
||||||
|
res *= x;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="k"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool ApproxContains(this IEnumerable<Complex> l, Complex k)
|
||||||
|
{
|
||||||
|
foreach (Complex x in l)
|
||||||
|
if (x.IsEqualApprox(k))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="k"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool ApproxContains(this IEnumerable<float> l, float k)
|
||||||
|
{
|
||||||
|
foreach (float x in l)
|
||||||
|
if (x.IsEqualApprox(k))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="k"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool ApproxContains(this IEnumerable<double> l, double k)
|
||||||
|
{
|
||||||
|
foreach (double x in l)
|
||||||
|
if (x.IsEqualApprox(k))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="r"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Dictionary<Complex, int> RoughGroup(this IEnumerable<Complex> r)
|
||||||
|
{
|
||||||
|
List<List<Complex>> clusters = new List<List<Complex>>();
|
||||||
|
foreach (Complex c in r)
|
||||||
|
{
|
||||||
|
bool added = false;
|
||||||
|
foreach (List<Complex> cluster in clusters)
|
||||||
|
{
|
||||||
|
double distance = cluster.Min(x => (c - x).ManhattanError());
|
||||||
|
if (distance < 1E-6d)
|
||||||
|
{
|
||||||
|
cluster.Add(c);
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!added)
|
||||||
|
clusters.Add(new List<Complex> { c });
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<Complex, int> res = new Dictionary<Complex, int>();
|
||||||
|
foreach (List<Complex> cluster in clusters)
|
||||||
|
{
|
||||||
|
Complex center = cluster.Aggregate((a, b) => a + b) / cluster.Count;
|
||||||
|
res[center] = cluster.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// group complex numbers by count
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Dictionary<TScalar, int> Group<TScalar>(this IEnumerable<TScalar> l)
|
||||||
|
where TScalar : notnull
|
||||||
|
{
|
||||||
|
Dictionary<TScalar, int> res = new ();
|
||||||
|
FieldStructure<TScalar> structure = FieldStructure<TScalar>.Dispatch();
|
||||||
|
foreach (TScalar val in l)
|
||||||
|
{
|
||||||
|
bool exists = false;
|
||||||
|
foreach (TScalar u in res.Keys)
|
||||||
|
if (structure.IsEqualApprox(val, u))
|
||||||
|
{
|
||||||
|
exists = true;
|
||||||
|
res[u] += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!exists)
|
||||||
|
res[val] = 1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/Algebra/FixableObjects/FixableTensor.cs
Normal file
50
src/Algebra/FixableObjects/FixableTensor.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
namespace Skeleton.Algebra.FixableObjects;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// error in tensor might increase as the increased number of calculations
|
||||||
|
/// provide methods to fix this
|
||||||
|
/// </summary>
|
||||||
|
public abstract class FixableTensor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Dimension of the tensor
|
||||||
|
/// </summary>
|
||||||
|
public abstract int Dim { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected FixableTensor() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// if the tensor need to be fixed
|
||||||
|
/// </summary>
|
||||||
|
internal virtual bool NeedFix => false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// fix the tensor
|
||||||
|
/// </summary>
|
||||||
|
internal virtual void Fix()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call abstract/virtual methods in constructor to kill warning
|
||||||
|
/// most derived class's implementation will be called
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static T CancelAbstract<T>(T a) => a;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
internal TFixable FixByPass<TFixable>()
|
||||||
|
where TFixable : FixableTensor
|
||||||
|
{
|
||||||
|
Fix();
|
||||||
|
return (this as TFixable)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
11
src/Algebra/FixableObjects/PostConstructionFixExtension.cs
Normal file
11
src/Algebra/FixableObjects/PostConstructionFixExtension.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Skeleton.Algebra.FixableObjects;
|
||||||
|
|
||||||
|
internal static class PostConstructionFixExtension
|
||||||
|
{
|
||||||
|
internal static void PostConstructionFix<TFixable>(this TFixable obj)
|
||||||
|
where TFixable : FixableTensor
|
||||||
|
{
|
||||||
|
if (obj.GetType() == typeof(TFixable) && obj.NeedFix)
|
||||||
|
obj.Fix();
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/Algebra/Groups/FUnitaryGroup.cs
Normal file
21
src/Algebra/Groups/FUnitaryGroup.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using Skeleton.Algebra.Groups;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public static partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// unitary group
|
||||||
|
/// </summary>
|
||||||
|
public class FUnitaryGroup : Group<FUnitaryMatrix>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override FUnitaryMatrix GroupUnit => FUnitaryMatrix.One;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override FUnitaryMatrix GroupInv(FUnitaryMatrix element) => element.Inv();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override FUnitaryMatrix GroupOperation(FUnitaryMatrix a, FUnitaryMatrix b) => a * b;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/Algebra/Groups/Group.cs
Normal file
46
src/Algebra/Groups/Group.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
namespace Skeleton.Algebra.Groups;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a set of elements closed under group operation
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TElement"></typeparam>
|
||||||
|
public abstract class Group<TElement>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// unit of the group<br/>
|
||||||
|
/// unit * x = x * unit = x for all x in group
|
||||||
|
/// </summary>
|
||||||
|
public abstract TElement GroupUnit { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// inverse of the element under group operation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TElement GroupInv(TElement element);
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TElement GroupOperation(TElement a, TElement b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Commutator of group
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">a</param>
|
||||||
|
/// <param name="b">b</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TElement GroupCommutator(TElement a, TElement b) =>
|
||||||
|
GroupOperation(GroupOperation(a, b), GroupOperation(GroupInv(a), GroupInv(b)));
|
||||||
|
/// <summary>
|
||||||
|
/// a conjugate of b => aba^{-1}
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">a</param>
|
||||||
|
/// <param name="b">b</param>
|
||||||
|
/// <returns>a b a^{-1}</returns>
|
||||||
|
public TElement Conjugation(TElement a, TElement b) =>
|
||||||
|
GroupOperation(a, GroupOperation(b, GroupInv(a)));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
206
src/Algebra/Matrices/FMatrix.cs
Normal file
206
src/Algebra/Matrices/FMatrix.cs
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties.Extensions;
|
||||||
|
using Skeleton.Algebra.DimensionProviders;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
using Skeleton.Algebra.Matrices;
|
||||||
|
using Skeleton.DataStructure.Packs.MatrixDecompositions;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
public static partial class OnField<TScalar>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class FMatrix : Matrix<TScalar, FVector, FMatrix>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FMatrix() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FMatrix(params TScalar[] es) : base(es) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FMatrix(IEnumerable<FVector> es, bool row = true) : base(es, row) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => FDim;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Rank() => Im<FVectorSpace>().Rank;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override JDPair<FMatrix> EigenDecomposition() =>
|
||||||
|
InternalEigenDecomposition<FVectorSpace>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// real part of the matrix<br/>
|
||||||
|
/// homomorphism from field to complex has to be defined
|
||||||
|
/// </summary>
|
||||||
|
public OnField<double>.FMatrix Real =>
|
||||||
|
new(this.Select(row => row.Real));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// imaginary part of the matrix<br/>
|
||||||
|
/// homomorphism from field to complex has to be defined
|
||||||
|
/// </summary>
|
||||||
|
public OnField<double>.FMatrix Imaginary =>
|
||||||
|
new(this.Select(row => row.Imaginary));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// map the matrix to a complex matrix<br/>
|
||||||
|
/// homomorphism from field to complex has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public OnField<Complex>.FMatrix AsComplex() =>
|
||||||
|
new(this.Select(x => x.AsComplex()));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// cast from matrix over K to a matrix over R<br/>
|
||||||
|
/// morphism K -> R has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static explicit operator OnField<double>.FMatrix(FMatrix a) =>
|
||||||
|
new(a.Select(x => (OnField<double>.FVector)x));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// cast from matrix over K to a matrix over C<br/>
|
||||||
|
/// morphism K -> C has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static explicit operator OnField<Complex>.FMatrix(FMatrix a) =>
|
||||||
|
new(a.Select(x => (OnField<Complex>.FVector)x));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// cast from matrix over R to a matrix over K<br/>
|
||||||
|
/// morphism R -> K has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static explicit operator FMatrix(OnField<double>.FMatrix a) =>
|
||||||
|
new(a.Select(x => (FVector)x));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// cast from matrix over C to a matrix over K<br/>
|
||||||
|
/// morphism C -> K has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static explicit operator FMatrix(OnField<Complex>.FMatrix a) =>
|
||||||
|
new(a.Select(x => (FVector)x));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// kernel space
|
||||||
|
/// </summary>
|
||||||
|
public FVectorSpace Ker => Ker<FVectorSpace>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// average of column vectors
|
||||||
|
/// </summary>
|
||||||
|
public FVector ColumnAverage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
FVector res = new();
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
res += this[i, false];
|
||||||
|
return res / FDim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public FVector ColumnAverageBivariant
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
double t = 0;
|
||||||
|
FVector res = new();
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
{
|
||||||
|
double p = Math.Abs(Dim * 0.5 - i);
|
||||||
|
res += this[i, false] * p;
|
||||||
|
t += p;
|
||||||
|
}
|
||||||
|
return res / t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed override void ResetOne()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
{
|
||||||
|
this[i, i] = FieldStructure.MultiplicationUnit;
|
||||||
|
for (int j = 1; j < i; j++)
|
||||||
|
{
|
||||||
|
this[i, j] = FieldStructure.AdditionUnit;
|
||||||
|
this[j, i] = FieldStructure.AdditionUnit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed override void ResetZero()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
{
|
||||||
|
this[i, i] = FieldStructure.AdditionUnit;
|
||||||
|
for (int j = 1; j < i; j++)
|
||||||
|
{
|
||||||
|
this[i, j] = FieldStructure.AdditionUnit;
|
||||||
|
this[j, i] = FieldStructure.AdditionUnit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void SelfMul(FMatrix other)
|
||||||
|
{
|
||||||
|
if (this is CategoryOf<IDim3>.OnField<Complex>.FMatrix c33)
|
||||||
|
{
|
||||||
|
ComplexMatrixExtension.FastSelfMul(c33, (other as CategoryOf<IDim3>.OnField<Complex>.FMatrix)!);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TScalar[] r1 = new TScalar[FDim];
|
||||||
|
TScalar[] r2 = new TScalar[FDim];
|
||||||
|
for (int r = 1; r <= FDim + 1; r++)
|
||||||
|
{
|
||||||
|
for (int c = 1; c <= FDim; c++)
|
||||||
|
{
|
||||||
|
if (r <= FDim)
|
||||||
|
r1[c-1] = this[r] * other[c, false];
|
||||||
|
if (r > 1)
|
||||||
|
this[r - 1, c] = r2[c-1];
|
||||||
|
}
|
||||||
|
(r1, r2) = (r2, r1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void SelfLMul(FMatrix other)
|
||||||
|
{
|
||||||
|
if (this is CategoryOf<IDim3>.OnField<Complex>.FMatrix c33)
|
||||||
|
{
|
||||||
|
ComplexMatrixExtension.FastSelfLMul((other as CategoryOf<IDim3>.OnField<Complex>.FMatrix)!, c33);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TScalar[] c1 = new TScalar[FDim];
|
||||||
|
TScalar[] c2 = new TScalar[FDim];
|
||||||
|
for (int c = 1; c <= FDim + 1; c++)
|
||||||
|
{
|
||||||
|
for (int r = 1; r <= FDim; r++)
|
||||||
|
{
|
||||||
|
if (c <= FDim)
|
||||||
|
c1[r - 1] = this[c, false] * other[r];
|
||||||
|
if (c > 1)
|
||||||
|
this[r, c - 1] = c2[r - 1];
|
||||||
|
}
|
||||||
|
(c1, c2) = (c2, c1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
1312
src/Algebra/Matrices/Matrix.cs
Normal file
1312
src/Algebra/Matrices/Matrix.cs
Normal file
File diff suppressed because it is too large
Load Diff
102
src/Algebra/Matrices/MatrixProperty/MatrixProperty.cs
Normal file
102
src/Algebra/Matrices/MatrixProperty/MatrixProperty.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
using Skeleton.Algebra.Vectors;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.Matrices.MatrixProperty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// test properties of matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
/// <typeparam name="TVector"></typeparam>
|
||||||
|
/// <typeparam name="TMatrix"></typeparam>
|
||||||
|
public class MatrixProperty<TScalar, TVector, TMatrix>
|
||||||
|
where TVector : Vector<TScalar, TVector>, new()
|
||||||
|
where TMatrix : Matrix<TScalar, TVector, TMatrix>, new()
|
||||||
|
where TScalar : notnull
|
||||||
|
{
|
||||||
|
private TMatrix Mat { get; }
|
||||||
|
private static readonly FieldStructure<TScalar> Structure = FieldStructure<TScalar>.Dispatch();
|
||||||
|
internal MatrixProperty(TMatrix m) => Mat = m;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// M[i, j] = 0 if i!= j
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDiagonal => Mat.OffDiagonals
|
||||||
|
.All(x => Structure.IsEqualApprox(x, StaticAccess<TScalar>.AdditionUnit));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// exist of inv(M)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsInvertible => !Structure.IsEqualApprox(Mat.Det(), StaticAccess<TScalar>.AdditionUnit);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// M M* = M* M
|
||||||
|
/// </summary>
|
||||||
|
public bool IsNormal => (Mat * Mat.Hermitian()).IsEqualApprox(Mat.Hermitian() * Mat);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// M = M*
|
||||||
|
/// </summary>
|
||||||
|
public bool IsHermitian => Mat.IsEqualApprox(Mat.Hermitian());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// M[i, j] = 0 for all j < i
|
||||||
|
/// </summary>
|
||||||
|
public bool IsUpperTriangle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
for (int i = 2; i <= Mat.Dim; i++)
|
||||||
|
for (int j = 1; j < i; j++)
|
||||||
|
if (!Structure.IsEqualApprox(Mat[i, j], StaticAccess<TScalar>.AdditionUnit))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// M[i, j] = 0 for all j > i
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLowerTriangle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= Mat.Dim; i++)
|
||||||
|
for (int j = i + 1; j <= Mat.Dim; j++)
|
||||||
|
if (!Structure.IsEqualApprox(Mat[i, j], StaticAccess<TScalar>.AdditionUnit))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// U*U = UU* = I
|
||||||
|
/// </summary>
|
||||||
|
public bool IsUnitary => (Mat * Mat.Hermitian()).IsEqualApprox(Mat.VarOne);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// U + U* = 0
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSkewHermitian => (Mat + Mat.Hermitian()).IsEqualApprox(Mat.VarZero);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tr(M) = 0
|
||||||
|
/// </summary>
|
||||||
|
public bool IsTraceless => Structure.IsEqualApprox(Mat.Trace(), StaticAccess<TScalar>.AdditionUnit);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// M M^T = I
|
||||||
|
/// </summary>
|
||||||
|
public bool IsOrthogonal => (Mat * Mat.Transpose()).IsEqualApprox(Mat.VarOne);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// M = M^T
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSymmetric => Mat.IsEqualApprox(Mat.Transpose());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// M = -M^T
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSkewSymmetric => Mat.IsEqualApprox(-Mat.Transpose());
|
||||||
|
}
|
||||||
79
src/Algebra/Matrices/NormalMatrices/FDiagonalMatrix.cs
Normal file
79
src/Algebra/Matrices/NormalMatrices/FDiagonalMatrix.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
public static partial class OnField<TScalar>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class FDiagonalMatrix : FNormalMatrix
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FDiagonalMatrix()
|
||||||
|
{
|
||||||
|
U = One;
|
||||||
|
D = AsMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FDiagonalMatrix(IEnumerable<FVector> es, bool row = true) : base(es, row) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FDiagonalMatrix(params TScalar[] es)
|
||||||
|
{
|
||||||
|
U = One;
|
||||||
|
if (es.Length == FDim)
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
this[i, i] = es[i - 1];
|
||||||
|
else
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
for (int j = 1; j <= FDim; j++)
|
||||||
|
this[i, j] = es[i - 1 + (j - 1) * FDim];
|
||||||
|
this.PostConstructionFix();
|
||||||
|
}
|
||||||
|
internal override bool NeedFix => base.NeedFix || !Property.IsDiagonal;
|
||||||
|
internal override void Fix()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j <= Dim; j++)
|
||||||
|
{
|
||||||
|
this[i, j] = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
this[j, i] = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// log of the normal matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public FDiagonalMatrix Log()
|
||||||
|
{
|
||||||
|
FDiagonalMatrix res = new();
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
res[i, i] = FieldStructure.Log(this[i, i]);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// exp of the normal matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public FDiagonalMatrix Exp()
|
||||||
|
{
|
||||||
|
FDiagonalMatrix res = new();
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
res[i, i] = FieldStructure.Exp(this[i, i]);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void UnitaryFix(FMatrix a) { }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
99
src/Algebra/Matrices/NormalMatrices/FHermitianMatrix.cs
Normal file
99
src/Algebra/Matrices/NormalMatrices/FHermitianMatrix.cs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties.Extensions;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public static partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class FHermitianMatrix :
|
||||||
|
OnField<Complex>.FNormalMatrix,
|
||||||
|
IUnitaryInvariantMatrix<FHermitianMatrix>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// id hermitian matrix
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly FHermitianMatrix One = new(OnField<Complex>.FMatrix.One);
|
||||||
|
/// <summary>
|
||||||
|
/// zero hermitian matrix
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly FHermitianMatrix Zero = new();
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FHermitianMatrix() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FHermitianMatrix(IEnumerable<OnField<Complex>.FVector> es, bool row = true) : base(es, row) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// addition
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FHermitianMatrix operator +(FHermitianMatrix a, FHermitianMatrix b) => new(a.AsMatrix + b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// scalar multiplication
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">hermitian matrix</param>
|
||||||
|
/// <param name="b">scalar</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FHermitianMatrix operator *(FHermitianMatrix a, double b) => new(a.AsMatrix * b);
|
||||||
|
/// <summary>
|
||||||
|
/// scalar multiplication
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b">hermitian matrix</param>
|
||||||
|
/// <param name="a">scalar</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FHermitianMatrix operator *(double b, FHermitianMatrix a) => a * b;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// rayleigh quotient
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Complex operator /(FHermitianMatrix a, OnField<Complex>.FVector b) => a.Rayleigh(b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rayleigh quotient
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="v"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public double Rayleigh(OnField<Complex>.FVector v)
|
||||||
|
{
|
||||||
|
Complex t = 0;
|
||||||
|
Complex w = 0;
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
{
|
||||||
|
w += v[i] * Complex.Conjugate(v[i]);
|
||||||
|
for (int j = 1; j <= Dim; j++)
|
||||||
|
t += Complex.Conjugate(v[i]) * v[j] * this[j, i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (t / w).Real;
|
||||||
|
}
|
||||||
|
internal override void Fix()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
{
|
||||||
|
for (int j = i+1; j <= Dim; j++)
|
||||||
|
{
|
||||||
|
Complex w = (this[i, j] + Complex.Conjugate(this[j, i])) / 2d;
|
||||||
|
this[i, j] = w;
|
||||||
|
this[j, i] = Complex.Conjugate(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override bool NeedFix => base.NeedFix || !Hermitian().IsEqualApprox(this);
|
||||||
|
|
||||||
|
/*/// <inheritdoc />
|
||||||
|
public override JDPair<OnField<Complex>.FMatrix> EigenDecomposition()
|
||||||
|
=> this.UnitaryDecomposition();*/
|
||||||
|
|
||||||
|
internal override void UnitaryFix(OnField<Complex>.FMatrix a) => a.UnitaryFix();
|
||||||
|
}
|
||||||
|
}
|
||||||
158
src/Algebra/Matrices/NormalMatrices/FLieUnitaryMatrix.cs
Normal file
158
src/Algebra/Matrices/NormalMatrices/FLieUnitaryMatrix.cs
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties.Extensions;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public static partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// equivalence class of Skew hermitian matrices<br/>
|
||||||
|
/// A~B if eigenvalues of A = eigenvalues of B + 2 k pi i
|
||||||
|
/// </summary>
|
||||||
|
public class FLieUnitaryMatrix :
|
||||||
|
OnField<Complex>.FNormalMatrix,
|
||||||
|
IUnitaryInvariantMatrix<FLieUnitaryMatrix>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FLieUnitaryMatrix() { }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FLieUnitaryMatrix(IEnumerable<OnField<Complex>.FVector> es, bool row = true) : base(es, row) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct by unitary matrix and diagonal matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="u"></param>
|
||||||
|
/// <param name="d"></param>
|
||||||
|
public FLieUnitaryMatrix(OnField<Complex>.FMatrix u, OnField<Complex>.FMatrix d) : base(u, d)
|
||||||
|
=> this.PostConstructionFix();
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FLieUnitaryMatrix(params Complex[] es) : base(es) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FLieUnitaryMatrix(OnField<Complex>.FNormalMatrix n) : base(n) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// zero matrix as skew hermitian matrix
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly FLieUnitaryMatrix Zero = new();
|
||||||
|
/// <summary>
|
||||||
|
/// exp of the matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public FUnitaryMatrix Exp()
|
||||||
|
{
|
||||||
|
//JDPair<OnField<Complex>.FMatrix> jd = EigenDecomposition();
|
||||||
|
//FUnitaryMatrix u = jd.J.MatrixCast<FUnitaryMatrix>();
|
||||||
|
FUnitaryMatrix expd = new();
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
expd[i, i] = Complex.Exp(D[i, i]);
|
||||||
|
return new(U, expd);
|
||||||
|
}
|
||||||
|
private bool LieNeedFix
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (U == Zero)
|
||||||
|
return true;
|
||||||
|
return
|
||||||
|
!(this + Hermitian()).IsEqualApprox(Zero) ||
|
||||||
|
!Trace().Real.IsEqualApprox(0) ||
|
||||||
|
D.Diagonals.Any(x => x.Imaginary < -Math.PI || x.Imaginary > Math.PI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override bool NeedFix => base.NeedFix || LieNeedFix;
|
||||||
|
internal static void EigenValueFix(Complex[] eigenValues)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < eigenValues.Length; i++)
|
||||||
|
{
|
||||||
|
double posDiff = eigenValues[i].Imaginary - Math.PI;
|
||||||
|
double negDiff = -eigenValues[i].Imaginary - Math.PI;
|
||||||
|
if (posDiff > 0)
|
||||||
|
eigenValues[i] =
|
||||||
|
(eigenValues[i].Imaginary -
|
||||||
|
(1 + Math.Floor(posDiff / (2 * Math.PI))) * 2 * Math.PI) * Complex.ImaginaryOne;
|
||||||
|
else if (negDiff > 0)
|
||||||
|
eigenValues[i] =
|
||||||
|
(eigenValues[i].Imaginary +
|
||||||
|
(1 + Math.Floor(negDiff / (2 * Math.PI))) * 2 * Math.PI) * Complex.ImaginaryOne;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void UnitaryFix(OnField<Complex>.FMatrix a) => a.UnitaryFix();
|
||||||
|
internal override void InternalFix()
|
||||||
|
{
|
||||||
|
Complex[] eigenValues = D.Diagonals.ToArray();
|
||||||
|
EigenValueFix(eigenValues);
|
||||||
|
for (int i = 0; i < eigenValues.Length; i++)
|
||||||
|
D[i + 1, i + 1] = eigenValues[i].Imaginary * Complex.ImaginaryOne;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// scalar multiplication
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">matrix</param>
|
||||||
|
/// <param name="b">scalar</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FLieUnitaryMatrix operator *(FLieUnitaryMatrix a, double b) =>
|
||||||
|
new(a.AsMatrix * b);
|
||||||
|
/// <summary>
|
||||||
|
/// scalar multiplication
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b">scalar</param>
|
||||||
|
/// <param name="a">matrix</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FLieUnitaryMatrix operator *(double b, FLieUnitaryMatrix a) =>
|
||||||
|
new(a.AsMatrix * b);
|
||||||
|
/// <summary>
|
||||||
|
/// Cayley transformation (I + A)/(I - A)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public FUnitaryMatrix CayleyPositive() => new((One + this) / (One - this));
|
||||||
|
/// <summary>
|
||||||
|
/// Cayley transformation (I - A)/(I + A)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public FUnitaryMatrix CayleyNegative() => new((One - this) / (One + this));
|
||||||
|
/// <summary>
|
||||||
|
/// addition
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FLieUnitaryMatrix operator +(FLieUnitaryMatrix a, FLieUnitaryMatrix b) =>
|
||||||
|
new(a.AsMatrix + b);
|
||||||
|
/// <summary>
|
||||||
|
/// subtraction
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FLieUnitaryMatrix operator -(FLieUnitaryMatrix a, FLieUnitaryMatrix b) =>
|
||||||
|
new(a.AsMatrix - b);
|
||||||
|
/// <summary>
|
||||||
|
/// commutator
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FLieUnitaryMatrix operator ^(FLieUnitaryMatrix a, FLieUnitaryMatrix b) =>
|
||||||
|
new(Commutator(a, b));
|
||||||
|
/// <summary>
|
||||||
|
/// anti commutator
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FHermitianMatrix operator |(FLieUnitaryMatrix a, FLieUnitaryMatrix b) =>
|
||||||
|
new(AntiCommutator(a, b));
|
||||||
|
/*
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override JDPair<OnField<Complex>.FMatrix> EigenDecomposition() =>
|
||||||
|
this.UnitaryDecomposition(true);
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
106
src/Algebra/Matrices/NormalMatrices/FNormalMatrix.cs
Normal file
106
src/Algebra/Matrices/NormalMatrices/FNormalMatrix.cs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
using Skeleton.DataStructure.Packs.MatrixDecompositions;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
public static partial class OnField<TScalar> where TScalar : notnull
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// matrices that commutative with its hermitian
|
||||||
|
/// NN* = N*N
|
||||||
|
/// </summary>
|
||||||
|
public class FNormalMatrix : FMatrix
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unitary matrix
|
||||||
|
/// </summary>
|
||||||
|
public FMatrix U { get; set; } = Zero;
|
||||||
|
/// <summary>
|
||||||
|
/// Diagonal matrix
|
||||||
|
/// </summary>
|
||||||
|
public FMatrix D { get; set; } = Zero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FNormalMatrix() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FNormalMatrix(IEnumerable<FVector> es, bool row = true) : base(es, row) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FNormalMatrix(params TScalar[] es) : base(es) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// construct by unitary matrix and diagonal matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="u">unitary matrix</param>
|
||||||
|
/// <param name="d">diagonal matrix</param>
|
||||||
|
public FNormalMatrix(FMatrix u, FMatrix d)
|
||||||
|
{
|
||||||
|
U = u;
|
||||||
|
D = d;
|
||||||
|
ConstructFromUnitaryAndDiagonal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FNormalMatrix(FNormalMatrix n)
|
||||||
|
{
|
||||||
|
U = n.U;
|
||||||
|
D = n.D;
|
||||||
|
ConstructFromUnitaryAndDiagonal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConstructFromUnitaryAndDiagonal()
|
||||||
|
{
|
||||||
|
ResetOne();
|
||||||
|
SelfMul(U);
|
||||||
|
SelfMul(D);
|
||||||
|
SelfMul(U.Hermitian());
|
||||||
|
}
|
||||||
|
internal override bool NeedFix => U == Zero;
|
||||||
|
internal virtual void UnitaryFix(FMatrix a) { }
|
||||||
|
|
||||||
|
internal override void Fix()
|
||||||
|
{
|
||||||
|
if (U == Zero)
|
||||||
|
{
|
||||||
|
JDPair<FMatrix> jd = InternalUnitaryDecomposition();
|
||||||
|
U = jd.J;
|
||||||
|
D = jd.D;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(U * U.Hermitian()).IsEqualApprox(One))
|
||||||
|
UnitaryFix(U);
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
{
|
||||||
|
for (int j = 1 + 1; j <= FDim; j++)
|
||||||
|
{
|
||||||
|
this[i, j] = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
this[j, i] = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InternalFix();
|
||||||
|
ConstructFromUnitaryAndDiagonal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public new FNormalMatrix Hermitian() => new(U, D.Hermitian());
|
||||||
|
internal virtual void InternalFix() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override JDPair<FMatrix> EigenDecomposition() => new (U, D);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<TScalar> EigenValues() => D.Diagonals;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
111
src/Algebra/Matrices/NormalMatrices/FSpecialLieUnitaryMatrix.cs
Normal file
111
src/Algebra/Matrices/NormalMatrices/FSpecialLieUnitaryMatrix.cs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public static partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// equivalence class of skew hermitian matrices with trace = 2 k pi i
|
||||||
|
/// by A~B if A eigenvalues of A = eigenvalues of B + 2 k pi i
|
||||||
|
/// </summary>
|
||||||
|
public class FSpecialLieUnitaryMatrix :
|
||||||
|
FLieUnitaryMatrix,
|
||||||
|
IUnitaryInvariantMatrix<FSpecialLieUnitaryMatrix>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// zero matrix as skew hermitian matrix with trace = 2 k pi i
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly FSpecialLieUnitaryMatrix Zero = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialLieUnitaryMatrix() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialLieUnitaryMatrix(IEnumerable<OnField<Complex>.FVector> es, bool row = true) :
|
||||||
|
base(es, row) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialLieUnitaryMatrix(params Complex[] es) : base(es) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialLieUnitaryMatrix(OnField<Complex>.FMatrix u, OnField<Complex>.FMatrix d) : base(u, d) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialLieUnitaryMatrix(OnField<Complex>.FNormalMatrix n) : base(n) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
internal override bool NeedFix => base.NeedFix || !Complex.Exp(Trace()).IsEqualApprox(1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// addition of matrices
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">left operand</param>
|
||||||
|
/// <param name="b">right operand</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FSpecialLieUnitaryMatrix operator +(FSpecialLieUnitaryMatrix a, FSpecialLieUnitaryMatrix b) =>
|
||||||
|
new(a.AsMatrix + b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// scalar multiplication<br/>
|
||||||
|
/// LieSU x R -> LieSU
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FSpecialLieUnitaryMatrix operator *(FSpecialLieUnitaryMatrix a, double b) =>
|
||||||
|
new(a.U, a.D * b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// scalar multiplication<br/>
|
||||||
|
/// LieSU x R -> LieSU
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FSpecialLieUnitaryMatrix operator *(double b, FSpecialLieUnitaryMatrix a) => a * b;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// exp of the matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public new FSpecialUnitaryMatrix Exp()
|
||||||
|
{
|
||||||
|
OnField<Complex>.FMatrix expd = new();
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
expd[i, i] = Complex.Exp(D[i, i]);
|
||||||
|
return new(U, expd);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void InternalFix()
|
||||||
|
{
|
||||||
|
base.InternalFix();
|
||||||
|
Complex e = D.Trace();
|
||||||
|
double eMin = e.Imaginary;
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
{
|
||||||
|
double errP = e.Imaginary - i * Math.PI;
|
||||||
|
double errN = e.Imaginary + i * Math.PI;
|
||||||
|
if (Math.Abs(errP) < Math.Abs(eMin))
|
||||||
|
eMin = errP;
|
||||||
|
if (Math.Abs(errN) < Math.Abs(eMin))
|
||||||
|
eMin = errN;
|
||||||
|
}
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
D[i, i] = (D[i, i].Imaginary - eMin / Dim) * Complex.ImaginaryOne;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// commutator
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FSpecialLieUnitaryMatrix operator ^(FSpecialLieUnitaryMatrix a, FSpecialLieUnitaryMatrix b) =>
|
||||||
|
new(Commutator(a, b));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
94
src/Algebra/Matrices/NormalMatrices/FSpecialUnitaryMatrix.cs
Normal file
94
src/Algebra/Matrices/NormalMatrices/FSpecialUnitaryMatrix.cs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public static partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unitary matrices with det = 1
|
||||||
|
/// </summary>
|
||||||
|
public class FSpecialUnitaryMatrix :
|
||||||
|
FUnitaryMatrix,
|
||||||
|
IUnitaryInvariantMatrix<FSpecialUnitaryMatrix>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialUnitaryMatrix() => ResetOne();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialUnitaryMatrix(IEnumerable<OnField<Complex>.FVector> es, bool row = true) : base(es, row) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialUnitaryMatrix(params Complex[] es) : base(es) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialUnitaryMatrix(OnField<Complex>.FNormalMatrix n) : base(n) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FSpecialUnitaryMatrix(OnField<Complex>.FMatrix u, OnField<Complex>.FMatrix d) : base(u, d) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// id matrix as special unitary matrix
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly FSpecialUnitaryMatrix One = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public new FSpecialLieUnitaryMatrix Log()
|
||||||
|
{
|
||||||
|
OnField<Complex>.FMatrix logd = new();
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
logd[i, i] = Complex.Log(D[i, i]);
|
||||||
|
return new(U, logd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public new FSpecialUnitaryMatrix Inv() => Hermitian();
|
||||||
|
|
||||||
|
internal override void InternalFix()
|
||||||
|
{
|
||||||
|
base.InternalFix();
|
||||||
|
Complex det = 1;
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
det *= D[i, i];
|
||||||
|
Complex d = Complex.Pow(1d / det, 1d / Dim);
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
D[i, i] *= d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// transpose + conjugate
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public new FSpecialUnitaryMatrix Hermitian() => new(U, D.Hermitian());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// multiplication
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FSpecialUnitaryMatrix operator *(FSpecialUnitaryMatrix a, FSpecialUnitaryMatrix b) =>
|
||||||
|
new(a.AsMatrix * b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a/b => a b*
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FSpecialUnitaryMatrix operator /(FSpecialUnitaryMatrix a, FSpecialUnitaryMatrix b) =>
|
||||||
|
a * b.Hermitian();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
119
src/Algebra/Matrices/NormalMatrices/FUnitaryMatrix.cs
Normal file
119
src/Algebra/Matrices/NormalMatrices/FUnitaryMatrix.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties;
|
||||||
|
using Skeleton.Algebra.AdditionalProperties.Extensions;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public static partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Matrices whose inverse is its hermitian
|
||||||
|
/// AA* = I = A*A
|
||||||
|
/// </summary>
|
||||||
|
public class FUnitaryMatrix :
|
||||||
|
OnField<Complex>.FNormalMatrix,
|
||||||
|
IUnitaryInvariantMatrix<FUnitaryMatrix>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FUnitaryMatrix() => ResetOne();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FUnitaryMatrix(IEnumerable<OnField<Complex>.FVector> es, bool row = true) : base(es, row) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FUnitaryMatrix(params Complex[] es) : base(es) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FUnitaryMatrix(OnField<Complex>.FMatrix u, OnField<Complex>.FMatrix d) : base(u, d) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FUnitaryMatrix(OnField<Complex>.FNormalMatrix n) : base(n) =>
|
||||||
|
this.PostConstructionFix();
|
||||||
|
/// <summary>
|
||||||
|
/// id matrix as unitary matrix
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly FUnitaryMatrix One = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// inverse of the matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public new FUnitaryMatrix Inv() => Hermitian();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// multiplication between unitary matrices
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FUnitaryMatrix operator *(FUnitaryMatrix self, FUnitaryMatrix other) =>
|
||||||
|
new(self.AsMatrix * other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// transpose + conjugate
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public new FUnitaryMatrix Hermitian() => new(U, D.Hermitian());
|
||||||
|
|
||||||
|
internal override void InternalFix()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
D[i, i] /= D[i, i].Magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool UnitaryNeedFix =>
|
||||||
|
!D.Diagonals.Aggregate((a, b) => a * b).Magnitude.IsEqualApprox(1);
|
||||||
|
internal override bool NeedFix => base.NeedFix || UnitaryNeedFix;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a conjugate on b => a b inv(a)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <typeparam name="TUnitaryInvariant"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TUnitaryInvariant ConjugateOn<TUnitaryInvariant>(TUnitaryInvariant a)
|
||||||
|
where TUnitaryInvariant : OnField<Complex>.FMatrix, IUnitaryInvariantMatrix<TUnitaryInvariant>, new()
|
||||||
|
{
|
||||||
|
TUnitaryInvariant res = new();
|
||||||
|
res.Elements = (this * a * Hermitian()).ToArray();
|
||||||
|
res.Fix();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// conjugate of real is itself<br/>
|
||||||
|
/// so if homomorphism h: R -> K kept the conj<br/>
|
||||||
|
/// h(x) = h(conj(x)) = conj(h(x))<br/>
|
||||||
|
/// h will map real diag matrix to hermitian matrix in K
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public FHermitianMatrix ConjugateOn(OnField<double>.FDiagonalMatrix a)
|
||||||
|
{
|
||||||
|
FHermitianMatrix g = a.AsComplex().MatrixCast<FHermitianMatrix>();
|
||||||
|
return ConjugateOn(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// log of unitary matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public FLieUnitaryMatrix Log()
|
||||||
|
{
|
||||||
|
OnField<Complex>.FMatrix logd = new();
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
logd[i, i] = Complex.Log(D[i, i]);
|
||||||
|
return new(U, logd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*/// <inheritdoc />
|
||||||
|
public override JDPair<OnField<Complex>.FMatrix> EigenDecomposition() => this.UnitaryDecomposition();*/
|
||||||
|
|
||||||
|
internal override void UnitaryFix(OnField<Complex>.FMatrix a) => a.UnitaryFix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
13
src/Algebra/Morphisms/Homomorphism.cs
Normal file
13
src/Algebra/Morphisms/Homomorphism.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Skeleton.Algebra.Morphisms;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a morphism K -> D that preserve some structures of K
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TK"></typeparam>
|
||||||
|
/// <typeparam name="TD"></typeparam>
|
||||||
|
/// <typeparam name="TProperty">property ketp by morphism</typeparam>
|
||||||
|
public class Homomorphism<TK, TD, TProperty> : Morphism<TK, TD>
|
||||||
|
where TProperty : Morphism<TK, TK>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
11
src/Algebra/Morphisms/Isomorphism.cs
Normal file
11
src/Algebra/Morphisms/Isomorphism.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Skeleton.Algebra.Morphisms;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// morphism K -> D that preserve all structures of K
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TK"></typeparam>
|
||||||
|
/// <typeparam name="TD"></typeparam>
|
||||||
|
public class Isomorphism<TK, TD> : Morphism<TK, TD>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
11
src/Algebra/Morphisms/Morphism.cs
Normal file
11
src/Algebra/Morphisms/Morphism.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Skeleton.Algebra.Morphisms;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a map from K to D
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TK"></typeparam>
|
||||||
|
/// <typeparam name="TD"></typeparam>
|
||||||
|
public class Morphism<TK, TD>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
121
src/Algebra/ScalarFieldStructure/ComplexFieldStructure.cs
Normal file
121
src/Algebra/ScalarFieldStructure/ComplexFieldStructure.cs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class ComplexFieldStructure : FieldStructure<Complex>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static readonly ComplexFieldStructure Structure = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Addition(Complex self, Complex other) => self + other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex AdditionUnit => 0d;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Multiplication(Complex self, Complex other) => self * other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex MultiplicationUnit => 1d;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex AdditionInverse(Complex self) => -self;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex MultiplicationInverse(Complex self) => 1d / self;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Subtraction(Complex self, Complex other) => self - other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Division(Complex self, Complex other) => self / other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool IsEqualApprox(Complex self, Complex other, double? absTol = null, double? relTol = null)
|
||||||
|
|
||||||
|
=> RealFieldStructure.Structure.IsEqualApprox(self.Real, other.Real, absTol, relTol) &&
|
||||||
|
RealFieldStructure.Structure.IsEqualApprox(self.Imaginary, other.Imaginary, absTol, relTol);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Fix(Complex x)
|
||||||
|
=> base.Fix(new Complex(
|
||||||
|
RealFieldStructure.Structure.Fix(x.Real),
|
||||||
|
RealFieldStructure.Structure.Fix(x.Imaginary)
|
||||||
|
));
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Conj(Complex self) => Complex.Conjugate(self);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double AsReal(Complex x) => x.Real;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex FromReal(double x) => x;
|
||||||
|
|
||||||
|
private const string PlusSign = "+";
|
||||||
|
private const string EmptyString = "";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string RawRepresentation(Complex x)
|
||||||
|
=> RealFieldStructure.Structure.IsEqualApprox(x.Imaginary, 0d)
|
||||||
|
? RealFieldStructure.Structure.Representation(x.Real)
|
||||||
|
: $"{x.Real}{(x.Imaginary > 0 ? PlusSign : EmptyString)}{x.Imaginary}i";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string RawPythonRepresentation(Complex x)
|
||||||
|
=> RealFieldStructure.Structure.IsEqualApprox(x.Imaginary, 0d)
|
||||||
|
? RealFieldStructure.Structure.Representation(x.Real)
|
||||||
|
: $"{x.Real}{(x.Imaginary > 0 ? PlusSign : EmptyString)}{x.Imaginary}j";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string RawCSharpRepresentation(Complex x)
|
||||||
|
=> RealFieldStructure.Structure.IsEqualApprox(x.Imaginary, 0d)
|
||||||
|
? RealFieldStructure.Structure.Representation(x.Real)
|
||||||
|
: $"{x.Real}{(x.Imaginary >= 0 ? PlusSign : EmptyString)}{x.Imaginary}*AlgebraConstant.I";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string DumpString(Complex x)
|
||||||
|
=> "<C>" +
|
||||||
|
RealFieldStructure.Structure.DumpString(x.Real) +
|
||||||
|
"<CSPLIT/>" +
|
||||||
|
RealFieldStructure.Structure.DumpString(x.Imaginary) +
|
||||||
|
"</C>";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Resolve(string dumpString)
|
||||||
|
{
|
||||||
|
double[] restored = dumpString
|
||||||
|
.Replace("<C>", "")
|
||||||
|
.Replace("</C>", "")
|
||||||
|
.Split("<CSPLIT/>")
|
||||||
|
.Select(x => RealFieldStructure.Structure.Resolve(x))
|
||||||
|
.ToArray();
|
||||||
|
return new Complex(restored[0], restored[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double MaxError(Complex a)
|
||||||
|
=> Math.Max(Math.Abs(a.Real), Math.Abs(a.Imaginary));
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex ComplexCast(Complex a) => a;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex RealMul(Complex a, double b) => a * b;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex SquareRoot(Complex a) => Complex.Sqrt(a);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex FromComplex(Complex a) => a;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Log(Complex x) => Complex.Log(x);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Exp(Complex x) => Complex.Exp(x);
|
||||||
|
}
|
||||||
325
src/Algebra/ScalarFieldStructure/FieldStructure.cs
Normal file
325
src/Algebra/ScalarFieldStructure/FieldStructure.cs
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.DataStructure.Packs;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// operations / structure of the field
|
||||||
|
/// </summary>
|
||||||
|
public abstract class FieldStructure
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class FieldStructure<TScalar> : FieldStructure
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// return the singleton base on type
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static FieldStructure<TScalar> Dispatch()
|
||||||
|
{
|
||||||
|
if (typeof(TScalar) == typeof(double))
|
||||||
|
return (RealFieldStructure.Structure as FieldStructure<TScalar>)!;
|
||||||
|
if (typeof(TScalar) == typeof(Complex))
|
||||||
|
return (ComplexFieldStructure.Structure as FieldStructure<TScalar>)!;
|
||||||
|
return ScalarFieldStructureProvider.GetOperation<TScalar>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FieldStructure()
|
||||||
|
{
|
||||||
|
StaticAccess<TScalar>.AdditionUnit = AdditionUnit;
|
||||||
|
StaticAccess<TScalar>.MultiplicationUnit = MultiplicationUnit;
|
||||||
|
StaticAccess<TScalar>.Structure = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// addition in field
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TScalar Addition(TScalar self, TScalar other);
|
||||||
|
/// <summary>
|
||||||
|
/// addition unit of the field<br/>
|
||||||
|
/// a + unit = a for any a in field
|
||||||
|
/// </summary>
|
||||||
|
public abstract TScalar AdditionUnit { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// multiplication in field
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TScalar Multiplication(TScalar self, TScalar other);
|
||||||
|
/// <summary>
|
||||||
|
/// multiplication unit of the field<br/>
|
||||||
|
/// unit * a = a for any a in the field except the addition unit
|
||||||
|
/// </summary>
|
||||||
|
public abstract TScalar MultiplicationUnit { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// inverse of element under addition<br/>
|
||||||
|
/// a + AddInv(a) = unit(addition) for any a in field
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TScalar AdditionInverse(TScalar self);
|
||||||
|
/// <summary>
|
||||||
|
/// inverse of element under multiplication<br/>
|
||||||
|
/// a * MulInv(a) = unit(multiplication) for any a in field except the addition unit
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TScalar MultiplicationInverse(TScalar self);
|
||||||
|
/// <summary>
|
||||||
|
/// a + AddInv(b)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar Subtraction(TScalar self, TScalar other)
|
||||||
|
=> Addition(self, AdditionInverse(other));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a * MulInv(b)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar Division(TScalar self, TScalar other)
|
||||||
|
=> Multiplication(self, MultiplicationInverse(other));
|
||||||
|
/// <summary>
|
||||||
|
/// conjugate of the scalar
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TScalar Conj(TScalar self);
|
||||||
|
/// <summary>
|
||||||
|
/// if two elements are close to each other in the field
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <param name="absTol"></param>
|
||||||
|
/// <param name="relTol"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract bool IsEqualApprox(TScalar self, TScalar other, double? absTol=null, double? relTol = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tolerance to check if two scalars are close
|
||||||
|
/// </summary>
|
||||||
|
public double AbsoluteTolerance { get; set; } = 1E-8d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public double RelativeTolerance { get; set; } = 1E-5d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// if calculation in field won't introduce error, override this and leave it empty
|
||||||
|
/// otherwise, provide method to reduce the error here
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar Fix(TScalar x)
|
||||||
|
{
|
||||||
|
if (IsEqualApprox(x, AdditionUnit))
|
||||||
|
return AdditionUnit;
|
||||||
|
if (IsEqualApprox(x, MultiplicationUnit))
|
||||||
|
return MultiplicationUnit;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// homomorphism from scalar field to real<br/>
|
||||||
|
/// ignore if not applicable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual double AsReal(TScalar x) => IsEqualApprox(x, AdditionUnit) ? 0 : 1;
|
||||||
|
/// <summary>
|
||||||
|
/// conjugated square xx* when field is real/complex
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public double ConjX2(TScalar x) => AsReal(Multiplication(x, Conj(x)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// homomorphism from real to scalar<br/>
|
||||||
|
/// ignore if not applicable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar FromReal(double x) => x.IsEqualApprox(0) ? AdditionUnit : MultiplicationUnit;
|
||||||
|
/// <summary>
|
||||||
|
/// readable string representation of data
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string Representation(TScalar x) => RawRepresentation(Fix(x));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// representation of the original data, without fix
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual string RawRepresentation(TScalar x) => $"{x}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// code to construct object in python
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string PythonRepresentation(TScalar x) => RawPythonRepresentation(Fix(x));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// code to construct scalar object in python<br/>
|
||||||
|
/// ignore if not applicable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual string RawPythonRepresentation(TScalar x) => "";
|
||||||
|
/// <summary>
|
||||||
|
/// code to construct the object in c#
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string CSharpRepresentation(TScalar x) => RawCSharpRepresentation(Fix(x));
|
||||||
|
/// <summary>
|
||||||
|
/// C# string for the original data
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract string RawCSharpRepresentation(TScalar x);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// dump the object as string which can be restored exactly<br/>
|
||||||
|
/// ignore if not applicable<br/>
|
||||||
|
/// if override can not contain following string as substring<br/>
|
||||||
|
/// <D> </D> <C> </C> <CSPLIT/><br/>
|
||||||
|
/// <VECTOR> <VSPLIT/> </VECTOR><br/>
|
||||||
|
/// <MATRIX> <MSPLIT/> </MSPLIT>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual string DumpString(TScalar x) => "";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// method to restore a value from dump string<br/>
|
||||||
|
/// ignore if not applicable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dumpString"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar Resolve(string dumpString) => AdditionUnit;
|
||||||
|
/// <summary>
|
||||||
|
/// max diff from zero
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract double MaxError(TScalar a);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// homomorphism from field to complex<br/>
|
||||||
|
/// ignore if not applicable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual Complex ComplexCast(TScalar a) => IsEqualApprox(a, AdditionUnit) ? 0 : 1;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// K x R -> K<br/>
|
||||||
|
/// ignore if not applicable
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar RealMul(TScalar a, double b) => a;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// for y in field, find x such that x*x = y
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TScalar SquareRoot(TScalar a);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Absolute value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TScalar Abs(TScalar a) => SquareRoot(Multiplication(a, Conj(a)));
|
||||||
|
/// <summary>
|
||||||
|
/// a x^2 + b x + c = unit(add)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <param name="c"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public QuadraticRoots<TScalar> QuadraticRoot(TScalar a, TScalar b, TScalar c)
|
||||||
|
{
|
||||||
|
TScalar invB = AdditionInverse(b);
|
||||||
|
TScalar b2 = Multiplication(b, b);
|
||||||
|
TScalar ax2 = Addition(a, a);
|
||||||
|
TScalar ac = Multiplication(a, c);
|
||||||
|
TScalar acx2 = Addition(ac, ac);
|
||||||
|
TScalar acx4 = Addition(acx2, acx2);
|
||||||
|
TScalar x1 = Division(Addition(invB, SquareRoot(Subtraction(b2, acx4))), ax2);
|
||||||
|
TScalar x2 = Division(Subtraction(invB, SquareRoot(Subtraction(b2, acx4))), ax2);
|
||||||
|
return new QuadraticRoots<TScalar>(x1, x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TScalar WilkinsonShift(TScalar a1, TScalar b1, TScalar b2, TScalar a2)
|
||||||
|
{
|
||||||
|
QuadraticRoots<TScalar> es = QuadraticRoot(
|
||||||
|
AdditionUnit,
|
||||||
|
AdditionInverse(Addition(a1, a2)),
|
||||||
|
Subtraction(Multiplication(a1, a2), Multiplication(b1, b2))
|
||||||
|
);
|
||||||
|
TScalar k = a2;
|
||||||
|
TScalar s = Addition(Addition(Abs(a1), Abs(b1)), Addition(Abs(b2), Abs(a2)));
|
||||||
|
if (IsEqualApprox(s, AdditionUnit))
|
||||||
|
return k;
|
||||||
|
TScalar q = Multiplication(Division(b1, s), Division(b2, s));
|
||||||
|
|
||||||
|
if (IsEqualApprox(q, AdditionUnit))
|
||||||
|
return k;
|
||||||
|
TScalar p = Division(
|
||||||
|
Subtraction(Division(a1, s), Division(a2, s)),
|
||||||
|
Addition(MultiplicationUnit, MultiplicationUnit)
|
||||||
|
);
|
||||||
|
TScalar r = SquareRoot(Addition(Multiplication(p, p), q));
|
||||||
|
Complex cp = ComplexCast(p);
|
||||||
|
Complex cr = ComplexCast(r);
|
||||||
|
if (cp.Real * cr.Real + cp.Imaginary * cr.Imaginary < 0)
|
||||||
|
r = AdditionInverse(r);
|
||||||
|
k = Subtraction(k, Multiplication(s, Division(q, Addition(p, r))));
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// homomorphism from complex to this field
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar FromComplex(Complex a) => AdditionUnit;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// log of the element in the field
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar Log(TScalar x) => AdditionUnit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// exp of the element in the field
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual TScalar Exp(TScalar x) => MultiplicationUnit;
|
||||||
|
}
|
||||||
|
|
||||||
86
src/Algebra/ScalarFieldStructure/RealFieldStructure.cs
Normal file
86
src/Algebra/ScalarFieldStructure/RealFieldStructure.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class RealFieldStructure : FieldStructure<double>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static readonly RealFieldStructure Structure = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Addition(double self, double other) => self + other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double AdditionUnit => 0d;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Multiplication(double self, double other) => self * other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double MultiplicationUnit => 1d;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double AdditionInverse(double self) => -self;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double MultiplicationInverse(double self) => 1d / self;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Division(double self, double other) => self / other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Subtraction(double self, double other) => self - other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool IsEqualApprox(double self, double other, double? absTol = null, double? relTol = null)
|
||||||
|
{
|
||||||
|
double absTolerance = absTol ?? AbsoluteTolerance;
|
||||||
|
double relTolerance = relTol ?? RelativeTolerance;
|
||||||
|
return Math.Abs(self - other) < absTolerance + relTolerance * Math.Max(Math.Abs(self), Math.Abs(other));
|
||||||
|
}
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Conj(double self) => self;
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double AsReal(double x) => x;
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double FromReal(double x) => x;
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string RawRepresentation(double x) => $"{x}";
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string RawPythonRepresentation(double x) => RawRepresentation(x);
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string RawCSharpRepresentation(double x) => RawRepresentation(x);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string DumpString(double x)
|
||||||
|
=> "<D>" + string.Join(",", BitConverter.GetBytes(x)) + "</D>";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Resolve(string dumpString)
|
||||||
|
=> BitConverter.ToDouble(
|
||||||
|
dumpString
|
||||||
|
.Replace("<D>", "")
|
||||||
|
.Replace("</D>", "")
|
||||||
|
.Split(",")
|
||||||
|
.Select(x => Convert.ToByte(x))
|
||||||
|
.ToArray()
|
||||||
|
);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double MaxError(double a) => Math.Abs(a);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex ComplexCast(double a) => a;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double RealMul(double a, double b) => a * b;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double SquareRoot(double a) => Math.Sqrt(a);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double FromComplex(Complex a) => a.Real;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
namespace Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static class ScalarFieldStructureProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Register customer field structure
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="structure"></param>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
public static void Register<TScalar>(FieldStructure<TScalar> structure)
|
||||||
|
=> Cache[typeof(TScalar)] = structure;
|
||||||
|
|
||||||
|
internal static FieldStructure<TScalar> GetOperation<TScalar>()
|
||||||
|
=> (Cache[typeof(TScalar)] as FieldStructure<TScalar>)!;
|
||||||
|
private static readonly Dictionary<Type, FieldStructure> Cache = new ();
|
||||||
|
}
|
||||||
23
src/Algebra/ScalarFieldStructure/StaticAccess.cs
Normal file
23
src/Algebra/ScalarFieldStructure/StaticAccess.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
namespace Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public static class StaticAccess<T>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static T AdditionUnit { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static T MultiplicationUnit { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static FieldStructure<T> Structure { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
25
src/Algebra/VectorSpaces/FVectorSpace.cs
Normal file
25
src/Algebra/VectorSpaces/FVectorSpace.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
using Skeleton.Algebra.VectorSpaces;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
public static partial class OnField<TScalar> where TScalar : notnull
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class FVectorSpace : VectorSpace<TScalar, FVector, FMatrix, FVectorSpace>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => FDim;
|
||||||
|
internal override FieldStructure<TScalar> Structure => FieldStructure;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FVectorSpace() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FVectorSpace(IEnumerable<FVector> es) : base(es) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
319
src/Algebra/VectorSpaces/VectorSpace.cs
Normal file
319
src/Algebra/VectorSpaces/VectorSpace.cs
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
using Skeleton.Algebra.Matrices;
|
||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
using Skeleton.Algebra.Vectors;
|
||||||
|
using Skeleton.DataStructure.Packs;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.VectorSpaces;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// meta vector space
|
||||||
|
/// </summary>
|
||||||
|
public abstract class VectorSpace : FixableTensor
|
||||||
|
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// number of independent basis
|
||||||
|
/// </summary>
|
||||||
|
public abstract int Rank { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// dimension of complementary space
|
||||||
|
/// </summary>
|
||||||
|
public int Nullity => Dim - Rank;
|
||||||
|
}
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class VectorSpace< TVectorSpace> : VectorSpace
|
||||||
|
|
||||||
|
where TVectorSpace : VectorSpace< TVectorSpace>, new()
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// OTC of the space
|
||||||
|
/// </summary>
|
||||||
|
public abstract TVectorSpace OrthogonalComplementSpace { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// the union vector space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oth"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TVectorSpace UnionWith(TVectorSpace oth);
|
||||||
|
}
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class VectorSpace< TMatrix, TVectorSpace> : VectorSpace< TVectorSpace>
|
||||||
|
|
||||||
|
where TMatrix : Matrix< TMatrix>, new()
|
||||||
|
where TVectorSpace : VectorSpace< TMatrix, TVectorSpace>, new()
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Matrix that transform inner basis to basis
|
||||||
|
/// </summary>
|
||||||
|
protected TMatrix I2OTransformation { get; set; } = new();
|
||||||
|
/// <summary>
|
||||||
|
/// Matrix that transform basis to inner basis
|
||||||
|
/// </summary>
|
||||||
|
protected TMatrix O2ITransformation { get; set; } = new();
|
||||||
|
/// <summary>
|
||||||
|
/// I forgot what is this matrix
|
||||||
|
/// </summary>
|
||||||
|
protected TMatrix LTransformation { get; set; } = new();
|
||||||
|
/// <summary>
|
||||||
|
/// union to vector spaces
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVectorSpace operator +(VectorSpace<TMatrix, TVectorSpace> self, TVectorSpace other)
|
||||||
|
=> self.UnionWith(other);
|
||||||
|
/// <summary>
|
||||||
|
/// intersection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVectorSpace operator *(VectorSpace< TMatrix, TVectorSpace> self, TVectorSpace other)
|
||||||
|
=> (self.OrthogonalComplementSpace + other.OrthogonalComplementSpace).OrthogonalComplementSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="VectorSpace" />
|
||||||
|
public abstract class VectorSpace<TVector, TMatrix, TVectorSpace> : VectorSpace<TMatrix, TVectorSpace>, IEnumerable<TVector>
|
||||||
|
|
||||||
|
where TVector : Vector<TVector>, new()
|
||||||
|
where TMatrix : Matrix<TVector, TMatrix>, new()
|
||||||
|
where TVectorSpace : VectorSpace< TVector, TMatrix, TVectorSpace>, new()
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public VectorSpace() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public VectorSpace(IEnumerable<TVector> es) => Fill(es);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="v"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract bool ContainsVector(TVector v);
|
||||||
|
/// <summary>
|
||||||
|
/// as iterator
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idx"></param>
|
||||||
|
public TVector this[int idx] => Basis[idx];
|
||||||
|
/// <summary>
|
||||||
|
/// basis
|
||||||
|
/// </summary>
|
||||||
|
protected List<TVector> Basis { get; set; } = new();
|
||||||
|
/// <summary>
|
||||||
|
/// Standard basis
|
||||||
|
/// </summary>
|
||||||
|
protected List<TVector> InnerBasis { get; set; } = new();
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override int Rank => Basis.Count;
|
||||||
|
/// <summary>
|
||||||
|
/// init from numerable of vectors
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bs"></param>
|
||||||
|
public void Fill(IEnumerable<TVector> bs)
|
||||||
|
{
|
||||||
|
InnerBasis = new List<TVector>();
|
||||||
|
Basis = new List<TVector>();
|
||||||
|
foreach (TVector b in bs)
|
||||||
|
AddBasis(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// add a basis to the space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="basis"></param>
|
||||||
|
public abstract void AddBasis(TVector basis);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// union with another vector space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oth"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override TVectorSpace UnionWith(TVectorSpace oth)
|
||||||
|
{
|
||||||
|
TVectorSpace res = new TVectorSpace();
|
||||||
|
foreach (TVector b in Basis)
|
||||||
|
res.AddBasis(b);
|
||||||
|
foreach (TVector b in oth.Basis)
|
||||||
|
res.AddBasis(b);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IEnumerator<TVector> GetEnumerator()
|
||||||
|
{
|
||||||
|
foreach (TVector b in Basis)
|
||||||
|
yield return b;
|
||||||
|
}
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// if vector belongs to this space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="oth"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool operator >(VectorSpace< TVector, TMatrix, TVectorSpace> self, TVector oth)
|
||||||
|
=> self.ContainsVector(oth);
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="oth"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static bool operator <(VectorSpace< TVector, TMatrix, TVectorSpace> self, TVector oth)
|
||||||
|
=> throw new Exception("TODO");
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oth"></param>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static bool operator >(TVector oth, VectorSpace< TVector, TMatrix, TVectorSpace> self)
|
||||||
|
=> throw new Exception("TODO");
|
||||||
|
/// <summary>
|
||||||
|
/// if this space contains the vector
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oth"></param>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool operator <(TVector oth, VectorSpace< TVector, TMatrix, TVectorSpace> self)
|
||||||
|
=> self.ContainsVector(oth);
|
||||||
|
/// <summary>
|
||||||
|
/// add a basis to the space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVectorSpace operator +(VectorSpace< TVector, TMatrix, TVectorSpace> self, TVector other)
|
||||||
|
{
|
||||||
|
self.AddBasis(other);
|
||||||
|
return (self as TVectorSpace)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// generate vector space from basis
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="basis"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVectorSpace Dispatch(IEnumerable<TVector> basis)
|
||||||
|
{
|
||||||
|
TVectorSpace res = new();
|
||||||
|
res.Fill(basis);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// meta vector space
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
/// <typeparam name="TVector"></typeparam>
|
||||||
|
/// <typeparam name="TMatrix"></typeparam>
|
||||||
|
/// <typeparam name="TVectorSpace"></typeparam>
|
||||||
|
public abstract class VectorSpace< TScalar, TVector, TMatrix, TVectorSpace> :
|
||||||
|
VectorSpace< TVector, TMatrix, TVectorSpace>
|
||||||
|
where TScalar : notnull
|
||||||
|
where TVector : Vector<TScalar, TVector>, new()
|
||||||
|
where TMatrix : Matrix<TScalar, TVector, TMatrix>, new()
|
||||||
|
where TVectorSpace : VectorSpace<TScalar, TVector, TMatrix, TVectorSpace>, new()
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// constructor
|
||||||
|
/// </summary>
|
||||||
|
protected VectorSpace()
|
||||||
|
{
|
||||||
|
InnerBasis = new List<TVector>();
|
||||||
|
I2OTransformation = new TMatrix();
|
||||||
|
O2ITransformation = new TMatrix();
|
||||||
|
LTransformation = new TMatrix();
|
||||||
|
Basis = new List<TVector>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected VectorSpace(IEnumerable<TVector> es) : base(es) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// check if vector is in the vector space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="v"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override bool ContainsVector(TVector v)
|
||||||
|
{
|
||||||
|
if (Basis.Count == Dim)
|
||||||
|
return true;
|
||||||
|
if (v.IsEqualApprox(v.VarZero))
|
||||||
|
return true;
|
||||||
|
TVector iv = v.Copy();
|
||||||
|
foreach (TVector b in InnerBasis)
|
||||||
|
{
|
||||||
|
int pivot = b.LeadingZeros + 1;
|
||||||
|
iv -= b * iv[pivot] / b[pivot];
|
||||||
|
iv[pivot] = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iv.IsEqualApprox(iv.VarZero);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override void AddBasis(TVector basis)
|
||||||
|
{
|
||||||
|
if (Basis.Count == Dim)
|
||||||
|
return;
|
||||||
|
if (ContainsVector(basis))
|
||||||
|
return;
|
||||||
|
InnerBasis = new List<TVector>();
|
||||||
|
Basis.Add(basis);
|
||||||
|
List<TVector> basisPaddedWithZero = Basis.Select(x => x.Copy()).ToList();
|
||||||
|
while (basisPaddedWithZero.Count < Dim)
|
||||||
|
basisPaddedWithZero.Add(basis.VarZero);
|
||||||
|
TMatrix m = Matrix< TVector, TMatrix>.Dispatch(basisPaddedWithZero);
|
||||||
|
ReducedRowEchelonForm<TMatrix> rowReduceInfo = m.RowReduce();
|
||||||
|
List<TVector> fullSpaceBasis = Basis.Select(x => x).ToList();
|
||||||
|
foreach (TVector kernelBase in m.KerBasis())
|
||||||
|
fullSpaceBasis.Add(kernelBase.Conj());
|
||||||
|
if (fullSpaceBasis.Count != Dim)
|
||||||
|
throw new Exception("Unknown Err");
|
||||||
|
TMatrix changeBasis = Matrix< TVector, TMatrix>.Dispatch(fullSpaceBasis);
|
||||||
|
O2ITransformation = changeBasis.Inv() * rowReduceInfo.ReducedForm;
|
||||||
|
|
||||||
|
LTransformation = rowReduceInfo.RowOperation;
|
||||||
|
int[] np = Utils.Utils
|
||||||
|
.XRange(1, Dim)
|
||||||
|
.Where(x => !rowReduceInfo.Pivots.Contains(x))
|
||||||
|
.ToArray();
|
||||||
|
int kernelDim = 0;
|
||||||
|
for (int r = 1; r <= Dim; r++)
|
||||||
|
if (rowReduceInfo.ReducedForm[r].IsEqualApprox(basis.VarZero))
|
||||||
|
{
|
||||||
|
rowReduceInfo.ReducedForm[r, np[kernelDim]] = Structure.MultiplicationUnit;
|
||||||
|
kernelDim += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InnerBasis.Add(rowReduceInfo.ReducedForm[r]);
|
||||||
|
}
|
||||||
|
|
||||||
|
I2OTransformation = rowReduceInfo.ReducedForm.Inv() * m;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract FieldStructure<TScalar> Structure { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override TVectorSpace OrthogonalComplementSpace
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<TVector> fullSpaceBasis = Basis.Select(x => x).ToList();
|
||||||
|
while (fullSpaceBasis.Count < Dim)
|
||||||
|
fullSpaceBasis.Add(new TVector());
|
||||||
|
return Matrix< TVector, TMatrix>.Dispatch(fullSpaceBasis)
|
||||||
|
.ConjKer<TVectorSpace>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
125
src/Algebra/Vectors/FVector.cs
Normal file
125
src/Algebra/Vectors/FVector.cs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
using Skeleton.Algebra.Vectors;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra;
|
||||||
|
|
||||||
|
public partial class CategoryOf<TDimension>
|
||||||
|
{
|
||||||
|
public static partial class OnField<TScalar>
|
||||||
|
where TScalar : notnull
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class FVector : Vector<TScalar, FVector>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// zero vector
|
||||||
|
/// </summary>
|
||||||
|
public static readonly FVector Zero = new();
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FVector() { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FVector(params TScalar[] es) : base(es) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FVector(IEnumerable<TScalar> es) : base(es) => this.PostConstructionFix();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => FDim;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// real part of the vector<br/>
|
||||||
|
/// homomorphism from field to complex has to be defined
|
||||||
|
/// </summary>
|
||||||
|
public OnField<double>.FVector Real =>
|
||||||
|
new(this.Select(x => FieldStructure.ComplexCast(x).Real));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// imaginary part of the vector<br/>
|
||||||
|
/// homomorphism from field to complex has to be defined
|
||||||
|
/// </summary>
|
||||||
|
public OnField<double>.FVector Imaginary =>
|
||||||
|
new(this.Select(x => Structure.ComplexCast(x).Imaginary));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// map the vector to a complex vector<br/>
|
||||||
|
/// homomorphism from field to complex has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public OnField<Complex>.FVector AsComplex() =>
|
||||||
|
new(this.Select(x => Structure.ComplexCast(x)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// outer product of two vector<br/>
|
||||||
|
/// M = v v*
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public FMatrix OuterProduct(FVector other)
|
||||||
|
{
|
||||||
|
FMatrix res = new();
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
for (int j = 1; j <= FDim; j++)
|
||||||
|
res[i, j] = Structure.Multiplication(this[i], other[j]);
|
||||||
|
res.Fix();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// cast from vector over K to a vector over R<br/>
|
||||||
|
/// morphism K -> R has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static explicit operator OnField<double>.FVector(FVector a) => a.Real;
|
||||||
|
/// <summary>
|
||||||
|
/// cast from vector over K to a vector over C<br/>
|
||||||
|
/// morphism K -> C has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static explicit operator OnField<Complex>.FVector(FVector a) =>
|
||||||
|
new(a.Select(x => FieldStructure.ComplexCast(x)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// cast from vector over R to a vector over K<br/>
|
||||||
|
/// morphism R -> K has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static explicit operator FVector(OnField<double>.FVector a) =>
|
||||||
|
new(a.Select(x => FieldStructure.FromReal(x)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// cast from vector over C to a vector over C<br/>
|
||||||
|
/// morphism C -> K has to be defined
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static explicit operator FVector(OnField<Complex>.FVector a) =>
|
||||||
|
new(a.Select(x => FieldStructure.FromComplex(x)));
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override FieldStructure<TScalar> Structure =>
|
||||||
|
FieldStructure;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override FVector Conj()
|
||||||
|
{
|
||||||
|
TScalar[] ele = new TScalar[FDim];
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
ele[i-1] = FieldStructure.Conj(this[i]);
|
||||||
|
return new(ele);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TScalar Dot(FVector other)
|
||||||
|
{
|
||||||
|
TScalar res = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
for (int i = 1; i <= FDim; i++)
|
||||||
|
res = FieldStructure.Addition(res, FieldStructure.Multiplication(this[i], other[i]));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
499
src/Algebra/Vectors/Vector.cs
Normal file
499
src/Algebra/Vectors/Vector.cs
Normal file
@@ -0,0 +1,499 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.Algebra.FixableObjects;
|
||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
|
||||||
|
namespace Skeleton.Algebra.Vectors;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// meta for 2-4 dim vectors
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Vector : FixableTensor
|
||||||
|
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected Vector() { }
|
||||||
|
/// <summary>
|
||||||
|
/// length of the vector
|
||||||
|
/// </summary>
|
||||||
|
public abstract double Magnitude { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// count leading zeros in the vector
|
||||||
|
/// </summary>
|
||||||
|
public abstract int LeadingZeros { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// count ending zeros in the vector
|
||||||
|
/// </summary>
|
||||||
|
public abstract int EndingZeros { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// reset the vector to zero vector
|
||||||
|
/// </summary>
|
||||||
|
protected abstract void ResetZero();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// fix vector with additional action
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="f"></param>
|
||||||
|
protected void WithFix(Action f)
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public abstract string Representation { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public abstract string PythonRepresentation { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public abstract string CSharpRepresentation { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// string representation of the matrix to create a new instance with the same data
|
||||||
|
/// debug use only
|
||||||
|
/// </summary>
|
||||||
|
public abstract string LatexRepresentation { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// meta for 2-4 dim vectors
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TVector"></typeparam>
|
||||||
|
public abstract class Vector<TVector> : Vector
|
||||||
|
where TVector : Vector<TVector>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// normalize the vector so that length is 1
|
||||||
|
/// </summary>
|
||||||
|
public abstract TVector Normalize { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// get a variable zero vector
|
||||||
|
/// </summary>
|
||||||
|
public abstract TVector VarZero { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// get a copy of this vector
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TVector Copy();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected abstract TVector Addition(TVector other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected abstract TVector Negation();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector operator +(Vector< TVector> self, TVector other) => self.Addition(other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector operator -(Vector< TVector> self) => self.Negation();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OPT Required
|
||||||
|
/// </summary>
|
||||||
|
public static TVector operator -(Vector< TVector> self, TVector other)
|
||||||
|
{
|
||||||
|
return self + -other;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// the projection of this vector on another vector
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TVector ProjectionOn(TVector b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// the rejection of this vector on another vector
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TVector RejectionOn(TVector b) => this - ProjectionOn(b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// if two vectors are close to each other numerically
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract bool IsEqualApprox(TVector other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Conjugate of this vector
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract TVector Conj();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// meta for 2-4 dim vector
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
/// <typeparam name="TVector"></typeparam>
|
||||||
|
public abstract class Vector<TScalar, TVector> : Vector<TVector>, IEnumerable<TScalar>
|
||||||
|
where TVector : Vector<TScalar,TVector>, new()
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected Vector(IEnumerable<TScalar> elements)
|
||||||
|
{
|
||||||
|
Elements = elements.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected Vector() => Elements = new TScalar[Dim];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected TScalar[] Elements { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index"></param>
|
||||||
|
public TScalar this[int index]
|
||||||
|
{
|
||||||
|
get => Elements[index - 1];
|
||||||
|
set => Elements[index - 1] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IEnumerator<TScalar> GetEnumerator()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Dim; i++)
|
||||||
|
yield return Elements[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void ResetZero()
|
||||||
|
{
|
||||||
|
Elements = new TScalar[Dim];
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
Elements[i] = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected abstract TScalar Dot(TVector other);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector operator *(Vector< TScalar, TVector> self, TScalar other)
|
||||||
|
{
|
||||||
|
TVector res = new ();
|
||||||
|
for (int i = 1; i <= self.Dim; i++)
|
||||||
|
res[i] = res.Structure.Multiplication(self[i], other);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector operator *(TScalar other, Vector< TScalar, TVector> self) => self * other!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector operator /(Vector< TScalar, TVector> self, TScalar other)
|
||||||
|
{
|
||||||
|
TVector res = new TVector();
|
||||||
|
for (int i = 1; i <= self.Dim; i++)
|
||||||
|
res[i] = res.Structure.Division(self[i], other);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector operator /(Vector< TScalar, TVector> self, double other)
|
||||||
|
=> self / self.Structure.FromReal(other)!;
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector operator *(Vector< TScalar, TVector> self, double other)
|
||||||
|
=> self * self.Structure.FromReal(other)!;
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TScalar operator *(Vector< TScalar, TVector> self, TVector other) => self.Dot(other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// if this vector is linear dependent with another vector v
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="v"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsLinearDependantWith(TVector v)
|
||||||
|
{
|
||||||
|
bool started = false;
|
||||||
|
TScalar comDiv = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
for (int i = 1; i <= v.Dim; i++)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
Structure.IsEqualApprox(v[i], StaticAccess<TScalar>.AdditionUnit) &&
|
||||||
|
Structure.IsEqualApprox(this[i], StaticAccess<TScalar>.AdditionUnit)
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
if (Structure.IsEqualApprox(v[i], StaticAccess<TScalar>.AdditionUnit))
|
||||||
|
return false;
|
||||||
|
TScalar ratio = Structure.Division(this[i], v[i]);
|
||||||
|
if (!started)
|
||||||
|
comDiv = ratio;
|
||||||
|
else if (!Structure.IsEqualApprox(comDiv, ratio))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// field structure
|
||||||
|
/// </summary>
|
||||||
|
protected abstract FieldStructure<TScalar> Structure { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override bool IsEqualApprox(TVector other)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
if (!Structure.IsEqualApprox(this[i], other[i]))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected sealed override TVector Negation()
|
||||||
|
{
|
||||||
|
TVector res = new TVector();
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
res[i] = Structure.AdditionInverse(this[i]);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected sealed override TVector Addition(TVector other)
|
||||||
|
{
|
||||||
|
TVector res = new();
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
res[i] = Structure.Addition(this[i], other[i]);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override TVector Copy()
|
||||||
|
{
|
||||||
|
TVector res = new();
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
res[i] = this[i];
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Fix()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
this[i] = Structure.Fix(this[i]);
|
||||||
|
base.Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override int EndingZeros
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= Dim; i++)
|
||||||
|
if (!Structure.IsEqualApprox(Elements[^(i + 1)], StaticAccess<TScalar>.AdditionUnit))
|
||||||
|
return i;
|
||||||
|
return Dim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override int LeadingZeros {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
for(int i = 0;i<Dim; i++)
|
||||||
|
if (!Structure.IsEqualApprox(Elements[i], StaticAccess<TScalar>.AdditionUnit))
|
||||||
|
return i;
|
||||||
|
return Dim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*/// <inheritdoc />
|
||||||
|
public override TVector Conj()
|
||||||
|
{
|
||||||
|
TVector res = new();
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
res[i] = Structure.Conj(this[i]);
|
||||||
|
return res;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override TVector ProjectionOn(TVector b)
|
||||||
|
{
|
||||||
|
TVector bconj = b.Conj();
|
||||||
|
return Structure.Division(this * bconj, b * bconj)! * b;
|
||||||
|
}
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override double Magnitude
|
||||||
|
=> Math.Sqrt(Elements.Sum(x => Structure.ConjX2(x)));
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override TVector Normalize => (
|
||||||
|
Magnitude.IsEqualApprox(0) ? this as TVector : this / Magnitude
|
||||||
|
)!;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Representation =>
|
||||||
|
string.Join(",\t", Elements.Select(x => Structure.Representation(x)));
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string PythonRepresentation
|
||||||
|
=> "np.matrix([" + string.Join(",", Elements.Select(x => Structure.PythonRepresentation(x))) + "])";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string CSharpRepresentation
|
||||||
|
=> $"new {GetType().Name} (" +
|
||||||
|
string.Join(",", Elements.Select(x => Structure.CSharpRepresentation(x))) +
|
||||||
|
");";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string LatexRepresentation
|
||||||
|
=> "\\begin{pmatrix}" +
|
||||||
|
string.Join('&', Elements.Select(x => Structure.Representation(x))) +
|
||||||
|
"\\end{pmatrix}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// generate vector from elements
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elements"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector Dispatch(IEnumerable<TScalar> elements)
|
||||||
|
{
|
||||||
|
TVector res = new ()
|
||||||
|
{
|
||||||
|
Elements = elements.ToArray()
|
||||||
|
};
|
||||||
|
res.PostConstructionFix();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// save object to string
|
||||||
|
/// </summary>
|
||||||
|
public string DumpString
|
||||||
|
=> "<VECTOR>" +
|
||||||
|
string.Join("<VSPLIT/>", Elements.Select(x => Structure.DumpString(x))) +
|
||||||
|
"</VECTOR>";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dumpString"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static TVector Resolve(string dumpString)
|
||||||
|
{
|
||||||
|
TVector res = new ();
|
||||||
|
res.Elements = dumpString
|
||||||
|
.Replace("<VECTOR>", "")
|
||||||
|
.Replace("</VECTOR>", "")
|
||||||
|
.Split("<VSPLIT/>")
|
||||||
|
.Select(x => FieldStructure<TScalar>.Dispatch().Resolve(x))
|
||||||
|
.ToArray();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public double MaxError => this.Select(x => Structure.MaxError(x)).Max();
|
||||||
|
|
||||||
|
internal TComplexVector ComplexCast<TComplexVector>()
|
||||||
|
where TComplexVector : Vector<Complex, TComplexVector>, new()
|
||||||
|
=> Vector< Complex, TComplexVector>.Dispatch(Elements.Select(Structure.ComplexCast));
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public sealed override TVector VarZero
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
TVector res = new();
|
||||||
|
res.Elements = Enumerable.Range(0, Dim).Select(_ => StaticAccess<TScalar>.AdditionUnit).ToArray();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// make the vector a (dim - d) vector
|
||||||
|
/// V[i] = 0 for all i<=d
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="d"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TVector UpTruncateBy(int d)
|
||||||
|
{
|
||||||
|
TVector res = Copy();
|
||||||
|
for (int i = 1; i <= d; i++)
|
||||||
|
res[i] = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// make the vector a d-1 dimensional vector
|
||||||
|
/// V[i] = 0 for all i>=d
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="d"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TVector DownTruncateBy(int d)
|
||||||
|
{
|
||||||
|
TVector res = Copy();
|
||||||
|
for (int i = d; i < Dim; i++)
|
||||||
|
res[i] = StaticAccess<TScalar>.AdditionUnit;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// addition
|
||||||
|
/// </summary>
|
||||||
|
public class AnalyticAddition : Analytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left"></param>
|
||||||
|
/// <param name="right"></param>
|
||||||
|
public AnalyticAddition(Analytic left, Analytic right)
|
||||||
|
{
|
||||||
|
Left = left;
|
||||||
|
Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Analytic Left { get; }
|
||||||
|
private Analytic Right { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// d (f+g)/dx
|
||||||
|
/// </summary>
|
||||||
|
public override Analytic Derivative => Left.Derivative + Right.Derivative;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [f+g](x)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return Left.Evaluate(x) + Right.Evaluate(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/Analysis/AnalyticFunctions/Arithmetics/AnalyticApply.cs
Normal file
39
src/Analysis/AnalyticFunctions/Arithmetics/AnalyticApply.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// f(x),g(x) -> f(g(x))
|
||||||
|
/// </summary>
|
||||||
|
public class AnalyticApply : Analytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="outer"></param>
|
||||||
|
/// <param name="inner"></param>
|
||||||
|
public AnalyticApply(Analytic outer, Analytic inner)
|
||||||
|
{
|
||||||
|
Outer = outer;
|
||||||
|
Inner = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Analytic Outer { get; }
|
||||||
|
private Analytic Inner { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// d(f(g(x)))/dx
|
||||||
|
/// </summary>
|
||||||
|
public override Analytic Derivative => Inner.Derivative * Outer.Derivative[Inner];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// f(g(x))
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return Outer.Evaluate(Inner.Evaluate(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// C
|
||||||
|
/// </summary>
|
||||||
|
public class AnalyticConstant : Analytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// zero
|
||||||
|
/// </summary>
|
||||||
|
public static readonly AnalyticConstant Zero = new(0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// one
|
||||||
|
/// </summary>
|
||||||
|
public static readonly AnalyticConstant One = new(1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="c"></param>
|
||||||
|
public AnalyticConstant(Complex c)
|
||||||
|
{
|
||||||
|
Constant = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Complex Constant { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// dc/dx = 0
|
||||||
|
/// </summary>
|
||||||
|
public override Analytic Derivative => Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// c(x) = c
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return Constant;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// f(x) = x
|
||||||
|
/// </summary>
|
||||||
|
public class AnalyticIdentity : Analytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// dx/dx = 1
|
||||||
|
/// </summary>
|
||||||
|
public override Analytic Derivative => AnalyticConstant.One;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// x = x
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// -f
|
||||||
|
/// </summary>
|
||||||
|
public class AnalyticNegation : Analytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element"></param>
|
||||||
|
public AnalyticNegation(Analytic element)
|
||||||
|
{
|
||||||
|
Element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Analytic Element { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// d[-f]/dx = -df/dx
|
||||||
|
/// </summary>
|
||||||
|
public override Analytic Derivative => -Element.Derivative;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [-f](x) = -x
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return -Element.Evaluate(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// f(x), g(x) -> f(x)g(x)
|
||||||
|
/// </summary>
|
||||||
|
public class AnalyticProduction : Analytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left"></param>
|
||||||
|
/// <param name="right"></param>
|
||||||
|
public AnalyticProduction(Analytic left, Analytic right)
|
||||||
|
{
|
||||||
|
Left = left;
|
||||||
|
Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Analytic Left { get; }
|
||||||
|
private Analytic Right { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// dfg/dx = fdg/dx + gdf/dx
|
||||||
|
/// </summary>
|
||||||
|
public override Analytic Derivative => Left.Derivative * Right + Left * Right.Derivative;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// f(x)*g(x)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return Left.Evaluate(x) * Right.Evaluate(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/Analysis/AnalyticFunctions/IAnalytic.cs
Normal file
19
src/Analysis/AnalyticFunctions/IAnalytic.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public interface IAnalytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
Analytic Derivative { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Complex Evaluate(Complex x);
|
||||||
|
}
|
||||||
63
src/Analysis/AnalyticFunctions/Implements/Analytic.cs
Normal file
63
src/Analysis/AnalyticFunctions/Implements/Analytic.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Arithmetics;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// analytic functions
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Analytic : IAnalytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// f(g)(x) -> f(g(x))
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inner"></param>
|
||||||
|
public Analytic this[Analytic inner] => new AnalyticApply(this, inner);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// df/dx
|
||||||
|
/// </summary>
|
||||||
|
public abstract Analytic Derivative { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// f(x)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract Complex Evaluate(Complex x);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [f+g](x) = f(x) + g(x)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Analytic operator +(Analytic a, Analytic b)
|
||||||
|
=> new AnalyticAddition(a, b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [-f](x) = -f(x)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Analytic operator -(Analytic a)
|
||||||
|
=> new AnalyticNegation(a);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [f-g](x) = f(x) - g(x)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Analytic operator -(Analytic a, Analytic b)
|
||||||
|
=> -b + a;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [fg](x) = f(x)g(x)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Analytic operator *(Analytic a, Analytic b)
|
||||||
|
=> new AnalyticProduction(a, b);
|
||||||
|
}
|
||||||
29
src/Analysis/AnalyticFunctions/Polynomials/IPolynomial.cs
Normal file
29
src/Analysis/AnalyticFunctions/Polynomials/IPolynomial.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public interface IPolynomial : IAnalytic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
int Dim { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
int Degree { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
Complex[] Coefficients { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
BivariantContinuous Re { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
BivariantContinuous Im { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// p = a0
|
||||||
|
/// </summary>
|
||||||
|
public class C0Polynomial : Polynomial
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a0"></param>
|
||||||
|
public C0Polynomial(Complex a0)
|
||||||
|
{
|
||||||
|
Coefficients = new[] { a0 };
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a0
|
||||||
|
/// </summary>
|
||||||
|
public Complex A0 => Coefficients[0];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 0
|
||||||
|
/// </summary>
|
||||||
|
public override Polynomial Derivative => Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// real part
|
||||||
|
/// </summary>
|
||||||
|
public override BivariantContinuous Re => new BivariantContinuousConstant(A0.Real);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// imaginary part
|
||||||
|
/// </summary>
|
||||||
|
public override BivariantContinuous Im => new BivariantContinuousConstant(A0.Imaginary);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// string for debug
|
||||||
|
/// </summary>
|
||||||
|
public override string Representation => $"{A0.Real} + {A0.Imaginary}i";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => 0;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<Complex> Roots => Array.Empty<Complex>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return A0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// p(x) = a0 + a1 x
|
||||||
|
/// </summary>
|
||||||
|
public class C1Polynomial : Polynomial
|
||||||
|
{
|
||||||
|
private static readonly BivariantContinuous X = BivariantContinuous.X;
|
||||||
|
private static readonly BivariantContinuous Y = BivariantContinuous.Y;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public C1Polynomial()
|
||||||
|
{
|
||||||
|
Coefficients = new Complex[2];
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public C1Polynomial(Complex a0, Complex a1)
|
||||||
|
{
|
||||||
|
Coefficients = new[] { a0, a1 };
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Complex A0 => Coefficients[0];
|
||||||
|
private Complex A1 => Coefficients[1];
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Representation => $"{A0.Real} + {A0.Imaginary}i + ({A1.Real} + {A1.Imaginary}i)x";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => 1;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Polynomial Derivative => new C0Polynomial(A1);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<Complex> Roots => new[] { -A0 / A1 };
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Re => A0.Real + A1.Real * X - A1.Imaginary * Y;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Im => A0.Imaginary + A1.Real * Y + A1.Imaginary * X;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return A0 + x * A1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.PolynomialHelpers;
|
||||||
|
using Skeleton.Utils.Helpers;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class C2Polynomial : Polynomial
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public C2Polynomial()
|
||||||
|
{
|
||||||
|
Coefficients = new Complex[3];
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public C2Polynomial(Complex a0, Complex a1, Complex a2)
|
||||||
|
{
|
||||||
|
Coefficients = new[] { a0, a1, a2 };
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A0 => Coefficients[0];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A1 => Coefficients[1];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A2 => Coefficients[2];
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Representation =>
|
||||||
|
$"{A0.Real} + {A0.Imaginary}i + ({A1.Real} + {A1.Imaginary}i)x + ({A2.Real} + {A2.Imaginary}i)x2";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => 2;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Polynomial Derivative => new C1Polynomial(A1, A2 * 2);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<Complex> Roots => Decorators.WithTol(1E-20,
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if (A2.IsEqualApprox(0))
|
||||||
|
return new C1Polynomial(A0, A1).Roots;
|
||||||
|
if (A0.IsEqualApprox(0))
|
||||||
|
return new C1Polynomial(A1, A2).Roots.Concat(new[] { Complex.Zero });
|
||||||
|
Complex x1 = (-A1 + Complex.Sqrt(A1 * A1 - 4 * A2 * A0)) / (2 * A2);
|
||||||
|
Complex x2 = (-A1 - Complex.Sqrt(A1 * A1 - 4 * A2 * A0)) / (2 * A2);
|
||||||
|
return new[] { x1, x2 };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Re => new PolyCHelper.PolyC2Re(A0, A1, A2);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Im => new PolyCHelper.PolyC2Im(A0, A1, A2);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return A0 + x * (A1 + x * A2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.PolynomialHelpers;
|
||||||
|
using Skeleton.Utils.Helpers;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class C3Polynomial : Polynomial
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public C3Polynomial()
|
||||||
|
{
|
||||||
|
Coefficients = new Complex[4];
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public C3Polynomial(Complex a0, Complex a1, Complex a2, Complex a3)
|
||||||
|
{
|
||||||
|
Coefficients = new[] { a0, a1, a2, a3 };
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A0 => Coefficients[0];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A1 => Coefficients[1];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A2 => Coefficients[2];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A3 => Coefficients[3];
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => 3;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Polynomial Derivative => new C2Polynomial(A1, A2 * 2, A3 * 3);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<Complex> Roots =>
|
||||||
|
Decorators.WithTol(1E-20, () =>
|
||||||
|
{
|
||||||
|
if (A3.IsEqualApprox(0))
|
||||||
|
return new C2Polynomial(A0, A1, A2).Roots;
|
||||||
|
if (A0.IsEqualApprox(0))
|
||||||
|
return new C2Polynomial(A1, A2, A3).Roots.Concat(new[] { Complex.Zero });
|
||||||
|
Polynomial gcd = GreatestCommonDivisor(Derivative);
|
||||||
|
if (!gcd.IsConstant)
|
||||||
|
{
|
||||||
|
Polynomial div = LongDivision(gcd).Quotient;
|
||||||
|
return div.Roots.Concat(gcd.Roots);
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex a = A3;
|
||||||
|
Complex b = A2;
|
||||||
|
Complex c = A1;
|
||||||
|
Complex d = A0;
|
||||||
|
Complex D0 = b * b - 3d * a * c;
|
||||||
|
Complex D1 = 2d * b * b * b - 9d * a * b * c + 27d * a * a * d;
|
||||||
|
if (D0.IsEqualApprox(0) && D1.IsEqualApprox(0))
|
||||||
|
{
|
||||||
|
Complex root = -b / (a * 3d);
|
||||||
|
return new[] { root, root, root };
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex C = Complex.Pow((D1 + Complex.Sqrt(D1 * D1 - 4d * D0 * D0 * D0)) / 2d, 1d / 3d);
|
||||||
|
if (C.IsEqualApprox(0))
|
||||||
|
C = Complex.Pow((D1 - Complex.Sqrt(D1 * D1 - 4d * D0 * D0 * D0)) / 2d, 1d / 3d);
|
||||||
|
if (C.IsEqualApprox(0))
|
||||||
|
throw new Exception($"Unknown situation with {a}, {b}, {c}, {d}"); //TODO
|
||||||
|
Complex ee = (-1d + Complex.Sqrt(-3d)) / 2d;
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
-1d / (3d * a) * (b + C + D0 / C),
|
||||||
|
-1d / (3d * a) * (b + ee * C + D0 / (ee * C)),
|
||||||
|
-1d / (3d * a) * (b + ee * ee * C + D0 / (ee * ee * C))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Re => new PolyCHelper.PolyC3Re(A0, A1, A2, A3);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Im => new PolyCHelper.PolyC3Im(A0, A1, A2, A3);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Representation =>
|
||||||
|
$"{A0.Real} + {A0.Imaginary}i + ({A1.Real} + {A1.Imaginary}i)x + ({A2.Real} + {A2.Imaginary}i)x2 + ({A3.Real} + {A3.Imaginary}i)X3";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
{
|
||||||
|
return A0 + x * (A1 + x * (A2 + x * A3));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.PolynomialHelpers;
|
||||||
|
using Skeleton.Utils.Helpers;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class C4Polynomial : Polynomial
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public C4Polynomial()
|
||||||
|
{
|
||||||
|
Coefficients = new Complex[5];
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public C4Polynomial(Complex a0, Complex a1, Complex a2, Complex a3, Complex a4)
|
||||||
|
{
|
||||||
|
Coefficients = new[] { a0, a1, a2, a3, a4 };
|
||||||
|
Fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A0 => Coefficients[0];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A1 => Coefficients[1];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A2 => Coefficients[2];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A3 => Coefficients[3];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Complex A4 => Coefficients[4];
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => 4;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Polynomial Derivative => new C3Polynomial(A1, A2 * 2, A3 * 3, A4 * 4);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<Complex> Roots =>
|
||||||
|
Decorators.WithTol(1e-20, () =>
|
||||||
|
{
|
||||||
|
if (A4.IsEqualApprox(Complex.Zero))
|
||||||
|
return new C3Polynomial(A0, A1, A2, A3).Roots;
|
||||||
|
if (A0.IsEqualApprox(Complex.Zero))
|
||||||
|
return new C3Polynomial(A1, A2, A3, A4).Roots.Concat(new[] { Complex.Zero });
|
||||||
|
if (A3.IsEqualApprox(Complex.Zero) && A1.IsEqualApprox(Complex.Zero))
|
||||||
|
return new C2Polynomial(A0, A2, A4).Roots
|
||||||
|
.SelectMany(x => new[] { Complex.Sqrt(x), -Complex.Sqrt(x) });
|
||||||
|
|
||||||
|
|
||||||
|
Polynomial gcd = GreatestCommonDivisor(Derivative);
|
||||||
|
if (!gcd.IsConstant)
|
||||||
|
{
|
||||||
|
Polynomial div = LongDivision(gcd).Quotient;
|
||||||
|
return div.Roots.Concat(gcd.Roots);
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex a = A4;
|
||||||
|
Complex b = A3;
|
||||||
|
Complex c = A2;
|
||||||
|
Complex d = A1;
|
||||||
|
Complex e = A0;
|
||||||
|
Complex P = (c * c + 12d * a * e - 3d * b * d) / 9d;
|
||||||
|
Complex Q = (27d * a * d * d + 2d * c * c * c + 27d * b * b * e - 72d * a * c * e - 9d * b * c * d) / 54d;
|
||||||
|
Complex D = Complex.Sqrt(Q * Q - P * P * P);
|
||||||
|
Complex ua = Complex.Pow(Q + D, 1d / 3d);
|
||||||
|
Complex ub = Complex.Pow(Q - D, 1d / 3d);
|
||||||
|
Complex u = Complex.Abs(ua) > Complex.Abs(ub) ? ua : ub;
|
||||||
|
Complex v = u.IsEqualApprox(0d) ? 0d : P / u;
|
||||||
|
Complex omega = -0.5d + Complex.Sqrt(3d) * Complex.ImaginaryOne / 2d;
|
||||||
|
|
||||||
|
Complex m(int k)
|
||||||
|
{
|
||||||
|
return Complex.Sqrt(b * b - 8d / 3d * a * c +
|
||||||
|
4d * a * (Utils.Utils.IterPow(omega, k - 1) * u +
|
||||||
|
Utils.Utils.IterPow(omega, 4 - k) * v));
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex S(int k)
|
||||||
|
{
|
||||||
|
return 2d * b * b - 16d / 3d * a * c -
|
||||||
|
4d * a * (Utils.Utils.IterPow(omega, k - 1) * u + Utils.Utils.IterPow(omega, 4 - k) * v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = new[] { 1, 2, 3 }.MaxBy(x => m(x).Magnitude);
|
||||||
|
Complex mm = m(i);
|
||||||
|
Complex SS = S(i);
|
||||||
|
Complex T = 0;
|
||||||
|
if (mm.Magnitude.IsEqualApprox(0))
|
||||||
|
{
|
||||||
|
mm = 0;
|
||||||
|
SS = b * b - 8d / 3d * a * c;
|
||||||
|
T = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T = (8d * a * b * c - 16d * a * a * d - 2d * b * b * b) / mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex x(int i)
|
||||||
|
{
|
||||||
|
return (-b + Utils.Utils.SPow(Math.Ceiling(i / 2f)) * mm + Utils.Utils.SPow(i + 1) *
|
||||||
|
Complex.Sqrt(SS + Utils.Utils.SPow(Math.Ceiling(i / 2f)) * T)) /
|
||||||
|
(4d * a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new[] { x(1), x(2), x(3), x(4) };
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Re => new PolyCHelper.PolyC4Re(A0, A1, A2, A3, A4);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Im => new PolyCHelper.PolyC4Im(A0, A1, A2, A3, A4);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Representation =>
|
||||||
|
$"{A0.Real} + {A0.Imaginary}i + ({A1.Real} + {A1.Imaginary}i)x + ({A2.Real} + {A2.Imaginary}i)x2 + ({A3.Real} + {A3.Imaginary}i)X3 + ({A4.Real} + {A4.Imaginary}i)x4";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
=> A0 + x * (A1 + x * (A2 + x * (A3 + x * A4)));
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class GeneralPolynomial : Polynomial
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public GeneralPolynomial(int dim, Complex[] coefficients)
|
||||||
|
{
|
||||||
|
PDim = dim;
|
||||||
|
Coefficients = new Complex[dim + 1];
|
||||||
|
for (int i = 0; i <= Dim; i++)
|
||||||
|
Coefficients[i] = coefficients[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int PDim { get; }
|
||||||
|
public override IEnumerable<Complex> Roots { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int Dim => PDim;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Re { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Im { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,262 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.Extensions;
|
||||||
|
using Skeleton.Algebra.ScalarFieldStructure;
|
||||||
|
using Skeleton.Analysis.AnalyticFunctions.Implements;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
using Skeleton.DataStructure.Packs;
|
||||||
|
using Skeleton.Utils.Helpers;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Polynomial : Analytic, IPolynomial
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected static readonly Polynomial Zero = new C0Polynomial(0);
|
||||||
|
|
||||||
|
private static readonly Polynomial One = new C0Polynomial(1);
|
||||||
|
private static readonly Polynomial X = new C1Polynomial(0, 1);
|
||||||
|
private static readonly Polynomial X2 = new C2Polynomial(0, 0, 1);
|
||||||
|
private static readonly Polynomial X3 = new C3Polynomial(0, 0, 0, 1);
|
||||||
|
private static readonly Polynomial X4 = new C4Polynomial(0, 0, 0, 0, 1);
|
||||||
|
private bool IsZero => Decorators.WithTol(1e-30, () => Coefficients.All(x => x.IsEqualApprox(Complex.Zero)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public bool IsConstant =>
|
||||||
|
Decorators.WithTol(1E-30, () => Coefficients.Skip(1).All(x => x.IsEqualApprox(Complex.Zero)));
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Polynomial Derivative
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Complex[] coeff = new Complex[Dim];
|
||||||
|
for (int i = 1; i <= Dim; i++)
|
||||||
|
coeff[i - 1] = Coefficients[i] * i;
|
||||||
|
return Dispatch(coeff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public virtual string Representation =>
|
||||||
|
string.Join(
|
||||||
|
" + ",
|
||||||
|
Coefficients
|
||||||
|
.Zip(Enumerable.Range(0, Degree + 1))
|
||||||
|
.Select(
|
||||||
|
x
|
||||||
|
=> "(" +
|
||||||
|
ComplexFieldStructure.Structure.Representation(x.First) +
|
||||||
|
$")x^{x.Second}"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public abstract IEnumerable<Complex> Roots { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract int Dim { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public int Degree
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= Dim; i++)
|
||||||
|
if (Coefficients[^(i + 1)] != Complex.Zero)
|
||||||
|
return Dim - i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Complex[] Coefficients { get; set; } = Array.Empty<Complex>();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract BivariantContinuous Re { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract BivariantContinuous Im { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="coefficients"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static Polynomial Dispatch(Complex[] coefficients)
|
||||||
|
{
|
||||||
|
return coefficients.Length switch
|
||||||
|
{
|
||||||
|
1 => new C0Polynomial(coefficients[0]),
|
||||||
|
2 => new C1Polynomial(coefficients[0], coefficients[1]),
|
||||||
|
3 => new C2Polynomial(coefficients[0], coefficients[1], coefficients[2]),
|
||||||
|
4 => new C3Polynomial(coefficients[0], coefficients[1], coefficients[2], coefficients[3]),
|
||||||
|
5 => new C4Polynomial(coefficients[0], coefficients[1], coefficients[2], coefficients[3], coefficients[4]),
|
||||||
|
_ => new GeneralPolynomial(coefficients.Length - 1, coefficients)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator +(Polynomial a, Complex b) => a + new C0Polynomial(b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator +(Complex b, Polynomial a) => a + b;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator -(Polynomial a, Complex b) => a + new C0Polynomial(-b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator +(Polynomial a, Polynomial b)
|
||||||
|
{
|
||||||
|
int d = Math.Max(a.Degree, b.Degree);
|
||||||
|
int md = Math.Min(a.Degree, b.Degree);
|
||||||
|
Polynomial lp = new[] { a, b }.MaxBy(p => p.Degree)!;
|
||||||
|
Complex[] coefficients = new Complex[d + 1];
|
||||||
|
for (int i = 0; i <= d; i++)
|
||||||
|
if (i <= md)
|
||||||
|
coefficients[i] = a.Coefficients[i] + b.Coefficients[i];
|
||||||
|
else
|
||||||
|
coefficients[i] = lp.Coefficients[i];
|
||||||
|
return Dispatch(coefficients);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator -(Polynomial a)
|
||||||
|
=> Dispatch(a.Coefficients.Select(x => -x).ToArray());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator -(Polynomial a, Polynomial b) => -b + a;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator *(Polynomial a, Complex b)
|
||||||
|
=> Dispatch(a.Coefficients.Select(x => x * b).ToArray());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator *(Complex b, Polynomial a) => a * b;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Polynomial operator /(Polynomial a, Complex b)
|
||||||
|
=> Dispatch(a.Coefficients.Select(x => x / b).ToArray());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static Polynomial operator *(Polynomial a, Polynomial b)
|
||||||
|
{
|
||||||
|
int cd = a.Degree + b.Degree;
|
||||||
|
if (cd > 4)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
Complex[] coefficients = new Complex[cd + 1];
|
||||||
|
for (int i = 0; i <= a.Degree; i++)
|
||||||
|
for (int j = 0; j <= b.Degree; j++)
|
||||||
|
coefficients[i + j] += a.Coefficients[i] * b.Coefficients[j];
|
||||||
|
return Dispatch(coefficients);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public PolynomialDivisionResult LongDivision(Polynomial a)
|
||||||
|
{
|
||||||
|
if (a.Degree > Degree)
|
||||||
|
return new PolynomialDivisionResult(Zero, a);
|
||||||
|
Complex leadingC = Coefficients[Degree] / a.Coefficients[a.Degree];
|
||||||
|
int degreeDifference = Degree - a.Degree;
|
||||||
|
Polynomial q = leadingC * new Xd(degreeDifference);
|
||||||
|
Complex[] rCoefficients = Coefficients.Select(x => x).ToArray();
|
||||||
|
rCoefficients[Degree] = 0;
|
||||||
|
Polynomial r = Dispatch(rCoefficients); //this - q * a;
|
||||||
|
if (r.Degree < a.Degree || (r.Degree == 0 && a.Degree == 0))
|
||||||
|
return new PolynomialDivisionResult(q, r);
|
||||||
|
PolynomialDivisionResult rDiv = r.LongDivision(a);
|
||||||
|
return new PolynomialDivisionResult(q + rDiv.Quotient, rDiv.Remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Polynomial GreatestCommonDivisor(Polynomial o)
|
||||||
|
{
|
||||||
|
Polynomial g, l;
|
||||||
|
if (Degree > o.Degree)
|
||||||
|
{
|
||||||
|
g = this;
|
||||||
|
l = o;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g = o;
|
||||||
|
l = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!l.IsZero)
|
||||||
|
{
|
||||||
|
PolynomialDivisionResult div = g.LongDivision(l); // = g.LongDivision(l);
|
||||||
|
g = l;
|
||||||
|
l = div.Remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected void Fix()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Dim; i++)
|
||||||
|
Coefficients[i] = ComplexFieldStructure.Structure.Fix(Coefficients[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Complex Evaluate(Complex x)
|
||||||
|
=> Enumerable
|
||||||
|
.Range(0, Degree + 1)
|
||||||
|
.Reverse()
|
||||||
|
.Select(i => Coefficients[i])
|
||||||
|
.Aggregate((x1, x2) => x1 * x + x2);
|
||||||
|
}
|
||||||
13
src/Analysis/AnalyticFunctions/Polynomials/Implements/Xd.cs
Normal file
13
src/Analysis/AnalyticFunctions/Polynomials/Implements/Xd.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// x^d
|
||||||
|
/// </summary>
|
||||||
|
public class Xd : GeneralPolynomial
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Xd(int degree) : base(degree, new Complex[degree + 1])
|
||||||
|
=> Coefficients[^1] = 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousAddition : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public BivariantContinuousAddition(BivariantContinuous left, BivariantContinuous right)
|
||||||
|
{
|
||||||
|
Left = left;
|
||||||
|
Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BivariantContinuous Left { get; }
|
||||||
|
private BivariantContinuous Right { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => Left.Dx + Right.Dx;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => Left.Dy + Right.Dy;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousConstant : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuousConstant COne = new(1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuousConstant CZero = new(0);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public BivariantContinuousConstant(double c)
|
||||||
|
{
|
||||||
|
Constant = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double Constant { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => CZero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => CZero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return Constant;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousIdentityX : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => BivariantContinuousConstant.COne;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => BivariantContinuousConstant.CZero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y) => x;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousIdentityY : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => BivariantContinuousConstant.CZero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => BivariantContinuousConstant.COne;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y) => y;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousNegation : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public BivariantContinuousNegation(BivariantContinuous e) => Element = e;
|
||||||
|
|
||||||
|
private BivariantContinuous Element { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => -Element.Dx;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => -Element.Dy;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y) => -Element.Evaluate(x, y);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousProduction : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public BivariantContinuousProduction(BivariantContinuous l, BivariantContinuous r)
|
||||||
|
{
|
||||||
|
Left = l;
|
||||||
|
Right = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BivariantContinuous Left { get; }
|
||||||
|
private BivariantContinuous Right { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => Left.Dx * Right + Left * Right.Dx;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => Left.Dy * Right + Left * Right.Dy;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return Left.Evaluate(x, y) * Right.Evaluate(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousX2 : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => 2 * X;
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => Zero;
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y) => x * x;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousX3 : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => 3 * X2;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => Zero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return x * x * x;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousX4 : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => 4 * X3;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => Zero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return x * x * x * x;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousY2 : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => Zero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => 2 * Y;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return y * y;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousY3 : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => Zero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => 3 * Y2;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return y * y * y;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class BivariantContinuousY4 : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => Zero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => 4 * Y3;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return y * y * y * y;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/Analysis/BivariantFunctions/Real/IBivariantContinuous.cs
Normal file
23
src/Analysis/BivariantFunctions/Real/IBivariantContinuous.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public interface IBivariantContinuous
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
BivariantContinuous Dx { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
BivariantContinuous Dy { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <param name="y"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
double Evaluate(double x, double y);
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public abstract class BivariantContinuous : IBivariantContinuous
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous X = new BivariantContinuousIdentityX();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous Y = new BivariantContinuousIdentityY();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous Zero = BivariantContinuousConstant.CZero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous One = BivariantContinuousConstant.COne;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous X2 = new BivariantContinuousX2();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous Y2 = new BivariantContinuousY2();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous X3 = new BivariantContinuousX3();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous Y3 = new BivariantContinuousY3();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous X4 = new BivariantContinuousX4();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly BivariantContinuous Y4 = new BivariantContinuousY4();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract double Evaluate(double x, double y);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract BivariantContinuous Dx { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract BivariantContinuous Dy { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator +(BivariantContinuous a, BivariantContinuous b)
|
||||||
|
{
|
||||||
|
return new BivariantContinuousAddition(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator -(BivariantContinuous a)
|
||||||
|
{
|
||||||
|
return new BivariantContinuousNegation(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator -(BivariantContinuous a, BivariantContinuous b)
|
||||||
|
{
|
||||||
|
return -b + a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator *(BivariantContinuous a, BivariantContinuous b)
|
||||||
|
{
|
||||||
|
return new BivariantContinuousProduction(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator +(BivariantContinuous a, double b)
|
||||||
|
{
|
||||||
|
return a + new BivariantContinuousConstant(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator +(double b, BivariantContinuous a)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator -(BivariantContinuous a, double b)
|
||||||
|
{
|
||||||
|
return a + new BivariantContinuousConstant(-b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator -(double a, BivariantContinuous b)
|
||||||
|
{
|
||||||
|
return new BivariantContinuousConstant(a) - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator *(BivariantContinuous a, double b)
|
||||||
|
{
|
||||||
|
return a * new BivariantContinuousConstant(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static BivariantContinuous operator *(double b, BivariantContinuous a)
|
||||||
|
{
|
||||||
|
return a * b;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,435 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Arithmetics;
|
||||||
|
using Skeleton.Analysis.BivariantFunctions.Real.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.BivariantFunctions.Real.PolynomialHelpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static class PolyCHelper
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class PolyC4Re : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC4Re(Complex c0, Complex c1, Complex c2, Complex c3, Complex c4)
|
||||||
|
{
|
||||||
|
A0 = c0.Real;
|
||||||
|
B0 = c0.Imaginary;
|
||||||
|
A1 = c1.Real;
|
||||||
|
B1 = c1.Imaginary;
|
||||||
|
A2 = c2.Real;
|
||||||
|
B2 = c2.Imaginary;
|
||||||
|
A3 = c3.Real;
|
||||||
|
B3 = c3.Imaginary;
|
||||||
|
A4 = c4.Real;
|
||||||
|
B4 = c4.Imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double A0 { get; }
|
||||||
|
private double B0 { get; set; }
|
||||||
|
private double A1 { get; }
|
||||||
|
private double B1 { get; }
|
||||||
|
private double A2 { get; }
|
||||||
|
private double B2 { get; }
|
||||||
|
private double A3 { get; }
|
||||||
|
private double B3 { get; }
|
||||||
|
private double A4 { get; }
|
||||||
|
private double B4 { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx =>
|
||||||
|
new PolyC3Re(A1, 0, 2 * A2, 2 * B2, 3 * A3, 3 * B3, 4 * A4, 4 * B4);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy =>
|
||||||
|
new PolyC3Re(-B1, 0, -2 * B2, 2 * A2, -3 * B3, 3 * A3, 4 * A4, -4 * B4);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
double x2 = x * x;
|
||||||
|
double y2 = y * y;
|
||||||
|
double x3 = x2 * x;
|
||||||
|
double y3 = y2 * y;
|
||||||
|
double x4 = x2 * x2;
|
||||||
|
double y4 = y2 * y2;
|
||||||
|
return
|
||||||
|
+A0
|
||||||
|
+ A1 * x - B1 * y
|
||||||
|
+ A2 * (x2 - y2) - B2 * 2 * x * y
|
||||||
|
+ A3 * (x3 - 3 * x * y2) + B3 * (y3 - 3 * x2 * y)
|
||||||
|
+ A4 * (x4 - 6 * x2 * y2 + y4) - B4 * (4 * (x3 * y + x * y3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class PolyC4Im : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC4Im(Complex c0, Complex c1, Complex c2, Complex c3, Complex c4)
|
||||||
|
{
|
||||||
|
A0 = c0.Real;
|
||||||
|
B0 = c0.Imaginary;
|
||||||
|
A1 = c1.Real;
|
||||||
|
B1 = c1.Imaginary;
|
||||||
|
A2 = c2.Real;
|
||||||
|
B2 = c2.Imaginary;
|
||||||
|
A3 = c3.Real;
|
||||||
|
B3 = c3.Imaginary;
|
||||||
|
A4 = c4.Real;
|
||||||
|
B4 = c4.Imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double A0 { get; set; }
|
||||||
|
private double B0 { get; }
|
||||||
|
private double A1 { get; }
|
||||||
|
private double B1 { get; }
|
||||||
|
private double A2 { get; }
|
||||||
|
private double B2 { get; }
|
||||||
|
private double A3 { get; }
|
||||||
|
private double B3 { get; }
|
||||||
|
private double A4 { get; }
|
||||||
|
private double B4 { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx =>
|
||||||
|
new PolyC3Im(0, B1, 2 * A2, 2 * B2, 3 * A3, 3 * B3, 4 * A4, 4 * B4);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy =>
|
||||||
|
new PolyC3Im(0, A1, -2 * B2, 2 * A2, -3 * B3, 3 * A3, -4 * B4, 4 * A4);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
double x2 = x * x;
|
||||||
|
double y2 = y * y;
|
||||||
|
double x3 = x2 * x;
|
||||||
|
double y3 = y2 * y;
|
||||||
|
double x4 = x2 * x2;
|
||||||
|
double y4 = y2 * y2;
|
||||||
|
return
|
||||||
|
+B0
|
||||||
|
+ A1 * y + B1 * x
|
||||||
|
+ A2 * 2 * x * y + B2 * (x2 - y2)
|
||||||
|
+ A3 * (3 * x2 * y - y3) + B3 * (x3 - 3 * x * y2)
|
||||||
|
+ A4 * (4 * (x3 * y - x * y3)) + B4 * (x4 - 6 * x2 * y2 + y4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class PolyC3Re : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC3Re(Complex c0, Complex c1, Complex c2, Complex c3)
|
||||||
|
{
|
||||||
|
A0 = c0.Real;
|
||||||
|
B0 = c0.Imaginary;
|
||||||
|
A1 = c1.Real;
|
||||||
|
B1 = c1.Imaginary;
|
||||||
|
A2 = c2.Real;
|
||||||
|
B2 = c2.Imaginary;
|
||||||
|
A3 = c3.Real;
|
||||||
|
B3 = c3.Imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC3Re(double a0, double b0, double a1, double b1, double a2, double b2, double a3, double b3)
|
||||||
|
{
|
||||||
|
A0 = a0;
|
||||||
|
B0 = b0;
|
||||||
|
A1 = a1;
|
||||||
|
B1 = b1;
|
||||||
|
A2 = a2;
|
||||||
|
B2 = b2;
|
||||||
|
A3 = a3;
|
||||||
|
B3 = b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double A0 { get; }
|
||||||
|
private double B0 { get; set; }
|
||||||
|
private double A1 { get; }
|
||||||
|
private double B1 { get; }
|
||||||
|
private double A2 { get; }
|
||||||
|
private double B2 { get; }
|
||||||
|
private double A3 { get; }
|
||||||
|
private double B3 { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => new PolyC2Re(A1, 0, 2 * A2, 2 * B2, 3 * A3, 3 * B3);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => new PolyC2Re(-B1, 0, -2 * B2, 2 * A2, -3 * B3, 3 * A3);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
double x2 = x * x;
|
||||||
|
double y2 = y * y;
|
||||||
|
double x3 = x2 * x;
|
||||||
|
double y3 = y2 * y;
|
||||||
|
//ddx =>
|
||||||
|
// A1 +2A2 x - 2B2 y + 3A3 x2 - 6B3 xy -3A3 y2
|
||||||
|
|
||||||
|
//ddy =>
|
||||||
|
// -B1 -2B2 x -2A2 y - 3B3 X2 - 6A3 xy + 3B3 y2
|
||||||
|
return
|
||||||
|
+A0
|
||||||
|
+ A1 * x - B1 * y
|
||||||
|
+ A2 * (x2 - y2) - B2 * 2 * x * y
|
||||||
|
+ A3 * (x3 - 3 * x * y2) + B3 * (y3 - 3 * x2 * y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class PolyC3Im : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC3Im(Complex c0, Complex c1, Complex c2, Complex c3)
|
||||||
|
{
|
||||||
|
A0 = c0.Real;
|
||||||
|
B0 = c0.Imaginary;
|
||||||
|
A1 = c1.Real;
|
||||||
|
B1 = c1.Imaginary;
|
||||||
|
A2 = c2.Real;
|
||||||
|
B2 = c2.Imaginary;
|
||||||
|
A3 = c3.Real;
|
||||||
|
B3 = c3.Imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC3Im(double a0, double b0, double a1, double b1, double a2, double b2, double a3, double b3)
|
||||||
|
{
|
||||||
|
A0 = a0;
|
||||||
|
B0 = b0;
|
||||||
|
A1 = a1;
|
||||||
|
B1 = b1;
|
||||||
|
A2 = a2;
|
||||||
|
B2 = b2;
|
||||||
|
A3 = a3;
|
||||||
|
B3 = b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double A0 { get; set; }
|
||||||
|
private double B0 { get; }
|
||||||
|
private double A1 { get; }
|
||||||
|
private double B1 { get; }
|
||||||
|
private double A2 { get; }
|
||||||
|
private double B2 { get; }
|
||||||
|
private double A3 { get; }
|
||||||
|
private double B3 { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => new PolyC2Im(0, B1, 2 * A2, 2 * B2, 3 * A3, 3 * B3);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => new PolyC2Im(0, A1, -2 * B2, 2 * A2, -3 * B3, 3 * A3);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
double x2 = x * x;
|
||||||
|
double y2 = y * y;
|
||||||
|
double x3 = x2 * x;
|
||||||
|
double y3 = y2 * y;
|
||||||
|
//ddx =>
|
||||||
|
// B1 + 2B2 x + 2A2 y + 6A3 xy + 3B3 (x2 - y2)
|
||||||
|
|
||||||
|
//ddy =>
|
||||||
|
// A1 + 2A2 x - 2B2 y - 6B3 xy + 3A3 (x2 - y2)
|
||||||
|
return
|
||||||
|
+B0
|
||||||
|
+ A1 * y + B1 * x
|
||||||
|
+ A2 * 2 * x * y + B2 * (x2 - y2) +
|
||||||
|
-A3 * (y3 - 3 * x2 * y) + B3 * (x3 - 3 * x * y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class PolyC2Re : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC2Re(Complex c0, Complex c1, Complex c2)
|
||||||
|
{
|
||||||
|
A0 = c0.Real;
|
||||||
|
B0 = c0.Imaginary;
|
||||||
|
A1 = c1.Real;
|
||||||
|
B1 = c1.Imaginary;
|
||||||
|
A2 = c2.Real;
|
||||||
|
B2 = c2.Imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC2Re(double a0, double b0, double a1, double b1, double a2, double b2)
|
||||||
|
{
|
||||||
|
A0 = a0;
|
||||||
|
B0 = b0;
|
||||||
|
A1 = a1;
|
||||||
|
B1 = b1;
|
||||||
|
A2 = a2;
|
||||||
|
B2 = b2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double A0 { get; }
|
||||||
|
private double B0 { get; set; }
|
||||||
|
private double A1 { get; }
|
||||||
|
private double B1 { get; }
|
||||||
|
private double A2 { get; }
|
||||||
|
private double B2 { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => new PolyC1Re(A1, 0, 2 * A2, 2 * B2);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => new PolyC1Re(-B1, 0, -2 * B2, 2 * A2);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
double x2 = x * x;
|
||||||
|
double y2 = y * y;
|
||||||
|
return //-B1 -2B2x - 2A2y
|
||||||
|
+A0
|
||||||
|
+ A1 * x - B1 * y
|
||||||
|
+ A2 * (x2 - y2) - B2 * 2 * x * y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class PolyC2Im : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC2Im(Complex c0, Complex c1, Complex c2)
|
||||||
|
{
|
||||||
|
A0 = c0.Real;
|
||||||
|
B0 = c0.Imaginary;
|
||||||
|
A1 = c1.Real;
|
||||||
|
B1 = c1.Imaginary;
|
||||||
|
A2 = c2.Real;
|
||||||
|
B2 = c2.Imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC2Im(double a0, double b0, double a1, double b1, double a2, double b2)
|
||||||
|
{
|
||||||
|
A0 = a0;
|
||||||
|
B0 = b0;
|
||||||
|
A1 = a1;
|
||||||
|
B1 = b1;
|
||||||
|
A2 = a2;
|
||||||
|
B2 = b2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double A0 { get; set; }
|
||||||
|
private double B0 { get; }
|
||||||
|
private double A1 { get; }
|
||||||
|
private double B1 { get; }
|
||||||
|
private double A2 { get; }
|
||||||
|
private double B2 { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => new PolyC1Im(0, B1, 2 * B2, 2 * A2);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => new PolyC1Im(0, A1, -2 * B2, 2 * A2);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
double x2 = x * x;
|
||||||
|
double y2 = y * y;
|
||||||
|
return // B1 + 2B2x + 2A2y
|
||||||
|
+B0
|
||||||
|
+ A1 * y + B1 * x +
|
||||||
|
+A2 * 2 * x * y + B2 * (x2 - y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class PolyC1Re : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC1Re(Complex c0, Complex c1)
|
||||||
|
{
|
||||||
|
A0 = c0.Real;
|
||||||
|
B0 = c0.Imaginary;
|
||||||
|
A1 = c1.Real;
|
||||||
|
B1 = c1.Imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC1Re(double a0, double b0, double a1, double b1)
|
||||||
|
{
|
||||||
|
A0 = a0;
|
||||||
|
B0 = b0;
|
||||||
|
A1 = a1;
|
||||||
|
B1 = b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double A0 { get; }
|
||||||
|
private double B0 { get; set; }
|
||||||
|
private double A1 { get; }
|
||||||
|
private double B1 { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => new BivariantContinuousConstant(A1);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => new BivariantContinuousConstant(-B1);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
+A0
|
||||||
|
+ A1 * x - B1 * y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class PolyC1Im : BivariantContinuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC1Im(Complex c0, Complex c1)
|
||||||
|
{
|
||||||
|
A0 = c0.Real;
|
||||||
|
B0 = c0.Imaginary;
|
||||||
|
A1 = c1.Real;
|
||||||
|
B1 = c1.Imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolyC1Im(double a0, double b0, double a1, double b1)
|
||||||
|
{
|
||||||
|
A0 = a0;
|
||||||
|
B0 = b0;
|
||||||
|
A1 = a1;
|
||||||
|
B1 = b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double A0 { get; set; }
|
||||||
|
private double B0 { get; }
|
||||||
|
private double A1 { get; }
|
||||||
|
private double B1 { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dx => new BivariantContinuousConstant(B1);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override BivariantContinuous Dy => new BivariantContinuousConstant(A1);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x, double y)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
+B0
|
||||||
|
+ A1 * y + B1 * x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Skeleton.Analysis.ContinuousFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.ContinuousFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class ContinuousAddition : Continuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ContinuousAddition(Continuous left, Continuous right)
|
||||||
|
{
|
||||||
|
Left = left;
|
||||||
|
Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Continuous Left { get; }
|
||||||
|
private Continuous Right { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Continuous Derivative => Left.Derivative + Right.Derivative;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x)
|
||||||
|
{
|
||||||
|
return Left.Evaluate(x) + Right.Evaluate(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Skeleton.Analysis.ContinuousFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.ContinuousFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class ContinuousApply : Continuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ContinuousApply(Continuous o, Continuous i)
|
||||||
|
{
|
||||||
|
Outer = o;
|
||||||
|
Inner = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Continuous Outer { get; }
|
||||||
|
private Continuous Inner { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Continuous Derivative => Inner.Derivative * Outer.Derivative[Inner];
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x)
|
||||||
|
{
|
||||||
|
return Outer.Evaluate(Inner.Evaluate(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Skeleton.Analysis.ContinuousFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.ContinuousFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class ContinuousConstant : Continuous
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly ContinuousConstant Zero = new(0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly ContinuousConstant One = new(1);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ContinuousConstant(double c)
|
||||||
|
{
|
||||||
|
Constant = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double Constant { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Continuous Derivative => Zero;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x)
|
||||||
|
{
|
||||||
|
return Constant;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using Skeleton.Analysis.ContinuousFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.ContinuousFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class ContinuousNegation : Continuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ContinuousNegation(Continuous e)
|
||||||
|
{
|
||||||
|
Element = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Continuous Element { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Continuous Derivative => -Element.Derivative;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x)
|
||||||
|
{
|
||||||
|
return -Element.Evaluate(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Skeleton.Analysis.ContinuousFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.ContinuousFunctions.Arithmetics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class ContinuousProduction : Continuous
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ContinuousProduction(Continuous left, Continuous right)
|
||||||
|
{
|
||||||
|
Left = left;
|
||||||
|
Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Continuous Left { get; }
|
||||||
|
private Continuous Right { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Continuous Derivative => Left * Right.Derivative + Left.Derivative * Right;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override double Evaluate(double x)
|
||||||
|
{
|
||||||
|
return Left.Evaluate(x) * Right.Evaluate(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/Analysis/ContinuousFunctions/IContinuous.cs
Normal file
18
src/Analysis/ContinuousFunctions/IContinuous.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Skeleton.Analysis.ContinuousFunctions.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.ContinuousFunctions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public interface IContinuous
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
Continuous Derivative { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
double Evaluate(double x);
|
||||||
|
}
|
||||||
58
src/Analysis/ContinuousFunctions/Implements/Continuous.cs
Normal file
58
src/Analysis/ContinuousFunctions/Implements/Continuous.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using Skeleton.Analysis.ContinuousFunctions.Arithmetics;
|
||||||
|
|
||||||
|
namespace Skeleton.Analysis.ContinuousFunctions.Implements;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Continuous : IContinuous
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="c"></param>
|
||||||
|
public Continuous this[Continuous c] => new ContinuousApply(this, c);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract Continuous Derivative { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract double Evaluate(double x);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Continuous operator +(Continuous a, Continuous b)
|
||||||
|
{
|
||||||
|
return new ContinuousAddition(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Continuous operator -(Continuous a)
|
||||||
|
{
|
||||||
|
return new ContinuousNegation(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Continuous operator -(Continuous a, Continuous b)
|
||||||
|
{
|
||||||
|
return -b + a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Continuous operator *(Continuous a, Continuous b)
|
||||||
|
{
|
||||||
|
return new ContinuousProduction(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/Constants/AlgebraConstant.cs
Normal file
100
src/Constants/AlgebraConstant.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Skeleton.Algebra.DimensionProviders;
|
||||||
|
|
||||||
|
namespace Skeleton.Constants;
|
||||||
|
using DiagR4 = Algebra.CategoryOf<IDim4>.OnField<double>.FDiagonalMatrix;
|
||||||
|
using DiagR3 = Algebra.CategoryOf<IDim3>.OnField<double>.FDiagonalMatrix;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// constants
|
||||||
|
/// </summary>
|
||||||
|
public static class AlgebraConstant
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// sqrt of pi
|
||||||
|
/// </summary>
|
||||||
|
public const double SqrtPi = 1.772453850905516027298167483341145182797549456122387128213807789852911284183d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// erf(1)
|
||||||
|
/// </summary>
|
||||||
|
public const double Erf1 = 0.8427007877600066754197883d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// erfc(1)
|
||||||
|
/// </summary>
|
||||||
|
public const double Erfc1 = 1 - Erf1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// erf(2)
|
||||||
|
/// </summary>
|
||||||
|
public const double Erf2 = 0.9953222650189527341620691d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// erfc(2)
|
||||||
|
/// </summary>
|
||||||
|
public const double Erfc2 = 1 - Erf2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// pi * pi
|
||||||
|
/// </summary>
|
||||||
|
public const double PI2 = Math.PI * Math.PI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// imaginary one
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Complex I = Complex.ImaginaryOne;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 0, 1/3, 2/3, 1 as diag
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DiagR4 UniformSpectrum4 = new(0d, 1d / 3d, 2d / 3d, 1d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 0, 0.5, 1 as diag
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DiagR3 UniformSpectrum3 = new(0d, 1d / 2d, 1d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// no use
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int Fib(int x)
|
||||||
|
{
|
||||||
|
return x switch
|
||||||
|
{
|
||||||
|
1 => 1,
|
||||||
|
2 => 2,
|
||||||
|
3 => 3,
|
||||||
|
4 => 5,
|
||||||
|
5 => 8,
|
||||||
|
6 => 13,
|
||||||
|
7 => 21,
|
||||||
|
8 => 34,
|
||||||
|
_ => -1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// no use
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int Ludic(int x)
|
||||||
|
{
|
||||||
|
return x switch
|
||||||
|
{
|
||||||
|
0 => 0,
|
||||||
|
1 => 1,
|
||||||
|
2 => 2,
|
||||||
|
3 => 4,
|
||||||
|
4 => 16,
|
||||||
|
5 => 26,
|
||||||
|
6 => 42,
|
||||||
|
7 => 57,
|
||||||
|
8 => 79,
|
||||||
|
_ => -1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
76
src/Constants/CC.cs
Normal file
76
src/Constants/CC.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Skeleton.Constants;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static class CC
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Complex I = Complex.ImaginaryOne;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double Sqrt2 = Math.Sqrt(2d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double Sqrt3 = Math.Sqrt(3d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double Sqrt5 = Math.Sqrt(5d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double Sqrt6 = Math.Sqrt(6d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double Sqrt7 = Math.Sqrt(7d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double Sqrt10 = Math.Sqrt(10d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double Sqrt11 = Math.Sqrt(11d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double Sqrt13 = Math.Sqrt(13d);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double SqrtInv2 = 1d / Sqrt2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double SqrtInv3 = 1d / Sqrt3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double SqrtInv5 = 1d / Sqrt5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double SqrtInv6 = 1d / Sqrt6;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double SqrtInv7 = 1d / Sqrt7;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double SqrtInv10 = 1d / Sqrt10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double SqrtInv11 = 1d / Sqrt11;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public static readonly double SqrtInv13 = 1d / Sqrt13;
|
||||||
|
}
|
||||||
82
src/DataStructure/CacheItem.cs
Normal file
82
src/DataStructure/CacheItem.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
namespace Skeleton.DataStructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// store value from calculation to avoid redundant computations
|
||||||
|
/// </summary>
|
||||||
|
public abstract class CacheItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// if the item needs update
|
||||||
|
/// </summary>
|
||||||
|
public bool Expired { get; protected set; } = true;
|
||||||
|
internal HashSet<CacheItem> References { get; set; } = new();
|
||||||
|
internal HashSet<CacheItem> Dependencies { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tag the item and all dependencies as out dated
|
||||||
|
/// </summary>
|
||||||
|
public void Expire()
|
||||||
|
{
|
||||||
|
Expired = true;
|
||||||
|
foreach (CacheItem c in References)
|
||||||
|
if (!c.Expired)
|
||||||
|
c.Expire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class CacheItem<TObject> : CacheItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// construct by provide a method to update the value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rec"></param>
|
||||||
|
public CacheItem(Func<CacheItem, TObject> rec) => ProxyCalculator = rec;
|
||||||
|
private TObject? Value { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// return cached/updated value when reference is not used to calculate another cache item
|
||||||
|
/// </summary>
|
||||||
|
public TObject Get
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Expired)
|
||||||
|
{
|
||||||
|
Value = Calculator();
|
||||||
|
Expired = false;
|
||||||
|
}
|
||||||
|
return Value!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Func<TObject> Calculator => () => ProxyCalculator(this);
|
||||||
|
/// <summary>
|
||||||
|
/// provide trace information while calculating
|
||||||
|
/// </summary>
|
||||||
|
public Func<CacheItem, TObject> ProxyCalculator { get; internal set; }
|
||||||
|
/// <summary>
|
||||||
|
/// trace the dependency and return cached value/updated value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="d"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TObject GetFrom(CacheItem d)
|
||||||
|
{
|
||||||
|
References.Add(d);
|
||||||
|
d.Dependencies.Add(this);
|
||||||
|
return Get;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// update the formula of item value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val"></param>
|
||||||
|
public void UpdateCalculation(Func<CacheItem, TObject> val)
|
||||||
|
{
|
||||||
|
Expire();
|
||||||
|
foreach (CacheItem item in Dependencies)
|
||||||
|
item.References.Remove(this);
|
||||||
|
Dependencies = new HashSet<CacheItem>();
|
||||||
|
ProxyCalculator = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
60
src/DataStructure/IsomorphicMap.cs
Normal file
60
src/DataStructure/IsomorphicMap.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
namespace Skeleton.DataStructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class IsomorphicMap<TKey, TValue>
|
||||||
|
where TKey : notnull
|
||||||
|
where TValue : notnull
|
||||||
|
{
|
||||||
|
private Dictionary<TKey, TValue> F { get; set; } = new();
|
||||||
|
private Dictionary<TValue, TKey> G { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
public TValue this[TKey key]
|
||||||
|
{
|
||||||
|
get => F[key];
|
||||||
|
set
|
||||||
|
{
|
||||||
|
F[key] = value;
|
||||||
|
G[value] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
public TKey this[TValue key]
|
||||||
|
{
|
||||||
|
get => G[key];
|
||||||
|
set
|
||||||
|
{
|
||||||
|
F[value] = key;
|
||||||
|
G[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsKey(TKey key) => F.ContainsKey(key);
|
||||||
|
public bool ContainsKey(TValue key) => G.ContainsKey(key);
|
||||||
|
public IEnumerable<TValue> Values => G.Keys;
|
||||||
|
public IEnumerable<TKey> Keys => F.Keys;
|
||||||
|
|
||||||
|
public void Remove(TKey key)
|
||||||
|
{
|
||||||
|
TValue v = F[key];
|
||||||
|
F.Remove(key);
|
||||||
|
G.Remove(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(TValue val)
|
||||||
|
{
|
||||||
|
TKey key = G[val];
|
||||||
|
F.Remove(key);
|
||||||
|
G.Remove(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
236
src/DataStructure/Link/Link.cs
Normal file
236
src/DataStructure/Link/Link.cs
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Skeleton.DataStructure.Link;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Linked List
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TObject"></typeparam>
|
||||||
|
public class Link<TObject> : IEnumerable<TObject>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// singleton for default value
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Link<TObject> Null = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
public Link()
|
||||||
|
{
|
||||||
|
Head = new LinkHead<TObject>();
|
||||||
|
Tail = new LinkTail<TObject>();
|
||||||
|
Head.Parent = this;
|
||||||
|
Tail.Parent = this;
|
||||||
|
Head.Next = Tail;
|
||||||
|
Tail.Previous = Head;
|
||||||
|
Count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// First item
|
||||||
|
/// </summary>
|
||||||
|
public LinkNode<TObject> First => Head.Next;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Last item
|
||||||
|
/// </summary>
|
||||||
|
public LinkNode<TObject> Last => Tail.Previous;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// number of items
|
||||||
|
/// </summary>
|
||||||
|
public int Count { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// head of linked list
|
||||||
|
/// </summary>
|
||||||
|
private LinkHead<TObject> Head { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tail of linked list
|
||||||
|
/// </summary>
|
||||||
|
private LinkTail<TObject> Tail { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// iterator in reverse direction
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public IEnumerable<TObject> Backward
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
LinkNode<TObject> iter = Tail.Previous;
|
||||||
|
int current = 1;
|
||||||
|
while (!iter.IsHead)
|
||||||
|
{
|
||||||
|
if (current > Count)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
yield return iter.Value;
|
||||||
|
iter = iter.Previous;
|
||||||
|
current += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public IEnumerator<TObject> GetEnumerator()
|
||||||
|
{
|
||||||
|
LinkNode<TObject> iter = Head.Next;
|
||||||
|
int current = 1;
|
||||||
|
while (!iter.IsTail)
|
||||||
|
{
|
||||||
|
if (current > Count)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
yield return iter.Value;
|
||||||
|
iter = iter.Next;
|
||||||
|
current += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// add item next to head
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
public void AddFirst(TObject obj)
|
||||||
|
{
|
||||||
|
LinkNode<TObject> node = new LinkNode<TObject>(obj);
|
||||||
|
node.Parent = this;
|
||||||
|
Head.Next.Previous = node;
|
||||||
|
node.Previous = Head;
|
||||||
|
node.Next = Head.Next;
|
||||||
|
Head.Next = node;
|
||||||
|
Count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// add item before tail
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
public void AddLast(TObject obj)
|
||||||
|
{
|
||||||
|
LinkNode<TObject> node = new LinkNode<TObject>(obj);
|
||||||
|
node.Parent = this;
|
||||||
|
Tail.Previous.Next = node;
|
||||||
|
node.Next = Tail;
|
||||||
|
node.Previous = Tail.Previous;
|
||||||
|
Tail.Previous = node;
|
||||||
|
Count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// add item after specific node
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node"></param>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public void AddAfter(LinkNode<TObject> node, TObject obj)
|
||||||
|
{
|
||||||
|
if (node.Parent != this)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
LinkNode<TObject> newNode = new LinkNode<TObject>(obj);
|
||||||
|
node.Parent = this;
|
||||||
|
node.Next.Previous = newNode;
|
||||||
|
newNode.Next = node.Next;
|
||||||
|
node.Next = newNode;
|
||||||
|
newNode.Previous = node;
|
||||||
|
Count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// add item before specific node
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node"></param>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
public void AddBefore(LinkNode<TObject> node, TObject obj)
|
||||||
|
{
|
||||||
|
AddAfter(node.Previous, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public LinkNode<TObject> Find(TObject value)
|
||||||
|
{
|
||||||
|
LinkNode<TObject> iter = Head.Next;
|
||||||
|
int current = 1;
|
||||||
|
while (!iter.IsTail)
|
||||||
|
{
|
||||||
|
if (current > Count)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
if (iter.Value!.Equals(value))
|
||||||
|
return iter;
|
||||||
|
iter = iter.Next;
|
||||||
|
current += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LinkNode<TObject>.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// find the node by selector
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="selector"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public LinkNode<TObject> Find(Func<TObject, bool> selector)
|
||||||
|
{
|
||||||
|
LinkNode<TObject> iter = Head.Next;
|
||||||
|
int current = 1;
|
||||||
|
while (!iter.IsTail)
|
||||||
|
{
|
||||||
|
if (current > Count)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
if (selector(iter.Value))
|
||||||
|
return iter;
|
||||||
|
iter = iter.Next;
|
||||||
|
current += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LinkNode<TObject>.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// remove specific node
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node"></param>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public void Remove(LinkNode<TObject> node)
|
||||||
|
{
|
||||||
|
if (!ReferenceEquals(node.Parent, this))
|
||||||
|
throw new Exception();
|
||||||
|
if (node.IsEnding)
|
||||||
|
throw new Exception();
|
||||||
|
node.Previous.Next = node.Next;
|
||||||
|
node.Next.Previous = node.Previous;
|
||||||
|
node.Previous = LinkNode<TObject>.Null;
|
||||||
|
node.Next = LinkNode<TObject>.Null;
|
||||||
|
node.Parent = Null;
|
||||||
|
Count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// remove the first item
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public TObject RemoveFirst()
|
||||||
|
{
|
||||||
|
LinkNode<TObject> res = First;
|
||||||
|
if (res.IsEnding)
|
||||||
|
throw new Exception("TODO EMPTY");
|
||||||
|
TObject resValue = res.Value;
|
||||||
|
Remove(res);
|
||||||
|
return resValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/DataStructure/Link/LinkHead.cs
Normal file
38
src/DataStructure/Link/LinkHead.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
namespace Skeleton.DataStructure.Link;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// head of linked list
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TObject"></typeparam>
|
||||||
|
public class LinkHead<TObject> : LinkNode<TObject>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// no previous element
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public override LinkNode<TObject> Previous
|
||||||
|
{
|
||||||
|
get => throw new Exception("TODO");
|
||||||
|
set => throw new Exception("TODO");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// no value
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public new TObject Value
|
||||||
|
{
|
||||||
|
get => throw new Exception("TODO");
|
||||||
|
set => throw new Exception("TODO");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// is head
|
||||||
|
/// </summary>
|
||||||
|
public override bool IsHead => true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// is ending
|
||||||
|
/// </summary>
|
||||||
|
public override bool IsEnding => true;
|
||||||
|
}
|
||||||
164
src/DataStructure/Link/LinkNode.cs
Normal file
164
src/DataStructure/Link/LinkNode.cs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
namespace Skeleton.DataStructure.Link;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// node of linked list
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TObject"></typeparam>
|
||||||
|
public class LinkNode<TObject>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// singleton for initialize
|
||||||
|
/// </summary>
|
||||||
|
public static readonly LinkNode<TObject> Null = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
protected LinkNode() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="val"></param>
|
||||||
|
public LinkNode(TObject val)
|
||||||
|
{
|
||||||
|
Value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// by default, node is not the tail
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool IsTail => false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// by default, node is not the head
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool IsHead => false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// by default, node is not head nor tail
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool IsEnding => false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// unexpected
|
||||||
|
/// </summary>
|
||||||
|
public bool Isolated => !IsEnding && (Next == Null || Previous == Null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// linked list that node belongs to
|
||||||
|
/// </summary>
|
||||||
|
public Link<TObject> Parent { get; set; } = Link<TObject>.Null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// next node
|
||||||
|
/// </summary>
|
||||||
|
public virtual LinkNode<TObject> Next { get; set; } = Null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// previous node
|
||||||
|
/// </summary>
|
||||||
|
public virtual LinkNode<TObject> Previous { get; set; } = Null;
|
||||||
|
|
||||||
|
|
||||||
|
private TObject? PrivateValue { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// item
|
||||||
|
/// </summary>
|
||||||
|
public TObject Value
|
||||||
|
{
|
||||||
|
get => PrivateValue ?? throw new Exception();
|
||||||
|
set => PrivateValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// move item forward
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public void MoveForward()
|
||||||
|
{
|
||||||
|
if (IsEnding)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
if (Next.IsTail)
|
||||||
|
return;
|
||||||
|
LinkNode<TObject> cOrder0 = Previous;
|
||||||
|
LinkNode<TObject> cOrder1 = Next;
|
||||||
|
LinkNode<TObject> cOrder2 = Next.Next;
|
||||||
|
cOrder0.Next = cOrder1;
|
||||||
|
cOrder1.Previous = cOrder0;
|
||||||
|
cOrder1.Next = this;
|
||||||
|
Previous = cOrder1;
|
||||||
|
Next = cOrder2;
|
||||||
|
cOrder2.Previous = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// move item backward
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public void MoveBackward()
|
||||||
|
{
|
||||||
|
if (IsEnding)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
if (Previous.IsHead)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LinkNode<TObject> cOrder0 = Previous.Previous;
|
||||||
|
LinkNode<TObject> cOrder1 = Previous;
|
||||||
|
LinkNode<TObject> cOrder2 = Next;
|
||||||
|
|
||||||
|
cOrder0.Next = this;
|
||||||
|
Previous = cOrder0;
|
||||||
|
cOrder1.Previous = this;
|
||||||
|
Next = cOrder1;
|
||||||
|
cOrder2.Previous = cOrder1;
|
||||||
|
cOrder1.Next = cOrder2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// move node after specific node
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public void MoveAfter(LinkNode<TObject> target)
|
||||||
|
{
|
||||||
|
if (target.IsTail)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
if (target.Parent != Parent)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
if (!Isolated)
|
||||||
|
{
|
||||||
|
Next.Previous = Previous;
|
||||||
|
Previous.Next = Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Previous = target;
|
||||||
|
Next = target.Next;
|
||||||
|
target.Next.Previous = this;
|
||||||
|
target.Next = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// move item before specific node
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public void MoveBefore(LinkNode<TObject> target)
|
||||||
|
{
|
||||||
|
if (target.IsHead)
|
||||||
|
throw new Exception("TODO");
|
||||||
|
if (!ReferenceEquals(target.Parent, Parent))
|
||||||
|
throw new Exception("TODO");
|
||||||
|
if (!Isolated)
|
||||||
|
{
|
||||||
|
Next.Previous = Previous;
|
||||||
|
Previous.Next = Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Previous = target.Previous;
|
||||||
|
Next = target;
|
||||||
|
target.Previous.Next = this;
|
||||||
|
target.Previous = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/DataStructure/Link/LinkTail.cs
Normal file
38
src/DataStructure/Link/LinkTail.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
namespace Skeleton.DataStructure.Link;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tail of linked list
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TObject"></typeparam>
|
||||||
|
public class LinkTail<TObject> : LinkNode<TObject>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// no next
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public override LinkNode<TObject> Next
|
||||||
|
{
|
||||||
|
get => throw new Exception("TODO");
|
||||||
|
set => throw new Exception("TODO");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// no value
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public new TObject Value
|
||||||
|
{
|
||||||
|
get => throw new Exception("TODO");
|
||||||
|
set => throw new Exception("TODO");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// is tail
|
||||||
|
/// </summary>
|
||||||
|
public override bool IsTail => true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// is ending
|
||||||
|
/// </summary>
|
||||||
|
public override bool IsEnding => true;
|
||||||
|
}
|
||||||
26
src/DataStructure/Packs/EigenPair.cs
Normal file
26
src/DataStructure/Packs/EigenPair.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Skeleton.Algebra.Vectors;
|
||||||
|
|
||||||
|
namespace Skeleton.DataStructure.Packs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TVector"></typeparam>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
public class EigenPair<TScalar, TVector> : Pack2<TScalar, TVector[]>
|
||||||
|
where TVector : Vector<TVector>, new()
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public EigenPair(TScalar eigenValue, TVector[] eigenVectors) : base(eigenValue, eigenVectors) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public TScalar EigenValue
|
||||||
|
{
|
||||||
|
get => Item1;
|
||||||
|
set => Item1 = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public TVector[] EigenVectors => Item2;
|
||||||
|
}
|
||||||
37
src/DataStructure/Packs/LinearSystems/LinearSystem.cs
Normal file
37
src/DataStructure/Packs/LinearSystems/LinearSystem.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using Skeleton.Algebra.Matrices;
|
||||||
|
using Skeleton.Algebra.Vectors;
|
||||||
|
|
||||||
|
namespace Skeleton.DataStructure.Packs.LinearSystems;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// system Ax = y
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
/// <typeparam name="TVector"></typeparam>
|
||||||
|
/// <typeparam name="TMatrix"></typeparam>
|
||||||
|
public class LinearSystem<TScalar, TVector, TMatrix> : Pack2<TMatrix, TVector>
|
||||||
|
where TVector : Vector<TScalar, TVector>, new()
|
||||||
|
where TMatrix : Matrix<TScalar, TVector, TMatrix>, new()
|
||||||
|
where TScalar : notnull
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="m"></param>
|
||||||
|
/// <param name="v"></param>
|
||||||
|
public LinearSystem(TMatrix m, TVector v)
|
||||||
|
{
|
||||||
|
Item1 = m;
|
||||||
|
Item2 = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// matrix
|
||||||
|
/// </summary>
|
||||||
|
public TMatrix A => Item1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// y
|
||||||
|
/// </summary>
|
||||||
|
public TVector Y => Item2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
namespace Skeleton.DataStructure.Packs.MatrixDecompositions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="U"></typeparam>
|
||||||
|
/// <typeparam name="H"></typeparam>
|
||||||
|
public class GeneralUHPair<U, H> : Pack2<U, H>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
public GeneralUHPair(U a, H b) : base(a, b) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public U Unitary => Item1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public H Hermitian => Item2;
|
||||||
|
}
|
||||||
21
src/DataStructure/Packs/MatrixDecompositions/JDPair.cs
Normal file
21
src/DataStructure/Packs/MatrixDecompositions/JDPair.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Skeleton.DataStructure.Packs.MatrixDecompositions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TMat"></typeparam>
|
||||||
|
public class JDPair<TMat> : Pack2<TMat, TMat>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="diagonal"></param>
|
||||||
|
public JDPair(TMat a, TMat diagonal) : base(a, diagonal) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public TMat J => Item1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public TMat D => Item2;
|
||||||
|
}
|
||||||
37
src/DataStructure/Packs/MatrixDecompositions/PLUPack.cs
Normal file
37
src/DataStructure/Packs/MatrixDecompositions/PLUPack.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
namespace Skeleton.DataStructure.Packs.MatrixDecompositions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// plu decomposition result
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TMatrix"></typeparam>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
public class PLUPack<TScalar, TMatrix> : Pack3<TMatrix, TMatrix, TMatrix>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p"></param>
|
||||||
|
/// <param name="l"></param>
|
||||||
|
/// <param name="u"></param>
|
||||||
|
/// <param name="det"></param>
|
||||||
|
public PLUPack(TMatrix p, TMatrix l, TMatrix u, TScalar det) : base(p, l, u) => Det = det;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// permutation
|
||||||
|
/// </summary>
|
||||||
|
public TMatrix P => Item1;
|
||||||
|
/// <summary>
|
||||||
|
/// lower triangle
|
||||||
|
/// </summary>
|
||||||
|
public TMatrix L => Item2;
|
||||||
|
/// <summary>
|
||||||
|
/// upper triangle
|
||||||
|
/// </summary>
|
||||||
|
public TMatrix U => Item3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// det of mat
|
||||||
|
/// </summary>
|
||||||
|
public TScalar Det { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
28
src/DataStructure/Packs/MatrixDecompositions/QRPair.cs
Normal file
28
src/DataStructure/Packs/MatrixDecompositions/QRPair.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
namespace Skeleton.DataStructure.Packs.MatrixDecompositions;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// result of qr decomposition
|
||||||
|
/// M = QR
|
||||||
|
/// Q : unitary matrix
|
||||||
|
/// R : right(upper) triangle matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TMatrix"></typeparam>
|
||||||
|
public class QRPair<TMatrix> : Pack2<TMatrix, TMatrix>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// unitary matrix
|
||||||
|
/// </summary>
|
||||||
|
public TMatrix Q => Item1;
|
||||||
|
/// <summary>
|
||||||
|
/// right(upper) triangle matrix
|
||||||
|
/// </summary>
|
||||||
|
public TMatrix R => Item2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="q"></param>
|
||||||
|
/// <param name="r"></param>
|
||||||
|
public QRPair(TMatrix q, TMatrix r) : base(q, r) { }
|
||||||
|
}
|
||||||
124
src/DataStructure/Packs/Pack.cs
Normal file
124
src/DataStructure/Packs/Pack.cs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
namespace Skeleton.DataStructure.Packs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T1"></typeparam>
|
||||||
|
/// <typeparam name="T2"></typeparam>
|
||||||
|
/// <typeparam name="T3"></typeparam>
|
||||||
|
/// <typeparam name="T4"></typeparam>
|
||||||
|
public class Pack4<T1, T2, T3, T4>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Pack4()
|
||||||
|
{
|
||||||
|
Item1 = default!;
|
||||||
|
Item2 = default!;
|
||||||
|
Item3 = default!;
|
||||||
|
Item4 = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="i1"></param>
|
||||||
|
/// <param name="i2"></param>
|
||||||
|
/// <param name="i3"></param>
|
||||||
|
/// <param name="i4"></param>
|
||||||
|
public Pack4(T1 i1, T2 i2, T3 i3, T4 i4)
|
||||||
|
{
|
||||||
|
Item1 = i1;
|
||||||
|
Item2 = i2;
|
||||||
|
Item3 = i3;
|
||||||
|
Item4 = i4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T1 Item1 { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T2 Item2 { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T3 Item3 { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T4 Item4 { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T1"></typeparam>
|
||||||
|
/// <typeparam name="T2"></typeparam>
|
||||||
|
/// <typeparam name="T3"></typeparam>
|
||||||
|
public class Pack3<T1, T2, T3>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T1 Item1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T2 Item2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T3 Item3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Pack3()
|
||||||
|
{
|
||||||
|
Item1 = default!;
|
||||||
|
Item2 = default!;
|
||||||
|
Item3 = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="i1"></param>
|
||||||
|
/// <param name="i2"></param>
|
||||||
|
/// <param name="i3"></param>
|
||||||
|
public Pack3(T1 i1, T2 i2, T3 i3)
|
||||||
|
{
|
||||||
|
Item1 = i1;
|
||||||
|
Item2 = i2;
|
||||||
|
Item3 = i3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T1"></typeparam>
|
||||||
|
/// <typeparam name="T2"></typeparam>
|
||||||
|
public class Pack2<T1, T2>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T1 Item1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
protected T2 Item2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Pack2()
|
||||||
|
{
|
||||||
|
Item1 = default!;
|
||||||
|
Item2 = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="i1"></param>
|
||||||
|
/// <param name="i2"></param>
|
||||||
|
public Pack2(T1 i1, T2 i2)
|
||||||
|
{
|
||||||
|
Item1 = i1;
|
||||||
|
Item2 = i2;
|
||||||
|
}
|
||||||
|
}
|
||||||
78
src/DataStructure/Packs/PlainPack.cs
Normal file
78
src/DataStructure/Packs/PlainPack.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
namespace Skeleton.DataStructure.Packs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T1"></typeparam>
|
||||||
|
/// <typeparam name="T2"></typeparam>
|
||||||
|
public class PlainPack2<T1, T2> : Pack2<T1, T2>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PlainPack2(T1 a, T2 b) : base(a, b) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T1 Item1
|
||||||
|
{
|
||||||
|
get => base.Item1;
|
||||||
|
set => base.Item1 = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T2 Item2
|
||||||
|
{
|
||||||
|
get => base.Item2;
|
||||||
|
set => base.Item2 = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T1"></typeparam>
|
||||||
|
/// <typeparam name="T2"></typeparam>
|
||||||
|
/// <typeparam name="T3"></typeparam>
|
||||||
|
public class PlainPack3<T1, T2, T3> : Pack3<T1, T2, T3>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PlainPack3(T1 a, T2 b, T3 c) : base(a, b, c) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T1 Item1 => base.Item1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T2 Item2 => base.Item2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T3 Item3 => base.Item3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T1"></typeparam>
|
||||||
|
/// <typeparam name="T2"></typeparam>
|
||||||
|
/// <typeparam name="T3"></typeparam>
|
||||||
|
/// <typeparam name="T4"></typeparam>
|
||||||
|
public class PlainPack4<T1, T2, T3, T4> : Pack4<T1, T2, T3, T4>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PlainPack4(T1 a, T2 b, T3 c, T4 d) : base(a, b, c, d) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T1 Item1 => base.Item1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T2 Item2 => base.Item2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T3 Item3 => base.Item3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public new T4 Item4 => base.Item4;
|
||||||
|
}
|
||||||
19
src/DataStructure/Packs/PolynomialDivisionResult.cs
Normal file
19
src/DataStructure/Packs/PolynomialDivisionResult.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Skeleton.Analysis.AnalyticFunctions.Polynomials.Implements;
|
||||||
|
|
||||||
|
namespace Skeleton.DataStructure.Packs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class PolynomialDivisionResult : Pack2<Polynomial, Polynomial>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public PolynomialDivisionResult(Polynomial q, Polynomial r) : base(q, r) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Polynomial Quotient => Item1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Polynomial Remainder => Item2;
|
||||||
|
}
|
||||||
21
src/DataStructure/Packs/QuadraticRoots.cs
Normal file
21
src/DataStructure/Packs/QuadraticRoots.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Skeleton.DataStructure.Packs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TScalar"></typeparam>
|
||||||
|
public class QuadraticRoots<TScalar> : Pack2<TScalar, TScalar>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public QuadraticRoots(TScalar x1, TScalar x2) : base(x1, x2) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public TScalar X1 => Item1;
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public TScalar X2 => Item2;
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user