FLINT3.7.0-dev
Module · 261 functions

fmpz_mod_poly.h

#include <flint/fmpz_mod_poly.h>

This module implements dense univariate polynomials over Z/nZ\mathbb{Z}/n\mathbb{Z} for an arbitrary modulus n≥1n \ge 1, typically a prime of more than one word. A polynomial is an fmpz_mod_poly_t, an array of fmpz coefficients reduced to [0,n)[0, n); the modulus is not stored in the polynomial but passed to every function as an fmpz_mod_ctx_t (see fmpz_mod). For moduli that fit in a word, nmod_poly is faster, and its documentation describes the same operations in more detail. For moduli of 2 to 16 limbs, the generic polynomials gr_poly over the ring mpn_mod (gr_ctx_init_mpn_mod) are usually faster still; see Arithmetic modulo multiword integers.

Most of the arithmetic is delegated: products are computed over Z\mathbb{Z} by fmpz_poly (Kronecker substitution, Schönhage–Strassen or multimodular FFTs, depending on the sizes) and reduced afterwards, while division, power series, GCDs, resultants, powering modulo a polynomial, composition and modular composition are thin wrappers around the generic algorithms of gr_poly over the fmpz_mod context. These algorithms are quasi-linear: Newton iteration for division and series (Newton iteration for power series and division), the half-GCD algorithm for GCDs and resultants (Half-GCD) and the Brent–Kung algorithm for modular composition (Composition and modular composition). Factorisation, irreducibility tests and root finding are in fmpz_mod_poly_factor.h.

The guide Getting started with fmpz_mod_poly shows how to create and use polynomials and how to work with a modulus that may be composite.

Guides#

Types and conventions#

A polynomial over Z/nZ\mathbb{Z}/n\mathbb{Z}. The structure has the fields coeffs (an array of alloc coefficients of type fmpz), alloc and length, in the same layout as gr_poly_struct. An fmpz_mod_poly_t is an array of one fmpz_mod_poly_struct, so it is passed by reference. The coefficient of xix^i is coeffs[i].

  • All polynomials passed to one function must belong to the context ctx. Some functions do not use ctx but take it for uniformity.
  • A polynomial is normalised if its length is zero or its leading coefficient is nonzero, and its coefficients are reduced if they lie in [0,n)[0, n). All functions require normalised inputs with reduced coefficients and produce such outputs, unless stated otherwise.
  • Functions without a leading underscore manage memory and allow every output to be the same object as any input, unless stated otherwise. Functions with a leading underscore work on coefficient arrays, assume nonzero lengths and enough space in the output, and do not allow aliasing unless stated otherwise.
  • Division by a polynomial needs an invertible leading coefficient, and GCDs, modular inverses, minimal polynomials and square roots need a prime modulus. This is not checked; a non-invertible element usually raises an exception.
  • The functions with suffix _f support a composite modulus nn: they take an fmpz_t f as first argument and either set f=1f = 1 and compute the result, or, if they meet a non-invertible leading coefficient, set ff to a nontrivial factor of nn (and leave the other outputs undefined).

Memory management#

Initialise poly as the zero polynomial. fmpz_mod_poly_init allocates nothing, fmpz_mod_poly_init2 allocates space for alloc coefficients.

Frees the memory used by poly, which must be initialised again before it is used.

Changes the allocated space of poly to alloc coefficients. If the length exceeds alloc, the polynomial is truncated to length alloc and normalised. For alloc = 0 the polynomial is cleared and reinitialised.

Ensure that poly has space for at least len coefficients. If it has to grow, it grows to at least twice the old allocation, so that repeated calls cost amortised linear time. The length and coefficients are not changed.

Decreases the length of poly until the leading coefficient is nonzero or the length is zero.

Sets the length of poly to len. If len is smaller than the current length, the discarded coefficients are set to zero (freeing their memory); otherwise the coefficients between the old and the new length must already be valid. The result is not normalised.

Truncates poly to length len (if it is longer) and normalises it.

Sets res to poly truncated to length nn, that is, to poly mod xn\mathit{poly} \bmod x^n.

Length, degree and basic properties#

Return the length and the degree of poly. The zero polynomial has length 0 and degree −1-1.

Returns a pointer to the leading coefficient of poly, or NULL if poly is zero.

Return whether poly is 0, 1, or the generator xx. Modulo n=1n = 1 every polynomial is zero; fmpz_mod_poly_is_gen then returns 1, while fmpz_mod_poly_is_one returns 0.

Returns whether f is nonzero with leading coefficient 1.

Returns whether op is a constant that is invertible modulo nn (or whether n=1n = 1). For prime nn these are exactly the units of (Z/nZ)[x](\mathbb{Z}/n\mathbb{Z})[x]; for composite nn there are also nonconstant units, such as 1+2x1 + 2x modulo 4, which this function does not recognise.

Returns whether A is normalised and has all its coefficients reduced modulo nn. Useful for checking the result of low-level manipulations.

Returns the number of nonzero coefficients of A.

int fmpz_mod_poly_equal(const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx)

Return whether poly1 and poly2 are equal, respectively equal modulo xnx^n.

Randomisation#

Set f to a random polynomial of length at most len with uniformly distributed coefficients; fmpz_mod_poly_rand_monic makes the coefficient of xlen−1x^{\mathit{len} - 1} equal to 1 (len>0\mathit{len} > 0).

Sets f to a random irreducible polynomial of length at most len with uniformly distributed coefficients, by testing random polynomials with fmpz_mod_poly_is_irreducible. Requires len≥1\mathit{len} \ge 1 and a prime modulus.

Set f to a random polynomial of length at most len, nonzero (len≥1\mathit{len} \ge 1), or monic of length exactly len. The coefficients are drawn with fmpz_randtest_mod, which favours special values (small values, values close to nn), as appropriate for testing.

