FLINT3.7.0-dev
Module · 398 functions

nmod_poly.h

#include <flint/nmod_poly.h>

This module implements dense univariate polynomials over \mathbb{Z}/n\mathbb{Z} for a word-size modulus n \ge 1. A polynomial is an nmod_poly_t: an array of ulong coefficients reduced modulo n, together with its length and an nmod_t for the modulus. Multiplication switches between the classical algorithm, several variants of Kronecker substitution and FFTs modulo word-size primes (FFTs modulo word-size primes in floating point), so that a product of length m costs O(m \log m) word operations for large m. Division, power series inversion, GCDs, multipoint evaluation, interpolation and composition are reduced to multiplication by Newton iteration, the half-GCD algorithm and subproduct trees, and inherit its quasi-linear complexity. Factorisation and irreducibility testing are in nmod_poly_factor.h, and polynomial matrices in nmod_poly_mat.h.

The guides below explain how to use the module; start with Getting started with nmod_poly.

OverviewMultiplying polynomials over Z/nZHow nmod_poly multiplies: classical products built on modular dot products, Kronecker substitution (KS, KS2, KS4), and the small-prime FFT of fft_small, with the length and modulus-size cutoffs that choose between them for full, low, middle and high products.

Guides#

Types and conventions#

A polynomial over \mathbb{Z}/n\mathbb{Z}. The structure has the fields coeffs (an array of alloc coefficients), alloc, length and mod (an nmod_t for n, see nmod.h). An nmod_poly_t is an array of one nmod_poly_struct, so it is passed by reference. The coefficient of x^i is coeffs[i].

  • The modulus is stored in each polynomial. All polynomials passed to one function must have the same modulus, which is not checked.
  • A polynomial is normalised if its length is zero or its leading coefficient coeffs[length - 1] is nonzero. The zero polynomial has length 0 and degree -1. Coefficients are reduced, that is, lie in [0, n). All functions require normalised inputs with reduced coefficients and produce such outputs. This is not checked.
  • Functions without a leading underscore manage memory and allow every output to be the same object as any input, unless stated otherwise. Several outputs of one function (such as quotient and remainder) must be distinct objects.
  • Functions with a leading underscore work on plain coefficient arrays (poly, len), take the modulus as an nmod_t, and leave memory management to the caller. They usually require nonzero lengths, place ordering conditions on them, write a fixed number of coefficients (including leading zeros), and do not allow the output to overlap the inputs. Each function states its conditions.
  • Many functions need to invert leading coefficients, or integers up to the length, and therefore assume that n is prime: division by a polynomial whose leading coefficient is not a unit, GCDs, resultants, modular inverses, square roots, interpolation and the transcendental power series. This is not checked. A non-invertible element usually causes an exception (FLINT_IMPINV or FLINT_ERROR), but a composite modulus can also give wrong results without warning. The GCD and resultant functions always throw FLINT_IMPINV when they meet a leading coefficient that is not invertible.

The conventions for arithmetic modulo a fixed polynomial are explained in Computing modulo a fixed polynomial.

Memory management#

Initialise poly as the zero polynomial modulo n \ge 1, without allocating coefficients. nmod_poly_init_preinv takes the precomputed inverse ninv = n_preinvert_limb(n) instead of computing it.

void nmod_poly_init_mod(nmod_poly_t poly, const nmod_t mod)

Initialises poly as the zero polynomial with the modulus mod, which must have been set up with nmod_init. This is the cheapest way to create polynomials with the modulus of an existing one, nmod_poly_init_mod(a, b->mod).

void nmod_poly_init2(nmod_poly_t poly, ulong n, slong alloc)

Like nmod_poly_init and nmod_poly_init_preinv, but allocate space for alloc coefficients.

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 coefficients are freed and poly becomes zero.

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

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

void nmod_poly_set_mod(nmod_poly_t poly, const nmod_t mod)

Replaces the modulus of poly by mod without changing the coefficients, which must be reduced modulo the new modulus.

Sets the length field of poly to len without zeroing or normalising anything. poly must have space for len coefficients.

Decreases the length of poly until the leading coefficient is nonzero or the length is zero. This is the usual last step after writing coefficients with an underscore function.

Length, degree and basic properties#

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

Returns the modulus n of poly.

Returns the number of bits of the largest coefficient of poly, or 0 for the zero polynomial.

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

Return the number of nonzero coefficients.

Returns whether poly is the zero polynomial.

Return whether poly is the constant 1, respectively the generator x. For n = 1 both return 1, since every polynomial is zero modulo 1.

Returns whether poly is a nonzero constant, which for prime n is the same as being a unit. For composite n the result does not tell whether the constant is invertible. For n = 1 it returns 1.

Returns whether poly is nonzero with leading coefficient 1.

Assignment and coefficients#

Sets a to a copy of b.

Swaps poly1 and poly2 in constant time by swapping the structures, including the moduli.

Set res to 0 and to 1. Modulo n = 1, nmod_poly_one sets res to the zero polynomial.

Set res to poly truncated to length len, that is, poly modulo x^{\mathit{len}}, and truncate poly in place. The result is normalised. Nothing happens if len is at least the length.

void _nmod_poly_reverse(nn_ptr output, nn_srcptr input, slong len, slong m)
void nmod_poly_reverse(nmod_poly_t output, const nmod_poly_t input, slong m)

Set output to the reversal x^{m-1} f(1/x) of the input f viewed as a polynomial of length m \ge 0: coefficient i of the output is coefficient m - 1 - i of the input, taken as 0 beyond its length. Input coefficients from index m on are ignored.

More

Returns the coefficient of x^j, or 0 if j is at least the length. Requires j \ge 0.

Sets the coefficient of x^j to c \bmod n, for any c. The polynomial grows, with zero coefficients in between, or shrinks if the leading coefficient is set to zero.

Comparison#

Returns whether a and b are equal. The moduli are not compared.

int nmod_poly_equal_ui(const nmod_poly_t poly, ulong cst)

Return whether poly is the constant cst. nmod_poly_equal_nmod requires cst to be reduced; nmod_poly_equal_ui reduces it first.

int nmod_poly_equal_trunc(const nmod_poly_t poly1, const nmod_poly_t poly2, slong n)

Returns whether poly1 and poly2 agree modulo x^n. A negative n is treated as 0.

Random polynomials#

The rand functions draw coefficients uniformly from [0, n). The randtest functions use n_randtest, which favours special values and sparse polynomials; they are meant for test code. Functions that produce irreducible or primitive polynomials repeat until nmod_poly_is_irreducible (from nmod_poly_factor.h) succeeds and require a prime modulus.

Set poly to a random polynomial of length at most len, respectively a random monic polynomial of length exactly \mathit{len} \ge 1.

Sets poly to a random irreducible polynomial of length at most len. Since nmod_poly_is_irreducible regards nonzero constants as irreducible, the result can be a constant, and it need not be monic.

Set poly to a random test polynomial of length at most len, a nonzero one (requires \mathit{len} \ge 1 and n \ge 2), and a monic one of length exactly \mathit{len} \ge 1.

Set poly to a random irreducible polynomial of length at most len (which may be a constant), and to a random monic irreducible polynomial of length exactly \mathit{len} \ge 2.

Sets poly to a random monic irreducible polynomial of length \mathit{len} \ge 2 whose root generates the multiplicative group of the field \mathbb{F}_n[x]/(\mathit{poly}). Primitivity is tested with fq_nmod_is_primitive.

Set poly to a random monic polynomial of length len with at most three nonzero terms x^{\mathit{len}-1} + a x^k + b, 0 < k < \mathit{len} - 1 (requires \mathit{len} \ge 3), respectively at most five nonzero terms x^{\mathit{len}-1} + a_3 x^3 + a_2 x^2 + a_1 x + a_0 (requires \mathit{len} \ge 5).

Try up to max_attempts random trinomials, respectively pentomials, as above and return 1 as soon as one is irreducible, or 0 if none is. For max_attempts = 0 they try until they succeed, which does not terminate if there is no irreducible polynomial of that shape.

Sets poly to a sparse monic irreducible polynomial of length len: it tries 2 \mathit{len} trinomials, then 2 \mathit{len} pentomials, then random polynomials with a growing number of terms.

Input and output#

The plain format is the length, the modulus and the coefficients from the constant term upwards, for example "3 7 6 0 5" for 5x^2 + 6 modulo 7 (two spaces before the first coefficient). The pretty format writes the terms from the highest degree down, for example "5*x^2+6".

char * nmod_poly_get_str(const nmod_poly_t poly)
char * nmod_poly_get_str_pretty(const nmod_poly_t poly, const char * x)

Return poly as a string in the plain format and in the pretty format with variable name x. The zero polynomial is "0 n" and "0". Free the string with flint_free.

int nmod_poly_set_str(nmod_poly_t poly, const char * s)

Reads poly from a string in the plain format and returns 1, or returns 0 if the string is not in this format. The modulus in the string is ignored and the coefficients are not reduced: they must be smaller than the modulus of poly.

int nmod_poly_fprint(FILE * f, const nmod_poly_t poly)
int nmod_poly_print_pretty(const nmod_poly_t a, const char * x)
int nmod_poly_fprint_pretty(FILE * f, const nmod_poly_t a, const char * x)

Write the polynomial to stdout or to f, in the plain or the pretty format. Return a positive value on success and a non-positive value on failure.

int nmod_poly_fread(FILE * f, nmod_poly_t poly)

