View on GitHub

malachite

An arbitrary-precision arithmetic library for Rust.

Malachite for FLINT Users: Integers

This page maps the functions of FLINT’s integer type, fmpz_t, onto their Malachite counterparts: Natural and Integer, from the malachite-nz crate. It follows the organization of the fmpz.h chapter of the FLINT manual, as of FLINT 3.6.0, and is a companion to Malachite for GMP Users: Integers; the mapping index lists the whole family. The Conventions of the GMP page, including Allocation, apply here unchanged: where FLINT writes into an output argument, Malachite returns the result. Functions whose names begin with an underscore are FLINT-internal and are omitted.

Conventions

The fmpz representation

An fmpz stores values of absolute value at most \(2^{62}-1\) inline and promotes larger ones to a GMP integer. A Natural likewise stores values below \(2^{64}\) inline, and an Integer is a sign and a Natural. (With 32-bit limbs, the thresholds are \(2^{30}-1\) and \(2^{32}\).) The macros and constants of the tagged representation (COEFF_MAX, COEFF_MIN, COEFF_IS_MPZ, PTR_TO_COEFF, COEFF_TO_PTR) have no counterparts, since Malachite’s representation is not part of its public API. Arrays of fmpz become Vec<Integer> or slices.

Word types

FLINT’s ulong and slong are u64 and i64 on every 64-bit platform, Windows included. As on the GMP page, most _ui and _si variants collapse into their base function’s row.

Aliasing

FLINT functions generally permit outputs to alias inputs. Rust does not; use the assign and by-value forms described under Allocation. The case fmpz_mul(x, x, x) is Square, with x.square_assign() as the in-place form.

Categories

Each function falls into one of five categories:

  meaning
✓ A Malachite function does the same thing.
≈ A Malachite function serves the same purpose, but its specification differs. The notes say how.
⚙ Malachite does not expose this algorithm or helper; the Malachite column or the notes say what to call instead.
— No counterpart is needed, either because Rust handles it for you or because it is outside Malachite’s scope. The notes say which.
✗ Malachite does not fully support this yet, but will in a future version.

Memory management

The discussion on the GMP page of why Rust has no separate initialization step and nothing to clear applies here.

  FLINT Malachite
✓ void fmpz_init (fmpz_t f) Natural::ZERO, Integer::ZERO
— void fmpz_init2 (fmpz_t f, ulong limbs)  
— void fmpz_clear (fmpz_t f)  
✓ void fmpz_init_set (fmpz_t f, const fmpz_t g) Clone
✓ void fmpz_init_set_ui (fmpz_t f, ulong g) From
✓ void fmpz_init_set_si (fmpz_t f, slong g) From, TryFrom

fmpz_init. let x = Integer::ZERO;, which allocates nothing. Default also returns zero.

fmpz_init2. A capacity hint; see the note under mpz_init2 on the GMP page.

fmpz_clear. Memory is released when the value goes out of scope.

fmpz_init_set, fmpz_init_set_ui, fmpz_init_set_si. g.clone(), Natural::from(g), and Integer::from(g), as in the corresponding GMP section; TryFrom turns a signed value into a Natural.

Random generation

FLINT’s flint_rand_t state has the same shape as GMP’s gmp_randstate_t, and the same note applies: Malachite’s stream generators take a Seed and return an infinite iterator, and its single-value get_* forms borrow a source of random words mutably (a StripedBitSource for the striped forms). Random generation lives behind the random feature, in the natural::random and integer::random modules.

  FLINT Malachite
✓ void fmpz_randbits_unsigned (fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) get_random_natural_with_bits
✓ void fmpz_randbits (fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) get_random_natural_with_bits, from_sign_and_abs
≈ void fmpz_randtest_unsigned (fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) random_naturals, striped_random_naturals
≈ void fmpz_randtest (fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) random_integers, striped_random_integers
≈ void fmpz_randtest_not_zero (fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) random_nonzero_integers
✓ void fmpz_randm (fmpz_t f, flint_rand_t state, const fmpz_t m) get_random_natural_less_than, random_naturals_less_than
≈ void fmpz_randtest_mod (fmpz_t f, flint_rand_t state, const fmpz_t m) striped_random_natural_range
≈ void fmpz_randtest_mod_signed (fmpz_t f, flint_rand_t state, const fmpz_t m) striped_random_integer_range
✗ void fmpz_randprime (fmpz_t f, flint_rand_t state, flint_bitcnt_t bits, int proved)  

fmpz_randbits, fmpz_randbits_unsigned. get_random_natural_with_bits chooses uniformly among the Naturals of exactly bits bits. FLINT’s signed version also picks a random sign; compose it with Integer::from_sign_and_abs and a random bool.

The randtest family. The distributions differ, hence ≈. FLINT draws the bit length uniformly from 0 to bits inclusive, with a hard cap. Malachite’s streams take a mean bit length and draw sizes from a geometric distribution, with no cap; random_nonzero_integers covers the not_zero variant. To reproduce FLINT’s shape, draw a length and then a value of that length; get_random_natural_with_up_to_bits caps the length but is uniform over values, not over lengths.

fmpz_randm, fmpz_randtest_mod, fmpz_randtest_mod_signed. fmpz_randm is get_random_natural_less_than, or the random_naturals_less_than stream. The two randtest_mod forms bias toward the endpoints of the range (and toward zero, for the signed one); Malachite’s range generators are uniform or striped instead, with no endpoint bias. The signed range (-m/2, m/2] is an ordinary range for uniform_random_integer_inclusive_range or its striped counterpart.

fmpz_randprime. No counterpart: Malachite does not generate bignum primes.

FLINT’s limb-level random functions, in mpn_extras, are not mapped: Malachite’s limb-level functions are not public.

Conversion

Conversions to and from primitives follow the policy-trait scheme on the GMP page. The multi-word forms become Rust’s 128-bit primitives and Malachite’s limb-slice conversions.

  FLINT Malachite
