/// <summary> /// Solves the equation \f$e + d x + c x^2 + b x^3 + a x^4 = 0\f$, returning all real values of /// \f$x\f$ for which the equation is true. See https://en.wikipedia.org/wiki/Quartic_function for the /// algorithm used. /// </summary> public static IEnumerable <float> Solve(float e2, float d2, float c2, float b2, float a2) { if (Math.Abs(a2) <= 0.005f) { foreach (float v in CubicFunction.Solve(e2, d2, c2, b2)) { yield return(v); } yield break; } double a = a2; double b = b2; double c = c2; double d = d2; double e = e2; double ba = b / a; double ca = c / a; double da = d / a; double ea = e / a; double p1 = c * c * c - 4.5 * b * c * d + 13.5 * a * d * d + 13.5 * b * b * e - 36.0 * a * c * e; double q = c * c - 3.0 * b * d + 12.0 * a * e; Complex p2 = p1 + Complex.Sqrt(-q * q * q + p1 * p1); Complex pow = Complex.Pow(p2, (1.0 / 3.0)); Complex p3 = q / (3.0 * a * pow) + pow / (3.0 * a); Complex p4 = Complex.Sqrt(ba * ba / 4.0 - 2.0 * ca / (3.0) + p3); Complex p5 = b * b / (2.0 * a * a) - 4.0 * c / (3.0 * a) - p3; Complex p6 = (-ba * ba * ba + 4.0 * ba * ca - 8.0 * da) / (4.0 * p4); List <Complex> roots = new List <Complex> { -ba / (4.0) - p4 / 2.0 - 0.5 * Complex.Sqrt(p5 - p6), -ba / (4.0) - p4 / 2.0 + 0.5 * Complex.Sqrt(p5 - p6), -ba / (4.0) + p4 / 2.0 - 0.5 * Complex.Sqrt(p5 + p6), -ba / (4.0) + p4 / 2.0 + 0.5 * Complex.Sqrt(p5 + p6), }; foreach (Complex root in roots) { if (Math.Abs(root.Imaginary) <= 0.005f) { yield return((float)root.Real); } } }
/// <summary> /// Solves the equation \f$a0 + a1 x + a2 x^2 + a3 x^3 + a4 x^4 = 0\f$, returning all real values of /// \f$x\f$ for which the equation is true. See https://en.wikipedia.org/wiki/Quartic_function for the /// algorithm used. /// </summary> public static IEnumerable <double> Solve(double a0, double a1, double a2, double a3, double a4) { DebugUtil.AssertAllFinite(new double[] { a0, a1, a2, a3, a4 }, "a"); if (Math.Abs(a4) <= 0.005) { foreach (double v in CubicFunction.Solve(a0, a1, a2, a3)) { QuarticFunction f = new QuarticFunction(a0, a1, a2, a3, a4); yield return(f.NewtonRaphson(v)); } yield break; } double ba = a3 / a4; double ca = a2 / a4; double da = a1 / a4; // double ea = a0/a4; double p1 = a2 * a2 * a2 - 4.5 * a3 * a2 * a1 + 13.5 * a4 * a1 * a1 + 13.5 * a3 * a3 * a0 - 36.0 * a4 * a2 * a0; double q = a2 * a2 - 3.0 * a3 * a1 + 12.0 * a4 * a0; Complex p2 = p1 + Complex.Sqrt(-q * q * q + p1 * p1); Complex pow = Complex.Pow(p2, (1.0 / 3.0)); Complex p3 = q / (3.0 * a4 * pow) + pow / (3.0 * a4); Complex p4 = Complex.Sqrt(ba * ba / 4.0 - 2.0 * ca / (3.0) + p3); Complex p5 = a3 * a3 / (2.0 * a4 * a4) - 4.0 * a2 / (3.0 * a4) - p3; Complex p6 = (-ba * ba * ba + 4.0 * ba * ca - 8.0 * da) / (4.0 * p4); List <Complex> roots = new List <Complex> { -ba / (4.0) - p4 / 2.0 - 0.5 * Complex.Sqrt(p5 - p6), -ba / (4.0) - p4 / 2.0 + 0.5 * Complex.Sqrt(p5 - p6), -ba / (4.0) + p4 / 2.0 - 0.5 * Complex.Sqrt(p5 + p6), -ba / (4.0) + p4 / 2.0 + 0.5 * Complex.Sqrt(p5 + p6), }; foreach (Complex root in roots) { if (Math.Abs(root.Imaginary) <= 0.005) { DebugUtil.AssertFinite(root.Real, nameof(root.Real)); yield return(root.Real); } } }
public IEnumerable <float> Roots() { return(CubicFunction.Solve(a0, a1, a2, a3)); }