Read a polynomial in the plain format from stdin or from f. Unlike nmod_poly_set_str, they reinitialise poly with the modulus that was read. Return 1 on success and 0 if the input is not in the plain format. The coefficients are not reduced.

Shifting#

Set res to poly times x^k, for k \ge 0. The underscore version writes \mathit{len} + k coefficients and allows res == poly.

Set res to poly divided by x^k, discarding the remainder, for k \ge 0. In the underscore version len is the length of the output: it sets res[i] = poly[i + k] for 0 \le i < \mathit{len}, so poly must have at least \mathit{len} + k coefficients. It allows res == poly.

Addition and subtraction#

void _nmod_poly_add(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, nmod_t mod)
void _nmod_poly_sub(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, nmod_t mod)

Set res to the sum and the difference of (poly1, len1) and (poly2, len2), writing \max(\mathit{len1}, \mathit{len2}) coefficients, which may include leading zeros. Any lengths, including 0, are allowed, and res may be poly1 or poly2.

void nmod_poly_add(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)
void nmod_poly_sub(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)
void nmod_poly_neg(nmod_poly_t res, const nmod_poly_t poly1)

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

void nmod_poly_add_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n)
void nmod_poly_sub_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n)

Set res to the sum and the difference modulo x^n. A negative n is treated as 0.

Set res to \mathit{poly} + c and \mathit{poly} - c, for any c.

Scalar multiplication#

Sets res to c \cdot \mathit{poly}, for reduced c. The result is normalised, which matters for composite n.

Sets res to \mathit{res} + c \cdot \mathit{poly}, for reduced c.

void _nmod_poly_make_monic(nn_ptr output, nn_srcptr input, slong len, nmod_t mod)
void nmod_poly_make_monic(nmod_poly_t output, const nmod_poly_t input)

Set output to input divided by its leading coefficient, which must be invertible modulo n (otherwise FLINT_IMPINV is thrown). nmod_poly_make_monic throws FLINT_DIVZERO for the zero polynomial; the underscore version requires \mathit{len} \ge 1 and allows output == input.

Multiplication#

nmod_poly_mul and the other functions without an algorithm in their name choose the algorithm from the lengths and the number of bits of n:

  • the classical algorithm, computing each coefficient as a dot product with _nmod_vec_dot_rev (see Computing dot products), for short operands;
  • Kronecker substitution (KS), which packs the coefficients into integers and multiplies those with flint_mpn_mul, and its multipoint variants KS2 and KS4 [Har2009a], for medium lengths;
  • the small-prime FFT of fft_small for long operands, when FLINT is built with it (the usual case on x86-64 and ARM64). Moduli n \le 23 use a repacked product of half the length.

The crossover points, tabulated for each bit size of n, are explained in Multiplying polynomials. Truncated products (mullow), high products (mulhigh) and middle products (mulmid) compute part of the product for about the cost of the part; middle products are the transposes of ordinary products and are what Newton iteration needs (Middle products and the transposition principle).

OverviewMultiplying polynomials over Z/nZHow nmod_poly multiplies: classical products built on modular dot products, Kronecker substitution (KS, KS2, KS4), and the small-prime FFT of fft_small, with the length and modulus-size cutoffs that choose between them for full, low, middle and high products.

Choosing the algorithm automatically#

void _nmod_poly_mul(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, nmod_t mod)
void nmod_poly_mul(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)

Set res to the product \mathit{poly1} \cdot \mathit{poly2}. The underscore version requires \mathit{len1} \ge \mathit{len2} \ge 1, writes \mathit{len1} + \mathit{len2} - 1 coefficients and does not allow res to overlap the inputs; poly1 == poly2 (squaring) is allowed and faster.

Full documentation
void _nmod_poly_mullow(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong trunc, nmod_t mod)
void nmod_poly_mullow(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc)

Set res to the product truncated to length trunc, that is, \mathit{poly1} \cdot \mathit{poly2} \bmod x^{\mathit{trunc}}. The underscore version requires \mathit{len1} \ge \mathit{len2} \ge 1 and 1 \le \mathit{trunc} \le \mathit{len1} + \mathit{len2} - 1, writes trunc coefficients and does not allow aliasing. Inputs longer than trunc are allowed.

Full documentation
void _nmod_poly_mulhigh(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong n, nmod_t mod)
void nmod_poly_mulhigh(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n)

Set the coefficients of res from index n on to those of the product. The coefficients below n are either zero or the coefficients of the product. The underscore version requires \mathit{len1} \ge \mathit{len2} \ge 1, writes \mathit{len1} + \mathit{len2} - 1 coefficients and does not allow aliasing.

Full documentation
void _nmod_poly_mulmid(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong nlo, slong nhi, nmod_t mod)
void nmod_poly_mulmid(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong nlo, slong nhi)

Set res to the coefficients \mathit{nlo}, \ldots, \mathit{nhi} - 1 of the product, that is, \lfloor \mathit{poly1} \cdot \mathit{poly2} / x^{\mathit{nlo}} \rfloor \bmod x^{\mathit{nhi} - \mathit{nlo}}. The underscore version requires \mathit{len1}, \mathit{len2} \ge 1 in either order and 0 \le \mathit{nlo} < \mathit{nhi} \le \mathit{len1} + \mathit{len2} - 1, writes \mathit{nhi} - \mathit{nlo} coefficients and does not allow aliasing. The non-underscore version accepts any 0 \le \mathit{nlo} \le \mathit{nhi}.

Full documentation

Classical multiplication#

void _nmod_poly_mul_classical(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, nmod_t mod)
void nmod_poly_mul_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)

Set res to the product by the classical algorithm, with O(\mathit{len1} \cdot \mathit{len2}) operations. The underscore version requires \mathit{len1} \ge \mathit{len2} \ge 1 and does not allow aliasing.

More
void _nmod_poly_mullow_classical(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong trunc, nmod_t mod)
void nmod_poly_mullow_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc)

Set res to the product modulo x^{\mathit{trunc}} by the classical algorithm. The underscore version requires \mathit{len1} \ge \mathit{len2} \ge 1 and 1 \le \mathit{trunc} \le \mathit{len1} + \mathit{len2} - 1, and does not allow aliasing.

void _nmod_poly_mulhigh_classical(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong start, nmod_t mod)
void nmod_poly_mulhigh_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong start)

Set the coefficients of res from index start on to those of the product, by the classical algorithm, and the coefficients below start to zero. The underscore version requires \mathit{len1} \ge \mathit{len2} \ge 1, writes \mathit{len1} + \mathit{len2} - 1 coefficients and does not allow aliasing.

void _nmod_poly_mulmid_classical(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong nlo, slong nhi, nmod_t mod)
void nmod_poly_mulmid_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong nlo, slong nhi)

Set res to the coefficients \mathit{nlo}, \ldots, \mathit{nhi} - 1 of the product by the classical algorithm, with the same conventions as _nmod_poly_mulmid and nmod_poly_mulmid.

Kronecker substitution#

Kronecker substitution evaluates both polynomials at a power of two 2^b, with b large enough that the coefficients of the product do not overlap, multiplies the resulting integers and reads off the coefficients. KS2 evaluates at 2^b and -2^b and KS4 also at 2^{-b} and -2^{-b}, which halves, respectively quarters, the size of each integer product [Har2009a]. All three variants read their inputs completely before writing the output, so the output may be the same array as an input.

AlgorithmKronecker substitutionMultiplies polynomials over \mathbb{Z}/n\mathbb{Z} by packing their coefficients into large integers, multiplying the integers and unpacking; Harvey's KS2 and KS4 variants evaluate at ±2^b and ±2^(-b) to split the integer product into two or four smaller ones.
void _nmod_poly_mul_KS(nn_ptr out, nn_srcptr in1, slong len1, nn_srcptr in2, slong len2, nmod_t mod)
void nmod_poly_mul_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)

Set res to the product by Kronecker substitution. The underscore version requires \mathit{len1}, \mathit{len2} \ge 1 in either order.

More
void _nmod_poly_mullow_KS(nn_ptr out, nn_srcptr in1, slong len1, nn_srcptr in2, slong len2, slong n, nmod_t mod)
void nmod_poly_mullow_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n)

Set res to the product modulo x^n by Kronecker substitution. The underscore version requires \mathit{len1}, \mathit{len2} \ge 1 and 1 \le n \le \mathit{len1} + \mathit{len2} - 1. It multiplies the operands truncated to length n in full and unpacks the low n coefficients.

void _nmod_poly_mulmid_KS(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong nlo, slong nhi, nmod_t mod)
void nmod_poly_mulmid_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong nlo, slong nhi)

Set res to the coefficients \mathit{nlo}, \ldots, \mathit{nhi} - 1 of the product by Kronecker substitution, with the same conventions as _nmod_poly_mulmid and nmod_poly_mulmid, except that the output may alias the inputs.

void _nmod_poly_mul_KS2(nn_ptr res, nn_srcptr op1, slong n1, nn_srcptr op2, slong n2, nmod_t mod)
void nmod_poly_mul_KS2(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)

Set res to the product by Kronecker substitution at 2^b and -2^b [Har2009a]. The underscore version requires \mathit{n1} \ge \mathit{n2} \ge 1.

More
void _nmod_poly_mul_KS4(nn_ptr res, nn_srcptr op1, slong n1, nn_srcptr op2, slong n2, nmod_t mod)
void nmod_poly_mul_KS4(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)

