FLINT3.7.0-dev
Module · 460 functions

fmpz_poly.h

#include <flint/fmpz_poly.h>

This module implements dense univariate polynomials over Z\mathbb{Z}. An fmpz_poly_t is an array of fmpz coefficients together with its length; each coefficient is an integer of arbitrary size and is managed separately. Multiplication chooses among the classical algorithm, word-size and packed-limb kernels, Karatsuba and Toom–Cook interpolation in the polynomial variable, Kronecker substitution on top of the FFTs of fft_small, and Schönhage–Strassen convolutions, according to the lengths and the coefficient sizes. GCDs and resultants are computed by multimodular algorithms that reduce to polynomial arithmetic modulo word-size primes, division by divide-and-conquer algorithms, and power series by Newton iteration. Factorisation is in fmpz_poly_factor.h; polynomials with rational coefficients are in fmpq_poly.h, matrices of polynomials in fmpz_poly_mat.h, and rigorous numerical root finding in arb_fmpz_poly.h (Isolating the roots of integer polynomials, Certified roots of polynomials).

Start with the guide Getting started with fmpz_poly, which explains the conventions below with examples.

Guides#

Types and conventions#

A polynomial over Z\mathbb{Z}. The structure has the fields coeffs (an array of alloc coefficients of type fmpz), alloc and length. An fmpz_poly_t is an array of one fmpz_poly_struct, so it is passed by reference. The coefficient of xix^i is coeffs[i].

  • 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-1. All functions require normalised inputs and produce normalised outputs, unless stated otherwise.
  • The allocated coefficients beyond the length are always zero: every function that shortens a polynomial clears the coefficients it drops, and newly allocated coefficients are zero. Code that writes coefficients directly must keep this invariant.
  • 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 a quotient and a remainder) must be distinct objects.
  • Functions with a leading underscore work on coefficient arrays (poly, len) and leave memory management to the caller. They usually require positive lengths and an ordering of the lengths, write a fixed number of coefficients (including leading zeros), and do not allow the output to overlap the inputs. Each function states its conditions. Zero padding of an input (poly, len) means that the top coefficients may be zero.
  • Division by a polynomial whose leading coefficient is not ±1\pm 1 cannot in general be carried out over Z\mathbb{Z}. The division functions either assume that the division is exact, or define the quotient by rounding each coefficient (see Division and pseudo-division), or work with pseudo-division.

Memory management#

Initialise poly as the zero polynomial. fmpz_poly_init allocates nothing; fmpz_poly_init2 allocates alloc coefficients, all zero. A polynomial must be cleared with fmpz_poly_clear after use.

Changes the allocated space of poly to exactly alloc coefficients. If the length exceeds alloc, the polynomial is first 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 len 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, including that of its coefficients. The polynomial must be initialised again before it is used.

Sets the length of poly to newlen. If the length decreases, the dropped coefficients are set to zero (freeing their memory), which keeps the invariant that coefficients beyond the length are zero. No normalisation is done; poly must have space for newlen 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.

Make the uninitialised trunc a read-only view of part of poly without copying: fmpz_poly_attach_truncate of the low min⁡(n,len⁡)\min(n, \operatorname{len}) coefficients, fmpz_poly_attach_shift of the coefficients from index nn on, that is of ⌊poly/xn⌋\lfloor \mathit{poly} / x^n \rfloor (zero if n≥len⁡n \ge \operatorname{len}). The view shares memory with poly; it must not be cleared, modified or used as an output, and becomes invalid when poly changes. A truncated view may have a zero leading coefficient, so it is not necessarily normalised.

Length and degree#

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

Coefficients#

Return (or set x to) the coefficient of xnx^n in poly, which is zero if nn is at least the length. The si and ui versions return the result of fmpz_get_si or fmpz_get_ui and are only meaningful when the coefficient fits.

Set the coefficient of xnx^n in poly to xx, extending the polynomial with zero coefficients if nn is beyond the length, and normalising if the leading coefficient is set to zero.

Returns a pointer to the coefficient of xnx^n, or NULL if nn is at least the length. The coefficient can be read or changed with the functions of fmpz; changing the leading coefficient to zero requires a call to _fmpz_poly_normalise.

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

Assignment and basic manipulation#

void fmpz_poly_set(fmpz_poly_t poly1, const fmpz_poly_t poly2)

Sets poly1 to a copy of poly2.

Set poly to the constant polynomial cc.

Set poly to the constant polynomial 0, respectively 1.

Swaps poly1 and poly2 in constant time by swapping their structures.

Sets the coefficients of xi,…,xj−1x^i, \ldots, x^{j-1} to zero, clamping the range to the length of poly, and normalises.

Reduce modulo xnx^n: fmpz_poly_truncate truncates poly in place to length at most newlen, and fmpz_poly_set_trunc sets res to poly truncated to length nn. Both normalise the result.

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

Set res to the reversal xn−1f(1/x)x^{n-1} f(1/x) of ff = poly considered as a polynomial of length nn, truncating or zero-padding it first. The underscore version writes nn coefficients and requires 0<len≤n0 < \mathit{len} \le n; res may be equal to poly but must not partially overlap it. The non-underscore version normalises, so the result can be shorter than nn.

Comparison#

int fmpz_poly_equal(const fmpz_poly_t poly1, const fmpz_poly_t poly2)
int fmpz_poly_equal_trunc(const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)

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

int fmpz_poly_equal_fmpz(const fmpz_poly_t poly, const fmpz_t c)

Returns whether poly is the constant polynomial cc (the zero polynomial if c=0c = 0).

Returns whether poly is zero.

int _fmpz_poly_is_one(const fmpz * poly, slong len)

Return whether the polynomial is the constant 1. The underscore version allows zero padding and returns 0 for len = 0.

Returns whether poly is a unit of Z[x]\mathbb{Z}[x], that is, the constant 11 or −1-1.

Returns whether poly is the generator xx.

Randomisation#

Set ff to a random polynomial of length at most len whose coefficients have at most bits bits, with random signs (randtest), nonnegative (randtest_unsigned), or, for randtest_not_zero, not the zero polynomial, which requires len and bits to be positive. The coefficients are generated by fmpz_randtest, which favours special values (zero, small values, values close to powers of two), so these functions are meant for testing.

Sets p to a random polynomial of length at most len with coefficients of at most bits bits that has no real root.

Set pol to a random polynomial of length at most len with coefficients of at most bits bits that is irreducible over Z\mathbb{Z}. irreducible1 lifts a random irreducible polynomial modulo a random prime to Z\mathbb{Z} (an irreducible image modulo a prime that does not divide the leading coefficient proves irreducibility); irreducible2 factors a random polynomial and returns a random factor; the third function chooses one of the two at random.

Input and output#

The functions in this section are meant for debugging and for exchanging small amounts of data, not for speed. There are two formats.

  • The plain format lists the length followed by the coefficients from the constant term up, in decimal and separated by spaces; the length is followed by two spaces. For example 5x3−x+15x^3 - x + 1 is "4 1 -1 0 5" and the zero polynomial is "0".
  • The pretty format writes the nonzero terms from the highest degree down, as in 5*x^3-x+1, with a variable name chosen by the caller. Coefficients ±1\pm 1 are written as a sign only, and the constant term without the variable.
int _fmpz_poly_set_str(fmpz * poly, const char * str)
int fmpz_poly_set_str(fmpz_poly_t poly, const char * str)

Set poly to the polynomial given in plain format by the null-terminated string str. Return 0 on success and a nonzero value if the string is malformed, in which case fmpz_poly_set_str sets poly to zero and the underscore version leaves the array in an undefined state. The underscore version requires that poly has room for the number of coefficients given in the string.

char * _fmpz_poly_get_str(const fmpz * poly, slong len)
char * fmpz_poly_get_str(const fmpz_poly_t poly)
char * _fmpz_poly_get_str_pretty(const fmpz * poly, slong len, const char * x)
char * fmpz_poly_get_str_pretty(const fmpz_poly_t poly, const char * x)

Return a newly allocated string with the polynomial in plain format, respectively in pretty format with the variable name x. The string must be freed with flint_free.

int _fmpz_poly_print(const fmpz * poly, slong len)
int _fmpz_poly_fprint(FILE * file, const fmpz * poly, slong len)
int fmpz_poly_fprint(FILE * file, const fmpz_poly_t poly)

Print the polynomial in plain format to stdout, respectively to file. Return a positive value on success and a nonpositive value on failure.

int _fmpz_poly_print_pretty(const fmpz * poly, slong len, const char * x)
int fmpz_poly_print_pretty(const fmpz_poly_t poly, const char * x)
int _fmpz_poly_fprint_pretty(FILE * file, const fmpz * poly, slong len, const char * x)
int fmpz_poly_fprint_pretty(FILE * file, const fmpz_poly_t poly, const char * x)

Print the polynomial in pretty format with the variable name x to stdout, respectively to file. Return a positive value on success and a nonpositive value on failure.

int fmpz_poly_fread(FILE * file, fmpz_poly_t poly)

Read a polynomial in plain format from stdin, respectively from file, into poly. Return a positive value on success and a nonpositive value on failure.

int fmpz_poly_read_pretty(fmpz_poly_t poly, char ** x)
int fmpz_poly_fread_pretty(FILE * file, fmpz_poly_t poly, char ** x)

Read a polynomial in pretty format from stdin, respectively from file, into poly, and set *x to a newly allocated string with the variable name found in the input, to be freed with flint_free. Return the number of characters read on success, and a nonpositive value on a read error or malformed input.

void fmpz_poly_debug(const fmpz_poly_t poly)

Prints the fields alloc and length and all alloc allocated coefficients of poly to stdout, for debugging.

Addition and subtraction#

void _fmpz_poly_add(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void _fmpz_poly_sub(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)

Set (res, max(len1, len2)) to the sum, respectively difference, of (poly1, len1) and (poly2, len2). The output may be equal to either input.

void fmpz_poly_add(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)
void fmpz_poly_sub(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)
void fmpz_poly_neg(fmpz_poly_t res, const fmpz_poly_t poly)

Set res to poly1 + poly2, poly1 - poly2, respectively -poly.

void fmpz_poly_add_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)
void fmpz_poly_sub_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)

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

Set res to poly + c, poly - c, respectively c - poly, for an integer constant cc.

Scalar multiplication and division#

Sets res to the polynomial whose coefficients are the absolute values of those of poly.

void fmpz_poly_scalar_mul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x)

Set poly1 to poly2 multiplied by xx, respectively by 2exp2^{exp}.

Set poly1 to poly1 + x * poly2, respectively poly1 - x * poly2.

void fmpz_poly_scalar_fdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x)
void fmpz_poly_scalar_tdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x)

Set poly1 to poly2 divided by xx, rounding each coefficient towards −∞-\infty (fdiv) or towards zero (tdiv). Division by zero raises an exception.

Set poly1 to poly2 divided by 2exp2^{exp}, rounding each coefficient towards −∞-\infty, respectively towards zero.

Set poly1 to poly2 divided by xx, assuming that xx divides every coefficient. This is not checked; the result is undefined otherwise. Division by zero raises an exception.

void fmpz_poly_scalar_mod_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x)
void fmpz_poly_scalar_smod_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x)

Set poly1 to poly2 with each coefficient reduced modulo x>0x > 0, into [0,x)[0, x), respectively into the symmetric range (−x/2,x/2](-x/2, x/2].

Shifting, inflation and deflation#

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

