How Malachite Is Tested: Rationals
This page lists every public function of Rational, the rational number type of the
malachite-q crate, and records which independent implementations it is checked against.
The introduction describes the oracles and the testing they sit in; this page is
the ledger. It follows the organization of the crate’s documentation, one section per module, so
that a function is where its documentation is. A Rational is a sign and a reduced fraction of two
Naturals, so its arithmetic rests on the Natural and
Integer functions, but each of its functions is listed and checked
here in its own right.
Reading the tables
Each row is one operation, named after the module that implements it and linked to that module’s
documentation. The Functions column lists the traits and methods the module implements; a
trait’s by-value and by-reference implementations, and its *Assign form, count as one function,
since they compute the same thing, while functions with genuinely different results (div_mod
against div_rem, Add against Sum) are listed separately. The remaining columns are the
oracles of the introduction:
| meaning | |
|---|---|
| ✓ | The oracle computes this function and agrees with Malachite on every input tried. |
| ≈ | The oracle agrees, after an adaptation on the oracle side that is more than a change of spelling: a convention of Malachite’s that the oracle does not share is applied to the oracle’s output before the comparison. The mapping pages say what the adaptation is. |
| The oracle does not check this function. |
A function with no mark in any column is checked only by Malachite’s own unit and property tests. Those rows are collected at the end of the page, in What is not yet cross-checked, which is the list of what the oracles, Azurite first, should gain next.
Functions that are not part of the public interface are not listed: the limbs_* functions that
operate on limb slices and the other #[doc(hidden)] helpers are exercised by the same runs as
the functions built on them, but they are implementation details.
Basic
The constants and the standard traits of the type itself, from
malachite_q::rational.
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| constants | Zero, One, Two, NegativeOne, OneHalf |
|||||
| default | Default |
|||||
| named | Named |
|||||
| hash | Hash |
|||||
| clone | Clone |
✓ | ✓ | |||
| significant_bits | SignificantBits |
The constants are the values \(0\), \(1\), \(2\), \(-1\), and \(1/2\); every oracle run uses them
on the way to checking something else, but no run checks them as such. Named gives the type’s
name as a string, and Hash is derived from the sign, numerator, and denominator, so neither has
anything to compare against. Clone, also derived, is checked against GMP’s and num’s copies.
significant_bits, the total number of bits in the numerator and denominator, is covered by
property tests alone.
Comparison
From
malachite_q::rational::comparison.
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| cmp | Ord, PartialOrd |
✓ | ✓ | ✓ | ||
| eq | PartialEq, Eq |
✓ | ✓ | ✓ | ||
| cmp_complexity | cmp_complexity |
|||||
| cmp_abs | OrdAbs, PartialOrdAbs |
✓ | ||||
| cmp_abs | OrdAbsDouble, PartialOrdAbsDouble |
|||||
| eq_abs | EqAbs |
|||||
| partial_cmp_natural | PartialOrd<Natural> and the reverse direction |
✓ | ||||
| partial_cmp_integer | PartialOrd<Integer> and the reverse direction |
✓ | ||||
| partial_eq_natural | PartialEq<Natural> and the reverse direction |
✓ | ||||
| partial_eq_integer | PartialEq<Integer> and the reverse direction |
✓ | ||||
| partial_cmp_primitive_int | PartialOrd<u8>, …, PartialOrd<isize>, and the reverse directions |
✓ | ||||
| partial_eq_primitive_int | PartialEq<u8>, …, PartialEq<isize>, and the reverse directions |
✓ | ||||
| partial_cmp_primitive_float | PartialOrd<f32>, PartialOrd<f64>, and the reverse directions |
✓ | ||||
| partial_eq_primitive_float | PartialEq<f32>, PartialEq<f64>, and the reverse directions |
✓ | ||||
| partial_cmp_abs_natural | PartialOrdAbs<Natural> and the reverse direction |
|||||
| partial_cmp_abs_integer | PartialOrdAbs<Integer> and the reverse direction |
|||||
| eq_abs_natural | EqAbs<Natural> and the reverse direction |
|||||
| eq_abs_integer | EqAbs<Integer> and the reverse direction |
|||||
| partial_cmp_abs_primitive_int | PartialOrdAbs<u8>, …, PartialOrdAbs<isize>, and the reverse directions |
|||||
| eq_abs_primitive_int | EqAbs<u8>, …, EqAbs<isize>, and the reverse directions |
|||||
| partial_cmp_abs_primitive_float | PartialOrdAbs<f32>, PartialOrdAbs<f64>, and the reverse directions |
|||||
| eq_abs_primitive_float | EqAbs<f32>, EqAbs<f64>, and the reverse directions |
The order and equality of two Rationals are checked by Azurite, GMP, and num. Comparison and
equality with a Natural, an Integer, a primitive integer, or a primitive float are checked by
GMP. Azurite checks the comparisons with a Natural, an Integer, or a primitive integer, and the
equalities with a Natural or an Integer, with the Rational on the left (x < n), but not the
reverse direction, so those rows carry no Azurite mark. Comparison of absolute values is checked
by GMP’s cmp_abs for two Rationals; the mixed absolute-value comparisons and equalities, and
the doubled comparison cmp_abs_double (\(\operatorname{cmp}(|x|, 2|y|)\)), have no oracle.
cmp_complexity, the well-order by denominator, then absolute numerator, then sign, behind the
simplest-rational functions, is tested by unit and property tests alone.
Arithmetic
From
malachite_q::rational::arithmetic.
The module is large, so its rows are grouped by theme.
Addition, subtraction, multiplication, and division
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| add | Add |
✓ | ✓ | ✓ | ✓ | |
| add | Sum |
✓ | ||||
| sub | Sub |
✓ | ✓ | ✓ | ✓ | |
| abs_diff | AbsDiff |
|||||
| neg | Neg |
✓ | ✓ | ✓ | ||
| mul | Mul |
✓ | ✓ | ✓ | ✓ | |
| mul | Product |
✓ | ||||
| div | Div |
✓ | ✓ | ✓ | ✓ | |
| div | CheckedDiv |
✓ | ||||
| reciprocal | Reciprocal |
✓ | ✓ | ✓ | ||
| square | Square |
|||||
| abs_squared | AbsSquared |
|||||
| add_mul | AddMul |
✓ | ||||
| sub_mul | SubMul |
|||||
| mul_add_mul | MulAddMul |
|||||
| mul_sub_mul | MulSubMul |
|||||
| average | Average |
The four field operations, negation, and the reciprocal are checked by Azurite (AzRat.add,
sub, mul, div, neg, inv, each reducing its result to lowest terms with Azurite’s GCD), by
GMP and num, and, for the four operations, by references that combine the fractions by the
schoolbook formula and reduce once at the end. Sum and Product are checked against references
that do the same over a whole sequence, and add_mul against a reference that multiplies and adds
in separate canonical steps. checked_div is checked against num. square, abs_squared,
abs_diff, average, and the other fused operations are covered by property tests that compare
them with the unfused combinations, which is a strong check but not an independent one.
Shifts
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| shl | Shl<u8>, …, Shl<isize> |
✓ | ✓ | |||
| shr | Shr<u8>, …, Shr<isize> |
✓ | ✓ | |||
| round_to_multiple_of_power_of_2 | RoundToMultipleOfPowerOf2 |
Shifting a Rational multiplies or divides it by a power of 2 exactly, with no rounding, so a
negative count simply reverses the direction. Both shifts are checked by Azurite’s shiftLeft and
shiftRight and against GMP for every shift type. round_to_multiple_of_power_of_2 is covered by
property tests alone.
Signs and units
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| sign | Sign |
✓ | ✓ | ✓ | ||
| abs | Abs |
✓ | ✓ | ✓ | ||
| is_unit | IsUnit |
|||||
| conjugate | Conjugate |
|||||
| canonicalize_unit | CanonicalizeUnit |
|||||
| canonical_unit_i_pow | CanonicalUnitIPow |
sign and abs are checked by Azurite (AzRat.sign and AzRat.abs), GMP, and num. The unit
functions (is_unit, true for every nonzero Rational; conjugate; canonicalize_unit;
canonical_unit_i_pow) are the trivial cases of functions that matter for Gaussian rationals and
polynomials, where they are cross-checked.
Rounding
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| floor | Floor |
✓ | ✓ | ✓ | ||
| ceiling | Ceiling |
✓ | ✓ | ✓ | ||
| round_to_multiple | RoundToMultiple |
|||||
| mod_op | Mod |
✓ | ||||
| mod_op | Rem |
✓ | ✓ | |||
| mod_op | CeilingMod |
✓ |
floor and ceiling, which return an Integer, are checked by Azurite’s AzRat.round in the
Floor and Ceiling modes, by GMP, and by num. The remainders of a Rational by a Rational
(mod_op, whose result takes the divisor’s sign; rem, the dividend’s; and ceiling_mod) are
checked against references that compute the floored, truncated, or ceiling quotient and subtract,
and rem also against num. round_to_multiple is covered by property tests alone; rounding to an
Integer in any mode is listed under Integers and naturals.
Powers, roots, and logarithms
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| pow | Pow<u64>, Pow<i64> |
✓ | ✓ | ✓ | ||
| sqrt | CheckedSqrt |
|||||
| root | CheckedRoot<u64>, CheckedRoot<i64> |
|||||
| express_as_power | ExpressAsPower |
|||||
| log_base_2 | FloorLogBase2, CeilingLogBase2, floor_log_base_2_abs, ceiling_log_base_2_abs |
✓ | ||||
| log_base_2 | CheckedLogBase2 |
|||||
| log_base | FloorLogBase, CeilingLogBase, CheckedLogBase |
✓ | ||||
| log_base | approx_log |
|||||
| log_base_power_of_2 | FloorLogBasePowerOf2, CeilingLogBasePowerOf2, CheckedLogBasePowerOf2 |
pow, with a non-negative or a negative exponent, is checked by Azurite (AzRat.pow and zpow),
GMP, and num. The base-2 logarithms are checked by Azurite’s floorLogBase2Abs and
ceilingLogBase2Abs, and the logarithms to a u64 base by floorLogBaseAbs (the ceiling and
checked forms derived from it by an exact power comparison in the oracle). checked_log_base_2,
the logarithms to a power-of-2 base, checked_sqrt, checked_root, and express_as_power, which
return a value only when the answer is exact, are covered by property tests alone, as is
approx_log, a floating-point estimate.
Powers of 2
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| power_of_2 | PowerOf2<u64>, PowerOf2<i64> |
|||||
| is_power_of_2 | IsPowerOf2 |
|||||
| next_power_of_2 | NextPowerOf2 |
The powers of 2, including negative ones (\(2^{-k}\)), is_power_of_2, and next_power_of_2
(the smallest power of 2 at least the input, possibly a fraction) are covered by property tests
alone.
Approximation
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| approximate | Approximate |
✓ | ||||
| simplest_rational_in_interval | SimplestRationalInInterval |
✓ | ||||
| denominators_in_closed_interval | DenominatorsInClosedInterval |
|||||
| farey_neighbors | Rational::farey_neighbors |
✓ | ||||
| height | Height, HeightRef, height_significant_bits |
✓ | ||||
| reconstruct | Rational::reconstruct, reconstruct_ref |
✓ | ||||
| reconstruct | Rational::reconstruct_with_bounds, reconstruct_with_bounds_ref |
✓ |
approximate, the closest Rational with a bounded denominator, is checked against a reference
that tries every denominator; simplest_rational_in_interval against references that search by
increasing denominator and that walk the continued fractions of the endpoints. The neighbors of a
Rational in the Farey sequence of a given order are checked against FLINT’s
fmpq_farey_neighbors, the height (the larger of the numerator and denominator) and its bit count
against fmpq_height and fmpq_height_bits, and rational reconstruction from a residue, with the
default bounds and with explicit ones, against fmpq_reconstruct_fmpz and
fmpq_reconstruct_fmpz_2. denominators_in_closed_interval is covered by property tests alone.
Number theory
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| gcd | Gcd |
✓ | ||||
| extended_gcd | ExtendedGcd |
✓ | ||||
| dedekind_sum | Rational::dedekind_sum |
✓ | ✓ | |||
| harmonic_number | Rational::harmonic_number |
✓ | ✓ |
The GCD of two Rationals, the largest Rational of which both are integer multiples, is checked
against FLINT’s fmpq_gcd, and the extended GCD, with its cofactors, against
fmpq_gcd_cofactors. The Dedekind sum \(s(h, k)\) is checked against FLINT’s fmpq_dedekind_sum
and against a reference that evaluates the defining sum term by term, and the harmonic numbers
\(H_n\) against FLINT’s fmpq_harmonic_ui and the sum \(\sum_{i=1}^n 1/i\).
Conversion
From
malachite_q::rational::conversion.
Integers and naturals
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| from_natural | From<Natural> |
✓ | ||||
| from_integer | From<Integer> |
✓ | ||||
| from_numerator_and_denominator | from_naturals, from_naturals_ref |
✓ | ||||
| from_numerator_and_denominator | from_integers, from_integers_ref |
✓ | ✓ | ✓ | ||
| from_numerator_and_denominator | from_sign_and_naturals, from_sign_and_naturals_ref |
✓ | ||||
| from_numerator_and_denominator | from_unsigneds, from_sign_and_unsigneds |
|||||
| from_numerator_and_denominator | from_signeds |
✓ | ||||
| from_numerator_and_denominator | const_from_unsigneds, const_from_signeds |
|||||
| to_numerator_and_denominator | to_numerator, into_numerator, numerator_ref |
✓ | ✓ | |||
| to_numerator_and_denominator | to_denominator, into_denominator, denominator_ref |
✓ | ✓ | |||
| to_numerator_and_denominator | to_numerator_and_denominator, into_numerator_and_denominator, numerator_and_denominator_ref |
|||||
| mutate_numerator_and_denominator | mutate_numerator, mutate_denominator, mutate_numerator_and_denominator |
|||||
| integer_from_rational | RoundingFrom<Rational> for Integer |
✓ | ||||
| integer_from_rational | TryFrom<Rational>, ConvertibleFrom<Rational> for Integer |
|||||
| natural_from_rational | RoundingFrom<Rational>, TryFrom<Rational>, ConvertibleFrom<Rational> for Natural |
|||||
| from_gaussian_integer | TryFrom<GaussianInteger>, ConvertibleFrom<GaussianInteger> |
Conversion from a Natural or an Integer, and construction from a numerator and denominator
(from_naturals, from_integers, from_sign_and_naturals, each reducing the fraction), are
checked by Azurite (AzNat.toAzRat, AzInt.toAzRat, ofAzNats, ofAzInts, and ofSignAzNats);
from_integers also against GMP and num, and from_signeds against GMP. The numerator and
denominator accessors are checked against GMP’s and num’s. Rounding a Rational to an Integer in
any mode is checked by Azurite’s AzRat.round, Exact being checked as “the denominator is 1”.
The fallible and clamping conversions to Integer and Natural, the constructors from primitive
pairs, the paired accessors, and mutate_numerator_and_denominator, which applies a function to
the parts and re-reduces, are covered by property tests alone, as is the conversion from a
Gaussian integer.
Primitive types
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| from_primitive_int | From<u8>, …, From<isize> |
✓ | ✓ | |||
| from_primitive_int | const_from_unsigned, const_from_signed |
|||||
| primitive_int_from_rational | RoundingFrom<Rational>, TryFrom<Rational>, ConvertibleFrom<Rational> for every primitive integer |
|||||
| from_primitive_float | TryFrom<f32>, TryFrom<f64> |
✓ | ||||
| from_primitive_float | ConvertibleFrom<f32>, ConvertibleFrom<f64> |
|||||
| from_float_simplest | try_from_float_simplest |
|||||
| primitive_float_from_rational | RoundingFrom<Rational> for f32, f64 |
|||||
| primitive_float_from_rational | TryFrom<Rational>, ConvertibleFrom<Rational> for f32, f64 |
|||||
| from_bool | From<bool> |
|||||
| is_integer | IsInteger |
|||||
| is_real | IsReal |
|||||
| is_gaussian_integer | IsGaussianInteger |
Conversion from every primitive integer type is checked by Azurite (UInt64.toAzRat,
Int64.toAzRat, and their narrower forms) and GMP, and the exact conversion from a finite f32 or
f64 by GMP. Conversion to a float is compared with GMP’s mpq_get_d in the Down mode only,
since GMP’s conversion truncates rather than rounding in a chosen mode; the other modes, like the
conversions to the primitive integers and try_from_float_simplest (the simplest Rational that
rounds to a given float), are covered by property tests alone.
Mantissa and exponent
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| mantissa_and_exponent | SciMantissaAndExponent<f32, i64>, SciMantissaAndExponent<f64, i64> |
|||||
| mantissa_and_exponent | sci_mantissa_and_exponent_round, sci_mantissa_and_exponent_round_ref |
The scientific mantissa and exponent of a Rational, a float mantissa in \([1, 2)\) and a signed
exponent, rounded in a chosen mode, are covered by property tests alone. The Natural versions are
checked by Azurite, and the same oracle would extend to a fraction.
Continued fractions
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| to_continued_fraction | ContinuedFraction |
|||||
| from_continued_fraction | Rational::from_continued_fraction, from_continued_fraction_ref |
✓ | ||||
| convergents | Convergents |
✓ |
Building a Rational from its continued fraction and listing its convergents are checked against
references that evaluate the continued fraction from the bottom up and that compute each convergent
from scratch. The continued fraction itself is tested by round trips through
from_continued_fraction and by its defining properties.
Digits
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| digits | Rational::digits |
|||||
| to_digits | to_digits, into_digits |
|||||
| from_digits | Rational::from_digits, from_digits_ref |
|||||
| power_of_2_digits | Rational::power_of_2_digits |
|||||
| to_power_of_2_digits | to_power_of_2_digits, into_power_of_2_digits |
|||||
| from_power_of_2_digits | Rational::from_power_of_2_digits, from_power_of_2_digits_ref |
The expansion of a Rational in a base, an integer part and a fractional part that eventually
repeats, and its inverse are covered by property tests alone: round trips through the
from_* functions, agreement of the integer part with the Natural digit functions (which are
checked by Azurite), and the expansion’s shape, such as, in a power-of-2 base, a repeating part that
is empty exactly when the denominator is a power of 2.
Strings
| Operation | Functions | Azurite | FLINT | GMP | num | Reference |
|---|---|---|---|---|---|---|
| to_string | Display, Debug |
✓ | ✓ | ✓ | ||
| to_string | Binary, Octal, LowerHex, UpperHex |
✓ | ✓ | |||
| to_string | ToStringBase |
✓ | ||||
| from_string | FromStr |
✓ | ✓ | ✓ | ||
| from_string | FromStringBase |
✓ | ||||
| from_sci_string | FromSciString |
✓ | ||||
| from_sci_string | from_sci_string_simplest, from_sci_string_simplest_with_options |
|||||
| to_sci | ToSci |
✓ | ||||
| to_sci | length_after_point_in_small_base |
✓ | ||||
| format_rational | format_rational_str, GmpFormatArg |
✓ | ||||
| latex | ToLatex |
|||||
| typst | ToTypst |
|||||
| serde | Serialize, Deserialize |
Decimal output and input are checked by Azurite (toString and a parse in Malachite’s grammar,
with its optional + signs and its rejection of a zero denominator), GMP, and num; output and
input in other bases, and the formatting traits, by GMP (and the traits also by num). Scientific
notation is checked by Azurite: from_sci_string in every base and with its options by
AzRat.fromSci, to_sci and to_sci_with_options digit for digit by AzRat.toSci (the options’
Debug text read into Azurite’s SciOptions), fmt_sci_valid by toSciExact, and
length_after_point_in_small_base, the number of digits after the point when the expansion ends,
by lengthAfterPoint. The GMP-style format_rational_str is compared with GMP’s own
gmp_snprintf. from_sci_string_simplest, which returns the simplest Rational that rounds to
the given digits, and LaTeX, Typst, and serde output are covered by property tests alone.
Exhaustive generation
This section is not yet written.
Random generation
This section is not yet written.
What is not yet cross-checked
This section is not yet written.