Set res to the product by Kronecker substitution at \pm 2^b and at the reciprocal points \pm 2^{-b} [Har2009a]. The underscore version requires \mathit{n1} \ge \mathit{n2} \ge 1.

More

FFT multiplication#

These functions call the small-prime FFT of fft_small (fft_small.h), which multiplies modulo one to several 50-bit primes and reconstructs the coefficients modulo n by the Chinese remainder theorem (Multiplication with several primes and CRT). They exist only when FLINT is built with fft_small (FLINT_HAVE_FFT_SMALL); otherwise _nmod_poly_mulmid_fft_small and _nmod_poly_mullow_fft_small throw an exception and the want functions return 0.

Write the coefficients \mathit{znlo}, \ldots, \mathit{zn} - 1 (respectively 0, \ldots, \mathit{zn} - 1) of the product of (a, an) and (b, bn) to z, using fft_small. Require \mathit{an}, \mathit{bn} \ge 1, in either order, and 0 \le \mathit{znlo} < \mathit{zn} \le \mathit{an} + \mathit{bn} - 1; the output must not overlap the inputs.

More
int _nmod_poly_mullow_want_fft_small(slong len1, slong len2, slong n, int squaring, nmod_t mod)

Return whether fft_small is expected to be the fastest algorithm for a product of lengths len1 and len2 truncated to length n (a full product if n = \mathit{len1} + \mathit{len2} - 1), respectively for m coefficients of a middle product whose shorter operand, after trimming, has length len2.

More

Internal helper of _nmod_poly_mulmid_fft_small for n \le 23: if the coefficients are small enough, writes the coefficients \mathit{znlo}, \ldots, \mathit{zn} - 1 of the product to z and returns 1; otherwise returns 0 without writing anything. The conditions on the arguments are those of _nmod_poly_mulmid_fft_small.

More

Powering#

void _nmod_poly_pow(nn_ptr res, nn_srcptr poly, slong len, ulong e, nmod_t mod)
void nmod_poly_pow(nmod_poly_t res, const nmod_poly_t poly, ulong e)

Set res to \mathit{poly}^e by binary exponentiation; the two pairs of functions are the same. The underscore versions require \mathit{len} \ge 1 and e \ge 1, write (\mathit{len} - 1) e + 1 coefficients and do not allow aliasing. nmod_poly_pow returns 1 for 0^0, but nmod_poly_pow_binexp returns 0.

More
void _nmod_poly_pow_trunc(nn_ptr res, nn_srcptr poly, ulong e, slong trunc, nmod_t mod)
void nmod_poly_pow_trunc(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc)

Set res to \mathit{poly}^e \bmod x^{\mathit{trunc}} by binary exponentiation with truncated products; the two pairs of functions are the same. The underscore versions read exactly trunc coefficients of poly (zero-pad shorter inputs), require \mathit{trunc} \ge 1 and e \ge 1, write trunc coefficients and do not allow aliasing.

More

Division#

Division with remainder by B requires the leading coefficient of B to be invertible modulo n; otherwise FLINT_IMPINV is thrown. Division by the zero polynomial throws FLINT_DIVZERO, except modulo n = 1, where nmod_poly_divrem, nmod_poly_div and nmod_poly_divexact return Q = A and R = 0. Short quotients are computed by schoolbook division; long ones by Newton iteration on the reversed polynomials, which costs a constant number of multiplications. Division with remainder compares the functions and gives examples.

AlgorithmNewton iteration for power series and divisionInverse, quotient, square root, reciprocal square root, exponential and logarithm of power series by Newton iteration with middle products and the Karp–Markstein trick, and polynomial division with remainder via reversed polynomials, as implemented for nmod_poly.

Set Q and R to the quotient and remainder of A by B, so that A = BQ + R with \deg R < \deg B. The underscore version requires \mathit{lenA} \ge \mathit{lenB} \ge 1 and writes \mathit{lenA} - \mathit{lenB} + 1 coefficients to Q and \mathit{lenB} - 1 to R. R may be the same array as A; otherwise the outputs must not overlap each other or the inputs.

Full documentation
void _nmod_poly_div(nn_ptr Q, nn_srcptr A, slong lenA, nn_srcptr B, slong lenB, nmod_t mod)

Set Q to the quotient of A by B without computing the remainder. The underscore version requires \mathit{lenA} \ge \mathit{lenB} \ge 1, writes \mathit{lenA} - \mathit{lenB} + 1 coefficients and does not allow aliasing.

Full documentation
void _nmod_poly_rem(nn_ptr R, nn_srcptr A, slong lenA, nn_srcptr B, slong lenB, nmod_t mod)

Set R to the remainder of A by B. The underscore version requires \mathit{lenA} \ge \mathit{lenB} \ge 1, writes \mathit{lenB} - 1 coefficients and does not allow aliasing. Quotients of length 2, the typical step of the Euclidean algorithm, use a dedicated routine. nmod_poly_rem throws FLINT_DIVZERO for B = 0 even modulo 1.

Full documentation

Set Q to A / B, assuming that B divides A; otherwise the result is meaningless. The underscore version requires \mathit{lenA} \ge \mathit{lenB} \ge 1, writes \mathit{lenA} - \mathit{lenB} + 1 coefficients and does not allow aliasing.

Full documentation

Set Q to the quotient of A by x - c and return the remainder A(c), by Horner's rule (synthetic division). The value c must be reduced. The underscore version requires \mathit{len} \ge 2 (for smaller lengths it returns 0 and writes nothing), writes \mathit{len} - 1 coefficients and allows Q == A.

If B divides A, set Q = A / B and return 1; otherwise set Q = 0 and return 0. The zero polynomial divides only itself. The underscore versions require \mathit{lenA} \ge \mathit{lenB} \ge 1, write \mathit{lenA} - \mathit{lenB} + 1 coefficients and do not allow aliasing.

Full documentation

Removes the largest power p^k dividing f from f and returns k. Requires \deg p \ge 1: for a nonzero constant p the function does not terminate. For f = 0 it returns 0.

Division with remainder by the schoolbook algorithm, with the same conventions as _nmod_poly_divrem and nmod_poly_divrem.

More

Set Q to the quotient of A by B, given the power series inverse Binv of the reversal of B (see Computing modulo a fixed polynomial). The quotient is the reversal of \operatorname{rev}(A) \cdot \mathit{Binv} \bmod x^{\mathit{lenQ}}, so Binv must be correct modulo x^{\mathit{lenQ}}, \mathit{lenQ} = \mathit{lenA} - \mathit{lenB} + 1. The underscore version requires \mathit{lenA} \ge \mathit{lenB} \ge 1, does not read B, and does not allow Q to overlap Binv.

More

Set Q and R to the quotient and remainder of A by B, given Binv as for nmod_poly_div_newton_n_preinv; the remainder is A - BQ computed by a short product. The underscore version requires \mathit{lenA} \ge \mathit{lenB} \ge 1 and does not allow the outputs to overlap the inputs.

More

Power series inversion and division#

These functions compute with power series truncated to length n, that is, modulo x^n. The constant term of the divisor must be invertible modulo n; otherwise FLINT_IMPINV is thrown. For long series they use Newton iteration, which costs a small constant number of multiplications of length n. See Power series inversion and division.

Set Qinv to the inverse of the power series Q modulo x^n, that is, Q \cdot \mathit{Qinv} \equiv 1 \pmod{x^n}. The underscore version requires \mathit{Qlen} \ge 1 and n \ge 1, writes n coefficients and does not allow aliasing; Q may be longer than n. The non-underscore version throws FLINT_DIVZERO if Q = 0 or n = 0.

Full documentation

The same, by the O(n \min(n, \mathit{Qlen})) recurrence q_0 = Q_0^{-1}, q_i = -q_0 \sum_{j \ge 1} Q_j q_{i-j}, with each sum computed as a dot product. A binomial Q_0 + c x^k is inverted directly as a geometric series.

Full documentation

The same as _nmod_poly_inv_series and nmod_poly_inv_series, of which they are aliases; they use Newton iteration only when the length makes it faster.

Full documentation

Set Q to A / B \bmod x^n, so that BQ \equiv A \pmod{x^n}. The underscore version requires \mathit{Alen}, \mathit{Blen}, n \ge 1, writes n coefficients and does not allow aliasing. The non-underscore version throws FLINT_DIVZERO if n = 0, B = 0 or B_0 = 0.

Full documentation

The same by the O(n \min(n, \mathit{Blen})) recurrence q_i = B_0^{-1} (A_i - \sum_{j \ge 1} B_j q_{i-j}).

Full documentation

Arithmetic modulo a polynomial#

These functions compute in (\mathbb{Z}/n\mathbb{Z})[x]/(f) for a nonzero f whose leading coefficient is invertible. Elements are represented by their remainders, polynomials of length less than \mathit{lenf}; the underscore functions usually require them to be zero-padded to length exactly \mathit{lenf} - 1. The _preinv variants take the power series inverse finv of the reversal of f, computed once with nmod_poly_inv_series(finv, rev(f), lenf), which turns every reduction into two products. The guide Computing modulo a fixed polynomial explains these conventions; Exponentiation modulo a polynomial covers exponentiation.

void _nmod_poly_mulmod(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, nn_srcptr f, slong lenf, nmod_t mod)
void nmod_poly_mulmod(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f)