≈ slong fmpz_get_si (const fmpz_t f) TryFrom, WrappingFrom, SaturatingFrom
≈ ulong fmpz_get_ui (const fmpz_t f) TryFrom, WrappingFrom, SaturatingFrom
≈ void fmpz_get_uiui (ulong * hi, ulong * low, const fmpz_t f) TryFrom, WrappingFrom
✓ ulong fmpz_get_nmod (const fmpz_t f, nmod_t mod) Mod
≈ double fmpz_get_d (const fmpz_t f) RoundingFrom, TryFrom
— void fmpz_set_mpf (fmpz_t f, const mpf_t x)  
— void fmpz_get_mpf (mpf_t x, const fmpz_t f)  
✓ void fmpz_get_mpfr (mpfr_t x, const fmpz_t f, mpfr_rnd_t rnd) from_integer_prec_round
≈ double fmpz_get_d_2exp (slong * exp, const fmpz_t f) SciMantissaAndExponent
— void fmpz_get_mpz (mpz_t x, const fmpz_t f)  
✓ int fmpz_get_mpn (nn_ptr * n, fmpz_t n_in) to_limbs_asc
✓ char * fmpz_get_str (char * str, int b, const fmpz_t f) ToStringBase, Display
✓ void fmpz_set_si (fmpz_t f, slong val) From, TryFrom
✓ void fmpz_set_ui (fmpz_t f, ulong val) From
≈ void fmpz_set_d (fmpz_t f, double c) RoundingFrom, TryFrom
✓ void fmpz_set_d_2exp (fmpz_t f, double d, slong exp) RoundingFrom, Shl
✓ void fmpz_neg_ui (fmpz_t f, ulong val) From, Neg
✓ void fmpz_set_uiui (fmpz_t f, ulong hi, ulong lo) From
✓ void fmpz_neg_uiui (fmpz_t f, ulong hi, ulong lo) From, Neg
✓ void fmpz_set_signed_uiui (fmpz_t f, ulong hi, ulong lo) From
✓ void fmpz_set_signed_uiuiui (fmpz_t f, ulong hi, ulong mid, ulong lo) from_twos_complement_limbs_asc
✓ void fmpz_set_ui_array (fmpz_t out, const ulong * in, slong n) from_limbs_asc
✓ void fmpz_set_signed_ui_array (fmpz_t out, const ulong * in, slong n) from_twos_complement_limbs_asc
✓ void fmpz_get_ui_array (ulong * out, slong n, const fmpz_t in) to_limbs_asc
✓ void fmpz_get_signed_ui_array (ulong * out, slong n, const fmpz_t in) to_twos_complement_limbs_asc
✓ void fmpz_set_mpn_large (fmpz_t z, nn_srcptr src, slong n, int negative) from_limbs_asc, from_sign_and_abs
✓ void fmpz_get_signed_uiui (ulong * hi, ulong * lo, const fmpz_t in) WrappingFrom
— void fmpz_set_mpz (fmpz_t f, const mpz_t x)  
✓ int fmpz_set_str (fmpz_t f, const char * str, int b) FromStringBase, FromStr
✓ void fmpz_set_ui_smod (fmpz_t f, ulong x, ulong m) BalancedMod
— void flint_mpz_init_set_readonly (mpz_t z, const fmpz_t f)  
— void flint_mpz_clear_readonly (mpz_t z)  
— void fmpz_init_set_readonly (fmpz_t f, const mpz_t z)  
— void fmpz_clear_readonly (fmpz_t f)  

fmpz_get_si, fmpz_get_ui. The policy-trait family from the GMP page: TryFrom fails when the value does not fit, WrappingFrom keeps the low bits, SaturatingFrom clamps, and ConvertibleFrom is the fits-test. FLINT leaves fmpz_get_ui of a negative number undefined (GMP’s mpz_get_ui returns the low bits of the absolute value); each Malachite trait defines its result.

Words in pairs and arrays. The two-word forms are Rust’s 128-bit primitives: fmpz_set_uiui(f, hi, lo) is Natural::from of a u128, fmpz_set_signed_uiui is Integer::from of an i128, and the two neg forms compose with Neg. fmpz_get_uiui is a u128 conversion under whichever policy you choose, and fmpz_get_signed_uiui (the value modulo \(2^{128}\) in two’s complement) is i128::wrapping_from. To go between a u128 and a word pair, use JoinHalves (u128::join_halves(hi, lo)) and SplitInHalf (split_in_half(), returning (hi, lo)). The array forms are the limb-slice conversions: fmpz_set_ui_array is Natural::from_limbs_asc, the signed versions (including fmpz_set_signed_uiuiui) are Integer::from_twos_complement_limbs_asc, and the get versions are to_limbs_asc and to_twos_complement_limbs_asc. These return a minimal-length Vec where FLINT fills exactly n words; pad with zero words (or sign words, for two’s complement) if you need a fixed width. fmpz_set_mpn_large is from_limbs_asc plus Integer::from_sign_and_abs, without its preconditions: from_limbs_asc accepts any slice, unnormalized or empty. fmpz_get_mpn is to_limbs_asc.

fmpz_get_d, fmpz_set_d, and the 2exp pair. fmpz_get_d truncates, so it is f64::rounding_from(&f, Down); where FLINT leaves out-of-range values undefined, the defined overflow behavior on the GMP page applies. fmpz_set_d is Integer::rounding_from(c, Down); an infinity or NaN fails try_from and makes rounding_from panic, and a subnormal (undefined in FLINT) truncates to zero. fmpz_get_d_2exp is SciMantissaAndExponent, with the mantissa-normalization difference noted on the GMP page for mpz_get_d_2exp. fmpz_set_d_2exp rounds \(d \cdot 2^{exp}\) to the nearest integer; the exact spelling is Rational::try_from(d) shifted by exp, then Integer::rounding_from(&q, Nearest).