Set res to poly multiplied by xnx^n. The underscore version writes len + n coefficients; res may be equal to poly.

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

Set res to ⌊poly/xn⌋\lfloor \mathit{poly} / x^n \rfloor, dropping the low nn coefficients; the result is zero if nn is at least the length. The underscore version requires len>n\mathit{len} > n and writes len - n coefficients; res may be equal to poly, in which case the top nn entries of the array are left unchanged.

void fmpz_poly_inflate(fmpz_poly_t result, const fmpz_poly_t input, ulong inflation)

Sets result to p(xn)p(x^n), where pp is input and nn = inflation. For n=0n = 0 the result is the constant p(1)p(1).

void fmpz_poly_deflate(fmpz_poly_t result, const fmpz_poly_t input, ulong deflation)

Sets result to p(x1/n)p(x^{1/n}), where pp is input and nn = deflation, that is, keeps the coefficients of x0,xn,x2n,…x^0, x^n, x^{2n}, \ldots. Requires that n≥1n \ge 1 divides fmpz_poly_deflation(input); other coefficients are dropped and the result is not necessarily normalised. Division by n=0n = 0 raises an exception.

Return the largest nn such that the polynomial is a polynomial in xnx^n, that is, the GCD of the exponents of its nonzero terms. Return 0 for the zero polynomial and 1 for a nonzero constant.

Bit sizes and norms#

Returns the largest number of limbs needed to store the absolute value of a coefficient of poly, or 0 if poly is zero.

Returns the largest bit length bb of the absolute value of a coefficient of poly if all coefficients are nonnegative, and −b-b otherwise.

void fmpz_poly_height(fmpz_t res, const fmpz_poly_t poly)

Sets res to the height of poly, the largest absolute value of a coefficient (the ∞\infty-norm), which is 0 for the zero polynomial.

void _fmpz_poly_2norm(fmpz_t res, const fmpz * poly, slong len)
void fmpz_poly_2norm(fmpz_t res, const fmpz_poly_t poly)

Set res to ⌊∥f∥2⌋\lfloor \|f\|_2 \rfloor, the integer square root of the sum of the squares of the coefficients.

Returns an upper bound, at most one too large, for the number of bits of ∥f∥2/∣lc⁡(f)∣\|f\|_2 / |\operatorname{lc}(f)|, the Euclidean norm of (poly, len) divided by the absolute value of its leading coefficient. Requires len>0\mathit{len} > 0 and a nonzero leading coefficient. This is used for Landau–Mignotte bounds.

Returns the number of nonzero coefficients of (a, len).

Multiplication#

All products, truncated products, middle products and squares are computed by one dispatcher, _fmpz_poly_mulmid, which chooses the algorithm from the lengths, the requested range of coefficients and the bit sizes of the coefficients; see Multiplying polynomials and Multiplying polynomials over Z. Squaring is detected when both operands are the same array with the same length.

void _fmpz_poly_mul(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_mul(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Set res to the product of poly1 and poly2. The underscore version writes len1 + len2 - 1 coefficients, requires positive lengths (in either order), allows zero padding and does not allow res to overlap the inputs.

Full documentation
void _fmpz_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n)
void fmpz_poly_mullow(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)

Set res to the product of poly1 and poly2 truncated to length nn, that is, reduced modulo xnx^n. The underscore version writes nn coefficients and requires positive lengths (in either order), 0<n≤len1+len2−10 < n \le \mathit{len1} + \mathit{len2} - 1 and no overlap of res with the inputs.

Full documentation
void _fmpz_poly_mulmid(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi)
void fmpz_poly_mulmid(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong nlo, slong nhi)

Set res to the coefficients of xnlo,…,xnhi−1x^{nlo}, \ldots, x^{nhi - 1} of the product of poly1 and poly2, shifted down to start at index 0, that is, to ⌊(poly1⋅poly2 mod xnhi)/xnlo⌋\lfloor (\mathit{poly1} \cdot \mathit{poly2} \bmod x^{nhi}) / x^{nlo} \rfloor. The non-underscore version clamps nhi\mathit{nhi} to the length of the product and returns zero for an empty range. The underscore version writes nhi−nlo\mathit{nhi} - \mathit{nlo} coefficients and requires positive lengths (in either order), 0≤nlo<nhi≤len1+len2−10 \le \mathit{nlo} < \mathit{nhi} \le \mathit{len1} + \mathit{len2} - 1 and no overlap of res with the inputs.

Full documentation
void fmpz_poly_mulhigh_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)

Sets res to a polynomial of length len1+len2−1\mathit{len1} + \mathit{len2} - 1 whose top nn coefficients are those of the product of poly1 and poly2; the coefficients below are arbitrary. Both operands are used at their full lengths.

Full documentation
void _fmpz_poly_mulhigh(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start)

Sets the coefficients res[start], ..., res[len1 + len2 - 2] to those of the product of (poly1, len1) and (poly2, len2), leaving res[0], ..., res[start - 1] unchanged. Requires positive lengths (in either order), 0≤start<len1+len2−10 \le \mathit{start} < \mathit{len1} + \mathit{len2} - 1 and no overlap of res with the inputs.

Full documentation
void _fmpz_poly_sqr(fmpz * rop, const fmpz * op, slong len)

Set rop to the square of op. The underscore version writes `2*len

  • 1coefficients, requires $\mathit{len} > 0$, allows zero padding and does not allowropto overlapop`.
Full documentation
void _fmpz_poly_sqrlow(fmpz * res, const fmpz * poly, slong len, slong n)

Set res to the square of poly truncated to length nn. The underscore version writes nn coefficients and requires len>0\mathit{len} > 0, 0<n≤2len−10 < n \le 2 \mathit{len} - 1 and no overlap of res with poly.

Full documentation

Multiplication algorithms#

The functions in this section implement one algorithm each and are called by _fmpz_poly_mulmid; they are public for testing, tuning and special applications. Unless stated otherwise, each family has full (mul), low (mullow), high (mulhigh) and middle (mulmid) products and squares with the same conventions as the functions of the previous section, and the non-underscore versions allow aliasing. See Multiplying polynomials over Z for the algorithms and the selection.

void _fmpz_poly_mul_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_mul_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)
void _fmpz_poly_mullow_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n)
void fmpz_poly_mullow_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)
void _fmpz_poly_mulmid_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi)
void fmpz_poly_mulmid_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong nlo, slong nhi)
void _fmpz_poly_sqr_classical(fmpz * rop, const fmpz * op, slong len)
void _fmpz_poly_sqrlow_classical(fmpz * res, const fmpz * poly, slong len, slong n)

Classical (schoolbook) multiplication: each output coefficient is computed as one dot product of fmpz values (_fmpz_vec_dot_general), and squares use the symmetry of the products. The cost is proportional to the number of coefficient products in the requested range. The underscore versions require positive lengths and do not allow res to overlap the inputs.

void _fmpz_poly_mulhigh_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start)
void fmpz_poly_mulhigh_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong start)

Set the coefficients of res from index start on to those of the product of poly1 and poly2 by the classical algorithm, and the coefficients below start to zero; the result has length len1+len2−1\mathit{len1} + \mathit{len2} - 1, or is zero if start is at least that. The underscore version requires positive lengths and does not allow res to overlap the inputs.

void _fmpz_poly_mulmid_mpn(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi)
void _fmpz_poly_mul_mpn(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_mulmid_mpn(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong nlo, slong nhi)
void fmpz_poly_mul_mpn(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Middle and full products computed on packed fixed-size limb arrays instead of fmpz values, with classical, Karatsuba and Karatsuba middle-product algorithms (_flint_mpn_poly_mulmid). Intended for lengths up to a few dozen and coefficients up to about a thousand bits.

More
void _fmpz_poly_mulmid_mpn_bits(fmpz * res, const fmpz * poly1, slong len1, slong bits1, const fmpz * poly2, slong len2, slong bits2, slong nlo, slong nhi)

As _fmpz_poly_mulmid_mpn, taking the signed bit bounds bits1 and bits2 of the coefficients, as returned by _fmpz_vec_max_bits, from the caller. The absolute values of the bounds need not be tight, but a bound must be negative if the polynomial has a negative coefficient, and a bound 0 means that the polynomial is zero.

int _fmpz_poly_mul_toom_scalar(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
int _fmpz_poly_mul_toom_scalar_nmax(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nmax)

Multiply by Toom–Cook evaluation and interpolation in the polynomial variable, at the points 0,±1,…,±p0, \pm 1, \ldots, \pm p, one more point when the output length is odd, and infinity, using exactly len1+len2−1\mathit{len1} + \mathit{len2} - 1 coefficient multiplications. Return 1 on success and 0, leaving res unchanged, if the output length len1+len2−1\mathit{len1} + \mathit{len2} - 1 exceeds FMPZ_POLY_TOOM_SCALAR_N_MAX (20 on 64-bit and 13 on 32-bit machines), respectively min⁡(nmax,\min(\mathit{nmax}, FMPZ_POLY_TOOM_SCALAR_N_MAX)).

More
int _fmpz_poly_mulmid_toom_scalar(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi)
int _fmpz_poly_mulmid_toom_scalar_nmax(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi, slong nmax)
int fmpz_poly_mulmid_toom_scalar(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong nlo, slong nhi)

Compute the middle product window [nlo,nhi)[\mathit{nlo}, \mathit{nhi}) as _fmpz_poly_mulmid, by Toom–Cook interpolation. With mm, nn the lengths of the operands after removing coefficients that cannot contribute and ww the length of the window, the number of coefficient multiplications is the sum of the two smallest of m,n,wm, n, w, minus one: either a full product of the trimmed operands, or, transposed, a middle product of the window against the shorter operand. Return 0, leaving res unchanged, when both routes exceed the length bound of _fmpz_poly_mul_toom_scalar_nmax.

More
void _fmpz_poly_mul_toom_karatsuba(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void _fmpz_poly_mulmid_toom_karatsuba(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi)
void fmpz_poly_mulmid_toom_karatsuba(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong nlo, slong nhi)

Karatsuba multiplication with the Toom–Cook functions _fmpz_poly_mul_toom_scalar_nmax and _fmpz_poly_mulmid_toom_scalar_nmax as base cases, for short polynomials with large coefficients. Full products use Karatsuba with the longer operand cut into pieces of the length of the shorter one; low products use Mulders' short product [Mul2000], high products a low product of the reversed operands, and other windows the Karatsuba middle product of Hanrot, Quercia and Zimmermann [HQZ2004], so that a middle-product-shaped window costs about half a full product.

More
void _fmpz_poly_mul_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_mul_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)
void _fmpz_poly_mullow_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n)
void fmpz_poly_mullow_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)
void _fmpz_poly_mulmid_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi)
void fmpz_poly_mulmid_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong nlo, slong nhi)
void _fmpz_poly_sqr_KS(fmpz * rop, const fmpz * op, slong len)
void _fmpz_poly_sqrlow_KS(fmpz * res, const fmpz * poly, slong len, slong n)

Multiply by Kronecker substitution: the coefficients are packed into bit fields of b1+b2+⌈log⁡2(min⁡(len1,len2)+1)⌉b_1 + b_2 + \lceil \log_2 (\min(\mathit{len1}, \mathit{len2}) + 1) \rceil bits, plus one for signs (where bib_i bounds the bits of the coefficients), the two integers are multiplied with flint_mpn_mul (or flint_mpn_mulmid for windows, which computes only the needed limbs), and the product is unpacked. The underscore versions require positive lengths (in either order), allow zero padding and zero polynomials, and allow res to be equal to an input, since the inputs are packed before anything is written.

