Exemple #1
0
        PartialFractionDecomposition(
            WWComplex [] nCoeffs, WWComplex [] dRoots)
        {
            var result = new List <FirstOrderComplexRationalPolynomial>();

            if (dRoots.Length == 1 && nCoeffs.Length == 1)
            {
                result.Add(new FirstOrderComplexRationalPolynomial(WWComplex.Zero(),
                                                                   nCoeffs[0], WWComplex.Unity(), WWComplex.Minus(dRoots[0])));
                return(result);
            }

            if (dRoots.Length < 2)
            {
                throw new ArgumentException("denomR");
            }
            if (dRoots.Length < nCoeffs.Length)
            {
                throw new ArgumentException("nCoeffs");
            }

            for (int k = 0; k < dRoots.Length; ++k)
            {
                // cn = ... + nCoeffs[2]s^2 + nCoeffs[1]s + nCoeffs[0]
                // 係数c[0]は、s==denomR[0]としたときの、cn/(s-denomR[1])(s-denomR[2])(s-denomR[3])…(s-denomR[p-1])
                // 係数c[1]は、s==denomR[1]としたときの、cn/(s-denomR[0])(s-denomR[2])(s-denomR[3])…(s-denomR[p-1])
                // 係数c[2]は、s==denomR[2]としたときの、cn/(s-denomR[0])(s-denomR[1])(s-denomR[3])…(s-denomR[p-1])

                // 分子の値c。
                var c = WWComplex.Zero();
                var s = WWComplex.Unity();
                for (int j = 0; j < nCoeffs.Length; ++j)
                {
                    c = WWComplex.Add(c, WWComplex.Mul(nCoeffs[j], s));
                    s = WWComplex.Mul(s, dRoots[k]);
                }

                for (int i = 0; i < dRoots.Length; ++i)
                {
                    if (i == k)
                    {
                        continue;
                    }

                    c = WWComplex.Div(c, WWComplex.Sub(dRoots[k], dRoots[i]));
                }

                result.Add(new FirstOrderComplexRationalPolynomial(
                               WWComplex.Zero(), c,
                               WWComplex.Unity(), WWComplex.Minus(dRoots[k])));
            }

            return(result);
        }
        public static double Distance(WWComplex a, WWComplex b)
        {
            var s = WWComplex.Sub(a, b);

            return(s.Magnitude());
        }
        private void FindRootCubic(double[] coeffs)
        {
            // 3次多項式 cubic poly equation
            // https://en.wikipedia.org/wiki/Cubic_function#Algebraic_solution
            System.Diagnostics.Debug.Assert(4 == coeffs.Length);
            double a = coeffs[3];
            double b = coeffs[2];
            double c = coeffs[1];
            double d = coeffs[0];

            double Δ =
                18 * a * b * c * d
                - 4 * b * b * b * d
                + 1 * b * b * c * c
                - 4 * a * c * c * c
                - 27 * a * a * d * d;

            double Δ0 = b * b - 3 * a * c;

            // ↓ 雑な0かどうかの判定処理。
            if (AlmostZero(Δ))
            {
                if (AlmostZero(Δ0))
                {
                    // triple root
                    double root = -b / (3 * a);
                    mRoots.Add(new WWComplex(root, 0));
                    mRoots.Add(new WWComplex(root, 0));
                    mRoots.Add(new WWComplex(root, 0));
                    return;
                }
                // double root and a simple root
                double root2 = (9 * a * d - b * c) / (2 * Δ0);
                double root1 = (4 * a * b * c - 9 * a * a * d - b * b * b);
                mRoots.Add(new WWComplex(root2, 0));
                mRoots.Add(new WWComplex(root2, 0));
                mRoots.Add(new WWComplex(root1, 0));
                return;
            }

            {
                double Δ1 =
                    +2 * b * b * b
                    - 9 * a * b * c
                    + 27 * a * a * d;

                WWComplex C;
                {
                    WWComplex c1 = new WWComplex(Δ1 / 2, 0);

                    double    c2Sqrt = Math.Sqrt(Math.Abs(-27 * a * a * Δ) / 4);
                    WWComplex c2;
                    if (Δ < 0)
                    {
                        //C2 is real number
                        c2 = new WWComplex(c2Sqrt, 0);
                    }
                    else
                    {
                        //C2 is imaginary number
                        c2 = new WWComplex(0, c2Sqrt);
                    }

                    WWComplex c1c2;
                    WWComplex c1Pc2 = WWComplex.Add(c1, c2);
                    WWComplex c1Mc2 = WWComplex.Sub(c1, c2);
                    if (c1Mc2.Magnitude() <= c1Pc2.Magnitude())
                    {
                        c1c2 = c1Pc2;
                    }
                    else
                    {
                        c1c2 = c1Mc2;
                    }

                    // 3乗根 = 大きさが3分の1乗で角度が3分の1.
                    double magnitude = c1c2.Magnitude();
                    double phase     = c1c2.Phase();
                    double cMag      = Math.Pow(magnitude, 1.0 / 3.0);
                    double cPhase    = phase / 3;

                    C = new WWComplex(cMag * Math.Cos(cPhase), cMag * Math.Sin(cPhase));
                }

                var ζ   = new WWComplex(-1.0 / 2.0, 1.0 / 2.0 * Math.Sqrt(3.0));
                var ζ2  = new WWComplex(-1.0 / 2.0, -1.0 / 2.0 * Math.Sqrt(3.0));
                var r3a = new WWComplex(-1.0 / 3.0 / a, 0);

                WWComplex root0 = WWComplex.Mul(r3a, WWComplex.Add(
                                                    WWComplex.Add(new WWComplex(b, 0), C),
                                                    WWComplex.Div(new WWComplex(Δ0, 0), C)));

                WWComplex root1 = WWComplex.Mul(r3a, WWComplex.Add(
                                                    WWComplex.Add(new WWComplex(b, 0), WWComplex.Mul(ζ, C)),
                                                    WWComplex.Div(new WWComplex(Δ0, 0), WWComplex.Mul(ζ, C))));

                WWComplex root2 = WWComplex.Mul(r3a, WWComplex.Add(
                                                    WWComplex.Add(new WWComplex(b, 0), WWComplex.Mul(ζ2, C)),
                                                    WWComplex.Div(new WWComplex(Δ0, 0), WWComplex.Mul(ζ2, C))));

                mRoots.Add(root0);
                mRoots.Add(root1);
                mRoots.Add(root2);
                return;
            }
        }