The GMP and MPFR boundary. The conversions to and from mpz_t and mpf_t, including the four readonly functions, have no counterpart because Malachite is not built on GMP. To pass a value to C, or to GMP through bindings such as rug, use the limb-slice conversions above, strings, or serde. For mpf_t, see the note on the GMP page. fmpz_get_mpfr is Float::from_integer_prec_round(f, prec, rnd) on Float, which takes the target precision explicitly and also returns an Ordering giving the rounding direction.

fmpz_get_nmod. Reduce with Natural::from(m) and Mod, then convert the result to a word. Malachite has no public counterpart of the precomputed nmod_t context; see the mod-n page.

fmpz_get_str, fmpz_set_str. to_string_base and from_string_base, covering bases 2 through 62 with GMP’s digit alphabet, as described in the notes on the GMP page: Option replaces the -1 return and String replaces the buffer. FLINT has no uppercase mode, so to_string_base covers all of fmpz_get_str. When parsing, FLINT skips surrounding whitespace and tolerates interior whitespace; Malachite accepts no whitespace, accepts a single leading + that FLINT rejects, and, like FLINT, rejects a doubled minus sign.

fmpz_set_ui_smod. The representative of x modulo m in (-m/2, m/2], which is BalancedMod, returning an Integer. FLINT requires (without checking) 0 <= x < m; balanced_mod accepts any Natural and agrees wherever FLINT’s precondition holds.

Input and output

As on the GMP page, Malachite has no FILE * functions: formatting and parsing work with any Rust reader or writer.

  FLINT Malachite
✓ int fmpz_read (fmpz_t f) FromStr
✓ int fmpz_fread (FILE * file, fmpz_t f) FromStr
≈ size_t fmpz_inp_raw (fmpz_t x, FILE * fin) Deserialize
✓ int fmpz_print (const fmpz_t x) Display
✓ int fmpz_fprint (FILE * fs, const fmpz_t x) Display
≈ size_t fmpz_out_raw (FILE * fout, const fmpz_t x) Serialize

fmpz_read, fmpz_fread. Read a token and call parse::<Integer>() (decimal), or from_string_base for other bases. Failure is an Err rather than a non-positive return. FLINT rejects leading zeros; Malachite parses "00123".

fmpz_print, fmpz_fprint. print!("{x}"), or write!(f, "{x}") for any Write. FLINT returns the number of characters written; x.to_string().len() gives it if needed.

fmpz_out_raw, fmpz_inp_raw. These use GMP’s raw format, so the discussion on the GMP page of mpz_out_raw and mpz_inp_raw versus Malachite’s serde support applies, including the encoding differences behind the ≈.

Basic properties and manipulation

  FLINT Malachite
✓ size_t fmpz_sizeinbase (const fmpz_t f, int b) SignificantBits, FloorLogBase
✓ flint_bitcnt_t fmpz_bits (const fmpz_t f) SignificantBits
✓ slong fmpz_size (const fmpz_t f) limb_count
✓ int fmpz_sgn (const fmpz_t f) Sign
≈ flint_bitcnt_t fmpz_val2 (const fmpz_t f) trailing_zeros
— void fmpz_swap (fmpz_t f, fmpz_t g)  
✓ void fmpz_set (fmpz_t f, const fmpz_t g) Clone
✓ void fmpz_zero (fmpz_t f) ZERO
✓ void fmpz_one (fmpz_t f) ONE
✓ int fmpz_abs_fits_ui (const fmpz_t f) ConvertibleFrom, UnsignedAbs
✓ int fmpz_fits_si (const fmpz_t f) ConvertibleFrom
✓ void fmpz_setbit (fmpz_t f, ulong i) BitAccess
✓ int fmpz_tstbit (const fmpz_t f, ulong i) BitAccess
✓ ulong fmpz_abs_lbound_ui_2exp (slong * exp, const fmpz_t x, int bits) sci_mantissa_and_exponent_round, ShrRound
✓ ulong fmpz_abs_ubound_ui_2exp (slong * exp, const fmpz_t x, int bits) sci_mantissa_and_exponent_round, ShrRound

fmpz_sizeinbase, fmpz_bits, fmpz_size, fmpz_sgn. fmpz_bits is significant_bits(), and fmpz_size is limb_count(), on a Natural or on an Integer’s unsigned_abs_ref; all return 0 for zero. fmpz_sgn is Sign, returning an Ordering. For fmpz_sizeinbase, the digit count is f.floor_log_base(&base) + 1, but floor_log_base panics on zero, so handle zero separately.

fmpz_val2. trailing_zeros(), on a Natural or on an Integer’s absolute value. For zero, FLINT returns 0 and Malachite returns None, hence ≈.

fmpz_swap, fmpz_set, fmpz_zero, fmpz_one. std::mem::swap; x = y.clone() or x.clone_from(&y); x = Integer::ZERO and x = Integer::ONE.

fmpz_abs_fits_ui, fmpz_fits_si. u64::convertible_from(f.unsigned_abs_ref()) and i64::convertible_from(&f).

fmpz_setbit, fmpz_tstbit. f.set_bit(i) and f.get_bit(i), from BitAccess, with negative values acting as their two’s complement.

fmpz_abs_lbound_ui_2exp, fmpz_abs_ubound_ui_2exp. sci_mantissa_and_exponent_round with Floor or Ceiling gives a mantissa and exponent bounding the value from below or above, but its mantissa is an f32 or f64 in [1, 2) (24 or 53 bits), where FLINT’s is an integer of a caller-chosen width. For FLINT’s shape at width bits, let e = x.significant_bits() as i64 - bits; the mantissa is x.unsigned_abs_ref().shr_round(e, Floor).0, or Ceiling for the upper bound. As in FLINT, the ceiling can carry to a power of two and gain a bit; shift once more if the width must be exact.

Comparison

As on the GMP page, comparisons return an Ordering instead of a signed int, and the _ui and _si variants use the same traits as their base functions.

  FLINT Malachite