void _fmpz_poly_mul_SS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_mul_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)
void _fmpz_poly_mullow_SS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n)
void fmpz_poly_mullow_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)
void _fmpz_poly_mulmid_SS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi)
void fmpz_poly_mulmid_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong nlo, slong nhi)

Multiply by a Schönhage–Strassen convolution (Schönhage–Strassen multiplication): each coefficient becomes one element of Z/(2N+1)Z\mathbb{Z}/(2^N + 1)\mathbb{Z} large enough for the coefficients of the product, and the product is a convolution of power-of-two length computed with fft_convolution (or fft_convolution_sd_fft, whose pointwise products use fft_small). For a window that does not reach the top of the product, a cyclic convolution of a power-of-two length ≥max⁡(nhi,len1+len2−1−nlo)\ge \max(\mathit{nhi}, \mathit{len1} + \mathit{len2} - 1 - \mathit{nlo}) is used when it is shorter than the truncated transform, so that the wrapped-around terms land below nlo\mathit{nlo} (fft_convolution_choose_mid). The underscore versions require positive lengths (in either order), allow zero padding and allow res to be equal to an input. The convolutions use flint_get_num_threads threads.

int _fmpz_poly_mulmid_classical_fft_small(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong nlo, slong nhi)

Classical multiplication in which the coefficient products are computed in the transform space of fft_small (Arithmetic in transform space): the coefficients of the shorter operand are transformed once, the longer operand runs through a window of transformed coefficients, and each output coefficient is a sum of pointwise products transformed back once. Squares share transforms and pair symmetric terms. This is efficient for short polynomials with very large coefficients. Return 1 on success and 0, writing nothing, when the transform representation is not available (small coefficients, or a build without fft_small). The underscore version takes the lengths in either order and does not allow res to overlap the inputs.

Precached multiplication#

When many polynomials are multiplied by the same polynomial with large coefficients, its Schönhage–Strassen transform can be computed once. See also Convolutions with a fixed operand.

Stores the transform of a fixed polynomial poly2 (a copy of which is kept in the field poly2), with the transform length and ring chosen for products with polynomials of bounded length and coefficient size.

Precomputes the transform of poly2 for multiplications by polynomials of length at most len1 whose coefficients have at most bits1 bits. The transform length is the power of two 2k≥len1+len2−12^k \ge \mathit{len1} + \mathit{len2} - 1; products whose length is at most 2k−12^{k-1} are computed with the same, too long, transform. bits1 may be negative, as returned by fmpz_poly_max_bits for polynomials with negative coefficients; only its absolute value is used.

Frees the memory used by pre.

void _fmpz_poly_mullow_SS_precache(fmpz * output, const fmpz * input1, slong len1, fmpz_poly_mul_precache_t pre, slong trunc)

Set res to the product of poly1 and the polynomial stored in pre, truncated to length nn (trunc) for the mullow versions. The length and bit size of poly1 must not exceed those given to fmpz_poly_mul_SS_precache_init. The non-underscore versions use classical multiplication when one of the lengths or nn is at most 2. The underscore version requires trunc to be at most the length of the product and does not allow output to overlap input1.

Bit packing#

These functions convert between polynomials and integers by evaluation at 2b2^b, the basis of Kronecker substitution.

void _fmpz_poly_bit_pack(nn_ptr arr, const fmpz * poly, slong len, flint_bitcnt_t bit_size, int negate)

Adds the coefficients of (poly, len), negated if negate is −1-1, into consecutive fields of bit_size bits of the zero-initialised limb array arr, representing negative coefficients by borrows from the next field, so that the array holds ±f(2b)\pm f(2^b) as a nonnegative integer when the leading coefficient times the sign is positive. negate must be 0 or −1-1, and bit_size must exceed the bit length of every coefficient.

int _fmpz_poly_bit_unpack(fmpz * poly, slong nlo, slong nhi, nn_srcptr arr, flint_bitcnt_t bit_size, int negate)

Unpack the signed (respectively unsigned) coefficients in the fields nlo,…,nhi−1\mathit{nlo}, \ldots, \mathit{nhi} - 1 of bit_size bits of arr, written by _fmpz_poly_bit_pack, to poly[0], ..., poly[nhi - nlo - 1], negating them if negate is −1-1. The signed version returns the final borrow: if it is nonzero, a coefficient ±1\pm 1 (with the sign given by negate) has to be added at index nhi.

void fmpz_poly_bit_pack(fmpz_t f, const fmpz_poly_t poly, flint_bitcnt_t bit_size)

Sets ff to poly(2b)\mathit{poly}(2^b) for bb = bit_size, which must exceed the bit length of every coefficient plus one. The sign of ff is that of the leading coefficient.

Set poly to the polynomial with signed (respectively nonnegative) coefficients of absolute value less than 2b−12^{b-1} (respectively 2b2^b) such that poly(2b)=f\mathit{poly}(2^b) = f, for bb = bit_size. The unsigned version requires f≥0f \ge 0.

Powering#

void _fmpz_poly_pow(fmpz * res, const fmpz * poly, slong len, ulong e)
void fmpz_poly_pow(fmpz_poly_t res, const fmpz_poly_t poly, ulong e)

Set res to poly raised to the power ee, with 00=10^0 = 1. The function uses repeated squaring and multiplication for e≤4e \le 4, the binomial theorem for binomials, the J. C. P. Miller recurrence (_fmpz_poly_pow_multinomial) for short polynomials with small coefficients compared to ee, and binary exponentiation otherwise. The underscore version requires e>0e > 0 and len>0\mathit{len} > 0, writes e(len−1)+1e(\mathit{len} - 1) + 1 coefficients and does not allow aliasing.

void _fmpz_poly_pow_small(fmpz * res, const fmpz * poly, slong len, ulong e)

Sets res to poly raised to the power e≤4e \le 4 by squarings and one multiplication. Requires len>0\mathit{len} > 0 and room for e(len−1)+1e(\mathit{len} - 1) + 1 coefficients; no aliasing.

void _fmpz_poly_pow_binexp(fmpz * res, const fmpz * poly, slong len, ulong e)

Set res to poly raised to the power ee by left-to-right binary exponentiation [Knu1997, §4.6.3]. The underscore version requires len>0\mathit{len} > 0, e>1e > 1 and room for e(len−1)+1e(\mathit{len} - 1) + 1 coefficients, and does not allow aliasing.

void _fmpz_poly_pow_addchains(fmpz * res, const fmpz * poly, slong len, const int * a, int n)

Set res to poly raised to the power ee along an addition chain. The underscore version takes a star chain 1=a0<a1<⋯<an=e1 = a_0 < a_1 < \cdots < a_n = e (each aia_i is ai−1+aja_{i-1} + a_j for some j<ij < i) with n>1n > 1, requires len>0\mathit{len} > 0 and does not allow aliasing. The non-underscore version uses a table of chains for e≤148e \le 148 and raises an exception for larger ee.

void _fmpz_poly_pow_binomial(fmpz * res, const fmpz * poly, ulong e)

Set res to (a+bx)e(a + bx)^e for poly =a+bx= a + bx of length exactly 2, by the binomial theorem. The non-underscore version raises an exception for any other length; the underscore version requires e>0e > 0 and does not allow aliasing.

void _fmpz_poly_pow_multinomial(fmpz * res, const fmpz * poly, slong len, ulong e)

Set res to poly raised to the power ee using the J. C. P. Miller recurrence [Knu1997, §4.6.1, exercise 16], [Zei1995]: if P(x)=∑i=0mpixiP(x) = \sum_{i=0}^m p_i x^i with p0≠0p_0 \ne 0 and P(x)e=∑kakxkP(x)^e = \sum_k a_k x^k, then a0=p0ea_0 = p_0^e and

ak=1kp0∑i=1min⁡(k,m)pi((e+1)i−k)ak−i,k≥1.a_k = \frac{1}{k p_0} \sum_{i=1}^{\min(k, m)} p_i \bigl((e + 1) i - k\bigr) a_{k-i}, \qquad k \ge 1.

Each coefficient costs O(m)O(m) multiplications and one exact division. Low zero coefficients are removed first. The underscore version requires len>0\mathit{len} > 0 and e>0e > 0 and does not allow aliasing.

void _fmpz_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong n)

Set res to poly raised to the power ee and truncated to length nn, computed with truncated products throughout, which is much faster than powering and truncating; with 00=10^0 = 1 for n>0n > 0. The underscore version reads nn coefficients of poly (so it must be zero padded to length nn), requires e,n>0e, n > 0 and does not allow aliasing.

Division#

Over Z\mathbb{Z}, the quotient of AA by BB is defined coefficient by coefficient from the top: at each step the leading remaining coefficient rr is divided by ℓ=lc⁡(B)\ell = \operatorname{lc}(B) with floor rounding if ∣r∣≥∣ℓ∣|r| \ge |\ell|, and the quotient coefficient is zero otherwise. This gives A=BQ+RA = BQ + R in which every coefficient of RR of degree at least deg⁡B\deg B has absolute value less than ∣ℓ∣|\ell|. If ℓ=±1\ell = \pm 1, or if BB divides AA, this is division in Q[x]\mathbb{Q}[x] and deg⁡R<deg⁡B\deg R < \deg B. See Division and pseudo-division for details, pseudo-division and examples.

int _fmpz_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact)

Set QQ and RR to the quotient and remainder of AA by BB as defined above. Division by zero raises an exception. The underscore version writes (Q, lenA - lenB + 1) and (R, lenA), requires lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0, allows zero padding of AA and does not allow aliasing. It uses the basecase algorithm for lenB<6\mathit{lenB} < 6 and divide and conquer otherwise.

Full documentation
int _fmpz_poly_div(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact)

Set QQ to the quotient of AA by BB as defined above, without computing the remainder. Division by zero raises an exception. The underscore version writes lenA - lenB + 1 coefficients, requires lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0, allows zero padding of AA and does not allow aliasing; exact is as for _fmpz_poly_divrem.

Full documentation
void _fmpz_poly_rem(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB)

Set RR to the remainder of AA by BB as defined above. Division by zero raises an exception. The underscore version writes lenA coefficients, requires lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0 and does not allow aliasing.

Full documentation
void _fmpz_poly_divexact(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB)

Set QQ to A/BA / B, assuming that BB divides AA; this is not checked, and the result is undefined otherwise. Division by zero raises an exception. Short quotients and short divisors are computed from both ends at once, with coefficients no larger than those of QQ; long ones use _fmpz_poly_div. The underscore version requires lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0 and does not allow aliasing.

Full documentation
int _fmpz_poly_divides(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB)

Return whether BB divides AA in Z[x]\mathbb{Z}[x], and if so set QQ to the quotient. Inexact divisions are usually detected quickly: by the constant coefficients, by the values at x=1x = 1, and by the first inexact quotient coefficient. If BB does not divide AA, the value of QQ is undefined. Division by zero raises an exception. The underscore version requires lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0, room for lenA−lenB+1\mathit{lenA} - \mathit{lenB} + 1 coefficients in QQ and no aliasing.

Full documentation

Returns the largest kk such that poly2k^k divides poly1 and sets res to poly1 divided by poly2k^k. The value of kk is first bounded using the values at x=1x = 1. Raises an exception if poly2 is zero or ±1\pm 1.

Full documentation
void _fmpz_poly_div_root_fmpz(fmpz * Q, const fmpz * A, slong len, const fmpz_t c)

