Malachite for FLINT Users: Gaussian Integers
This page maps the functions of FLINT’s Gaussian integer type, fmpzi_t, onto their Malachite
counterpart:
GaussianInteger,
from the malachite-nz crate. It follows the organization of the
fmpzi.h chapter of the FLINT manual, as of FLINT 3.6.0,
and is a companion to Malachite for FLINT Users: Integers, whose
conventions, including word types and aliasing, apply
here as well; the mapping index lists the whole family. Every function is mapped,
including three that the header declares but the manual chapter does not list. Where FLINT
exposes a function, Malachite often exposes a struct field, an operator, or a trait shared with
its real types.
Conventions
The fmpzi representation
A
GaussianInteger
is a pair of
Integers in
public fields, real and imaginary. Every pair of parts is a valid value, so there is no
constructor: the struct literal is the constructor.
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. |
Types, macros and constants
The types are covered under Conventions.
| FLINT | Malachite | |
|---|---|---|
| ✓ | fmpzi_realref(x) |
x.real |
| ✓ | fmpzi_imagref(x) |
x.imaginary |
fmpzi_realref, fmpzi_imagref. The fields are read and written directly: x.real,
x.real = ..., x.real += ..., and &mut x.real for any in-place
Integer
function. Unlike the rational case on
the fmpq page, writing a part directly
is safe, because there is no canonical form to disturb.
Basic manipulation
| FLINT | Malachite | |
|---|---|---|
| ✓ | void fmpzi_init (fmpzi_t x) |
GaussianInteger::ZERO |
| — | void fmpzi_clear (fmpzi_t x) |
|
| ✓ | void fmpzi_swap (fmpzi_t x, fmpzi_t y) |
mem::swap |
| ✓ | void fmpzi_zero (fmpzi_t x) |
GaussianInteger::ZERO |
| ✓ | void fmpzi_one (fmpzi_t x) |
GaussianInteger::ONE |
| ✓ | void fmpzi_set (fmpzi_t res, const fmpzi_t x) |
Clone |
| ✓ | void fmpzi_set_si_si (fmpzi_t res, slong a, slong b) |
GaussianInteger { real: Integer::from(a), imaginary: Integer::from(b) } |
fmpzi_init, fmpzi_clear. let x = GaussianInteger::ZERO;, or
Default. Dropping
replaces clearing; see the GMP page.
fmpzi_swap, fmpzi_zero, fmpzi_one, fmpzi_set. mem::swap(&mut x, &mut y),
x = GaussianInteger::ZERO, x = GaussianInteger::ONE, and res = x.clone() or
res.clone_from(&x), the latter reusing the destination’s storage as fmpzi_set does.
fmpzi_set_si_si. The struct literal, with each part converted from any primitive integer
or from a
Natural. A
purely real value can also be built with GaussianInteger::from(a).
Input and output
| FLINT | Malachite | |
|---|---|---|
| ≈ | void fmpzi_print (const fmpzi_t x) |
Display |
fmpzi_print. print!("{x}"). The formats differ: FLINT always prints both parts and
*I, as in 3+4*I, 3+0*I, 0-1*I, while Malachite’s
Display
omits a zero part and a unit coefficient, as in 3+4i, 3, -i.
Random number generation
| FLINT | Malachite | |
|---|---|---|
| ≈ | void fmpzi_randtest (fmpzi_t res, flint_rand_t state, flint_bitcnt_t bits) |
random_gaussian_integers, striped_random_gaussian_integers |
fmpzi_randtest. Two independent fmpz_randtest draws, one per part, so the notes on
the fmpz page apply to each part. Malachite’s
generators also draw the parts independently, in plain and striped flavors; they are infinite
iterators over a
Seed rather
than calls against a state, their size parameter is a mean bit length rather than a bound, and
they require the random feature.
Properties
| FLINT | Malachite | |
|---|---|---|
| ✓ | int fmpzi_equal (const fmpzi_t x, const fmpzi_t y) |
== |
| ✓ | int fmpzi_is_zero (const fmpzi_t x) |
x == 0u32 |
| ✓ | int fmpzi_is_one (const fmpzi_t x) |
x == 1u32 |
fmpzi_is_zero, fmpzi_is_one. Mixed-type
PartialEq against a
primitive integer, which holds when the imaginary part is zero and the real part matches.
Units
| FLINT | Malachite | |
|---|---|---|
| ✓ | int fmpzi_is_unit (const fmpzi_t x) |
is_unit |
| ✓ | slong fmpzi_canonical_unit_i_pow (const fmpzi_t x) |
canonical_unit_i_pow |
| ✓ | void fmpzi_canonicalise_unit (fmpzi_t res, const fmpzi_t x) |
canonicalize_unit |
Units. Both libraries choose the same canonical associate, tie for tie: the one whose
argument lies in \((-\pi/4, \pi/4]\), that is, whose real part is positive and at least the
imaginary part in absolute value, with \(a + ai\) chosen on the diagonal. Zero is its own
canonical form. canonical_unit_i_pow returns the \(k \in \{0, 1, 2, 3\}\) with \(x i^k\)
canonical, as a u64;
canonicalize_unit
has an in-place
_assign
form.
Norms
| FLINT | Malachite | |
|---|---|---|
| ✓ | slong fmpzi_bits (const fmpzi_t x) |
max_significant_bits |
| ✓ | void fmpzi_norm (fmpz_t res, const fmpzi_t x) |
abs_squared |
fmpzi_bits. The bit length of the larger part in absolute value. It is not what
significant_bits
returns for a GaussianInteger, which is the sum of the two parts’ counts.
fmpzi_norm. \(a^2 + b^2\), returned as an
Integer.
Arithmetic
| FLINT | Malachite | |
|---|---|---|
| ✓ | void fmpzi_conj (fmpzi_t res, const fmpzi_t x) |
conjugate |
| ✓ | void fmpzi_neg (fmpzi_t res, const fmpzi_t x) |
- |
| ✓ | void fmpzi_add (fmpzi_t res, const fmpzi_t x, const fmpzi_t y) |
+ |
| ✓ | void fmpzi_sub (fmpzi_t res, const fmpzi_t x, const fmpzi_t y) |
- |
| ✓ | void fmpzi_sqr (fmpzi_t res, const fmpzi_t x) |
square |
| ✓ | void fmpzi_mul (fmpzi_t res, const fmpzi_t x, const fmpzi_t y) |
* |
| ✓ | void fmpzi_pow_ui (fmpzi_t res, const fmpzi_t x, ulong exp) |
pow, pow_assign |
| ✓ | void fmpzi_mul_i (fmpzi_t z, const fmpzi_t x) |
mul_i |
| ✓ | void fmpzi_div_i (fmpzi_t z, const fmpzi_t x) |
div_i |
| ✓ | void fmpzi_mul_i_pow_si (fmpzi_t res, const fmpzi_t z, slong k) |
mul_i_pow, mul_i_pow_assign |
Ownership. Each operation comes in the usual ownership variants, x + y, x + &y,
&x + y, &x + &y, and x += y, with the by-value forms reusing their operand’s storage;
the trait methods have _assign forms, such as
square_assign.
pow takes a u64 exponent.
fmpzi_mul_i, fmpzi_div_i, fmpzi_mul_i_pow_si. Declared in the header but not listed
in the manual chapter.
MulIPow
takes a u64 exponent; since only \(k \bmod 4\) matters, pass that for a negative FLINT
exponent \(k\).
Division
| FLINT | Malachite | |
|---|---|---|
| ✓ | void fmpzi_divexact (fmpzi_t q, const fmpzi_t x, const fmpzi_t y) |
div_exact |
| ✓ | void fmpzi_divrem (fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y) |
div_rem, div_assign_rem |
| — | void fmpzi_divrem_approx (fmpzi_t q, fmpzi_t r, const fmpzi_t x, const fmpzi_t y) |
|
| ✓ | slong fmpzi_remove_one_plus_i (fmpzi_t res, const fmpzi_t x) |
remove_one_plus_i, remove_one_plus_i_assign |
fmpzi_divexact. As in FLINT, the division must be exact; otherwise the result is
unspecified and may be a panic.
fmpzi_divrem. Malachite rounds as FLINT does: each part of the exact quotient is rounded
to the nearest integer, with ties rounded up, so the remainder’s norm satisfies
\(N(r) \leq N(y) / 2\) and the result agrees with FLINT’s at ties. The / and % operators
return the two halves of the same pair.
fmpzi_divrem_approx. Its quotient depends on a double-precision estimate and guarantees
only \(N(r) < N(y)\), without fixing which remainder; Malachite has no public counterpart, and
div_rem satisfies the stronger bound.
fmpzi_remove_one_plus_i. Returns the reduced number and the exponent as a tuple, as
RemovePower does for fmpz_remove; the _assign form reduces in place and returns the
exponent. Zero maps to zero with exponent 0, as in FLINT.
GCD
| FLINT | Malachite | |
|---|---|---|
| — | void fmpzi_gcd_euclidean (fmpzi_t res, const fmpzi_t x, const fmpzi_t y) |
|
| ⚙ | void fmpzi_gcd_euclidean_improved (fmpzi_t res, const fmpzi_t x, const fmpzi_t y) |
Gcd, GcdAssign |
| — | void fmpzi_gcd_binary (fmpzi_t res, const fmpzi_t x, const fmpzi_t y) |
|
| — | void fmpzi_gcd_shortest (fmpzi_t res, const fmpzi_t x, const fmpzi_t y) |
|
| ✓ | void fmpzi_gcd (fmpzi_t res, const fmpzi_t x, const fmpzi_t y) |
Gcd, GcdAssign |
The GCD family. Every FLINT variant returns the GCD in canonical unit form, so
all five return the same value, and so does Malachite’s
gcd.
The named variants differ only in algorithm, and Malachite does not expose them separately.
Primality testing
| FLINT | Malachite | |
|---|---|---|
| ✗ | int fmpzi_is_prime (const fmpzi_t n) |
|
| ✗ | int fmpzi_is_probabprime (const fmpzi_t n) |
fmpzi_is_prime, fmpzi_is_probabprime. No counterpart, because Malachite has no bignum
primality test; see the fmpz page. FLINT’s test:
a purely real or purely imaginary value is prime when its nonzero part is, in absolute value, a
prime congruent to 3 modulo 4; any other value is prime when its norm is prime.