Set res to \mathit{poly1} \cdot \mathit{poly2} \bmod f, computed as a product followed by _nmod_poly_divrem. The underscore version requires \mathit{len1}, \mathit{len2} \ge 1 and \mathit{len1} + \mathit{len2} - 1 \ge \mathit{lenf} (otherwise there is nothing to reduce; use _nmod_poly_mul), writes \mathit{lenf} - 1 coefficients and does not allow res to overlap f. The non-underscore version accepts inputs of any length and throws FLINT_ERROR for f = 0.

void _nmod_poly_mulmod_preinv(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, nn_srcptr f, slong lenf, nn_srcptr finv, slong lenfinv, nmod_t mod)
void nmod_poly_mulmod_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f, const nmod_poly_t finv)

Set res to \mathit{poly1} \cdot \mathit{poly2} \bmod f, reducing with _nmod_poly_divrem_newton_n_preinv and the precomputed finv. Both factors must be reduced modulo f: the non-underscore version throws FLINT_ERROR if \mathit{len1} \ge \mathit{lenf} or \mathit{len2} \ge \mathit{lenf}. The underscore version also requires \mathit{len1}, \mathit{len2} \ge 1 and \mathit{len1} + \mathit{len2} - 1 \ge \mathit{lenf}, writes \mathit{lenf} - 1 coefficients and does not allow res to overlap f or finv.

int _nmod_poly_invmod(ulong * A, const ulong * B, slong lenB, const ulong * P, slong lenP, const nmod_t mod)

If B is invertible modulo P, set A to its inverse and return 1; otherwise return 0, leaving A undefined. Requires a prime modulus. The non-underscore version reduces B modulo P first, returns 0 for B = 0 and throws FLINT_ERROR if \mathit{lenP} < 2. The underscore version requires 1 \le \mathit{lenB} < \mathit{lenP} (zero padding of B is allowed), writes \mathit{lenP} - 1 coefficients and does not allow aliasing. It calls the extended Euclidean algorithm _nmod_poly_gcdinv.

Set res to \mathit{poly}^e \bmod f by left-to-right binary exponentiation, reducing each product with _nmod_poly_divrem. The non-underscore versions accept any poly (reducing it first) and e \ge 0, and throw FLINT_ERROR for f = 0. The underscore versions require \mathit{lenf} \ge 2, poly reduced and zero-padded to length \mathit{lenf} - 1, and e \ge 1; they write \mathit{lenf} - 1 coefficients and do not allow aliasing.

Full documentation

The same with a precomputed finv, reducing with _nmod_poly_divrem_newton_n_preinv. These are the functions to use for large f or many exponentiations modulo the same f.

Full documentation

Set res to x^e \bmod f, given finv. They use sliding-window exponentiation in which a multiplication by x^w is a shift followed by a reduction, so each window costs one reduction instead of a full multiplication. The underscore versions require \mathit{lenf} \ge 3 and e \ge 1 and write \mathit{lenf} - 1 coefficients; the non-underscore versions accept e \ge 0 and any nonzero f.

Full documentation
void _nmod_poly_powers_mod_preinv_naive(nn_ptr * res, nn_srcptr f, slong flen, slong n, nn_srcptr g, slong glen, nn_srcptr ginv, slong ginvlen, const nmod_t mod)

Set res[i] to f^i \bmod g for 0 \le i < n, computing f^i as f^{\lfloor i/2 \rfloor} f^{\lceil i/2 \rceil}. The non-underscore version takes an array of n initialised polynomials, reduces f first, and throws FLINT_ERROR for g = 0; for f = 0 or constant g it sets res[0] to 1 and the others to 0. The underscore version requires 1 \le \mathit{flen} < \mathit{glen}, ginv as for _nmod_poly_mulmod_preinv, and n arrays of \mathit{glen} - 1 coefficients, all of which are written.

void _nmod_poly_powers_mod_preinv_threaded_pool(nn_ptr * res, nn_srcptr f, slong flen, slong n, nn_srcptr g, slong glen, nn_srcptr ginv, slong ginvlen, const nmod_t mod, thread_pool_handle * threads, slong num_threads)
void _nmod_poly_powers_mod_preinv_threaded(nn_ptr * res, nn_srcptr f, slong flen, slong n, nn_srcptr g, slong glen, nn_srcptr ginv, slong ginvlen, const nmod_t mod)

The same as the naive functions, computed with baby steps and giant steps in parallel: with k = \lfloor \sqrt{n} \rfloor, the powers f^0, \ldots, f^k and f^{2k}, f^{3k}, \ldots are computed first, and then the threads fill in f^{ik + j} = f^{ik} f^j, taking blocks of k powers from a shared counter. _nmod_poly_powers_mod_preinv_threaded and nmod_poly_powers_mod_bsgs take their threads from the global pool (see thread_pool.h), the _pool version uses the num_threads threads given.

Preconditioned modular multiplication#

When many products ab \bmod d are needed with the same a and d, data depending on a can be precomputed so that each product is cheaper than nmod_poly_mulmod_preinv. Two methods are available. The matrix method stores the n \times n matrix of multiplication by a, whose column i is a x^i \bmod d, n = \deg d, and computes ab \bmod d as a matrix-vector product; for small moduli several entries are packed into one word. It costs O(n^2) but is very fast for n up to a few hundred. The Shoup method stores the quotient \lfloor a x^n / d \rfloor; then the quotient of ab by d is the high part of a short product, and ab \bmod d costs three short products instead of four, by the polynomial analogue of Shoup multiplication [Sho1995].

Precomputed data for multiplication by a fixed a modulo a fixed d. It stores shallow references to a, d and the inverse of d, which must stay alive and unchanged while it is used.

The methods: no precomputation (_nmod_poly_mulmod_preinv is called), Shoup's method, and the matrix method.

Initialise precond for multiplication by a modulo d with the given method. Require a reduced modulo d (\mathit{alen} < \mathit{dlen}) and dinv the power series inverse of the reversal of d, as for nmod_poly_mulmod_preinv; the matrix method only reads dinv[0]. An invalid method throws FLINT_ERROR.

Like the init_method functions, but choose the method expected to be fastest for num multiplications.

More

Frees the memory used by precond.

Set res to ab \bmod d for the a and d of precond. Require b reduced modulo d. The underscore version requires \mathit{alen}, \mathit{blen} \ge 1, writes \deg d coefficients (zero-padded) and does not allow res to overlap b, a or d. The non-underscore version allows res to be b, but not a.

Greatest common divisor#

All GCD functions require a prime modulus (not checked); a non-invertible leading coefficient met by the Euclidean or the half-GCD algorithm throws FLINT_IMPINV. The non-underscore functions return the monic GCD, with \gcd(0, 0) = 0, and accept their inputs in any order. Below a cutoff that depends on the bit size of n the Euclidean algorithm is used, for moduli of \mathtt{FLINT\_BITS}/2 to \mathtt{FLINT\_BITS} - 2 bits and \mathit{lenB} \ge 32 in Montgomery arithmetic; above it the half-GCD algorithm [ThullYap1990] computes the GCD in O(M(n) \log n) operations. See Greatest common divisors.

AlgorithmHalf-GCDThe half-gcd algorithm computes the quotients of the first half of the Euclidean remainder sequence from the top halves of the inputs, recursively, giving GCDs, extended GCDs and resultants in O(M(n) \log n) operations; with a correctness proof and FLINT's cutoffs for nmod_poly.

Set G to a greatest common divisor of A and B. The underscore version requires \mathit{lenA} \ge \mathit{lenB} \ge 1, writes at most \mathit{lenB} coefficients, returns the length of G, does not make G monic and does not allow aliasing.

Full documentation

The GCD by the Euclidean algorithm, with the conventions of _nmod_poly_gcd and nmod_poly_gcd. Each step is a call to _nmod_poly_rem, so the cost is O(\mathit{lenA} \cdot \mathit{lenB}).

The Euclidean algorithm in Montgomery arithmetic (nmod_redc_fast, see nmod.h), after a first remainder in the ordinary representation. Require an odd prime modulus n < 2^{\mathtt{FLINT\_BITS} - 2}, which is not checked.

The condition under which _nmod_poly_gcd and _nmod_poly_resultant use the Montgomery version of the Euclidean algorithm: \mathit{lenB} \ge 32 and \mathtt{FLINT\_BITS}/2 \le NMOD_BITS(mod) \le \mathtt{FLINT\_BITS} - 2. It does not check that n is odd, so an even modulus in this range gives an exception or a crash; such moduli are not prime and therefore not supported anyway.

The GCD by the half-GCD algorithm, with the conventions of _nmod_poly_gcd and nmod_poly_gcd. Its complexity is O(M(n) \log n), where M(n) is the cost of a multiplication of length n.

More
slong _nmod_poly_hgcd(nn_ptr * M, slong * lenM, nn_ptr A, slong * lenA, nn_ptr B, slong * lenB, nn_srcptr a, slong lena, nn_srcptr b, slong lenb, nmod_t mod)

The half-GCD step. For \deg a > \deg b, compute consecutive remainders A, B of the Euclidean remainder sequence of a, b with \deg A \ge \deg(a)/2 > \deg B and the matrix

M = \begin{pmatrix} m_{11} & m_{12} \\ m_{21} & m_{22} \end{pmatrix}, \qquad \begin{pmatrix} a \\ b \end{pmatrix} = M \begin{pmatrix} A \\ B \end{pmatrix},

the product of the matrices \left(\begin{smallmatrix} q_i & 1 \\ 1 & 0 \end{smallmatrix}\right) for the quotients q_i of these steps. Return \det M = \pm 1.

