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


16 Qax — The Polynomial Ring Q(a)[x]

CALIB provides the Qax domain, representing the ring Q(a)[x], the univariate polynomials having coefficients that are an algebraic extension of the rationals. The “values” of this domain are represented by the following object:

/*
 * An instance of a polynomial in K[x], where K = Q(a).
 */

struct calib_Qax_obj {
	int	degree;		/* Degree of polynomial			*/
	int	size;		/* Size of coeff buffer			*/
	const struct calib_Qax_dom *
		dom;		/* Qax domain of polymial		*/
	struct calib_Qa_obj *
		coeff;		/* Coefficients of polynomial.		*/
};

The CALIB Qax domain is constructed by specifying a Qa domain used to represent the coefficients of the corresponding Qax polynomials.

One may access CALIB’s Qax domain as follows:

	#include "calib/Qax.h"
	...
	struct calib_Zx_obj *		gpoly;
	struct calib_Qa_dom *		Qa;
        struct calib_Qax_dom *		Qax;
	struct calib_Qax_obj		poly1, poly2;
	...
	gpoly	= /* generator poly in Z[x] */
	Qa	= calib_make_Qa_dom (gpoly);
	Qax	= calib_make_Qax_dom (Qa);
	...
	Qax -> init (Qax, &poly1);
	Qax -> init (Qax, &poly2);
	...
	Qax -> mul (Qax, &poly1, &poly1, &poly2);
	...
	Qax -> clear (&poly2);
	Qax -> clear (&poly1);
	calib_free_Qax_dom (Qax);
	calib_free_Qa_dom (Qa);

The CALIB Qax domain supports the following settings:

/*
 * Which factorization algorithm to use (for square-free polynomials).
 */

enum calib_Qax_factor_method {
	CALIB_QAX_FACTOR_METHOD_WEINBERGER_ROTHSCHILD,
	CALIB_QAX_FACTOR_METHOD_NORM
};

/*
 * The "settings" object for the Qax domain.
 */

struct calib_Qax_settings {
	/* Factorization method for square-free Qax polynomials. */
	enum calib_Qax_factor_method	factor_method;

	/* Print initial factors during Weinberger-Rothschild? */
	calib_bool			WR_print_initial_factors;

	/* Print lifted factors during Weinberger-Rothschild? */
	calib_bool			WR_print_lifted_factors;

	/* Print trial factor combinations during Weinberger-Rothschild? */
	calib_bool			WR_print_trial_factor_combinations;
};

/*
 * Newly created Qax domains default to these settings.
 */

extern struct calib_Qax_settings	calib_Qax_default_settings;

Each CALIB Qax domain has its own copy of these settings (consulted by the domain’s operations):

struct calib_Qax_dom {
	...
	struct calib_Qax_settings	settings;
	...
};

These settings are initialized from calib_Qax_default_settings when the domain is constructed, but applications may alter these settings after construction, if desired.

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

Qax::init():

	void	(*init) (const struct calib_Qax_dom *	K_of_x,
			 struct calib_Qax_obj *		x);

Initialize the given Qax polynomial x to be the constant zero polynomial of the given Qax domain K_of_x, where:

K_of_xis the Qax ring/domain performing this operation; and
xis the polynomial to initialize.

Qax::init_degree():

	void	(*init_degree)
			(const calib_Qax_dom *	K_of_x,
			 struct calib_Qax_obj *	x,
			 int			degree);

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

K_of_xis the Qax ring/domain performing this operation;
xis the polynomial to initialize; and
degreeis the guaranteed minimimum degree polynomial that dst will be able to hold (without further buffer allocation) upon successful completion of this operation.