Set f to a random irreducible polynomial of length at most len (respectively a monic one of length exactly len), for testing. Requires len≥1\mathit{len} \ge 1 and a prime modulus.

Sets f to a random monic irreducible polynomial of length len whose roots generate the multiplicative group of Fplen−1\mathbb{F}_{p^{\mathit{len} - 1}} (a primitive polynomial), tested with fq_is_primitive.

Set f to a random monic polynomial of length len of the form xd+axk+bx^{d} + a x^k + b with 0<k<d0 < k < d (trinomial, len≥3\mathit{len} \ge 3), or xd+a3x3+a2x2+a1x+a0x^{d} + a_3 x^3 + a_2 x^2 + a_1 x + a_0 (pentanomial, len≥5\mathit{len} \ge 5), where d=len−1d = \mathit{len} - 1 and some of the random coefficients may be zero.

Try up to max_attempts random trinomials or pentanomials of length len (without limit if max_attempts is 0) and return 1 as soon as one is irreducible, with f set to it; return 0 if none was found.

Sets f to a sparse monic irreducible polynomial of length len: an irreducible trinomial if one is found in 2len2 \mathit{len} attempts, otherwise a pentanomial (likewise), otherwise a random monic irreducible polynomial with few terms.

Assignment and basic manipulation#

Sets poly1 to poly2.

Swaps poly1 and poly2 efficiently, by swapping the structures.

Set poly to 0, 1 or the generator xx (all three are zero for n=1n = 1).

Sets the coefficients of xkx^k for i≤k<ji \le k < j to zero, normalising the result if the top coefficients were cleared. Indices outside [0,len)[0, \mathit{len}) are ignored.

void _fmpz_mod_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n)

Set res to the reversal xn−1poly(1/x)x^{n-1} \mathit{poly}(1/x) of poly viewed as a polynomial of length nn (truncated or zero-padded). The underscore version writes exactly nn coefficients, requires len≤n\mathit{len} \le n and allows res and poly to be the same array; the other version normalises the result, which can therefore be shorter than nn.

Conversion#

Set the polynomial to the constant x or c, reduced modulo nn.

Sets f to the integer polynomial g reduced modulo nn.

Sets f to the integer polynomial whose coefficients are the representatives in [0,n)[0, n) of the coefficients of g.

Copy the coefficients between an fmpz_mod_poly_t and an nmod_poly_t, assuming that both have the same modulus, which is not checked (no context is passed). For fmpz_mod_poly_get_nmod_poly, the modulus of f must already be set.

Getting and setting coefficients#

Set the coefficient of xnx^n, n≥0n \ge 0, to x reduced modulo the modulus, extending or normalising the polynomial as needed.

Sets x to the coefficient of xnx^n in poly (zero if nn is at least the length).

Shifting#

void _fmpz_mod_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n)

Set the output to the input multiplied by xnx^n. The underscore version writes len + n coefficients and allows res and poly to be the same array.

void _fmpz_mod_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n)

Set the output to the input divided by xnx^n, discarding the low coefficients; the result is zero if nn is at least the length. The underscore version writes len - n coefficients, requires len>n\mathit{len} > n and allows res and poly to be the same array.

Inflation and deflation#

void fmpz_mod_poly_inflate(fmpz_mod_poly_t result, const fmpz_mod_poly_t input, ulong inflation, const fmpz_mod_ctx_t ctx)

Sets result to p(xm)p(x^m) where pp is input and mm = inflation.

void fmpz_mod_poly_deflate(fmpz_mod_poly_t result, const fmpz_mod_poly_t input, ulong deflation, const fmpz_mod_ctx_t ctx)

Sets result to p(x1/m)p(x^{1/m}) where pp is input and m≥1m \ge 1 = deflation, which must divide the exponents of all nonzero terms of input (see fmpz_mod_poly_deflation). m=0m = 0 raises an exception.

Returns the largest mm such that input is a polynomial in xmx^m, that is, the gcd of the exponents of its nonzero terms; 0 for the zero polynomial and 1 for a nonzero constant.

Addition and subtraction#

void _fmpz_mod_poly_add(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx)
void _fmpz_mod_poly_sub(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx)

Set res to the sum or difference of (poly1, len1) and (poly2, len2), writing max⁡(len1,len2)\max(\mathit{len1}, \mathit{len2}) coefficients without normalising. res may be one of the inputs.