✓ int fmpz_cmp (const fmpz_t f, const fmpz_t g) Ord
✓ int fmpz_cmp_ui (const fmpz_t f, ulong g) PartialOrd
✓ int fmpz_cmp_si (const fmpz_t f, slong g) PartialOrd
✓ int fmpz_cmpabs (const fmpz_t f, const fmpz_t g) OrdAbs
✓ int fmpz_cmp2abs (const fmpz_t f, const fmpz_t g) OrdAbsDouble
✓ int fmpz_equal (const fmpz_t f, const fmpz_t g) PartialEq
✓ int fmpz_equal_ui (const fmpz_t f, ulong g) PartialEq
✓ int fmpz_equal_si (const fmpz_t f, slong g) PartialEq
✓ int fmpz_is_zero (const fmpz_t f) PartialEq
✓ int fmpz_is_one (const fmpz_t f) PartialEq
✓ int fmpz_is_pm1 (const fmpz_t f) EqAbs
✓ int fmpz_is_even (const fmpz_t f) Parity
✓ int fmpz_is_odd (const fmpz_t f) Parity

fmpz_cmp2abs. f.cmp_abs_double(&g), from OrdAbsDouble, compares |f| against |2g| without forming 2g. On Natural, the same comparison is OrdDouble’s cmp_double.

The predicates. fmpz_is_zero and fmpz_is_one are f == 0 and f == 1; fmpz_is_pm1 is f.eq_abs(&1), from EqAbs; and the parity pair is f.even() and f.odd().

Basic arithmetic

This section is divided into subsections in the manual’s order. As on the GMP page, the *Assign traits cover the in-place case, every operator has borrowing forms, and the _ui and _si variants collapse into their base function’s row.

Addition and multiplication

  FLINT Malachite
✓ void fmpz_neg (fmpz_t f1, const fmpz_t f2) Neg, NegAssign
✓ void fmpz_abs (fmpz_t f1, const fmpz_t f2) Abs, UnsignedAbs
✓ void fmpz_add (fmpz_t f, const fmpz_t g, const fmpz_t h) Add, AddAssign
✓ void fmpz_add_ui (fmpz_t f, const fmpz_t g, ulong h) Add, AddAssign
✓ void fmpz_add_si (fmpz_t f, const fmpz_t g, slong h) Add, AddAssign
≈ void fmpz_sub (fmpz_t f, const fmpz_t g, const fmpz_t h) Sub, CheckedSub, SaturatingSub
≈ void fmpz_sub_ui (fmpz_t f, const fmpz_t g, ulong h) Sub, CheckedSub
≈ void fmpz_sub_si (fmpz_t f, const fmpz_t g, slong h) Sub, CheckedSub
✓ void fmpz_mul (fmpz_t f, const fmpz_t g, const fmpz_t h) Mul, MulAssign
✓ void fmpz_mul_ui (fmpz_t f, const fmpz_t g, ulong h) Mul, MulAssign
✓ void fmpz_mul_si (fmpz_t f, const fmpz_t g, slong h) Mul, MulAssign
✓ void fmpz_mul2_uiui (fmpz_t f, const fmpz_t g, ulong x, ulong y) Mul
✓ void fmpz_mul_2exp (fmpz_t f, const fmpz_t g, ulong e) Shl, ShlAssign
✓ void fmpz_one_2exp (fmpz_t f, ulong e) PowerOf2
✓ void fmpz_addmul (fmpz_t f, const fmpz_t g, const fmpz_t h) AddMul, AddMulAssign
✓ void fmpz_addmul_ui (fmpz_t f, const fmpz_t g, ulong h) AddMul, AddMulAssign
✓ void fmpz_addmul_si (fmpz_t f, const fmpz_t g, slong h) AddMul, AddMulAssign
≈ void fmpz_submul (fmpz_t f, const fmpz_t g, const fmpz_t h) SubMul, SubMulAssign
≈ void fmpz_submul_ui (fmpz_t f, const fmpz_t g, ulong h) SubMul, SubMulAssign
≈ void fmpz_submul_si (fmpz_t f, const fmpz_t g, slong h) SubMul, SubMulAssign
✓ void fmpz_fmma (fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d) MulAddMul, MulAddMulAssign
≈ void fmpz_fmms (fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d) MulSubMul, MulSubMulAssign

The operators. -g, g.abs(), g + h, g - h, g * h, and g << e, with UnsignedAbs producing the absolute value as a Natural. The subtraction and submul rows are ≈ because on Natural a negative difference panics; CheckedSub and SaturatingSub are the alternatives. On Integer they match exactly.

fmpz_mul2_uiui. g * Natural::from(u128::from(x) * u128::from(y)); the word product cannot overflow a u128.

fmpz_mul_2exp, fmpz_one_2exp. g << e, and Integer::power_of_2(e) from PowerOf2. FLINT’s restriction that e + FLINT_BITS must not overflow does not apply.

fmpz_addmul, fmpz_submul. f.add_mul_assign(&g, &h) and f.sub_mul_assign(&g, &h); f.add_mul(&g, &h) and f.sub_mul(&g, &h) return the result instead.

fmpz_fmma, fmpz_fmms. \(ab + cd\) and \(ab - cd\) are a.mul_add_mul(b, c, d) and a.mul_sub_mul(b, c, d). The fmms row is ≈ for the same reason as submul: on Natural a negative result panics, and CheckedMulSubMul and SaturatingMulSubMul return None and 0 instead.

Division with rounding

FLINT uses GMP’s naming: cdiv rounds the quotient toward positive infinity, fdiv toward negative infinity, and tdiv toward zero. As on the GMP page, cdiv is CeilingDivMod and CeilingMod, fdiv is DivMod and Mod, tdiv is DivRem and Rem (the / and % operators), and a quotient alone under any mode is DivRound with Ceiling, Floor, or Down. A zero divisor raises an exception in FLINT and panics in Malachite.

  FLINT Malachite
