/*
    Copyright (C) 2016 Vincent Delecroix

    This file is part of e-ANTIC

    e-ANTIC is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 2.1 of the License, or
    (at your option) any later version.  See <http://www.gnu.org/licenses/>.
*/


*******************************************************************************

    Polynomial functions

*******************************************************************************

void _fmpz_poly_scale_2exp(fmpz * pol, slong len, slong k)

    Scale \code{(pol, len)} to $p(2^k X)$ inplace and divide by the
    2-content (so that the gcd of coefficients is odd). If \code{k}
    is negative the polynomial is multiplied by $2^{kd}$.

*******************************************************************************

    Polynomial evaluation

*******************************************************************************


void _fmpz_poly_evaluate_arb(arb_t res, const fmpz * pol, slong len, const arb_t a, slong prec);
void fmpz_poly_evaluate_arb(arb_t b, const fmpz_poly_t pol, const arb_t a, slong prec);
void fmpq_poly_evaluate_arb(arb_t b, const fmpq_poly_t pol, const arb_t a, slong prec);


void _fmpz_poly_evaluate_acb(acb_t b, const fmpz * pol, slong len, const acb_t a, slong prec);
void fmpz_poly_evaluate_acb(acb_t b, const fmpz_poly_t pol, const acb_t a, slong prec);
void fmpq_poly_evaluate_acb(acb_t b, const fmpq_poly_t pol, const acb_t a, slong prec);

void _fmpz_poly_evaluate_arf(arf_t res, const fmpz * pol, slong len, const arf_t a, slong prec);
void fmpz_poly_evaluate_arf(arf_t res, const fmpz_poly_t pol, const arf_t a, slong prec);
void fmpq_poly_evaluate_arf(arf_t b, const fmpq_poly_t pol, const arf_t a, slong prec);

*******************************************************************************

    Root refinement

*******************************************************************************

int fmpq_poly_check_unique_real_root(const fmpq_poly_t pol, const arb_t a, slong prec)

int fmpq_poly_check_unique_complex_root(const fmpq_poly_t pol, const acb_t a, slong prec)

int _fmpz_poly_newton_step_arb(arb_t res, const fmpz * pol, const fmpz * der, slong len, arb_t a, slong prec)

int fmpz_poly_newton_step_arb(arb_t res, const fmpz_poly_t pol, const fmpz_poly_t der, arb_t a, slong prec)

int _fmpz_poly_newton_step_acb(acb_t res, const fmpz * pol, const fmpz * der, slong len, acb_t a, slong prec)

int fmpz_poly_newton_step_acb(acb_t res, const fmpz_poly_t pol, const fmpz_poly_t der, acb_t a, slong prec)

void _fmpz_poly_bisection_step_arb(arb_t res, const fmpz * pol, slong len, arb_t a, slong prec)

int fmpz_poly_bisection_step_arb(arb_t res, const fmpz_poly_t pol, arb_t a, slong prec)

*******************************************************************************

    Real roots isolation

*******************************************************************************

slong _fmpz_poly_positive_root_upper_bound_2exp(fmpz * pol, slong len)

    Gives an upper bound on the bitsize of largest real root of
    \code{(pol, len)}.

slong fmpz_poly_positive_root_upper_bound_2exp(fmpz_poly_t pol)

    Gives an upper bound on the bitsize of largest real root of
    \code{pol}. 

slong _fmpz_poly_descartes_bound_0_1(fmpz * p, slong len, slong bound)

    Gives an upper bound on the number of real roots between 0 and 1
    of the polynomial \code{(p, len)} using Decartes rule of sign. If
    the result is larger than \code{bound} then \code{WORD_MAX} is
    returned.

slong fmpz_poly_num_real_roots_upper_bound(fmpz_poly_t pol)

    Gives an upper bound on the number of real roots of the polynomial
    \code{pol} (currently using Decartes rule of sign).

slong fmpz_poly_num_real_roots_in_interval_sturm(fmpz_poly_t pol, fmpq_t a, fmpq_t b)

    Compute the number of real roots of \code{pol} in the half-open
    interval (a, b] using Sturm sequence (perform pseudo-division). 

void _fmpz_poly_isolate_real_roots_0_1_vca(fmpq * exact_roots, slong * n_exact_roots, fmpz * c_array, slong * k_array, slong * n_intervals, fmpz * pol, slong len)

    Isolate the real roots of \code{(pol, len)} contained in the
    interval $(0, 1)$. The array \code{exact_roots} will be set by
    the exact diadic roots found by the algorithm and
    \code{n_exact_roots} updated accordingly. The arrays
    \code{c_array} and \code{k_array} are set to be interval data
    that enclose the remaining roots and \code{n_interval} is
    updated accordingly. A data \code{c = c_array + i} and
    \code{k = k_array[i]} represents the open interval
    $(c 2^k, (c + 1) 2^k)$.

void fmpz_poly_isolate_real_roots(fmpq * exact_roots, slong * n_exact, fmpz * c_array, slong * k_array, slong * n_interval, fmpz_poly_t pol)

    Isolate the real roots of \code{pol}. The array
    \code{exact_roots} will be set by the exact diadic roots found
    by the algorithm and \code{n_exact_roots} updated accordingly.
    The arrays \code{c_array} and \code{k_array} are set to be
    interval data that enclose the remaining roots and
    \code{n_interval} is updated accordingly. A data
    \code{c = c_array + i} and \code{k = k_array[i]} represents the
    open interval $(c 2^k, (c + 1) 2^k)$.

