1597 lines
68 KiB
Plaintext
1597 lines
68 KiB
Plaintext
/*=============================================================================
|
|
|
|
This file is part of FLINT.
|
|
|
|
FLINT is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
FLINT is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with FLINT; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
=============================================================================*/
|
|
/******************************************************************************
|
|
|
|
Copyright (C) 2009, 2008 William Hart
|
|
Copyright (C) 2011 Fredrik Johansson
|
|
Copyright (C) 2012 Sebastian Pancratz
|
|
Copyright (C) 2012,2013 Andres Goens
|
|
Copyright (C) 2013 Mike Hansen
|
|
|
|
******************************************************************************/
|
|
|
|
*******************************************************************************
|
|
|
|
Memory management
|
|
|
|
*******************************************************************************
|
|
|
|
void fq_zech_poly_init(fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Initialises \code{poly} for use, with context ctx, and setting its
|
|
length to zero. A corresponding call to \code{fq_zech_poly_clear()}
|
|
must be made after finishing with the \code{fq_zech_poly_t} to free the
|
|
memory used by the polynomial.
|
|
|
|
void fq_zech_poly_init2(fq_zech_poly_t poly, slong alloc,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Initialises \code{poly} with space for at least \code{alloc}
|
|
coefficients and sets the length to zero. The allocated
|
|
coefficients are all set to zero. A corresponding call to
|
|
\code{fq_zech_poly_clear()} must be made after finishing with the
|
|
\code{fq_zech_poly_t} to free the memory used by the polynomial.
|
|
|
|
void fq_zech_poly_realloc(fq_zech_poly_t poly, slong alloc,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Reallocates the given polynomial to have space for \code{alloc}
|
|
coefficients. If \code{alloc} is zero the polynomial is cleared
|
|
and then reinitialised. If the current length is greater than
|
|
\code{alloc} the polynomial is first truncated to length
|
|
\code{alloc}.
|
|
|
|
void fq_zech_poly_fit_length(fq_zech_poly_t poly, slong len,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
If \code{len} is greater than the number of coefficients currently
|
|
allocated, then the polynomial is reallocated to have space for at
|
|
least \code{len} coefficients. No data is lost when calling this
|
|
function.
|
|
|
|
The function efficiently deals with the case where
|
|
\code{fit_length} is called many times in small increments by at
|
|
least doubling the number of allocated coefficients when length is
|
|
larger than the number of coefficients currently allocated.
|
|
|
|
void _fq_zech_poly_set_length(fq_zech_poly_t poly, slong newlen,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets the coefficients of \code{poly} beyond \code{len} to zero and
|
|
sets the length of \code{poly} to \code{len}.
|
|
|
|
void fq_zech_poly_clear(fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Clears the given polynomial, releasing any memory used. It must
|
|
be reinitialised in order to be used again.
|
|
|
|
void _fq_zech_poly_normalise(fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Sets the length of \code{poly} so that the top coefficient is
|
|
non-zero. If all coefficients are zero, the length is set to
|
|
zero. This function is mainly used internally, as all functions
|
|
guarantee normalisation.
|
|
|
|
void _fq_zech_poly_normalise2(fq_zech_struct *poly, slong *length,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets the length \code{length} of \code{(poly,length)} so that the
|
|
top coefficient is non-zero. If all coefficients are zero, the
|
|
length is set to zero. This function is mainly used internally, as
|
|
all functions guarantee normalisation.
|
|
|
|
void fq_zech_poly_truncate(fq_zech_poly_t poly, slong newlen,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Truncates the polynomial to length at most~$n$.
|
|
|
|
void _fq_zech_poly_reverse(fq_zech_struct* output, const fq_zech_struct* input,
|
|
slong len, slong m, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{output} to the reverse of \code{input}, which is of
|
|
length \code{len}, but thinking of it as a polynomial of
|
|
length~\code{m}, notionally zero-padded if necessary. The
|
|
length~\code{m} must be non-negative, but there are no other
|
|
restrictions. The polynomial \code{output} must have space for
|
|
\code{m} coefficients.
|
|
|
|
void fq_zech_poly_reverse(fq_zech_poly_t output, const fq_zech_poly_t input,
|
|
slong m, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{output} to the reverse of \code{input}, thinking of it
|
|
as a polynomial of length~\code{m}, notionally zero-padded if
|
|
necessary). The length~\code{m} must be non-negative, but there
|
|
are no other restrictions. The output polynomial will be set to
|
|
length~\code{m} and then normalised.
|
|
|
|
*******************************************************************************
|
|
|
|
Polynomial parameters
|
|
|
|
*******************************************************************************
|
|
|
|
long fq_zech_poly_degree(fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Returns the degree of the polynomial \code{poly}.
|
|
|
|
long fq_zech_poly_length(fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Returns the length of the polynomial \code{poly}.
|
|
|
|
fq_zech_struct * fq_zech_poly_lead(const fq_zech_poly_t poly,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Returns a pointer to the leading coefficient of \code{poly}, or
|
|
\code{NULL} if \code{poly} is the zero polynomial.
|
|
|
|
*******************************************************************************
|
|
|
|
Randomisation
|
|
|
|
*******************************************************************************
|
|
|
|
void fq_zech_poly_randtest(fq_zech_poly_t f, flint_rand_t state,
|
|
slong len, const fq_zech_ctx_t ctx)
|
|
|
|
Sets $f$ to a random polynomial of length at most \code{len}
|
|
with entries in the field described by \code{ctx}.
|
|
|
|
void fq_zech_poly_randtest_not_zero(fq_zech_poly_t f, flint_rand_t state,
|
|
slong len, const fq_zech_ctx_t ctx)
|
|
|
|
Same as \code{fq_zech_poly_randtest} but guarantees that the polynomial
|
|
is not zero.
|
|
|
|
void fq_zech_poly_randtest_monic(fq_zech_poly_t f, flint_rand_t state,
|
|
slong len, const fq_zech_ctx_t ctx)
|
|
|
|
Sets $f$ to a random monic polynomial of length \code{len} with
|
|
entries in the field described by \code{ctx}.
|
|
|
|
void fq_zech_poly_randtest_irreducible(fq_zech_poly_t f, flint_rand_t state,
|
|
slong len, const fq_zech_ctx_t ctx)
|
|
|
|
Sets $f$ to a random monic, irreducible polynomial of length
|
|
\code{len} with entries in the field described by \code{ctx}.
|
|
|
|
*******************************************************************************
|
|
|
|
Assignment and basic manipulation
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_set(fq_zech_struct *rop, const fq_zech_struct *op, slong len,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, len}) to \code{(op, len)}.
|
|
|
|
void fq_zech_poly_set(fq_zech_poly_t poly1, const fq_zech_poly_t poly2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets the polynomial \code{poly1} to the polynomial \code{poly2}.
|
|
|
|
void fq_zech_poly_set_fq_zech(fq_zech_poly_t poly, const fq_zech_t c,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets the polynomial \code{poly} to \code{c}.
|
|
|
|
void fq_zech_poly_swap(fq_zech_poly_t op1, fq_zech_poly_t op2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Swaps the two polynomials \code{op1} and \code{op2}.
|
|
|
|
void _fq_zech_poly_zero(fq_zech_struct *rop, slong len, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, len)} to the zero polynomial.
|
|
|
|
void fq_zech_poly_zero(fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{poly} to the zero polynomial.
|
|
|
|
void void fq_zech_poly_one(fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{poly} to the constant polynomial~$1$.
|
|
|
|
void void fq_zech_poly_gen(fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{poly} to the polynomial~$x$.
|
|
|
|
void fq_zech_poly_make_monic(fq_zech_poly_t rop, const fq_zech_poly_t op,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to \code{op}, normed to have leading coefficient 1.
|
|
|
|
void _fq_zech_poly_make_monic(fq_zech_struct *rop, const fq_zech_struct *op,
|
|
slong length, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to \code{(op,length)}, normed to have leading coefficient 1.
|
|
Assumes that \code{rop} has enough space for the polynomial, assumes that
|
|
\code{op} is not zero (and thus has an invertible leading coefficient).
|
|
|
|
*******************************************************************************
|
|
|
|
Getting and setting coefficients
|
|
|
|
*******************************************************************************
|
|
|
|
void fq_zech_poly_get_coeff(fq_zech_t x, const fq_zech_poly_t poly, slong n,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets $x$ to the coefficient of $X^n$ in \code{poly}.
|
|
|
|
void fq_zech_poly_set_coeff(fq_zech_poly_t poly, slong n, const fq_zech_t x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets the coefficient of $X^n$ in \code{poly} to $x$.
|
|
|
|
void
|
|
fq_zech_poly_set_coeff_fmpz(fq_zech_poly_t poly, slong n, const fmpz_t x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets the coefficient of $X^n$ in the polynomial to $x$,
|
|
assuming $n \geq 0$.
|
|
|
|
*******************************************************************************
|
|
|
|
Comparison
|
|
|
|
*******************************************************************************
|
|
|
|
int fq_zech_poly_equal(const fq_zech_poly_t poly1, const fq_zech_poly_t poly2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Returns whether the two polynomials \code{poly1} and \code{poly2}
|
|
are equal.
|
|
|
|
int fq_zech_poly_is_zero(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Returns whether the polynomial \code{poly} is the zero polynomial.
|
|
|
|
int fq_zech_poly_is_one(const fq_zech_poly_t op)
|
|
|
|
Returns whether the polynomial \code{poly} is equal
|
|
to the constant polynomial~$1$.
|
|
|
|
int fq_zech_poly_is_gen(const fq_zech_poly_t op, const fq_zech_ctx_t ctx)
|
|
|
|
Returns whether the polynomial \code{poly} is equal
|
|
to the polynomial~$x$.
|
|
|
|
int fq_zech_poly_is_unit(const fq_zech_poly_t op, const fq_zech_ctx_t ctx)
|
|
|
|
Returns whether the polynomial \code{poly} is a unit in the polynomial
|
|
ring $\mathbf{F}_q[X]$, i.e. if it has degree $0$ and is non-zero.
|
|
|
|
int fq_zech_poly_equal_fq_zech(const fq_zech_poly_t poly, const fq_zech_t c,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Returns whether the polynomial \code{poly} is equal the (constant)
|
|
$\mathbf{F}_q$ element \code{c}
|
|
|
|
*******************************************************************************
|
|
|
|
Addition and subtraction
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_add(fq_zech_struct *res,
|
|
const fq_zech_struct *poly1, slong len1,
|
|
const fq_zech_struct *poly2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the sum of \code{(poly1,len1)} and \code{(poly2,len2)}.
|
|
|
|
void fq_zech_poly_add(fq_zech_poly_t res, const fq_zech_poly_t poly1,
|
|
const fq_zech_poly_t poly2, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the sum of \code{poly1} and \code{poly2}.
|
|
|
|
void _fq_zech_poly_sub(fq_zech_struct *res,
|
|
const fq_zech_struct *poly1, slong len1,
|
|
const fq_zech_struct *poly2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the difference of \code{(poly1,len1)} and
|
|
\code{(poly2,len2)}.
|
|
|
|
void fq_zech_poly_sub(fq_zech_poly_t res, const fq_zech_poly_t poly1,
|
|
const fq_zech_poly_t poly2, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the difference of \code{poly1} and \code{poly2}.
|
|
|
|
void _fq_zech_poly_neg(fq_zech_struct *rop, const fq_zech_struct *op, slong len,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the additive inverse of \code{(poly,len)}.
|
|
|
|
void fq_zech_poly_neg(fq_zech_poly_t res, const fq_zech_poly_t poly,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the additive inverse of \code{poly}.
|
|
|
|
*******************************************************************************
|
|
|
|
Scalar multiplication and division
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_scalar_mul_fq_zech(fq_zech_struct *rop,
|
|
const fq_zech_struct *op, slong len, const fq_zech_t x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop,len)} to the product of \code{(op,len)} by the
|
|
scalar \code{x}, in the context defined by \code{ctx}.
|
|
|
|
void fq_zech_poly_scalar_mul_fq_zech(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op, const fq_zech_t x, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop,len)} to the product of \code{(op,len)} by the
|
|
scalar \code{x}, in the context defined by \code{ctx}.
|
|
|
|
void _fq_zech_poly_scalar_addmul_fq_zech(fq_zech_struct *rop,
|
|
const fq_zech_struct *op, slong len, const fq_zech_t x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Adds to \code{(rop,len)} the product of \code{(op,len)} by the
|
|
scalar \code{x}, in the context defined by \code{ctx}.
|
|
In particular, assumes the same length for \code{op} and
|
|
\code{rop}.
|
|
|
|
void fq_zech_poly_scalar_addmul_fq_zech(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op, const fq_zech_t x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Adds to \code{rop} the product of \code{op} by the
|
|
scalar \code{x}, in the context defined by \code{ctx}.
|
|
|
|
void _fq_zech_poly_scalar_submul_fq_zech(fq_zech_struct *rop,
|
|
const fq_zech_struct *op, slong len, const fq_zech_t x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Substracts from \code{(rop,len)} the product of \code{(op,len)} by the
|
|
scalar \code{x}, in the context defined by \code{ctx}.
|
|
In particular, assumes the same length for \code{op} and
|
|
\code{rop}.
|
|
|
|
void fq_zech_poly_scalar_submul_fq_zech(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op, const fq_zech_t x, const fq_zech_ctx_t ctx)
|
|
|
|
Substracts from \code{rop} the product of \code{op} by the
|
|
scalar \code{x}, in the context defined by \code{ctx}.
|
|
|
|
*******************************************************************************
|
|
|
|
Multiplication
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_mul_classical(fq_zech_struct *rop,
|
|
const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, len1 + len2 - 1)} to the product of \code{(op1, len1)}
|
|
and \code{(op2, len2)}, assuming that \code{len1} is at least \code{len2}
|
|
and neither is zero.
|
|
|
|
Permits zero padding. Does not support aliasing of \code{rop}
|
|
with either \code{op1} or \code{op2}.
|
|
|
|
void fq_zech_poly_mul_classical(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1,
|
|
const fq_zech_poly_t op2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the product of \code{op1} and \code{op2}
|
|
using classical polynomial multiplication.
|
|
|
|
void _fq_zech_poly_mul_reorder(fq_zech_struct *rop,
|
|
const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, len1 + len2 - 1)} to the product of \code{(op1, len1)}
|
|
and \code{(op2, len2)}, assuming that \code{len1} and \code{len2} are
|
|
non-zero.
|
|
|
|
Permits zero padding. Supports aliasing.
|
|
|
|
void fq_zech_poly_mul_reorder(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1, const fq_zech_poly_t op2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the product of \code{op1} and \code{op2},
|
|
reordering the two indeterminates $X$ and $Y$ when viewing
|
|
the polynomials as elements of $\mathbf{F}_p[X,Y]$.
|
|
|
|
Suppose $\mathbf{F}_q = \mathbf{F}_p[X]/ (f(X))$ and recall
|
|
that elements of $\mathbf{F}_q$ are internally represented
|
|
by elements of type \code{fmpz_poly}. For small degree extensions
|
|
but polynomials in $\mathbf{F}_q[Y]$ of large degree~$n$, we
|
|
change the representation to
|
|
|
|
\begin{equation*}
|
|
\begin{split}
|
|
g(Y) & = \sum_{i=0}^{n} a_i(X) Y^i \\
|
|
& = \sum_{j=0}^{d} \sum_{i=0}^{n} \text{Coeff}(a_i(X), j) Y^i.
|
|
\end{split}
|
|
\end{equation*}
|
|
|
|
This allows us to use a poor algorithm (such as classical multiplication)
|
|
in the $X$-direction and leverage the existing fast integer
|
|
multiplication routines in the $Y$-direction where the polynomial
|
|
degree~$n$ is large.
|
|
|
|
void _fq_zech_poly_mul_KS(fq_zech_struct *rop, const fq_zech_struct *op1,
|
|
slong len1, const fq_zech_struct *op2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, len1 + len2 - 1)} to the product of \code{(op1, len1)}
|
|
and \code{(op2, len2)}.
|
|
|
|
Permits zero padding and places no assumptions on the
|
|
lengths \code{len1} and \code{len2}. Supports aliasing.
|
|
|
|
void fq_zech_poly_mul_KS(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1, const fq_zech_poly_t op2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the product of \code{op1} and \code{op2}
|
|
using Kronecker substitution, that is, by encoding each
|
|
coefficient in $\mathbf{F}_{q}$ as an integer and reducing
|
|
this problem to multiplying two polynomials over the integers.
|
|
|
|
void _fq_zech_poly_mul(fq_zech_struct *rop,
|
|
const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, len1 + len2 - 1)} to the product of \code{(op1, len1)}
|
|
and \code{(op2, len2)}, choosing an appropriate algorithm.
|
|
|
|
Permits zero padding. Does not support aliasing.
|
|
|
|
void fq_zech_poly_mul(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1, const fq_zech_poly_t op2, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the product of \code{op1} and \code{op2},
|
|
choosing an appropriate algorithm.
|
|
|
|
void _fq_zech_poly_mullow_classical(fq_zech_struct *rop,
|
|
const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2, slong n,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(res, n)} to the first $n$ coefficients of
|
|
\code{(poly1, len1)} multiplied by \code{(poly2, len2)}.
|
|
|
|
Assumes \code{0 < n <= len1 + len2 - 1}. Assumes neither
|
|
\code{len1} nor \code{len2} is zero.
|
|
|
|
void fq_zech_poly_mullow_classical(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1, const fq_zech_poly_t op2, slong n, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the product of \code{poly1} and \code{poly2},
|
|
computed using the classical or schoolbook method.
|
|
|
|
void _fq_zech_poly_mullow_KS(fq_zech_struct *rop,
|
|
const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2, slong n,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(res, n)} to the lowest $n$ coefficients of the product of
|
|
\code{(poly1, len1)} and \code{(poly2, len2)}.
|
|
|
|
Assumes that \code{len1} and \code{len2} are positive, but does allow
|
|
for the polynomials to be zero-padded. The polynomials may be zero,
|
|
too. Assumes $n$ is positive. Supports aliasing between \code{res},
|
|
\code{poly1} and \code{poly2}.
|
|
|
|
void fq_zech_poly_mullow_KS(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1, const fq_zech_poly_t op2,
|
|
slong n, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the product of \code{poly1} and \code{poly2}.
|
|
|
|
void _fq_zech_poly_mullow(fq_zech_struct *rop,
|
|
const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2, slong n,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(res, n)} to the lowest $n$ coefficients of the product of
|
|
\code{(poly1, len1)} and \code{(poly2, len2)}.
|
|
|
|
Assumes \code{0 < n <= len1 + len2 - 1}. Allows for zero-padding in
|
|
the inputs. Does not support aliasing between the inputs and the output.
|
|
|
|
void fq_zech_poly_mullow(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1, const fq_zech_poly_t op2, slong n,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the lowest $n$ coefficients of the product of
|
|
\code{poly1} and \code{poly2}.
|
|
|
|
void _fq_zech_poly_mulmod(fq_zech_struct* res,
|
|
const fq_zech_struct* poly1, slong len1,
|
|
const fq_zech_struct* poly2, slong len2,
|
|
const fq_zech_struct* f, slong lenf,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the remainder of the product of \code{poly1}
|
|
and \code{poly2} upon polynomial division by \code{f}.
|
|
|
|
It is required that \code{len1 + len2 - lenf > 0}, which is
|
|
equivalent to requiring that the result will actually be
|
|
reduced. Otherwise, simply use \code{_fq_zech_poly_mul} instead.
|
|
|
|
Aliasing of \code{f} and \code{res} is not permitted.
|
|
|
|
void fq_zech_poly_mulmod(fq_zech_poly_t res,const fq_zech_poly_t poly1,
|
|
const fq_zech_poly_t poly2, const fq_zech_poly_t f,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the remainder of the product of \code{poly1}
|
|
and \code{poly2} upon polynomial division by \code{f}.
|
|
|
|
void _fq_zech_poly_mulmod_preinv(fq_zech_struct* res,
|
|
const fq_zech_struct* poly1, slong len1,
|
|
const fq_zech_struct* poly2, slong len2,
|
|
const fq_zech_struct* f, slong lenf,
|
|
const fq_zech_struct* finv, slong lenfinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the remainder of the product of \code{poly1}
|
|
and \code{poly2} upon polynomial division by \code{f}.
|
|
|
|
It is required that \code{finv} is the inverse of the reverse of
|
|
\code{f} mod \code{x^lenf}. It is required that
|
|
\code{len1 + len2 - lenf > 0}, which is equivalent to requiring that
|
|
the result will actually be reduced. Otherwise, simply use
|
|
\code{_fq_zech_poly_mul} instead.
|
|
|
|
Aliasing of \code{f} or \code{finv} and \code{res} is not
|
|
permitted.
|
|
|
|
void fq_zech_poly_mulmod_preinv(fq_zech_poly_t res, const fq_zech_poly_t poly1,
|
|
const fq_zech_poly_t poly2,
|
|
const fq_zech_poly_t f,
|
|
const fq_zech_poly_t finv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the remainder of the product of \code{poly1}
|
|
and \code{poly2} upon polynomial division by \code{f}. \code{finv}
|
|
is the inverse of the reverse of \code{f}.
|
|
|
|
*******************************************************************************
|
|
|
|
Squaring
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_sqr_classical(fq_zech_struct *rop,
|
|
const fq_zech_struct *op, slong len,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, 2*len - 1)} to the square of \code{(op, len)},
|
|
assuming that \code{(op,len)} is not zero and using classical
|
|
polynomial multiplication.
|
|
|
|
Permits zero padding. Does not support aliasing of \code{rop}
|
|
with either \code{op1} or \code{op2}.
|
|
|
|
void fq_zech_poly_sqr_classical(fq_zech_poly_t rop, const fq_zech_poly_t op,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the square of \code{op} using classical
|
|
polynomial multiplication.
|
|
|
|
|
|
void _fq_zech_poly_sqr_KS(fq_zech_struct *rop, const fq_zech_struct *op,
|
|
slong len, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, 2*len - 1)} to the square of \code{(op, len)}.
|
|
|
|
Permits zero padding and places no assumptions on the
|
|
lengths \code{len1} and \code{len2}. Supports aliasing.
|
|
|
|
void fq_zech_poly_sqr_KS(fq_zech_poly_t rop, const fq_zech_poly_t op,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the square \code{op} using Kronecker substitution,
|
|
that is, by encoding each coefficient in $\mathbf{F}_{q}$ as an integer
|
|
and reducing this problem to multiplying two polynomials over the integers.
|
|
|
|
void _fq_zech_poly_sqr(fq_zech_struct *rop, const fq_zech_struct *op, slong len,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rop, 2* len - 1)} to the square of \code{(op, len)},
|
|
choosing an appropriate algorithm.
|
|
|
|
Permits zero padding. Does not support aliasing.
|
|
|
|
void fq_zech_poly_sqr(fq_zech_poly_t rop, const fq_zech_poly_t op,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the square of \code{op},
|
|
choosing an appropriate algorithm.
|
|
|
|
|
|
*******************************************************************************
|
|
|
|
Powering
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_pow(fq_zech_struct *rop, const fq_zech_struct *op, slong len,
|
|
ulong e, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res = poly^e}, assuming that \code{e, len > 0} and that
|
|
\code{res} has space for \code{e*(len - 1) + 1} coefficients. Does
|
|
not support aliasing.
|
|
|
|
void fq_zech_poly_pow(fq_zech_poly_t rop, const fq_zech_poly_t op, ulong e,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Computes \code{res = poly^e}. If $e$ is zero, returns one,
|
|
so that in particular \code{0^0 = 1}.
|
|
|
|
void _fq_zech_poly_powmod_ui_binexp(fq_zech_struct* res,
|
|
const fq_zech_struct* poly, ulong e,
|
|
const fq_zech_struct* f, slong lenf,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using binary exponentiation. We require \code{e > 0}.
|
|
|
|
We require \code{lenf > 1}. It is assumed that \code{poly} is
|
|
already reduced modulo \code{f} and zero-padded as necessary to
|
|
have length exactly \code{lenf - 1}. The output \code{res} must
|
|
have room for \code{lenf - 1} coefficients.
|
|
|
|
void fq_zech_poly_powmod_ui_binexp(fq_zech_poly_t res,
|
|
const fq_zech_poly_t poly, ulong e,
|
|
const fq_zech_poly_t f,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using binary exponentiation. We require \code{e >= 0}.
|
|
|
|
void
|
|
_fq_zech_poly_powmod_ui_binexp_preinv(fq_zech_struct* res,
|
|
const fq_zech_struct* poly, ulong e,
|
|
const fq_zech_struct* f, slong lenf,
|
|
const fq_zech_struct* finv, slong lenfinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using binary exponentiation. We require \code{e > 0}.
|
|
We require \code{finv} to be the inverse of the reverse of
|
|
\code{f}.
|
|
|
|
We require \code{lenf > 1}. It is assumed that \code{poly} is
|
|
already reduced modulo \code{f} and zero-padded as necessary to
|
|
have length exactly \code{lenf - 1}. The output \code{res} must
|
|
have room for \code{lenf - 1} coefficients.
|
|
|
|
void
|
|
fq_zech_poly_powmod_ui_binexp_preinv(fq_zech_poly_t res,
|
|
const fq_zech_poly_t poly, ulong e,
|
|
const fq_zech_poly_t f, const fq_zech_poly_t finv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using binary exponentiation. We require \code{e >= 0}.
|
|
We require \code{finv} to be the inverse of the reverse of
|
|
\code{f}.
|
|
|
|
void _fq_zech_poly_powmod_fmpz_binexp(fq_zech_struct* res,
|
|
const fq_zech_struct* poly,
|
|
fmpz_t e, const fq_zech_struct* f,
|
|
slong lenf, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using binary exponentiation. We require \code{e > 0}.
|
|
|
|
We require \code{lenf > 1}. It is assumed that \code{poly} is
|
|
already reduced modulo \code{f} and zero-padded as necessary to
|
|
have length exactly \code{lenf - 1}. The output \code{res} must
|
|
have room for \code{lenf - 1} coefficients.
|
|
|
|
void fq_zech_poly_powmod_fmpz_binexp(fq_zech_poly_t res,
|
|
const fq_zech_poly_t poly, fmpz_t e,
|
|
const fq_zech_poly_t f,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using binary exponentiation. We require \code{e >= 0}.
|
|
|
|
void
|
|
_fq_zech_poly_powmod_fmpz_binexp_preinv(fq_zech_struct* res, const fq_zech_struct* poly,
|
|
fmpz_t e, const fq_zech_struct* f, slong lenf,
|
|
const fq_zech_struct* finv, slong lenfinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using binary exponentiation. We require \code{e > 0}.
|
|
We require \code{finv} to be the inverse of the reverse of
|
|
\code{f}.
|
|
|
|
We require \code{lenf > 1}. It is assumed that \code{poly} is
|
|
already reduced modulo \code{f} and zero-padded as necessary to
|
|
have length exactly \code{lenf - 1}. The output \code{res} must
|
|
have room for \code{lenf - 1} coefficients.
|
|
|
|
void
|
|
fq_zech_poly_powmod_fmpz_binexp_preinv(fq_zech_poly_t res,
|
|
const fq_zech_poly_t poly, fmpz_t e,
|
|
const fq_zech_poly_t f,
|
|
const fq_zech_poly_t finv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using binary exponentiation. We require \code{e >= 0}.
|
|
We require \code{finv} to be the inverse of the reverse of
|
|
\code{f}.
|
|
|
|
void
|
|
_fq_zech_poly_powmod_fmpz_sliding_preinv(fq_zech_struct* res,
|
|
const fq_zech_struct* poly,
|
|
fmpz_t e, ulong k,
|
|
const fq_zech_struct* f, slong lenf,
|
|
const fq_zech_struct* finv, slong lenfinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using sliding-window exponentiation with window size
|
|
\code{k}. We require \code{e > 0}. We require \code{finv} to be
|
|
the inverse of the reverse of \code{f}. If \code{k} is set to
|
|
zero, then an "optimum" size will be selected automatically base
|
|
on \code{e}.
|
|
|
|
We require \code{lenf > 1}. It is assumed that \code{poly} is
|
|
already reduced modulo \code{f} and zero-padded as necessary to
|
|
have length exactly \code{lenf - 1}. The output \code{res} must
|
|
have room for \code{lenf - 1} coefficients.
|
|
|
|
void
|
|
fq_zech_poly_powmod_fmpz_sliding_preinv(fq_zech_poly_t res,
|
|
const fq_zech_poly_t poly, fmpz_t e,
|
|
ulong k, const fq_zech_poly_t f,
|
|
const fq_zech_poly_t finv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e} modulo
|
|
\code{f}, using sliding-window exponentiation with window size
|
|
\code{k}. We require \code{e >= 0}. We require \code{finv} to be
|
|
the inverse of the reverse of \code{f}. If \code{k} is set to
|
|
zero, then an "optimum" size will be selected automatically base
|
|
on \code{e}.
|
|
|
|
void
|
|
_fq_zech_poly_powmod_x_fmpz_preinv(fq_zech_struct * res, const fmpz_t e,
|
|
const fq_zech_struct * f, slong lenf,
|
|
const fq_zech_struct * finv, slong lenfinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{x} raised to the power \code{e} modulo \code{f},
|
|
using sliding window exponentiation. We require \code{e > 0}.
|
|
We require \code{finv} to be the inverse of the reverse of \code{f}.
|
|
|
|
We require \code{lenf > 2}. The output \code{res} must have room for
|
|
\code{lenf - 1} coefficients.
|
|
|
|
void
|
|
fq_zech_poly_powmod_x_fmpz_preinv(fq_zech_poly_t res, const fmpz_t e,
|
|
const fq_zech_poly_t f, const fq_zech_poly_t finv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{x} raised to the power \code{e}
|
|
modulo \code{f}, using sliding window exponentiation. We require
|
|
\code{e >= 0}. We require \code{finv} to be the inverse of the reverse of
|
|
\code{f}.
|
|
|
|
*******************************************************************************
|
|
|
|
Shifting
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_shift_left(fq_zech_struct *rop, const fq_zech_struct *op,
|
|
slong len, slong n, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(res, len + n)} to \code{(poly, len)} shifted left by
|
|
$n$ coefficients.
|
|
|
|
Inserts zero coefficients at the lower end. Assumes that
|
|
\code{len} and $n$ are positive, and that \code{res} fits
|
|
\code{len + n} elements. Supports aliasing between \code{res} and
|
|
\code{poly}.
|
|
|
|
void fq_zech_poly_shift_left(fq_zech_poly_t rop, const fq_zech_poly_t op, slong n,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} shifted left by $n$ coeffs. Zero
|
|
coefficients are inserted.
|
|
|
|
void _fq_zech_poly_shift_right(fq_zech_struct *rop, const fq_zech_struct *op,
|
|
slong len, slong n, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(res, len - n)} to \code{(poly, len)} shifted right by
|
|
$n$ coefficients.
|
|
|
|
Assumes that \code{len} and $n$ are positive, that \code{len > n},
|
|
and that \code{res} fits \code{len - n} elements. Supports
|
|
aliasing between \code{res} and \code{poly}, although in this case
|
|
the top coefficients of \code{poly} are not set to zero.
|
|
|
|
void fq_zech_poly_shift_right(fq_zech_poly_t rop, const fq_zech_poly_t op,
|
|
slong n, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to \code{poly} shifted right by $n$ coefficients.
|
|
If $n$ is equal to or greater than the current length of
|
|
\code{poly}, \code{res} is set to the zero polynomial.
|
|
|
|
*******************************************************************************
|
|
|
|
Norms
|
|
|
|
*******************************************************************************
|
|
|
|
long _fq_zech_poly_hamming_weight(const fq_zech_poly *op, slong len,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Returns the number of non-zero entries in \code{(op, len)}.
|
|
|
|
long fq_zech_poly_hamming_weight(const fq_zech_poly_t op,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Returns the number of non-zero entries in the polynomial \code{op}.
|
|
|
|
*******************************************************************************
|
|
|
|
Euclidean division
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_divrem_basecase(fq_zech_struct *Q, fq_zech_struct *R,
|
|
const fq_zech_struct *A, slong lenA, const fq_zech_struct *B, slong lenB,
|
|
const fq_zech_t invB, const fq_zech_ctx_t ctx)
|
|
|
|
Computes \code{(Q, lenA - lenB + 1)}, \code{(R, lenA)} such that
|
|
$A = B Q + R$ with $0 \leq \len(R) < \len(B)$.
|
|
|
|
Assumes that the leading coefficient of $B$ is invertible
|
|
and that \code{invB} is its inverse.
|
|
|
|
Assumes that $\len(A), \len(B) > 0$. Allows zero-padding in
|
|
\code{(A, lenA)}. $R$ and $A$ may be aliased, but apart from
|
|
this no aliasing of input and output operands is allowed.
|
|
|
|
void fq_zech_poly_divrem_basecase(fq_zech_poly_t Q, fq_zech_poly_t R,
|
|
const fq_zech_poly_t A, const fq_zech_poly_t B,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Computes $Q$, $R$ such that $A = B Q + R$ with
|
|
$0 \leq \len(R) < \len(B)$.
|
|
|
|
Assumes that the leading coefficient of $B$ is invertible. This can
|
|
be taken for granted the context is for a finite field, that is, when
|
|
$p$ is prime and $f(X)$ is irreducible.
|
|
|
|
void _fq_zech_poly_divrem(fq_zech_struct *Q, fq_zech_struct *R,
|
|
const fq_zech_struct *A, slong lenA, const fq_zech_struct *B, slong lenB,
|
|
const fq_zech_t invB, const fq_zech_ctx_t ctx)
|
|
|
|
Computes \code{(Q, lenA - lenB + 1)}, \code{(R, lenA)} such that
|
|
$A = B Q + R$ with $0 \leq \len(R) < \len(B)$.
|
|
|
|
Assumes that the leading coefficient of $B$ is invertible
|
|
and that \code{invB} is its inverse.
|
|
|
|
Assumes that $\len(A), \len(B) > 0$. Allows zero-padding in
|
|
\code{(A, lenA)}. $R$ and $A$ may be aliased, but apart from
|
|
this no aliasing of input and output operands is allowed.
|
|
|
|
void fq_zech_poly_divrem(fq_zech_poly_t Q, fq_zech_poly_t R,
|
|
const fq_zech_poly_t A, const fq_zech_poly_t B,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Computes $Q$, $R$ such that $A = B Q + R$ with
|
|
$0 \leq \len(R) < \len(B)$.
|
|
|
|
Assumes that the leading coefficient of $B$ is invertible. This can
|
|
be taken for granted the context is for a finite field, that is, when
|
|
$p$ is prime and $f(X)$ is irreducible.
|
|
|
|
void _fq_zech_poly_rem(fq_zech_struct *R, const fq_zech_struct *A, slong lenA,
|
|
const fq_zech_struct *B, slong lenB, const fq_zech_t invB,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{R} to the remainder of the division of \code{(A,lenA)} by
|
|
\code{(B,lenB)}. Assumes that the leading coefficient of \code{(B,lenB)}
|
|
is invertible and that \code{invB} is its inverse.
|
|
|
|
void fq_zech_poly_rem(fq_zech_poly_t R,
|
|
const fq_zech_poly_t A, const fq_zech_poly_t B,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{R} to the remainder of the division of \code{A} by
|
|
\code{B} in the context described by \code{ctx}.
|
|
|
|
void _fq_zech_poly_div_basecase(fq_zech_struct *Q, fq_zech_struct *R,
|
|
const fq_zech_struct *A, slong lenA,
|
|
const fq_zech_struct *B, slong lenB,
|
|
const fq_zech_t invB, const fq_zech_ctx_t ctx)
|
|
|
|
Notationally, computes $Q$, $R$ such that $A = B Q + R$ with $0
|
|
\leq \len(R) < \len(B)$ but only sets \code{(Q, lenA - lenB + 1)}.
|
|
|
|
Requires temporary space \code{(R, lenA)}. If \code{R} is
|
|
\code{NULL}, then the temporary space will be allocated. Allows
|
|
aliasing only between $A$ and $R$. Allows zero-padding in $A$ but
|
|
not in $B$. Assumes that the leading coefficient of $B$ is a
|
|
unit.
|
|
|
|
void fq_zech_poly_div_basecase(fq_zech_poly_t Q, const fq_zech_poly_t A,
|
|
const fq_zech_poly_t B, const fq_zech_ctx_t ctx)
|
|
|
|
Notionally finds polynomials $Q$ and $R$ such that $A = B Q + R$ with
|
|
$\len(R) < \len(B)$, but returns only \code{Q}. If $\len(B) = 0$ an
|
|
exception is raised.
|
|
|
|
void _fq_zech_poly_divrem_divconquer_recursive(fq_zech_struct * Q, fq_zech_struct * BQ,
|
|
fq_zech_struct * W, const fq_zech_struct * A,
|
|
const fq_zech_struct * B, slong lenB,
|
|
const fq_zech_t invB, const fq_zech_ctx_t ctx)
|
|
|
|
Computes \code{(Q, lenB)}, \code{(BQ, 2 lenB - 1)} such that
|
|
$BQ = B \times Q$ and $A = B Q + R$ where $0 \leq \len(R) < \len(B)$.
|
|
|
|
Assumes that the leading coefficient of $B$ is invertible and that
|
|
\code{invB} is the inverse.
|
|
|
|
Assumes $\len(B) > 0$. Allows zero-padding in \code{(A, lenA)}. Requires
|
|
a temporary array \code{(W, 2 lenB - 1)}. No aliasing of input and output
|
|
operands is allowed.
|
|
|
|
This function does not read the bottom $\len(B) - 1$ coefficients from
|
|
$A$, which means that they might not even need to exist in allocated
|
|
memory.
|
|
|
|
void _fq_zech_poly_divrem_divconquer(fq_zech_struct * Q, fq_zech_struct * R,
|
|
const fq_zech_struct * A, slong lenA,
|
|
const fq_zech_struct * B, slong lenB,
|
|
const fq_zech_t invB, const fq_zech_ctx_t ctx)
|
|
|
|
Computes \code{(Q, lenA - lenB + 1)}, \code{(R, lenA)} such that
|
|
$A = B Q + R$ and $0 \leq \len(R) < \len(B)$.
|
|
|
|
Assumes that the leading coefficient of $B$ is invertible and that
|
|
\code{invB} is the inverse.
|
|
|
|
Assumes $\len(A) \geq \len(B) > 0$. Allows zero-padding in
|
|
\code{(A, lenA)}. No aliasing of input and output operands is
|
|
allowed.
|
|
|
|
void fq_zech_poly_divrem_divconquer(fq_zech_poly_t Q, fq_zech_poly_t R,
|
|
const fq_zech_poly_t A, const fq_zech_poly_t B,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Computes $Q$, $R$ such that $A = B Q + R$ and $0 \leq \len(R) < \len(B)$.
|
|
|
|
Assumes that $B$ is non-zero and that the leading coefficient of
|
|
$B$ is invertible.
|
|
|
|
void _fq_zech_poly_div_newton_n_preinv(fq_zech_struct* Q,
|
|
const fq_zech_struct* A, slong lenA,
|
|
const fq_zech_struct* B, slong lenB,
|
|
const fq_zech_struct* Binv, slong lenBinv,
|
|
const fq_zech_struct ctx_t)
|
|
|
|
Notionally computes polynomials $Q$ and $R$ such that $A = BQ + R$ with
|
|
$\len(R)$ less than \code{lenB}, where \code{A} is of length \code{lenA}
|
|
and \code{B} is of length \code{lenB}, but return only $Q$.
|
|
|
|
We require that $Q$ have space for \code{lenA - lenB + 1} coefficients
|
|
and assume that the leading coefficient of $B$ is a unit. Furthermore, we
|
|
assume that $Binv$ is the inverse of the reverse of $B$ mod $x^{\len(B)}$.
|
|
|
|
The algorithm used is to reverse the polynomials and divide the
|
|
resulting power series, then reverse the result.
|
|
|
|
void fq_zech_poly_div_newton_n_preinv(fq_zech_poly_t Q, const fq_zech_poly_t A,
|
|
const fq_zech_poly_t B, const fq_zech_poly_t Binv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Notionally computes $Q$ and $R$ such that $A = BQ + R$ with
|
|
$\len(R) < \len(B)$, but returns only $Q$.
|
|
|
|
We assume that the leading coefficient of $B$ is a unit and that $Binv$ is
|
|
the inverse of the reverse of $B$ mod $x^{\len(B)}$.
|
|
|
|
It is required that the length of $A$ is less than or equal to
|
|
2*the length of $B$ - 2.
|
|
|
|
The algorithm used is to reverse the polynomials and divide the
|
|
resulting power series, then reverse the result.
|
|
|
|
void _fq_zech_poly_divrem_newton_n_preinv(fq_zech_struct* Q, fq_zech_struct* R,
|
|
const fq_zech_struct* A, slong lenA,
|
|
const fq_zech_struct* B, slong lenB,
|
|
const fq_zech_struct* Binv, slong lenBinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Computes $Q$ and $R$ such that $A = BQ + R$ with $\len(R)$ less
|
|
than \code{lenB}, where $A$ is of length \code{lenA} and $B$ is of
|
|
length \code{lenB}. We require that $Q$ have space for
|
|
\code{lenA - lenB + 1} coefficients. Furthermore, we assume that $Binv$ is
|
|
the inverse of the reverse of $B$ mod $x^{\len(B)}$. The algorithm
|
|
used is to call \code{div_newton_preinv()} and then multiply out
|
|
and compute the remainder.
|
|
|
|
void fq_zech_poly_divrem_newton_n_preinv(fq_zech_poly_t Q, fq_zech_poly_t R,
|
|
const fq_zech_poly_t A, const fq_zech_poly_t B,
|
|
const fq_zech_poly_t Binv, const fq_zech_ctx_t ctx)
|
|
|
|
Computes $Q$ and $R$ such that $A = BQ + R$ with $\len(R) <
|
|
\len(B)$. We assume $Binv$ is the inverse of the reverse of $B$
|
|
mod $x^{\len(B)}$.
|
|
|
|
It is required that the length of $A$ is less than or equal to
|
|
2*the length of $B$ - 2.
|
|
|
|
The algorithm used is to call \code{div_newton()} and then
|
|
multiply out and compute the remainder.
|
|
|
|
void
|
|
_fq_zech_poly_inv_series_newton(fq_zech_struct* Qinv, const fq_zech_struct* Q, slong n,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Given \code{Q} of length \code{n} whose constant coefficient is
|
|
invertible modulo the given modulus, find a polynomial \code{Qinv}
|
|
of length \code{n} such that \code{Q * Qinv} is \code{1} modulo
|
|
$x^n$. Requires \code{n > 0}. This function can be viewed as
|
|
inverting a power series via Newton iteration.
|
|
|
|
void
|
|
fq_zech_poly_inv_series_newton(fq_zech_poly_t Qinv, const fq_zech_poly_t Q, slong n,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Given \code{Q} find \code{Qinv} such that \code{Q * Qinv} is
|
|
\code{1} modulo $x^n$. The constant coefficient of \code{Q} must
|
|
be invertible modulo the modulus of \code{Q}. An exception is
|
|
raised if this is not the case or if \code{n = 0}. This function
|
|
can be viewed as inverting a power series via Newton iteration.
|
|
|
|
*******************************************************************************
|
|
|
|
Greatest common divisor
|
|
|
|
*******************************************************************************
|
|
|
|
void fq_zech_poly_gcd(fq_zech_poly_t rop, const fq_zech_poly_t op1,
|
|
const fq_zech_poly_t op2, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the greatest common divisor of \code{op1} and
|
|
\code{op2}, using the either the Euclidean or HGCD algorithm. The
|
|
GCD of zero polynomials is defined to be zero, whereas the GCD of
|
|
the zero polynomial and some other polynomial $P$ is defined to be
|
|
$P$. Except in the case where the GCD is zero, the GCD $G$ is made
|
|
monic.
|
|
|
|
long _fq_zech_poly_gcd(fq_zech_struct* G,const fq_zech_struct* A, slong lenA,
|
|
const fq_zech_struct* B, slong lenB,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Computes the GCD of $A$ of length \code{lenA} and $B$ of length
|
|
\code{lenB}, where \code{lenA >= lenB > 0} and sets $G$ to it. The
|
|
length of the GCD $G$ is returned by the function. No attempt is
|
|
made to make the GCD monic. It is required that $G$ have space for
|
|
\code{lenB} coefficients.
|
|
|
|
void fq_zech_poly_gcd_euclidean(fq_zech_poly_t rop, const fq_zech_poly_t op1,
|
|
const fq_zech_poly_t op2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the greatest common divisor of \code{op1} and
|
|
\code{op2}, using the Euclidean algorithm. The GCD of zero
|
|
polynomials is defined to be zero, whereas the GCD of the zero
|
|
polynomial and some other polynomial $P$ is defined to be
|
|
$P$. Except in the case where the GCD is zero, the GCD $G$ is made
|
|
monic.
|
|
|
|
long _fq_zech_poly_gcd_euclidean(fq_zech_struct* G,
|
|
const fq_zech_struct* A, slong lenA,
|
|
const fq_zech_struct* B, slong lenB,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Computes the GCD of $A$ of length \code{lenA} and $B$ of length
|
|
\code{lenB}, where \code{lenA >= lenB > 0} and sets $G$ to it. The
|
|
length of the GCD $G$ is returned by the function. No attempt is
|
|
made to make the GCD monic. It is required that $G$ have space for
|
|
\code{lenB} coefficients.
|
|
|
|
*******************************************************************************
|
|
|
|
Divisibility testing
|
|
|
|
*******************************************************************************
|
|
|
|
int _fq_zech_poly_divides(fq_zech_struct *Q,
|
|
const fq_zech_struct *A, slong lenA,
|
|
const fq_zech_struct *B, slong lenB, const fq_zech_t invB,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Returns $1$ if \code{(B, lenB)} divides \code{(A, lenA)} exactly and
|
|
sets $Q$ to the quotient, otherwise returns $0$.
|
|
|
|
It is assumed that $\len(A) \geq \len(B) > 0$ and that $Q$ has space
|
|
for $\len(A) - \len(B) + 1$ coefficients.
|
|
|
|
Aliasing of $Q$ with either of the inputs is not permitted.
|
|
|
|
This function is currently unoptimised and provided for convenience
|
|
only.
|
|
|
|
int fq_zech_poly_divides(fq_zech_poly_t Q, const fq_zech_poly_t A, const fq_zech_poly_t B,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
|
|
Returns $1$ if $B$ divides $A$ exactly and sets $Q$ to the quotient,
|
|
otherwise returns $0$.
|
|
|
|
This function is currently unoptimised and provided for convenience
|
|
only.
|
|
|
|
*******************************************************************************
|
|
|
|
Derivative
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_derivative(fq_zech_struct *rop, const fq_zech_struct *op, slong len,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{(rpoly, len - 1)} to the derivative of \code{(poly, len)}.
|
|
Also handles the cases where \code{len} is $0$ or $1$ correctly.
|
|
Supports aliasing of \code{rpoly} and \code{poly}.
|
|
|
|
void fq_zech_poly_derivative(fq_zech_poly_t rop, const fq_zech_poly_t op, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the derivative of \code{poly}.
|
|
|
|
*******************************************************************************
|
|
|
|
Evaluation
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_evaluate_fq_zech(fq_zech_t rop, const fq_zech_struct *op, slong len,
|
|
const fq_zech_t a, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to \code{(op, len)} evaluated at $a$.
|
|
|
|
Supports zero padding. There are no restrictions on \code{len}, that
|
|
is, \code{len} is allowed to be zero, too.
|
|
|
|
void fq_zech_poly_evaluate_fq_zech(fq_zech_t rop, const fq_zech_poly_t f, const fq_zech_t a,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the value of $f(a)$.
|
|
|
|
As the coefficient ring $\mathbf{F}_q$ is finite, Horner's method
|
|
is sufficient.
|
|
|
|
*******************************************************************************
|
|
|
|
Composition
|
|
|
|
*******************************************************************************
|
|
|
|
void _fq_zech_poly_compose_divconquer(fq_zech_struct *rop,
|
|
const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Computes the composition of \code{(op1, len1)} and \code{(op2, len2)}
|
|
using a divide and conquer approach and places the result into \code{rop},
|
|
assuming \code{rop} can hold the output of length
|
|
\code{(len1 - 1) * (len2 - 1) + 1}.
|
|
|
|
Assumes \code{len1, len2 > 0}. Does not support aliasing between
|
|
\code{rop} and any of \code{(op1, len1)} and \code{(op2, len2)}.
|
|
|
|
void fq_zech_poly_compose_divconquer(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1, const fq_zech_poly_t op2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the composition of \code{op1} and \code{op2}.
|
|
To be precise about the order of composition, denoting \code{rop},
|
|
\code{op1}, and \code{op2} by $f$, $g$, and $h$, respectively,
|
|
sets $f(t) = g(h(t))$.
|
|
|
|
void _fq_zech_poly_compose_horner(fq_zech_struct *rop, const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the composition of \code{(op1, len1)} and
|
|
\code{(op2, len2)}.
|
|
|
|
Assumes that \code{rop} has space for \code{(len1-1)*(len2-1) + 1}
|
|
coefficients. Assumes that \code{op1} and \code{op2} are non-zero
|
|
polynomials. Does not support aliasing between any of the inputs and
|
|
the output.
|
|
|
|
void fq_zech_poly_compose_horner(fq_zech_poly_t rop,
|
|
const fq_zech_poly_t op1, const fq_zech_poly_t op2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the composition of \code{op1} and \code{op2}.
|
|
To be more precise, denoting \code{rop}, \code{op1}, and \code{op2}
|
|
by $f$, $g$, and $h$, sets $f(t) = g(h(t))$.
|
|
|
|
This implementation uses Horner's method.
|
|
|
|
void _fq_zech_poly_compose(fq_zech_struct *rop, const fq_zech_struct *op1, slong len1,
|
|
const fq_zech_struct *op2, slong len2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the composition of \code{(op1, len1)} and
|
|
\code{(op2, len2)}.
|
|
|
|
Assumes that \code{rop} has space for \code{(len1-1)*(len2-1) + 1}
|
|
coefficients. Assumes that \code{op1} and \code{op2} are non-zero
|
|
polynomials. Does not support aliasing between any of the inputs and
|
|
the output.
|
|
|
|
void fq_zech_poly_compose(fq_zech_poly_t rop, const fq_zech_poly_t op1, const fq_zech_poly_t op2,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{rop} to the composition of \code{op1} and \code{op2}.
|
|
To be precise about the order of composition, denoting \code{rop},
|
|
\code{op1}, and \code{op2} by $f$, $g$, and $h$, respectively,
|
|
sets $f(t) = g(h(t))$.
|
|
|
|
void _fq_zech_poly_compose_mod_horner(fq_zech_struct * res,
|
|
const fq_zech_struct * f, slong lenf,
|
|
const fq_zech_struct * g,
|
|
const fq_zech_struct * h, slong lenh,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require that
|
|
$h$ is nonzero and that the length of $g$ is one less than the
|
|
length of $h$ (possibly with zero padding). The output is not allowed
|
|
to be aliased with any of the inputs.
|
|
|
|
The algorithm used is Horner's rule.
|
|
|
|
void fq_zech_poly_compose_mod_horner(fq_zech_poly_t res, const fq_zech_poly_t f,
|
|
const fq_zech_poly_t g, const fq_zech_poly_t h,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require that
|
|
$h$ is nonzero. The algorithm used is Horner's rule.
|
|
|
|
void _fq_zech_poly_compose_mod_horner_preinv(fq_zech_struct * res,
|
|
const fq_zech_struct * f, slong lenf,
|
|
const fq_zech_struct * g,
|
|
const fq_zech_struct * h, slong lenh,
|
|
const fq_zech_struct * hinv, slong lenhiv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that the length of $g$ is one less than
|
|
the length of $h$ (possibly with zero padding). We also require
|
|
that the length of $f$ is less than the length of
|
|
$h$. Furthermore, we require \code{hinv} to be the inverse of the
|
|
reverse of \code{h}. The output is not allowed to be aliased with
|
|
any of the inputs.
|
|
|
|
The algorithm used is Horner's rule.
|
|
|
|
void fq_zech_poly_compose_mod_horner_preinv(fq_zech_poly_t res, const fq_zech_poly_t f,
|
|
const fq_zech_poly_t g, const fq_zech_poly_t h,
|
|
const fq_zech_poly_t hinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that $f$ has smaller degree than
|
|
$h$. Furthermore, we require \code{hinv} to be the inverse of the
|
|
reverse of \code{h}. The algorithm used is Horner's rule.
|
|
|
|
|
|
void _fq_zech_poly_compose_mod_brent_kung(fq_zech_struct * res,
|
|
const fq_zech_struct * f, slong lenf,
|
|
const fq_zech_struct * g,
|
|
const fq_zech_struct * h, slong lenh,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that the length of $g$ is one less than
|
|
the length of $h$ (possibly with zero padding). We also require
|
|
that the length of $f$ is less than the length of $h$. The output
|
|
is not allowed to be aliased with any of the inputs.
|
|
|
|
The algorithm used is the Brent-Kung matrix algorithm.
|
|
|
|
void fq_zech_poly_compose_mod_brent_kung(fq_zech_poly_t res, const fq_zech_poly_t f,
|
|
const fq_zech_poly_t g, const fq_zech_poly_t h,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that $f$ has smaller degree than $h$. The
|
|
algorithm used is the Brent-Kung matrix algorithm.
|
|
|
|
void _fq_zech_poly_compose_mod_brent_kung_preinv(fq_zech_struct * res,
|
|
const fq_zech_struct * f, slong lenf,
|
|
const fq_zech_struct * g,
|
|
const fq_zech_struct * h, slong lenh,
|
|
const fq_zech_struct * hinv, slong lenhiv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that the length of $g$ is one less than
|
|
the length of $h$ (possibly with zero padding). We also require
|
|
that the length of $f$ is less than the length of
|
|
$h$. Furthermore, we require \code{hinv} to be the inverse of the
|
|
reverse of \code{h}. The output is not allowed to be aliased with
|
|
any of the inputs.
|
|
|
|
The algorithm used is the Brent-Kung matrix algorithm.
|
|
|
|
void fq_zech_poly_compose_mod_brent_kung_preinv(fq_zech_poly_t res, const fq_zech_poly_t f,
|
|
const fq_zech_poly_t g, const fq_zech_poly_t h,
|
|
const fq_zech_poly_t hinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that $f$ has smaller degree than
|
|
$h$. Furthermore, we require \code{hinv} to be the inverse of the
|
|
reverse of \code{h}. The algorithm used is the Brent-Kung matrix
|
|
algorithm.
|
|
|
|
void _fq_zech_poly_compose_mod(fq_zech_struct * res, const fq_zech_struct * f, slong lenf,
|
|
const fq_zech_struct * g, const fq_zech_struct * h, slong lenh,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that the length of $g$ is one less than
|
|
the length of $h$ (possibly with zero padding). The output is not
|
|
allowed to be aliased with any of the inputs.
|
|
|
|
void fq_zech_poly_compose_mod(fq_zech_poly_t res, const fq_zech_poly_t f, const fq_zech_poly_t g,
|
|
const fq_zech_poly_t h, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero.
|
|
|
|
void _fq_zech_poly_compose_mod_preinv(fq_zech_struct * res,
|
|
const fq_zech_struct * f, slong lenf,
|
|
const fq_zech_struct * g,
|
|
const fq_zech_struct * h, slong lenh,
|
|
const fq_zech_struct * hinv, slong lenhiv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that the length of $g$ is one less than
|
|
the length of $h$ (possibly with zero padding). We also require
|
|
that the length of $f$ is less than the length of
|
|
$h$. Furthermore, we require \code{hinv} to be the inverse of the
|
|
reverse of \code{h}. The output is not allowed to be aliased with
|
|
any of the inputs.
|
|
|
|
void fq_zech_poly_compose_mod_preinv(fq_zech_poly_t res, const fq_zech_poly_t f,
|
|
const fq_zech_poly_t g, const fq_zech_poly_t h,
|
|
const fq_zech_poly_t hinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero and that $f$ has smaller degree than
|
|
$h$. Furthermore, we require \code{hinv} to be the inverse of the
|
|
reverse of \code{h}.
|
|
|
|
void
|
|
_fq_zech_poly_reduce_matrix_mod_poly (fq_zech_mat_t A, const fq_zech_mat_t B,
|
|
const fq_zech_poly_t f, const fq_zech_ctx_t ctx)
|
|
|
|
Sets the ith row of \code{A} to the reduction of the ith row of $B$ modulo
|
|
$f$ for $i=1,\ldots,\sqrt{\deg(f)}$. We require $B$ to be at least
|
|
a $\sqrt{\deg(f)}\times \deg(f)$ matrix and $f$ to be nonzero.
|
|
|
|
void
|
|
_fq_zech_poly_precompute_matrix (fq_zech_mat_t A, const fq_zech_struct* f, const fq_zech_struct* g,
|
|
slong leng, const fq_zech_struct* ginv, slong lenginv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets the ith row of \code{A} to $f^i$ modulo $g$ for
|
|
$i=1,\ldots,\sqrt{\deg(g)}$. We require $A$ to be a
|
|
$\sqrt{\deg(g)}\times \deg(g)$ matrix. We require \code{ginv} to
|
|
be the inverse of the reverse of \code{g} and $g$ to be nonzero.
|
|
|
|
void
|
|
fq_zech_poly_precompute_matrix (fq_zech_mat_t A, const fq_zech_poly_t f,
|
|
const fq_zech_poly_t g, const fq_zech_poly_t ginv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets the ith row of \code{A} to $f^i$ modulo $g$ for
|
|
$i=1,\ldots,\sqrt{\deg(g)}$. We require $A$ to be a
|
|
$\sqrt{\deg(g)}\times \deg(g)$ matrix. We require \code{ginv} to
|
|
be the inverse of the reverse of \code{g}.
|
|
|
|
|
|
void
|
|
_fq_zech_poly_compose_mod_brent_kung_precomp_preinv(fq_zech_struct* res, const fq_zech_struct* f,
|
|
slong lenf, const fq_zech_mat_t A, const fq_zech_struct* h,
|
|
slong h, const fq_zech_struct* hinv, slong lenhinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that $h$ is nonzero. We require that the ith row of $A$ contains
|
|
$g^i$ for $i=1,\ldots,\sqrt{\deg(h)}$, i.e. $A$ is a
|
|
$\sqrt{\deg(h)}\times \deg(h)$ matrix. We also require that the
|
|
length of $f$ is less than the length of $h$. Furthermore, we
|
|
require \code{hinv} to be the inverse of the reverse of \code{h}.
|
|
The output is not allowed to be aliased with any of the inputs.
|
|
|
|
The algorithm used is the Brent-Kung matrix algorithm.
|
|
|
|
void
|
|
fq_zech_poly_compose_mod_brent_kung_precomp_preinv(fq_zech_poly_t res,
|
|
const fq_zech_poly_t f, const fq_zech_mat_t A,
|
|
const fq_zech_poly_t h, const fq_zech_poly_t hinv,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require
|
|
that the ith row of $A$ contains $g^i$ for
|
|
$i=1,\ldots,\sqrt{\deg(h)}$, i.e. $A$ is a $\sqrt{\deg(h)}\times
|
|
\deg(h)$ matrix. We require that $h$ is nonzero and that $f$ has
|
|
smaller degree than $h$. Furthermore, we require \code{hinv} to be
|
|
the inverse of the reverse of \code{h}. This version of Brent-Kung
|
|
modular composition is particularly useful if one has to perform
|
|
several modular composition of the form $f(g)$ modulo $h$ for
|
|
fixed $g$ and $h$.
|
|
|
|
|
|
*******************************************************************************
|
|
|
|
Output
|
|
|
|
*******************************************************************************
|
|
|
|
int _fq_zech_poly_fprint_pretty(FILE *file, const fq_zech_struct *poly, slong len,
|
|
const char *x, const fq_zech_ctx_t ctx)
|
|
|
|
Prints the pretty representation of \code{(poly, len)} to the stream
|
|
\code{file}, using the string \code{x} to represent the indeterminate.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
int fq_zech_poly_fprint_pretty(FILE * file, const fq_zech_poly_t poly, const char *x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Prints the pretty representation of \code{poly} to the stream
|
|
\code{file}, using the string \code{x} to represent the indeterminate.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
|
|
int _fq_zech_poly_print_pretty(const fq_zech_struct *poly, slong len,
|
|
const char *x, const fq_zech_ctx_t ctx)
|
|
|
|
Prints the pretty representation of \code{(poly, len)} to \code{stdout},
|
|
using the string \code{x} to represent the indeterminate.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
|
|
int fq_zech_poly_print_pretty(const fq_zech_poly_t poly, const char *x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Prints the pretty representation of \code{poly} to \code{stdout},
|
|
using the string \code{x} to represent the indeterminate.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
int _fq_zech_poly_fprint(FILE *file, const fq_zech_struct *poly, slong len,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Prints the pretty representation of \code{(poly, len)} to the stream
|
|
\code{file}.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
int fq_zech_poly_fprint(FILE * file, const fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Prints the pretty representation of \code{poly} to the stream
|
|
\code{file}.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
|
|
int _fq_zech_poly_print(const fq_zech_struct *poly, slong len, const fq_zech_ctx_t ctx)
|
|
|
|
Prints the pretty representation of \code{(poly, len)} to \code{stdout}.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
|
|
int fq_zech_poly_print(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Prints the representation of \code{poly} to \code{stdout}.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
char * _fq_zech_poly_get_str(const fq_zech_struct * poly, slong len, const fq_zech_ctx_t ctx)
|
|
|
|
Returns the plain FLINT string representation of the polynomial
|
|
\code{(poly, len)}.
|
|
|
|
char * fq_zech_poly_get_str(const fq_zech_poly_t poly, const fq_zech_ctx_t ctx)
|
|
|
|
Returns the plain FLINT string representation of the polynomial
|
|
\code{poly}.
|
|
|
|
char * _fq_zech_poly_get_str_pretty(const fq_zech_struct * poly, slong len,
|
|
const char * x, const fq_zech_ctx_t ctx)
|
|
|
|
Returns a pretty representation of the polynomial
|
|
\code{(poly, len)} using the null-terminated string~\code{x} as the
|
|
variable name.
|
|
|
|
char * fq_zech_poly_get_str_pretty(const fq_zech_poly_t poly, const char * x,
|
|
const fq_zech_ctx_t ctx)
|
|
|
|
Returns a pretty representation of the polynomial~\code{poly} using the
|
|
null-terminated string \code{x} as the variable name
|
|
|
|
*******************************************************************************
|
|
|
|
Inflation and deflation
|
|
|
|
*******************************************************************************
|
|
|
|
void fq_zech_poly_inflate(fq_zech_poly_t result, const fq_zech_poly_t input,
|
|
ulong inflation, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{result} to the inflated polynomial $p(x^n)$ where
|
|
$p$ is given by \code{input} and $n$ is given by \code{inflation}.
|
|
|
|
void fq_zech_poly_deflate(fq_zech_poly_t result, const fq_zech_poly_t input,
|
|
ulong deflation, const fq_zech_ctx_t ctx)
|
|
|
|
Sets \code{result} to the deflated polynomial $p(x^{1/n})$ where
|
|
$p$ is given by \code{input} and $n$ is given by \code{deflation}.
|
|
Requires $n > 0$.
|
|
|
|
ulong fq_zech_poly_deflation(const fq_zech_poly_t input, const fq_zech_ctx_t ctx)
|
|
|
|
Returns the largest integer by which \code{input} can be deflated.
|
|
As special cases, returns 0 if \code{input} is the zero polynomial
|
|
and 1 of \code{input} is a constant polynomial.
|