// Copyright (c) 2005 Stanford University (USA). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; version 2.1 of the License. // See the file LICENSE.LGPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Daniel Russel #include #include #include #include #include /*#ifdef _MSC_VER #pragma warning(disable:1572) #endif*/ CGAL_POLYNOMIAL_BEGIN_INTERNAL_NAMESPACE static double max_error_value=.00005; namespace { template inline void compute_quadratic_roots_t(const NT *begin, const NT * /*end*/, NT lb, NT ub, std::vector &roots) { NT max_error=0; if (CLEAN) max_error=max_error_value; CGAL_Polynomial_assertion(begin[2] != 0); NT desc= begin[1]*begin[1]-4*begin[0]*begin[2]; if (desc <= 0) return; NT ur= (-begin[1]+sqrt(desc))/(2*begin[2]); NT lr= (-begin[1]-sqrt(desc))/(2*begin[2]); if (begin[2]< 0) std::swap(lr, ur); if (lr > lb-max_error && lr < ub) { roots.push_back(ur); if (lr > lb-max_error && lr < ub && (!CLEAN || /*lr > lb+max_error ||*/ begin[2] >0)){ roots.push_back(lr); } } else { // only upper if (ur > lb-max_error && ur < ub && (!CLEAN || /*ur > lb+max_error ||*/ begin[2] <0)){ roots.push_back(ur); } } // drop even roots /*if (ur >lb-max_error && ur < ub){ if (!CLEAN || sign(begin[2]) != POSITIVE){ roots.push_back(ur); if (lr >lb-max_error && lr < ub){ roots.push_back(lr); } } } else { if (lr > lb-max_error && lr &roots) { return compute_quadratic_roots_t(begin, end, lb, ub, roots); } void compute_quadratic_cleaned_roots(const double *begin, const double *end, double lb, double ub, std::vector &roots) { return compute_quadratic_roots_t(begin, end, lb, ub, roots); } namespace { template inline void compute_linear_roots_t(const NT *begin, const NT *, NT lb, NT ub, std::vector &roots) { if (CLEAN && begin[1]>0 ) return; //NT max_error=0; //if (CLEAN) max_error=max_error_value; NT r= -to_double(begin[0]/begin[1]); if ((CLEAN || r > lb) && r < ub) { roots.push_back(r); } } } void compute_linear_roots(const double *begin, const double *end, double lb, double ub, std::vector &roots) { return compute_linear_roots_t(begin, end, lb, ub, roots); } void compute_linear_cleaned_roots(const double *begin, const double *end, double lb, double ub, std::vector &roots) { return compute_linear_roots_t(begin, end, lb, ub, roots); } namespace { template inline void filter_roots_t(const NT *begin, const NT *end, NT lb, NT ub, NT last_root, std::vector &roots) { // if we are not close to the current time, then we are fine if (roots.empty()) return; //if (roots.back() > lb+ .0005) return; //double eps= .0005; /*double last_root=-std::numeric_limits::infinity(); while (roots.back() < lb) { last_root= roots.back(); roots.pop_back(); }*/ //if (roots.back() > lb+eps) return; //typedef CGAL_POLYNOMIAL_NS::Polynomial Fn; typedef CGAL_POLYNOMIAL_NS::Interval_polynomial IFn; typedef CGAL_POLYNOMIAL_NS::internal::Derivative Diff; typedef typename IFn::NT INT; /*bool popped=false;*/ // if the last valid root is closer than last, consider it as doubtful instead if (lb-last_root > roots.back()-lb) { last_root= roots.back(); roots.pop_back(); /*popped=true;*/ } /*else { last_root=lb; }*/ INT vi; if (last_root== -std::numeric_limits::infinity()){ if ((end-begin)%2==1) { vi= std::numeric_limits::infinity(); } else { vi = -*(end-1); } } else { IFn fi(begin, end); if (roots.empty()) { Interval_arithmetic_guard guard; if (ub== std::numeric_limits::infinity()) { vi = 10*lb + 1000; } else { vi = fi((INT(lb)+INT(ub))/2.0); } } else { Interval_arithmetic_guard guard; vi = fi((INT(last_root)+INT(roots.back()))/2.0); } } if (vi.inf() > 0) { return; } else if (vi.sup() < 0){ roots.push_back(last_root); /*if (!popped) { IFn f(begin, end); std::cout << "Adding last due to sign of " << vi << std::endl; std::cout << "last " << last_root << " lb " << lb << " poly " << f << std::endl; }*/ return; } Interval_arithmetic_guard guard; Diff dx; IFn f(begin, end); IFn d= dx(f); INT dv= d(roots.back()); // switch //while (sign(d(roots.back().representation()))== ZERO) d= dx_(d); while (dv.inf() <= 0 && dv.sup() >= 0) { d= dx(d); dv= d(roots.back()); } // switch //if (sign(d(roots.back().representation()))==POSITIVE){ if (dv.sup() < 0) { roots.push_back(last_root); /*if (!popped) { IFn f(begin, end); std::cout << "Adding last due to deriv of " << vi << std::endl; std::cout << "last " << last_root << " lb " << lb << " poly " << f << std::endl; }*/ } } } void filter_solver_roots(const double *begin, const double *end, double lb, double ub, double last, std::vector &roots) { filter_roots_t(begin, end, lb, ub, last, roots); } /*void polynomial_compute_roots(const double *begin, const double *end, double lb, double ub, std::vector &roots){ #ifdef POLYNOMIAL_USE_GSL gsl_polynomial_compute_roots(begin, end, lb, ub, roots); #else jama_polynomial_compute_roots(begin, end, lb, ub, roots); #endif } void polynomial_compute_cleaned_roots(const double *begin, const double *end, double lb, double ub, std::vector &roots){ #ifdef POLYNOMIAL_USE_GSL gsl_polynomial_compute_cleaned_roots(begin, end, lb, ub, roots); #else jama_polynomial_compute_cleaned_roots(begin, end, lb, ub, roots); #endif }*/ double evaluate_polynomial(const double *b, const double *e, double t) { #ifdef POLYNOMIAL_USE_GSL return gsl_evaluate_polynomial(b, e, t); #else if (b==e) return 0.0; const double *rit=e-1; double result = *rit; --rit; for (; rit != b-1; --rit) { result *= t; result += (*rit); } return result; #endif } CGAL_POLYNOMIAL_END_INTERNAL_NAMESPACE