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:
void (*init) (struct calib_Qx_obj * x);
Initialize the given Qx polynomial x
, where:
x | is the polynomial to initialize. |
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:
x | is the polynomial to initialize; and |
degree | is the guaranteed minimimum degree polynomial that x
will be able to hold (without further buffer allocation) upon
successful completion of this operation. |
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:
rop | is the polynomial whose allocation is to be adjusted; and |
degree | is the guaranteed minimum degree polynomial that rop will
be able to hold (without further buffer allocation) upon successful
completion of this operation. |
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:
x | is the polynomial to be cleared. |
void (*set) (struct calib_Qx_obj * rop, const struct calib_Qx_obj * op);
Set rop
to op
in Qx, where:
rop | is the polynomial receiving the result; |
op | is the polynomial to copy. |
void (*set_si) (struct calib_Qx_obj * rop, calib_si_t op);
Set rop
to op
in Qx, where:
rop | is the polynomial receiving the result; and |
op | is the integer value to set. |
void (*set_z) (struct calib_Qx_obj * rop, mpz_srcptr op);
Set rop
to op
in Qx, where:
rop | is the polynomial receiving the result; and |
op | is the GMP integer value to set. |
void (*set_q) (struct calib_Qx_obj * rop, mpq_srcptr op);
Set rop
to op
in Qx, where:
rop | is the polynomial receiving the result; and |
op | is the GMP rational value to set. |
void (*set_var_power) (struct calib_Qx_obj * rop, int power);
Set rop
to x ** power
in Qx, where:
rop | is the polynomial receiving the result; |
power | is the power to set (must be non-negative). |
void (*set_Zx) (struct calib_Qx_obj * rop, const struct calib_Zx_obj * op);
Set rop
to op
in Qx, where:
rop | is the Qx polynomial receiving the result; |
op | is the source Zx polynomial. |
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:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
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:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
void (*neg) (struct calib_Qx_obj * rop, const struct calib_Zxyz_obj * op);
Set rop
to - op
in Qx, where:
rop | is the polynomial receiving the result; |
op | is the operand to negate. |
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:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
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:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
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:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
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:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
void (*ipow) (struct calib_Qx_obj * rop, const struct calib_Qx_obj * op, int power);
Set rop
to op ** power
in Qx, where:
rop | is the polynomial receiving the result; |
op | is the polynomial to exponentiate; and |
power | is the power to take (must be >= 0). |
struct calib_Qx_obj * (*dup) (const struct calib_Qx_obj * op);
Return a dynamically-allocated Qx polynomial that is a copy of
op
, where:
op | is the polynomial to be duplicated. |
void (*free) (struct calib_Qx_obj * poly);
Free the given dynamically-allocated polynomial poly
, where:
poly | is the polynomial to be freed. |
This is equivalent to performing Qx -> clear (poly);
, followed
by free (poly);
.
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:
rop | is the GMP rational receiving the result; |
poly | is the polynomial to be evaluated; and |
value | is the value at which to evaluate the polynomial. |
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:
quotient | receives the quotient polynomial (may be NULL); |
remainder | receives the remainder polynomial (may be NULL); |
a | is the dividend polynomial; and |
b | is the divisor polynomial (may not be zero). |
Division in Q[x] has the following properties:
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:
gcd | receives the resulting GCD polynomial (always monic); |
a | is the first operand polynomial; and |
b | is the second operand polynomial. |
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:
gcd | receives the resulting GCD polynomial (always monic); |
xa | receives the multiplier polynomial for a ; |
xb | receives the multiplier polynomial for b ; |
a | is the first operand polynomial; and |
b | is the second operand polynomial. |
The result satisfies the following properties:
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:
poly | is 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.
void (*free_factors) (struct calib_Qx_factor * factors);
Free up the given list of Qx factors, where:
factors | is a linked-list factors to be freed. |
void (*derivative) (struct calib_Qx_obj * rop, const struct calib_Qx_obj * op);
Set rop
to be the derivative of Qx polynomial op
, where:
rop | is the derivative of the given polynomial; and |
op | is the polynomial whose derivative is to be computed. |
void (*integral) (struct calib_Qx_obj * rop, const struct calib_Qx_obj * op);
Set rop
to be the integral of Qx polynomial op
, where:
rop | is the derivative of the given polynomial; and |
op | is the polynomial whose integral is to be computed. |
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:
op | is the Qx polynomial to test for zero. |
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:
op | is the Qx polynomial to test for one. |
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:
rop | receives the resulting Qx polynomial; |
op | is the genrep to convert into Qx polynomial form; and |
var | is the variable name (appearing within genrep op ) that is
to be interpreted as the polynomial variable in Qx. |
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:
op | is the Qx polynomial to convert into genrep form; and |
var | is the variable name to use in the genrep for the polynomial variable of Qx. |
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:
factors | is the list of Qx polynomial factors to convert into genrep form; and |
var | is the variable name to use in the genrep for the polynomial variable of Qx. |
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:
op | is 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
).
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:
rop | is the Qx polynomial receiving the result; |
degree | is the degree to set; and |
coeffs | is the array of GMP rational coefficients
(of length degree + 1 ) to set. |