// Univariate Polynomial operations.

// General includes.
#include "cl_sysdep.h"

CL_PROVIDE(cl_UP)

// Specification.
#define CL_GV_NO_RANGECHECKS
#define CL_SV_NO_RANGECHECKS
#include "cl_univpoly.h"
#include "cl_UP.h"


// Implementation.

#include "cl_output.h"

cl_symbol cl_univpoly_varname_key = (cl_symbol)(cl_string)"variable name";

// Prepare for looking into a polynomial.
  #define DeclarePoly(type,x)  \
    const type& __tmp_##x = *(const type*) &(x).rep;			\
    const type& x = __tmp_##x;
  #define DeclareMutablePoly(type,x)  \
    type& __tmp_##x = *(type*) &(x).rep;				\
    type& x = __tmp_##x;

// Three different implementations of the polynomial operations, for efficiency:
#include "cl_UP_N.h"	// polynomials over number rings
#include "cl_UP_MI.h"	// polynomials over modular integer rings
#include "cl_UP_gen.h"	// polynomials over all other rings

cl_heap_univpoly_ring::cl_heap_univpoly_ring (const cl_ring& r, cl_univpoly_setops* setopv, cl_univpoly_addops* addopv, cl_univpoly_mulops* mulopv, cl_univpoly_polyops* polyopv)
	: setops (setopv), addops (addopv), mulops (mulopv), polyops (polyopv),
	  basering (r)
{
	refcount = 0; // will be incremented by the `cl_univpoly_ring' constructor
	typetag = cl_typetag_univpoly_ring;
}

static void cl_univpoly_ring_destructor (cl_heap* pointer)
{
	(*(cl_heap_univpoly_ring*)pointer).~cl_heap_univpoly_ring();
}
AT_INITIALIZATION(ini_cl_univpoly_ring)
{ cl_register_typetag(cl_typetag_univpoly_ring,cl_univpoly_ring_destructor); }

// This tells the compiler to put the `cl_heap_univpoly_ring' vtable
// into this file.
void cl_heap_univpoly_ring::dummy () {}


// Create a new univariate polynomial ring.

cl_heap_univpoly_ring* cl_make_univpoly_ring (const cl_ring& r)
{
	switch (r.pointer_typetag()) {
		case cl_typetag_complex_ring:
		case cl_typetag_real_ring:
		case cl_typetag_rational_ring:
		case cl_typetag_integer_ring:
			return new cl_heap_num_univpoly_ring(r);
		case cl_typetag_modint_ring:
			return new cl_heap_modint_univpoly_ring(r);
		default:
			return new cl_heap_gen_univpoly_ring(r);
	}
}

CL_PROVIDE_END(cl_UP)
