cgal/Algebraic_kernel_d/include/CGAL/RS/polynomial_1_eval.h

127 lines
4.1 KiB
C++

// Copyright (c) 2006-2010 Inria Lorraine (France). 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; either version 3 of the License,
// or (at your option) any later version.
//
// 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: Luis Peñaranda <luis.penaranda@gmx.com>
#ifndef CGAL_RS_POLYNOMIAL_1_EVAL_H
#define CGAL_RS_POLYNOMIAL_1_EVAL_H
namespace CGAL{
// This function uses the Horner's method to evaluate the polynomial.
inline
void RS_polynomial_1::eval_dyadic(CGALRS_dyadic_ptr h,
CGALRS_dyadic_srcptr x)const{
int d=get_degree();
CGALRS_dyadic_set_z(h,leading_coefficient());
for(int i=1;i<d+1;++i){
CGALRS_dyadic_mul(h,h,x);
CGALRS_dyadic_add_z(h,h,coef(d-i));
}
}
inline
void RS_polynomial_1::eval_mpfr(mpfr_ptr result,mpfr_srcptr xcoord)const{
// mpfr and dyadic are now the same struct
this->eval_dyadic(result,xcoord);
}
inline
void RS_polynomial_1::inexact_eval_mpfr(mpfr_ptr h,mpfr_srcptr x)const{
int d=get_degree();
mpfr_set_z(h,leading_coefficient(),GMP_RNDN);
for(int i=1;i<d+1;++i){
mpfr_mul(h,h,x,GMP_RNDN);
mpfr_add_z(h,h,coef(d-i),GMP_RNDN);
}
}
// Evaluation of a polynomial in a given interval using Horner's rule.
// y=p(x), y must be already initialized.
inline
void RS_polynomial_1::eval_mpfi(mpfi_ptr y,mpfi_srcptr x)const{
int d=get_degree();
mpfi_set_z(y,leading_coefficient());
for(int i=1;i<d+1;++i){
mpfi_mul(y,y,x);
mpfi_add_z(y,y,coef(d-i));
}
}
// Sign determination is essentially the same that evaluation. As we only
// want to know the sign, we don't finish the Horner's evaluation.
inline
Sign RS_polynomial_1::sign_dyadic(CGALRS_dyadic_srcptr x)const{
int d,s;
CGALRS_dyadic_t h;
if(!(d=get_degree())){
s=mpz_sgn(coef(0));
return(s?(s>0?CGAL::POSITIVE:CGAL::NEGATIVE):CGAL::ZERO);
}
CGALRS_dyadic_init_set_z(h,leading_coefficient());
for(int i=1;i<d;++i){
CGALRS_dyadic_mul(h,h,x);
CGALRS_dyadic_add_z(h,h,coef(d-i));
}
CGALRS_dyadic_mul(h,h,x);
CGALRS_dyadic_neg(h,h);
s=mpfr_cmp_z(h,coef(0));
return(s?(s>0?CGAL::NEGATIVE:CGAL::POSITIVE):CGAL::ZERO);
}
inline
Sign RS_polynomial_1::sign_mpfr(mpfr_srcptr x)const{
// no need to convert mpfr to dyadic anymore:
// they are now the same struct
return sign_dyadic(x);
}
// calculates the sign of the evaluation of a polynomial in a given interval
inline
RS::rs_sign RS_polynomial_1::sign_mpfi(mpfi_srcptr x)const{
mpfi_t y;
int l,r,d;
if(!(d=get_degree())){
l=mpz_sgn(coef(0));
return(l?(l>0?RS::RS_POSITIVE:RS::RS_NEGATIVE):RS::RS_ZERO);
}
// TODO: check if the precision is ok (Fabrice said that we lose
// one bit per operation, there are 2*d operations and with three
// we are on the safe side, but with two it works better)
mpfi_init2(y,mpfi_get_prec(x)+2*d);
mpfi_set_z(y,leading_coefficient());
for(int i=d-1;i>=0;--i){
mpfi_mul(y,y,x);
mpfi_add_z(y,y,coef(i));
}
l=mpfr_sgn(&y->left);
if(l>0){
mpfi_clear(y);
return RS::RS_POSITIVE;
}
r=mpfr_sgn(&y->right);
mpfi_clear(y);
if(r<0)
return RS::RS_NEGATIVE;
if(!l&&!r)
return RS::RS_ZERO;
return RS::RS_UNKNOWN;
}
} // namespace CGAL
#endif // CGAL_RS_POLYNOMIAL_1_EVAL_H