Set QQ to the quotient of AA by x−cx - c by synthetic division (Horner's rule); the remainder A(c)A(c) is discarded. The underscore version writes len - 1 coefficients; QQ may be equal to AA but must not partially overlap it.

void _fmpz_poly_divexact_root_fmpq(fmpz * Q, const fmpz * A, slong len, const fmpq_t c)

Set QQ to A/(qx−p)A / (qx - p) where c=p/qc = p/q in lowest terms, assuming that cc is a root of AA; this is not checked. The underscore version writes len - 1 coefficients; QQ may be equal to AA but must not partially overlap it.

void _fmpz_poly_pseudo_divrem(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv)

Set QQ, RR and dd such that ℓdA=BQ+R\ell^d A = BQ + R with deg⁡R<deg⁡B\deg R < \deg B, where ℓ=lc⁡(B)\ell = \operatorname{lc}(B) and 0≤d≤lenA−lenB+10 \le d \le \mathit{lenA} - \mathit{lenB} + 1. Factors ℓ\ell are introduced only where a quotient coefficient would otherwise not be an integer, so dd is small when the division is nearly exact. These are the divide-and-conquer functions fmpz_poly_pseudo_divrem_divconquer under another name. Q and R must be distinct, and division by zero raises an exception.

Full documentation
void _fmpz_poly_pseudo_div(fmpz * Q, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv)
void _fmpz_poly_pseudo_rem(fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv)

As fmpz_poly_pseudo_divrem, returning only the quotient, respectively only the remainder, together with dd.

Full documentation

Division algorithms#

int _fmpz_poly_divrem_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact)

Division with remainder by the schoolbook algorithm, with the semantics of fmpz_poly_divrem. The underscore version requires positive lengths, allows zero padding of AA, and allows RR to be equal to AA; no other aliasing is allowed.

int _fmpz_poly_div_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact)

Quotient by the schoolbook algorithm, with the semantics of fmpz_poly_div; only the coefficients of the remainder that are needed for the quotient are updated. The underscore version takes a temporary array RR of length lenA, or NULL to allocate one; RR may be equal to AA; no other aliasing is allowed.

int _fmpz_poly_divrem_divconquer(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact)
int _fmpz_poly_div_divconquer(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact)

Division with remainder, respectively quotient only, by recursive division of the top halves, so that the cost is O(M(n)log⁡n)O(M(n) \log n) coefficient operations for a product cost M(n)M(n), with the semantics of fmpz_poly_divrem and fmpz_poly_div. The underscore versions require lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0, allow zero padding of AA and do not allow aliasing.

int _fmpz_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W, const fmpz * A, const fmpz * B, slong lenB, int exact)
int _fmpz_poly_divremlow_divconquer_recursive(fmpz * Q, fmpz * QB, const fmpz * A, const fmpz * B, slong lenB, int exact)
int _fmpz_poly_div_divconquer_recursive(fmpz * Q, fmpz * temp, const fmpz * A, const fmpz * B, slong lenB, int exact)

The recursive steps of divide-and-conquer division for the balanced case len⁡(A)=2lenB−1\operatorname{len}(A) = 2 \mathit{lenB} - 1: they compute the quotient (Q, lenB), and divrem also the product (BQ, 2 lenB - 1) using the temporary (W, 2 lenB - 1); divremlow computes only the low lenB−1\mathit{lenB} - 1 coefficients of BQBQ correctly (the array must still have room for 2lenB−12 \mathit{lenB} - 1); div uses a temporary (temp, 2 lenB - 1) and does not compute BQBQ [Mul2000]. The low lenB−1\mathit{lenB} - 1 coefficients of AA are not read. They require lenB>0\mathit{lenB} > 0 and do not allow aliasing; exact is as for _fmpz_poly_divrem.

void _fmpz_poly_rem_basecase(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB)

Remainder by the schoolbook algorithm, with the semantics of fmpz_poly_rem. The underscore version writes lenA coefficients and allows RR to be equal to AA; no other aliasing is allowed.

void _fmpz_poly_preinvert(fmpz * B_inv, const fmpz * B, slong n)

Set B_inv to the inverse of the reversal of BB as a power series of length n=len⁡(B)n = \operatorname{len}(B), by Newton iteration, for use with fmpz_poly_div_preinv and fmpz_poly_divrem_preinv. BB must have leading coefficient ±1\pm 1 (for example, be monic). Division by zero raises an exception. The underscore version requires n>0n > 0 and no aliasing.

void _fmpz_poly_div_preinv(fmpz * Q, const fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2)
void fmpz_poly_div_preinv(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t B_inv)

Set QQ to the quotient of AA by BB, given the precomputed inverse B_inv of BB, using a truncated product with the inverse (and splitting AA into blocks if its quotient is longer than BB). BB must have leading coefficient ±1\pm 1. The underscore version requires len1≥len2\mathit{len1} \ge \mathit{len2}, room for len1−len2+1\mathit{len1} - \mathit{len2} + 1 coefficients in QQ, and no aliasing.

void _fmpz_poly_divrem_preinv(fmpz * Q, fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2)

As fmpz_poly_div_preinv, also computing the remainder. The underscore version replaces the low len2−1\mathit{len2} - 1 coefficients of AA by the remainder.

Stores the residues xi mod Bx^i \bmod B for 0≤i<2len⁡(B)−10 \le i < 2 \operatorname{len}(B) - 1, for repeated reduction modulo a fixed monic polynomial BB.

Compute the residues of xix^i modulo the monic polynomial BB of length len for 0≤i<2len−10 \le i < 2 \mathit{len} - 1, each as a vector of len−1\mathit{len} - 1 coefficients. Division by zero raises an exception.

void _fmpz_poly_rem_powers_precomp(fmpz * A, slong m, const fmpz * B, slong n, fmpz ** const powers)

Set RR to A mod BA \bmod B for the monic BB of length nn, as a linear combination of the precomputed residues of xix^i; this costs O(len⁡(A)⋅n)O(\operatorname{len}(A) \cdot n) coefficient operations and is fast for len⁡(A)<2n\operatorname{len}(A) < 2n. The underscore version reduces (A, m) in place, leaving the remainder in its low n−1n - 1 coefficients, and does not allow aliasing.

void fmpz_poly_divlow_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n)

Sets (res, n) to the low nn coefficients of f/gf / g modulo pp, reduced into the symmetric range, assuming that the division is exact modulo pp. Common low zero coefficients are removed first; the lowest nonzero coefficient of gg must be invertible modulo pp, which is not checked. Used by _fmpz_poly_factor_CLD_mat.

void fmpz_poly_divhigh_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n)

Sets (res, n) to the high nn coefficients of f/gf / g modulo pp, reduced into the symmetric range, where ff is the output of fmpz_poly_mulhigh_n applied to gg and a polynomial of length nn (only the top nn coefficients of ff are read). The leading coefficient of gg must be invertible modulo pp, which is not checked. Used by _fmpz_poly_factor_CLD_mat.

void _fmpz_poly_pseudo_divrem_basecase(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv)
void _fmpz_poly_pseudo_divrem_divconquer(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv)

Pseudo-division with the semantics of fmpz_poly_pseudo_divrem, by the schoolbook algorithm, which multiplies the partial remainder by ℓ\ell only when a quotient coefficient would be inexact, respectively by divide and conquer. The underscore basecase version allows RR to be equal to AA; the divide-and-conquer version only sets the low lenB−1\mathit{lenB} - 1 coefficients of (R, lenA) correctly and allows no aliasing. inv is as for _fmpz_poly_pseudo_divrem.

void _fmpz_poly_pseudo_divrem_cohen(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB)
void _fmpz_poly_pseudo_rem_cohen(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB)

Pseudo-division with the exponent fixed at d=max⁡(0,len⁡(A)−len⁡(B)+1)d = \max(0, \operatorname{len}(A) - \operatorname{len}(B) + 1), by Algorithm 3.1.2 of [Coh1996]: ℓdA=BQ+R\ell^d A = BQ + R with deg⁡R<deg⁡B\deg R < \deg B. This is the pseudo-remainder of the subresultant algorithm; it is quadratic and meant for short polynomials. The underscore versions require lenA≥lenB>0\mathit{lenA} \ge \mathit{lenB} > 0, room for lenA\mathit{lenA} coefficients in RR, and allow RR to be equal to AA; no other aliasing.

Content and primitive part#

The content of a nonzero f∈Z[x]f \in \mathbb{Z}[x] is the nonnegative GCD of its coefficients, and the primitive part is ff divided by its content, with the sign chosen so that the leading coefficient is positive. By Gauss' lemma, the content of a product is the product of the contents.

void _fmpz_poly_content(fmpz_t res, const fmpz * poly, slong len)
void fmpz_poly_content(fmpz_t res, const fmpz_poly_t poly)

Set res to the nonnegative content of the polynomial; the content of the zero polynomial is zero. res may be one of the coefficients of poly. The underscore version is _fmpz_vec_content.

void _fmpz_poly_primitive_part(fmpz * res, const fmpz * poly, slong len)

Set res to the primitive part of poly, with positive leading coefficient; the primitive part of zero is zero. The underscore version requires a nonzero polynomial and allows res to be equal to poly.

Greatest common divisors#

The GCD of two polynomials in Z[x]\mathbb{Z}[x] is defined up to sign; these functions return the one with positive leading coefficient, so that gcd⁡(f,g)=gcd⁡(cont⁡f,cont⁡g)⋅gcd⁡(pp⁡f,pp⁡g)\gcd(f, g) = \gcd(\operatorname{cont} f, \operatorname{cont} g) \cdot \gcd(\operatorname{pp} f, \operatorname{pp} g). The GCD of ff and 00 is ±f\pm f, and that of 00 and 00 is 00. See Greatest common divisors and GCDs of polynomials over Z.

