Пример #1
0
        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);
        }
Пример #2
0
 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);
 }
Пример #3
0
 public bool Equals(ComplexD other)
 {
     if (this.Real == other.Real)
     {
         return(this.Imaginary == other.Imaginary);
     }
     return(false);
 }
Пример #4
0
        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))));
        }
Пример #5
0
        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);
        }
Пример #6
0
 public static bool AreApproxEqual(ComplexD u, ComplexD v)
 {
     return(ComplexD.AreApproxEqual(u, v, 8.88178419700125E-16));
 }
Пример #7
0
 public static double MultiplyAndGetReal(ComplexD u, ComplexD v)
 {
     return(u.Real * v.Real - u.Imaginary * v.Imaginary);
 }
Пример #8
0
 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);
         }
     }
 }
Пример #9
0
        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);
        }