void fmpz_mod_poly_add(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_sub(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx)

Set res to poly1+poly2\mathit{poly1} + \mathit{poly2}, respectively poly1−poly2\mathit{poly1} - \mathit{poly2}.

Set res to the sum or difference of poly1 and poly2 truncated to length nn.

Set res to poly+c\mathit{poly} + c, poly−c\mathit{poly} - c or c−polyc - \mathit{poly} for an integer constant cc, which is reduced modulo nn.

void _fmpz_mod_poly_neg(fmpz * res, const fmpz * poly, slong len, const fmpz_mod_ctx_t ctx)

Set res to −poly-\mathit{poly}.

Scalar multiplication and division#

void _fmpz_mod_poly_scalar_mul_fmpz(fmpz * res, const fmpz * poly, slong len, const fmpz_t x, const fmpz_mod_ctx_t ctx)
void _fmpz_mod_poly_scalar_mul_ui(fmpz * res, const fmpz * poly, slong len, ulong x, const fmpz_mod_ctx_t ctx)

Set res to x⋅polyx \cdot \mathit{poly}, with xx reduced modulo nn (it need not be reduced on input).

Sets AA to A+xBA + x B.

void _fmpz_mod_poly_scalar_div_fmpz(fmpz * res, const fmpz * poly, slong len, const fmpz_t x, const fmpz_mod_ctx_t ctx)

Set res to x−1⋅polyx^{-1} \cdot \mathit{poly}. If xx is not invertible modulo nn, an exception is raised (FLINT_DIVZERO for x≡0x \equiv 0, FLINT_ERROR otherwise).

Multiplication#

void _fmpz_mod_poly_mul(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_mul(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx)

Set res to the product of poly1 and poly2. The underscore version writes len1+len2−1\mathit{len1} + \mathit{len2} - 1 coefficients, requires positive lengths (in either order) and allows zero-padded inputs.

More
void _fmpz_mod_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n, const fmpz_mod_ctx_t ctx)

Set res to the product of poly1 and poly2 truncated to length nn. The underscore version requires positive lengths and 0<n≤len1+len2−10 < n \le \mathit{len1} + \mathit{len2} - 1, and does not allow aliasing.

void _fmpz_mod_poly_mulmid(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_mulmid(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong nlo, slong nhi, const fmpz_mod_ctx_t ctx)

Set res to the coefficients of index nlo≤i<nhi\mathit{nlo} \le i < \mathit{nhi} of the product, that is, to ((poly1⋅poly2) mod xnhi)/xnlo((\mathit{poly1} \cdot \mathit{poly2}) \bmod x^{\mathit{nhi}}) / x^{\mathit{nlo}}. The underscore version requires positive lengths and 0≤nlo<nhi≤len1+len2−10 \le \mathit{nlo} < \mathit{nhi} \le \mathit{len1} + \mathit{len2} - 1, writes nhi−nlo\mathit{nhi} - \mathit{nlo} coefficients and does not allow aliasing.

void fmpz_mod_poly_mulhigh(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, slong start, const fmpz_mod_ctx_t ctx)

Sets the coefficients of index at least start of res to those of the product of poly1 and poly2. The coefficients of index less than start are arbitrary (they are not set to zero).

void _fmpz_mod_poly_sqr(fmpz * res, const fmpz * poly, slong len, const fmpz_mod_ctx_t ctx)

Set res to the square of poly; the underscore version writes 2len−12 \mathit{len} - 1 coefficients.

void _fmpz_mod_poly_mulmod(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx)

Set res to poly1⋅poly2 mod f\mathit{poly1} \cdot \mathit{poly2} \bmod f. The underscore version requires len1+len2−lenf>0\mathit{len1} + \mathit{len2} - \mathit{lenf} > 0 (so that a reduction takes place), writes lenf−1\mathit{lenf} - 1 coefficients and does not allow res to alias f. The leading coefficient of ff must be invertible (FLINT_IMPINV otherwise).

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_mod_ctx_t ctx)

Like fmpz_mod_poly_mulmod, given finv, the inverse of the reversal of ff modulo xlenfx^{\mathit{lenf}} (computed with fmpz_mod_poly_reverse and fmpz_mod_poly_inv_series). Both factors must be reduced modulo ff (len1, len2 <lenf< \mathit{lenf}); otherwise an exception is raised.

Powering#

void _fmpz_mod_poly_pow(fmpz * rop, const fmpz * op, slong len, ulong e, const fmpz_mod_ctx_t ctx)

Set rop to ope\mathit{op}^e, with 00=10^0 = 1. The underscore version requires e>1e > 1 and len>0\mathit{len} > 0, writes e(len−1)+1e(\mathit{len} - 1) + 1 coefficients and does not allow aliasing.

void _fmpz_mod_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx)
void _fmpz_mod_poly_pow_trunc_binexp(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_mod_ctx_t ctx)

Set res to polye mod xtrunc\mathit{poly}^e \bmod x^{\mathit{trunc}} by binary exponentiation with truncated products. The underscore versions require poly to be zero-padded to length trunc, trunc>0\mathit{trunc} > 0 and e>1e > 1, and do not allow aliasing.

void _fmpz_mod_poly_powmod_ui_binexp(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx)
void _fmpz_mod_poly_powmod_fmpz_binexp(fmpz * res, const fmpz * poly, const fmpz_t e, const fmpz * f, slong lenf, const fmpz_mod_ctx_t ctx)

Set res to polye mod f\mathit{poly}^e \bmod f by binary exponentiation, for e≥0e \ge 0. The underscore versions require e>0e > 0, lenf>1\mathit{lenf} > 1 and poly reduced modulo ff and zero-padded to length lenf−1\mathit{lenf} - 1; they write lenf−1\mathit{lenf} - 1 coefficients.

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_mod_ctx_t ctx)
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_mod_ctx_t ctx)

Like the previous functions, given finv, the inverse of the reversal of ff modulo xlenfx^{\mathit{lenf}}, so that each reduction modulo ff costs two multiplications.

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_mod_ctx_t ctx)

Set res to xe mod fx^e \bmod f for e≥0e \ge 0 by sliding-window exponentiation, given finv as above. Multiplications by xx are shifts, which makes this cheaper than powering a general polynomial. The underscore version requires e>0e > 0 and lenf>2\mathit{lenf} > 2 and writes lenf−1\mathit{lenf} - 1 coefficients.

Sets res to (x+a)e mod f(x + a)^e \bmod f for e≥0e \ge 0, given finv as above, by binary exponentiation in which the multiplications by x+ax + a are done in linear time. Used in root finding. A negative ee raises an exception.

void _fmpz_mod_poly_powers_mod_preinv_naive(fmpz ** res, const fmpz * f, slong flen, slong n, const fmpz * g, slong glen, const fmpz * ginv, slong ginvlen, const fmpz_mod_ctx_t ctx)

Set the nn entries of res to f0,f1,…,fn−1 mod gf^0, f^1, \ldots, f^{n-1} \bmod g by repeated multiplication. In the underscore version ff must be reduced modulo gg (with length flen>0\mathit{flen} > 0, possibly zero-padded), each res[i] must have space for glen−1\mathit{glen} - 1 coefficients, and ginv is the inverse of the reversal of gg. The entries of res must not alias the inputs.