✓ void fmpz_cdiv_qr (fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) CeilingDivMod
✓ void fmpz_fdiv_qr (fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) DivMod
✓ void fmpz_tdiv_qr (fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) DivRem
≈ void fmpz_ndiv_qr (fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) DivRound
✓ void fmpz_cdiv_q (fmpz_t f, const fmpz_t g, const fmpz_t h) DivRound, CeilingDivMod
✓ void fmpz_fdiv_q (fmpz_t f, const fmpz_t g, const fmpz_t h) DivRound, DivMod
✓ void fmpz_tdiv_q (fmpz_t f, const fmpz_t g, const fmpz_t h) Div, DivRound
✓ void fmpz_cdiv_q_si (fmpz_t f, const fmpz_t g, slong h) DivRound
✓ void fmpz_fdiv_q_si (fmpz_t f, const fmpz_t g, slong h) DivRound
✓ void fmpz_tdiv_q_si (fmpz_t f, const fmpz_t g, slong h) Div, DivRound
✓ void fmpz_cdiv_q_ui (fmpz_t f, const fmpz_t g, ulong h) DivRound
✓ void fmpz_fdiv_q_ui (fmpz_t f, const fmpz_t g, ulong h) DivRound
✓ void fmpz_tdiv_q_ui (fmpz_t f, const fmpz_t g, ulong h) Div, DivRound
✓ void fmpz_cdiv_q_2exp (fmpz_t f, const fmpz_t g, ulong exp) ShrRound
✓ void fmpz_fdiv_q_2exp (fmpz_t f, const fmpz_t g, ulong exp) Shr, ShrRound
✓ void fmpz_tdiv_q_2exp (fmpz_t f, const fmpz_t g, ulong exp) ShrRound
✓ void fmpz_fdiv_r (fmpz_t s, const fmpz_t g, const fmpz_t h) Mod
✓ void fmpz_cdiv_r_2exp (fmpz_t s, const fmpz_t g, ulong exp) CeilingModPowerOf2
✓ void fmpz_fdiv_r_2exp (fmpz_t s, const fmpz_t g, ulong exp) ModPowerOf2
✓ void fmpz_tdiv_r_2exp (fmpz_t s, const fmpz_t g, ulong exp) RemPowerOf2
✓ ulong fmpz_cdiv_ui (const fmpz_t g, ulong h) CeilingMod, UnsignedAbs
✓ ulong fmpz_fdiv_ui (const fmpz_t g, ulong h) Mod
✓ ulong fmpz_tdiv_ui (const fmpz_t g, ulong h) Rem, UnsignedAbs

fmpz_ndiv_qr. DivRound with Nearest rounds the quotient to the nearest integer, but ties differ: FLINT rounds a tie toward zero, Malachite to even. For 3 / 2, fmpz_ndiv_qr gives 1 and (3).div_round(2, Nearest) gives 2. To reproduce FLINT’s rule, compare twice the truncated remainder against the divisor (cmp_abs_double). DivRound returns only the quotient; the remainder is g - &q * h, or one SubMul.

The 2exp columns. ShrRound with Ceiling, Floor, or Down gives cdiv, fdiv, or tdiv; a plain g >> exp floors. The remainders are ModPowerOf2 (floor, nonnegative), CeilingModPowerOf2 (ceiling, nonpositive), and RemPowerOf2 (truncating, sign of g).

fmpz_cdiv_ui, fmpz_fdiv_ui, fmpz_tdiv_ui. These return the remainder’s absolute value as a word. fmpz_fdiv_ui is Mod; the other two compose with UnsignedAbs, since the ceiling remainder is nonpositive and the truncated one takes g’s sign.

Exact division, divisibility, and modular reduction

  FLINT Malachite
✓ void fmpz_divexact (fmpz_t f, const fmpz_t g, const fmpz_t h) DivExact, DivExactAssign
✓ void fmpz_divexact_si (fmpz_t f, const fmpz_t g, slong h) DivExact
✓ void fmpz_divexact_ui (fmpz_t f, const fmpz_t g, ulong h) DivExact
✓ void fmpz_divexact2_uiui (fmpz_t f, const fmpz_t g, ulong x, ulong y) DivExact
✓ int fmpz_divisible (const fmpz_t f, const fmpz_t g) DivisibleBy
✓ int fmpz_divisible_si (const fmpz_t f, slong g) DivisibleBy
✓ int fmpz_divides (fmpz_t q, const fmpz_t f, const fmpz_t g) DivMod
✓ void fmpz_mod (fmpz_t f, const fmpz_t g, const fmpz_t h) ModEuclidean
✓ ulong fmpz_mod_ui (fmpz_t f, const fmpz_t g, ulong h) ModEuclidean
✓ void fmpz_smod (fmpz_t f, const fmpz_t g, const fmpz_t h) BalancedMod
✓ void fmpz_preinvn_init (fmpz_preinvn_t inv, const fmpz_t f) DivModPrecomputed
— void fmpz_preinvn_clear (fmpz_preinvn_t inv)  
✓ void fmpz_fdiv_qr_preinvn (fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h, const fmpz_preinvn_t hinv) DivModPrecomputed, DivAssignModPrecomputed

The divexact family. g.div_exact(&h). As in FLINT, exactness is not checked: if h does not divide g, div_exact may panic or return a meaningless result. For fmpz_divexact2_uiui, form x * y as a u128 and divide once.

fmpz_divisible, fmpz_divides. f.divisible_by(&g). For fmpz_divides, use let (q, r) = f.div_mod(&g) and test r == 0. FLINT defines fmpz_divides(q, f, 0) to report whether f is zero, while div_mod by zero panics, so test the divisor first if it can be zero.

fmpz_mod, fmpz_mod_ui. fmpz_mod returns a nonnegative remainder whatever the sign of h, which is ModEuclidean (mod_euclidean, returning a Natural). For a positive divisor, as in fmpz_mod_ui, Mod agrees.

fmpz_smod. The remainder in (-|h|/2, |h|/2], which is BalancedMod. As in FLINT, only the magnitude of h matters, and a remainder of exactly |h|/2 is positive.