Full documentation

A reference implementation of nmod_poly_hgcd by repeated division with remainder, for testing. Same contract; no aliasing is allowed.

Return the tuned cutoffs for the bit size of the modulus: the length below which the half-GCD recursion uses Euclidean steps (60 to 244), the length below which the outer loop of the half-GCD GCD switches to the Euclidean algorithm (310 to 1585), and the length of B from which _nmod_poly_gcd (470 to 2199) and _nmod_poly_xgcd (72 to 388) use the half-GCD algorithm.

Compute the GCD G of A and B and cofactors S, T with SA + TB = G. The non-underscore version makes G monic; for B \ne 0 the cofactors satisfy \deg S < \max(\deg B - \deg G, 1) and \deg T < \max(\deg A - \deg G, 1), and for B = 0 it returns S = \operatorname{lc}(A)^{-1}, T = 0. G, S and T must be distinct objects.

Full documentation

The extended GCD by the Euclidean and by the half-GCD algorithm, with the conventions of _nmod_poly_xgcd and nmod_poly_xgcd.

slong _nmod_poly_gcdinv(ulong * G, ulong * S, const ulong * A, slong lenA, const ulong * B, slong lenB, const nmod_t mod)

Compute G = \gcd(A, B) and S with G \equiv SA \pmod B and \deg S < \deg B - \deg G, without the cofactor of B. If \gcd(A, B) = 1, then S = A^{-1} \bmod B. The non-underscore version requires \mathit{lenB} \ge 2 (otherwise it throws FLINT_ERROR), reduces A modulo B first, makes G monic and returns G = S = 0 if B divides A. The underscore version requires 1 \le \mathit{lenA} < \mathit{lenB}, writes at most lenA coefficients to G and \mathit{lenB} - 1 to S, returns the length of G and does not make G monic.

Full documentation

Resultant and discriminant#

The resultant of f = a \prod_{i=1}^{m} (x - \alpha_i) and g = b \prod_{j=1}^{k} (x - \beta_j) is

\operatorname{res}(f, g) = a^{k} b^{m} \prod_{i,j} (\alpha_i - \beta_j) = a^{k} \prod_{i} g(\alpha_i),

the determinant of the Sylvester matrix. It is zero exactly when f and g have a common factor. These functions require a prime modulus (not checked) and return 0 if either polynomial is zero. See Resultants and discriminants.

Return \operatorname{res}(f, g). The underscore version requires \mathit{len1} \ge \mathit{len2} \ge 1.

Full documentation

The resultant by the Euclidean algorithm, using \operatorname{res}(f, g) = (-1)^{\deg f \deg g} \operatorname{lc}(g)^{\deg f - \deg r} \operatorname{res}(g, r) for r = f \bmod g.

Full documentation

The resultant by the half-GCD algorithm, in O(M(n) \log n) operations.

Full documentation

Return the discriminant of f of degree d,

\operatorname{disc}(f) = (-1)^{d(d-1)/2} \operatorname{lc}(f)^{-1} \operatorname{res}(f, f') = \operatorname{lc}(f)^{2d - 2} \prod_{i < j} (\alpha_i - \alpha_j)^2,

where the power of \operatorname{lc}(f) is adjusted if \deg f' < d - 1 (when the characteristic divides d). The discriminant is 0 for constants and when f' = 0. The underscore version requires \mathit{len} \ge 2.

Full documentation

Derivative and integral#

Set x_prime to the derivative of x. The underscore version requires \mathit{len} \ge 1, writes \mathit{len} - 1 coefficients and allows x_prime == x.

Set x_int to the integral of x with constant term 0. The integers 1, \ldots, \deg x + 1 must be invertible modulo n, for example n prime and n > \deg x + 1; otherwise FLINT_IMPINV is thrown. Here len is the length of the output: the underscore version reads \mathit{len} - 1 coefficients, writes len coefficients, requires \mathit{len} \ge 1 and allows x_int == x. It needs only one modular inversion.

Evaluation#

Return \mathit{poly}(c) for reduced c. Any length, including 0, is allowed.

More

Return \mathit{poly}(c) by Horner's rule, and by rectangular splitting: with m = \min(\lfloor\sqrt{\mathit{len}}\rfloor + 1, 1024), the powers c, \ldots, c^m are computed once, each block of m coefficients is evaluated by a dot product (see Computing dot products), and the blocks are combined by Horner's rule in c^m. The dot products accumulate without intermediate reductions, which makes rectangular splitting faster than Horner's rule for long polynomials although it does the same number of multiplications.

Evaluate poly at c modulo modn by Horner's rule with Shoup multiplication, given c_precomp = n_mulmod_precomp_shoup(c, modn). Require c < \mathit{modn} < 2^{\mathtt{FLINT\_BITS} - 1}.

More

Set dest to the matrix \mathit{poly}(c), for a square matrix c with the modulus of poly; dest must have the same dimensions and may be c. The Horner version uses \deg(\mathit{poly}) matrix multiplications, the Paterson–Stockmeyer version [PS1973] about 2\sqrt{\deg} matrix multiplications and O(\deg) scalar multiply-adds. nmod_poly_evaluate_mat uses Horner's rule if \mathit{len} < 5 or \mathit{len} \cdot r < 425 for an r \times r matrix, and Paterson–Stockmeyer otherwise.

More

Sets dest to \mathit{mat} + cI for a square matrix mat and reduced c, the step of Horner's rule above. dest may be mat.

Multipoint evaluation and interpolation#

Evaluating a polynomial of length n at n points, or interpolating through n points, takes O(n^2) operations with Horner's rule or Lagrange interpolation, and O(M(n) \log n) operations with a subproduct tree: the products \prod (x - x_i) over the leaves of a binary tree on the points. Evaluation reduces the polynomial down the tree, interpolation combines the values up the tree. Interpolation needs the x_i to be distinct, with invertible differences (for example, n prime). See Multipoint evaluation and interpolation.

AlgorithmMultipoint evaluation and interpolationEvaluation of a polynomial at many points and interpolation through many points in O(M(n) \log n) operations with the subproduct tree and the remainder tree, and in O(M(n)) for points in geometric progression with Bluestein's chirp transform and the method of Bostan and Schost.

Set ys[i] to \mathit{poly}(\mathit{xs}[i]) for 0 \le i < \mathit{olen}, for reduced points. Polynomials of length less than 32 are evaluated point by point with _nmod_poly_evaluate_nmod, longer ones with a subproduct tree.

Full documentation

The same, evaluating at each point with _nmod_poly_evaluate_nmod.

The same with a temporary subproduct tree.

Full documentation
void _nmod_poly_evaluate_nmod_vec_fast_precomp(nn_ptr vs, nn_srcptr poly, slong ilen, const nn_ptr * tree, slong olen, nmod_t mod)

Evaluates (poly, ilen) at the olen points of the subproduct tree tree, built with _nmod_poly_tree_build. The polynomial may be longer or shorter than the number of points; it is first reduced modulo the products at the highest useful level of the tree, and the remainders are then reduced down the tree.

Allocate and free a subproduct tree for len points. For len = 0, _nmod_poly_tree_alloc returns NULL.

void _nmod_poly_tree_build(nn_ptr * tree, nn_srcptr roots, slong len, nmod_t mod)

Builds the subproduct tree of the monic linear factors x - r_i, 0 \le i < \mathit{len}, in the space allocated by _nmod_poly_tree_alloc.

Full documentation

Sets w[i] to the barycentric weight 1 / \prod_{j \ne i} (x_i - x_j) = 1 / P'(x_i), where P = \prod_j (x - x_j) for the points of tree.

Sets (poly, len) to the polynomial of length at most len taking the values ys at the points of tree, given the weights from _nmod_poly_interpolation_weights, by combining the scaled values y_i w_i up the tree (fast Lagrange interpolation). Writes len coefficients.

Set poly to the unique polynomial of length at most len with \mathit{poly}(x_i) = y_i for 0 \le i < \mathit{len}. The points must be distinct and all values reduced. Uses the Newton form for \mathit{len} < 6, the barycentric form for \mathit{len} < 16 and fast interpolation otherwise. The underscore version requires \mathit{len} \ge 1, writes len coefficients and does not allow poly to overlap xs or ys.

Full documentation

The same by fast Lagrange interpolation with a temporary subproduct tree, in O(M(\mathit{len}) \log \mathit{len}) operations.

Full documentation

The same by divided differences, followed by a conversion from the Newton basis to the monomial basis. It uses O(\mathit{len}^2) multiplications and O(\mathit{len}^2) modular inversions.

The same by the Lagrange formula \sum_i y_i w_i P(x)/(x - x_i), with P = \prod (x - x_i) and w_i as above, in O(\mathit{len}^2) multiplications and len inversions.

Set poly to \prod_{i=0}^{n-1} (x - x_i), for reduced x_i. The underscore version writes n + 1 coefficients and does not allow aliasing. Uses the quadratic algorithm for n < 20 and balanced products above.

Geometric progressions#

Evaluation and interpolation at the points of a geometric progression 1, q, q^2, \ldots cost O(M(n)) instead of O(M(n) \log n): evaluation is a single middle product by Bluestein's chirp transform [Blu1970] [RSR1969], using ij = \binom{i+j}{2} - \binom{i}{2} - \binom{j}{2}, and interpolation is two products [BS2005]. The functions take r with q = r^2, so that q^{i^2/2} = r^{i^2} needs no square root, and use the points 1, r^2, r^4, \ldots. The value r must be reduced and invertible modulo n. For interpolation and extrapolation the points must be distinct with r^{2k} - 1 invertible, which for prime n means that the multiplicative order of r^2 exceeds the number of points. See Geometric progressions.

Precomputed data for evaluation, interpolation and extrapolation at the points 1, r^2, \ldots, r^{2(\mathit{len} - 1)}: scaling vectors, the polynomials to multiply by and, optionally, their fft_small transforms. The functions using it only read it, so several threads can use one progression at the same time.

Initialise G for the points 1, r^2, \ldots, r^{2(\mathit{len}-1)}. len must be at least the number of points and at least the length of the polynomials used. nmod_geometric_progression_init prepares evaluation, interpolation and extrapolation; the second function only the functionalities selected by the bits of function: bit 0 evaluation, bit 1 interpolation, bit 2 extrapolation, and bit 3 stored transforms.

More

Stores the fft_small transforms described above for the functionalities of G, with a separate bound, at most G->len, for each: evaluation of polynomials of length at most ev_len, interpolation from at most int_len points, and extrapolation from at most ext_len values. A bound 0 removes the stored transforms of the functionality and a negative bound keeps them unchanged. Smaller bounds give shorter transforms for evaluation (\mathit{ev\_len} + \mathit{len} - 1 instead of 2 \mathit{len} - 1) and interpolation (about 2\,\mathit{int\_len}), and may need fewer primes; the extrapolation transforms have length \mathit{len} - 1 whatever ext_len, which only bounds the number of primes. Longer inputs remain possible without the stored transforms. Must not be called while other threads use G.

Sets vs[i] to \mathit{poly}(r^{2i}) for 0 \le i < \mathit{olen}, using G prepared for evaluation. Requires \mathit{ilen}, \mathit{olen} \le G->len.

More

The same with a temporary precomputation for evaluation.

The same by evaluating at each point with _nmod_poly_evaluate_nmod. No condition on r.

Set poly to the polynomial of length at most len taking the values v[i] at r^{2i}, 0 \le i < \mathit{len}, using G prepared for interpolation. Requires 1 \le \mathit{len} \le G->len. The underscore version writes len coefficients and does not allow poly to overlap v.

More

The same with a temporary precomputation for interpolation.

void nmod_poly_extrapolate_geometric(nn_ptr oval, slong olen, nn_srcptr ival, slong ilen, slong offset, ulong r, nmod_t mod)

Given the values ival of a polynomial f of degree less than \mathit{ilen} at ilen consecutive points of the progression, compute its values oval at olen consecutive points starting offset positions later, without computing f. The points must not overlap: \mathit{offset} \ge \mathit{ilen} (forward) or \mathit{offset} + \mathit{olen} \le 0 (backward).

More

Composition#

Composition f(g) and the Taylor shift f(x + c); see Composition and Taylor shifts.

void _nmod_poly_compose(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, nmod_t mod)
void nmod_poly_compose(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)

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

Full documentation
void _nmod_poly_compose_horner(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, nmod_t mod)
void nmod_poly_compose_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2)