void _fmpz_poly_gcd(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_gcd(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Set res to the GCD of poly1 and poly2 with positive leading coefficient. Common powers of xx are removed first. Polynomials of length less than 6 use the subresultant algorithm; otherwise, when the coefficients have at most 40 bits in total, the heuristic GCD is tried, and the multimodular algorithm is used if it fails or the coefficients are larger. The underscore version requires len1≥len2>0\mathit{len1} \ge \mathit{len2} > 0 and writes len2 coefficients (zero padded); res may be equal to an input.

Full documentation
void _fmpz_poly_gcd_modular(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_gcd_modular(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

GCD by the multimodular algorithm: the primitive parts are reduced modulo batches of word-size primes, their monic GCDs modulo each prime are scaled to a common leading (or constant) coefficient and combined by the Chinese remainder theorem, and the candidate is certified by checking that it divides both inputs. The result is always correct. The underscore version has the conventions of _fmpz_poly_gcd.

Full documentation
int _fmpz_poly_gcd_heuristic(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
int fmpz_poly_gcd_heuristic(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Attempt to compute the GCD by the heuristic GCD algorithm GCDHEU [CGG1989], evaluating the primitive parts at a power of two, taking the GCD of the two integers and reconstructing a polynomial from it. Return 1 on success, when the reconstructed polynomial is verified to divide both inputs, and 0 on failure, in which case res is undefined. The underscore version has the conventions of _fmpz_poly_gcd.

Full documentation
void _fmpz_poly_gcd_subresultant(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)

GCD by the subresultant pseudo-remainder sequence, Algorithm 3.3.1 of [Coh1996], which keeps the intermediate coefficients small by exact divisions. It is quadratic in the degree and fast only for short polynomials. The underscore version has the conventions of _fmpz_poly_gcd.

Full documentation
void _fmpz_poly_xgcd(fmpz_t r, fmpz * s, fmpz * t, const fmpz * f, slong len1, const fmpz * g, slong len2)
void _fmpz_poly_xgcd_modular(fmpz_t r, fmpz * s, fmpz * t, const fmpz * f, slong len1, const fmpz * g, slong len2)

Set rr to the resultant of ff and gg and, if r≠0r \ne 0, find ss, tt with deg⁡s<deg⁡g\deg s < \deg g, deg⁡t<deg⁡f\deg t < \deg f and sf+tg=rsf + tg = r. If r=0r = 0 the function returns after setting rr; ss and tt are then not computed and their values are undefined. The functions without _modular are inline wrappers of the multimodular algorithm, which computes the extended GCD modulo word-size primes and combines the cofactors by the Chinese remainder theorem until the identity is proved by a size bound.

Full documentation
void _fmpz_poly_lcm(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_lcm(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Set res to the least common multiple fg/gcd⁡(f,g)fg / \gcd(f, g) of the two polynomials with nonnegative leading coefficient, so that fg=±gcd⁡(f,g)lcm⁡(f,g)fg = \pm \gcd(f, g) \operatorname{lcm}(f, g). The LCM is zero if either input is zero. The underscore version requires len1≥len2>0\mathit{len1} \ge \mathit{len2} > 0, writes len1+len2−1\mathit{len1} + \mathit{len2} - 1 coefficients (zero padded) and does not allow aliasing.

Full documentation

Resultants and discriminants#

For nonzero f=a∏i=1m(x−αi)f = a \prod_{i=1}^m (x - \alpha_i) and g=b∏j=1n(x−βj)g = b \prod_{j=1}^n (x - \beta_j), the resultant is

res⁡(f,g)=anbm∏i,j(αi−βj)=an∏ig(αi),\operatorname{res}(f, g) = a^n b^m \prod_{i, j} (\alpha_i - \beta_j) = a^n \prod_i g(\alpha_i),

the determinant of the Sylvester matrix; it is zero if either polynomial is zero. See Resultants and discriminants and Resultants and discriminants over Z.

void _fmpz_poly_resultant(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_resultant(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Set res to the resultant of poly1 and poly2. The function uses the subresultant algorithm (fmpz_poly_resultant_euclidean) for short polynomials with small coefficients and the multimodular algorithm otherwise: when len2>144\mathit{len2} > 144 or len23(b1+b2)>6⋅106\mathit{len2}^3 (b_1 + b_2) > 6 \cdot 10^6, where b1b_1, b2b_2 are the bit sizes of the coefficients. The underscore version requires len1≥len2>0\mathit{len1} \ge \mathit{len2} > 0.

Full documentation
void _fmpz_poly_resultant_modular(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_resultant_modular(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Resultant by the multimodular algorithm [Col1971]: the contents are removed, the resultant of the primitive parts is computed modulo enough 64-bit primes to exceed twice the Hadamard bound ∥f∥2deg⁡g∥g∥2deg⁡f\|f\|_2^{\deg g} \|g\|_2^{\deg f}, and the images are combined by the Chinese remainder theorem. The underscore version requires len1≥len2>0\mathit{len1} \ge \mathit{len2} > 0.

Full documentation
void _fmpz_poly_resultant_modular_div(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_t divisor, slong nbits)
void fmpz_poly_resultant_modular_div(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t divisor, slong nbits)

Set res to the resultant of poly1 and poly2 divided by divisor, assuming that the division is exact and that the quotient has at most nbits bits in absolute value. Only enough primes for nbits bits are used, instead of the general bound; this is used when the size of the result is known in advance, as for discriminants of number fields. If divisor is zero, res is set to zero. The underscore version requires len1≥len2>0\mathit{len1} \ge \mathit{len2} > 0. The number of primes is chosen so that their product exceeds 2nbits+12^{\mathit{nbits} + 1}, as the signed reconstruction requires.

Full documentation
void _fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Resultant by the subresultant algorithm, Algorithm 3.3.7 of [Coh1996], with exact divisions that keep the coefficients of the remainders of the size of minors of the Sylvester matrix. The underscore version requires len1≥len2>0\mathit{len1} \ge \mathit{len2} > 0.

Full documentation
void _fmpz_poly_discriminant(fmpz_t res, const fmpz * poly, slong len)

Set res to the discriminant of ff = poly of degree nn,

disc⁡(f)=(−1)n(n−1)/2lc⁡(f)res⁡(f,f′)=lc⁡(f)2n−2∏i<j(αi−αj)2,\operatorname{disc}(f) = \frac{(-1)^{n(n-1)/2}}{\operatorname{lc}(f)} \operatorname{res}(f, f') = \operatorname{lc}(f)^{2n-2} \prod_{i < j} (\alpha_i - \alpha_j)^2,

where α1,…,αn\alpha_1, \ldots, \alpha_n are the roots of ff. The discriminant of a polynomial of degree 1 is 1, and that of a constant or zero polynomial is defined to be 0. The underscore version requires len>1\mathit{len} > 1.

Full documentation

Squarefree polynomials#

int _fmpz_poly_is_squarefree(const fmpz * poly, slong len)

Return whether the polynomial has no repeated factor of positive degree, that is, whether it is squarefree in Q[x]\mathbb{Q}[x]; the content is ignored, so 4x+44x + 4 counts as squarefree. Polynomials of length at most 2 are squarefree, including zero; quadratics are tested with the discriminant, and longer polynomials by checking that gcd⁡(f,f′)\gcd(f, f') is constant.

Sets res to f/gcd⁡(f,f′)f / \gcd(f, f') for ff = poly, with positive leading coefficient: the product of the distinct irreducible factors of positive degree of ff, times a constant. The squarefree part of a nonzero constant is 1 and that of zero is zero.

Derivatives#

void _fmpz_poly_derivative(fmpz * rpoly, const fmpz * poly, slong len)

Set res to the derivative of poly. The underscore version writes len - 1 coefficients, handles len≤1\mathit{len} \le 1, and allows rpoly to be equal to poly.

void _fmpz_poly_nth_derivative(fmpz * rpoly, const fmpz * poly, ulong n, slong len)

Set res to the nn-th derivative of poly. The underscore version writes len - n coefficients, handles len≤n\mathit{len} \le n, and allows rpoly to be equal to poly.

Evaluation#

void _fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a)
void fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a)

Set res to f(a)f(a) for an integer aa, by Horner's rule for length at most 50 and by the divide-and-conquer algorithm otherwise. In the non-underscore version res may be equal to aa; in both versions res must not be a coefficient of ff, and in the underscore version it must not be aa. See Evaluation.

Full documentation
void _fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a)
void _fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz * poly, slong len, const fmpz_t a)

Evaluate at an integer by Horner's rule, respectively by splitting f=f0+amf1f = f_0 + a^m f_1 recursively, which balances the sizes of the integer products so that they can use fast multiplication. The aliasing rules are those of fmpz_poly_evaluate_fmpz; the divide-and-conquer underscore version requires len≥1\mathit{len} \ge 1 and allows zero padding.

Full documentation
void _fmpz_poly_evaluate_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden)
void fmpz_poly_evaluate_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a)

Set res to f(a)f(a) for a rational aa, in lowest terms, by Horner's rule for short polynomials or large denominators, and by divide and conquer otherwise. The underscore version takes aa = anum/aden in lowest terms with positive denominator and sets (rnum, rden); the outputs must not be aliased with the inputs or the coefficients. The non-underscore version allows res to be equal to aa.

Full documentation
void _fmpz_poly_evaluate_horner_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden)
void _fmpz_poly_evaluate_divconquer_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden)

Evaluate at a rational number by Horner's rule, respectively by divide and conquer, with the conventions of fmpz_poly_evaluate_fmpq. The divide-and-conquer underscore version requires len≥1\mathit{len} \ge 1.

Full documentation
ulong _fmpz_poly_evaluate_mod(const fmpz * poly, slong len, ulong a, ulong n, ulong ninv)

Return f(a) mod nf(a) \bmod n for a word-size modulus n≥1n \ge 1, by Horner's rule with each coefficient reduced modulo nn. The underscore version takes the precomputed inverse ninv = n_preinvert_limb(n).

Full documentation
void fmpz_poly_evaluate_fmpz_vec(fmpz * res, const fmpz_poly_t f, const fmpz * a, slong n)

Sets res[i] to f(ai)f(a_i) for the nn integers in a, one at a time with fmpz_poly_evaluate_fmpz.

Full documentation
double _fmpz_poly_evaluate_horner_d(const fmpz * poly, slong n, double d)
double fmpz_poly_evaluate_horner_d(const fmpz_poly_t poly, double d)

Return an approximation of f(d)f(d) computed by Horner's rule in double precision, with no control of the error and no protection against overflow. Meant for quick estimates, for example for polynomials with nonnegative coefficients evaluated at d>0d > 0.

double _fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz * poly, slong n, double d)
double fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz_poly_t poly, double d)
double _fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz * poly, slong n, double d, slong dexp)
double fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz_poly_t poly, double d, slong dexp)

Return mm and set *exp to ee such that m2em 2^e approximates f(d)f(d), respectively f(d⋅2dexp)f(d \cdot 2^{\mathit{dexp}}), by Horner's rule in a floating-point format with a double mantissa and a separate exponent, which cannot overflow. As for fmpz_poly_evaluate_horner_d, the error is not controlled; cancellation can make the result meaningless for polynomials with coefficients of both signs.

Multipoint evaluation and interpolation#

int _fmpz_poly_interpolate(fmpz * poly, const fmpz * xs, const fmpz * ys, slong n)
int fmpz_poly_interpolate(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n)
int _fmpz_poly_interpolate_newton(fmpz * poly, const fmpz * xs, const fmpz * ys, slong n)
int fmpz_poly_interpolate_newton(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n)
int _fmpz_poly_interpolate_multi_mod(fmpz * poly, const fmpz * xs, const fmpz * ys, slong n)
int fmpz_poly_interpolate_multi_mod(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n)

Set poly to the polynomial ff of degree less than nn with f(xi)=yif(x_i) = y_i for 0≤i<n0 \le i < n and return 1, if the xix_i are distinct and ff has integer coefficients; otherwise return 0. The newton version computes divided differences, failing at the first inexact division, and converts from the Newton basis; the multi_mod version interpolates modulo word-size primes (with a fast algorithm for many points) and combines the results by the Chinese remainder theorem until they stabilise and are checked. The default uses Newton interpolation for n≤25n \le 25 and chooses by size otherwise. The underscore versions write nn coefficients.

void _fmpz_poly_interpolate_exact(fmpz * poly, const fmpz * xs, const fmpz * ys, slong n)
void fmpz_poly_interpolate_exact(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n)
void _fmpz_poly_interpolate_exact_newton(fmpz * poly, const fmpz * xs, const fmpz * ys, slong n)
void fmpz_poly_interpolate_exact_newton(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n)

As fmpz_poly_interpolate and fmpz_poly_interpolate_newton, but assuming that the xix_i are distinct and that the interpolating polynomial has integer coefficients; this is not checked, and the result is undefined otherwise. The default uses Newton interpolation for n≤70n \le 70 and the multimodular algorithm otherwise.

void fmpz_poly_interpolate_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n)

As fmpz_poly_interpolate, but raises a FLINT_INEXACT exception if the xix_i are not distinct or the interpolating polynomial does not have integer coefficients.

void _fmpz_poly_monomial_to_newton(fmpz * poly, const fmpz * roots, slong n)
void _fmpz_poly_newton_to_monomial(fmpz * poly, const fmpz * roots, slong n)

Convert (poly, n) in place between the monomial basis and the Newton basis 1,(x−r0),(x−r0)(x−r1),…,(x−r0)⋯(x−rn−2)1, (x - r_0), (x - r_0)(x - r_1), \ldots, (x - r_0) \cdots (x - r_{n-2}) for the integers rir_i in roots: monomial_to_newton finds the cic_i with f=∑ici∏j<i(x−rj)f = \sum_i c_i \prod_{j < i} (x - r_j) by repeated synthetic division, and newton_to_monomial evaluates such a sum by Horner's rule.

void _fmpz_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n)

Set poly to (x−x0)(x−x1)⋯(x−xn−1)(x - x_0)(x - x_1) \cdots (x - x_{n-1}). The underscore version writes n+1n + 1 coefficients and does not allow aliasing.

void _fmpz_poly_product_roots_fmpq_vec(fmpz * poly, const fmpq * xs, slong n)

Set poly to (q0x−p0)⋯(qn−1x−pn−1)(q_0 x - p_0) \cdots (q_{n-1} x - p_{n-1}) for the rational numbers xi=pi/qix_i = p_i / q_i in xs, the primitive polynomial in Z[x]\mathbb{Z}[x] with roots xix_i when they are given in lowest terms. The underscore version writes n+1n + 1 coefficients.

void _fmpz_poly_tree_free(fmpz ** tree, slong len)

Allocate and free a subproduct tree for len linear factors. Level ii of the tree is one array that holds the ⌊len/2i⌋\lfloor \mathit{len}/2^i \rfloor products of 2i2^i linear factors, each stored with 2i+12^i + 1 coefficients, followed by the product of the remaining factors if 2i2^i does not divide len.

void _fmpz_poly_tree_build_fmpq_vec(fmpz ** tree, const fmpq * roots, slong len)

Fills the tree allocated by _fmpz_poly_tree_alloc with the products of the linear factors qix−piq_i x - p_i for the roots pi/qip_i / q_i; the product at the top level is not computed.

Composition and Taylor shift#

void _fmpz_poly_compose(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_compose(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)

Set res to the composition g(h(x))g(h(x)) of gg = poly1 and hh = poly2. Inner polynomials of the form axn+bax^n + b use a Taylor shift and a scaling, short outer polynomials Horner's rule, and others the divide-and-conquer algorithm. The underscore version requires positive lengths, writes (len1−1)(len2−1)+1(\mathit{len1} - 1)(\mathit{len2} - 1) + 1 coefficients and does not allow aliasing. See Composition and Taylor shifts.

Full documentation
void _fmpz_poly_compose_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
void fmpz_poly_compose_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2)
void _fmpz_poly_compose_divconquer(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)

Composition by Horner's rule, respectively by the divide-and-conquer algorithm that splits gg into blocks evaluated at hh and combines them with the powers h2kh^{2^k}. The underscore versions have the conventions of _fmpz_poly_compose.

Full documentation
void _fmpz_poly_taylor_shift(fmpz * poly, const fmpz_t c, slong n)

Set gg to f(x+c)f(x + c); the underscore version shifts (poly, n) in place. It uses Horner's scheme for length less than 64 and the divide-and-conquer algorithm otherwise.

Full documentation

Taylor shift by Horner's scheme, O(n2)O(n^2) additions and multiplications by cc (only additions for c=±1c = \pm 1).

Full documentation

Taylor shift by divide and conquer, f0(x+c)+(x+c)mf1(x+c)f_0(x + c) + (x + c)^m f_1(x + c) with the powers of x+cx + c computed by the binomial theorem; the two halves are shifted in parallel when threads are available. Short inputs use Horner's scheme, with a cutoff that grows with the size of the coefficients.

Full documentation

Taylor shift by a multimodular algorithm: the shift is computed modulo enough word-size primes for a bound on the result and combined by the Chinese remainder theorem, using flint_get_num_threads threads.

Full documentation

Power series#

These functions treat polynomials as power series truncated to length nn, that is, as elements of Z[[x]]/(xn)\mathbb{Z}[[x]]/(x^n). See Power series and Newton iteration for power series and division.

void _fmpz_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n)