The preinvn trio. DivModPrecomputed: Integer::precompute_div_mod_data(&h) corresponds to fmpz_preinvn_init, and g.div_mod_precomputed(&h, &data) to fmpz_fdiv_qr_preinvn (floor division). DivAssignModPrecomputed is the in-place form. As in FLINT, the data depends only on |h|. fmpz_preinvn_clear is replaced by Drop.

Powers and logarithms

  FLINT Malachite
✓ void fmpz_pow_ui (fmpz_t f, const fmpz_t g, ulong x) Pow, PowAssign
✓ void fmpz_ui_pow_ui (fmpz_t f, ulong g, ulong x) Pow
✓ int fmpz_pow_fmpz (fmpz_t f, const fmpz_t g, const fmpz_t x) Pow, TryFrom
≈ void fmpz_powm_ui (fmpz_t f, const fmpz_t g, ulong e, const fmpz_t m) ModPow
≈ void fmpz_powm (fmpz_t f, const fmpz_t g, const fmpz_t e, const fmpz_t m) ModPow
✓ slong fmpz_clog (const fmpz_t x, const fmpz_t b) CeilingLogBase
✓ slong fmpz_clog_ui (const fmpz_t x, ulong b) CeilingLogBase
✓ slong fmpz_flog (const fmpz_t x, const fmpz_t b) FloorLogBase
✓ slong fmpz_flog_ui (const fmpz_t x, ulong b) FloorLogBase
✓ double fmpz_dlog (const fmpz_t x) approx_log

fmpz_pow_ui, fmpz_ui_pow_ui, fmpz_pow_fmpz. g.pow(x), with \(0^0 = 1\) in both libraries. For fmpz_pow_fmpz, convert the exponent with u64::try_from(&x); its Err takes the place of FLINT’s failure return (and of FLINT’s throw on a negative exponent). FLINT succeeds for bases -1, 0, and 1 at any exponent, so handle those before converting.

fmpz_powm, fmpz_powm_ui. ModPow, with the differences explained on the GMP page for mpz_powm: the base must already be reduced, the residues are Naturals, and a negative exponent is spelled as ModInverse followed by a positive power. FLINT’s abort on a zero modulus is a panic.

fmpz_clog, fmpz_flog. x.ceiling_log_base(&b) and x.floor_log_base(&b). Both panic when x < 1 or b < 2, inputs FLINT assumes do not occur.

fmpz_dlog. approx_log on Rational, via Rational::from(&x). FLINT’s result depends on the platform’s C log; Malachite’s uses the libm crate and is identical on every platform.

Roots

  FLINT Malachite
✓ int fmpz_sqrtmod (fmpz_t b, const fmpz_t a, const fmpz_t p) ModSqrt
✓ void fmpz_sqrt (fmpz_t f, const fmpz_t g) FloorSqrt
✓ void fmpz_sqrtrem (fmpz_t f, fmpz_t r, const fmpz_t g) SqrtRem
✓ int fmpz_is_square (const fmpz_t f) IsSquare
≈ int fmpz_root (fmpz_t r, const fmpz_t f, slong n) FloorRoot, CeilingRoot, CheckedRoot
✓ int fmpz_is_perfect_power (fmpz_t root, const fmpz_t f) ExpressAsPower

fmpz_sqrt, fmpz_sqrtrem, fmpz_is_square. g.floor_sqrt(), g.sqrt_rem(), and f.is_square(); FLINT’s exception on a negative operand is a panic. sqrt_rem returns a tuple. IsSquare is implemented only for Natural; for an Integer, test the sign first.

fmpz_root. The same ≈ as mpz_root, explained on the GMP page: FLINT truncates toward zero, so for a negative operand with odd n use CeilingRoot, and for a nonnegative one FloorRoot. For FLINT’s exactness flag, use CheckedRoot (the root only when exact) or RootRem.

fmpz_sqrtmod. a.mod_sqrt(&p), returning an Option where FLINT sets an output and returns a flag; ModSqrt is implemented for Natural and the unsigned primitives. As in FLINT, p is assumed prime but not checked, and for a composite p the results match FLINT’s, including missed and spurious roots, with two exceptions where Malachite returns the mathematically expected value: even moduli between 50 and 600, and p = 2^64 - 1 or 2^64 - 3.

fmpz_is_perfect_power. ExpressAsPower: express_as_power on 64 returns Some((2, 6)), the root and the exponent, where fmpz_is_perfect_power sets the root and returns the exponent. As in FLINT, 0 and 1 count as perfect powers, and the root is not necessarily the smallest. For a negative Integer, the exponent is always odd (\(-8 = (-2)^3\)). The predicate alone is IsPower.

Combinatorial functions and fused operations

  FLINT Malachite
✓ void fmpz_fac_ui (fmpz_t f, ulong n) Factorial
✓ void fmpz_fib_ui (fmpz_t f, ulong n) Fibonacci
✓ void fmpz_bin_uiui (fmpz_t f, ulong n, ulong k) BinomialCoefficient
✓ void fmpz_rfac_ui (fmpz_t r, const fmpz_t x, ulong k) RisingFactorial
✓ void fmpz_rfac_uiui (fmpz_t r, ulong x, ulong k) RisingFactorial
✓ void fmpz_mul_tdiv_q_2exp (fmpz_t f, const fmpz_t g, const fmpz_t h, ulong exp) MulShrRound, MulShrRoundAssign
✓ void fmpz_mul_si_tdiv_q_2exp (fmpz_t f, const fmpz_t g, slong x, ulong exp) MulShrRound, MulShrRoundAssign

fmpz_fac_ui, fmpz_fib_ui, fmpz_bin_uiui. Natural::factorial(n), Natural::fibonacci(n), and Natural::binomial_coefficient(n, k).

fmpz_rfac_ui, fmpz_rfac_uiui. The rising factorial \(x (x+1) \cdots (x+k-1)\) is x.rising_factorial(k): Integer::rising_factorial for fmpz_rfac_ui, with the same handling of negative bases, and Natural::rising_factorial for fmpz_rfac_uiui, with a base of any size.