void _fmpz_mod_poly_powers_mod_preinv_threaded_pool(fmpz ** res, const fmpz * f, slong flen, slong n, const fmpz * g, slong glen, const fmpz * ginv, slong ginvlen, const fmpz_mod_ctx_t ctx, thread_pool_handle * threads, slong num_threads)

Like the previous functions, computing the powers with a baby-step giant-step scheme in which blocks of consecutive powers are computed in parallel using the threads of the given thread pool (respectively the threads available through flint_get_num_threads).

Tables of Frobenius powers xpk mod fx^{p^k} \bmod f, with fields pow (an array of polynomials) and len.

Compute (and free) the table of xp2i mod fx^{p^{2^i}} \bmod f for 2i≤m2^i \le m, where pp is the modulus, given finv, the inverse of the reversal of ff. The first entry is computed by exponentiation and each following one by modular composition of the previous one with itself.

Sets res to xpm mod fx^{p^m} \bmod f using the table pow from fmpz_mod_poly_frobenius_powers_2exp_precomp (computed for a bound at least mm), by modular compositions of the table entries along the binary expansion of mm (see Finite fields and the Frobenius map).

Compute (and free) the table of all xpk mod fx^{p^k} \bmod f for 0≤k≤m0 \le k \le m, given finv.

Division#

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_mod_ctx_t ctx)

Compute QQ and RR with A=BQ+RA = BQ + R and deg⁡R<deg⁡B\deg R < \deg B. The leading coefficient of BB must be invertible; invB is its inverse. The underscore version requires lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0, writes lenA−lenB+1\mathit{lenA} - \mathit{lenB} + 1 coefficients of QQ and lenB−1\mathit{lenB} - 1 of RR, allows zero-padding of AA and no aliasing. A zero BB raises FLINT_DIVZERO (except modulo 1).

More
void _fmpz_mod_poly_div(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx)

Set QQ to the quotient of the division of AA by BB, with the same conventions as the division with remainder.

void _fmpz_mod_poly_rem(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx)

Set RR to A mod BA \bmod B, with the same conventions as the division with remainder.

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_mod_ctx_t ctx)
void _fmpz_mod_poly_rem_basecase(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx)

Division with remainder, respectively remainder, by the classical algorithm in O(lenB(lenA−lenB+1))O(\mathit{lenB} (\mathit{lenA} - \mathit{lenB} + 1)) operations. In the underscore versions RR (of length lenA\mathit{lenA} for _fmpz_mod_poly_divrem_basecase, lenB−1\mathit{lenB} - 1 for _fmpz_mod_poly_rem_basecase) may alias AA, but no other aliasing is allowed.

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_mod_ctx_t ctx)
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_mod_ctx_t ctx)

Division with remainder, respectively quotient only, given Binv, the inverse of the reversal of BB modulo xlenBx^{\mathit{lenB}}: the quotient is a truncated product of the reversed AA with Binv, and the remainder costs one more product. Requires lenA≤2lenB−2\mathit{lenA} \le 2 \mathit{lenB} - 2; the non-underscore versions raise an exception otherwise.

void _fmpz_mod_poly_divrem_f(fmpz_t f, fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx)

Division with remainder (respectively remainder) for a possibly composite modulus: if the leading coefficient of BB is invertible, sets f=1f = 1 and computes the result; otherwise sets ff to the nontrivial factor gcd⁡(lc(B),n)\gcd(\mathrm{lc}(B), n) of nn and leaves QQ and RR unchanged. A zero BB raises a division by zero exception.

Divides f by the largest power of p that divides it and returns the exponent. p must have an invertible leading coefficient. An exception is raised if p is zero or constant.

Divisibility testing#

int _fmpz_mod_poly_divides(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx)
int _fmpz_mod_poly_divides_classical(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx)

Return 1 and set Q=A/BQ = A/B if BB divides AA, and otherwise return 0 and set QQ to zero. The leading coefficient of BB must be invertible. The underscore versions require lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0 and write lenA−lenB+1\mathit{lenA} - \mathit{lenB} + 1 coefficients.

More

Power series#

void _fmpz_mod_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n, const fmpz_mod_ctx_t ctx)

Set Qinv to the inverse of the power series QQ modulo xnx^n, n≥1n \ge 1, by Newton iteration (_gr_poly_inv_series). The constant term of QQ must be invertible: zero raises FLINT_DIVZERO, a non-invertible nonzero value (composite modulus) another exception. The underscore version writes nn coefficients and does not allow aliasing.

Like fmpz_mod_poly_inv_series for a possibly composite modulus: sets f=1f = 1 and Qinv to the inverse, or sets ff to a nontrivial factor of nn (when the constant term is not invertible) with Qinv undefined.

void _fmpz_mod_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n, const fmpz_mod_ctx_t ctx)

Set QQ to A/B mod xnA/B \bmod x^n. The constant term of BB must be invertible (an exception is raised otherwise). The underscore version requires Alen,Blen≤n\mathit{Alen}, \mathit{Blen} \le n.

void _fmpz_mod_poly_sqrt_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t ctx)
void _fmpz_mod_poly_invsqrt_series(fmpz * g, const fmpz * h, slong hlen, slong n, const fmpz_mod_ctx_t ctx)

Set gg to h\sqrt{h}, respectively 1/h1/\sqrt{h}, modulo xnx^n, the series being defined by the binomial expansion of (1+y)±1/2(1 + y)^{\pm 1/2}. The constant term of hh must be 1 (an exception is raised otherwise), and 2 must be invertible modulo nn. The underscore versions require n>0n > 0 and hlen>0\mathit{hlen} > 0 and do not allow aliasing.

Greatest common divisors and modular inverses#

Sets res to poly divided by its leading coefficient (zero if poly is zero). A non-invertible leading coefficient raises FLINT_IMPINV.

