CALIB provides the Zxyz
domain, representing the ring
Z[x,y,z,...], the multivariate polynomials having integer
coefficients.
The “values” of this domain are represented by the following object:
struct calib_Zxyz_obj { int nterms; /* Number of terms in polynomial */ int size; /* Size of pow[] and coeff[] arrays */ const struct calib_Zxyz_dom * dom; /* Domain of polynomial */ int * pow; /* Powers of each var, each term */ mpz_ptr coeff; /* Coefficient for each term */ };
A Zxyz polynomial with n terms and k variables uses
n*k elements of the pow
array (each term specifies the
exponent for all k variables); and n elements of the
coeff
array.
The terms are sorted lexically by their k-element power
vectors (largest degrees before smaller).
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 Zxyz factorization algorithms:
struct calib_Zxyz_factor { int multiplicity; struct calib_Zxyz_obj * factor; struct calib_Zxyz_factor * next; };
When making a Zxyz
domain, one must specify the number of
variables and a textual name for each.
These are stored in the fields:
struct calib_Zxyz_dom { int nvars; /* Number of variables */ char ** vars; /* Name of each variable */ ... };
One may access CALIB’s Zxyz
domain as follows:
#include "calib/Zxyz.h" ... const struct calib_Zxyz_dom * Zxyz; struct calib_Zxyz_obj poly1, poly2; const char * varnames [3] = {"x", "y", "z"}; ... Zxyz = calib_make_Zxyz_dom (3, varnames); ... Zxyz -> init (&poly1); Zxyz -> init (&poly2); ... Zxyz -> mul (&poly1, &poly1, &poly2); ... Zxyz -> clear (&poly2); Zxyz -> clear (&poly1); ... calib_free_Zxyz_dom (Zxyz);
The struct calib_Zxyz_dom
object contains the following members
(pointers to functions) that provide operations of the domain:
void (*init) (const struct calib_Zxyz_dom * dom, struct calib_Zxyz_obj * x);
Initialize the given Zxyz polynomial x
, where:
dom | is the Zxyz ring/domain the polynomial belongs to; and |
x | is the polynomial to initialize. |
void (*init_si) (const struct calib_Zxyz_dom * dom, struct calib_Zxyz_obj * x, calib_si_t op);
Initialize the given Zxyz polynomial x
to the given constant
value op
, where:
dom | is the Zxyz ring/domain the polynomial belongs to; and |
x | is the polynomial to initialize; and |
op | is the constant value to which polynomial x is set. |
void (*alloc) (struct calib_Zxyz_obj * rop, int nterms);
Force the given (already initialized) polynomial rop
to have
buffer space sufficient to hold a polynomial having at least the given
nterms
number of (non-zero) terms, where:
rop | is the polynomial whose allocation is to be adjusted; and |
nterms | is the guaranteed minimum number of terms that polynomial
rop will be able to hold (without further buffer allocation)
upon successful completion of this operation. |
void (*clear) (struct calib_Zxyz_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_Zxyz_obj * rop, const struct calib_Zxyz_obj * op);
Set rop
to op
in Zxyz, where:
rop | is the polynomial receiving the result; |
op | is the polynomial to copy. |
void (*set_si) (struct calib_Zxyz_obj * rop, calib_si_t op);
Set rop
to op
in Zxyz, where:
rop | is the polynomial receiving the result; |
op | is the integer value to set. |
void (*set_z) (struct calib_Zxyz_obj * rop, mpz_srcptr op);
Set rop
to op
in Zxyz, where:
rop | is the polynomial receiving the result; |
op | is the GMP integer value to set. |
void (*set_var_power) (struct calib_Zxyz_obj * rop, int var, int power);
Set rop
to var ** power
in Zxyz, where:
rop | is the polynomial receiving the result; |
var | is the index of the variable; and |
power | is the power to set (must be non-negative). |
void (*add) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op1, const struct calib_Zxyz_obj * op2);
Set rop
to op1 + op2
in Zxyz, where:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
void (*add_n) (struct calib_Zxyz_obj * rop, int npoly, const struct calib_Zxyz_obj ** poly_ptrs);
Add npoly
polynomials together (given by the poly_ptrs
),
storing the result in rop
, where:
rop | is the polynomial receiving the result; |
npoly | is the number of polynomials being added; and |
poly_ptrs | is an array of pointers to the polynomials being added. |
void (*sub) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op1, const struct calib_Zxyz_obj * op2);
Set rop
to op1 - op2
in Zxyz, where:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
void (*neg) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op);
Set rop
to - op
in Zxyz, where:
rop | is the polynomial receiving the result; |
op | is the operand to negate. |
void (*mul) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op1, const struct calib_Zxyz_obj * op2);
Set rop
to op1 * op2
in Zxyz, where:
rop | is the polynomial receiving the result; |
op1 | is the first operand; and |
op2 | is the second operand. |
void (*mul_z) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op1, mpz_srcptr op2);
Set rop
to op1 * op2
in Zxyz, where:
rop | is the polynomial receiving the result; |
op1 | is the first (polynomial) operand; and |
op2 | is the second (GMP integer) operand. |
void (*ipow) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op, int power);
Set rop
to op ** power
in Zxyz, 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_Zxyz_obj * (*dup) (const struct calib_Zxyz_obj * op);
Return a dynamically-allocated Zxyz polynomial that is a copy of
op
, where:
op | is the polynomial to be duplicated. |
void (*free) (struct calib_Zxyz_obj * poly);
Free the given dynamically-allocated polynomial poly
, where:
poly | is the polynomial to be freed. |
This is equivalent to performing Zxyz -> clear (poly);
, followed
by free (poly);
.
void (*eval) (mpz_ptr rop, const struct calib_Zxyz_obj * poly, mpz_srcptr values);
Evaluate polynomial poly
at the given values
, storing the
result in rrop
, where:
rop | is the GMP integer receiving the result; |
poly | is the polynomial to be evaluated; and |
values | is an array of GMP integer values (one per variable) at which to evaluate the polynomial. |
void (*eval_var_subset) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * poly, const calib_bool * evflags, mpz_srcptr values);
Evaluate polynomial poly
at a specified subset of its
variables, storing the result in rop
.
For each variable i
, evaluate away variable i
at value
values[i]
if-and-only-if evflags[i]
is true, where:
rop | is the GMP integer receiving the result; |
poly | is the polynomial to be evaluated; |
evflags | is an array of booleans (one per variable) for which TRUE means to evaluate the corresponding variable; and |
values | is an array of GMP integer values (one per variable) at which to evaluate the polynomial. |
void (*div) (struct calib_Zxyz_obj * quotient, struct calib_Zxyz_obj * remainder, struct calib_Zxyz_obj * d, const struct calib_Zxyz_obj * a, const struct calib_Zxyz_obj * b, int var);
Polynomial pseudo-division in Z[x,y,z] with respect to a
specified main variable var
, where:
quotient | receives the quotient polynomial (may be NULL); |
remainder | receives the remainder polynomial (may be NULL); |
d | receives the “denominator” value (may be NULL); |
a | is the dividend polynomial; |
b | is the divisor polynomial (may not be zero); |
var | is the main variable for division. |
Pseudo-division has the following properties:
void (*div_z_exact) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op1, mpz_srcptr op2);
Set rop
to op1 / op2
in Zxyz, where:
rop | receives result polynomial; |
op1 | is the dividend polynomial; and |
op2 | is the GMP integer by which to divide poly . |
It is a fatal error if the division is not exact.
int (*div_remove) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op1, const struct calib_Zxyz_obj * op2);
Repeatedly divide polynomial op1
by polynomial op2
until no
more factors op2
can be removed, storing op1 / op2**k
into
rop
and returning k
, where:
rop | receives result polynomial; |
op1 | is the dividend polynomial; and |
op2 | is the divisor polynomial. |
void (*gcd) (struct calib_Zxyz_obj * gcd, const struct calib_Zxyz_obj * a, const struct calib_Zxyz_obj * b);
Compute the greatest common divisor (GCD) of a
and b
,
storing the result in gcd
, where:
gcd | receives the resulting GCD polynomial; |
a | is the first operand polynomial; and |
b | is the second operand polynomial. |
void (*gcd_n) (struct calib_Zxyz_obj * gcd, struct calib_Zxyz_obj ** cofact, int npoly, const struct calib_Zxyz_obj ** array);
Compute the greatest common divisor (GCD) polynomial that simultaneously divides n given polynomials, where:
gcd | receives the resulting GCD polynomial; |
cofact | is an array of nfact pointers to polynomials
receiving the cofactor corresponding to each given input polynomial
(may be NULL); |
npoly | is the number of input polynomials provided; and |
array | is an array of nfact pointers to input polynomials
whose GCD is to be computed. |
This can be vastly more efficient that decomposing this into
nfact-1 consecutive calls to the gcd
function.
void (*extgcd) (struct calib_Zxyz_obj * gcd, struct calib_Zxyz_obj * xa, struct calib_Zxyz_obj * xb, mpz_ptr d, const struct calib_Zxyz_obj * a, const struct calib_Zxyz_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; |
xa | receives the multiplier polynomial for a ; |
xb | receives the multiplier polynomial for b ; |
d | receives the denominator for xa and xb ; |
a | is the first operand polynomial; and |
b | is the second operand polynomial. |
void (*z_content) (mpz_ptr zcont, const struct calib_Zxyz_obj * op);
Compute the integer content zcont
of the given polynomial
op
, where:
zcont | a GMP integer receiving the content of op ; |
op | the polynomial whose integer content is to be computed. |
void (*strip_z_content) (mpz_ptr zcont, struct calib_Zxyz_obj * poly);
Compute and remove the content
from the given polynomial
poly
, where:
zcont | a GMP integer receiving the content of poly ; |
poly | the polynomial whose content is to be computed and removed. |
void (*prim_part) (mpz_ptr content, struct calib_Zxyz_obj * ppart, const struct calib_Zxyz_obj * op, int var);
Compute the multi-variate polynomial content
(with respect to
given main variable var
) of polynomial op
and setting
ppart
to be the primitive part, where:
content | receives the content of op with respect to variable var ; |
ppart | receives primitive part of op with respect to variable
var ; |
op | the polynomial to be decomposed into content and primitive parts; and |
var | is the main variable with respect to which the content is computed. |
void (*resultant) (mpz_ptr result, const struct calib_Zxyz_obj * a, const struct calib_Zxyz_obj * b, int var);
Compute the resultant of polynomials a
and b
with
respect to given main variable var
, storing the result in
result
, where:
result | is the resultant of given polynomials; |
a | is the first operand; |
b | is the second operand; and |
var | is the main variable to use / eliminate. |
struct calib_Zxyz_factor * (*resultant) (const struct calib_Zxyz_obj * a, const struct calib_Zxyz_obj * b, int var);
Compute the resultant of polynomials a
and b
with
respect to given main variable var
, returning the result as a
partially-factored list of factors, where:
a | is the first operand; |
b | is the second operand; and |
var | is the main variable to use / eliminate. |
Note: This is an old and very naive implementation!!! Use only on small polynomials of fairly low degree!
void (*discriminant) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op, int var);
Set rop
to be the discriminant of polynomial op
with
respect to variable var
, where:
rop | is the resulting polynomial; |
op | is the polynomial for which to compute the discriminant; and |
var | is the main variable to use / eliminate. |
void (*cvZpxyz) (const calib_Zxyz_obj * rop, const struct calib_Zp_dom * Zp, const struct calib_Zxyz_obj * op);
Compute a polynomial in Z[x,y,z] that is the
corresponding representative of the given polynomial op
in
Zp[x,y,z] (given in Zxyz form but having coefficients mod
p — the Z coefficients are chosen to have smallest absolute
value that are equivalent to the correponding Zp coefficient),
storing the result in rrop
, where:
rop | receives the resulting polynomial; |
Zp | is the source Zp coefficient domain; and |
op | is the Zxyz polynomial (with Zp coefficients) to convert into Zxyz form. |
struct calib_Zxyz_factor * (*factor) (const struct calib_Zxyz_obj * poly);
Factor the given polynomial poly
into its irreducible factors,
returning a linked list of these factors, where:
poly | is the Zxyz polynomial to be factored. |
See the Note in Zx::factor() regarding the Van Hoeij and LLL algorithms.
struct calib_Zxyz_factor * (*sqf_factor) (const struct calib_Zxyz_obj * poly);
Perform “square-free factorization” of given polynomial poly
,
where:
poly | is the Zxyz polynomial to be square-free factored. |
void (*free_factors) (struct calib_Zxyz_factor * factors);
Free up the given list of Zxyz factors, where:
factors | is a linked-list factors to be freed. |
struct calib_Zxyz_obj * (*map_to_subring) (struct calib_Zxyz_obj * result, const struct calib_Zxyz_obj * poly, const struct calib_Zxyz_dom * subring, const int * varmap);
Map the given polynomial poly
from its original ring into a new
polynomial whose coefficients reside in the given subring.
The varmap
array controls this mapping on a variable-by-variable
basis.
Let i be a variable index within the original polynomial ring,
and let j = varmap [i].
Then j = -1 ==> variable i remains in the source ring,
whereas j >= 0 ==> variable i (from the original ring)
maps to variable j of the subring.
(j must satisfy 0 <= j < subring.nvars.)
Since the calib_Zxyz_obj representation handles only GMP integer
coefficients, the result
object contains only dummy “1”
coefficient values.
The actual coefficients are found in this function’s return
values, which is an array of struct calib_Zxyz_obj
objects
(each of whose dom
member is the given subring).
This returned array has the same number of elements as
result -> nterms
.
It is the caller’s responsibility to free up the coefficient array
when done with it.
The arguments are:
result | The high-level structural result (but with “dummy” coefficient values of 1); |
poly | is the Zxyz polynomial to be mapped into the given subring ; |
subring | is the Zxyz domain describing the subring into which we are mapping coefficients; and |
varmap | is the array specifying how each variable in poly is to be
mapped. |
struct calib_Zxyz_obj * (*copy_into_superring) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op);
Set rop
to op
.
The domain of rop
and op
need not be the same, but
the rop
domain must have at least as many variables as the
domain of op
.
Extra variables receive a power of zero in every term copied.
The arguments are:
rop | the destination polynomial / domain; and |
op | the source polynomial / domain. |
void (*convert_with_varmap) (struct calib_Zxyz_obj * rop, const struct calib_Zxyz_obj * op, const int * varmap);
Convert a polynomial from one ring to another, mapping variables
according to the given varmap
.
Variables mapping to -1 in the varmap
must not appear in the
source polynomial op
.
The arguments are:
rop | the destination polynomial / domain; |
op | the source polynomial / domain; and |
varmap | the variable mapping array. |
void (*copy_from_Zx) (struct calib_Zxyz_obj * rop, const struct calib_Zx_obj * op, int var);
Set Zxyz polynomial rop
to Zx polynomial op
.
The polynomial op
becomes a polynomial in the given var
of the rop
polynomial.
The arguments are:
rop | the destination Zxyz polynomial / domain; |
op | the source Zx polynomial; and |
var | the dst polynomial variable to use. |
void (*copy_into_Zx) (struct calib_Zx_obj * rop, const struct calib_Zxyz_obj * op, int var);
Set Zx polynomial rop
to Zxyz polynomial op
(which must
contain only given variable var
), where:
rop | the destination Zx polynomial; |
op | the source Zxyz polynomial / domain; and |
var | the source polynomial variable. |
void (*copy_from_Zpx) (struct calib_Zxyz_obj * rop, const struct calib_Zpx_obj * op, int var);
Set Zxyz polynomial rop
from Zpx polynomial op
.
The polynomial op
becomes a polynomial in the given var
of the rop
polynomial.
The arguments are:
rop | the destination Zxyz polynomial / domain; |
op | the source Zpx polynomial; and |
var | the destination polynomial variable to use. |
void (*copy_into_Zpx) (struct calib_Zpx_obj * rop, const struct calib_Zxyz_obj * op, int var);
Set Zpx polynomial rop
to Zxyz polynomial op
(which must
contain only givenvariable var
), where:
rop | the destination Zpx polynomial; |
op | the source Zxyz polynomial / domain; and |
var | the source polynomial variable. |
void (*copy_from_Qax) (struct calib_Zxyz_obj * rop, mpz_ptr denom, const struct calib_Qax_obj * op, int xvar, int avar);
Copy the given op
polynomial (in Qax form) into the given
destination polynomial (in Zxyz form).
The op
polynomial’s main variable becomes xvar
of the
rop
polynomial, while the op
polynomial’s algebraic
variable becomes the given avar
of the rop
polynomial,
where:
rop | the destination Zxyz polynomial / domain; |
denom | receives the common denominator; |
op | the source Qax polynomial; |
xvar | main variable of op becomes variable xvar in
rop polynomial; and |
avar | algebraic variable of op becomes variable avar in
rop polynomial. |
void (*copy_into_Qax) (struct calib_Qax_obj * rop, const struct calib_Zxyz_obj * op, int xvar, int avar);
Set Qax polynomial rop
to Zxyz polynomial op
.
Variable xvar
of op
becomes the main variable of
rop
, while variable avar
of op
becomes the
algebraic variable of rop
, where:
rop | the destination Qax polynomial; |
op | the source Zxyz polynomial / domain; and |
xvar | source polynomial variable xvar becomes the main
variable of rop ; and |
avar | source polynomial variable avar becomes the algebraic
number variable of rop . |
struct calib_Zxyz_dom * (*add_vars) (const struct Zxyz_dom * dom, int nvars, const char * const * newvars);
Create a new Zxyz domain having the given additional variables over
those in given domain dom
, where:
dom | is the original Zxyz domain; |
nvars | is the number of variables to add; and |
newvars | is an array of the new variable names being added. |
calib_bool (*zerop) (const struct calib_Zxyz_obj * op);
Return 1 if-and-only-if the given Zxyz polynomial is identically zero and 0 otherwise, where:
op | is the Zxyz polynomial to test for zero. |
calib_bool (*onep) (const struct calib_Zxyz_obj * op);
Return 1 if-and-only-if the given Zxyz polynomial is identically 1 and 0 otherwise, where:
op | is the Zxyz polynomial to test for one. |
void (*set_genrep) (struct calib_Zxyz_obj * rop, const struct calib_genrep * op);
Compute a Zxyz polynomial obtained from the given
genrep op
, storing the result in rop
.
Use the domain of rop
to map variable names in op
to variable numbers in the resulting polynomial, where:
rop | receives the resulting Zxyz polynomial; |
op | is the genrep to convert into Zxyz polynomial form. |
struct calib_genrep * (*to_genrep) (const struct calib_Zxyz_obj * op);
Return a dynamically-allocated genrep corresponding to the given Zxyz
polynomial op
(whose Zxyz domain provides variable names to
use for each variable number), where:
op | is the Zxyz polynomial to convert into genrep form. |
struct calib_genrep * (*factors_to_genrep) (const struct calib_Zxyz_factor * factors);
Return a dynamically-allocated genrep corresponding to the given list
of Zxyz factors
(each of whose Zxyz domain provides variable
names to use for each variable number), where:
factors | is the list of Zxyz polynomial factors to convert into genrep form. |
void (*print_maxima) (const struct calib_Zxyz_obj * op);
Print the given Zxyz polynomial op
to stdout using syntax that
can be directly read by Maxima, where:
op | is the Zxyz polynomial to be printed. |
void (*print_maxima_nnl) (const struct calib_Zxyz_obj * op);
Print the given Zxyz polynomial op
to stdout using syntax that
can be directly read by Maxima (but with no terminating newline),
where:
op | is the Zxyz polynomial to be printed. |
int (*lookup_var) (const struct calib_Zxyz_dom * dom, const char * var);
Return the index of the variable whose name is var
, or -1 if
var
does not match any of the variables in the given
domain dom
, where:
dom | is the Zxyz domain within which to lookup variable var ; and |
var | is the variable name to query. |