public static Tuple<List<BigFloat>, List<BigFloat>> Solve(int n, int n_iters, BigFloat tolerance, List<BigFloat> initialGuess, List<BigFloat> zi) { int m = initialGuess.Count, i, j, k; BigFloat d = 0, pa, pb, a, b, qa, qb, k1, k2, k3, na, nb, s1, s2; for (i = 0; i < n_iters; ++i) { d = 0.0; for (j = 0; j < m; ++j) { //Read in zj pa = initialGuess[j]; pb = zi[j]; //Compute denominator // // (zj - z0) * (zj - z1) * ... * (zj - z_{n-1}) // a = 1.0; b = 0.0; for (k = 0; k < m; ++k) { if (k == j) { continue; } qa = pa - initialGuess[k]; qb = pb - zi[k]; if (qa * qa + qb * qb < tolerance) { continue; } k1 = qa * (a + b); k2 = a * (qb - qa); k3 = b * (qa + qb); a = k1 - k3; b = k1 + k2; } //Compute numerator na = RealNumbers[n - 1]; nb = ImaginaryNumbers[n - 1]; s1 = pb - pa; s2 = pa + pb; for (k = n - 2; k >= 0; --k) { k1 = pa * (na + nb); k2 = na * s1; k3 = nb * s2; na = k1 - k3 + RealNumbers[k]; nb = k1 + k2 + ImaginaryNumbers[k]; } //Compute reciprocal k1 = a * a + b * b; if (BigFloat.Abs(k1) > Epsilon) { a /= k1; b /= -k1; } else { a = 1.0; b = 0.0; } //Multiply and accumulate k1 = na * (a + b); k2 = a * (nb - na); k3 = b * (na + nb); qa = k1 - k3; qb = k1 + k2; initialGuess[j] = pa - qa; zi[j] = pb - qb; d = BigFloat.Max(d, BigFloat.Max(BigFloat.Abs(qa), BigFloat.Abs(qb))); } //If converged, exit early if (d < tolerance) { break; } } // Post process: Combine any repeated roots int count; for (i = 0; i < m; ++i) { count = 1; a = initialGuess[i]; b = zi[i]; for (j = 0; j < m; ++j) { if (i == j) { continue; } if (Near(initialGuess[i], zi[i], initialGuess[j], zi[j], tolerance)) { ++count; a += initialGuess[j]; b += zi[j]; } } if (count > 1) { a /= count; b /= count; for (j = 0; j < m; ++j) { if (i == j) { continue; } if (Near(initialGuess[i], zi[i], initialGuess[j], zi[j], tolerance)) { initialGuess[j] = a; zi[j] = b; } } initialGuess[i] = a; zi[i] = b; } } for(i=0;i<initialGuess.Count;i++) { if(BigFloat.Abs(zi[i]) < Epsilon) { zi[i] = 0; } if (BigFloat.Abs(initialGuess[i]) < Epsilon) { initialGuess[i] = 0; } } // Order by size List<Tuple<BigFloat, BigFloat>> Elements = initialGuess.Zip(zi, (x, y) => Tuple.Create(x, y)).OrderByDescending(x => x.Item2.IsZero()).ToList(); Elements = Elements.OrderBy(x => x.Item1).ToList(); // Clear zi = new List<BigFloat>(); initialGuess = new List<BigFloat>(); for (i = 0; i < Elements.Count; i++) { bool found = false; for (j = 0; j < zi.Count; j++) { if (zi[j] == Elements[i].Item2 && initialGuess[j] == Elements[i].Item1) { found = true; } } if (!found) { zi.Add(Elements[i].Item2); initialGuess.Add(Elements[i].Item1); } } // Round the result foreach(BigFloat s in initialGuess) { BigFloat c = new BigFloat(s); c.FPart(); if (BigFloat.Abs(c) < tolerance) { s.Floor(); } } return new Tuple<List<BigFloat>, List<BigFloat>>(initialGuess, zi); }