malachite-q 0.14.0

The arbitrary-precision type Rational, with efficient algorithms partially derived from GMP and FLINT.
Documentation
// Copyright © 2026 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.

use crate::Rational;
use crate::gaussian_rational::GaussianRational;
use crate::gaussian_rational::exhaustive::gaussian_rational_from_pair;
use crate::rational::random::{
    RandomRationalsFromDoubleAndSign, random_rationals, striped_random_rationals,
};
use core::iter::Map;
use malachite_base::num::conversion::traits::ImaginaryFrom;
use malachite_base::num::random::geometric::GeometricRandomNaturalValues;
use malachite_base::random::Seed;
use malachite_base::tuples::random::{RandomPairsFromSingle, random_pairs_from_single};
use malachite_nz::natural::random::{RandomNaturals, StripedRandomNaturals};

#[doc(hidden)]
pub type RandomRationals = RandomRationalsFromDoubleAndSign<
    RandomNaturals<GeometricRandomNaturalValues<u64>>,
    RandomNaturals<GeometricRandomNaturalValues<u64>>,
>;

#[doc(hidden)]
pub type StripedRandomRationals = RandomRationalsFromDoubleAndSign<
    StripedRandomNaturals<GeometricRandomNaturalValues<u64>>,
    StripedRandomNaturals<GeometricRandomNaturalValues<u64>>,
>;

#[doc(hidden)]
pub type RandomGaussianRationalsFromPairs =
    Map<RandomPairsFromSingle<RandomRationals>, fn((Rational, Rational)) -> GaussianRational>;

#[doc(hidden)]
pub type StripedRandomGaussianRationalsFromPairs = Map<
    RandomPairsFromSingle<StripedRandomRationals>,
    fn((Rational, Rational)) -> GaussianRational,
>;

/// Generates random purely real [`GaussianRational`]s, whose real parts are generated by
/// [`random_rationals`] and have a specified mean bit length.
///
/// The output length is infinite.
///
/// # Expected complexity per iteration
/// Same as the complexity of [`random_rationals`].
///
/// # Panics
/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if after being reduced
/// to lowest terms, their sum is greater than or equal to $2^{64}$.
///
/// # Examples
/// ```
/// use malachite_base::iterators::prefix_to_string;
/// use malachite_base::random::EXAMPLE_SEED;
/// use malachite_q::gaussian_rational::random::*;
///
/// assert_eq!(
///     prefix_to_string(random_real_gaussian_rationals(EXAMPLE_SEED, 32, 1), 4),
///     "[-7301/34, -4183103/1234731190583, 54812347098686/6195807891591254727, \
///     812739/17841539017, ...]"
/// )
/// ```
#[inline]
pub fn random_real_gaussian_rationals(
    seed: Seed,
    mean_bits_numerator: u64,
    mean_bits_denominator: u64,
) -> Map<RandomRationals, fn(Rational) -> GaussianRational> {
    random_rationals(seed, mean_bits_numerator, mean_bits_denominator).map(GaussianRational::from)
}

/// Generates random purely imaginary [`GaussianRational`]s, whose imaginary parts are generated by
/// [`random_rationals`] and have a specified mean bit length.
///
/// The output length is infinite.
///
/// # Expected complexity per iteration
/// Same as the complexity of [`random_rationals`].
///
/// # Panics
/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if after being reduced
/// to lowest terms, their sum is greater than or equal to $2^{64}$.
///
/// # Examples
/// ```
/// use malachite_base::iterators::prefix_to_string;
/// use malachite_base::random::EXAMPLE_SEED;
/// use malachite_q::gaussian_rational::random::*;
///
/// assert_eq!(
///     prefix_to_string(random_imaginary_gaussian_rationals(EXAMPLE_SEED, 32, 1), 4),
///     "[-7301i/34, -4183103i/1234731190583, 54812347098686i/6195807891591254727, 812739i/17841539\
///     017, ...]"
/// )
/// ```
#[inline]
pub fn random_imaginary_gaussian_rationals(
    seed: Seed,
    mean_bits_numerator: u64,
    mean_bits_denominator: u64,
) -> Map<RandomRationals, fn(Rational) -> GaussianRational> {
    random_rationals(seed, mean_bits_numerator, mean_bits_denominator)
        .map(GaussianRational::imaginary_from)
}

/// Generates random [`GaussianRational`]s, whose real and imaginary parts are generated by
/// [`random_rationals`] and have a specified mean bit length.
///
/// The output length is infinite.
///
/// # Expected complexity per iteration
/// Same as the complexity of [`random_rationals`].
///
/// # Panics
/// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if after being reduced
/// to lowest terms, their sum is greater than or equal to $2^{64}$.
///
/// # Examples
/// ```
/// use malachite_base::iterators::prefix_to_string;
/// use malachite_base::random::EXAMPLE_SEED;
/// use malachite_q::gaussian_rational::random::*;
///
/// assert_eq!(
///     prefix_to_string(random_gaussian_rationals(EXAMPLE_SEED, 32, 1), 4),
///     "[-4183103/1234731190583-7301i/34, 812739/17841539017+54812347098686i/6195807891591254727, \
///     677/1138982845180-665i/908, 270142/5+166i/22491855393807861245619791028129, ...]"
/// )
/// ```
#[inline]
pub fn random_gaussian_rationals(
    seed: Seed,
    mean_bits_numerator: u64,
    mean_bits_denominator: u64,
) -> RandomGaussianRationalsFromPairs {
    random_pairs_from_single(random_rationals(
        seed,
        mean_bits_numerator,
        mean_bits_denominator,
    ))
    .map(gaussian_rational_from_pair)
}