Either sets f=1f = 1 and res to poly made monic, or sets ff to a nontrivial factor of nn (the gcd of nn with the leading coefficient) and leaves res undefined.

slong _fmpz_mod_poly_gcd(fmpz * G, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx)

Set GG to the greatest common divisor of AA and BB, which is made monic by the non-underscore version (the gcd of two zero polynomials is zero). The underscore version requires lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0 and space for lenB\mathit{lenB} coefficients in GG, returns the length of GG and does not normalise its leading coefficient. The modulus must be prime.

More
slong _fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz * G, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx)
slong _fmpz_mod_poly_gcd_f(fmpz_t f, fmpz * G, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx)

GCD for a possibly composite modulus by the Euclidean algorithm: either sets f=1f = 1 and computes GG as in fmpz_mod_poly_gcd (the underscore versions returning its length), or sets ff to a nontrivial factor of nn met as a non-invertible leading coefficient of a remainder, with GG undefined (the underscore versions then return 0). The _gcd_f names are aliases of the _gcd_euclidean_f functions. The underscore versions require lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0 and do not allow aliasing.

slong _fmpz_mod_poly_hgcd(fmpz ** M, slong * lenM, fmpz * A, slong * lenA, fmpz * B, slong * lenB, const fmpz * a, slong lena, const fmpz * b, slong lenb, const fmpz_mod_ctx_t ctx)

One step of the half-GCD algorithm (_gr_poly_hgcd): for lena>lenb>0\mathit{lena} > \mathit{lenb} > 0, computes the 2×22 \times 2 matrix MM (the entries M[0], ..., M[3] with lengths lenM[0], ..., lenM[3], each with space for lena coefficients) and the two consecutive remainders AA, BB of the Euclidean remainder sequence of (a,b)(a, b) that straddle half the degree of aa, such that (A,B)T=σM−1(a,b)T(A, B)^T = \sigma M^{-1} (a, b)^T, and returns the sign σ=±1\sigma = \pm 1. AA and BB need space for lena and lenb coefficients; their lengths are returned in *lenA, *lenB. See Half-GCD.

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_mod_ctx_t ctx)

Compute the GCD GG of AA and BB and cofactors with SA+TB=GSA + TB = G. The non-underscore version makes GG monic, with deg⁡S<deg⁡B\deg S < \deg B and deg⁡T<deg⁡A\deg T < \deg A (if AA or BB is nonzero; if both are zero, all outputs are zero). The underscore version requires lenA≥lenB≥1\mathit{lenA} \ge \mathit{lenB} \ge 1 with (lenA,lenB)≠(1,1)(\mathit{lenA}, \mathit{lenB}) \ne (1, 1), does not make GG monic, needs space for lenB\mathit{lenB}, lenB−1\mathit{lenB} - 1 and lenA−1\mathit{lenA} - 1 coefficients in GG, SS, TT, returns the length of GG, and does not allow aliasing (invB is not used). The modulus must be prime.

More
slong _fmpz_mod_poly_xgcd_euclidean_f(fmpz_t f, fmpz * G, fmpz * S, fmpz * T, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx)
slong _fmpz_mod_poly_xgcd_f(fmpz_t f, fmpz * G, fmpz * S, fmpz * T, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_mod_ctx_t ctx)

Extended GCD for a possibly composite modulus by the Euclidean algorithm: either set f=1f = 1 and compute the outputs as in fmpz_mod_poly_xgcd (with the same conventions for the underscore versions, where invB is the inverse of the leading coefficient of BB), or set ff to a nontrivial factor of nn. The _xgcd_f names are aliases of the _xgcd_euclidean_f functions.

slong _fmpz_mod_poly_gcdinv(fmpz * G, fmpz * S, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx)
slong _fmpz_mod_poly_gcdinv_euclidean(fmpz * G, fmpz * S, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invA, const fmpz_mod_ctx_t ctx)

Compute G=gcd⁡(A,B)G = \gcd(A, B) and SS, both reduced modulo BB, with G≡SA(modB)G \equiv SA \pmod B; when G=1G = 1, SS is the inverse of AA modulo BB. Requires len(B)≥2\mathit{len}(B) \ge 2 (an exception is raised otherwise); if A≡0(modB)A \equiv 0 \pmod B, sets G=S=0G = S = 0. The underscore versions require 0<lenA<lenB0 < \mathit{lenA} < \mathit{lenB}, write lenA coefficients of GG and lenB−1\mathit{lenB} - 1 of SS, and return the length of GG, which is not made monic. fmpz_mod_poly_gcdinv uses the Euclidean algorithm for lenB<16\mathit{lenB} < 16 and the extended half-GCD algorithm otherwise. The modulus must be prime.

slong _fmpz_mod_poly_gcdinv_f(fmpz_t f, fmpz * G, fmpz * S, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_mod_ctx_t ctx)
slong _fmpz_mod_poly_gcdinv_euclidean_f(fmpz_t f, fmpz * G, fmpz * S, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invA, const fmpz_mod_ctx_t ctx)

Versions of the previous functions for a possibly composite modulus: either set f=1f = 1 and compute GG and SS, or set ff to a nontrivial factor of nn.

int _fmpz_mod_poly_invmod(fmpz * A, const fmpz * B, slong lenB, const fmpz * P, slong lenP, const fmpz_mod_ctx_t ctx)

If BB is invertible modulo PP, set AA to the inverse (reduced modulo PP) and return 1; otherwise return 0, with AA undefined. The modulus must be prime. fmpz_mod_poly_invmod raises an exception if deg⁡P<1\deg P < 1 and reduces BB modulo PP first. The underscore version requires 0<lenB<lenP0 < \mathit{lenB} < \mathit{lenP} (allowing zero-padding of BB), writes lenP−1\mathit{lenP} - 1 coefficients and does not allow aliasing.

