Next: , Previous: , Up: Top   [Contents][Index]


7 Qx — The Polynomial Ring Q[x]

CALIB provides the Qx domain, representing the ring Q[x], the univariate polynomials having rational coefficients. The “values” of this domain are represented by the following object:

/*
 * An instance of a polynomial in Q[x].  We represent these as the product
 * of a rational factor with a primitive Z[x] polynomial whose leading
 * coefficient (if any) is strictly positive.
 */

struct calib_Qx_obj {
	mpq_t	qfact;		/* Rational multiplier			 */
	int	degree;		/* Degree of polynomial			 */
	int	size;		/* Size of coeff[] array (degree < size) */
	mpz_ptr	coeff;		/* Coefficients of polynomial.		 */
};

These objects are subject to init() and clear() operations. All such objects must be initialized prior to use by any other CALIB operation. Memory leaks result if they are not cleared when done.

The following additional object is used to represent linked-lists of factors produced by various Qx factorization algorithms:

struct calib_Qx_factor {
	int				multiplicity;
	struct calib_Qx_obj *		factor;
	struct calib_Qx_factor *	next;
};

No data is needed to instantiate the Qx domain. (There is only one such object, and cannot be freed.) Nonetheless, the Qx domain object is the only way to access the operations provided by this domain.

One may access CALIB’s Qx domain as follows:

	#include "calib/Qx.h"
	...
        const struct calib_Qx_dom *	Qx;
	struct calib_Qx_obj		poly1, poly2;
	...
	Qx = calib_get_Qx_dom ();
	...
	Qx -> init (&poly1);
	Qx -> init (&poly2);
	...
	Qx -> mul (&poly1, &poly1, &poly2);
	...
	Qx -> clear (&poly2);
	Qx -> clear (&poly1);

The struct calib_Qx_dom object contains the following members (pointers to functions) that provide operations of the domain:

Qx::init():

	void	(*init) (struct calib_Qx_obj *		x);

Initialize the given Qx polynomial x, where:

xis the polynomial to initialize.

Qx::init_degree():

	void	(*init_degree) (struct calib_Qx_obj *	x,
				int			degree);

Initialize the given Qx polynomial x (while assuring that internal buffers are sufficiently large to hold a polynomial of up to the given degree without further allocation), where:

xis the polynomial to initialize; and
degreeis the guaranteed minimimum degree polynomial that x will be able to hold (without further buffer allocation) upon successful completion of this operation.

Qx::alloc():

	void	(*alloc) (struct calib_Qx_obj *	rop,
			  int			degree);

Force the given (already initialized) polynomial rop to have buffer space sufficient to hold a polynomial of at least the given degree, where:

ropis the polynomial whose allocation is to be adjusted; and
degreeis the guaranteed minimum degree polynomial that rop will be able to hold (without further buffer allocation) upon successful completion of this operation.

Qx::clear():

	void	(*clear) (struct calib_Qx_obj *	x);

Clear out the given polynomial x (freeing all memory it might hold and returning it to the constant value of zero), where:

xis the polynomial to be cleared.

Qx::set():

	void	(*set) (struct calib_Qx_obj *		rop,
			const struct calib_Qx_obj *	op);

Set rop to op in Qx, where:

ropis the polynomial receiving the result;
opis the polynomial to copy.

Qx::set_si():

	void	(*set_si) (struct calib_Qx_obj *	rop,
			   calib_si_t			op);

Set rop to op in Qx, where:

ropis the polynomial receiving the result; and
opis the integer value to set.

Qx::set_z():

	void	(*set_z) (struct calib_Qx_obj *	rop,
			  mpz_srcptr		op);

Set rop to op in Qx, where:

ropis the polynomial receiving the result; and
opis the GMP integer value to set.

Qx::set_q():

	void	(*set_q) (struct calib_Qx_obj *	rop,
			  mpq_srcptr		op);

Set rop to op in Qx, where:

ropis the polynomial receiving the result; and
opis the GMP rational value to set.

Qx::set_var_power():

	void	(*set_var_power)
			 (struct calib_Qx_obj *	rop,
			  int			power);

Set rop to x ** power in Qx, where:

ropis the polynomial receiving the result;
poweris the power to set (must be non-negative).

Qx::set_Zx():

	void	(*set_Zx) (struct calib_Qx_obj *	rop,
			   const struct calib_Zx_obj *	op);

