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