Qax::alloc():

	void	(*alloc) (struct calib_Qax_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 dst will be able to hold (without further buffer allocation) upon successful completion of this operation.

Qax::clear():

	void	(*clear) (struct calib_Qax_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.

Qax::set():

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

Set rop to op in Q(a)[x], where:

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

Qax::set_si():

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

Set rop to op in Q(a)[x], where:

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

Qax::set_z():

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

Set rop to op in Q(a)[x], where:

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

Qax::set_q():

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

Set rop to op in Q(a)[x], where:

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

Qax::set_var_power():

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

Set the polynomial rop to be x**power (x is the Qax polynomial variable), where:

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

Qax::set_Zx():

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

Set rop to op, converting from Zx to Qax form, where:

ropthe destination Qax polynomial / domain; and
opthe source Zx polynomial.

Qax::add():

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

Set rop to op1 + op2 in Q(a)[x], where:

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

Qax::sub():

	void	(*sub) (struct calib_Qax_obj *		rop,
			const struct calib_Qax_obj *	op1,
			const struct calib_Qax_obj *	op2);

Set rop to op1 - op2 in Q(a)[x], where:

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

Qax::neg():

	void	(*neg) (struct calib_Qax_obj *		rop,
			const struct calib_Qax_obj *	op);

Set rop to - op in Q(a)[x], where:

ropis the Qax polynomial receiving the result; and
opis the Qax polynomial being negated.

Qax::mul():

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

Set rop to op1 * op2 in Q(a)[x], where:

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

Qax::ipow():

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

Set rop to op ** power in Q(a)[x], where:

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

Qax::dup():

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

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

opis the polynomial to be duplicated.

Qax::free():

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

Free the given dynamically-allocated polynomial poly, where:

polyis the polynomial to be freed.

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

Qax::eval():

	void	(*eval) (struct calib_Qa_obj *		rop,
			 const struct calib_Qax_obj *	poly,
			 const struct calib_Qa_obj *	value);

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

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

Qax::eval_poly():

	void	(*eval_poly)
			(struct calib_Qax_obj *		rop,
			 const struct calib_Qax_obj *	poly,
			 const struct calib_Qax_obj *	value);

Evaluate polynomial poly at the given value (which is itself a polynomial in K_of_X), storing the result in rop, where:

ropreceives the Qax polynomial result;
polyis the polynomial to be evaluated; and
valueis the Qax polynomial at which to evaluate the polynomial.

Qax::div():

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

Polynomial division in Q(a)[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(a)[x] has the following properties:

Qax::gcd():

	void	(*gcd) (struct calib_Qax_obj *		gcd,
			const struct calib_Qax_obj *	a,
			const struct calib_Qax_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.

The GCD is always monic unless a = b = 0.

Qax::extgcd():

	void	(*extgcd) (struct calib_Qax_obj *	gcd,
			   struct calib_Qax_obj *	xa,
			   struct calib_Qax_obj *	xb,
			   const struct calib_Qax_obj *	a,
			   const struct calib_Qax_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)

Qax::factor():

	struct calib_Qax_factor *
		(*factor) (const struct calib_Qax_obj *	poly);

Factor the given polynomial poly into its irreducible factors over Q(a)[x], returning a linked list of these factors, where:

polyis the Qax polynomial to be factored.

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

Qax::factor_square_free():

	struct calib_Qax_factor *
		(*factor_square_free)
			(const struct calib_Qax_obj *	sqfpoly);

Given sqfpoly that is monic, square-free and of degree at least 1, factor it into irreducible factors, where

sqfpolyis the Qax polynomial to be factored.

This is a subroutine used by Qax::factor(). Two different methods are supported:

  1. Weinberger, Rothschild, Factoring Polynomials Over Algebraic Number Fields, ACM Trans. Math. Softw., 1976, Vol 2, 335–350, https://api.semanticscholar.org/CorpusID:6704708.
  2. The “norm” method (the default).

Qax::finish_sqf():

	struct calib_Qax_factor *
		(*finish_sqf) (
			const struct calib_Qax_factor *	sqfactors);

Given a list of monic, square-free polynomial sqfactors, “finish” the factorization by factoring each such factor into irreducible polynomials, returning a linked-list of these factors, where:

sqfactorsis a linked-list of primitive, square-free Qax polynomial factors for which factorization into irreducibles is desired.

Qax::free_factors():

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

Free up the given list of Qax factors, where:

factorsis a linked-list factors to be freed.

Qax::algint_dom():

	const struct calib_Qax_dom *
		(*algint_dom) (const struct calib_Qax_dom *	dom);

Return the Qax domain representing the algebraic integer corresponding to given domain dom, where:

domis the Qax domain for which to get the corresponding algebraic integer domain.

Returns dom when the coefficient field of dom is already an algebraic integer. Note: Do NOT free this domain, because it is owned by the given Q(a)[x] domain dom!

Qax::to_algint():

	void	(*to_algint) (struct calib_Qax_obj *		rop,
			      const struct calib_Qax_obj *	op);

Set rop to be the same Q(a)[x] value as op, but coefficients represented in terms of the algebraic integer corresponding to op’s coefficient domain, where:

ropis the Qax polynomial receiving the result; and
opis the source Qax polynomial.

Let D be the Qax domain of op. The domain of rop must either be identically D, or it must be the algebraic integer domain corresponding to D (e.g., as returned by Qax::algint_dom()).

Qax::from_algint():

	void	(*from_algint) (struct calib_Qax_obj *		rop,
				const struct calib_Qax_obj *	op);

Set rop to be the same Q(a)[x] polynomial as op, converting the coefficients from the algebraic integer domain back to the original (possibly algebraic non-integer) domain, where:

ropis the Qax polynomial receiving the result; and
opis the source Qax polynomial.

Let D be the Qax domain of rop. The domain of op must either be identically D, or it must be the algebraic integer domain corresponding to D (e.g., as returned by Qax::algint_dom()).

Qax::zerop():

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

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

opis the Qax polynomial to test for zero.

Qax::onep():

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

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

opis the Qax polynomial to test for one.

Qax::set_genrep():

	void	(*set_genrep) (struct calib_Qax_obj *		rop,
			       const struct calib_genrep *	op,
			       const char *			xvar,
			       const char *			avar);

Compute a Qax polynomial obtained from the given genrep op, interpreting xvar to be the name of the variable used by the Qax polynomial and avar to be the name of the variable used by the Qa coefficients, storing the result in rop, where:

ropis the Qax polynomial receiving the result;
opis the genrep to convert into Qax polynomial form;
xvaris the variable name (appearing within genrep op) that is to be interpreted as the polynomial variable in Qax; and
avaris the variable name (appearing within genrep op) that is to be interpreted as the variable used by the Qa coefficients.

Qax::to_genrep():

	struct calib_genrep *
		(*to_genrep) (const struct calib_Qax_obj *	op,
			      const char *			xvar,
			      const char *			avar);

Return a dynamically-allocated genrep corresponding to the given Qax polynomial op, using xvar as the name of the Qax polynomial variable and avar as the name of the Qa coefficient variable within the returned genrep, where:

opis the Qax polynomial to convert into genrep form;
xvaris the variable name to use in the genrep for the polynomial variable of Qax; and
avaris the variable name to use in the genrep for the Qa coefficients.

Qax::factors_to_genrep():

	struct calib_genrep *
		(*factors_to_genrep)
			(const struct calib_Qax_factor *	factors,
			 const char *				xvar,
			 const char *				avar);

Return a dynamically-allocated genrep corresponding to the given list of Qax factors, using xvar as the name of the Qax polynomial variable and avar as the name of the Qa coefficient variable within the returned genrep, where:

factorsis the list of Qax polynomial factors to convert into genrep form; and
xvaris the variable name to use in the genrep for the polynomial variable of Qax;
avaris the variable name to use in the genrep for the Qa coefficients.

Qax::bit_size():

	size_t	(*bit_size)
			(const struct calib_Qax_obj *	op);

Return the maximum “bit size” among all rational coefficients of the given Qax polynomial op (the rational bit size is the number of significant bits in the product of the numerator and denominator), where:

opis the Qax polynomial for which to return the bit size.

Qax::factors_bit_size():

	size_t	(*bit_size)
			(const struct calib_Qax_factor *	factors);

Return the maximum “bit size” among all rational coefficients of all the given list factors of Qax factors (the rational bit size is the number of significant bits in the product of the numerator and denominator), where:

factorsis a linked-list of Qax polynomial factors for which to return the bit size.

Qax::get_Zax_dom():

	const struct calib_Zax_dom *
		(*get_Zax_dom) (const struct calib_Qax_dom *	K_of_x);

Return the Z(a)[x] version of the given Q(a)[x] domain K_of_x, where:

K_of_xis the Qax polynomial domain whose corresponding Zax polynomial domain is sought.

Note: Do NOT free this domain, because it is owned by the given Q(a)[x] domain K_of_x!


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