int _fmpz_mod_poly_invmod_f(fmpz_t f, fmpz * A, const fmpz * B, slong lenB, const fmpz * P, slong lenP, const fmpz_mod_ctx_t ctx)

Versions of the previous functions for a possibly composite modulus: either set f=1f = 1 and behave as fmpz_mod_poly_invmod, or set ff to a nontrivial factor of nn.

Resultant and discriminant#

void _fmpz_mod_poly_resultant(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx)

Set res to the resultant of the two polynomials (zero if one of them is zero), computed with _gr_poly_resultant, which uses the Euclidean or the half-GCD algorithm. The underscore version requires len1≥len2>0\mathit{len1} \ge \mathit{len2} > 0. The modulus should be prime; for a composite modulus the function raises an exception if it meets a non-invertible leading coefficient.

void _fmpz_mod_poly_discriminant(fmpz_t d, const fmpz * poly, slong len, const fmpz_mod_ctx_t ctx)

Set dd to the discriminant of ff, normalised as

disc⁡(f)=(−1)n(n−1)/2 res⁡(f,f′) lc⁡(f)−(n−m)\operatorname{disc}(f) = (-1)^{n(n-1)/2}\, \operatorname{res}(f, f') \, \operatorname{lc}(f)^{-(n - m)}

with n=deg⁡fn = \deg f and m=deg⁡f′m = \deg f' (so lc⁡(f)−1\operatorname{lc}(f)^{-1} when p∤np \nmid n); then disc⁡(f)=lc⁡(f)2n−2∏i<j(ri−rj)2\operatorname{disc}(f) = \operatorname{lc}(f)^{2n-2} \prod_{i < j} (r_i - r_j)^2 over the roots rir_i of ff. The discriminant of a polynomial of degree less than 1, or with f′=0f' = 0, is zero. The underscore version requires len>1\mathit{len} > 1.

Derivative#

void _fmpz_mod_poly_derivative(fmpz * res, const fmpz * poly, slong len, const fmpz_mod_ctx_t ctx)

Set res to the derivative of poly. The underscore version writes len−1\mathit{len} - 1 coefficients and allows aliasing.

Evaluation#

void _fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz * poly, slong len, const fmpz_t a, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz_mod_poly_t poly, const fmpz_t a, const fmpz_mod_ctx_t ctx)

Set res to the value of the polynomial at aa (reduced modulo nn first if necessary), by Horner's rule. res may alias aa in the non-underscore version, but not a coefficient of poly.

void _fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx)

Evaluate the polynomial at the nn reduced points xs, writing the values to ys. Uses Horner's rule for each point if the length of the polynomial is less than 32, and fast multipoint evaluation otherwise.

void _fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx)

Evaluate the polynomial at the nn reduced points xs by Horner's rule for each point, in O(n⋅len)O(n \cdot \mathit{len}) operations.

void _fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz * poly, slong plen, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx)
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_mod_ctx_t ctx)

Evaluate the polynomial at the reduced points by fast multipoint evaluation: the remainders modulo the products in a subproduct tree of the points are computed from the root to the leaves, in O(M(n)log⁡n)O(M(n) \log n) operations (Multipoint evaluation and interpolation). The _precomp version takes the tree built by _fmpz_mod_poly_tree_build for len points.

void _fmpz_mod_poly_tree_build(fmpz_poly_struct ** tree, const fmpz * roots, slong len, const fmpz_mod_ctx_t ctx)

Allocate, free and fill a subproduct tree for len points: level 0 holds the linear factors x−rix - r_i and each following level the products of pairs from the level below; the root (the product of all factors) is not computed.

Products of linear factors and roots#

void _fmpz_mod_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx)

Set poly to the monic polynomial (x−x0)(x−x1)⋯(x−xn−1)(x - x_0)(x - x_1) \cdots (x - x_{n-1}) for reduced xix_i, by a quadratic algorithm for n<20n < 20 and by splitting the roots into halves otherwise. The underscore version writes n+1n + 1 coefficients and does not allow aliasing.

If the nonzero polynomial PP has deg⁡P\deg P distinct nonzero roots in Fp\mathbb{F}_p, writes them to roots[0], ..., roots[deg(P) - 1] and returns 1; otherwise returns 0. The modulus must be prime.

More

Splits ff of degree at least 2, assumed to have deg⁡f\deg f distinct nonzero roots in Fp\mathbb{F}_p, into two nontrivial factors aa and bb with deg⁡a≥deg⁡b\deg a \ge \deg b, as a=gcd⁡(f,(x+δ)(p−1)/2−1)a = \gcd(f, (x + \delta)^{(p-1)/2} - 1) for random δ\delta (degree 2 is solved directly with a square root). halfp must be (p−1)/2(p - 1)/2, and tt, t2t_2 are scratch polynomials.

Composition#

void _fmpz_mod_poly_compose(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_mod_ctx_t ctx)

Set res to the composition poly1(poly2)\mathit{poly1}(\mathit{poly2}), by _gr_poly_compose. The underscore version requires nonzero inputs, writes (len1−1)(len2−1)+1(\mathit{len1} - 1)(\mathit{len2} - 1) + 1 coefficients and does not allow aliasing.

Modular composition#

All functions in this section compute f(g) mod hf(g) \bmod h, where hh is nonzero with invertible leading coefficient and gg is reduced modulo hh; the underscore versions require gg zero-padded to length lenh−1\mathit{lenh} - 1, write lenh−1\mathit{lenh} - 1 coefficients and do not allow aliasing. They are wrappers of the corresponding gr_poly functions; see 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_mod_ctx_t ctx)

Set res to f(g) mod hf(g) \bmod h (in the non-underscore version f,g,hf, g, h are poly1, poly2, poly3), choosing between Horner's rule and the Brent–Kung algorithm according to the lengths.