The composition by Horner's rule, with the conventions of _nmod_poly_compose.

Full documentation

Set g(x) = f(x + c), for reduced c; the underscore version works in place on (poly, len). Uses Horner's rule for \mathit{len} < 100 or \mathit{len} > n, and for c = \pm 1 and \mathit{len} < 1000, and the convolution method otherwise, which requires (\mathit{len} - 1)! to be invertible modulo n (for prime n, guaranteed by \mathit{len} \le n); otherwise FLINT_IMPINV is thrown.

Full documentation

The Taylor shift by Horner's rule, with O(\mathit{len}^2) additions and multiplications. Works for every modulus.

Full documentation

The Taylor shift as one product of length len, using \sum_k f_k (x + c)^k = \sum_j \frac{x^j}{j!} \sum_k k!\, f_k \frac{c^{k-j}}{(k-j)!} [ASU1975] [GG1997], in O(M(\mathit{len})) operations. Requires (\mathit{len} - 1)! to be invertible modulo n.

Full documentation

Modular composition#

Modular composition computes f(g) \bmod h. By the algorithm of Brent and Kung [BrentKung1978] it costs O(n^{1/2} M(n) + n^{(\omega + 1)/2}) operations for \deg h = n, using a matrix product of size \sqrt{n} \times \sqrt{n} by \sqrt{n} \times n. With m = \lfloor \sqrt n \rfloor + 1, the m \times n matrix A holding g^0, \ldots, g^{m-1} \bmod h in its rows can be precomputed and reused for many f. All functions require h \ne 0 with invertible leading coefficient and allow res to be any input (the non-underscore versions). See Modular composition.

AlgorithmComposition and modular compositionComputing f(g), f(g) \bmod x^n and f(g) \bmod h by Horner's rule, divide and conquer, Taylor shifts, the baby-step giant-step method of Brent and Kung, and the algorithm of Kinoshita and Li, with the choices made by nmod_poly.

Set res to f(g) \bmod h. The non-underscore version accepts any f and g and throws FLINT_DIVZERO for h = 0. The underscore version requires \mathit{lenh} \ge 2, \mathit{lenf} \ge 1 and g reduced and zero-padded to length \mathit{lenh} - 1, writes \mathit{lenh} - 1 coefficients and does not allow aliasing. It uses Horner's rule if \mathit{lenh} < 8 or \mathit{lenf} \ge \mathit{lenh}, and the Brent–Kung algorithm otherwise.

Full documentation

Modular composition by Horner's rule, with \mathit{lenf} - 1 multiplications modulo h, and the conventions of _nmod_poly_compose_mod.

Full documentation

Modular composition by the Brent–Kung algorithm, with the conventions of _nmod_poly_compose_mod. Requires \mathit{lenf} < \mathit{lenh} (\deg f < \deg h); the non-underscore version throws FLINT_ERROR otherwise.

Full documentation
void _nmod_poly_compose_mod_brent_kung_preinv(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, nn_srcptr poly3, slong len3, nn_srcptr poly3inv, slong len3inv, nmod_t mod)
void nmod_poly_compose_mod_brent_kung_preinv(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly3, const nmod_poly_t poly3inv)

Set res to \mathit{poly1}(\mathit{poly2}) \bmod \mathit{poly3} by the Brent–Kung algorithm, given the inverse poly3inv of the reversal of poly3 as for nmod_poly_mulmod_preinv. Requires \mathit{len1} < \mathit{len3}; the underscore version also requires poly2 reduced and zero-padded to length \mathit{len3} - 1.

Full documentation
void _nmod_poly_precompute_matrix(nmod_mat_t A, nn_srcptr poly1, nn_srcptr poly2, slong len2, nn_srcptr poly2inv, slong len2inv, nmod_t mod)
void nmod_poly_precompute_matrix(nmod_mat_t A, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly2inv)

Set the rows of the m \times n matrix A to \mathit{poly1}^i \bmod \mathit{poly2} for 0 \le i < m, where n = \deg \mathit{poly2} and m = \lfloor \sqrt{n} \rfloor + 1, given the inverse poly2inv of the reversal of poly2. A must be initialised with these dimensions (the non-underscore version throws FLINT_ERROR otherwise). The underscore version requires poly1 reduced and zero-padded to length n.

Full documentation
void _nmod_poly_compose_mod_brent_kung_precomp_preinv(nn_ptr res, nn_srcptr poly1, slong len1, const nmod_mat_t A, nn_srcptr poly3, slong len3, nn_srcptr poly3inv, slong len3inv, nmod_t mod)

Set res to \mathit{poly1}(g) \bmod \mathit{poly3}, where A is the matrix computed by nmod_poly_precompute_matrix for g and poly3. Requires \mathit{len1} < \mathit{len3}. This is the function to use for many compositions with the same g and modulus, as in the computation of Frobenius powers in polynomial factorisation [GatSho1992] [KalSho1998].

Full documentation

Initialises A as an m \times n matrix, n = \deg f, m = \lfloor \sqrt n \rfloor + 1, and sets row 0 to 1 and row i to row i of B reduced modulo f for 1 \le i < m. A must not be initialised before the call; B needs at least m rows and at least \deg f + 1 columns.

void _nmod_poly_mod_matrix_rows_evaluate(nn_ptr res, const nmod_mat_t A, nn_srcptr h, slong n, nn_srcptr poly3, slong len3, nn_srcptr poly3inv, slong len3inv, nmod_t mod)

Sets (res, n) to \sum_{i} A_i h^i \bmod \mathit{poly3}, where A_i is row i of the d \times n matrix A, h has length n and \mathit{len3} = n + 1. This is the last step of the Brent–Kung algorithm, with h = g^m; it uses Horner's rule for d \le 10 and rectangular splitting otherwise.

Power series composition and reversion#

void _nmod_poly_compose_series(nn_ptr res, nn_srcptr poly1, slong len1, nn_srcptr poly2, slong len2, slong n, nmod_t mod)
void nmod_poly_compose_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n)

Set res to \mathit{poly1}(\mathit{poly2}) \bmod x^n, where poly2 must have constant term 0 (the non-underscore version throws FLINT_ERROR otherwise). The underscore version requires 0 < \mathit{len1}, \mathit{len2} \le n, writes n coefficients and does not allow aliasing.

More

Set Qinv to the compositional inverse of the power series Q modulo x^n, so that Q(\mathit{Qinv}(x)) = \mathit{Qinv}(Q(x)) = x \bmod x^n. Requires Q_0 = 0 and Q_1 invertible; the non-underscore version throws FLINT_ERROR otherwise. The underscore version writes n coefficients and does not allow aliasing.