Set rop to op in Qx, where:

ropis the Qx polynomial receiving the result;
opis the source Zx polynomial.

Qx::add():

	void	(*add) (struct calib_Qx_obj *           rop,
			const struct calib_Qx_obj *	op1,
			const struct calib_Qx_obj *	op2);

Set rop to op1 + op2 in Qx, where:

ropis the polynomial receiving the result;
op1is the first operand; and
op2is the second operand.

Qx::sub():

	void	(*sub) (struct calib_Qx_obj *           result,
			const struct calib_Qx_obj *	a,
			const struct calib_Qx_obj *	b);

Set rop to op1 - op2 in Qx, where:

ropis the polynomial receiving the result;
op1is the first operand; and
op2is the second operand.

Qx::neg():

	void	(*neg) (struct calib_Qx_obj *		rop,
			const struct calib_Zxyz_obj *	op);

Set rop to - op in Qx, where:

ropis the polynomial receiving the result;
opis the operand to negate.

Qx::mul():

	void	(*mul) (struct calib_Qx_obj *           rop,
			const struct calib_Qx_obj *	op1,
			const struct calib_Qx_obj *	op2);

Set rop to op1 * op2 in Qx, where:

ropis the polynomial receiving the result;
op1is the first operand; and
op2is the second operand.

Qx::mul_si():

	void	(*mul_si) (struct calib_Qx_obj *        rop);
			   const struct calib_Qx_obj *  op1,
			   calib_si_t			op2);

Set rop to op1 * op2 in Qx, where:

ropis the polynomial receiving the result;
op1is the first operand; and
op2is the second operand.

Qx::mul_z():

	void	(*mul_z) (struct calib_Qx_obj *        rop);
			   const struct calib_Qx_obj *  op1,
			   mpz_ptr			op2);

Set rop to op1 * op2 in Qx, where:

ropis the polynomial receiving the result;
op1is the first operand; and
op2is the second operand.

Qx::mul_q():

	void	(*mul_q) (struct calib_Qx_obj *        rop);
			   const struct calib_Qx_obj *  op1,
			   mpq_ptr			op2);

Set rop to op1 * op2 in Qx, where:

ropis the polynomial receiving the result;
op1is the first operand; and
op2is the second operand.

Qx::ipow():

	void	(*ipow) (struct calib_Qx_obj *		rop,
			 const struct calib_Qx_obj *	op,
			 int				power);

Set rop to op ** power in Qx, where:

ropis the polynomial receiving the result;
opis the polynomial to exponentiate; and
poweris the power to take (must be >= 0).

Qx::dup():

	struct calib_Qx_obj *
		(*dup) (const struct calib_Qx_obj *	op);

Return a dynamically-allocated Qx polynomial that is a copy of op, where:

opis the polynomial to be duplicated.

Qx::free():

	void	(*free) (struct calib_Qx_obj *	poly);

Free the given dynamically-allocated polynomial poly, where:

polyis the polynomial to be freed.

This is equivalent to performing Qx -> clear (poly);, followed by free (poly);.

Qx::eval():

	void	(*eval) (mpq_ptr			rop,
			 const struct calib_Qx_obj *	poly,
			 mpq_srcptr			value);

Evaluate polynomial poly at the given value, storing the result in rop, where:

ropis the GMP rational receiving the result;
polyis the polynomial to be evaluated; and
valueis the value at which to evaluate the polynomial.

Qx::div():

	void	(*div) (struct calib_Qx_obj *		quotient,
			struct calib_Qx_obj *		remainder,
			const struct calib_Qx_obj *	a,
			const struct calib_Qx_obj *	b);

Polynomial division in Q[x], where:

quotientreceives the quotient polynomial (may be NULL);
remainderreceives the remainder polynomial (may be NULL);
ais the dividend polynomial; and
bis the divisor polynomial (may not be zero).

Division in Q[x] has the following properties:

Qx::gcd():

	void	(*gcd) (struct calib_Qx_obj *		gcd,
			const struct calib_Qx_obj *	a,
			const struct calib_Qx_obj *	b);

Compute the greatest common divisor (GCD) of a and b, storing the result in gcd, where:

gcdreceives the resulting GCD polynomial (always monic);
ais the first operand polynomial; and
bis the second operand polynomial.

