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; /// /// public class C4Polynomial : Polynomial { /// public C4Polynomial() { Coefficients = new Complex[5]; Fix(); } /// public C4Polynomial(Complex a0, Complex a1, Complex a2, Complex a3, Complex a4) { Coefficients = new[] { a0, a1, a2, a3, a4 }; Fix(); } /// /// public Complex A0 => Coefficients[0]; /// /// public Complex A1 => Coefficients[1]; /// /// public Complex A2 => Coefficients[2]; /// /// public Complex A3 => Coefficients[3]; /// /// public Complex A4 => Coefficients[4]; /// public override int Dim => 4; /// public override Polynomial Derivative => new C3Polynomial(A1, A2 * 2, A3 * 3, A4 * 4); /// public override IEnumerable 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) }; }); /// public override BivariantContinuous Re => new PolyCHelper.PolyC4Re(A0, A1, A2, A3, A4); /// public override BivariantContinuous Im => new PolyCHelper.PolyC4Im(A0, A1, A2, A3, A4); /// 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"; /// public override Complex Evaluate(Complex x) => A0 + x * (A1 + x * (A2 + x * (A3 + x * A4))); }