public static ComplexD EvaluatePolynomialAndFirstDerivative( IList <double> coefficients, ComplexD x, out ComplexD firstDerivative) { int index1 = coefficients.Count - 1; double coefficient1 = coefficients[index1]; firstDerivative = (ComplexD)(coefficient1 * (double)index1); ComplexD complexD = (ComplexD)coefficient1; int index2; for (index2 = index1 - 1; index2 > 0; --index2) { double coefficient2 = coefficients[index2]; firstDerivative = x * firstDerivative + (ComplexD)(coefficient2 * (double)index2); complexD = x * complexD + (ComplexD)coefficient2; } if (index2 == 0) { double coefficient2 = coefficients[index2]; complexD = x * complexD + (ComplexD)coefficient2; } return(complexD); }
public static bool AreApproxEqual(ComplexD u, ComplexD v, double tolerance) { if (System.Math.Abs(v.Real - u.Real) <= tolerance) { return(System.Math.Abs(v.Imaginary - u.Imaginary) <= tolerance); } return(false); }
public bool Equals(ComplexD other) { if (this.Real == other.Real) { return(this.Imaginary == other.Imaginary); } return(false); }
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 ComplexD EvaluatePolynomial(IList <double> coefficients, ComplexD x) { int num = coefficients.Count - 1; IList <double> doubleList = coefficients; int index1 = num; int index2 = index1 - 1; ComplexD complexD = (ComplexD)doubleList[index1]; for (; index2 >= 0; --index2) { complexD = x * complexD + (ComplexD)coefficients[index2]; } return(complexD); }
public static bool AreApproxEqual(ComplexD u, ComplexD v) { return(ComplexD.AreApproxEqual(u, v, 8.88178419700125E-16)); }
public static double MultiplyAndGetReal(ComplexD u, ComplexD v) { return(u.Real * v.Real - u.Imaginary * v.Imaginary); }
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); } } }
public static IList <double> GetCubicPolynomialRoots(IList <double> coefficients) { if (coefficients == null) { throw new ArgumentNullException(nameof(coefficients)); } if (coefficients.Count < 4) { throw new ArgumentException("The coefficients should at least have length 4."); } double coefficient1 = coefficients[3]; if (coefficient1 == 0.0) { throw new ArgumentException("Coefficient a is zero."); } double coefficient2 = coefficients[2]; double coefficient3 = coefficients[1]; double coefficient4 = coefficients[0]; double num1 = coefficient2 * coefficient2; double num2 = coefficient1 * coefficient3; double num3 = coefficient1 * coefficient4; double a = num1 - 3.0 * num2; double num4 = coefficient2 * (2.0 * num1 - 9.0 * num2) + 27.0 * coefficient1 * num3; double d = num4 * num4 - 4.0 * a * a * a; double[] numArray; if (d < -8.88178419700125E-16) { double num5 = System.Math.Sqrt(-d); ComplexD complexD = new ComplexD(0.5 * num4, 0.5 * num5); ComplexD v = ComplexD.FromModulusAndArgument(System.Math.Pow(complexD.GetModulusSquared(), 1.0 / 6.0), 1.0 / 3.0 * complexD.GetArgument()); ComplexD conjugate = v.GetConjugate(); double num6 = -1.0 / (3.0 * coefficient1); numArray = new double[3] { num6 *(coefficient2 + v.Real + conjugate.Real), num6 *(coefficient2 + ComplexD.MultiplyAndGetReal(MathUtil.complexD_2, v) + ComplexD.MultiplyAndGetReal(MathUtil.complexD_3, conjugate)), num6 *(coefficient2 + ComplexD.MultiplyAndGetReal(MathUtil.complexD_4, v) + ComplexD.MultiplyAndGetReal(MathUtil.complexD_5, conjugate)) }; } else if (d > 8.88178419700125E-16) { double num5 = System.Math.Sqrt(d); double x1 = 0.5 * (num4 + num5); double x2 = 0.5 * (num4 - num5); double num6 = x1 >= 0.0 ? System.Math.Pow(x1, 1.0 / 3.0) : -System.Math.Pow(-x1, 1.0 / 3.0); double num7 = x2 >= 0.0 ? System.Math.Pow(x2, 1.0 / 3.0) : -System.Math.Pow(-x2, 1.0 / 3.0); numArray = new double[1] { -(coefficient2 + num6 + num7) / (3.0 * coefficient1) }; } else if (MathUtil.AreApproxEqual(a, 0.0, 8.88178419700125E-16)) { numArray = new double[1] { -coefficient2 / (3.0 * coefficient1) } } ; else { numArray = new double[2] { (9.0 * num3 - coefficient2 * coefficient3) / (2.0 * a), (4.0 * coefficient2 * num2 - 9.0 * coefficient1 * num3 - coefficient2 * num1) / (coefficient1 * a) } }; return((IList <double>)numArray); }