using System.Numerics; using Skeleton.Algebra.Extensions; using Skeleton.DataStructure.Packs; namespace Skeleton.Algebra.ScalarFieldStructure; /// /// operations / structure of the field /// public abstract class FieldStructure { } /// public abstract class FieldStructure : FieldStructure { /// /// return the singleton base on type /// /// public static FieldStructure Dispatch() { if (typeof(TScalar) == typeof(double)) return (RealFieldStructure.Structure as FieldStructure)!; if (typeof(TScalar) == typeof(Complex)) return (ComplexFieldStructure.Structure as FieldStructure)!; return ScalarFieldStructureProvider.GetOperation(); } /// public FieldStructure() { StaticAccess.AdditionUnit = AdditionUnit; StaticAccess.MultiplicationUnit = MultiplicationUnit; StaticAccess.Structure = this; } /// /// addition in field /// /// /// /// public abstract TScalar Addition(TScalar self, TScalar other); /// /// addition unit of the field
/// a + unit = a for any a in field ///
public abstract TScalar AdditionUnit { get; } /// /// multiplication in field /// /// /// /// public abstract TScalar Multiplication(TScalar self, TScalar other); /// /// multiplication unit of the field
/// unit * a = a for any a in the field except the addition unit ///
public abstract TScalar MultiplicationUnit { get; } /// /// inverse of element under addition
/// a + AddInv(a) = unit(addition) for any a in field ///
/// /// public abstract TScalar AdditionInverse(TScalar self); /// /// inverse of element under multiplication
/// a * MulInv(a) = unit(multiplication) for any a in field except the addition unit ///
/// /// public abstract TScalar MultiplicationInverse(TScalar self); /// /// a + AddInv(b) /// /// /// /// public virtual TScalar Subtraction(TScalar self, TScalar other) => Addition(self, AdditionInverse(other)); /// /// a * MulInv(b) /// /// /// /// public virtual TScalar Division(TScalar self, TScalar other) => Multiplication(self, MultiplicationInverse(other)); /// /// conjugate of the scalar /// /// /// public abstract TScalar Conj(TScalar self); /// /// if two elements are close to each other in the field /// /// /// /// /// /// public abstract bool IsEqualApprox(TScalar self, TScalar other, double? absTol=null, double? relTol = null); /// /// tolerance to check if two scalars are close /// public double AbsoluteTolerance { get; set; } = 1E-8d; /// /// /// public double RelativeTolerance { get; set; } = 1E-5d; /// /// if calculation in field won't introduce error, override this and leave it empty /// otherwise, provide method to reduce the error here /// /// /// public virtual TScalar Fix(TScalar x) { if (IsEqualApprox(x, AdditionUnit)) return AdditionUnit; if (IsEqualApprox(x, MultiplicationUnit)) return MultiplicationUnit; return x; } /// /// homomorphism from scalar field to real
/// ignore if not applicable ///
/// /// public virtual double AsReal(TScalar x) => IsEqualApprox(x, AdditionUnit) ? 0 : 1; /// /// conjugated square xx* when field is real/complex /// /// /// public double ConjX2(TScalar x) => AsReal(Multiplication(x, Conj(x))); /// /// homomorphism from real to scalar
/// ignore if not applicable ///
/// /// public virtual TScalar FromReal(double x) => x.IsEqualApprox(0) ? AdditionUnit : MultiplicationUnit; /// /// readable string representation of data /// /// /// public string Representation(TScalar x) => RawRepresentation(Fix(x)); /// /// representation of the original data, without fix /// /// /// public virtual string RawRepresentation(TScalar x) => $"{x}"; /// /// code to construct object in python /// /// /// public string PythonRepresentation(TScalar x) => RawPythonRepresentation(Fix(x)); /// /// code to construct scalar object in python
/// ignore if not applicable ///
/// /// public virtual string RawPythonRepresentation(TScalar x) => ""; /// /// code to construct the object in c# /// /// /// public string CSharpRepresentation(TScalar x) => RawCSharpRepresentation(Fix(x)); /// /// C# string for the original data /// /// /// public abstract string RawCSharpRepresentation(TScalar x); /// /// dump the object as string which can be restored exactly
/// ignore if not applicable
/// if override can not contain following string as substring
/// <D> </D> <C> </C> <CSPLIT/>
/// <VECTOR> <VSPLIT/> </VECTOR>
/// <MATRIX> <MSPLIT/> </MSPLIT> ///
/// /// public virtual string DumpString(TScalar x) => ""; /// /// method to restore a value from dump string
/// ignore if not applicable ///
/// /// public virtual TScalar Resolve(string dumpString) => AdditionUnit; /// /// max diff from zero /// /// /// public abstract double MaxError(TScalar a); /// /// homomorphism from field to complex
/// ignore if not applicable ///
/// /// public virtual Complex ComplexCast(TScalar a) => IsEqualApprox(a, AdditionUnit) ? 0 : 1; /// /// K x R -> K
/// ignore if not applicable ///
/// /// /// public virtual TScalar RealMul(TScalar a, double b) => a; /// /// for y in field, find x such that x*x = y /// /// /// public abstract TScalar SquareRoot(TScalar a); /// /// Absolute value /// /// /// public TScalar Abs(TScalar a) => SquareRoot(Multiplication(a, Conj(a))); /// /// a x^2 + b x + c = unit(add) /// /// /// /// /// public QuadraticRoots 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(x1, x2); } internal TScalar WilkinsonShift(TScalar a1, TScalar b1, TScalar b2, TScalar a2) { QuadraticRoots 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; } /// /// homomorphism from complex to this field /// /// /// public virtual TScalar FromComplex(Complex a) => AdditionUnit; /// /// log of the element in the field /// /// /// public virtual TScalar Log(TScalar x) => AdditionUnit; /// /// exp of the element in the field /// /// /// public virtual TScalar Exp(TScalar x) => MultiplicationUnit; }