public ComplexD GetSqrt() { if (this.Imaginary == 0.0) { return(ComplexD.Sqrt(this.Real)); } double modulus = this.GetModulus(); return(new ComplexD((double)System.Math.Sign(this.Imaginary) * System.Math.Sqrt(0.5 * (modulus + this.Real)), System.Math.Sqrt(0.5 * (modulus - this.Real)))); }
public static void GetPolynomialRoots( IList <double> coefficients, IList <double> roots, double epsilon) { if (roots == null) { throw new ArgumentNullException(nameof(roots)); } if (coefficients.Count < 2) { throw new ArgumentException("Number of coefficients must be 2 or greater."); } if (coefficients[coefficients.Count - 1] == 0.0) { throw new ArgumentException("The highest coefficient is expected to be non-zero."); } if (epsilon == 0.0) { epsilon = -1E-08; } if (coefficients.Count == 2) { roots.Add(-coefficients[0] / coefficients[1]); } else if (coefficients.Count == 3) { MathUtil.GetQuadraticPolynomialRoots(coefficients, roots); } else if (coefficients.Count == 4) { IList <double> cubicPolynomialRoots = MathUtil.GetCubicPolynomialRoots(coefficients); for (int index = 0; index < cubicPolynomialRoots.Count; ++index) { roots.Add(cubicPolynomialRoots[index]); } } else { double rootBoundsRadius = MathUtil.GetPolynomialSingleRootBoundsRadius(coefficients); Pair <ComplexD> pair1 = new Pair <ComplexD>((ComplexD)(-rootBoundsRadius), (ComplexD)MathUtil.EvaluatePolynomial(coefficients, -rootBoundsRadius)); Pair <ComplexD> pair2 = new Pair <ComplexD>((ComplexD)0.0, (ComplexD)MathUtil.EvaluatePolynomial(coefficients, 0.0)); Pair <ComplexD> pair3 = new Pair <ComplexD>((ComplexD)rootBoundsRadius, (ComplexD)double.NaN); double num1 = epsilon > 0.0 ? epsilon : -epsilon * rootBoundsRadius; double num2 = num1 * num1; int num3; ComplexD first1; for (num3 = 50; (pair3.First - pair2.First).GetModulusSquared() > num2 && num3 > 0; pair3 = new Pair <ComplexD>(first1, new ComplexD(double.NaN))) { --num3; Pair <ComplexD> pair4 = new Pair <ComplexD>(pair3.First, MathUtil.EvaluatePolynomial(coefficients, pair3.First)); ComplexD dividedDifference = MathUtil.GetDividedDifference((IList <Pair <ComplexD> >) new Pair <ComplexD>[3] { pair1, pair2, pair4 }, 0, 3); ComplexD complexD1 = MathUtil.GetDividedDifference((IList <Pair <ComplexD> >) new Pair <ComplexD>[2] { pair2, pair4 }, 0, 2) + dividedDifference * (pair4.First - pair2.First); ComplexD second = pair4.Second; ComplexD complexD2 = complexD1 * complexD1 - 4.0 * dividedDifference * second; first1 = new ComplexD(double.NaN); if (complexD2.Imaginary == 0.0) { if (complexD2.Real >= 0.0) { first1 = second.Imaginary != 0.0 || complexD1.Imaginary != 0.0 ? pair4.First - 2.0 * second / (complexD1 + (ComplexD)((double)System.Math.Sign(complexD1.Real) * System.Math.Sqrt(complexD2.Real))) : pair4.First - (ComplexD)(2.0 * second.Real / (complexD1.Real + (double)System.Math.Sign(complexD1.Real) * System.Math.Sqrt(complexD2.Real))); } else { ComplexD complexD3 = ComplexD.Sqrt(complexD2.Real); ComplexD complexD4 = complexD1 + complexD3; ComplexD complexD5 = complexD1 - complexD3; ComplexD complexD6 = complexD4.GetModulusSquared() >= complexD5.GetModulusSquared() ? complexD4 : complexD5; first1 = pair4.First - 2.0 * second / complexD6; } } else { ComplexD sqrt = complexD2.GetSqrt(); ComplexD complexD3 = complexD1 + sqrt; ComplexD complexD4 = complexD1 - sqrt; ComplexD complexD5 = complexD3.GetModulusSquared() >= complexD4.GetModulusSquared() ? complexD3 : complexD4; first1 = pair4.First - 2.0 * second / complexD5; } pair1 = pair2; pair2 = pair4; } if (num3 <= 0) { return; } if (MathUtil.AreApproxEqual(pair3.First.Imaginary, 0.0, num1)) { double real = pair3.First.Real; roots.Add(real); IList <double> coefficients1 = MathUtil.DeflatePolynomial(coefficients, real); if (epsilon > 0.0) { while (coefficients1.Count > 1 && MathUtil.AreApproxEqual(MathUtil.EvaluatePolynomial(coefficients1, real), 0.0, epsilon)) { coefficients1 = MathUtil.DeflatePolynomial(coefficients1, real); } } else { double largestTerm; while (coefficients1.Count > 1 && MathUtil.AreApproxEqual(MathUtil.EvaluatePolynomial(coefficients1, real, out largestTerm), 0.0, -epsilon * largestTerm)) { coefficients1 = MathUtil.DeflatePolynomial(coefficients1, real); } } MathUtil.GetPolynomialRoots(coefficients1, roots, num1); } else { ComplexD first2 = pair3.First; double real = first2.Real; double imaginary = first2.Imaginary; double a1 = -2.0 * real; double a0 = real * real + imaginary * imaginary; MathUtil.GetPolynomialRoots(MathUtil.DeflatePolynomial(coefficients, a0, a1), roots, num1); } } }