Set Qinv to the inverse of the power series QQ modulo xnx^n, which requires the constant term of QQ to be ±1\pm 1; this is not checked. The basecase recurrence is used when QQ or nn is shorter than 64, Newton iteration otherwise. A zero QQ or n=0n = 0 raises an exception. The underscore version requires n≥1n \ge 1, writes nn coefficients and does not allow aliasing.

Full documentation
void _fmpz_poly_inv_series_basecase(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n)
void _fmpz_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n)

Power series inversion by the recurrence bk=−b0∑j=1kqjbk−jb_k = -b_0 \sum_{j=1}^{k} q_j b_{k-j}, with word-size arithmetic while the sizes allow and a special case for binomials, respectively by Newton iteration. The conventions are those of fmpz_poly_inv_series.

Full documentation
void _fmpz_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n)

Set QQ to the quotient A/BA/B of power series modulo xnx^n. The constant term of BB must be nonzero and the quotient must have integer coefficients, which holds in particular if B(0)=±1B(0) = \pm 1; an inexact division raises an exception. For B(0)=±1B(0) = \pm 1 and lengths at least 72 the function multiplies by the inverse of BB; otherwise it uses the basecase recurrence or, for long inputs, divide and conquer. A zero BB raises an exception. The underscore version requires n≥1n \ge 1, writes nn coefficients and does not allow aliasing.

Full documentation
void _fmpz_poly_div_series_basecase(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n)
void _fmpz_poly_div_series_divconquer(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n)

Power series division by the recurrence, respectively by divide-and-conquer division of the reversed polynomials, with the conventions of fmpz_poly_div_series.

Full documentation
void _fmpz_poly_compose_series(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n)
void fmpz_poly_compose_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n)

Set res to g(h(x)) mod xng(h(x)) \bmod x^n for gg = poly1 and hh = poly2, where h(0)h(0) must be zero; otherwise an exception is raised. The function uses Horner's scheme for len1≤10\mathit{len1} \le 10, the Brent–Kung baby-step giant-step algorithm [BrentKung1978] for n<500n < 500 and the algorithm of Kinoshita and Li [KL2024] otherwise. The underscore version requires 0<len1,len2≤n0 < \mathit{len1}, \mathit{len2} \le n, writes nn coefficients and does not allow aliasing; the non-underscore version first reduces nn to at most (len1−1)(len2−1)+1(\mathit{len1} - 1)(\mathit{len2} - 1) + 1.

Full documentation
void _fmpz_poly_compose_series_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n)
void _fmpz_poly_compose_series_brent_kung(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n)

Power series composition by Horner's scheme, respectively by Algorithm 2.1 of [BrentKung1978], with the conventions of fmpz_poly_compose_series.

Full documentation
void _fmpz_poly_revert_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n)

Set Qinv to the compositional inverse of the power series QQ modulo xnx^n, so that Q(Q−1(x))=Q−1(Q(x))=x mod xnQ(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n. Requires Q(0)=0Q(0) = 0 and Q′(0)=±1Q'(0) = \pm 1, which is not checked.

Full documentation
int _fmpz_poly_sqrt_series(fmpz * res, const fmpz * poly, slong len, slong n)

If the power series aa of precision nn has a square root in Z[[x]]\mathbb{Z}[[x]], set bb to it (the one with positive lowest coefficient) and return 1; otherwise return 0. If aa has valuation 2v>02v > 0, the square root is only determined to precision n−vn - v, and the underscore version pads with zeros. The underscore version writes nn coefficients.

Full documentation

Square roots#

int _fmpz_poly_sqrt(fmpz * res, const fmpz * poly, slong len)

If aa is the square of a polynomial in Z[x]\mathbb{Z}[x], set bb to the square root with positive leading coefficient and return 1; otherwise return 0. The heuristic _fmpz_poly_sqrt_KS is tried first, and the divide-and-conquer algorithm is used if it fails. The underscore version writes len / 2 + 1 coefficients.

int _fmpz_poly_sqrt_classical(fmpz * res, const fmpz * poly, slong len, int exact)
int _fmpz_poly_sqrt_divconquer(fmpz * res, const fmpz * poly, slong len, int exact)

Square root with the conventions of fmpz_poly_sqrt, computed from the top coefficient down, by the classical O(n2)O(n^2) algorithm, respectively by divide and conquer. Most non-squares are detected early by cheap tests: the length must be odd, the valuation even, the leading and constant coefficients squares, and certain coefficients even (the square root must exist modulo 2). If exact is 0, the underscore versions only compute the top half of the root and allow a remainder, which is not computed.

int _fmpz_poly_sqrt_KS(fmpz * rop, const fmpz * op, slong len)

Heuristic square root by Kronecker substitution: after the same quick tests as the classical algorithm, the integer square root of a(2k)a(2^k), for kk a few bits more than the coefficients of aa, is unpacked and checked. Return −1-1 if the heuristic is inconclusive, and otherwise 1 or 0 as fmpz_poly_sqrt.

int _fmpz_poly_sqrtrem_classical(fmpz * res, fmpz * r, const fmpz * poly, slong len)
int _fmpz_poly_sqrtrem_divconquer(fmpz * res, fmpz * r, const fmpz * poly, slong len, fmpz * temp)

If aa can be written as b2+rb^2 + r with b∈Z[x]b \in \mathbb{Z}[x] and deg⁡r<deg⁡a/2\deg r < \deg a / 2 (equivalently, deg⁡r<deg⁡b\deg r < \deg b), set bb and rr and return 1; otherwise return 0. The underscore versions write len/2+1\mathit{len}/2 + 1 coefficients of bb and require room for len coefficients in rr, which may be equal to poly; the divide-and-conquer version also takes a temporary array of len coefficients.

Power sums#

For a monic f=∏i=1d(x−αi)f = \prod_{i=1}^d (x - \alpha_i), the power sums are pk=∑iαikp_k = \sum_i \alpha_i^k, and the power sum series is ∑k≥0pkxk=d−xfrev′(x)/frev(x)\sum_{k \ge 0} p_k x^k = d - x f_{\mathrm{rev}}'(x) / f_{\mathrm{rev}}(x), where frev=xdf(1/x)f_{\mathrm{rev}} = x^d f(1/x). These sums determine ff by Newton's identities.

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

Set res to the power sums p0,…,pn−1p_0, \ldots, p_{n-1} of the roots of the monic polynomial poly, computed with Newton's identities; the roots at zero are counted in p0p_0 only. A zero polynomial raises an exception in fmpz_poly_power_sums. The underscore version writes nn coefficients.

void _fmpz_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, slong len)

Set res to the monic polynomial whose roots have the power sums given by QQ, with p0=Q(0)p_0 = Q(0) the degree, using Newton's identities; the power sums must be those of a polynomial in Z[x]\mathbb{Z}[x].

Integer and rational roots#

slong fmpz_poly_roots_fmpz(fmpz * res, slong * exp, const fmpz_poly_t poly)
slong fmpz_poly_roots_fmpq(fmpq * res, slong * exp, const fmpz_poly_t poly)

