1613 lines
65 KiB
Plaintext
1613 lines
65 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 Sebastian Pancratz
|
|
Copyright (C) 2011 Fredrik Johansson
|
|
Copyright (C) 2013 Mike Hansen
|
|
|
|
******************************************************************************/
|
|
|
|
*******************************************************************************
|
|
|
|
Memory management
|
|
|
|
*******************************************************************************
|
|
|
|
void fmpz_mod_poly_init(fmpz_mod_poly_t poly, const fmpz_t p)
|
|
|
|
Initialises \code{poly} for use over $\mathbf{Z} / p \mathbf{Z}$,
|
|
setting its length to zero.
|
|
|
|
A corresponding call to \code{fmpz_mod_poly_clear()} must be made after
|
|
finishing with the \code{fmpz_mod_poly_t} to free the memory used by
|
|
the polynomial. The user is also responsible to clearing the
|
|
integer~$p$.
|
|
|
|
void fmpz_mod_poly_init2(fmpz_mod_poly_t poly, const fmpz_t p, slong alloc)
|
|
|
|
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.
|
|
|
|
void fmpz_mod_poly_clear(fmpz_mod_poly_t poly)
|
|
|
|
Clears the given polynomial, releasing any memory used. It must
|
|
be reinitialised in order to be used again.
|
|
|
|
void fmpz_mod_poly_realloc(fmpz_mod_poly_t poly, slong alloc)
|
|
|
|
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 fmpz_mod_poly_fit_length(fmpz_mod_poly_t poly, slong len)
|
|
|
|
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 it 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 _fmpz_mod_poly_normalise(fmpz_mod_poly_t poly)
|
|
|
|
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 _fmpz_mod_poly_set_length(fmpz_mod_poly_t poly, slong len)
|
|
|
|
Demotes the coefficients of \code{poly} beyond \code{len} and sets
|
|
the length of \code{poly} to \code{len}.
|
|
|
|
void fmpz_mod_poly_truncate(fmpz_mod_poly_t poly, slong len)
|
|
|
|
If the current length of \code{poly} is greater than \code{len}, it
|
|
is truncated to have the given length. Discarded coefficients are
|
|
not necessarily set to zero.
|
|
|
|
*******************************************************************************
|
|
|
|
Randomisation
|
|
|
|
*******************************************************************************
|
|
|
|
void fmpz_mod_poly_randtest(fmpz_mod_poly_t f, flint_rand_t state, slong len)
|
|
|
|
Sets the polynomial~$f$ to a random polynomial of length up~\code{len}.
|
|
|
|
void fmpz_mod_poly_randtest_irreducible(fmpz_mod_poly_t f,
|
|
flint_rand_t state, slong len)
|
|
|
|
Sets the polynomial~$f$ to a random irreducible polynomial of length
|
|
up~\code{len}, assuming \code{len} is positive.
|
|
|
|
void fmpz_mod_poly_randtest_not_zero(fmpz_mod_poly_t f,
|
|
flint_rand_t state, slong len)
|
|
|
|
Sets the polynomial~$f$ to a random polynomial of length up~\code{len},
|
|
assuming \code{len} is positive.
|
|
|
|
void fmpz_mod_poly_randtest_monic(fmpz_mod_poly_t poly, flint_rand_t state,
|
|
slong len)
|
|
|
|
Generates a random monic polynomial with length \code{len}.
|
|
|
|
void
|
|
fmpz_mod_poly_randtest_monic_irreducible(fmpz_mod_poly_t poly,
|
|
flint_rand_t state, slong len)
|
|
|
|
Generates a random monic irreducible polynomial with length \code{len}.
|
|
|
|
|
|
void
|
|
fmpz_mod_poly_randtest_trinomial(fmpz_mod_poly_t poly, flint_rand_t state,
|
|
slong len)
|
|
|
|
Generates a random monic trinomial of length \code{len}.
|
|
|
|
int
|
|
fmpz_mod_poly_randtest_trinomial_irreducible(fmpz_mod_poly_t poly,
|
|
flint_rand_t state,
|
|
slong len, slong max_attempts)
|
|
|
|
Attempts to set \code{poly} to a monic irreducible trinomial of
|
|
length \code{len}. It will generate up to \code{max_attempts}
|
|
trinomials in attempt to find an irreducible one. If
|
|
\code{max_attempts} is \code{0}, then it will keep generating
|
|
trinomials until an irreducible one is found. Returns $1$ if one
|
|
is found and $0$ otherwise.
|
|
|
|
void
|
|
fmpz_mod_poly_randtest_pentomial(fmpz_mod_poly_t poly, flint_rand_t state,
|
|
slong len)
|
|
|
|
Generates a random monic pentomial of length \code{len}.
|
|
|
|
int
|
|
fmpz_mod_poly_randtest_pentomial_irreducible(fmpz_mod_poly_t poly,
|
|
flint_rand_t state,
|
|
slong len, slong max_attempts)
|
|
|
|
Attempts to set \code{poly} to a monic irreducible pentomial of
|
|
length \code{len}. It will generate up to \code{max_attempts}
|
|
pentomials in attempt to find an irreducible one. If
|
|
\code{max_attempts} is \code{0}, then it will keep generating
|
|
pentomials until an irreducible one is found. Returns $1$ if one
|
|
is found and $0$ otherwise.
|
|
|
|
void
|
|
fmpz_mod_poly_randtest_sparse_irreducible(fmpz_mod_poly_t poly,
|
|
flint_rand_t state, slong len)
|
|
|
|
Attempts to set \code{poly} to a sparse, monic irreducible polynomial
|
|
with length \code{len}. It attempts to find an irreducible
|
|
trinomial. If that does not succeed, it attempts to find a
|
|
irreducible pentomial. If that fails, then \code{poly} is just
|
|
set to a random monic irreducible polynomial.
|
|
|
|
|
|
*******************************************************************************
|
|
|
|
Attributes
|
|
|
|
*******************************************************************************
|
|
|
|
fmpz * fmpz_mod_poly_modulus(const fmpz_mod_poly_t poly)
|
|
|
|
Returns the modulus of this polynomial. This function is
|
|
implemented as a macro.
|
|
|
|
slong fmpz_mod_poly_degree(const fmpz_mod_poly_t poly)
|
|
|
|
Returns the degree of the polynomial. The degree of the zero
|
|
polynomial is defined to be $-1$.
|
|
|
|
slong fmpz_mod_poly_length(const fmpz_mod_poly_t poly)
|
|
|
|
Returns the length of the polynomial, which is one more than
|
|
its degree.
|
|
|
|
fmpz * fmpz_mod_poly_lead(const fmpz_mod_poly_t poly)
|
|
|
|
Returns a pointer to the first leading coefficient of \code{poly}
|
|
if this is non-zero, otherwise returns \code{NULL}.
|
|
|
|
*******************************************************************************
|
|
|
|
Assignment and basic manipulation
|
|
|
|
*******************************************************************************
|
|
|
|
void fmpz_mod_poly_set(fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2)
|
|
|
|
Sets the polynomial \code{poly1} to the value of \code{poly2}.
|
|
|
|
void fmpz_mod_poly_swap(fmpz_mod_poly_t poly1, fmpz_mod_poly_t poly2)
|
|
|
|
Swaps the two polynomials. This is done efficiently by swapping
|
|
pointers rather than individual coefficients.
|
|
|
|
void fmpz_mod_poly_zero(fmpz_mod_poly_t poly)
|
|
|
|
Sets \code{poly} to the zero polynomial.
|
|
|
|
void fmpz_mod_poly_zero_coeffs(fmpz_mod_poly_t poly, slong i, slong j)
|
|
|
|
Sets the coefficients of $X^k$ for $k \in [i, j)$ in the polynomial
|
|
to zero.
|
|
|
|
void fmpz_mod_poly_reverse(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly, slong n)
|
|
|
|
This function considers the polynomial \code{poly} to be of length $n$,
|
|
notionally truncating and zero padding if required, and reverses
|
|
the result. Since the function normalises its result \code{res} may be
|
|
of length less than $n$.
|
|
|
|
*******************************************************************************
|
|
|
|
Conversion
|
|
|
|
*******************************************************************************
|
|
|
|
void fmpz_mod_poly_set_ui(fmpz_mod_poly_t f, ulong c)
|
|
|
|
Sets the polynomial $f$ to the constant $c$ reduced modulo $p$.
|
|
|
|
void fmpz_mod_poly_set_fmpz(fmpz_mod_poly_t f, const fmpz_t c)
|
|
|
|
Sets the polynomial $f$ to the constant $c$ reduced modulo $p$.
|
|
|
|
void fmpz_mod_poly_set_fmpz_poly(fmpz_mod_poly_t f, const fmpz_poly_t g)
|
|
|
|
Sets $f$ to $g$ reduced modulo $p$, where $p$ is the modulus that
|
|
is part of the data structure of $f$.
|
|
|
|
void fmpz_mod_poly_get_fmpz_poly(fmpz_poly_t f, const fmpz_mod_poly_t g)
|
|
|
|
Sets $f$ to $g$. This is done simply by lifting the coefficients
|
|
of $g$ taking representatives $[0, p) \subset \mathbf{Z}$.
|
|
|
|
*******************************************************************************
|
|
|
|
Comparison
|
|
|
|
*******************************************************************************
|
|
|
|
int fmpz_mod_poly_equal(const fmpz_mod_poly_t poly1,
|
|
const fmpz_mod_poly_t poly2)
|
|
|
|
Returns non-zero if the two polynomials are equal.
|
|
|
|
int fmpz_mod_poly_is_zero(const fmpz_mod_poly_t poly)
|
|
|
|
Returns non-zero if the polynomial is zero.
|
|
|
|
*******************************************************************************
|
|
|
|
Getting and setting coefficients
|
|
|
|
*******************************************************************************
|
|
|
|
void
|
|
fmpz_mod_poly_set_coeff_fmpz(fmpz_mod_poly_t poly, slong n, const fmpz_t x)
|
|
|
|
Sets the coefficient of $X^n$ in the polynomial to $x$,
|
|
assuming $n \geq 0$.
|
|
|
|
void fmpz_mod_poly_set_coeff_ui(fmpz_mod_poly_t poly, slong n, ulong x)
|
|
|
|
Sets the coefficient of $X^n$ in the polynomial to $x$,
|
|
assuming $n \geq 0$.
|
|
|
|
void
|
|
fmpz_mod_poly_get_coeff_fmpz(fmpz_t x, const fmpz_mod_poly_t poly, slong n)
|
|
|
|
Sets $x$ to the coefficient of $X^n$ in the polynomial,
|
|
assumng $n \geq 0$.
|
|
|
|
void
|
|
fmpz_mod_poly_set_coeff_mpz(fmpz_mod_poly_t poly, slong n, const mpz_t x)
|
|
|
|
Sets the coefficient of $X^n$ in the polynomial to $x$,
|
|
assuming $n \geq 0$.
|
|
|
|
void
|
|
fmpz_mod_poly_get_coeff_mpz(mpz_t x, const fmpz_mod_poly_t poly, slong n)
|
|
|
|
Sets $x$ to the coefficient of $X^n$ in the polynomial,
|
|
assumng $n \geq 0$.
|
|
|
|
*******************************************************************************
|
|
|
|
Shifting
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_shift_left(fmpz * res,
|
|
const fmpz * poly, slong len, slong n)
|
|
|
|
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 fmpz_mod_poly_shift_left(fmpz_mod_poly_t f,
|
|
const fmpz_mod_poly_t g, slong n)
|
|
|
|
Sets \code{res} to \code{poly} shifted left by $n$ coeffs. Zero
|
|
coefficients are inserted.
|
|
|
|
void _fmpz_mod_poly_shift_right(fmpz * res,
|
|
const fmpz * poly, slong len, slong n)
|
|
|
|
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 fmpz_mod_poly_shift_right(fmpz_mod_poly_t f,
|
|
const fmpz_mod_poly_t g, slong n)
|
|
|
|
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.
|
|
|
|
*******************************************************************************
|
|
|
|
Addition and subtraction
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_add(fmpz *res, const fmpz *poly1, slong len1,
|
|
const fmpz *poly2, slong len2,
|
|
const fmpz_t p)
|
|
|
|
Sets \code{res} to the sum of \code{(poly1, len1)} and
|
|
\code{(poly2, len2)}. It is assumed that \code{res} has
|
|
sufficient space for the longer of the two polynomials.
|
|
|
|
void fmpz_mod_poly_add(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly1,
|
|
const fmpz_mod_poly_t poly2)
|
|
|
|
Sets \code{res} to the sum of \code{poly1} and \code{poly2}.
|
|
|
|
void _fmpz_mod_poly_sub(fmpz *res, const fmpz *poly1, slong len1,
|
|
const fmpz *poly2, slong len2,
|
|
const fmpz_t p)
|
|
|
|
Sets \code{res} to \code{(poly1, len1)} minus \code{(poly2, len2)}. It
|
|
is assumed that \code{res} has sufficient space for the longer of the
|
|
two polynomials.
|
|
|
|
void fmpz_mod_poly_sub(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly1,
|
|
const fmpz_mod_poly_t poly2)
|
|
|
|
Sets \code{res} to \code{poly1} minus \code{poly2}.
|
|
|
|
void _fmpz_mod_poly_neg(fmpz *res, const fmpz *poly, slong len, const fmpz_t p)
|
|
|
|
Sets \code{(res, len)} to the negative of \code{(poly, len)}
|
|
modulo $p$.
|
|
|
|
void fmpz_mod_poly_neg(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly)
|
|
|
|
Sets \code{res} to the negative of \code{poly} modulo $p$.
|
|
|
|
*******************************************************************************
|
|
|
|
Scalar multiplication
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_scalar_mul_fmpz(fmpz *res, const fmpz *poly, slong len,
|
|
const fmpz_t x, const fmpz_t p)
|
|
|
|
Sets \code{(res, len}) to \code{(poly, len)} multiplied by $x$,
|
|
reduced modulo $p$.
|
|
|
|
void fmpz_mod_poly_scalar_mul_fmpz(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly, const fmpz_t x)
|
|
|
|
Sets \code{res} to \code{poly} multiplied by $x$.
|
|
|
|
*******************************************************************************
|
|
|
|
Multiplication
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_mul(fmpz *res, const fmpz *poly1, slong len1,
|
|
const fmpz *poly2, slong len2,
|
|
const fmpz_t p)
|
|
|
|
Sets \code{(res, len1 + len2 - 1)} to the product of \code{(poly1, len1)}
|
|
and \code{(poly2, len2)}. Assumes \code{len1 >= len2 > 0}. Allows
|
|
zero-padding of the two input polynomials.
|
|
|
|
void fmpz_mod_poly_mul(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly1,
|
|
const fmpz_mod_poly_t poly2)
|
|
|
|
Sets \code{res} to the product of \code{poly1} and \code{poly2}.
|
|
|
|
void _fmpz_mod_poly_mullow(fmpz *res, const fmpz *poly1, slong len1,
|
|
const fmpz *poly2, slong len2,
|
|
const fmpz_t p, slong n)
|
|
|
|
Sets \code{(res, n)} to the lowest $n$ coefficients of the product of
|
|
\code{(poly1, len1)} and \code{(poly2, len2)}.
|
|
|
|
Assumes \code{len1 >= len2 > 0} and \code{0 < n <= len1 + len2 - 1}.
|
|
Allows for zero-padding in the inputs. Does not support aliasing between
|
|
the inputs and the output.
|
|
|
|
void fmpz_mod_poly_mullow(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong n)
|
|
|
|
Sets \code{res} to the lowest $n$ coefficients of the product of
|
|
\code{poly1} and \code{poly2}.
|
|
|
|
void _fmpz_mod_poly_sqr(fmpz *res, const fmpz *poly, slong len, const fmpz_t p)
|
|
|
|
Sets \code{res} to the square of \code{poly}.
|
|
|
|
void fmpz_mod_poly_sqr(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly)
|
|
|
|
Computes \code{res} as the square of \code{poly}.
|
|
|
|
void _fmpz_mod_poly_mulmod(fmpz * res, const fmpz * poly1, slong len1,
|
|
const fmpz * poly2, slong len2, const fmpz * f,
|
|
slong lenf, const fmpz_t p)
|
|
|
|
Sets \code{res, len1 + len2 - 1} 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{_fmpz_mod_poly_mul} instead.
|
|
|
|
Aliasing of \code{f} and \code{res} is not permitted.
|
|
|
|
void fmpz_mod_poly_mulmod(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1,
|
|
const fmpz_mod_poly_t poly2, const fmpz_mod_poly_t f)
|
|
|
|
Sets \code{res} to the remainder of the product of \code{poly1} and
|
|
\code{poly2} upon polynomial division by \code{f}.
|
|
|
|
void _fmpz_mod_poly_mulmod_preinv(fmpz * res, const fmpz * poly1, slong len1,
|
|
const fmpz * poly2, slong len2, const fmpz * f, slong lenf,
|
|
const fmpz* finv, slong lenfinv, const fmpz_t p)
|
|
|
|
Sets \code{res, len1 + len2 - 1} 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.
|
|
It is required that \code{len1 < lenf} and \code{len2 < lenf}.
|
|
Otherwise, simply use \code{_fmpz_mod_poly_mul} instead.
|
|
|
|
Aliasing of \code{f} or \code{finv} and \code{res} is not permitted.
|
|
|
|
void fmpz_mod_poly_mulmod_preinv(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2,
|
|
const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv)
|
|
|
|
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}. It is required that \code{poly1} and
|
|
\code{poly2} are reduced modulo \code{f}.
|
|
|
|
*******************************************************************************
|
|
|
|
Powering
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_pow(fmpz *rop, const fmpz *op, slong len, ulong e,
|
|
const fmpz_t p)
|
|
|
|
Sets \code{res = poly^e}, assuming that $e > 1$ and \code{elen > 0},
|
|
and that \code{res} has space for \code{e*(len - 1) + 1} coefficients.
|
|
Does not support aliasing.
|
|
|
|
void fmpz_mod_poly_pow(fmpz_mod_poly_t rop, const fmpz_mod_poly_t op, ulong e)
|
|
|
|
Computes \code{res = poly^e}. If $e$ is zero, returns one,
|
|
so that in particular \code{0^0 = 1}.
|
|
|
|
void _fmpz_mod_poly_pow_trunc(fmpz * res, const fmpz * poly,
|
|
ulong e, slong trunc, const fmpz_t p)
|
|
|
|
Sets \code{res} to the low \code{trunc} coefficients of \code{poly}
|
|
(assumed to be zero padded if necessary to length \code{trunc}) to
|
|
the power \code{e}. This is equivalent to doing a powering followed
|
|
by a truncation. We require that \code{res} has enough space for
|
|
\code{trunc} coefficients, that \code{trunc > 0} and that
|
|
\code{e > 1}. Aliasing is not permitted.
|
|
|
|
void fmpz_mod_poly_pow_trunc(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly, ulong e, slong trunc)
|
|
|
|
Sets \code{res} to the low \code{trunc} coefficients of \code{poly}
|
|
to the power \code{e}. This is equivalent to doing a powering
|
|
followed by a truncation.
|
|
|
|
void _fmpz_mod_poly_pow_trunc_binexp(fmpz * res, const fmpz * poly,
|
|
ulong e, slong trunc, const fmpz_t p)
|
|
|
|
Sets \code{res} to the low \code{trunc} coefficients of \code{poly}
|
|
(assumed to be zero padded if necessary to length \code{trunc}) to
|
|
the power \code{e}. This is equivalent to doing a powering followed
|
|
by a truncation. We require that \code{res} has enough space for
|
|
\code{trunc} coefficients, that \code{trunc > 0} and that
|
|
\code{e > 1}. Aliasing is not permitted. Uses the binary
|
|
exponentiation method.
|
|
|
|
void fmpz_mod_poly_pow_trunc_binexp(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly, ulong e, slong trunc)
|
|
|
|
Sets \code{res} to the low \code{trunc} coefficients of \code{poly}
|
|
to the power \code{e}. This is equivalent to doing a powering
|
|
followed by a truncation. Uses the binary exponentiation method.
|
|
|
|
void _fmpz_mod_poly_powmod_ui_binexp(fmpz * res, const fmpz * poly,
|
|
ulong e, const fmpz * f,
|
|
slong lenf, const fmpz_t p)
|
|
|
|
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 fmpz_mod_poly_powmod_ui_binexp(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly, ulong e,
|
|
const fmpz_mod_poly_t f)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e}
|
|
modulo \code{f}, using binary exponentiation. We require \code{e >= 0}.
|
|
|
|
void
|
|
_fmpz_mod_poly_powmod_ui_binexp_preinv(fmpz * res, const fmpz * poly,
|
|
ulong e, const fmpz * f, slong lenf,
|
|
const fmpz * finv, slong lenfinv, const fmpz_t p)
|
|
|
|
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
|
|
fmpz_mod_poly_powmod_ui_binexp_preinv(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly, ulong e,
|
|
const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv)
|
|
|
|
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 _fmpz_mod_poly_powmod_fmpz_binexp(fmpz * res, const fmpz * poly,
|
|
const fmpz_t e, const fmpz * f,
|
|
slong lenf, const fmpz_t p)
|
|
|
|
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 fmpz_mod_poly_powmod_fmpz_binexp(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly, const fmpz_t e,
|
|
const fmpz_mod_poly_t f)
|
|
|
|
Sets \code{res} to \code{poly} raised to the power \code{e}
|
|
modulo \code{f}, using binary exponentiation. We require \code{e >= 0}.
|
|
|
|
void _fmpz_mod_poly_powmod_fmpz_binexp_preinv(fmpz * res, const fmpz * poly,
|
|
const fmpz_t e, const fmpz * f, slong lenf,
|
|
const fmpz* finv, slong lenfinv,
|
|
const fmpz_t p)
|
|
|
|
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 fmpz_mod_poly_powmod_fmpz_binexp_preinv(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly, const fmpz_t e,
|
|
const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv)
|
|
|
|
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
|
|
_fmpz_mod_poly_powmod_x_fmpz_preinv(fmpz * res, const fmpz_t e, const fmpz * f,
|
|
slong lenf, const fmpz* finv, slong lenfinv,
|
|
const fmpz_t p)
|
|
|
|
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
|
|
fmpz_mod_poly_powmod_x_fmpz_preinv(fmpz_mod_poly_t res, const fmpz_t e,
|
|
const fmpz_mod_poly_t f, const fmpz_mod_poly_t finv)
|
|
|
|
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}.
|
|
|
|
*******************************************************************************
|
|
|
|
Division
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_divrem_basecase(fmpz * Q, fmpz * R,
|
|
const fmpz * A, slong lenA, const fmpz * B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
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
|
|
modulo $p$, and that \code{invB} is the 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 fmpz_mod_poly_divrem_basecase(fmpz_mod_poly_t Q, fmpz_mod_poly_t R,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
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
|
|
modulo $p$.
|
|
|
|
void _fmpz_mod_poly_divrem_newton_n_preinv (fmpz* Q, fmpz* R, const fmpz* A,
|
|
slong lenA, const fmpz* B, slong lenB,
|
|
const fmpz* Binv, slong lenBinv, const fmpz_t mod)
|
|
|
|
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_n_preinv()} and then multiply out and compute
|
|
the remainder.
|
|
|
|
void fmpz_mod_poly_divrem_newton_n_preinv(fmpz_mod_poly_t Q, fmpz_mod_poly_t R,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B,
|
|
const fmpz_mod_poly_t Binv)
|
|
|
|
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_n()} and then multiply out
|
|
and compute the remainder.
|
|
|
|
void _fmpz_mod_poly_div_basecase(fmpz * Q, fmpz * R,
|
|
const fmpz * A, slong lenA, const fmpz * B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
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)}. 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 modulo $p$.
|
|
|
|
void fmpz_mod_poly_div_basecase(fmpz_mod_poly_t Q,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Notationally, computes $Q$, $R$ such that $A = B Q + R$ with
|
|
$0 \leq \len(R) < \len(B)$ assuming that the leading term
|
|
of $B$ is a unit.
|
|
|
|
void _fmpz_mod_poly_div_newton_n_preinv (fmpz* Q, const fmpz* A, slong lenA,
|
|
const fmpz* B, slong lenB, const fmpz* Binv,
|
|
slong lenBinv, const fmpz_t mod)
|
|
|
|
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 fmpz_mod_poly_div_newton_n_preinv(fmpz_mod_poly_t Q,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B,
|
|
const fmpz_mod_poly_t Binv)
|
|
|
|
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.
|
|
|
|
ulong fmpz_mod_poly_remove(fmpz_mod_poly_t f, const fmpz_mod_poly_t g)
|
|
|
|
Removes the highest possible power of \code{g} from \code{f} and
|
|
returns the exponent.
|
|
|
|
void _fmpz_mod_poly_rem_basecase(fmpz * R,
|
|
const fmpz * A, slong lenA, const fmpz * B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
Notationally, computes $Q$, $R$ such that $A = B Q + R$ with
|
|
$0 \leq \len(R) < \len(B)$ but only sets \code{(R, lenA)}.
|
|
|
|
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 modulo $p$.
|
|
|
|
void fmpz_mod_poly_rem_basecase(fmpz_mod_poly_t R,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Notationally, computes $Q$, $R$ such that $A = B Q + R$ with
|
|
$0 \leq \len(R) < \len(B)$ assuming that the leading term
|
|
of $B$ is a unit.
|
|
|
|
void _fmpz_mod_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W,
|
|
const fmpz * A, const fmpz * B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
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
|
|
modulo $p$, 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 _fmpz_mod_poly_divrem_divconquer(fmpz * Q, fmpz * R,
|
|
const fmpz * A, slong lenA, const fmpz * B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
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
|
|
modulo $p$, 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 fmpz_mod_poly_divrem_divconquer(fmpz_mod_poly_t Q, fmpz_mod_poly_t R,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
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 modulo $p$.
|
|
|
|
void _fmpz_mod_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA,
|
|
const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p)
|
|
|
|
Computes \code{(Q, lenA - lenB + 1)}, \code{(R, lenA)} such that
|
|
$A = B Q + R$ and $0 \leq \len(R) < \len(B)$.
|
|
|
|
Assumes that $B$ is non-zero, that the leading coefficient
|
|
of $B$ is invertible modulo $p$ 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 fmpz_mod_poly_divrem(fmpz_mod_poly_t Q, fmpz_mod_poly_t R,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
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 modulo $p$.
|
|
|
|
void fmpz_mod_poly_divrem_f(fmpz_t f, fmpz_mod_poly_t Q, fmpz_mod_poly_t R,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Either finds a non-trivial factor~$f$ of the modulus~$p$, or computes
|
|
$Q$, $R$ such that $A = B Q + R$ and $0 \leq \len(R) < \len(B)$.
|
|
|
|
If the leading coefficient of $B$ is invertible in $\mathbf{Z}/(p)$,
|
|
the division with remainder operation is carried out, $Q$ and $R$ are
|
|
computed correctly, and $f$ is set to $1$. Otherwise, $f$ is set to
|
|
a non-trivial factor of $p$ and $Q$ and $R$ are not touched.
|
|
|
|
Assumes that $B$ is non-zero.
|
|
|
|
void _fmpz_mod_poly_rem(fmpz *R,
|
|
const fmpz *A, slong lenA, const fmpz *B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
Notationally, computes \code{(Q, lenA - lenB + 1)}, \code{(R, lenA)}
|
|
such that $A = B Q + R$ and $0 \leq \len(R) < \len(B)$, returning
|
|
only the remainder part.
|
|
|
|
Assumes that $B$ is non-zero, that the leading coefficient
|
|
of $B$ is invertible modulo $p$ 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 fmpz_mod_poly_rem(fmpz_mod_poly_t R,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Notationally, computes $Q$, $R$ such that $A = B Q + R$
|
|
and $0 \leq \len(R) < \len(B)$, returning only the remainder
|
|
part.
|
|
|
|
Assumes that $B$ is non-zero and that the leading coefficient
|
|
of $B$ is invertible modulo $p$.
|
|
|
|
*******************************************************************************
|
|
|
|
Power series inversion
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong n,
|
|
const fmpz_t cinv, const fmpz_t p)
|
|
|
|
Sets \code{(Qinv, n)} to the inverse of \code{(Q, n)} modulo $x^n$,
|
|
where $n \geq 1$, assuming that the bottom coefficient of $Q$ is
|
|
invertible modulo $p$ and that its inverse is \code{cinv}.
|
|
|
|
void fmpz_mod_poly_inv_series_newton(fmpz_mod_poly_t Qinv,
|
|
const fmpz_mod_poly_t Q, slong n)
|
|
|
|
Sets \code{Qinv} to the inverse of \code{Q} modulo $x^n$,
|
|
where $n \geq 1$, assuming that the bottom coefficient of
|
|
$Q$ is a unit.
|
|
|
|
*******************************************************************************
|
|
|
|
Greatest common divisor
|
|
|
|
*******************************************************************************
|
|
|
|
void fmpz_mod_poly_make_monic(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly)
|
|
|
|
If \code{poly} is non-zero, sets \code{res} to \code{poly} divided
|
|
by its leading coefficient. This assumes that the leading coefficient
|
|
of \code{poly} is invertible modulo $p$.
|
|
|
|
Otherwise, if \code{poly} is zero, sets \code{res} to zero.
|
|
|
|
slong _fmpz_mod_poly_gcd_euclidean(fmpz *G, const fmpz *A, slong lenA,
|
|
const fmpz *B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
Sets $G$ to the greatest common divisor of $(A, \len(A))$
|
|
and $(B, \len(B))$ and returns its length.
|
|
|
|
Assumes that $\len(A) \geq \len(B) > 0$ and that the vector $G$ has
|
|
space for sufficiently many coefficients.
|
|
|
|
Assumes that \code{invB} is the inverse of the leading coefficients
|
|
of $B$ modulo the prime number $p$.
|
|
|
|
void fmpz_mod_poly_gcd_euclidean(fmpz_mod_poly_t G,
|
|
const fmpz_mod_poly_t A,
|
|
const fmpz_mod_poly_t B)
|
|
|
|
Sets $G$ to the greatest common divisor of $A$ and $B$.
|
|
|
|
The algorithm used to compute $G$ is the classical Euclidean
|
|
algorithm.
|
|
|
|
In general, the greatest common divisor is defined in the polynomial
|
|
ring $(\mathbf{Z}/(p \mathbf{Z}))[X]$ if and only if $p$ is a prime
|
|
number. Thus, this function assumes that $p$ is prime.
|
|
|
|
slong _fmpz_mod_poly_gcd(fmpz *G, const fmpz *A, slong lenA,
|
|
const fmpz *B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
Sets $G$ to the greatest common divisor of $(A, \len(A))$
|
|
and $(B, \len(B))$ and returns its length.
|
|
|
|
Assumes that $\len(A) \geq \len(B) > 0$ and that the vector $G$ has
|
|
space for sufficiently many coefficients.
|
|
|
|
Assumes that \code{invB} is the inverse of the leading coefficients
|
|
of $B$ modulo the prime number $p$.
|
|
|
|
void fmpz_mod_poly_gcd(fmpz_mod_poly_t G,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Sets $G$ to the greatest common divisor of $A$ and $B$.
|
|
|
|
In general, the greatest common divisor is defined in the polynomial
|
|
ring $(\mathbf{Z}/(p \mathbf{Z}))[X]$ if and only if $p$ is a prime
|
|
number. Thus, this function assumes that $p$ is prime.
|
|
|
|
slong _fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz *G,
|
|
const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t p)
|
|
|
|
Either sets $f = 1$ and $G$ to the greatest common divisor
|
|
of $(A, \len(A))$ and $(B, \len(B))$ and returns its length,
|
|
or sets $f \in (1,p)$ to a non-trivial factor of $p$ and
|
|
leaves the contents of the vector $(G, lenB)$ undefined.
|
|
|
|
Assumes that $\len(A) \geq \len(B) > 0$ and that the vector $G$ has
|
|
space for sufficiently many coefficients.
|
|
|
|
Does not support aliasing of any of the input arguments
|
|
with any of the output argument.
|
|
|
|
void fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Either sets $f = 1$ and $G$ to the greatest common divisor
|
|
of $A$ and $B$, or $ \in (1,p)$ to a non-trivial factor of $p$.
|
|
|
|
In general, the greatest common divisor is defined in the polynomial
|
|
ring $(\mathbf{Z}/(p \mathbf{Z}))[X]$ if and only if $p$ is a prime
|
|
number.
|
|
|
|
slong _fmpz_mod_poly_gcd_f(fmpz_t f, fmpz *G, const fmpz *A, slong lenA,
|
|
const fmpz *B, slong lenB, const fmpz_t p)
|
|
|
|
Either sets $f = 1$ and $G$ to the greatest common divisor
|
|
of $(A, \len(A))$ and $(B, \len(B))$ and returns its length,
|
|
or sets $f \in (1,p)$ to a non-trivial factor of $p$ and
|
|
leaves the contents of the vector $(G, lenB)$ undefined.
|
|
|
|
Assumes that $\len(A) \geq \len(B) > 0$ and that the vector $G$ has
|
|
space for sufficiently many coefficients.
|
|
|
|
Does not support aliasing of any of the input arguments
|
|
with any of the output argument.
|
|
|
|
void fmpz_mod_poly_gcd_f(fmpz_t f, fmpz_mod_poly_t G,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Either sets $f = 1$ and $G$ to the greatest common divisor
|
|
of $A$ and $B$, or $ \in (1,p)$ to a non-trivial factor of $p$.
|
|
|
|
In general, the greatest common divisor is defined in the polynomial
|
|
ring $(\mathbf{Z}/(p \mathbf{Z}))[X]$ if and only if $p$ is a prime
|
|
number.
|
|
|
|
slong _fmpz_mod_poly_xgcd_euclidean(fmpz *G, fmpz *S, fmpz *T,
|
|
const fmpz *A, slong lenA,
|
|
const fmpz *B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
Computes the GCD of $A$ and $B$ together with cofactors $S$ and $T$
|
|
such that $S A + T B = G$. Returns the length of $G$.
|
|
|
|
Assumes that $\len(A) \geq \len(B) \geq 1$ and
|
|
$(\len(A),\len(B)) \neq (1,1)$.
|
|
|
|
No attempt is made to make the GCD monic.
|
|
|
|
Requires that $G$ have space for $\len(B)$ coefficients. Writes
|
|
$\len(B)-1$ and $\len(A)-1$ coefficients to $S$ and $T$, respectively.
|
|
Note that, in fact, $\len(S) \leq \max(\len(B) - \len(G), 1)$ and
|
|
$\len(T) \leq \max(\len(A) - \len(G), 1)$.
|
|
|
|
No aliasing of input and output operands is permitted.
|
|
|
|
void fmpz_mod_poly_xgcd_euclidean(fmpz_mod_poly_t G,
|
|
fmpz_mod_poly_t S, fmpz_mod_poly_t T,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Computes the GCD of $A$ and $B$. 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.
|
|
|
|
Polynomials \code{S} and \code{T} are computed such that
|
|
\code{S*A + T*B = G}. The length of \code{S} will be at most
|
|
\code{lenB} and the length of \code{T} will be at most \code{lenA}.
|
|
|
|
slong _fmpz_mod_poly_xgcd(fmpz *G, fmpz *S, fmpz *T,
|
|
const fmpz *A, slong lenA,
|
|
const fmpz *B, slong lenB,
|
|
const fmpz_t invB, const fmpz_t p)
|
|
|
|
Computes the GCD of $A$ and $B$ together with cofactors $S$ and $T$
|
|
such that $S A + T B = G$. Returns the length of $G$.
|
|
|
|
Assumes that $\len(A) \geq \len(B) \geq 1$ and
|
|
$(\len(A),\len(B)) \neq (1,1)$.
|
|
|
|
No attempt is made to make the GCD monic.
|
|
|
|
Requires that $G$ have space for $\len(B)$ coefficients. Writes
|
|
$\len(B)-1$ and $\len(A)-1$ coefficients to $S$ and $T$, respectively.
|
|
Note that, in fact, $\len(S) \leq \max(\len(B) - \len(G), 1)$ and
|
|
$\len(T) \leq \max(\len(A) - \len(G), 1)$.
|
|
|
|
No aliasing of input and output operands is permitted.
|
|
|
|
void fmpz_mod_poly_xgcd(fmpz_mod_poly_t G,
|
|
fmpz_mod_poly_t S, fmpz_mod_poly_t T,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Computes the GCD of $A$ and $B$. 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.
|
|
|
|
Polynomials \code{S} and \code{T} are computed such that
|
|
\code{S*A + T*B = G}. The length of \code{S} will be at most
|
|
\code{lenB} and the length of \code{T} will be at most \code{lenA}.
|
|
|
|
slong _fmpz_mod_poly_gcdinv(fmpz *G, fmpz *S,
|
|
const fmpz *A, slong lenA, const fmpz *B, slong lenB,
|
|
const fmpz_t p)
|
|
|
|
Computes \code{(G, lenA)}, \code{(S, lenB-1)} such that
|
|
$G \cong S A \pmod{B}$, returning the actual length of $G$.
|
|
|
|
Assumes that $0 < \len(A) < \len(B)$.
|
|
|
|
void fmpz_mod_poly_gcdinv(fmpz_mod_poly_t G, fmpz_mod_poly_t S,
|
|
const fmpz_mod_poly_t A, const fmpz_mod_poly_t B)
|
|
|
|
Computes polynomials $G$ and $S$, both reduced modulo~$B$,
|
|
such that $G \cong S A \pmod{B}$, where $B$ is assumed to
|
|
have $\len(B) \geq 2$.
|
|
|
|
In the case that $A = 0 \pmod{B}$, returns $G = S = 0$.
|
|
|
|
int _fmpz_mod_poly_invmod(fmpz *A,
|
|
const fmpz *B, slong lenB,
|
|
const fmpz *P, slong lenP, const fmpz_t p)
|
|
|
|
Attempts to set \code{(A, lenP-1)} to the inverse of \code{(B, lenB)}
|
|
modulo the polynomial \code{(P, lenP)}. Returns $1$ if \code{(B, lenB)}
|
|
is invertible and $0$ otherwise.
|
|
|
|
Assumes that $0 < \len(B) < \len(P)$, and hence also $\len(P) \geq 2$,
|
|
but supports zero-padding in \code{(B, lenB)}.
|
|
|
|
Does not support aliasing.
|
|
|
|
Assumes that $p$ is a prime number.
|
|
|
|
int fmpz_mod_poly_invmod(fmpz_mod_poly_t A,
|
|
const fmpz_mod_poly_t B, const fmpz_mod_poly_t P)
|
|
|
|
Attempts to set $A$ to the inverse of $B$ modulo $P$ in the polynomial
|
|
ring $(\mathbf{Z}/p\mathbf{Z})[X]$, where we assume that $p$ is a prime
|
|
number.
|
|
|
|
If $\deg(P) < 2$, raises an exception.
|
|
|
|
If the greatest common divisor of $B$ and $P$ is~$1$, returns~$1$ and
|
|
sets $A$ to the inverse of $B$. Otherwise, returns~$0$ and the value
|
|
of $A$ on exit is undefined.
|
|
|
|
*******************************************************************************
|
|
|
|
Derivative
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_derivative(fmpz *res, const fmpz *poly, slong len,
|
|
const fmpz_t p)
|
|
|
|
Sets \code{(res, 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{res} and \code{poly}.
|
|
|
|
void fmpz_mod_poly_derivative(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly)
|
|
|
|
Sets \code{res} to the derivative of \code{poly}.
|
|
|
|
*******************************************************************************
|
|
|
|
Evaluation
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz *poly, slong len,
|
|
const fmpz_t a, const fmpz_t p)
|
|
|
|
Evaluates the polynomial \code{(poly, len)} at the integer $a$ and sets
|
|
\code{res} to the result. Aliasing between \code{res} and $a$ or any
|
|
of the coefficients of \code{poly} is not supported.
|
|
|
|
void fmpz_mod_poly_evaluate_fmpz(fmpz_t res,
|
|
const fmpz_mod_poly_t poly, const fmpz_t a)
|
|
|
|
Evaluates the polynomial \code{poly} at the integer $a$ and sets
|
|
\code{res} to the result.
|
|
|
|
As expected, aliasing between \code{res} and $a$ is supported. However,
|
|
\code{res} may not be aliased with a coefficient of \code{poly}.
|
|
|
|
*******************************************************************************
|
|
|
|
Multipoint evaluation
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz * coeffs,
|
|
slong len, const fmpz * xs, slong n, const fmpz_t mod)
|
|
|
|
Evaluates (\code{coeffs}, \code{len}) at the \code{n} values
|
|
given in the vector \code{xs}, writing the output values
|
|
to \code{ys}. The values in \code{xs} should be reduced
|
|
modulo the modulus.
|
|
|
|
Uses Horner's method iteratively.
|
|
|
|
void fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys,
|
|
const fmpz_mod_poly_t poly, const fmpz * xs, slong n)
|
|
|
|
Evaluates \code{poly} at the \code{n} values given in the vector
|
|
\code{xs}, writing the output values to \code{ys}. The values in
|
|
\code{xs} should be reduced modulo the modulus.
|
|
|
|
Uses Horner's method iteratively.
|
|
|
|
void _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp(fmpz * vs,
|
|
const fmpz * poly, slong plen, fmpz_poly_struct * const * tree,
|
|
slong len, const fmpz_t mod)
|
|
Evaluates (\code{poly}, \code{plen}) at the \code{len} values given
|
|
by the precomputed subproduct tree \code{tree}.
|
|
|
|
void _fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys,
|
|
const fmpz * poly, slong plen, const fmpz * xs, slong n, const fmpz_t mod)
|
|
|
|
Evaluates (\code{coeffs}, \code{len}) at the \code{n} values
|
|
given in the vector \code{xs}, writing the output values
|
|
to \code{ys}. The values in \code{xs} should be reduced
|
|
modulo the modulus.
|
|
|
|
Uses fast multipoint evaluation, building a temporary subproduct tree.
|
|
|
|
void fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys,
|
|
const fmpz_mod_poly_t poly, const fmpz * xs, slong n)
|
|
|
|
Evaluates \code{poly} at the \code{n} values given in the vector
|
|
\code{xs}, writing the output values to \code{ys}. The values in
|
|
\code{xs} should be reduced modulo the modulus.
|
|
|
|
Uses fast multipoint evaluation, building a temporary subproduct tree.
|
|
|
|
void _fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz * coeffs,
|
|
slong len, const fmpz * xs, slong n, const fmpz_t mod)
|
|
|
|
Evaluates (\code{coeffs}, \code{len}) at the \code{n} values
|
|
given in the vector \code{xs}, writing the output values
|
|
to \code{ys}. The values in \code{xs} should be reduced
|
|
modulo the modulus.
|
|
|
|
void fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys,
|
|
const fmpz_mod_poly_t poly, const fmpz * xs, slong n)
|
|
|
|
Evaluates \code{poly} at the \code{n} values given in the vector
|
|
\code{xs}, writing the output values to \code{ys}. The values in
|
|
\code{xs} should be reduced modulo the modulus.
|
|
|
|
*******************************************************************************
|
|
|
|
Composition
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_compose_horner(fmpz *res, const fmpz *poly1, slong len1,
|
|
const fmpz *poly2, slong len2,
|
|
const fmpz_t p)
|
|
|
|
Sets \code{res} to the composition of \code{(poly1, len1)} and
|
|
\code{(poly2, len2)} using Horner's algorithm.
|
|
|
|
Assumes that \code{res} has space for \code{(len1-1)*(len2-1) + 1}
|
|
coefficients, although in $\mathbf{Z}_p[X]$ this might not actually
|
|
be the length of the resulting polynomial when $p$ is not a prime.
|
|
|
|
Assumes that \code{poly1} and \code{poly2} are non-zero polynomials.
|
|
Does not support aliasing between any of the inputs and the output.
|
|
|
|
void fmpz_mod_poly_compose_horner(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly1,
|
|
const fmpz_mod_poly_t poly2)
|
|
|
|
Sets \code{res} to the composition of \code{poly1} and \code{poly2}
|
|
using Horner's algorithm.
|
|
|
|
To be precise about the order of composition, denoting \code{res},
|
|
\code{poly1}, and \code{poly2} by $f$, $g$, and $h$, respectively,
|
|
sets $f(t) = g(h(t))$.
|
|
|
|
void _fmpz_mod_poly_compose_divconquer(fmpz *res,
|
|
const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p)
|
|
|
|
Sets \code{res} to the composition of \code{(poly1, len1)} and
|
|
\code{(poly2, len2)} using a divide and conquer algorithm which
|
|
takes out factors of \code{poly2} raised to $2^i$ where possible.
|
|
|
|
Assumes that \code{res} has space for \code{(len1-1)*(len2-1) + 1}
|
|
coefficients, although in $\mathbf{Z}_p[X]$ this might not actually
|
|
be the length of the resulting polynomial when $p$ is not a prime.
|
|
|
|
Assumes that \code{poly1} and \code{poly2} are non-zero polynomials.
|
|
Does not support aliasing between any of the inputs and the output.
|
|
|
|
void fmpz_mod_poly_compose_divconquer(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t poly1,
|
|
const fmpz_mod_poly_t poly2)
|
|
|
|
Sets \code{res} to the composition of \code{poly1} and \code{poly2}
|
|
using a divide and conquer algorithm which takes out factors of
|
|
\code{poly2} raised to $2^i$ where possible.
|
|
|
|
To be precise about the order of composition, denoting \code{res},
|
|
\code{poly1}, and \code{poly2} by $f$, $g$, and $h$, respectively,
|
|
sets $f(t) = g(h(t))$.
|
|
|
|
void _fmpz_mod_poly_compose(fmpz *res, const fmpz *poly1, slong len1,
|
|
const fmpz *poly2, slong len2,
|
|
const fmpz_t p)
|
|
|
|
Sets \code{res} to the composition of \code{(poly1, len1)} and
|
|
\code{(poly2, len2)}.
|
|
|
|
Assumes that \code{res} has space for \code{(len1-1)*(len2-1) + 1}
|
|
coefficients, although in $\mathbf{Z}_p[X]$ this might not actually
|
|
be the length of the resulting polynomial when $p$ is not a prime.
|
|
|
|
Assumes that \code{poly1} and \code{poly2} are non-zero polynomials.
|
|
Does not support aliasing between any of the inputs and the output.
|
|
|
|
void fmpz_mod_poly_compose(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1,
|
|
const fmpz_mod_poly_t poly2)
|
|
|
|
Sets \code{res} to the composition of \code{poly1} and \code{poly2}.
|
|
|
|
To be precise about the order of composition, denoting \code{res},
|
|
\code{poly1}, and \code{poly2} by $f$, $g$, and $h$, respectively,
|
|
sets $f(t) = g(h(t))$.
|
|
|
|
*******************************************************************************
|
|
|
|
Modular composition
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_compose_mod(fmpz * res,
|
|
const fmpz * f, slong lenf, const fmpz * g,
|
|
const fmpz * h, slong lenh, const fmpz_t p)
|
|
|
|
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
|
|
fmpz_mod_poly_compose_mod(fmpz_mod_poly_t res, const fmpz_mod_poly_t f,
|
|
const fmpz_mod_poly_t g, const fmpz_mod_poly_t h)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require that
|
|
$h$ is nonzero.
|
|
|
|
void _fmpz_mod_poly_compose_mod_horner(fmpz * res,
|
|
const fmpz * f, slong lenf, const fmpz * g,
|
|
const fmpz * h, slong lenh, const fmpz_t p)
|
|
|
|
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
|
|
fmpz_mod_poly_compose_mod_horner(fmpz_mod_poly_t res, const fmpz_mod_poly_t f,
|
|
const fmpz_mod_poly_t g, const fmpz_mod_poly_t h)
|
|
|
|
Sets \code{res} to the composition $f(g)$ modulo $h$. We require that
|
|
$h$ is nonzero. The algorithm used is Horner's rule.
|
|
|
|
void
|
|
_fmpz_mod_poly_compose_mod_brent_kung(fmpz * res, const fmpz * f, slong len1,
|
|
const fmpz * g, const fmpz * h, slong len3, const fmpz_t p)
|
|
|
|
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 fmpz_mod_poly_compose_mod_brent_kung(
|
|
fmpz_mod_poly_t res, const fmpz_mod_poly_t f,
|
|
const fmpz_mod_poly_t g, const fmpz_mod_poly_t h)
|
|
|
|
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
|
|
_fmpz_mod_poly_reduce_matrix_mod_poly (fmpz_mat_t A, const fmpz_mat_t B,
|
|
const fmpz_mod_poly_t f)
|
|
|
|
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
|
|
_fmpz_mod_poly_precompute_matrix (fmpz_mat_t A, const fmpz * f,
|
|
const fmpz * g, slong leng, const fmpz * ginv,
|
|
slong lenginv, const fmpz_t p)
|
|
|
|
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
|
|
fmpz_mod_poly_precompute_matrix(fmpz_mat_t A, const fmpz_mod_poly_t f,
|
|
const fmpz_mod_poly_t g, const fmpz_mod_poly_t ginv)
|
|
|
|
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
|
|
_fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz * res,
|
|
const fmpz * f, slong lenf, const fmpz_mat_t A, const fmpz * h,
|
|
slong lenh, const fmpz * hinv, slong lenhinv, const fmpz_t p)
|
|
|
|
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
|
|
fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t f, const fmpz_mat_t A,
|
|
const fmpz_mod_poly_t h, const fmpz_mod_poly_t hinv)
|
|
|
|
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$.
|
|
|
|
void
|
|
_fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz * res, const fmpz * f,
|
|
slong lenf, const fmpz * g, const fmpz * h, slong lenh,
|
|
const fmpz * hinv, slong lenhinv, const fmpz_t p)
|
|
|
|
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
|
|
fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz_mod_poly_t res,
|
|
const fmpz_mod_poly_t f, const fmpz_mod_poly_t g,
|
|
const fmpz_mod_poly_t h, const fmpz_mod_poly_t hinv)
|
|
|
|
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.
|
|
|
|
*******************************************************************************
|
|
|
|
Subproduct trees
|
|
|
|
*******************************************************************************
|
|
|
|
fmpz_poly_struct ** _fmpz_mod_poly_tree_alloc(slong len)
|
|
|
|
Allocates space for a subproduct tree of the given length, having
|
|
linear factors at the lowest level.
|
|
|
|
void _fmpz_mod_poly_tree_free(fmpz_poly_struct ** tree, slong len)
|
|
|
|
Free the allocated space for the subproduct.
|
|
|
|
void _fmpz_mod_poly_tree_build(fmpz_poly_struct ** tree,
|
|
const fmpz * roots, slong len, const fmpz_t mod)
|
|
|
|
Builds a subproduct tree in the preallocated space from
|
|
the \code{len} monic linear factors $(x-r_i)$ where $r_i$ are given by
|
|
\code{roots}. The top level product is not computed.
|
|
|
|
*******************************************************************************
|
|
|
|
Radix conversion
|
|
|
|
The following functions provide the functionality to solve the
|
|
radix conversion problems for polynomials, which is to express
|
|
a polynomial $f(X)$ with respect to a given radix $r(X)$ as
|
|
\begin{equation*}
|
|
f(X) = \sum_{i = 0}^{N} b_i(X) r(X)^i
|
|
\end{equation*}
|
|
where $N = \floor{\deg(f) / \deg(r)}$.
|
|
|
|
The algorithm implemented here is a recursive one, which performs
|
|
Euclidean divisions by powers of $r$ of the form $r^{2^i}$, and it
|
|
has time complexity $\Theta(\deg(f) \log \deg(f))$.
|
|
|
|
It facilitates the repeated use of precomputed data, namely the
|
|
powers of $r$ and their power series inverses. This data is stored
|
|
in objects of type \code{fmpz_mod_poly_radix_t} and it is computed
|
|
using the function \code{fmpz_mod_poly_radix_init()}, which only
|
|
depends on~$r$ and an upper bound on the degree of~$f$.
|
|
|
|
*******************************************************************************
|
|
|
|
void _fmpz_mod_poly_radix_init(fmpz **Rpow, fmpz **Rinv,
|
|
const fmpz *R, slong lenR, slong k,
|
|
const fmpz_t invL, const fmpz_t p)
|
|
|
|
Computes powers of $R$ of the form $R^{2^i}$ and their Newton inverses
|
|
modulo $x^{2^{i} \deg(R)}$ for $i = 0, \dotsc, k-1$.
|
|
|
|
Assumes that the vectors \code{Rpow[i]} and \code{Rinv[i]} have space
|
|
for $2^i \deg(R) + 1$ and $2^i \deg(R)$ coefficients, respectively.
|
|
|
|
Assumes that the polynomial $R$ is non-constant, i.e.\ $\deg(R) \geq 1$.
|
|
|
|
Assumes that the leading coefficient of $R$ is a unit and that the
|
|
argument \code{invL} is the inverse of the coefficient modulo~$p$.
|
|
|
|
The argument~$p$ is the modulus, which in $p$-adic applications is
|
|
typically a prime power, although this is not necessary. Here, we
|
|
only assume that $p \geq 2$.
|
|
|
|
Note that this precomputed data can be used for any $F$ such that
|
|
$\len(F) \leq 2^k \deg(R)$.
|
|
|
|
void fmpz_mod_poly_radix_init(fmpz_mod_poly_radix_t D,
|
|
const fmpz_mod_poly_t R, slong degF)
|
|
|
|
Carries out the precomputation necessary to perform radix conversion
|
|
to radix~$R$ for polynomials~$F$ of degree at most \code{degF}.
|
|
|
|
Assumes that $R$ is non-constant, i.e.\ $\deg(R) \geq 1$,
|
|
and that the leading coefficient is a unit.
|
|
|
|
void _fmpz_mod_poly_radix(fmpz **B, const fmpz *F, fmpz **Rpow, fmpz **Rinv,
|
|
slong degR, slong k, slong i, fmpz *W, const fmpz_t p)
|
|
|
|
This is the main recursive function used by the
|
|
function \code{fmpz_mod_poly_radix()}.
|
|
|
|
Assumes that, for all $i = 0, \dotsc, N$, the vector
|
|
\code{B[i]} has space for $\deg(R)$ coefficients.
|
|
|
|
The variable $k$ denotes the factors of $r$ that have
|
|
previously been counted for the polynomial $F$, which
|
|
is assumed to have length $2^{i+1} \deg(R)$, possibly
|
|
including zero-padding.
|
|
|
|
Assumes that $W$ is a vector providing temporary space
|
|
of length $\len(F) = 2^{i+1} \deg(R)$.
|
|
|
|
The entire computation takes place over $\mathbf{Z} / p \mathbf{Z}$,
|
|
where $p \geq 2$ is a natural number.
|
|
|
|
Thus, the top level call will have $F$ as in the original
|
|
problem, and $k = 0$.
|
|
|
|
void fmpz_mod_poly_radix(fmpz_mod_poly_struct **B, const fmpz_mod_poly_t F,
|
|
const fmpz_mod_poly_radix_t D)
|
|
|
|
Given a polynomial $F$ and the precomputed data $D$ for the radix $R$,
|
|
computes polynomials $B_0, \dotsc, B_N$ of degree less than $\deg(R)$
|
|
such that
|
|
\begin{equation*}
|
|
F = B_0 + B_1 R + \dotsb + B_N R^N,
|
|
\end{equation*}
|
|
where necessarily $N = \floor{\deg(F) / \deg(R)}$.
|
|
|
|
Assumes that $R$ is non-constant, i.e.\ $\deg(R) \geq 1$,
|
|
and that the leading coefficient is a unit.
|
|
|
|
*******************************************************************************
|
|
|
|
Input and output
|
|
|
|
The printing options supported by this module are very similar to
|
|
what can be found in the two related modules \code{fmpz_poly} and
|
|
\code{nmod_poly}.
|
|
|
|
Consider, for example, the polynomial $f(x) = 5x^3 + 2x + 1$ in
|
|
$(\mathbf{Z}/6\mathbf{Z})[x]$. Its simple string representation
|
|
is \code{"4 6 1 2 0 5"}, where the first two numbers denote the
|
|
length of the polynomial and the modulus. The pretty string
|
|
representation is \code{"5*x^3+2*x+1"}.
|
|
|
|
*******************************************************************************
|
|
|
|
int _fmpz_mod_poly_fprint(FILE * file, const fmpz *poly, slong len,
|
|
const fmpz_t p)
|
|
|
|
Prints the polynomial \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 fmpz_mod_poly_fprint(FILE * file, const fmpz_mod_poly_t poly)
|
|
|
|
Prints the polynomial to the stream \code{file}.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
int fmpz_mod_poly_fprint_pretty(FILE * file,
|
|
const fmpz_mod_poly_t poly, const char * x)
|
|
|
|
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 fmpz_mod_poly_print(const fmpz_mod_poly_t poly)
|
|
|
|
Prints the polynomial to \code{stdout}.
|
|
|
|
In case of success, returns a positive value. In case of failure,
|
|
returns a non-positive value.
|
|
|
|
int fmpz_mod_poly_print_pretty(const fmpz_mod_poly_t poly, const char * x)
|
|
|
|
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.
|