Qx::extgcd():

	void	(*extgcd) (struct calib_Qx_obj *	gcd,
			   struct calib_Qx_obj *	xa,
			   struct calib_Qx_obj *	xb,
			   const struct calib_Qx_obj *	a,
			   const struct calib_Qx_obj *	b);

The extended Euclidean algorithm. Compute polynomials gcd, xa and xb such that gcd = a * xa + b * xb, where:

gcdreceives the resulting GCD polynomial (always monic);
xareceives the multiplier polynomial for a;
xbreceives the multiplier polynomial for b;
ais the first operand polynomial; and
bis the second operand polynomial.

The result satisfies the following properties:

  1. degree(xa) < degree(b)
  2. degree(xb) < degree(a)

Qx::factor():

	struct calib_Qx_factor *
		(*factor) (const struct calib_Qx_obj *	poly);

Factor the given polynomial poly into its irreducible factors, returning a linked list of these factors, where:

polyis the Qx polynomial to be factored.

Except for an optional leading constant factor, all other factors are monic and irreducible.

Note the discussion in Zx::factor() regarding Van Hoeij and LLL algorithms.

Qx::free_factors():

	void	(*free_factors)
			(struct calib_Qx_factor *	factors);

Free up the given list of Qx factors, where:

factorsis a linked-list factors to be freed.

Qx::derivative():

	void	(*derivative)
			(struct calib_Qx_obj *		rop,
			 const struct calib_Qx_obj *	op);

Set rop to be the derivative of Qx polynomial op, where:

ropis the derivative of the given polynomial; and
opis the polynomial whose derivative is to be computed.

Qx::integral():

	void	(*integral)
			(struct calib_Qx_obj *		rop,
			 const struct calib_Qx_obj *	op);

Set rop to be the integral of Qx polynomial op, where:

ropis the derivative of the given polynomial; and
opis the polynomial whose integral is to be computed.

Qx::zerop():

	calib_bool
		(*zerop) (const struct calib_Qx_obj *	op);

Return 1 if-and-only-if the given Qx polynomial is identically zero and 0 otherwise, where:

opis the Qx polynomial to test for zero.

Qx::onep():

	calib_bool
		(*onep) (const struct calib_Qx_obj *	op);

Return 1 if-and-only-if the given Qx polynomial is identically one and 0 otherwise, where:

opis the Qx polynomial to test for one.

Qx::set_genrep():

	void	(*set_genrep) (struct calib_Qx_obj *		rop,
			       const struct calib_genrep *	op,
			       const char *			var);

Compute a Qx polynomial obtained from the given genrep op, interpreting var to be the name of the variable used by the Qx polynomial, storing the result in rop, where:

ropreceives the resulting Qx polynomial;
opis the genrep to convert into Qx polynomial form; and
varis the variable name (appearing within genrep op) that is to be interpreted as the polynomial variable in Qx.

Qx::to_genrep():

	struct calib_genrep *
		(*to_genrep) (const struct calib_Qx_obj *	op,
			      const char *			var);

Return a dynamically-allocated genrep corresponding to the given Qx polynomial op, using var as the name of the polynomial variable within the returned genrep, where:

opis the Qx polynomial to convert into genrep form; and
varis the variable name to use in the genrep for the polynomial variable of Qx.

Qx::factors_to_genrep():

	struct calib_genrep *
		(*factors_to_genrep)
			(const struct calib_Qx_factor *	factors,
			 const char *			var);

Return a dynamically-allocated genrep corresponding to the given list of Qx factors, using var as the name of the polynomial variable within the returned genrep, where:

factorsis the list of Qx polynomial factors to convert into genrep form; and
varis the variable name to use in the genrep for the polynomial variable of Qx.

Qx::get_coeffs():

	mpq_ptr	(*get_coeffs) (const struct calib_Qx_obj *	op);

Return a dynamically allocated array of GMP rationals representing the coefficients of Qx polynomial op, where:

opis the Qx polynomial for which to get the coefficients.

It is the caller’s responsibility to free the returned array (of length op->degree + 1).

Qx::set_coeffs():

	void	(*set_coeffs) (struct calib_Qx_obj *	rop,
			       int			degree,
			       mpq_srcptr		coeffs);

Set rop to be the Q[x] polynomial having the given degree and rational coefficients, where:

ropis the Qx polynomial receiving the result;
degreeis the degree to set; and
coeffsis the array of GMP rational coefficients (of length degree + 1) to set.

Next: , Previous: , Up: Top   [Contents][Index]