/************************************************************************* Polynomial root finding. This function returns all roots of the polynomial P(x) = a0 + a1*x + a2*x^2 + ... + an*x^n Both real and complex roots are returned (see below). INPUT PARAMETERS: A - array[N+1], polynomial coefficients: * A[0] is constant term * A[N] is a coefficient of X^N N - polynomial degree OUTPUT PARAMETERS: X - array of complex roots: * for isolated real root, X[I] is strictly real: IMAGE(X[I])=0 * complex roots are always returned in pairs - roots occupy positions I and I+1, with: * X[I+1]=Conj(X[I]) * IMAGE(X[I]) > 0 * IMAGE(X[I+1]) = -IMAGE(X[I]) < 0 * multiple real roots may have non-zero imaginary part due to roundoff errors. There is no reliable way to distinguish real root of multiplicity 2 from two complex roots in the presence of roundoff errors. Rep - report, additional information, following fields are set: * Rep.MaxErr - max( |P(xi)| ) for i=0..N-1. This field allows to quickly estimate "quality" of the roots being returned. NOTE: this function uses companion matrix method to find roots. In case internal EVD solver fails do find eigenvalues, exception is generated. NOTE: roots are not "polished" and no matrix balancing is performed for them. -- ALGLIB -- Copyright 24.02.2014 by Bochkanov Sergey *************************************************************************/ public static void polynomialsolve(double[] a, int n, ref complex[] x, polynomialsolverreport rep) { double[,] c = new double[0,0]; double[,] vl = new double[0,0]; double[,] vr = new double[0,0]; double[] wr = new double[0]; double[] wi = new double[0]; int i = 0; int j = 0; bool status = new bool(); int nz = 0; int ne = 0; complex v = 0; complex vv = 0; a = (double[])a.Clone(); x = new complex[0]; alglib.ap.assert(n>0, "PolynomialSolve: N<=0"); alglib.ap.assert(alglib.ap.len(a)>=n+1, "PolynomialSolve: Length(A)<N+1"); alglib.ap.assert(apserv.isfinitevector(a, n+1), "PolynomialSolve: A contains infitite numbers"); alglib.ap.assert((double)(a[n])!=(double)(0), "PolynomialSolve: A[N]=0"); // // Prepare // x = new complex[n]; // // Normalize A: // * analytically determine NZ zero roots // * quick exit for NZ=N // * make residual NE-th degree polynomial monic // (here NE=N-NZ) // nz = 0; while( nz<n && (double)(a[nz])==(double)(0) ) { nz = nz+1; } ne = n-nz; for(i=nz; i<=n; i++) { a[i-nz] = a[i]/a[n]; } // // For NZ<N, build companion matrix and find NE non-zero roots // if( ne>0 ) { c = new double[ne, ne]; for(i=0; i<=ne-1; i++) { for(j=0; j<=ne-1; j++) { c[i,j] = 0; } } c[0,ne-1] = -a[0]; for(i=1; i<=ne-1; i++) { c[i,i-1] = 1; c[i,ne-1] = -a[i]; } status = evd.rmatrixevd(c, ne, 0, ref wr, ref wi, ref vl, ref vr); alglib.ap.assert(status, "PolynomialSolve: inernal error - EVD solver failed"); for(i=0; i<=ne-1; i++) { x[i].x = wr[i]; x[i].y = wi[i]; } } // // Remaining NZ zero roots // for(i=ne; i<=n-1; i++) { x[i] = 0; } // // Rep // rep.maxerr = 0; for(i=0; i<=ne-1; i++) { v = 0; vv = 1; for(j=0; j<=ne; j++) { v = v+a[j]*vv; vv = vv*x[i]; } rep.maxerr = Math.Max(rep.maxerr, math.abscomplex(v)); } }
public override alglib.apobject make_copy() { polynomialsolverreport _result = new polynomialsolverreport(); _result.maxerr = maxerr; return _result; }