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