//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995, 1996 by the LiDIA Group
//
// File        : bigfloat_polynomial.cc
// Author      : Stefan Neis (SN)

/*
$Id: bigfloat_polynomial.c,v 1.4 1997/01/21 22:27:05 neis Exp $
*/

#include <LiDIA/bigfloat.h>

#include <LiDIA/polynomial.h>
#ifndef LIDIA_INCLUDE_C
#include <LiDIA/polynomial.c>
#endif

#define DV_FLP LDBL_UNIPOL+20
#define DM_FLP "polynomial<bigfloat>"
#define LP_ERROR poly_error_msg

void base_polynomial <bigfloat>::remove_leading_zeros()
{
  debug_handler_c(DM_FLP, "in member - function remove_leading_zeros ()",
                  DV_FLP, cout<<"original degree is "<<deg<<endl<<flush);
  bigfloat c, *np;
  lidia_size_t d, i;

  d = deg;
  np = coeff + d;
  while (d >= 0 && np->is_approx_zero())
    d--, np--;

  if (d < 0){
    deg = d;
    delete[] coeff;
    coeff = NULL;
  }
  else if (d != deg){
    debug_handler_c(DM_FLP, "in member - function remove_leading_zeros()",
                    DV_FLP + 1, cout << "new degree is "<<d<<endl<<flush);
    deg = d;
    np = new bigfloat[d + 1];
    memory_handler(np, DM_CP, "remove_leading_zeros() :: "
                   "Error in memory allocation (np)");
    for (i = 0; i <= d; i++)
      np[i] = coeff[i];
    delete[] coeff;
    coeff = np;
  }
}

#ifdef __GNUG__
template class base_polynomial <bigfloat>;

template void negate(base_polynomial <bigfloat> & c,
                     const base_polynomial <bigfloat> &a);

template void add(base_polynomial <bigfloat> & c,
                  const base_polynomial <bigfloat> & a,
                  const base_polynomial <bigfloat> & b);
template void add(base_polynomial <bigfloat> & c,
                  const base_polynomial <bigfloat> & a,
                  const bigfloat & b);
template void add(base_polynomial <bigfloat> & c,
                  const bigfloat & b,
                  const base_polynomial <bigfloat> & a);

template void subtract(base_polynomial <bigfloat> & c,
                       const base_polynomial <bigfloat> & a,
                       const base_polynomial <bigfloat> & b);
template void subtract(base_polynomial <bigfloat> & c,
                       const base_polynomial <bigfloat> & a,
                       const bigfloat & b);
template void subtract(base_polynomial <bigfloat> & c,
                       const bigfloat & b,
                       const base_polynomial <bigfloat> & a);

template void multiply(base_polynomial <bigfloat> & c,
                       const base_polynomial <bigfloat> & a,
                       const base_polynomial <bigfloat> & b);
template void multiply(base_polynomial <bigfloat> & c,
                       const base_polynomial <bigfloat> & a,
                       const bigfloat & b);
template void multiply(base_polynomial <bigfloat> & c,
                       const bigfloat & b,
                       const base_polynomial <bigfloat> & a);

template void power(base_polynomial <bigfloat> & c,
                    const base_polynomial <bigfloat> & a, const bigint & b);

template void derivative(base_polynomial <bigfloat> &c,
                         const base_polynomial <bigfloat> &a);

template void power(base_polynomial <bigfloat> & c,
                    const base_polynomial <bigfloat> & a, const bigint & b);

template base_polynomial <bigfloat>
derivative(const base_polynomial <bigfloat> &a);

template istream & operator >> (istream &,
                                base_polynomial <bigfloat> &);
template ostream & operator << (ostream &,
                                const base_polynomial <bigfloat> &);


template class field_polynomial <bigfloat>;

template void div_rem(field_polynomial <bigfloat> &q,
                      field_polynomial <bigfloat> &r,
                      const base_polynomial <bigfloat> &a,
                      const base_polynomial <bigfloat> &b);
template void divide(field_polynomial <bigfloat> & c,
                     const base_polynomial <bigfloat> & a,
                     const bigfloat & b);
template void power_mod(field_polynomial <bigfloat> & c,
                        const base_polynomial <bigfloat> & a,
                        const bigint & b,
                        const base_polynomial <bigfloat> & f);

template void integral(field_polynomial <bigfloat> &c,
                       const base_polynomial <bigfloat> &a);

template field_polynomial <bigfloat>
gcd(const base_polynomial <bigfloat> &aa,
    const base_polynomial <bigfloat> &bb);

template field_polynomial <bigfloat>
xgcd(field_polynomial <bigfloat> &x,
     field_polynomial <bigfloat> &y,
     const base_polynomial <bigfloat> &aa,
     const base_polynomial <bigfloat> &bb);
#endif

  /**
   ** Cast operators:
   **/

polynomial<bigfloat>::operator base_polynomial<bigcomplex>() const
{
  base_polynomial <bigcomplex> x;
  x.set_degree(deg);
  for (lidia_size_t i = 0; i <= deg; i++)
    x[i] = bigcomplex(coeff[i]);
  return x;
}
#undef DV_FLP
#undef DM_FLP
#undef LP_ERROR
