Invalid input
Most FLINT functions assume that their input is valid: that objects are initialised and in canonical form, that residues are reduced, that arguments respect the documented aliasing rules and preconditions. They do not check this, and the behaviour for invalid input is undefined in the sense of C: the function may return a wrong result, corrupt memory, crash, or appear to work. Checking every precondition would cost time in the innermost loops, where FLINT spends most of its time, and many properties (such as primality of a modulus) are expensive to check at all.
What is checked#
Some errors are checked in all builds, because they are cheap to detect and easy to make, or because the function cannot know in advance whether the input is valid:
- Division by zero and impossible inverses in the basic arithmetic of the exact types raise an exception with
flint_throw: for examplefmpz_fdiv_q,fmpz_divexactandfmpq_divwith a zero divisor,nmod_invandfmpz_mod_invof a non-invertible residue,fmpz_poly_divandnmod_poly_divremby the zero polynomial, andnmod_poly_divremwhen the leading coefficient of the divisor is not invertible modulo a composite modulus. Context constructors check their parameters in the same way, for instancefmpz_mod_ctx_initwith a nonpositive modulus. By default an exception prints a message and aborts the program; Handling FLINT exceptions explains how to install a handler instead. - The generic rings report errors in their return value instead: every
grfunction returnsGR_SUCCESS,GR_DOMAIN(the result is not defined, such as 1/0 or 1/2 in \mathbb{Z}) orGR_UNABLE(the implementation cannot decide or compute it). Functions of the other modules that are wrappers ofgrfunctions often turn such a status into an exception, asnmod_poly_divremdoes. - Ball arithmetic never fails on numerical grounds: dividing by a ball that contains zero gives an indeterminate ball (
arb_divreturns NaN with infinite radius), and functions outside their domain give indeterminate results; see Ball arithmetic. - Exact numbers. The
ca_ttype has special values for undefined and infinite results:ca_divby zero givesUnsignedInfinity, and 0/0 givesUndefined.qqbar_divandqqbar_invthrow on division by zero. - Parsers return an error code for strings they cannot read, but the conventions differ:
fmpz_set_str,fmpq_set_strandfmpz_poly_set_strreturn -1 on failure and 0 on success,arb_set_strreturns nonzero on failure,nmod_poly_set_strreturns 0 on failure and 1 on success, and the genericgr_set_strreturns a status other thanGR_SUCCESS. Checking the syntax is not the same as checking the value:nmod_poly_set_strdoes not reduce the coefficients it reads, and parsing is not hardened against malicious input; see Untrusted input. - Allocation failure is detected by
flint_mallocand its relatives, which throw instead of returningNULL; see Running out of memory.
The documentation of each function says when it checks its input and how it reports errors.
What is not checked#
The following preconditions are typical of those that are assumed and not checked (except possibly by assertions, see Assertions and debug builds):
- Reduced residues. The functions of nmod.h and
fmpz_modrequire operands in [0, n).nmod_add(10, 3, mod)with n = 7 returns 13, which is not a residue at all, andfmpz_mod_addbehaves in the same way. Usenmod_set_ui,NMOD_REDorfmpz_mod_set_fmpzto reduce values first. - Canonical form. Polynomials must be normalised (no zero leading coefficient), rational numbers must be in lowest terms with a positive denominator, and so on; see Normalisation. Code that writes to the internal fields of an object must restore the canonical form.
- Nonzero arguments where the function does not check.
fmpq_invof zero silently produces the invalid value 1/0, althoughfmpq_divby zero throws. The documentation of each function says which arguments it requires to be nonzero, prime, positive and so on. - Mathematical preconditions. Functions for prime moduli or finite fields assume that the modulus is prime and do not test it; functions computing in a quotient ring assume that the modulus polynomial satisfies the documented conditions (monic, irreducible, ...). Violating these gives wrong results or failures in unrelated places.
- Dimensions and lengths.
fmpz_mat_mulandnmod_mat_mulassume compatible dimensions; the underscore functions assume that arrays have the stated lengths, that lengths are positive where required and that outputs have room for the result. - Aliasing. Arguments must respect the aliasing rules of Aliasing. An underscore function given overlapping input and output arrays where this is not allowed overwrites its input while still reading it.
- Initialisation. Every object must have been initialised and not yet cleared, and must be used with the context it belongs to.
#include <flint/flint.h>
#include <flint/nmod.h>
#include <flint/fmpz.h>
#include <flint/gr.h>
int main(void)
{
nmod_t mod;
fmpz_t a;
gr_ctx_t ZZ;
gr_ptr x, y;
int status;
/* not checked: nmod functions assume reduced operands */
nmod_init(&mod, 7);
flint_printf("nmod_add(10, 3) mod 7 = %wu\n", nmod_add(10, 3, mod));
flint_printf("reduced first: %wu\n",
nmod_add(nmod_set_ui(10, mod), 3, mod));
/* checked: parsers report invalid strings */
fmpz_init(a);
flint_printf("fmpz_set_str(\"12a\") returns %d\n", fmpz_set_str(a, "12a", 10));
fmpz_clear(a);
/* checked: generic rings return a status code */
gr_ctx_init_fmpz(ZZ);
x = gr_heap_init(ZZ);
y = gr_heap_init(ZZ);
status = gr_set_si(x, 1, ZZ);
status |= gr_set_si(y, 2, ZZ);
status |= gr_div(x, x, y, ZZ);
flint_printf("1/2 in ZZ: status %d (GR_DOMAIN = %d)\n", status, GR_DOMAIN);
gr_heap_clear(x, ZZ);
gr_heap_clear(y, ZZ);
gr_ctx_clear(ZZ);
return 0;
}nmod_add(10, 3) mod 7 = 13
reduced first: 6
fmpz_set_str("12a") returns -1
1/2 in ZZ: status 1 (GR_DOMAIN = 1)Finding invalid input#
An assertion build (--enable-assert) checks many of the preconditions above, and is the first thing to try when a program gives strange results; see Assertions and debug builds. Valgrind and the address sanitizer find uses of uninitialised or cleared objects and out-of-bounds accesses. Programs that must cope with arbitrary input, for example interpreters and language bindings, should check the preconditions themselves before calling FLINT, use the generic gr interface where errors are reported through status codes, and install an exception handler with flint_set_throw.
The FLINT team, “Invalid input,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/guide/correctness/input-validation.html (generated 2026-10-20).
@misc{flint-doc-guide-correctness-input-validation,
author = {{The FLINT team}},
title = {{Invalid input}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/guide/correctness/input-validation.html},
note = {Generated 2026-10-20}
}