Compute the distinct integer (respectively rational) roots of the nonzero polynomial poly, write them to res in increasing order and return their number. If exp is not NULL, the multiplicities are written to exp. The arrays must have room for deg⁡(poly)\deg(\mathit{poly}) entries. A zero polynomial raises an exception.

More

Write the integer (respectively rational) roots of (poly, len) to res in no particular order and return their number. The polynomial must be squarefree, with len≥1\mathit{len} \ge 1 and a nonzero constant coefficient; res must have room for len−1\mathit{len} - 1 entries.

void _fmpz_poly_bound_roots(fmpz_t bound, const fmpz * poly, slong len)
void fmpz_poly_bound_roots(fmpz_t bound, const fmpz_poly_t poly)

Set bound to a nonnegative integer that is intended to bound the absolute values of all complex roots, computed from Fujiwara's bound [Fuj1916]

2max⁡(∣an−1an∣,∣an−2an∣1/2,…,∣a1an∣1/(n−1),∣a02an∣1/n)2 \max \left( \left|\frac{a_{n-1}}{a_n}\right|, \left|\frac{a_{n-2}}{a_n}\right|^{1/2}, \ldots, \left|\frac{a_1}{a_n}\right|^{1/(n-1)}, \left|\frac{a_0}{2 a_n}\right|^{1/n} \right)

for f=∑i=0naixif = \sum_{i=0}^n a_i x^i, with each term rounded up to an integer (for n≥2n \ge 2, as ⌊⋅⌋+1\lfloor \cdot \rfloor + 1). The bound is zero for constant polynomials.

Real roots#

Unless stated otherwise, the functions in this section assume that the polynomial is squarefree; the results are undefined otherwise, and some functions raise an exception. Roots at zero are counted where noted. See Counting and isolating real roots over Z. For numerical enclosures of the real or complex roots, see Isolating the roots of integer polynomials.

Return the number of real roots of the squarefree polynomial poly, including a root at zero. A zero polynomial raises an exception.

More
void _fmpz_poly_num_real_roots_sturm(slong * n_neg, slong * n_pos, const fmpz * pol, slong len)

Count real roots with a Sturm sequence computed as the subresultant pseudo-remainder sequence (with _fmpz_poly_pseudo_rem_cohen). The underscore version sets the numbers of negative and positive roots and requires a squarefree polynomial of degree at least 2 with nonzero constant coefficient.

slong _fmpz_poly_num_real_roots_sturm_bounded(const fmpz * pol, slong len, int on_0_1, slong max_size)

Counts the real roots (all of them if on_0_1 is zero, those in (0,1)(0, 1) otherwise) with a Sturm sequence computed as a primitive pseudo-remainder sequence, removing the content after each step. Returns −1-1 as soon as a remainder has length times coefficient bit size larger than max_size; pass WORD_MAX to always finish.

More

Count real roots with the Vincent–Collins–Akritas algorithm, by isolating them with _fmpz_poly_isolate_real_roots_0_1_vca after scaling the positive and negative roots into (0,1)(0, 1).

Return the number of roots of the squarefree polynomial pol in the open interval (0,1)(0, 1). The default first applies Descartes' rule of signs on (0,1)(0, 1), which settles most generic polynomials, then tries the primitive Sturm sequence with a growth bound and falls back on the Vincent–Collins–Akritas algorithm. A zero polynomial raises an exception.

Returns an upper bound for the number of real roots of pol, counted with multiplicity: the multiplicity of the root at zero plus the Descartes bounds for the positive and the negative roots, each computed after scaling the roots into (0,1)(0, 1). The polynomial need not be squarefree. A zero polynomial raises an exception.

Returns the number of sign variations of (1+x)np(1/(1+x))(1 + x)^{n} p(1/(1 + x)), which bounds the number of roots of (p, len) in (0,1)(0, 1) and has the same parity (Descartes' rule of signs), or WORD_MAX as soon as the count exceeds bound.

int _fmpz_poly_has_real_root(const fmpz * p, slong len)

Return whether the squarefree polynomial has a real root. Odd degree, a root at zero, a sign change between 00 and ∞\infty, or an odd number of sign variations of f(x)f(x) or f(−x)f(-x) answer immediately; otherwise the real roots are counted.

Return ee such that 2e2^e is an upper bound (not necessarily strict) for the positive real roots of pol, computed with the local-max bound of Akritas, Strzeboński and Vigklas [ASV2008] as implemented in SLV by Tsigaridas; WORD_MIN is returned if the bound shows that there are no positive roots. The non-underscore version returns 0 for the zero polynomial and ignores roots at zero.

void _fmpz_poly_isolate_real_roots_0_1_vca(fmpq * exact_roots, slong * n_exact_roots, fmpz * c_array, slong * k_array, slong * n_intervals, const fmpz * pol, slong len)

Isolates the roots of (pol, len) in the open interval (0,1)(0, 1) with the Vincent–Collins–Akritas bisection algorithm. Roots found exactly (dyadic numbers) are appended to exact_roots, incrementing *n_exact_roots; every other root is enclosed in an interval (c 2k,(c+1)2k)(c\,2^k, (c + 1) 2^k) containing exactly one root, appended as cc = c_array[i] and kk = k_array[i], incrementing *n_intervals. If exact_roots, respectively c_array or k_array, is NULL, only the counters are updated.

void fmpz_poly_isolate_real_roots(fmpq * exact_roots, slong * n_exact, fmpz * c_array, slong * k_array, slong * n_interval, const fmpz_poly_t pol)
void fmpz_poly_isolate_positive_roots(fmpq * exact_roots, slong * n_exact, fmpz * c_array, slong * k_array, slong * n_interval, const fmpz_poly_t pol)

Isolate the real (respectively strictly positive) roots of the squarefree polynomial pol. Exact dyadic roots are written to exact_roots and counted in *n_exact; the other roots are enclosed in disjoint open intervals (c 2k,(c+1)2k)(c\,2^k, (c + 1) 2^k) with cc = c_array[i] and kk = k_array[i], counted in *n_interval. The arrays must have room for deg⁡(pol)\deg(\mathit{pol}) entries.

More
void _fmpz_poly_signature(slong * r1, slong * r2, const fmpz * poly, slong len)
void fmpz_poly_signature(slong * r1, slong * r2, const fmpz_poly_t poly)

Set (r1,r2)(r_1, r_2) to the signature of the squarefree polynomial poly: it has r1r_1 real roots and r2r_2 pairs of complex conjugate roots. Uses a Sturm sequence, Algorithm 4.1.11 of [Coh1996]. The zero polynomial gives (0,0)(0, 0); for a polynomial that is not squarefree the result is undefined and an exception may be raised.

Modular reduction and reconstruction#

Sets res to poly reduced modulo the modulus of res.

Set res to the lift of poly with coefficients in the symmetric range [−m/2,m/2)[-m/2, m/2), respectively in [0,m)[0, m), where mm is the modulus of poly.

void _fmpz_poly_CRT_ui_precomp(fmpz * res, const fmpz * poly1, slong len1, const fmpz_t m1, nn_srcptr poly2, slong len2, ulong m2, ulong m2inv, fmpz_t m1m2, ulong c, int sign)
void _fmpz_poly_CRT_ui(fmpz * res, const fmpz * poly1, slong len1, const fmpz_t m1, nn_srcptr poly2, slong len2, ulong m2, ulong m2inv, int sign)

Set res to the polynomial congruent to (poly1, len1) modulo m1m_1 and to (poly2, len2) modulo the word-size m2m_2, with coefficients in [0,m1m2)[0, m_1 m_2) if sign = 0 and in [−m1m2/2,m1m2/2)[-m_1 m_2/2, m_1 m_2/2) if sign = 1, writing max⁡(len1,len2)\max(\mathit{len1}, \mathit{len2}) coefficients. The moduli must be coprime. m2inv is n_preinvert_limb(m2); the precomp version also takes m1m2m_1 m_2 and c=m1−1 mod m2c = m_1^{-1} \bmod m_2, which the other version computes, raising an exception if m1m_1 is not invertible modulo m2m_2. res may be equal to poly1.

void fmpz_poly_CRT_ui(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_t m1, const nmod_poly_t poly2, int sign)

Sets res to the CRT combination of poly1 modulo m1m_1 and poly2 modulo its modulus m2m_2, coprime to m1m_1, with coefficients in [0,m1m2)[0, m_1 m_2) if sign = 0 and in [−m1m2/2,m1m2/2)[-m_1 m_2/2, m_1 m_2/2) if sign = 1.

Hensel lifting#

These functions lift a factorisation f≡ℓ g1⋯gr(modp)f \equiv \ell\, g_1 \cdots g_r \pmod p into pairwise coprime monic factors to a factorisation modulo pNp^N, as needed for factoring over Z\mathbb{Z}; see Hensel lifting for the algorithm and fmpz_poly_hensel_lift_once for the simplest entry point. The factors are lifted along a binary tree whose nodes hold products of factors and Bézout cofactors, with quadratic lifting pe→p2ep^e \to p^{2e}.

Lifts the r≥2r \ge 2 factors in local_fac of ff modulo a prime pp (the modulus of the factors) to factors modulo pNp^N, stored in the same order in lifted_fac. The factors must be monic, pairwise coprime, of product f/lc⁡(f)f / \operatorname{lc}(f) modulo pp, and lc⁡(f)\operatorname{lc}(f) must not be divisible by pp; the lifted factors are monic with product f/lc⁡(f)f / \operatorname{lc}(f) modulo pNp^N. The lift cannot be continued afterwards.

slong _fmpz_poly_hensel_start_lift(fmpz_poly_factor_t lifted_fac, slong * link, fmpz_poly_t * v, fmpz_poly_t * w, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, slong target_exp)

Builds the Hensel tree for the r≥2r \ge 2 local factors in local_fac of ff (with the conditions of fmpz_poly_hensel_lift_once) and lifts them to precision pNp^N with NN = target_exp ≥1\ge 1, storing the lifted factors in lifted_fac in the original order. link, v and w must be arrays of 2r−22r - 2 entries (initialised polynomials for v, w), which hold the tree on return so that the lift can be continued. Returns the exponent ee to which the cofactors are known, to be passed as prev to _fmpz_poly_hensel_continue_lift.

Continues a lift started by _fmpz_poly_hensel_start_lift: the factors in the tree (link, v, w) are known modulo pcurrp^{\mathit{curr}} and the cofactors modulo pprevp^{\mathit{prev}}, as returned by the previous call; the factors are lifted to pNp^N for N>curr≥1N > \mathit{curr} \ge 1 and written to lifted_fac. Returns the new value of prev.

Builds a Hensel tree from the rr local factors in fac. The arrays link, v and w have 2r−22r - 2 entries. The tree is built by repeatedly multiplying the two factors (or products) of smallest degree, so that it is balanced by degree; v holds the factors and products, with v[2r - 4] and v[2r - 3] the two children of the root, and w holds the Bézout cofactors, v2iw2i+v2i+1w2i+1≡1(modp)v_{2i} w_{2i} + v_{2i+1} w_{2i+1} \equiv 1 \pmod p. A negative link[j] means that v[j] is the original factor number -link[j] - 1; a nonnegative link[j] means that v[j] is the product of v[link[j]] and v[link[j] + 1].

void fmpz_poly_hensel_lift(fmpz_poly_t Gout, fmpz_poly_t Hout, fmpz_poly_t Aout, fmpz_poly_t Bout, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1)

One Hensel step for a factorisation into two factors: given f≡ghf \equiv gh and ag+bh≡1ag + bh \equiv 1 modulo pp, with gg and hh monic, computes G≡gG \equiv g, H≡hH \equiv h, A≡aA \equiv a, B≡bB \equiv b modulo pp with f≡GHf \equiv GH and AG+BH≡1AG + BH \equiv 1 modulo P=pp1P = p p_1:

G=g+p(f−ghp b mod g),H=h+p(f−ghp a mod h),B=b+p(1−aG−bHp b mod g),A=a+p(1−aG−bHp a mod h),\begin{aligned} G &= g + p \left( \tfrac{f - gh}{p}\, b \bmod g \right), & H &= h + p \left( \tfrac{f - gh}{p}\, a \bmod h \right), \\ B &= b + p \left( \tfrac{1 - aG - bH}{p}\, b \bmod g \right), & A &= a + p \left( \tfrac{1 - aG - bH}{p}\, a \bmod h \right), \end{aligned}

with the products reduced modulo p1p_1. Requires 1<p1≤p1 < p_1 \le p (so p1∣pp_1 \mid p for prime powers of the same prime), f,g,hf, g, h of degree at least 1, and a,ba, b nonzero. The outputs G,H,A,BG, H, A, B may be aliased only with g,h,a,bg, h, a, b respectively.

void _fmpz_poly_hensel_lift_without_inverse(fmpz * G, fmpz * H, const fmpz * f, slong lenF, const fmpz * g, slong lenG, const fmpz * h, slong lenH, const fmpz * a, slong lenA, const fmpz * b, slong lenB, const fmpz_t p, const fmpz_t p1)
void fmpz_poly_hensel_lift_without_inverse(fmpz_poly_t Gout, fmpz_poly_t Hout, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1)

As fmpz_poly_hensel_lift, lifting only the factors gg and hh.

void _fmpz_poly_hensel_lift_only_inverse(fmpz * A, fmpz * B, const fmpz * G, slong lenG, const fmpz * H, slong lenH, const fmpz * a, slong lenA, const fmpz * b, slong lenB, const fmpz_t p, const fmpz_t p1)
void fmpz_poly_hensel_lift_only_inverse(fmpz_poly_t Aout, fmpz_poly_t Bout, const fmpz_poly_t G, const fmpz_poly_t H, const fmpz_poly_t a, const fmpz_poly_t b, const fmpz_t p, const fmpz_t p1)

As fmpz_poly_hensel_lift, lifting only the cofactors, given the already lifted factors GG and HH.

Lifts the subtree of the Hensel tree (link, v, w) rooted at the pair v[j], v[j + 1], whose product is ff, from modulus p0p_0 to P=p0p1P = p_0 p_1 with 1<p1≤p01 < p_1 \le p_0. The cofactors are lifted if inv is 1, and not lifted if it is 0 (for the last step); with −1-1 the cofactors are lifted from the previous precision (when a lift is restarted). ff may be aliased with an entry of v or w, but the entries of v and w must be distinct.

More
void fmpz_poly_hensel_lift_tree(slong * link, fmpz_poly_t * v, fmpz_poly_t * w, fmpz_poly_t f, slong r, const fmpz_t p, slong e0, slong e1, slong inv)

Lifts the whole Hensel tree for the rr factors of the monic ff from pe0p^{e_0} to pe1p^{e_1}, where e0<e1≤2e0e_0 < e_1 \le 2 e_0, by calling fmpz_poly_hensel_lift_tree_recursive at the root with p0=pe0p_0 = p^{e_0} and p1=pe1−e0p_1 = p^{e_1 - e_0}. inv is as for that function.

Special polynomials#

void _fmpz_poly_cyclotomic(fmpz * a, ulong n, nn_ptr factors, slong num_factors, ulong phi)

Set poly to the cyclotomic polynomial Φn(x)=∏ω(x−ω)\Phi_n(x) = \prod_\omega (x - \omega), where ω\omega runs over the primitive nn-th roots of unity. The non-underscore version writes n=qsn = qs with qq squarefree and uses Φn(x)=Φq(xs)\Phi_n(x) = \Phi_q(x^s).

More

If poly is a cyclotomic polynomial Φn\Phi_n, return nn; otherwise return 0.

Set ff to the minimal polynomial of 2cos⁡(2π/n)2 \cos(2\pi/n), which is monic with integer coefficients [WaktinsZeitlin1993]; substituting x→2xx \to 2x gives the minimal polynomial of cos⁡(2π/n)\cos(2\pi/n) up to a constant. Its degree is φ(n)/2\varphi(n)/2 for n>2n > 2 and 1 for n=1,2n = 1, 2; for n=0n = 0 the result is defined to be 1. Suitable nn give the minimal polynomials of 2cos⁡(aπ)2 \cos(a\pi) and 2sin⁡(aπ)2 \sin(a\pi) for all rational aa.

Set poly to the Swinnerton-Dyer polynomial Sn=∏(x±2±3±5±⋯±pn)S_n = \prod (x \pm \sqrt{2} \pm \sqrt{3} \pm \sqrt{5} \pm \cdots \pm \sqrt{p_n}), where pnp_n is the nn-th prime and all sign combinations are taken. It has degree 2n2^n and is irreducible over Z\mathbb{Z}, but splits into factors of degree at most 2 modulo every prime, which makes it the standard worst case for the Zassenhaus algorithm.

Set poly to the Chebyshev polynomial of the first kind TnT_n, with Tn(cos⁡θ)=cos⁡(nθ)T_n(\cos \theta) = \cos(n\theta), respectively of the second kind Un=Tn+1′/(n+1)U_n = T'_{n+1}/(n + 1), for n≥0n \ge 0. The coefficients are computed by their hypergeometric recurrence. The underscore versions write n+1n + 1 coefficients.

Set poly to the shifted Legendre polynomial P~n(x)=Pn(2x−1)\tilde{P}_n(x) = P_n(2x - 1), which has integer coefficients, computed by a hypergeometric recurrence. The Legendre polynomials themselves are in fmpq_poly. The underscore version writes n+1n + 1 coefficients.

void _fmpz_poly_hermite_h(fmpz * coeffs, ulong n)
void _fmpz_poly_hermite_he(fmpz * coeffs, ulong n)

Set poly to the physicists' Hermite polynomial HnH_n (with Hn′=2nHn−1H_n' = 2n H_{n-1}), respectively the probabilists' Hermite polynomial Hen(x)=2−n/2Hn(x/2)\mathit{He}_n(x) = 2^{-n/2} H_n(x / \sqrt{2}), computed by a hypergeometric recurrence. The underscore versions write n+1n + 1 coefficients.