fmpz_mul_tdiv_q_2exp, fmpz_mul_si_tdiv_q_2exp. (&g).mul_shr_round(&h, exp, Down).0; Down is truncation toward zero. The second return value reports how the result compares with the exact quotient. A plain >> floors, so a negative product needs Down explicitly. For the si variant, pass Integer::from(x).

Greatest common divisor

  FLINT Malachite
✓ void fmpz_gcd_ui (fmpz_t f, const fmpz_t g, ulong h) Gcd
✓ void fmpz_gcd (fmpz_t f, const fmpz_t g, const fmpz_t h) Gcd
✓ void fmpz_gcd3 (fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c) Gcd
✓ void fmpz_lcm (fmpz_t f, const fmpz_t g, const fmpz_t h) Lcm
≈ void fmpz_gcdinv (fmpz_t d, fmpz_t a, const fmpz_t f, const fmpz_t g) ModInverse, ExtendedGcd
≈ void fmpz_xgcd (fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g) ExtendedGcd
✓ void fmpz_xgcd_canonical_bezout (fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g) ExtendedGcd
⚙ void fmpz_xgcd_partial (fmpz_t co2, fmpz_t co1, fmpz_t r2, fmpz_t r1, const fmpz_t L) internal

fmpz_gcd, fmpz_gcd3, fmpz_lcm. Gcd and Lcm are defined on Natural; since FLINT’s results are nonnegative, take unsigned_abs of each Integer first. fmpz_gcd3 is a.gcd(&b).gcd(&c).

The xgcd family. fmpz_xgcd_canonical_bezout normalizes the cofactors by \(|a| < |g/2d|\) and \(|b| < |f/2d|\), the same normalization, edge cases included, as ExtendedGcd, so extended_gcd returns identical cofactors, as a tuple. Plain fmpz_xgcd follows the fmpz_gcdinv convention instead, hence ≈.

fmpz_gcdinv. For 0 <= f < g, returns d = gcd(f, g) and a with \(af \equiv d \pmod{g}\). For a modular inverse, ModInverse returns None when f and g are not coprime. For d and a cofactor in every case, extended_gcd’s first cofactor satisfies the same congruence after reduction modulo g, but is normalized differently, hence ≈.

fmpz_xgcd_partial. Malachite has an internal port of this function (Lehmer’s extended GCD with early termination), but it is not public. There is no public way to stop the reduction at a bound; ExtendedGcd computes the complete GCD and cofactors.

Modular arithmetic

  FLINT Malachite
✓ slong fmpz_remove (fmpz_t rop, const fmpz_t op, const fmpz_t f) RemovePower
≈ int fmpz_invmod (fmpz_t f, const fmpz_t g, const fmpz_t h) ModInverse
✓ void fmpz_negmod (fmpz_t f, const fmpz_t g, const fmpz_t h) ModNeg, NegMod
≈ int fmpz_jacobi (const fmpz_t a, const fmpz_t n) JacobiSymbol, KroneckerSymbol
✓ int fmpz_kronecker (const fmpz_t a, const fmpz_t n) KroneckerSymbol
✓ void fmpz_divides_mod_list (fmpz_t xstart, fmpz_t xstride, fmpz_t xlength, const fmpz_t a, const fmpz_t b, const fmpz_t n) ModDivList

fmpz_remove. RemovePower, which returns the reduced number and the count as a tuple. As in FLINT, a zero input removes nothing, and a factor of 1 or less is rejected (FLINT aborts; Malachite panics).

fmpz_invmod. ModInverse returns Option instead of a flag. It is ≈ for two reasons: mod_inverse requires its input already reduced and nonzero, where FLINT reduces it; and FLINT treats every value as invertible modulo h = ±1, with inverse 0, while mod_inverse rejects the only residue, 0. Test for a unit modulus first if one can occur.

fmpz_negmod. FLINT requires g to be reduced but does not check. g.mod_neg(&h), from ModNeg, has the same precondition and panics if it fails. g.neg_mod(&h), from NegMod, accepts any g. Both agree on reduced inputs.

fmpz_jacobi, fmpz_kronecker. As on the GMP page, KroneckerSymbol matches for every input, while JacobiSymbol requires an odd positive denominator. FLINT’s fmpz_jacobi does not check the parity or sign of n; where its result would be undefined, jacobi_symbol panics, and kronecker_symbol returns the Kronecker symbol.

fmpz_divides_mod_list. The solutions of \(ax \equiv b \pmod n\), as an arithmetic progression. b.mod_div_list(&a, &n) returns Some((start, stride, length)) in place of FLINT’s three outputs and all-zeros-on-failure convention; note that the dividend b is the receiver, as in mod_div on the mod-n page. The results agree exactly with FLINT’s. FLINT reduces a modulo n itself, while mod_div_list requires both inputs already reduced.

Bit packing and unpacking

The counterpart is BitBlockAccess, which reads or writes a block of bits at any position in a Natural or an Integer. Hold the buffer as a Natural (the limb-slice conversions convert a raw buffer); FLINT’s limb pointer plus sub-word shift becomes a single u64 bit position.

  FLINT Malachite
≈ int fmpz_bit_pack (ulong * arr, flint_bitcnt_t shift, flint_bitcnt_t bits, const fmpz_t coeff, int negate, int borrow) BitBlockAccess
≈ int fmpz_bit_unpack (fmpz_t coeff, ulong * arr, flint_bitcnt_t shift, flint_bitcnt_t bits, int negate, int borrow) BitBlockAccess
✓ void fmpz_bit_unpack_unsigned (fmpz_t coeff, const ulong * arr, flint_bitcnt_t shift, flint_bitcnt_t bits) BitBlockAccess

fmpz_bit_unpack_unsigned. buffer.get_bits(pos, pos + bits).