void _fmpz_mod_poly_compose_mod_horner(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_mod_ctx_t ctx)

Set res to f(g) mod hf(g) \bmod h by Horner's rule, with lenf−1\mathit{lenf} - 1 multiplications modulo hh.

void _fmpz_mod_poly_compose_mod_brent_kung(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, const fmpz * poly3, slong len3, const fmpz_mod_ctx_t ctx)

Set res to f(g) mod hf(g) \bmod h by the Brent–Kung baby-step giant-step algorithm [BrentKung1978], with about 2n2\sqrt{n} multiplications modulo hh and one product of a n×n\sqrt{n} \times \sqrt{n} by a n×n\sqrt{n} \times n matrix, n=deg⁡hn = \deg h. Requires deg⁡f<deg⁡h\deg f < \deg h.

void _fmpz_mod_poly_compose_mod_brent_kung_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, const fmpz * poly3, slong len3, const fmpz * poly3inv, slong len3inv, const fmpz_mod_ctx_t ctx)

Like fmpz_mod_poly_compose_mod_brent_kung, given poly3inv, the inverse of the reversal of hh = poly3 modulo xlen3x^{\mathit{len3}}.

void _fmpz_mod_poly_precompute_matrix(fmpz_mat_t A, const fmpz * poly1, const fmpz * poly2, slong len2, const fmpz * poly2inv, slong len2inv, const fmpz_mod_ctx_t ctx)

Set the rows of AA to the coefficients of gi mod hg^i \bmod h for 0≤i<m0 \le i < m, where gg = poly1 is reduced modulo hh = poly2, poly2inv is the inverse of the reversal of hh, and AA must have been initialised as an m×deg⁡hm \times \deg h matrix with m=⌊deg⁡h⌋+1m = \lfloor \sqrt{\deg h} \rfloor + 1. This is the precomputation for repeated compositions with the same gg and hh.

void _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv(fmpz * res, const fmpz * poly1, slong len1, const fmpz_mat_t A, const fmpz * poly3, slong len3, const fmpz * poly3inv, slong len3inv, const fmpz_mod_ctx_t ctx)

Set res to f(g) mod hf(g) \bmod h for ff = poly1 with deg⁡f<deg⁡h\deg f < \deg h, hh = poly3, given the matrix AA of powers of gg computed by fmpz_mod_poly_precompute_matrix and the inverse poly3inv of the reversal of hh. Only the matrix product and the giant steps remain, which makes repeated compositions with the same gg, such as the Frobenius iterations in factorisation, cheaper.

Initialises AA and sets its rows to the rows of BB reduced modulo ff: BB is a matrix of powers gi mod hg^i \bmod h as above and ff a divisor of hh, so that AA is the corresponding matrix modulo ff, with ⌊deg⁡f⌋+1\lfloor \sqrt{\deg f} \rfloor + 1 rows and deg⁡f\deg f columns.

Square roots#

int _fmpz_mod_poly_sqrt(fmpz * s, const fmpz * p, slong len, const fmpz_mod_ctx_t ctx)

If the polynomial is a perfect square, set the output to a square root and return 1; otherwise return 0 (and set b to zero). The modulus must be prime. The underscore version writes len/2+1\mathit{len}/2 + 1 coefficients.

More

Minimal polynomials of sequences#

A minimal generating polynomial of a sequence s0,…,sℓ−1s_0, \ldots, s_{\ell-1} is a monic f=xd+cd−1xd−1+⋯+c0f = x^d + c_{d-1} x^{d-1} + \cdots + c_0 of least degree such that si+d+∑j<dcjsi+j=0s_{i+d} + \sum_{j<d} c_j s_{i+j} = 0 for all 0≤i<ℓ−d0 \le i < \ell - d. The modulus must be prime.