More

Square roots#

Set g to \sqrt{h} and 1/\sqrt{h} modulo x^n. The constant term of h must be a nonzero square modulo a prime n \ne 2 (it is usually 1), and its square root is chosen by nmod_sqrt; otherwise an exception is thrown. The underscore versions require \mathit{hlen}, n \ge 1, write n coefficients and do not allow aliasing.

More

If a is the square of a polynomial, set b to a square root and return 1; otherwise return 0 (and set b = 0). Requires a prime modulus. The underscore version requires \mathit{len} \ge 1, writes \mathit{len} / 2 + 1 coefficients and does not allow aliasing.

More

Power sums#

The power sums of a polynomial f with roots \alpha_1, \ldots, \alpha_d (with multiplicity, in an algebraic closure) are p_k = \sum_i \alpha_i^k. They determine f if d! is invertible, by Newton's identities k e_k = \sum_{i=1}^{k} (-1)^{i-1} e_{k-i} p_i, and can be computed in O(M(d)) operations from the series \sum_{k \ge 0} p_k x^k = d - x \tilde f'(x)/\tilde f(x), where \tilde f is the reversal of f [Sch1982b] [BFSS2006]. Here the power sum series of f is \sum_{k \ge 0} p_k x^k with p_0 = d.

Set res to \sum_{k=0}^{n-1} p_k x^k. The non-underscore version accepts any nonzero poly with invertible leading coefficient (throwing FLINT_ERROR for zero) and handles factors x^k. The underscore version requires poly monic and writes n coefficients. Uses Newton's identities for 10 n < \mathit{len} + 75 and the series formula otherwise.

The power sums by Newton's identities, in O(n \cdot \mathit{len}) operations, and by the series formula with one power series division, in O(M(n)) operations. The underscore versions require poly monic.

Set res to the monic polynomial of degree d = Q_0 whose power sum series is Q (modulo x^{\mathit{len}}, the higher power sums being determined by d of them). Requires 1, \ldots, d invertible modulo n. For Q = 0 the result is 1. The underscore version writes d + 1 coefficients. Uses Newton's identities if n \le 12 or d \le 10 and the exponential formula \tilde f = \exp(\int (d - Q)/x) otherwise.

The same by Newton's identities, in O(d^2) operations, and by the exponential formula, in O(M(d)) operations.

Elementary functions of power series#

For a power series h these functions compute f(h) \bmod x^n, where