fmpz_bit_pack, fmpz_bit_unpack. assign_bits and get_bits move raw fields, which covers nonnegative coefficients with no borrow. FLINT’s negate and borrow parameters, which store negative coefficients in two’s complement and carry a borrow into the next field, have no counterpart, hence ≈. Also, fmpz_bit_pack adds its field into the array, assuming the bits above shift are zero, while assign_bits overwrites the range.

Logic Operations

In both libraries, negative operands behave as infinitely sign-extended two’s complement; see the GMP page.

  FLINT Malachite
✓ void fmpz_complement (fmpz_t r, const fmpz_t f) Not
✓ void fmpz_clrbit (fmpz_t f, ulong i) BitAccess
✓ void fmpz_combit (fmpz_t f, ulong i) BitAccess
✓ void fmpz_and (fmpz_t r, const fmpz_t a, const fmpz_t b) BitAnd
✓ void fmpz_or (fmpz_t r, const fmpz_t a, const fmpz_t b) BitOr
✓ void fmpz_xor (fmpz_t r, const fmpz_t a, const fmpz_t b) BitXor
✓ ulong fmpz_popcnt (const fmpz_t a) CountOnes

The operators and bits. !f for the ones’ complement; a & b, a | b, and a ^ b with their Assign forms; and f.clear_bit(i) and f.flip_bit(i), from BitAccess.

fmpz_popcnt. count_ones() on a Natural. FLINT leaves negative input undefined; on an Integer, checked_count_ones returns None for negative values.

Chinese remaindering

  FLINT Malachite
✓ void fmpz_CRT_ui (fmpz_t out, const fmpz_t r1, const fmpz_t m1, ulong r2, ulong m2, int sign) Crt, BalancedCrt
✓ void fmpz_CRT (fmpz_t out, const fmpz_t r1, const fmpz_t m1, const fmpz_t r2, const fmpz_t m2, int sign) Crt, BalancedCrt

fmpz_CRT, fmpz_CRT_ui. FLINT’s sign flag selects the representative in \([0, m_1m_2)\) or in \((-m_1m_2/2, m_1m_2/2]\); Malachite has a function for each. Natural::crt is sign = 0, and Integer::balanced_crt is sign = 1, taking its first residue as an Integer anywhere in \([-m_1, m_1)\), so a balanced result can be fed into the next combination. FLINT treats coprimality as an unchecked precondition and throws when m1 is not invertible; both Malachite functions return an Option, None exactly when the moduli share a factor. On their shared domain, the results agree with FLINT’s.

  FLINT Malachite
⚙ void fmpz_multi_CRT_init (fmpz_multi_CRT_t CRT) internal
⚙ int fmpz_multi_CRT_precompute (fmpz_multi_CRT_t CRT, const fmpz * moduli, slong len) internal
⚙ void fmpz_multi_CRT_precomp (fmpz_t output, const fmpz_multi_CRT_t P, const fmpz * inputs, int sign) internal
✓ int fmpz_multi_CRT (fmpz_t output, const fmpz * moduli, const fmpz * values, slong len, int sign) Natural::multi_crt, Integer::multi_balanced_crt
⚙ void fmpz_multi_CRT_clear (fmpz_multi_CRT_t P) internal

The fmpz_multi_CRT family. Natural::multi_crt is fmpz_multi_CRT with sign = 0, and Integer::multi_balanced_crt is sign = 1. The precomputed context (init, precompute, precomp, clear) is ported but not public, so each call takes the moduli afresh. Failure is None, under FLINT’s conditions: with one modulus, only 0 is rejected; with two or more, any 0 or 1, or any non-coprime pair, is rejected. FLINT reduces arbitrary inputs, while Malachite requires each residue already reduced modulo its modulus. Otherwise the results agree with FLINT’s, edge cases included.

  FLINT Malachite
⚙ void fmpz_multi_mod_ui (ulong * out, const fmpz_t in, const fmpz_comb_t comb, fmpz_comb_temp_t temp) internal
⚙ void fmpz_multi_CRT_ui (fmpz_t output, nn_srcptr residues, const fmpz_comb_t comb, fmpz_comb_temp_t ctemp, int sign) internal
⚙ void fmpz_comb_init (fmpz_comb_t comb, nn_srcptr primes, slong num_primes) internal
⚙ void fmpz_comb_temp_init (fmpz_comb_temp_t temp, const fmpz_comb_t comb) internal
⚙ void fmpz_comb_clear (fmpz_comb_t comb) internal
⚙ void fmpz_comb_temp_clear (fmpz_comb_temp_t temp) internal

The comb. Malachite has an internal port of FLINT’s multimodular comb, but it is not public. To reduce a value modulo many word-sized moduli, use Mod for each; to recombine, use Natural::multi_crt or Integer::multi_balanced_crt.

Primality testing

This section is not mapped row by row. Malachite does not test the primality of Naturals or Integers, so fmpz_is_prime, fmpz_is_probabprime and its variants, fmpz_nextprime, the fmpz_lucas_chain functions, and fmpz_divisor_in_residue_class_lenstra have no counterparts.

Special functions

  FLINT Malachite
✓ void fmpz_primorial (fmpz_t res, ulong n) Primorial
✗ void fmpz_euler_phi (fmpz_t res, const fmpz_t n)  
✗ void fmpz_factor_euler_phi (fmpz_t res, const fmpz_factor_t fac)  
✗ int fmpz_moebius_mu (const fmpz_t n)  
✗ int fmpz_factor_moebius_mu (const fmpz_factor_t fac)  
✗ void fmpz_divisor_sigma (fmpz_t res, ulong k, const fmpz_t n)  
✗ void fmpz_factor_divisor_sigma (fmpz_t res, ulong k, const fmpz_factor_t fac)  

fmpz_primorial. Natural::primorial(n), the product of the primes up to and including n, as in FLINT.

The multiplicative functions. Euler’s totient, the Möbius function, and the divisor sums \(\sigma_k\) have no counterparts, nor does a factorization type corresponding to fmpz_factor_t.