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)); }
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)); }
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); }
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); }
/// <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); } }
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); }
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; } }