M2
This commit is contained in:
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user