use crate::Rational;
use crate::arithmetic::denominators_in_closed_interval::DenominatorsInClosedRationalInterval;
use crate::arithmetic::traits::DenominatorsInClosedInterval;
use crate::exhaustive::RationalsWithDenominator;
use core::cmp::min;
use malachite_base::bools::random::{RandomBools, random_bools};
use malachite_base::iterators::iterator_cache::IteratorCache;
use malachite_base::num::arithmetic::traits::{
CoprimeWith, Reciprocal, RoundToMultiple, UnsignedAbs,
};
use malachite_base::num::basic::traits::One;
use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
use malachite_base::num::logic::traits::SignificantBits;
use malachite_base::num::random::geometric::{
GeometricRandomNaturalValues, geometric_random_unsigneds,
};
use malachite_base::num::random::striped::StripedBitSource;
use malachite_base::num::random::{
RandomPrimitiveInts, VariableRangeGenerator, random_primitive_ints,
};
use malachite_base::random::Seed;
use malachite_base::rounding_modes::RoundingMode::*;
use malachite_nz::integer::Integer;
use malachite_nz::integer::random::{
RandomIntegerRange, RandomIntegerRangeToInfinity, get_random_integer_from_range_to_infinity,
get_random_integer_from_range_to_negative_infinity,
get_striped_random_integer_from_range_to_infinity,
get_striped_random_integer_from_range_to_negative_infinity, random_integer_range,
random_integer_range_to_infinity, random_integer_range_to_negative_infinity,
};
use malachite_nz::natural::Natural;
use malachite_nz::natural::random::{
RandomNaturals, StripedRandomNaturals, random_naturals, random_positive_naturals,
striped_random_naturals, striped_random_positive_naturals,
};
use std::collections::HashMap;
#[derive(Clone, Debug)]
pub struct RandomRationalsFromSingle<I: Iterator<Item = Natural>> {
xs: I,
}
impl<I: Iterator<Item = Natural>> Iterator for RandomRationalsFromSingle<I> {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
Some(Rational::from_naturals(
self.xs.next().unwrap(),
self.xs.next().unwrap(),
))
}
}
pub fn random_positive_rationals(
seed: Seed,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalsFromSingle<RandomNaturals<GeometricRandomNaturalValues<u64>>> {
RandomRationalsFromSingle {
xs: random_positive_naturals(seed, mean_bits_numerator, mean_bits_denominator),
}
}
#[derive(Clone, Debug)]
pub struct RandomRationalsFromDouble<I: Iterator<Item = Natural>, J: Iterator<Item = Natural>> {
xs: I,
ys: J,
}
impl<I: Iterator<Item = Natural>, J: Iterator<Item = Natural>> Iterator
for RandomRationalsFromDouble<I, J>
{
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
Some(Rational::from_naturals(
self.xs.next().unwrap(),
self.ys.next().unwrap(),
))
}
}
pub fn random_non_negative_rationals(
seed: Seed,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalsFromDouble<
RandomNaturals<GeometricRandomNaturalValues<u64>>,
RandomNaturals<GeometricRandomNaturalValues<u64>>,
> {
RandomRationalsFromDouble {
xs: random_naturals(
seed.fork("numerator"),
mean_bits_numerator,
mean_bits_denominator,
),
ys: random_positive_naturals(
seed.fork("denominator"),
mean_bits_numerator,
mean_bits_denominator,
),
}
}
#[derive(Clone, Debug)]
pub struct NegativeRationals<I: Iterator<Item = Rational>> {
xs: I,
}
impl<I: Iterator<Item = Rational>> Iterator for NegativeRationals<I> {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
self.xs.next().map(|mut q| {
q.sign = false;
q
})
}
}
pub fn random_negative_rationals(
seed: Seed,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> NegativeRationals<RandomRationalsFromSingle<RandomNaturals<GeometricRandomNaturalValues<u64>>>>
{
NegativeRationals {
xs: random_positive_rationals(seed, mean_bits_numerator, mean_bits_denominator),
}
}
#[derive(Clone, Debug)]
pub struct RandomRationalsFromSingleAndSign<I: Iterator<Item = Natural>> {
bs: RandomBools,
xs: I,
}
impl<I: Iterator<Item = Natural>> Iterator for RandomRationalsFromSingleAndSign<I> {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
Some(Rational::from_sign_and_naturals(
self.bs.next().unwrap(),
self.xs.next().unwrap(),
self.xs.next().unwrap(),
))
}
}
pub fn random_nonzero_rationals(
seed: Seed,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalsFromSingleAndSign<RandomNaturals<GeometricRandomNaturalValues<u64>>> {
RandomRationalsFromSingleAndSign {
bs: random_bools(seed.fork("sign")),
xs: random_positive_naturals(seed.fork("abs"), mean_bits_numerator, mean_bits_denominator),
}
}
#[derive(Clone, Debug)]
pub struct RandomRationalsFromDoubleAndSign<
I: Iterator<Item = Natural>,
J: Iterator<Item = Natural>,
> {
pub bs: RandomBools,
pub xs: I,
pub ys: J,
}
impl<I: Iterator<Item = Natural>, J: Iterator<Item = Natural>> Iterator
for RandomRationalsFromDoubleAndSign<I, J>
{
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
Some(Rational::from_sign_and_naturals(
self.bs.next().unwrap(),
self.xs.next().unwrap(),
self.ys.next().unwrap(),
))
}
}
pub fn random_rationals(
seed: Seed,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalsFromDoubleAndSign<
RandomNaturals<GeometricRandomNaturalValues<u64>>,
RandomNaturals<GeometricRandomNaturalValues<u64>>,
> {
RandomRationalsFromDoubleAndSign {
bs: random_bools(seed.fork("sign")),
xs: random_naturals(
seed.fork("numerator"),
mean_bits_numerator,
mean_bits_denominator,
),
ys: random_positive_naturals(
seed.fork("denominator"),
mean_bits_numerator,
mean_bits_denominator,
),
}
}
pub fn striped_random_positive_rationals(
seed: Seed,
mean_stripe_numerator: u64,
mean_stripe_denominator: u64,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalsFromSingle<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>> {
RandomRationalsFromSingle {
xs: striped_random_positive_naturals(
seed,
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
}
}
pub fn striped_random_non_negative_rationals(
seed: Seed,
mean_stripe_numerator: u64,
mean_stripe_denominator: u64,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalsFromDouble<
StripedRandomNaturals<GeometricRandomNaturalValues<u64>>,
StripedRandomNaturals<GeometricRandomNaturalValues<u64>>,
> {
RandomRationalsFromDouble {
xs: striped_random_naturals(
seed.fork("numerator"),
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
ys: striped_random_positive_naturals(
seed.fork("denominator"),
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
}
}
pub fn striped_random_negative_rationals(
seed: Seed,
mean_stripe_numerator: u64,
mean_stripe_denominator: u64,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> NegativeRationals<
RandomRationalsFromSingle<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>>,
> {
NegativeRationals {
xs: striped_random_positive_rationals(
seed,
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
}
}
pub fn striped_random_nonzero_rationals(
seed: Seed,
mean_stripe_numerator: u64,
mean_stripe_denominator: u64,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalsFromSingleAndSign<StripedRandomNaturals<GeometricRandomNaturalValues<u64>>> {
RandomRationalsFromSingleAndSign {
bs: random_bools(seed.fork("sign")),
xs: striped_random_positive_naturals(
seed.fork("abs"),
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
}
}
pub fn striped_random_rationals(
seed: Seed,
mean_stripe_numerator: u64,
mean_stripe_denominator: u64,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalsFromDoubleAndSign<
StripedRandomNaturals<GeometricRandomNaturalValues<u64>>,
StripedRandomNaturals<GeometricRandomNaturalValues<u64>>,
> {
RandomRationalsFromDoubleAndSign {
bs: random_bools(seed.fork("sign")),
xs: striped_random_naturals(
seed.fork("numerator"),
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
ys: striped_random_positive_naturals(
seed.fork("denominator"),
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
}
}
pub fn random_rational_with_denominator_range_to_infinity(
seed: Seed,
d: Natural,
a: Rational,
mean_numerator_bits_numerator: u64,
mean_numerator_bits_denominator: u64,
) -> RationalsWithDenominator<RandomIntegerRangeToInfinity> {
assert_ne!(d, 0u32);
RationalsWithDenominator {
numerators: random_integer_range_to_infinity(
seed,
Integer::rounding_from(a * Rational::from(&d), Ceiling).0,
mean_numerator_bits_numerator,
mean_numerator_bits_denominator,
),
denominator: d,
}
}
pub fn random_rational_with_denominator_range_to_negative_infinity(
seed: Seed,
d: Natural,
a: Rational,
mean_numerator_bits_numerator: u64,
mean_numerator_bits_denominator: u64,
) -> RationalsWithDenominator<RandomIntegerRangeToInfinity> {
assert_ne!(d, 0u32);
RationalsWithDenominator {
numerators: random_integer_range_to_negative_infinity(
seed,
Integer::rounding_from(a * Rational::from(&d), Floor).0,
mean_numerator_bits_numerator,
mean_numerator_bits_denominator,
),
denominator: d,
}
}
pub fn random_rational_with_denominator_range(
seed: Seed,
d: Natural,
a: Rational,
b: Rational,
mut mean_numerator_bits_numerator: u64,
mut mean_numerator_bits_denominator: u64,
) -> RationalsWithDenominator<RandomIntegerRange> {
assert_ne!(d, 0u32);
assert!(a < b);
let q_d = Rational::from(&d);
let a_i = Integer::rounding_from(a * &q_d, Ceiling).0;
let upper_included = b.denominator_ref() == &d;
let mut b_i = Integer::rounding_from(b * q_d, Floor).0;
if !upper_included {
b_i += Integer::ONE;
}
if (a_i >= 0) == (b_i >= 0) {
let (n, d) = (Rational::from_unsigneds(
mean_numerator_bits_numerator,
mean_numerator_bits_denominator,
) + Rational::from(min(a_i.significant_bits(), b_i.significant_bits())))
.into_numerator_and_denominator();
mean_numerator_bits_numerator = u64::exact_from(&n);
mean_numerator_bits_denominator = u64::exact_from(&d);
}
RationalsWithDenominator {
numerators: random_integer_range(
seed,
a_i,
b_i,
mean_numerator_bits_numerator,
mean_numerator_bits_denominator,
),
denominator: d,
}
}
pub fn random_rational_with_denominator_inclusive_range(
seed: Seed,
d: Natural,
a: Rational,
b: Rational,
mut mean_numerator_bits_numerator: u64,
mut mean_numerator_bits_denominator: u64,
) -> RationalsWithDenominator<RandomIntegerRange> {
assert_ne!(d, 0u32);
assert!(a <= b);
let q_d = Rational::from(&d);
let a_i = Integer::rounding_from(a * &q_d, Ceiling).0;
let b_i = Integer::rounding_from(b * q_d, Floor).0 + Integer::ONE;
if (a_i >= 0) == (b_i >= 0) {
let (n, d) = (Rational::from_unsigneds(
mean_numerator_bits_numerator,
mean_numerator_bits_denominator,
) + Rational::from(min(a_i.significant_bits(), b_i.significant_bits())))
.into_numerator_and_denominator();
mean_numerator_bits_numerator = u64::exact_from(&n);
mean_numerator_bits_denominator = u64::exact_from(&d);
}
RationalsWithDenominator {
numerators: random_integer_range(
seed,
a_i,
b_i,
mean_numerator_bits_numerator,
mean_numerator_bits_denominator,
),
denominator: d,
}
}
#[derive(Clone, Debug)]
pub struct RandomRationalRangeToInfinity {
a: Rational,
limbs: RandomPrimitiveInts<u64>,
range_generator: VariableRangeGenerator,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
denominators: RandomNaturals<GeometricRandomNaturalValues<u64>>,
}
impl Iterator for RandomRationalRangeToInfinity {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
let d = self.denominators.next().unwrap();
let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Ceiling).0;
let (numerator, denominator) = (Rational::from(d.significant_bits())
+ Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator))
.into_numerator_and_denominator();
let numerator = u64::exact_from(&numerator);
let denominator = u64::exact_from(&denominator);
loop {
let n = get_random_integer_from_range_to_infinity(
&mut self.limbs,
&mut self.range_generator,
numerator_bound.clone(),
numerator,
denominator,
);
if n.unsigned_abs_ref().coprime_with(&d) {
return Some(Rational {
sign: n >= 0,
numerator: n.unsigned_abs(),
denominator: d,
});
}
}
}
}
pub fn random_rational_range_to_infinity(
seed: Seed,
a: Rational,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalRangeToInfinity {
RandomRationalRangeToInfinity {
a,
limbs: random_primitive_ints(seed.fork("limbs")),
range_generator: VariableRangeGenerator::new(seed.fork("range generator")),
mean_bits_numerator,
mean_bits_denominator,
denominators: random_positive_naturals(
seed.fork("denominators"),
mean_bits_numerator,
mean_bits_denominator,
),
}
}
#[derive(Clone, Debug)]
pub struct RandomRationalRangeToNegativeInfinity {
a: Rational,
limbs: RandomPrimitiveInts<u64>,
range_generator: VariableRangeGenerator,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
denominators: RandomNaturals<GeometricRandomNaturalValues<u64>>,
}
impl Iterator for RandomRationalRangeToNegativeInfinity {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
let d = self.denominators.next().unwrap();
let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Floor).0;
let (numerator, denominator) = (Rational::from(d.significant_bits())
+ Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator))
.into_numerator_and_denominator();
let numerator = u64::exact_from(&numerator);
let denominator = u64::exact_from(&denominator);
loop {
let n = get_random_integer_from_range_to_negative_infinity(
&mut self.limbs,
&mut self.range_generator,
numerator_bound.clone(),
numerator,
denominator,
);
if n.unsigned_abs_ref().coprime_with(&d) {
return Some(Rational {
sign: n >= 0,
numerator: n.unsigned_abs(),
denominator: d,
});
}
}
}
}
pub fn random_rational_range_to_negative_infinity(
seed: Seed,
a: Rational,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> RandomRationalRangeToNegativeInfinity {
RandomRationalRangeToNegativeInfinity {
a,
limbs: random_primitive_ints(seed.fork("limbs")),
range_generator: VariableRangeGenerator::new(seed.fork("range generator")),
mean_bits_numerator,
mean_bits_denominator,
denominators: random_positive_naturals(
seed.fork("denominators"),
mean_bits_numerator,
mean_bits_denominator,
),
}
}
#[derive(Clone, Debug)]
pub struct RandomRationalRange {
seed: Seed,
mean_numerator_bits_numerator: u64,
mean_numerator_bits_denominator: u64,
a: Rational,
b: Rational,
denominators: IteratorCache<DenominatorsInClosedRationalInterval>,
denominator_map: HashMap<Natural, RationalsWithDenominator<RandomIntegerRange>>,
indices: GeometricRandomNaturalValues<usize>,
}
impl Iterator for RandomRationalRange {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
loop {
let d = self.denominators.get(self.indices.next().unwrap()).unwrap();
if (&self.a)
.round_to_multiple(Rational::from(d).reciprocal(), Ceiling)
.0
>= self.b
{
continue;
}
return self
.denominator_map
.entry(d.clone())
.or_insert_with(|| {
random_rational_with_denominator_range(
self.seed.fork(&d.to_string()),
d.clone(),
self.a.clone(),
self.b.clone(),
self.mean_numerator_bits_numerator,
self.mean_numerator_bits_denominator,
)
})
.next();
}
}
}
pub fn random_rational_range(
seed: Seed,
a: Rational,
b: Rational,
mean_numerator_bits_numerator: u64,
mean_numerator_bits_denominator: u64,
mean_denominator_index_numerator: u64,
mean_denominator_index_denominator: u64,
) -> RandomRationalRange {
assert!(a < b);
assert_ne!(mean_numerator_bits_denominator, 0);
assert_ne!(mean_denominator_index_denominator, 0);
RandomRationalRange {
seed: seed.fork("numerators"),
mean_numerator_bits_numerator,
mean_numerator_bits_denominator,
a: a.clone(),
b: b.clone(),
denominators: IteratorCache::new(Rational::denominators_in_closed_interval(a, b)),
denominator_map: HashMap::new(),
indices: geometric_random_unsigneds(
seed.fork("indices"),
mean_denominator_index_numerator,
mean_denominator_index_denominator,
),
}
}
#[doc(hidden)]
#[derive(Clone, Debug)]
pub struct RandomRationalInclusiveRangeInner {
seed: Seed,
mean_numerator_bits_numerator: u64,
mean_numerator_bits_denominator: u64,
a: Rational,
b: Rational,
denominators: IteratorCache<DenominatorsInClosedRationalInterval>,
denominator_map: HashMap<Natural, RationalsWithDenominator<RandomIntegerRange>>,
indices: GeometricRandomNaturalValues<usize>,
}
impl Iterator for RandomRationalInclusiveRangeInner {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
let d = self.denominators.get(self.indices.next().unwrap()).unwrap();
self.denominator_map
.entry(d.clone())
.or_insert_with(|| {
random_rational_with_denominator_inclusive_range(
self.seed.fork(&d.to_string()),
d.clone(),
self.a.clone(),
self.b.clone(),
self.mean_numerator_bits_numerator,
self.mean_numerator_bits_denominator,
)
})
.next()
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug)]
pub enum RandomRationalInclusiveRange {
Single(Rational),
Multiple(RandomRationalInclusiveRangeInner),
}
impl Iterator for RandomRationalInclusiveRange {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
match self {
Self::Single(x) => Some(x.clone()),
Self::Multiple(xs) => xs.next(),
}
}
}
pub fn random_rational_inclusive_range(
seed: Seed,
a: Rational,
b: Rational,
mean_numerator_bits_numerator: u64,
mean_numerator_bits_denominator: u64,
mean_denominator_index_numerator: u64,
mean_denominator_index_denominator: u64,
) -> RandomRationalInclusiveRange {
assert!(a <= b);
if a == b {
return RandomRationalInclusiveRange::Single(a);
}
assert_ne!(mean_numerator_bits_denominator, 0);
assert_ne!(mean_denominator_index_denominator, 0);
RandomRationalInclusiveRange::Multiple(RandomRationalInclusiveRangeInner {
seed: seed.fork("numerators"),
mean_numerator_bits_numerator,
mean_numerator_bits_denominator,
a: a.clone(),
b: b.clone(),
denominators: IteratorCache::new(Rational::denominators_in_closed_interval(a, b)),
denominator_map: HashMap::new(),
indices: geometric_random_unsigneds(
seed.fork("indices"),
mean_denominator_index_numerator,
mean_denominator_index_denominator,
),
})
}
#[derive(Clone, Debug)]
pub struct StripedRandomRationalRangeToInfinity {
a: Rational,
xs: StripedBitSource,
range_generator: VariableRangeGenerator,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
denominators: StripedRandomNaturals<GeometricRandomNaturalValues<u64>>,
}
impl Iterator for StripedRandomRationalRangeToInfinity {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
let d = self.denominators.next().unwrap();
let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Ceiling).0;
let (numerator, denominator) = (Rational::from(d.significant_bits())
+ Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator))
.into_numerator_and_denominator();
let numerator = u64::exact_from(&numerator);
let denominator = u64::exact_from(&denominator);
loop {
let n = get_striped_random_integer_from_range_to_infinity(
&mut self.xs,
&mut self.range_generator,
numerator_bound.clone(),
numerator,
denominator,
);
if n.unsigned_abs_ref().coprime_with(&d) {
return Some(Rational {
sign: n >= 0,
numerator: n.unsigned_abs(),
denominator: d,
});
}
}
}
}
pub fn striped_random_rational_range_to_infinity(
seed: Seed,
a: Rational,
mean_stripe_numerator: u64,
mean_stripe_denominator: u64,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> StripedRandomRationalRangeToInfinity {
StripedRandomRationalRangeToInfinity {
a,
xs: StripedBitSource::new(
seed.fork("xs"),
mean_stripe_numerator,
mean_stripe_denominator,
),
range_generator: VariableRangeGenerator::new(seed.fork("range generator")),
mean_bits_numerator,
mean_bits_denominator,
denominators: striped_random_positive_naturals(
seed.fork("denominators"),
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
}
}
#[derive(Clone, Debug)]
pub struct StripedRandomRationalRangeToNegativeInfinity {
a: Rational,
xs: StripedBitSource,
range_generator: VariableRangeGenerator,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
denominators: StripedRandomNaturals<GeometricRandomNaturalValues<u64>>,
}
impl Iterator for StripedRandomRationalRangeToNegativeInfinity {
type Item = Rational;
fn next(&mut self) -> Option<Rational> {
let d = self.denominators.next().unwrap();
let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Floor).0;
let (numerator, denominator) = (Rational::from(d.significant_bits())
+ Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator))
.into_numerator_and_denominator();
let numerator = u64::exact_from(&numerator);
let denominator = u64::exact_from(&denominator);
loop {
let n = get_striped_random_integer_from_range_to_negative_infinity(
&mut self.xs,
&mut self.range_generator,
numerator_bound.clone(),
numerator,
denominator,
);
if n.unsigned_abs_ref().coprime_with(&d) {
return Some(Rational {
sign: n >= 0,
numerator: n.unsigned_abs(),
denominator: d,
});
}
}
}
}
pub fn striped_random_rational_range_to_negative_infinity(
seed: Seed,
a: Rational,
mean_stripe_numerator: u64,
mean_stripe_denominator: u64,
mean_bits_numerator: u64,
mean_bits_denominator: u64,
) -> StripedRandomRationalRangeToNegativeInfinity {
StripedRandomRationalRangeToNegativeInfinity {
a,
xs: StripedBitSource::new(
seed.fork("xs"),
mean_stripe_numerator,
mean_stripe_denominator,
),
range_generator: VariableRangeGenerator::new(seed.fork("range generator")),
mean_bits_numerator,
mean_bits_denominator,
denominators: striped_random_positive_naturals(
seed.fork("denominators"),
mean_stripe_numerator,
mean_stripe_denominator,
mean_bits_numerator,
mean_bits_denominator,
),
}
}