public WWComplex Evaluate(WWComplex x)
        {
            WWComplex yN = WWComplex.Add(WWComplex.Mul(x, numer[1]), numer[0]);
            WWComplex yD = WWComplex.Add(WWComplex.Mul(x, denom[1]), denom[0]);

            return(WWComplex.Div(yN, yD));
        }
コード例 #2
0
        public WWComplex Evaluate(WWComplex x)
        {
            WWComplex n = WWComplex.Zero();
            {
                WWComplex xN = WWComplex.Unity();
                for (int i = 0; i < numer.Length; ++i)
                {
                    n  = WWComplex.Add(n, WWComplex.Mul(numer[i], xN));
                    xN = WWComplex.Mul(xN, x);
                }
            }

            WWComplex d = WWComplex.Zero();

            {
                WWComplex xN = WWComplex.Unity();
                for (int i = 0; i < denom.Length; ++i)
                {
                    d  = WWComplex.Add(d, WWComplex.Mul(denom[i], xN));
                    xN = WWComplex.Mul(xN, x);
                }
            }

            return(WWComplex.Div(n, d));
        }
コード例 #3
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);
        }
コード例 #4
0
        Reduction(WWComplex [] aNumerCoeffList, WWComplex [] aDenomRootList)
        {
            var rv = new PolynomialAndRationalPolynomial();

            rv.coeffList      = new WWComplex[0];
            rv.numerCoeffList = new WWComplex[aNumerCoeffList.Length];
            Array.Copy(aNumerCoeffList, rv.numerCoeffList, aNumerCoeffList.Length);
            rv.denomRootList = new WWComplex[aDenomRootList.Length];
            Array.Copy(aDenomRootList, rv.denomRootList, aDenomRootList.Length);

            if (rv.numerCoeffList.Length - 1 < rv.denomRootList.Length)
            {
                // 既に分子の多項式の次数が分母の多項式の次数よりも低い。
                return(rv);
            }

            // 分母の根のリスト⇒分母の多項式の係数のリストに変換。
            var denomCoeffList = RootListToCoeffList(aDenomRootList, new WWComplex(1, 0));

            var quotient = new List <WWComplex>();

            while (denomCoeffList.Length <= rv.numerCoeffList.Length)
            {
                // denomの最も次数が高い項の係数がcdn、numerの最も次数が高い項の係数がcnnとすると
                // denomiCoeffListを-cnn/cdn * s^(numerの次数-denomの次数)倍してnumerCoeffListと足し合わせてnumerの次数を1下げる。
                // このときrv.coeffListにc == cnn/cdnを足す。
                var c = WWComplex.Div(rv.numerCoeffList[rv.numerCoeffList.Length - 1],
                                      denomCoeffList[denomCoeffList.Length - 1]);
                quotient.Insert(0, c);
                var denomMulX = new ComplexPolynomial(denomCoeffList);
                while (denomMulX.Degree + 1 < rv.numerCoeffList.Length)
                {
                    denomMulX = ComplexPolynomial.MultiplyX(denomMulX);
                }
                denomMulX = ComplexPolynomial.MultiplyC(denomMulX, WWComplex.Mul(c, -1));

                // ここで引き算することで分子の多項式の次数が1減る。
                int expectedOrder = rv.numerCoeffList.Length - 2;
                rv.numerCoeffList = ComplexPolynomial.TrimPolynomialOrder(
                    ComplexPolynomial.Add(denomMulX, new ComplexPolynomial(rv.numerCoeffList)),
                    expectedOrder).ToArray();

                // 引き算によって一挙に2以上次数が減った場合coeffListに0を足す。
                int actualOrder = rv.numerCoeffList.Length - 1;
                for (int i = 0; i < expectedOrder - actualOrder; ++i)
                {
                    quotient.Insert(0, WWComplex.Zero());
                }
            }

            rv.coeffList = quotient.ToArray();
            return(rv);
        }
コード例 #5
0
        /// <summary>
        /// see this document: http://people.csail.mit.edu/bkph/articles/Quadratics.pdf
        /// </summary>
        private void FindRootQuadratic(double[] coeffs)
        {
            // 2次多項式 quadratic poly equation
            System.Diagnostics.Debug.Assert(3 == coeffs.Length);

            double a = coeffs[2];
            double b = coeffs[1];
            double c = coeffs[0];

            double discriminant = b * b - 4 * a * c;

            if (0 <= discriminant)
            {
                double x1;
                double x2;

                if (0 <= b)
                {
                    x1 = 2 * c / (-b - Math.Sqrt(discriminant));
                    x2 = (-b - Math.Sqrt(discriminant)) / 2 / a;
                }
                else
                {
                    x1 = (-b + Math.Sqrt(discriminant)) / 2 / a;
                    x2 = 2 * c / (-b + Math.Sqrt(discriminant));
                }

                mRoots.Add(new WWComplex(x1, 0));
                mRoots.Add(new WWComplex(x2, 0));
            }
            else
            {
                WWComplex x1;
                WWComplex x2;

                if (0 <= b)
                {
                    x1 = new WWComplex(-b / 2 / a, -Math.Sqrt(-discriminant) / 2 / a);
                    x2 = WWComplex.Div(new WWComplex(2 * c, 0), new WWComplex(-b, -Math.Sqrt(-discriminant)));
                }
                else
                {
                    x1 = WWComplex.Div(new WWComplex(2 * c, 0), new WWComplex(-b, Math.Sqrt(-discriminant)));
                    x2 = new WWComplex(-b / 2 / a, Math.Sqrt(-discriminant) / 2 / a);
                }

                mRoots.Add(x1);
                mRoots.Add(x2);
            }
        }
コード例 #6
0
        public WWComplex Evaluate(WWComplex x)
        {
            WWComplex n  = WWComplex.Zero();
            WWComplex xN = WWComplex.Unity();

            for (int i = 0; i < numer.Length; ++i)
            {
                n  = WWComplex.Add(n, WWComplex.Mul(xN, numer[i]));
                xN = WWComplex.Mul(xN, x);
            }

            WWComplex d = WWComplex.Zero();

            xN = WWComplex.Unity();
            for (int i = 0; i < denom.Length; ++i)
            {
                d  = WWComplex.Add(d, WWComplex.Mul(xN, denom[i]));
                xN = WWComplex.Mul(xN, x);
            }

            WWComplex y = WWComplex.Div(n, d);

            return(y);
        }
コード例 #7
0
        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;
            }
        }