void _fmpz_poly_fibonacci(fmpz * coeffs, ulong n)

Set poly to the nn-th Fibonacci polynomial FnF_n, with F0=0F_0 = 0, F1=1F_1 = 1 and Fn+1=xFn+Fn−1F_{n+1} = x F_n + F_{n-1}, computed by a hypergeometric recurrence.

Sets poly to the Eulerian polynomial An(x)=∑m=0nA(n,m)xmA_n(x) = \sum_{m=0}^n A(n, m) x^m, with A0=1A_0 = 1, computed by a recurrence. The coefficients are the Eulerian numbers

A(n,m)=∑k=0m+1(−1)k(n+1k)(m+1−k)n,A(n, m) = \sum_{k=0}^{m+1} (-1)^k \binom{n+1}{k} (m + 1 - k)^n,

and the polynomials have the exponential generating function (x−1)/(x−e(x−1)t)=∑nAn(x)tn/n!(x - 1)/(x - e^{(x - 1)t}) = \sum_n A_n(x) t^n / n!. They are not the Euler polynomials.

Set ff to the qq-expansion to length nn of (q−1/24η(q))e=∏k≥1(1−qk)e(q^{-1/24} \eta(q))^e = \prod_{k \ge 1} (1 - q^k)^e, the Dedekind eta function without its leading factor, raised to the power ee. For e=−1e = -1 this is the generating function of the partition function, and for e=24e = 24, after multiplication by qq, the modular discriminant Δ\Delta, which generates the Ramanujan τ\tau function. Sparse formulas are used for e=1,2,3,4,6e = 1, 2, 3, 4, 6, and power series arithmetic reduces other ee to those.

Set ff to the qq-expansion to length nn of ϑ(q)e\vartheta(q)^e, where ϑ(q)=1+2∑k≥1qk2\vartheta(q) = 1 + 2 \sum_{k \ge 1} q^{k^2} is the Jacobi theta function. Sparse formulas are used for e=1,2e = 1, 2, and power series arithmetic reduces other ee to those.

Internal functions#

Sets res to a bound for the absolute value of the coefficient of xnx^n in fg′/gf g'/g for every factor gg of ff in Z[x]\mathbb{Z}[x] (the coefficients of the logarithmic derivative used by van Hoeij's algorithm, Logarithmic derivatives). Requires 0≤n<deg⁡f0 \le n < \deg f.

More

Divides (pol, len) by 2k2^k, the largest power of two dividing all coefficients, and returns kk; returns 0 for the zero polynomial.

Replaces (pol, len) by f(2kx)f(2^k x) for k≥0k \ge 0, or by 2−k(len−1)f(2kx)2^{-k (\mathit{len} - 1)} f(2^k x) for k<0k < 0 (so that the result has integer coefficients), and then divides by the largest power of two dividing all coefficients.

References#

  • [Mul2000] Thom Mulders : On Short Multiplications and Divisions, AAECC vol. 11 (2000) 69–88
  • [HQZ2004] G. Hanrot, M. Quercia and P. Zimmermann, "The middle product algorithm I. Speeding up the division and square root of power series", Applicable Algebra in Engineering, Communication and Computing 14:6 (2004), 415–438
  • [Knu1997] Knuth, D. E. The Art of Computer Programming, volume 2: Seminumerical algorithms, 1997
  • [Zei1995] D. Zeilberger. The J. C. P. Miller recurrence for exponentiating a polynomial, and its q-analog. Journal of Difference Equations and Applications 1 (1995), 57–60. https://doi.org/10.1080/10236199508808006
  • [Coh1996] Cohen, Henri : A course in computational algebraic number theory, Springer, 1996
  • [CGG1989] B. W. Char, K. O. Geddes and G. H. Gonnet. GCDHEU: heuristic polynomial GCD algorithm based on integer GCD computation. Journal of Symbolic Computation 7 (1989), 31–48. https://doi.org/10.1016/S0747-7171(89)80004-6
  • [Col1971] Collins, George E. : The Calculation of Multivariate Polynomial Resultants, SYMSAC '71, ACM 1971 212–222
  • [BrentKung1978] Brent, R. P. and Kung, H. T. : Fast Algorithms for Manipulating Formal Power Series, J. ACM 25:4 (1978) 581–595
  • [KL2024] Y. Kinoshita and B. Li, "Power series composition in near-linear time", 2024, https://arxiv.org/abs/2404.05177
  • [Fuj1916] M. Fujiwara. Über die obere Schranke des absoluten Betrages der Wurzeln einer algebraischen Gleichung. Tôhoku Mathematical Journal 10 (1916), 167–171.
  • [ASV2008] A. G. Akritas, A. W. Strzeboński and P. S. Vigklas. Improving the performance of the continued fractions method using new bounds of positive roots. Nonlinear Analysis: Modelling and Control 13 (2008), 265–279.
  • [WaktinsZeitlin1993] Watkins, W. and Zeitlin, J. : The minimal polynomial of cos⁡(2π/n)\cos(2\pi/n) The American Mathematical Monthly 100:5 (1993) 471–474
Cite this page

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