slong _fmpz_mod_poly_minpoly(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_minpoly(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx)

Set poly to a minimal generating polynomial of (seq, len), choosing the Berlekamp–Massey algorithm for len<max⁡(200,530−22s)\mathit{len} < \max(200, 530 - 22s), ss being the number of limbs of the modulus, and the half-GCD algorithm otherwise. The underscore version needs space for len+1\mathit{len} + 1 coefficients, returns the length of poly and does not allow aliasing.

slong _fmpz_mod_poly_minpoly_bm(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_minpoly_bm(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx)

Like fmpz_mod_poly_minpoly, using the Berlekamp–Massey algorithm [Ber1968] [Mas1969], in O(len⋅d)O(\mathit{len} \cdot d) operations for a minimal polynomial of degree dd.

slong _fmpz_mod_poly_minpoly_hgcd(fmpz * poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_minpoly_hgcd(fmpz_mod_poly_t poly, const fmpz * seq, slong len, const fmpz_mod_ctx_t ctx)

Like fmpz_mod_poly_minpoly, using a half-GCD of xlenx^{\mathit{len}} and the reversed sequence, in O(M(len)log⁡len)O(M(\mathit{len}) \log \mathit{len}) operations regardless of the degree.

Incremental Berlekamp–Massey#

An fmpz_mod_berlekamp_massey_t processes an unbounded stream of points a1,a2,…a_1, a_2, \ldots. After nn points have been added, fmpz_mod_berlekamp_massey_reduce computes polynomials UU, VV, RR in the extended Euclidean remainder sequence of xnx^n and a1xn−1+⋯+ana_1 x^{n-1} + \cdots + a_n with

Uxn+V(a1xn−1+⋯+an−1x+an)=R,deg⁡U<deg⁡V≤n/2,deg⁡R<n/2.U x^n + V (a_1 x^{n-1} + \cdots + a_{n-1} x + a_n) = R, \qquad \deg U < \deg V \le n/2, \qquad \deg R < n/2.

Writing viv_i for the coefficients of VV, this means that ∑iviaj+i=0\sum_i v_i a_{j+i} = 0 for 1≤j<n−deg⁡R1 \le j < n - \deg R: VV annihilates the sequence if deg⁡R<deg⁡V\deg R < \deg V. Unlike fmpz_mod_poly_minpoly, which can return a polynomial of degree up to n−1n - 1 that annihilates all the points, the result is unique and the points can be added incrementally, as in sparse interpolation where the number of points needed is not known in advance.

The state of an incremental Berlekamp–Massey computation: the points added so far and the polynomials of the remainder sequence.

Initialise B with an empty stream of points, respectively free it.

Empties the stream of points of B.

Append points (reduced modulo nn) to the stream of B: count points from a, count zeros, or a single point. VV and RR are not updated until the next call to fmpz_mod_berlekamp_massey_reduce.

Brings VV and RR up to date with the points added so far and returns 1 if VV changed, 0 otherwise. For example, after the points 1,1,2,31, 1, 2, 3 the call returns 1 with deg⁡R<deg⁡V=2\deg R < \deg V = 2, since the Fibonacci recurrence has been recognised; after adding 5,85, 8 another call returns 0.

Return the number of points stored in B and a pointer to them (which may be NULL if there are none).

Prints VV and the stored points of B to standard output, for debugging.

Radix conversion#

Given a nonconstant polynomial RR with invertible leading coefficient, every FF has a unique expansion

F=∑i=0NBiRi,deg⁡Bi<deg⁡R,N=⌊deg⁡F/deg⁡R⌋.F = \sum_{i=0}^{N} B_i R^i, \qquad \deg B_i < \deg R, \qquad N = \lfloor \deg F / \deg R \rfloor.

The functions below compute it by divide and conquer with divisions by R2iR^{2^i}, in O(M(deg⁡F)log⁡deg⁡F)O(M(\deg F) \log \deg F) operations, reusing the powers of RR and the power series inverses of their reversals, which are stored in an fmpz_mod_poly_radix_t. The modulus need not be prime; this is used, for example, with prime power moduli in pp-adic computations.

Precomputed data for radix conversion with respect to a fixed RR: the powers R2iR^{2^i}, the inverses of their reversals, the degree of RR, the number kk of powers and the inverse of the leading coefficient of RR.

Initialise D with the data for radix conversion with respect to RR of polynomials of degree at most degF, respectively free it. RR must have degree at least 1 and an invertible leading coefficient.

Sets B[0], ..., B[N] to the digits BiB_i of FF with respect to the radix RR of D, where N=⌊deg⁡F/deg⁡R⌋N = \lfloor \deg F / \deg R \rfloor and deg⁡F\deg F is at most the bound given to fmpz_mod_poly_radix_init.

void _fmpz_mod_poly_radix_init(fmpz ** Rpow, fmpz ** Rinv, const fmpz * R, slong lenR, slong k, const fmpz_t invL, const fmpz_mod_ctx_t ctx)

Computes the powers R2iR^{2^i} and the inverses of their reversals modulo x2ideg⁡Rx^{2^i \deg R} for 0≤i<k0 \le i < k, where invL is the inverse of the leading coefficient of RR. Rpow[i] and Rinv[i] need space for 2ideg⁡R+12^i \deg R + 1 and 2ideg⁡R2^i \deg R coefficients. The data can be used for all FF with len(F)≤2kdeg⁡R\mathrm{len}(F) \le 2^k \deg R.

void _fmpz_mod_poly_radix(fmpz ** B, const fmpz * F, fmpz ** Rpow, fmpz ** Rinv, slong degR, slong k, slong i, fmpz * W, const fmpz_mod_ctx_t ctx)

The recursive step of fmpz_mod_poly_radix: FF has length 2i+1deg⁡R2^{i+1} \deg R (zero-padded), kk is the number of digits already accounted for (0 at the top level), every B[j] has space for deg⁡R\deg R coefficients, and WW is scratch space of length 2i+1deg⁡R2^{i+1} \deg R.

Input and output#

A polynomial is written as its length, the modulus, and the coefficients, for example "4 6 1 2 0 5" for 5x3+2x+15x^3 + 2x + 1 modulo 6 (two spaces before the first coefficient), and in the pretty format as 5*x^3+2*x+1. The printing functions return a positive value on success and a non-positive value on failure.

char * fmpz_mod_poly_get_str_pretty(const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx)

Return a string for poly in the format of fmpz_poly_get_str (the length and the coefficients, without the modulus), respectively the pretty format with variable name x. The string must be freed with flint_free.

int _fmpz_mod_poly_fprint(FILE * file, const fmpz * poly, slong len, const fmpz_t p)
int fmpz_mod_poly_fprint(FILE * file, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx)
int _fmpz_mod_poly_print(const fmpz * poly, slong len, const fmpz_t p)

Print the polynomial, with its length and modulus, to file or to standard output.

int fmpz_mod_poly_fprint_pretty(FILE * file, const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_print_pretty(const fmpz_mod_poly_t poly, const char * x, const fmpz_mod_ctx_t ctx)

Print the polynomial in the pretty format with variable name x.

Reads a polynomial in the format of fmpz_mod_poly_fprint from file, sets the modulus of ctx to the modulus read (which must be at least 2) and poly to the polynomial, and returns 1 on success and 0 on failure.

References#

  • [BrentKung1978] Brent, R. P. and Kung, H. T. : Fast Algorithms for Manipulating Formal Power Series, J. ACM 25:4 (1978) 581–595
  • [Ber1968] E. R. Berlekamp. Algebraic Coding Theory. McGraw-Hill, 1968.
  • [Mas1969] J. L. Massey. Shift-register synthesis and BCH decoding. IEEE Transactions on Information Theory 15 (1969), 122–127.
Cite this page

The FLINT team, “fmpz_mod_poly.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz_mod_poly/index.html (generated 2026-11-02).