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; /// /// public abstract class Polynomial : Analytic, IPolynomial { /// /// 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))); /// /// public bool IsConstant => Decorators.WithTol(1E-30, () => Coefficients.Skip(1).All(x => x.IsEqualApprox(Complex.Zero))); /// 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); } } /// /// public virtual string Representation => string.Join( " + ", Coefficients .Zip(Enumerable.Range(0, Degree + 1)) .Select( x => "(" + ComplexFieldStructure.Structure.Representation(x.First) + $")x^{x.Second}" ) ); /// /// public abstract IEnumerable Roots { get; } /// public abstract int Dim { get; } /// public int Degree { get { for (int i = 0; i <= Dim; i++) if (Coefficients[^(i + 1)] != Complex.Zero) return Dim - i; return 0; } } /// public Complex[] Coefficients { get; set; } = Array.Empty(); /// public abstract BivariantContinuous Re { get; } /// public abstract BivariantContinuous Im { get; } /// /// /// /// /// 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) }; } /// /// /// /// /// public static Polynomial operator +(Polynomial a, Complex b) => a + new C0Polynomial(b); /// /// /// /// /// public static Polynomial operator +(Complex b, Polynomial a) => a + b; /// /// /// /// /// public static Polynomial operator -(Polynomial a, Complex b) => a + new C0Polynomial(-b); /// /// /// /// /// 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); } /// /// /// /// public static Polynomial operator -(Polynomial a) => Dispatch(a.Coefficients.Select(x => -x).ToArray()); /// /// /// /// /// public static Polynomial operator -(Polynomial a, Polynomial b) => -b + a; /// /// /// /// /// public static Polynomial operator *(Polynomial a, Complex b) => Dispatch(a.Coefficients.Select(x => x * b).ToArray()); /// /// /// /// /// public static Polynomial operator *(Complex b, Polynomial a) => a * b; /// /// /// /// /// public static Polynomial operator /(Polynomial a, Complex b) => Dispatch(a.Coefficients.Select(x => x / b).ToArray()); /// /// /// /// /// /// 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); } /// /// /// /// 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); } /// /// /// /// 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; } /// /// protected void Fix() { for (int i = 0; i < Dim; i++) Coefficients[i] = ComplexFieldStructure.Structure.Fix(Coefficients[i]); } /// public override Complex Evaluate(Complex x) => Enumerable .Range(0, Degree + 1) .Reverse() .Select(i => Coefficients[i]) .Aggregate((x1, x2) => x1 * x + x2); }