double Polynomial::newtonRaphson(double guess){ Polynomial deriv = this->derivative(); double nextGuess = guess; double fVal = this->evaluate(nextGuess); while(std::abs(fVal) > .000000001){ if(0 == deriv.evaluate(nextGuess)){ nextGuess += 1; } nextGuess -= (fVal)/(deriv.evaluate(nextGuess)); fVal = this->evaluate(nextGuess); } return nextGuess; }
vector<CoeffT> Polynomial<CoeffT>::roots(size_t num_iterations, CoeffT ztol) const { assert(c.size() >= 1); size_t n = c.size() - 1; // initial guess vector<complex<CoeffT>> z0(n); for (size_t j = 0; j < n; j++) { z0[j] = pow(complex<double>(0.4, 0.9), j); } // durand-kerner-weierstrass iterations Polynomial<CoeffT> p = this->normalize(); for (size_t k = 0; k < num_iterations; k++) { complex<CoeffT> num, den; for (size_t i = 0; i < n; i++) { num = p.evaluate(z0[i]); den = 1.0; for (size_t j = 0; j < n; j++) { if (j == i) { continue; } den = den * (z0[i] - z0[j]); } z0[i] = z0[i] - num / den; } } vector<CoeffT> roots(n); for (size_t j = 0; j < n; j++) { roots[j] = abs(z0[j]) < ztol ? 0.0 : real(z0[j]); } sort(roots.begin(), roots.end()); return roots; }
Intervals PolynomialIntervalSolver::findPolyIntervals(const Polynomial &poly) { const double eps = 1e-8; int leadcoeff=0; std::vector<Interval> empty; std::vector<Interval> all; all. push_back(Interval(-std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity())); const std::vector<double> &coeffs = poly.getCoeffs(); int deg = coeffs.size()-1; for(int i=0; i<(int)coeffs.size(); i++) assert(!isnan(coeffs[i])); // get rid of leading 0s // for(leadcoeff=0; leadcoeff < (int)coeffs.size() && fabs(coeffs[leadcoeff]) < eps; leadcoeff++) // { // deg--; // } // check for the zero polynomial if(deg < 0) { return Intervals(empty); } // check for constant polynomial if(deg == 0) { double val = poly.evaluate(0); if(val > 0) { return Intervals(all); } return Intervals(empty); } // nonconstant polynomial... rpoly time!!! assert(deg <= 6); double zeror[6]; double zeroi[6]; int numroots = rf.rpoly(&coeffs[leadcoeff], deg, zeror, zeroi); std::vector<double> roots; for(int i=0; i<numroots; i++) if( fabs(zeroi[i]) < eps ) roots.push_back(zeror[i]); // no roots: check at 0 if(roots.size() == 0) { double val = poly.evaluate(0); if(val > 0) return Intervals(all); return Intervals(empty); } std::sort(roots.begin(), roots.end()); std::vector<Interval> intervals; for(int i=0; i<(int)roots.size(); i++) { if(i == 0) { //check poly on (-inf, r) double t = roots[i]-1; double val = poly.evaluate(t); if(val > 0) { intervals.push_back(Interval(-std::numeric_limits<double>::infinity(), roots[i])); } } if(i == (int)roots.size()-1) { //check poly on (r, inf) double t = roots[i]+1; double val = poly.evaluate(t); if(val > 0) { intervals.push_back(Interval(roots[i], std::numeric_limits<double>::infinity())); } } if(i < (int)roots.size()-1) { // check poly on (r, r+1) double t = 0.5*(roots[i]+roots[i+1]); double val = poly.evaluate(t); if(val > 0) { intervals.push_back(Interval(roots[i], roots[i+1])); } } } return Intervals(intervals); }