\exp(h) = \sum_{k \ge 0} \frac{h^k}{k!}, \quad \log(h) = \int \frac{h'}{h}, \quad \operatorname{atan}(h) = \int \frac{h'}{1 + h^2}, \quad \operatorname{atanh}(h) = \int \frac{h'}{1 - h^2},
\operatorname{asin}(h) = \int \frac{h'}{\sqrt{1 - h^2}}, \quad \operatorname{asinh}(h) = \int \frac{h'}{\sqrt{1 + h^2}},

with integration constants 0, and the trigonometric and hyperbolic functions are defined by the usual relations to \exp. The constant term of h must be 1 for \log and 0 for all other functions; the non-underscore functions throw FLINT_ERROR otherwise. The coefficients involve 1/k for k < n, so the modulus must be a prime p \ge n, and also p > 2; this is not checked. All functions cost O(M(n)) operations for large n, typically with Newton iteration [HZ2004] [BZ2011], and use quadratic algorithms for small n. The underscore versions require \mathit{hlen}, n \ge 1, write n coefficients, and allow g to be the same array as h unless stated otherwise.

Set f = \exp(h) \bmod x^n.

More

Sets f = \exp(h) and g = \exp(-h) = 1/f modulo x^n, currently by _nmod_poly_exp_series followed by _nmod_poly_inv_series. Requires \mathit{hlen} \le n and does not allow aliasing.

Set \mathit{res} = \log(f) \bmod x^n, for f with constant term 1, as the integral of f'/f.

Set g to \operatorname{atan}(h), \operatorname{atanh}(h), \operatorname{asin}(h) and \operatorname{asinh}(h) modulo x^n, from the integrals above.

Set g to \sin(h), \cos(h), \tan(h) and \tanh(h) modulo x^n.

Set g to \sinh(h) = (e^h - e^{-h})/2 and \cosh(h) = (e^h + e^{-h})/2 modulo x^n, using _nmod_poly_exp_expinv_series. The underscore versions read exactly n coefficients of h (zero-pad shorter inputs) and do not allow aliasing.

Roots#

Root finding and factorisation in general are in nmod_poly_factor.h (nmod_poly_roots, nmod_poly_factor). The function here is a fast path for polynomials that are expected to split into distinct linear factors, as in sparse interpolation and the decoding of Reed–Solomon codes (see Finding roots that are expected to be distinct and Decoding Reed–Solomon codes). The algorithms for roots over finite fields are described in Roots of polynomials over finite fields.

If the nonzero polynomial P of degree d has d distinct nonzero roots modulo the prime n (not checked), write them to roots[0], ..., roots[d - 1] in no particular order and return 1; otherwise return 0, in which case roots may have been partly written. Constants give 1 and no roots. For n = 2 the result is 0 for d \ge 2.

Full documentation

For monic f of degree at least 2 with \deg f distinct nonzero roots modulo an odd prime, find a factorisation f = ab with 1 \le \deg b \le \deg a by trying random \delta until \gcd((x + \delta)^{(n-1)/2} - 1, f) is a proper factor. t and t2 are temporaries.

Full documentation

Irreducible and Conway polynomials#

Sets res to a monic irreducible polynomial of degree n \ge 1 over the prime field \mathbb{F}_p, p the modulus of res, with the least possible number of nonzero terms: a binomial x^n + a if one exists, otherwise a trinomial, a tetranomial or a pentanomial. Throws FLINT_ERROR if none of these exists; it is conjectured that a tetranomial (p > 2) or pentanomial (p = 2) always does.

More
int _nmod_poly_conway(nn_ptr op, ulong prime, slong deg)

If FLINT's compressed copy of Lübeck's tables [Lüb2004] contains the Conway polynomial C_{p,d} for p = prime and d = deg, writes its d + 1 coefficients to op and returns 1; otherwise returns 0 (see Defining polynomials). The tables cover the primes below 109988, with all tabulated degrees for p < 260 and degree bounds that decrease with p above (12 for p < 300, then 9, 6, 4).

ulong _nmod_poly_conway_rand(slong * degree, flint_rand_t state, int type)

Returns a random prime p and sets degree to a random d such that _nmod_poly_conway(op, p, d) succeeds, for test code. For type 0 the pair is any tabulated one, for 1 the degree is less than 15, for 2 the prime is less than 2^{10}, and for 3 both. Other values of type throw FLINT_ERROR.

Inflation and deflation#

void nmod_poly_inflate(nmod_poly_t result, const nmod_poly_t input, slong inflation)

Sets result to p(x^k), where p is input and k = inflation \ge 0. For k = 0 the result is the constant p(1).

void nmod_poly_deflate(nmod_poly_t result, const nmod_poly_t input, slong deflation)

Sets result to p(x^{1/k}), where p is input and k = deflation \ge 1 must divide the exponent of every nonzero term (not checked). Throws FLINT_DIVZERO for k = 0.

Returns the largest k such that input is a polynomial in x^k, that is, the GCD of the exponents of its nonzero terms. Returns 0 for the zero polynomial and 1 for constants.

Chinese remaindering#

Given pairwise coprime moduli m_0, \ldots, m_{l-1} and values v_i, these functions find the polynomial r of least degree with r \equiv v_i \pmod{m_i}. The moduli are combined pairwise along a binary tree sorted by degree; each node stores an idempotent I with I \equiv 1 modulo one child and I \equiv 0 modulo the other, and computes A = B + I(C - B) \bmod M. All polynomials must have the same prime modulus.

Precomputed data for Chinese remaindering with fixed moduli: a straight line program of instructions _nmod_poly_multi_crt_prog_instr.

One instruction A = B + I(C - B) \bmod M of the program, with the indices of A, B and C (negative indices refer to the inputs), the idempotent I and the modulus M.

Prepare CRT for the \mathit{len} \ge 1 moduli, given as an array of polynomials or of pointers. Return 1 on success, which happens if and only if either \mathit{len} = 1 and the modulus is nonzero, or all moduli have positive degree and are pairwise coprime. On failure (0), later calls with CRT give undefined output.

Set output to the polynomial of least degree congruent to values[i] modulo the i-th modulus of CRT, for all i. The values need not be reduced.

int nmod_poly_multi_crt(nmod_poly_t output, const nmod_poly_struct * moduli, const nmod_poly_struct * values, slong len)

The same without a separate precomputation. Returns the value of nmod_poly_multi_crt_precompute; on failure the output is undefined.

void _nmod_poly_multi_crt_run_p(nmod_poly_struct * outputs, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * inputs)

Run the program of CRT with caller-supplied temporaries: outputs must be an array of at least _nmod_poly_multi_crt_local_size(CRT) initialised polynomials with the right modulus, and the result is placed in outputs[0]. Since CRT is only read, several threads can run it with their own outputs.

Berlekamp–Massey algorithm#

The Berlekamp–Massey algorithm [Ber1968] [Mas1969] finds the shortest linear recurrence satisfied by a sequence. FLINT's implementation views it as a partial extended Euclidean algorithm [SKHN1975]: after m points a_1, \ldots, a_m have been added, nmod_berlekamp_massey_reduce computes polynomials U, V, R of the extended Euclidean remainder sequence of x^m and S = a_1 x^{m-1} + a_2 x^{m-2} + \cdots + a_m with

U x^m + V S = R, \qquad \deg U < \deg V \le m/2, \qquad \deg R < m/2.

Then \sum_{i \ge 1} a_i x^{-i} = -U/V + R/(V x^m), so writing V = \sum_i v_i x^i, the recurrence \sum_i v_i a_{j+i} = 0 holds for 1 \le j < m - \deg R. If \deg R < \deg V, the recurrence holds for the whole sequence (1 \le j \le m - \deg V), and V is, up to a constant factor, the minimal polynomial (characteristic polynomial of the shortest recurrence) of the sequence; otherwise more points are needed. Unlike fmpz_mod_poly_minpoly, which returns a polynomial of least degree annihilating all m points, whose degree can be close to m and which is then not determined uniquely, V has degree at most m/2. The modulus must be prime. See Decoding Reed–Solomon codes for an application.

The state of the algorithm: the points added so far and the polynomials V and R of the last two steps of the remainder sequence.

Initialise B with an empty sequence modulo the prime p, and free it.

Empty the sequence of B; the second function also changes the prime to p.

Append count reduced points, count zeros, or one point to the sequence. The polynomials are updated only by nmod_berlekamp_massey_reduce.

Brings V and R up to date with all points added and returns 1 if V changed, 0 otherwise.

More

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

Prints V in pretty format with variable #, a comma and the points.

Bit packing#

These functions convert between polynomials and integers by placing the coefficients in fixed-width bit fields, that is, by evaluating at 2^{\mathit{bits}}. They are the building blocks of Kronecker substitution.

Writes \sum_i \mathit{poly}_i 2^{i \cdot \mathit{bits}} to res as \lceil \mathit{len} \cdot \mathit{bits} / \mathtt{FLINT\_BITS} \rceil limbs. Requires \mathit{len} \ge 1, 1 \le \mathit{bits} < 3 \mathtt{FLINT\_BITS} and every coefficient less than 2^{\mathit{bits}}.

Reads the bit fields \mathit{nlo}, \ldots, \mathit{nhi} - 1 of width bits from mpn, reduces them modulo n and writes them to res[0], ..., res[nhi - nlo - 1]. The fields may hold any value. Requires 1 \le \mathit{bits} < 3 \mathtt{FLINT\_BITS}.

void nmod_poly_bit_pack(fmpz_t f, const nmod_poly_t poly, flint_bitcnt_t bit_size)

Sets f = \mathit{poly}(2^{\mathit{bit\_size}}). Every coefficient must be less than 2^{\mathit{bit\_size}}; 1 \le \mathit{bit\_size} < 3 \mathtt{FLINT\_BITS}. For bit_size = 0 or the zero polynomial, f = 0.

Sets poly to the polynomial whose coefficients are the bit fields of width bit_size of f \ge 0, reduced modulo n; the inverse of nmod_poly_bit_pack for reduced coefficients. Throws FLINT_ERROR for f < 0. For bit_size = 0 the result is 0.

Write k zero bits followed by the n values op[0], op[s], ..., op[(n-1) s] in fields of b bits to res, and zero-pad the output to r limbs if r \ne 0. Each value must be less than 2^b. The pack1 version requires b \le \mathtt{FLINT\_BITS}, the other b \le 3 \mathtt{FLINT\_BITS}. Used by _nmod_poly_mul_KS2 and _nmod_poly_mul_KS4.

Skip k bits of op and extract n fields of b bits, writing each as one, two or three words to res. _nmod_poly_KS2_unpack1 requires b \le \mathtt{FLINT\_BITS}, unpack2 \mathtt{FLINT\_BITS} < b \le 2 \mathtt{FLINT\_BITS}, unpack3 2 \mathtt{FLINT\_BITS} < b < 3 \mathtt{FLINT\_BITS}; _nmod_poly_KS2_unpack dispatches on b.

Reduces n values of w \in \{1, 2, 3\} words each, stored consecutively in op, modulo n, writing them to res[0], res[s], ... with stride s.

Recover n coefficients of 2b bits from two sequences of n + 1 digits of b bits, unpacked from an integer product evaluated at 2^b (op1, low digits first) and from the product of the reversed polynomials (op2), propagating the borrows between them; reduce the coefficients modulo n and write them with stride s. Used by _nmod_poly_mul_KS4. The variants require 2b \le \mathtt{FLINT\_BITS} (1), \mathtt{FLINT\_BITS} < 2b < 2 \mathtt{FLINT\_BITS} (2), b = \mathtt{FLINT\_BITS} (2b) and 2 \mathtt{FLINT\_BITS} < 2b \le 3 \mathtt{FLINT\_BITS} (3); the version without suffix dispatches on b.

Internal functions#

The following helpers are declared in the header for use by other modules and by the functions above.

_nmod_poly_divrem_basecase given invB = \operatorname{lc}(B)^{-1}. Same conventions; R may be the same array as A.

Division with remainder for \mathit{lenA} = \mathit{lenB} + 1, the typical step of the Euclidean algorithm, given invL = \operatorname{lc}(B)^{-1}. Writes two coefficients to Q and \mathit{lenB} - 1 to R. R may be the same array as A, but Q must not overlap A. The two quotient coefficients are computed first, and each remainder coefficient a_i - q_1 b_{i-1} - q_0 b_i is then formed with a single reduction, using Lemire, Barrett or Möller–Granlund reduction depending on the size of n.

Bookkeeping for the resultant in a half-GCD computation (the resultant so far, the last leading coefficient and lengths). No function of the library uses it: the half-GCD functions above use the generic implementation in gr_poly.

An argument structure for computing the matrix of nmod_poly_precompute_matrix in a thread. It is not used by the library.

References#

  • [Har2009a] D. Harvey, "Faster polynomial multiplication via multipoint Kronecker substitution", Journal of Symbolic Computation 44:10 (2009), 1502–1510
  • [Sho1995] V. Shoup, "A new polynomial factorization algorithm and its implementation", Journal of Symbolic Computation 20:4 (1995), 363–397
  • [ThullYap1990] Thull, K. and Yap, C. : A Unified Approach to HGCD Algorithms for Polynomials and Integers, (1990)
  • [PS1973] M. S. Paterson and L. J. Stockmeyer, "On the number of nonscalar multiplications necessary to evaluate polynomials", SIAM J. Comput (1973)
  • [Blu1970] L. I. Bluestein. A linear filtering approach to the computation of discrete Fourier transform. IEEE Transactions on Audio and Electroacoustics 18:4 (1970), 451–455. https://doi.org/10.1109/TAU.1970.1162132
  • [RSR1969] L. R. Rabiner, R. W. Schafer and C. M. Rader. The chirp z-transform algorithm. IEEE Transactions on Audio and Electroacoustics 17:2 (1969), 86–92. https://doi.org/10.1109/TAU.1969.1162034
  • [BS2005] A. Bostan and É. Schost. Polynomial evaluation and interpolation on special sets of points. Journal of Complexity 21 (2005), 420–446.
  • [ASU1975] A. V. Aho, K. Steiglitz and J. D. Ullman. Evaluating polynomials at fixed sets of points. SIAM Journal on Computing 4 (1975), 533–539.
  • [GG1997] J. von zur Gathen and J. Gerhard. Fast algorithms for Taylor shifts and certain difference equations. ISSAC 1997, 40–47.
  • [BrentKung1978] Brent, R. P. and Kung, H. T. : Fast Algorithms for Manipulating Formal Power Series, J. ACM 25:4 (1978) 581–595
  • [GatSho1992] J. von zur Gathen and V. Shoup, "Computing Frobenius maps and factoring polynomials", Computational Complexity 2 (1992), 187-224. https://doi.org/10.1007/BF01272074
  • [KalSho1998] E. Kaltofen and V. Shoup, "Subquadratic-time factoring of polynomials over finite fields", Mathematics of Computation 67 (1998), 1179-1197. https://doi.org/10.1090/S0025-5718-98-00944-2
  • [Sch1982b] A. Schönhage. The fundamental theorem of algebra in terms of computational complexity. Technical report, Universität Tübingen, 1982.
  • [BFSS2006] A. Bostan, P. Flajolet, B. Salvy and É. Schost. "Fast computation of special resultants". Journal of Symbolic Computation, 41(1):1–29, January 2006. https://doi.org/10.1016/j.jsc.2005.07.001
  • [HZ2004] G. Hanrot and P. Zimmermann, "Newton Iteration Revisited" (2004), http://www.loria.fr/~zimmerma/papers/fastnewton.ps.gz
  • [BZ2011] R. P. Brent and P. Zimmermann, Modern Computer Arithmetic, Cambridge University Press (2011), http://www.loria.fr/~zimmerma/mca/pub226.html
  • [Lüb2004] F. Lübeck, "Conway polynomials for finite fields", RTWH Aachen, https://www.math.rwth-aachen.de/~Frank.Luebeck/data/ConwayPol/index.html, (accessed 2024-01-12)
  • [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.
  • [SKHN1975] Y. Sugiyama, M. Kasahara, S. Hirasawa and T. Namekawa. A method for solving key equation for decoding Goppa codes. Information and Control 27 (1975), 87–99.
Cite this page

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