/// Generates random purely real striped [`GaussianRational`]s, whose real parts are generated by
/// [`striped_random_rationals`] and have a specified mean bit length and mean stripe length.
///
/// The output length is infinite.
///
/// # Expected complexity per iteration
/// Same as the complexity of [`striped_random_rationals`].
///
/// # Panics
/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if
/// after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
///
/// # Examples
/// ```
/// use malachite_base::iterators::prefix_to_string;
/// use malachite_base::random::EXAMPLE_SEED;
/// use malachite_q::gaussian_rational::random::*;
///
/// assert_eq!(
///     prefix_to_string(
///         striped_random_real_gaussian_rationals(EXAMPLE_SEED, 16, 1, 32, 1),
///         4
///     ),
///     "[-8192/127, -16776704/4396972769407, 8796093005951/648518346332962816, 87381/2863267840, .\
///     ..]"
/// )
/// ```
#[inline]
pub fn striped_random_real_gaussian_rationals(
    seed: Seed,
    mean_stripe_numerator: u64,
    mean_stripe_denominator: u64,
    mean_bits_numerator: u64,
    mean_bits_denominator: u64,
) -> Map<StripedRandomRationals, fn(Rational) -> GaussianRational> {
    striped_random_rationals(
        seed,
        mean_stripe_numerator,
        mean_stripe_denominator,
        mean_bits_numerator,
        mean_bits_denominator,
    )
    .map(GaussianRational::from)
}

/// Generates random purely imaginary striped [`GaussianRational`]s, whose imaginary parts are
/// generated by [`striped_random_rationals`] and have a specified mean bit length and mean stripe
/// length.
///
/// The output length is infinite.
///
/// # Expected complexity per iteration
/// Same as the complexity of [`striped_random_rationals`].
///
/// # Panics
/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if
/// after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
///
/// # Examples
/// ```
/// use malachite_base::iterators::prefix_to_string;
/// use malachite_base::random::EXAMPLE_SEED;
/// use malachite_q::gaussian_rational::random::*;
///
/// let xs = striped_random_imaginary_gaussian_rationals(EXAMPLE_SEED, 16, 1, 32, 1);
/// assert_eq!(
///     prefix_to_string(xs, 4),
///     "[-8192i/127, -16776704i/4396972769407, 8796093005951i/648518346332962816, 87381i/286326784\
///     0, ...]"
/// )
/// ```
#[inline]
pub fn striped_random_imaginary_gaussian_rationals(
    seed: Seed,
    mean_stripe_numerator: u64,
    mean_stripe_denominator: u64,
    mean_bits_numerator: u64,
    mean_bits_denominator: u64,
) -> Map<StripedRandomRationals, fn(Rational) -> GaussianRational> {
    striped_random_rationals(
        seed,
        mean_stripe_numerator,
        mean_stripe_denominator,
        mean_bits_numerator,
        mean_bits_denominator,
    )
    .map(GaussianRational::imaginary_from)
}

/// Generates random striped [`GaussianRational`]s, whose real and imaginary parts are generated by
/// [`striped_random_rationals`] and have a specified mean bit length and mean stripe length.
///
/// The output length is infinite.
///
/// # Expected complexity per iteration
/// Same as the complexity of [`striped_random_rationals`].
///
/// # Panics
/// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <
/// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if
/// after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$.
///
/// # Examples
/// ```
/// use malachite_base::iterators::prefix_to_string;
/// use malachite_base::random::EXAMPLE_SEED;
/// use malachite_q::gaussian_rational::random::*;
///
/// assert_eq!(
///     prefix_to_string(
///         striped_random_gaussian_rationals(EXAMPLE_SEED, 16, 1, 32, 1),
///         4
///     ),
///     "[-16776704/4396972769407-8192i/127, 87381/2863267840+8796093005951i/648518346332962816, 51\
///     /58408828928-1024i/2043, 270335/7+85i/13521606402434254795714066382848, ...]"
/// )
/// ```
#[inline]
pub fn striped_random_gaussian_rationals(
    seed: Seed,
    mean_stripe_numerator: u64,
    mean_stripe_denominator: u64,
    mean_bits_numerator: u64,
    mean_bits_denominator: u64,
) -> StripedRandomGaussianRationalsFromPairs {
    random_pairs_from_single(striped_random_rationals(
        seed,
        mean_stripe_numerator,
        mean_stripe_denominator,
        mean_bits_numerator,
        mean_bits_denominator,
    ))
    .map(gaussian_rational_from_pair)
}